wifi: mac80211: limit HE RU capabilities when limiting bandwidth
authorJohannes Berg <johannes.berg@intel.com>
Mon, 29 Jan 2024 19:19:29 +0000 (20:19 +0100)
committerJohannes Berg <johannes.berg@intel.com>
Thu, 8 Feb 2024 14:00:43 +0000 (15:00 +0100)
When limiting a station's supported bandwidth while connecting,
also limit various other HE capabilities according to the bandwidth
needed for them.

Link: https://msgid.link/20240129202041.34be99efca25.I02a695961bc6aadd37768b17c50fcdec4427d460@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
net/mac80211/util.c

index 5224c22b1afc42cd85aabb1640b337b25f86cd61..c2fe9aece00d1fbd2eadb7396742f2c82734e06e 100644 (file)
@@ -3300,17 +3300,48 @@ ieee80211_get_adjusted_he_cap(const struct ieee80211_conn_settings *conn,
                              const struct ieee80211_sta_he_cap *he_cap,
                              struct ieee80211_he_cap_elem *elem)
 {
+       u8 ru_limit, max_ru;
+
        *elem = he_cap->he_cap_elem;
 
-       if (conn->bw_limit < IEEE80211_CONN_BW_LIMIT_40)
+       switch (conn->bw_limit) {
+       case IEEE80211_CONN_BW_LIMIT_20:
+               ru_limit = IEEE80211_HE_PHY_CAP8_DCM_MAX_RU_242;
+               break;
+       case IEEE80211_CONN_BW_LIMIT_40:
+               ru_limit = IEEE80211_HE_PHY_CAP8_DCM_MAX_RU_484;
+               break;
+       case IEEE80211_CONN_BW_LIMIT_80:
+               ru_limit = IEEE80211_HE_PHY_CAP8_DCM_MAX_RU_996;
+               break;
+       default:
+               ru_limit = IEEE80211_HE_PHY_CAP8_DCM_MAX_RU_2x996;
+               break;
+       }
+
+       max_ru = elem->phy_cap_info[8] & IEEE80211_HE_PHY_CAP8_DCM_MAX_RU_MASK;
+       max_ru = min(max_ru, ru_limit);
+       elem->phy_cap_info[8] &= ~IEEE80211_HE_PHY_CAP8_DCM_MAX_RU_MASK;
+       elem->phy_cap_info[8] |= max_ru;
+
+       if (conn->bw_limit < IEEE80211_CONN_BW_LIMIT_40) {
                elem->phy_cap_info[0] &=
                        ~(IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G |
                          IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G);
+               elem->phy_cap_info[9] &=
+                       ~IEEE80211_HE_PHY_CAP9_LONGER_THAN_16_SIGB_OFDM_SYM;
+       }
 
-       if (conn->bw_limit < IEEE80211_CONN_BW_LIMIT_160)
+       if (conn->bw_limit < IEEE80211_CONN_BW_LIMIT_160) {
                elem->phy_cap_info[0] &=
                        ~(IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G |
                          IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G);
+               elem->phy_cap_info[5] &=
+                       ~IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_MASK;
+               elem->phy_cap_info[7] &=
+                       ~(IEEE80211_HE_PHY_CAP7_STBC_TX_ABOVE_80MHZ |
+                         IEEE80211_HE_PHY_CAP7_STBC_RX_ABOVE_80MHZ);
+       }
 }
 
 u8 *ieee80211_ie_build_he_cap(const struct ieee80211_conn_settings *conn,