Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
[cascardo/linux.git] / net / mac80211 / mesh_hwmp.c
index faccef9..b747c96 100644 (file)
@@ -326,22 +326,33 @@ static u32 airtime_link_metric_get(struct ieee80211_local *local,
        u32 tx_time, estimated_retx;
        u64 result;
 
-       if (sta->mesh->fail_avg >= 100)
-               return MAX_METRIC;
+       /* Try to get rate based on HW/SW RC algorithm.
+        * Rate is returned in units of Kbps, correct this
+        * to comply with airtime calculation units
+        * Round up in case we get rate < 100Kbps
+        */
+       rate = DIV_ROUND_UP(sta_get_expected_throughput(sta), 100);
 
-       sta_set_rate_info_tx(sta, &sta->tx_stats.last_rate, &rinfo);
-       rate = cfg80211_calculate_bitrate(&rinfo);
-       if (WARN_ON(!rate))
-               return MAX_METRIC;
+       if (rate) {
+               err = 0;
+       } else {
+               if (sta->mesh->fail_avg >= 100)
+                       return MAX_METRIC;
 
-       err = (sta->mesh->fail_avg << ARITH_SHIFT) / 100;
+               sta_set_rate_info_tx(sta, &sta->tx_stats.last_rate, &rinfo);
+               rate = cfg80211_calculate_bitrate(&rinfo);
+               if (WARN_ON(!rate))
+                       return MAX_METRIC;
+
+               err = (sta->mesh->fail_avg << ARITH_SHIFT) / 100;
+       }
 
        /* bitrate is in units of 100 Kbps, while we need rate in units of
         * 1Mbps. This will be corrected on tx_time computation.
         */
        tx_time = (device_constant + 10 * test_frame_len / rate);
        estimated_retx = ((1 << (2 * ARITH_SHIFT)) / (s_unit - err));
-       result = (tx_time * estimated_retx) >> (2 * ARITH_SHIFT) ;
+       result = (tx_time * estimated_retx) >> (2 * ARITH_SHIFT);
        return (u32)result;
 }