mac80211: use rate provided via status->rate on ieee80211_tx_status_ext for AQL
authorFelix Fietkau <nbd@nbd.name>
Fri, 21 Aug 2020 16:30:43 +0000 (18:30 +0200)
committerJohannes Berg <johannes.berg@intel.com>
Thu, 27 Aug 2020 08:28:21 +0000 (10:28 +0200)
Since ieee80211_tx_info does not have enough room to encode HE rates, HE
drivers use status->rate to provide rate info.
Store it in struct sta_info and use it for AQL.

Signed-off-by: Felix Fietkau <nbd@nbd.name>
Acked-by: Toke Høiland-Jørgensen <toke@redhat.com>
Link: https://lore.kernel.org/r/20200821163045.62140-1-nbd@nbd.name
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
net/mac80211/airtime.c
net/mac80211/sta_info.h
net/mac80211/status.c

index 366f76c9003ddd1b125473218cd7daff445bcc80..656c9a033714a4257c583d09b37a7a9b70f44197 100644 (file)
@@ -487,14 +487,61 @@ u32 ieee80211_calc_rx_airtime(struct ieee80211_hw *hw,
 }
 EXPORT_SYMBOL_GPL(ieee80211_calc_rx_airtime);
 
+static bool ieee80211_fill_rate_info(struct ieee80211_hw *hw,
+                                    struct ieee80211_rx_status *stat, u8 band,
+                                    struct rate_info *ri)
+{
+       struct ieee80211_supported_band *sband = hw->wiphy->bands[band];
+       int i;
+
+       if (!ri || !sband)
+           return false;
+
+       stat->bw = ri->bw;
+       stat->nss = ri->nss;
+       stat->rate_idx = ri->mcs;
+
+       if (ri->flags & RATE_INFO_FLAGS_HE_MCS)
+               stat->encoding = RX_ENC_HE;
+       else if (ri->flags & RATE_INFO_FLAGS_VHT_MCS)
+               stat->encoding = RX_ENC_VHT;
+       else if (ri->flags & RATE_INFO_FLAGS_MCS)
+               stat->encoding = RX_ENC_HT;
+       else
+               stat->encoding = RX_ENC_LEGACY;
+
+       if (ri->flags & RATE_INFO_FLAGS_SHORT_GI)
+               stat->enc_flags |= RX_ENC_FLAG_SHORT_GI;
+
+       stat->he_gi = ri->he_gi;
+
+       if (stat->encoding != RX_ENC_LEGACY)
+               return true;
+
+       stat->rate_idx = 0;
+       for (i = 0; i < sband->n_bitrates; i++) {
+               if (ri->legacy != sband->bitrates[i].bitrate)
+                       continue;
+
+               stat->rate_idx = i;
+               return true;
+       }
+
+       return false;
+}
+
 static u32 ieee80211_calc_tx_airtime_rate(struct ieee80211_hw *hw,
                                          struct ieee80211_tx_rate *rate,
+                                         struct rate_info *ri,
                                          u8 band, int len)
 {
        struct ieee80211_rx_status stat = {
                .band = band,
        };
 
+       if (ieee80211_fill_rate_info(hw, &stat, band, ri))
+               goto out;
+
        if (rate->idx < 0 || !rate->count)
                return 0;
 
@@ -522,6 +569,7 @@ static u32 ieee80211_calc_tx_airtime_rate(struct ieee80211_hw *hw,
                stat.encoding = RX_ENC_LEGACY;
        }
 
+out:
        return ieee80211_calc_rx_airtime(hw, &stat, len);
 }
 
@@ -536,7 +584,7 @@ u32 ieee80211_calc_tx_airtime(struct ieee80211_hw *hw,
                struct ieee80211_tx_rate *rate = &info->status.rates[i];
                u32 cur_duration;
 
-               cur_duration = ieee80211_calc_tx_airtime_rate(hw, rate,
+               cur_duration = ieee80211_calc_tx_airtime_rate(hw, rate, NULL,
                                                              info->band, len);
                if (!cur_duration)
                        break;
@@ -573,6 +621,7 @@ u32 ieee80211_calc_expected_tx_airtime(struct ieee80211_hw *hw,
                struct sta_info *sta = container_of(pubsta, struct sta_info,
                                                    sta);
                struct ieee80211_tx_rate *rate = &sta->tx_stats.last_rate;
+               struct rate_info *ri = &sta->tx_stats.last_rate_info;
                u32 airtime;
 
                if (!(rate->flags & (IEEE80211_TX_RC_VHT_MCS |
@@ -586,7 +635,7 @@ u32 ieee80211_calc_expected_tx_airtime(struct ieee80211_hw *hw,
                 * This will not be very accurate, but much better than simply
                 * assuming un-aggregated tx.
                 */
-               airtime = ieee80211_calc_tx_airtime_rate(hw, rate, band,
+               airtime = ieee80211_calc_tx_airtime_rate(hw, rate, ri, band,
                                                         ampdu ? len * 16 : len);
                if (ampdu)
                        airtime /= 16;
index 9d398c9daa4c649a02bf9bf959d5e523f46fc700..8060d142e4f1f4b78c7bf7c6653c685c7a045f25 100644 (file)
@@ -611,6 +611,7 @@ struct sta_info {
                u64 packets[IEEE80211_NUM_ACS];
                u64 bytes[IEEE80211_NUM_ACS];
                struct ieee80211_tx_rate last_rate;
+               struct rate_info last_rate_info;
                u64 msdu[IEEE80211_NUM_TIDS + 1];
        } tx_stats;
        u16 tid_seq[IEEE80211_QOS_CTL_TID_MASK + 1];
index adb1d30ce06ef3dffae17c79f27f9e6ead3b2727..6de63f1d8c7b011adfe1a560b6d5e9cc53f6ac6e 100644 (file)
@@ -1137,9 +1137,17 @@ void ieee80211_tx_status_ext(struct ieee80211_hw *hw,
        struct ieee80211_tx_info *info = status->info;
        struct ieee80211_sta *pubsta = status->sta;
        struct ieee80211_supported_band *sband;
+       struct sta_info *sta;
        int retry_count;
        bool acked, noack_success;
 
+       if (pubsta) {
+               sta = container_of(pubsta, struct sta_info, sta);
+
+               if (status->rate)
+                       sta->tx_stats.last_rate_info = *status->rate;
+       }
+
        if (status->skb)
                return __ieee80211_tx_status(hw, status);
 
@@ -1154,10 +1162,6 @@ void ieee80211_tx_status_ext(struct ieee80211_hw *hw,
        noack_success = !!(info->flags & IEEE80211_TX_STAT_NOACK_TRANSMITTED);
 
        if (pubsta) {
-               struct sta_info *sta;
-
-               sta = container_of(pubsta, struct sta_info, sta);
-
                if (!acked && !noack_success)
                        sta->status_stats.retry_failed++;
                sta->status_stats.retry_count += retry_count;