]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
wifi: cfg80211/mac80211: Add fallback mechanism for INDOOR_SP connection
authorPagadala Yesu Anjaneyulu <pagadala.yesu.anjaneyulu@intel.com>
Mon, 10 Nov 2025 12:10:30 +0000 (14:10 +0200)
committerJohannes Berg <johannes.berg@intel.com>
Tue, 11 Nov 2025 10:05:00 +0000 (11:05 +0100)
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>
include/net/cfg80211.h
net/mac80211/mlme.c
net/wireless/core.h
net/wireless/nl80211.c
net/wireless/scan.c

index 1b257eaf8de57186d009f5715ea76f7140f1d840..625cb2c783613faf3798e905b15d7862803821ea 100644 (file)
@@ -10137,22 +10137,27 @@ static inline int cfg80211_color_change_notify(struct net_device *dev,
 /**
  * cfg80211_6ghz_power_type - determine AP regulatory power type
  * @control: control flags
+ * @client_flags: &enum ieee80211_channel_flags for station mode to enable
+ *     SP to LPI fallback, zero otherwise.
  *
  * Return: regulatory power type from &enum ieee80211_ap_reg_power
  */
 static inline enum ieee80211_ap_reg_power
-cfg80211_6ghz_power_type(u8 control)
+cfg80211_6ghz_power_type(u8 control, u32 client_flags)
 {
        switch (u8_get_bits(control, IEEE80211_HE_6GHZ_OPER_CTRL_REG_INFO)) {
        case IEEE80211_6GHZ_CTRL_REG_LPI_AP:
        case IEEE80211_6GHZ_CTRL_REG_INDOOR_LPI_AP:
                return IEEE80211_REG_LPI_AP;
        case IEEE80211_6GHZ_CTRL_REG_SP_AP:
-       case IEEE80211_6GHZ_CTRL_REG_INDOOR_SP_AP:
        case IEEE80211_6GHZ_CTRL_REG_INDOOR_SP_AP_OLD:
                return IEEE80211_REG_SP_AP;
        case IEEE80211_6GHZ_CTRL_REG_VLP_AP:
                return IEEE80211_REG_VLP_AP;
+       case IEEE80211_6GHZ_CTRL_REG_INDOOR_SP_AP:
+               if (client_flags & IEEE80211_CHAN_NO_6GHZ_AFC_CLIENT)
+                       return IEEE80211_REG_LPI_AP;
+               return IEEE80211_REG_SP_AP;
        default:
                return IEEE80211_REG_UNSET_AP;
        }
index 64230696f3e43e778b4266015b32616581090a88..c705d3f45affe8c63d71f0464f93b698b2bc7ad0 100644 (file)
@@ -6076,7 +6076,8 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata,
                he_6ghz_oper = ieee80211_he_6ghz_oper(elems->he_operation);
                if (he_6ghz_oper)
                        link->conf->power_type =
-                               cfg80211_6ghz_power_type(he_6ghz_oper->control);
+                               cfg80211_6ghz_power_type(he_6ghz_oper->control,
+                                                        cbss->channel->flags);
                else
                        link_info(link,
                                  "HE 6 GHz operation missing (on %d MHz), expect issues\n",
index b6bd7f4d6385a128ba8fb7fc82ca4b2e8dd7d7d8..82f343663e8fadaefbb45bb11dc03695a825925d 100644 (file)
@@ -550,7 +550,8 @@ cfg80211_bss_update(struct cfg80211_registered_device *rdev,
                    bool signal_valid, unsigned long ts);
 
 enum ieee80211_ap_reg_power
-cfg80211_get_6ghz_power_type(const u8 *elems, size_t elems_len);
+cfg80211_get_6ghz_power_type(const u8 *elems, size_t elems_len,
+                            u32 client_flags);
 
 #ifdef CONFIG_CFG80211_DEVELOPER_WARNINGS
 #define CFG80211_DEV_WARN_ON(cond)     WARN_ON(cond)
index 2187e148389de0de4166a5dbecc34c0283afda82..29c92bc8291bd5d24ab7751566421f8377bdb79a 100644 (file)
@@ -6748,7 +6748,7 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
        beacon_check.relax = true;
        beacon_check.reg_power =
                cfg80211_get_6ghz_power_type(params->beacon.tail,
-                                            params->beacon.tail_len);
+                                            params->beacon.tail_len, 0);
        if (!cfg80211_reg_check_beaconing(&rdev->wiphy, &params->chandef,
                                          &beacon_check)) {
                err = -EINVAL;
@@ -6927,7 +6927,7 @@ static int nl80211_set_beacon(struct sk_buff *skb, struct genl_info *info)
        beacon_check.relax = true;
        beacon_check.reg_power =
                cfg80211_get_6ghz_power_type(params->beacon.tail,
-                                            params->beacon.tail_len);
+                                            params->beacon.tail_len, 0);
        if (!cfg80211_reg_check_beaconing(&rdev->wiphy,
                                          &wdev->links[link_id].ap.chandef,
                                          &beacon_check)) {
index 68c4130d602f263a9d731b06b02c858f54e85616..7546647752fd8f596c749acd6abaf469ff602fe2 100644 (file)
@@ -2212,7 +2212,8 @@ struct cfg80211_inform_single_bss_data {
 };
 
 enum ieee80211_ap_reg_power
-cfg80211_get_6ghz_power_type(const u8 *elems, size_t elems_len)
+cfg80211_get_6ghz_power_type(const u8 *elems, size_t elems_len,
+                            u32 client_flags)
 {
        const struct ieee80211_he_6ghz_oper *he_6ghz_oper;
        struct ieee80211_he_operation *he_oper;
@@ -2230,13 +2231,13 @@ cfg80211_get_6ghz_power_type(const u8 *elems, size_t elems_len)
        if (!he_6ghz_oper)
                return IEEE80211_REG_UNSET_AP;
 
-       return cfg80211_6ghz_power_type(he_6ghz_oper->control);
+       return cfg80211_6ghz_power_type(he_6ghz_oper->control, client_flags);
 }
 
 static bool cfg80211_6ghz_power_type_valid(const u8 *elems, size_t elems_len,
                                           const u32 flags)
 {
-       switch (cfg80211_get_6ghz_power_type(elems, elems_len)) {
+       switch (cfg80211_get_6ghz_power_type(elems, elems_len, flags)) {
        case IEEE80211_REG_LPI_AP:
                return true;
        case IEEE80211_REG_SP_AP: