mac80211: fix mesh airtime link metric estimating
authorThomas Pedersen <thomas@cozybit.com>
Mon, 5 Mar 2012 23:31:48 +0000 (15:31 -0800)
committerJohn W. Linville <linville@tuxdriver.com>
Tue, 6 Mar 2012 20:16:17 +0000 (15:16 -0500)
Airtime link metric estimation was broken in HT mesh, use
cfg80211_calculate_bitrate to get the right rate value.

Also factor out tx rate copying from sta_set_sinfo().

Signed-off-by: Thomas Pedersen <thomas@cozybit.com>
Reviewed-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
net/mac80211/cfg.c
net/mac80211/mesh_hwmp.c
net/mac80211/sta_info.h

index ab31cc56a2fb62d83fe8b0062b310c305c8a0102..677d65929780ad147a531657f30ee26f6b52ae82 100644 (file)
@@ -336,6 +336,20 @@ static void rate_idx_to_bitrate(struct rate_info *rate, struct sta_info *sta, in
                rate->mcs = idx;
 }
 
+void sta_set_rate_info_tx(struct sta_info *sta,
+                         const struct ieee80211_tx_rate *rate,
+                         struct rate_info *rinfo)
+{
+       rinfo->flags = 0;
+       if (rate->flags & IEEE80211_TX_RC_MCS)
+               rinfo->flags |= RATE_INFO_FLAGS_MCS;
+       if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
+               rinfo->flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
+       if (rate->flags & IEEE80211_TX_RC_SHORT_GI)
+               rinfo->flags |= RATE_INFO_FLAGS_SHORT_GI;
+       rate_idx_to_bitrate(rinfo, sta, rate->idx);
+}
+
 static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
 {
        struct ieee80211_sub_if_data *sdata = sta->sdata;
@@ -378,14 +392,7 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
                sinfo->signal_avg = (s8) -ewma_read(&sta->avg_signal);
        }
 
-       sinfo->txrate.flags = 0;
-       if (sta->last_tx_rate.flags & IEEE80211_TX_RC_MCS)
-               sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
-       if (sta->last_tx_rate.flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
-               sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
-       if (sta->last_tx_rate.flags & IEEE80211_TX_RC_SHORT_GI)
-               sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
-       rate_idx_to_bitrate(&sinfo->txrate, sta, sta->last_tx_rate.idx);
+       sta_set_rate_info_tx(sta, &sta->last_tx_rate, &sinfo->txrate);
 
        sinfo->rxrate.flags = 0;
        if (sta->last_rx_rate_flag & RX_FLAG_HT)
index 4a993f2d1ae16f3adc65bea6a30fd8575261c1f0..1c6f3d02aebf5a4f19630f604aae94cda6810247 100644 (file)
@@ -324,6 +324,7 @@ static u32 airtime_link_metric_get(struct ieee80211_local *local,
                                   struct sta_info *sta)
 {
        struct ieee80211_supported_band *sband;
+       struct rate_info rinfo;
        /* This should be adjusted for each device */
        int device_constant = 1 << ARITH_SHIFT;
        int test_frame_len = TEST_FRAME_LEN << ARITH_SHIFT;
@@ -337,7 +338,9 @@ static u32 airtime_link_metric_get(struct ieee80211_local *local,
        if (sta->fail_avg >= 100)
                return MAX_METRIC;
 
-       if (sta->last_tx_rate.flags & IEEE80211_TX_RC_MCS)
+       sta_set_rate_info_tx(sta, &sta->last_tx_rate, &rinfo);
+       rate = cfg80211_calculate_bitrate(&rinfo);
+       if (WARN_ON(!rate))
                return MAX_METRIC;
 
        err = (sta->fail_avg << ARITH_SHIFT) / 100;
@@ -345,7 +348,6 @@ static u32 airtime_link_metric_get(struct ieee80211_local *local,
        /* bitrate is in units of 100 Kbps, while we need rate in units of
         * 1Mbps. This will be corrected on tx_time computation.
         */
-       rate = sband->bitrates[sta->last_tx_rate.idx].bitrate;
        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) ;
index 3336d54e55583c9cfe6b7aea306b271883c78ccf..ab0576827baf84c9b22a0b0aef2177699c856adf 100644 (file)
@@ -529,6 +529,9 @@ void sta_info_init(struct ieee80211_local *local);
 void sta_info_stop(struct ieee80211_local *local);
 int sta_info_flush(struct ieee80211_local *local,
                   struct ieee80211_sub_if_data *sdata);
+void sta_set_rate_info_tx(struct sta_info *sta,
+                         const struct ieee80211_tx_rate *rate,
+                         struct rate_info *rinfo);
 void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata,
                          unsigned long exp_time);