Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

wifi: cfg80211/mac80211: Add fallback mechanism for INDOOR_SP connection

Implement fallback to LPI mode when SP mode is not permitted
by regulatory constraints for INDOOR_SP connections.
Limit fallback mechanism to client mode.

Signed-off-by: Pagadala Yesu Anjaneyulu <pagadala.yesu.anjaneyulu@intel.com>
Reviewed-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
Link: https://patch.msgid.link/20251110140806.8b43201a34ae.I37fc7bb5892eb9d044d619802e8f2095fde6b296@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>

authored by

Pagadala Yesu Anjaneyulu and committed by
Johannes Berg
b54cf0f4 e18efacc

+17 -9
+7 -2
include/net/cfg80211.h
··· 10137 10137 /** 10138 10138 * cfg80211_6ghz_power_type - determine AP regulatory power type 10139 10139 * @control: control flags 10140 + * @client_flags: &enum ieee80211_channel_flags for station mode to enable 10141 + * SP to LPI fallback, zero otherwise. 10140 10142 * 10141 10143 * Return: regulatory power type from &enum ieee80211_ap_reg_power 10142 10144 */ 10143 10145 static inline enum ieee80211_ap_reg_power 10144 - cfg80211_6ghz_power_type(u8 control) 10146 + cfg80211_6ghz_power_type(u8 control, u32 client_flags) 10145 10147 { 10146 10148 switch (u8_get_bits(control, IEEE80211_HE_6GHZ_OPER_CTRL_REG_INFO)) { 10147 10149 case IEEE80211_6GHZ_CTRL_REG_LPI_AP: 10148 10150 case IEEE80211_6GHZ_CTRL_REG_INDOOR_LPI_AP: 10149 10151 return IEEE80211_REG_LPI_AP; 10150 10152 case IEEE80211_6GHZ_CTRL_REG_SP_AP: 10151 - case IEEE80211_6GHZ_CTRL_REG_INDOOR_SP_AP: 10152 10153 case IEEE80211_6GHZ_CTRL_REG_INDOOR_SP_AP_OLD: 10153 10154 return IEEE80211_REG_SP_AP; 10154 10155 case IEEE80211_6GHZ_CTRL_REG_VLP_AP: 10155 10156 return IEEE80211_REG_VLP_AP; 10157 + case IEEE80211_6GHZ_CTRL_REG_INDOOR_SP_AP: 10158 + if (client_flags & IEEE80211_CHAN_NO_6GHZ_AFC_CLIENT) 10159 + return IEEE80211_REG_LPI_AP; 10160 + return IEEE80211_REG_SP_AP; 10156 10161 default: 10157 10162 return IEEE80211_REG_UNSET_AP; 10158 10163 }
+2 -1
net/mac80211/mlme.c
··· 6076 6076 he_6ghz_oper = ieee80211_he_6ghz_oper(elems->he_operation); 6077 6077 if (he_6ghz_oper) 6078 6078 link->conf->power_type = 6079 - cfg80211_6ghz_power_type(he_6ghz_oper->control); 6079 + cfg80211_6ghz_power_type(he_6ghz_oper->control, 6080 + cbss->channel->flags); 6080 6081 else 6081 6082 link_info(link, 6082 6083 "HE 6 GHz operation missing (on %d MHz), expect issues\n",
+2 -1
net/wireless/core.h
··· 550 550 bool signal_valid, unsigned long ts); 551 551 552 552 enum ieee80211_ap_reg_power 553 - cfg80211_get_6ghz_power_type(const u8 *elems, size_t elems_len); 553 + cfg80211_get_6ghz_power_type(const u8 *elems, size_t elems_len, 554 + u32 client_flags); 554 555 555 556 #ifdef CONFIG_CFG80211_DEVELOPER_WARNINGS 556 557 #define CFG80211_DEV_WARN_ON(cond) WARN_ON(cond)
+2 -2
net/wireless/nl80211.c
··· 6748 6748 beacon_check.relax = true; 6749 6749 beacon_check.reg_power = 6750 6750 cfg80211_get_6ghz_power_type(params->beacon.tail, 6751 - params->beacon.tail_len); 6751 + params->beacon.tail_len, 0); 6752 6752 if (!cfg80211_reg_check_beaconing(&rdev->wiphy, &params->chandef, 6753 6753 &beacon_check)) { 6754 6754 err = -EINVAL; ··· 6927 6927 beacon_check.relax = true; 6928 6928 beacon_check.reg_power = 6929 6929 cfg80211_get_6ghz_power_type(params->beacon.tail, 6930 - params->beacon.tail_len); 6930 + params->beacon.tail_len, 0); 6931 6931 if (!cfg80211_reg_check_beaconing(&rdev->wiphy, 6932 6932 &wdev->links[link_id].ap.chandef, 6933 6933 &beacon_check)) {
+4 -3
net/wireless/scan.c
··· 2212 2212 }; 2213 2213 2214 2214 enum ieee80211_ap_reg_power 2215 - cfg80211_get_6ghz_power_type(const u8 *elems, size_t elems_len) 2215 + cfg80211_get_6ghz_power_type(const u8 *elems, size_t elems_len, 2216 + u32 client_flags) 2216 2217 { 2217 2218 const struct ieee80211_he_6ghz_oper *he_6ghz_oper; 2218 2219 struct ieee80211_he_operation *he_oper; ··· 2231 2230 if (!he_6ghz_oper) 2232 2231 return IEEE80211_REG_UNSET_AP; 2233 2232 2234 - return cfg80211_6ghz_power_type(he_6ghz_oper->control); 2233 + return cfg80211_6ghz_power_type(he_6ghz_oper->control, client_flags); 2235 2234 } 2236 2235 2237 2236 static bool cfg80211_6ghz_power_type_valid(const u8 *elems, size_t elems_len, 2238 2237 const u32 flags) 2239 2238 { 2240 - switch (cfg80211_get_6ghz_power_type(elems, elems_len)) { 2239 + switch (cfg80211_get_6ghz_power_type(elems, elems_len, flags)) { 2241 2240 case IEEE80211_REG_LPI_AP: 2242 2241 return true; 2243 2242 case IEEE80211_REG_SP_AP: