mac80211: minstrel_ht: support ieee80211_rate_status
authorJonas Jelonek <jelonek.jonas@gmail.com>
Mon, 9 May 2022 17:39:58 +0000 (19:39 +0200)
committerJohannes Berg <johannes.berg@intel.com>
Mon, 16 May 2022 08:07:58 +0000 (10:07 +0200)
This patch adds support for the new struct ieee80211_rate_status and its
annotation in struct ieee80211_tx_status in minstrel_ht.

In minstrel_ht_tx_status, a check for the presence of instances of the
new struct in ieee80211_tx_status is added. Based on this, minstrel_ht
then gets and updates internal rate stats with either struct
ieee80211_rate_status or ieee80211_tx_info->status.rates.
Adjusted variants of minstrel_ht_txstat_valid, minstrel_ht_get_stats,
minstrel_{ht/vht}_get_group_idx are added which use struct
ieee80211_rate_status and struct rate_info instead of the legacy structs.

struct rate_info from cfg80211.h does not provide whether short preamble
was used for the transmission. So we retrieve this information from VIF
and STA configuration and cache it in a new flag in struct minstrel_ht_sta
per rate control instance.

Compile-Tested: current wireless-next tree with all flags on
Tested-on: Xiaomi 4A Gigabit (MediaTek MT7603E, MT7612E) with OpenWrt
                Linux 5.10.113

Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
Link: https://lore.kernel.org/r/20220509173958.1398201-3-jelonek.jonas@gmail.com
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
net/mac80211/rc80211_minstrel_ht.c
net/mac80211/rc80211_minstrel_ht.h

index 273e63689e9a6d6064e77515cb18a37cc8f9b736..5f27e6746762a0456ed244bbff68c9953235c710 100644 (file)
@@ -333,6 +333,17 @@ minstrel_ht_get_group_idx(struct ieee80211_tx_rate *rate)
                         !!(rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH));
 }
 
+/*
+ * Look up an MCS group index based on new cfg80211 rate_info.
+ */
+static int
+minstrel_ht_ri_get_group_idx(struct rate_info *rate)
+{
+       return GROUP_IDX((rate->mcs / 8) + 1,
+                        !!(rate->flags & RATE_INFO_FLAGS_SHORT_GI),
+                        !!(rate->bw & RATE_INFO_BW_40));
+}
+
 static int
 minstrel_vht_get_group_idx(struct ieee80211_tx_rate *rate)
 {
@@ -342,6 +353,18 @@ minstrel_vht_get_group_idx(struct ieee80211_tx_rate *rate)
                             2*!!(rate->flags & IEEE80211_TX_RC_80_MHZ_WIDTH));
 }
 
+/*
+ * Look up an MCS group index based on new cfg80211 rate_info.
+ */
+static int
+minstrel_vht_ri_get_group_idx(struct rate_info *rate)
+{
+       return VHT_GROUP_IDX(rate->nss,
+                            !!(rate->flags & RATE_INFO_FLAGS_SHORT_GI),
+                            !!(rate->bw & RATE_INFO_BW_40) +
+                            2*!!(rate->bw & RATE_INFO_BW_80));
+}
+
 static struct minstrel_rate_stats *
 minstrel_ht_get_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
                      struct ieee80211_tx_rate *rate)
@@ -385,6 +408,50 @@ out:
        return &mi->groups[group].rates[idx];
 }
 
+/*
+ * Get the minstrel rate statistics for specified STA and rate info.
+ */
+static struct minstrel_rate_stats *
+minstrel_ht_ri_get_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
+                         struct ieee80211_rate_status *rate_status)
+{
+       int group, idx;
+       struct rate_info *rate = &rate_status->rate_idx;
+
+       if (rate->flags & RATE_INFO_FLAGS_MCS) {
+               group = minstrel_ht_ri_get_group_idx(rate);
+               idx = rate->mcs % 8;
+               goto out;
+       }
+
+       if (rate->flags & RATE_INFO_FLAGS_VHT_MCS) {
+               group = minstrel_vht_ri_get_group_idx(rate);
+               idx = rate->mcs;
+               goto out;
+       }
+
+       group = MINSTREL_CCK_GROUP;
+       for (idx = 0; idx < ARRAY_SIZE(mp->cck_rates); idx++) {
+               if (rate->legacy != minstrel_cck_bitrates[ mp->cck_rates[idx] ])
+                       continue;
+
+               /* short preamble */
+               if ((mi->supported[group] & BIT(idx + 4)) &&
+                                                       mi->use_short_preamble)
+                       idx += 4;
+               goto out;
+       }
+
+       group = MINSTREL_OFDM_GROUP;
+       for (idx = 0; idx < ARRAY_SIZE(mp->ofdm_rates[0]); idx++)
+               if (rate->legacy == minstrel_ofdm_bitrates[ mp->ofdm_rates[mi->band][idx] ])
+                       goto out;
+
+       idx = 0;
+out:
+       return &mi->groups[group].rates[idx];
+}
+
 static inline struct minstrel_rate_stats *
 minstrel_get_ratestats(struct minstrel_ht_sta *mi, int index)
 {
@@ -1152,6 +1219,40 @@ minstrel_ht_txstat_valid(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
        return false;
 }
 
+/*
+ * Check whether rate_status contains valid information.
+ */
+static bool
+minstrel_ht_ri_txstat_valid(struct minstrel_priv *mp,
+                           struct minstrel_ht_sta *mi,
+                           struct ieee80211_rate_status *rate_status)
+{
+       int i;
+
+       if (!rate_status)
+               return false;
+       if (!rate_status->try_count)
+               return false;
+
+       if (rate_status->rate_idx.flags & RATE_INFO_FLAGS_MCS ||
+           rate_status->rate_idx.flags & RATE_INFO_FLAGS_VHT_MCS)
+               return true;
+
+       for (i = 0; i < ARRAY_SIZE(mp->cck_rates); i++) {
+               if (rate_status->rate_idx.legacy ==
+                   minstrel_cck_bitrates[ mp->cck_rates[i] ])
+                       return true;
+       }
+
+       for (i = 0; i < ARRAY_SIZE(mp->ofdm_rates); i++) {
+               if (rate_status->rate_idx.legacy ==
+                   minstrel_ofdm_bitrates[ mp->ofdm_rates[mi->band][i] ])
+                       return true;
+       }
+
+       return false;
+}
+
 static void
 minstrel_downgrade_rate(struct minstrel_ht_sta *mi, u16 *idx, bool primary)
 {
@@ -1217,16 +1318,34 @@ minstrel_ht_tx_status(void *priv, struct ieee80211_supported_band *sband,
        mi->ampdu_packets++;
        mi->ampdu_len += info->status.ampdu_len;
 
-       last = !minstrel_ht_txstat_valid(mp, mi, &ar[0]);
-       for (i = 0; !last; i++) {
-               last = (i == IEEE80211_TX_MAX_RATES - 1) ||
-                      !minstrel_ht_txstat_valid(mp, mi, &ar[i + 1]);
+       if (st->rates && st->n_rates) {
+               last = !minstrel_ht_ri_txstat_valid(mp, mi, &(st->rates[0]));
+               for (i = 0; !last; i++) {
+                       last = (i == st->n_rates - 1) ||
+                               !minstrel_ht_ri_txstat_valid(mp, mi,
+                                                       &(st->rates[i + 1]));
+
+                       rate = minstrel_ht_ri_get_stats(mp, mi,
+                                                       &(st->rates[i]));
+
+                       if (last)
+                               rate->success += info->status.ampdu_ack_len;
+
+                       rate->attempts += st->rates[i].try_count *
+                                         info->status.ampdu_len;
+               }
+       } else {
+               last = !minstrel_ht_txstat_valid(mp, mi, &ar[0]);
+               for (i = 0; !last; i++) {
+                       last = (i == IEEE80211_TX_MAX_RATES - 1) ||
+                               !minstrel_ht_txstat_valid(mp, mi, &ar[i + 1]);
 
-               rate = minstrel_ht_get_stats(mp, mi, &ar[i]);
-               if (last)
-                       rate->success += info->status.ampdu_ack_len;
+                       rate = minstrel_ht_get_stats(mp, mi, &ar[i]);
+                       if (last)
+                               rate->success += info->status.ampdu_ack_len;
 
-               rate->attempts += ar[i].count * info->status.ampdu_len;
+                       rate->attempts += ar[i].count * info->status.ampdu_len;
+               }
        }
 
        if (mp->hw->max_rates > 1) {
@@ -1583,6 +1702,7 @@ minstrel_ht_update_caps(void *priv, struct ieee80211_supported_band *sband,
        u16 ht_cap = sta->deflink.ht_cap.cap;
        struct ieee80211_sta_vht_cap *vht_cap = &sta->deflink.vht_cap;
        const struct ieee80211_rate *ctl_rate;
+       struct sta_info *sta_info;
        bool ldpc, erp;
        int use_vht;
        int n_supported = 0;
@@ -1701,6 +1821,10 @@ minstrel_ht_update_caps(void *priv, struct ieee80211_supported_band *sband,
                        n_supported++;
        }
 
+       sta_info = container_of(sta, struct sta_info, sta);
+       mi->use_short_preamble = test_sta_flag(sta_info, WLAN_STA_SHORT_PREAMBLE) &&
+                                sta_info->sdata->vif.bss_conf.use_short_preamble;
+
        minstrel_ht_update_cck(mp, mi, sband, sta);
        minstrel_ht_update_ofdm(mp, mi, sband, sta);
 
index 06e7126727ad982c2533678ee376928181c3e919..1766ff0c78d3a7e6d6c97582a6507520337434cf 100644 (file)
@@ -180,7 +180,7 @@ struct minstrel_ht_sta {
 
        /* tx flags to add for frames for this sta */
        u32 tx_flags;
-
+       bool use_short_preamble;
        u8 band;
 
        u8 sample_seq;