summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2026-07-15 21:03:33 +0300
committerJohannes Berg <johannes.berg@intel.com>2026-07-21 19:18:52 +0200
commita3262f61d102eaae81048d10eb0aadcc623ea026 (patch)
treef6bf055d3cf43b8578eb17fb061eec51a019f86c
parentdd406779999fa2065ec6b7c4f80906b727041d2c (diff)
downloadlinux-next-a3262f61d102eaae81048d10eb0aadcc623ea026.tar.gz
linux-next-a3262f61d102eaae81048d10eb0aadcc623ea026.zip
wifi: mac80211: always send regulatory connectivity element
The spec says to include it if the STA is "capable of operating as STA 6G", which is a bit unclear because this is defined at a STA level and not at the MLD level or so, but WFA requires this to be included. Either way, the element is completely advisory and intended mostly for debugging (and perhaps a bit steering), so just include it in association request all the time if 6 GHz is supported. To determine what exactly to include, check all the channels that aren't disabled. That way, it ends up being a lowest common denominator, which is most useful for steering etc. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com> Link: https://patch.msgid.link/20260715210322.02a4f3fced21.I94bbd08ac38001e11d5143a8b3f54dcea8ae8e15@changeid Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-rw-r--r--net/mac80211/ieee80211_i.h4
-rw-r--r--net/mac80211/mlme.c13
-rw-r--r--net/mac80211/util.c24
3 files changed, 29 insertions, 12 deletions
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index d585820245dd..11f449e8ff00 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -2771,8 +2771,8 @@ int ieee80211_put_eht_cap(struct sk_buff *skb,
int ieee80211_put_uhr_cap(struct sk_buff *skb,
struct ieee80211_sub_if_data *sdata,
const struct ieee80211_supported_band *sband);
-int ieee80211_put_reg_conn(struct sk_buff *skb,
- enum ieee80211_channel_flags flags);
+void ieee80211_put_reg_conn(struct ieee80211_sub_if_data *sdata,
+ struct sk_buff *skb);
/* channel management */
bool ieee80211_chandef_ht_oper(const struct ieee80211_ht_operation *ht_oper,
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 9e92337bb6f9..1afdb610dff2 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -2307,13 +2307,14 @@ ieee80211_add_link_elems(struct ieee80211_sub_if_data *sdata,
offset = ieee80211_add_before_reg_conn(skb, extra_elems,
extra_elems_len, offset);
- if (sband->band == NL80211_BAND_6GHZ) {
+ /* only add this on the assoc link, not in per-STA profiles */
+ if (link) {
/*
* as per Section E.2.7 of IEEE 802.11 REVme D7.0, non-AP STA
* capable of operating on the 6 GHz band shall transmit
* regulatory connectivity element.
*/
- ieee80211_put_reg_conn(skb, chan->flags);
+ ieee80211_put_reg_conn(sdata, skb);
}
/*
@@ -2564,11 +2565,8 @@ ieee80211_link_common_elems_size(struct ieee80211_sub_if_data *sdata,
sizeof(struct ieee80211_he_mcs_nss_supp) +
IEEE80211_HE_PPE_THRES_MAX_LEN;
- if (sband->band == NL80211_BAND_6GHZ) {
+ if (sband->band == NL80211_BAND_6GHZ)
size += 2 + 1 + sizeof(struct ieee80211_he_6ghz_capa);
- /* reg connection */
- size += 4;
- }
size += 2 + 1 + sizeof(struct ieee80211_eht_cap_elem) +
sizeof(struct ieee80211_eht_mcs_nss_supp) +
@@ -2615,7 +2613,8 @@ static int ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
2 + assoc_data->ssid_len + /* SSID */
assoc_data->ie_len + /* extra IEs */
(assoc_data->fils_kek_len ? 16 /* AES-SIV */ : 0) +
- 9; /* WMM */
+ 9 /* WMM */ +
+ 4 /* regulatory connectivity, if 6 GHz is supported */;
for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++) {
struct cfg80211_bss *cbss = assoc_data->link[link_id].bss;
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index f6d4ae4127c8..34f500deb2c8 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -2703,12 +2703,31 @@ end:
return 0;
}
-int ieee80211_put_reg_conn(struct sk_buff *skb,
- enum ieee80211_channel_flags flags)
+void ieee80211_put_reg_conn(struct ieee80211_sub_if_data *sdata,
+ struct sk_buff *skb)
{
+ struct ieee80211_local *local = sdata->local;
u8 reg_conn = IEEE80211_REG_CONN_LPI_VALID |
IEEE80211_REG_CONN_LPI_VALUE |
IEEE80211_REG_CONN_SP_VALID;
+ struct ieee80211_supported_band *sband;
+ bool available_channels = false;
+ u32 flags = 0;
+ int i;
+
+ sband = local->hw.wiphy->bands[NL80211_BAND_6GHZ];
+ if (!sband)
+ return;
+
+ for (i = 0; i < sband->n_channels; i++) {
+ if (sband->channels[i].flags & IEEE80211_CHAN_DISABLED)
+ continue;
+ flags |= sband->channels[i].flags;
+ available_channels = true;
+ }
+
+ if (!available_channels)
+ return;
if (!(flags & IEEE80211_CHAN_NO_6GHZ_AFC_CLIENT))
reg_conn |= IEEE80211_REG_CONN_SP_VALUE;
@@ -2717,7 +2736,6 @@ int ieee80211_put_reg_conn(struct sk_buff *skb,
skb_put_u8(skb, 1 + sizeof(reg_conn));
skb_put_u8(skb, WLAN_EID_EXT_NON_AP_STA_REG_CON);
skb_put_u8(skb, reg_conn);
- return 0;
}
int ieee80211_put_he_6ghz_cap(struct sk_buff *skb,