* [PATCH wireless-next 0/7] wifi: mac80211: station link handling for ST
@ 2026-11-02 21:42 Johannes Berg
2026-11-02 21:42 ` [PATCH wireless-next 1/7] wifi: mac80211: rename ieee80211_sta_activate_link() Johannes Berg
` (6 more replies)
0 siblings, 7 replies; 12+ messages in thread
From: Johannes Berg @ 2026-11-02 21:42 UTC (permalink / raw)
To: linux-wireless
For SMD Transition, we're going to need to add a station for
the new AP MLD, with links relative to that, not related to
the links of the vif.
Rather than try to handle this in the drivers, do something
in mac80211 to make it easier: track the active links in the
station instead of inferring it from the vif links, so that
we can have it separate during SMD transition.
Outside of SMD transition this is just a bit of a help and
cleanup, but during SMD transition it's required.
johannes
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH wireless-next 1/7] wifi: mac80211: rename ieee80211_sta_activate_link()
2026-11-02 21:42 [PATCH wireless-next 0/7] wifi: mac80211: station link handling for ST Johannes Berg
@ 2026-11-02 21:42 ` Johannes Berg
2026-11-02 21:42 ` [PATCH wireless-next 2/7] wifi: mac80211: clarify station link handling Johannes Berg
` (5 subsequent siblings)
6 siblings, 0 replies; 12+ messages in thread
From: Johannes Berg @ 2026-11-02 21:42 UTC (permalink / raw)
To: linux-wireless; +Cc: Johannes Berg, Miriam Rachel Korenblit
From: Johannes Berg <johannes.berg@intel.com>
This isn't activate() in the sense of setting the link
to actually be active, since active links of a station
the intersection of valid links of the station and the
interface's active links.
For SMD Transition, we're going to have to track those
of a station separately, and activate() becomes more
confusing.
Rename this to ieee80211_sta_set_link_valid().
Reviewed-by: Miriam Rachel Korenblit <miriam.rachel.korenblit@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
net/mac80211/cfg.c | 4 ++--
net/mac80211/mlme.c | 4 ++--
net/mac80211/sta_info.c | 2 +-
net/mac80211/sta_info.h | 2 +-
4 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 6e466f8e1653..a4f242a23957 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -6122,8 +6122,8 @@ ieee80211_add_link_station(struct wiphy *wiphy, struct net_device *dev,
rate_control_rate_init(link_sta);
}
- /* ieee80211_sta_activate_link frees the link upon failure */
- return ieee80211_sta_activate_link(sta, params->link_id);
+ /* ieee80211_sta_set_link_valid frees the link upon failure */
+ return ieee80211_sta_set_link_valid(sta, params->link_id);
}
static int
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 8eda8154ba3d..2625103f6307 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -7223,7 +7223,7 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
}
if (link_id != assoc_data->assoc_link_id) {
- err = ieee80211_sta_activate_link(sta, link_id);
+ err = ieee80211_sta_set_link_valid(sta, link_id);
if (err)
goto out_err;
}
@@ -11218,7 +11218,7 @@ ieee80211_process_ml_reconf_resp(struct ieee80211_sub_if_data *sdata,
if (add_links_data->link[link_id].status != WLAN_STATUS_SUCCESS)
goto disconnect;
- if (ieee80211_sta_activate_link(sta, link_id))
+ if (ieee80211_sta_set_link_valid(sta, link_id))
goto disconnect;
changed |= ieee80211_link_set_associated(link, cbss);
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 23166fc39729..572455549c63 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -3473,7 +3473,7 @@ void ieee80211_sta_free_link(struct sta_info *sta, unsigned int link_id)
sta_remove_link(sta, link_id, false);
}
-int ieee80211_sta_activate_link(struct sta_info *sta, unsigned int link_id)
+int ieee80211_sta_set_link_valid(struct sta_info *sta, unsigned int link_id)
{
struct ieee80211_sub_if_data *sdata = sta->sdata;
struct link_sta_info *link_sta;
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 8c6a9fee6b29..0a286185125d 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -1008,7 +1008,7 @@ void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata,
int ieee80211_sta_allocate_link(struct sta_info *sta, unsigned int link_id);
void ieee80211_sta_free_link(struct sta_info *sta, unsigned int link_id);
-int ieee80211_sta_activate_link(struct sta_info *sta, unsigned int link_id);
+int ieee80211_sta_set_link_valid(struct sta_info *sta, unsigned int link_id);
void ieee80211_sta_remove_link(struct sta_info *sta, unsigned int link_id);
void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta);
--
2.56.0
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH wireless-next 2/7] wifi: mac80211: clarify station link handling
2026-11-02 21:42 [PATCH wireless-next 0/7] wifi: mac80211: station link handling for ST Johannes Berg
2026-11-02 21:42 ` [PATCH wireless-next 1/7] wifi: mac80211: rename ieee80211_sta_activate_link() Johannes Berg
@ 2026-11-02 21:42 ` Johannes Berg
2026-11-02 21:42 ` [PATCH wireless-next 3/7] wifi: mac80211: clarify change_vif_links() documentation Johannes Berg
` (4 subsequent siblings)
6 siblings, 0 replies; 12+ messages in thread
From: Johannes Berg @ 2026-11-02 21:42 UTC (permalink / raw)
To: linux-wireless; +Cc: Johannes Berg, Miriam Rachel Korenblit
From: Johannes Berg <johannes.berg@intel.com>
Just like for interfaces, the change_sta_links() method
really changes the active links of a station, not (just)
valid ones. It's possible that both change, of course,
but in many cases (such as link switching) only the
active ones really change.
Clarify the documentation and add a note in the mac80211
code about why ieee80211_sta_set_link_valid() can call
the driver wrapper directly without any check.
Reviewed-by: Miriam Rachel Korenblit <miriam.rachel.korenblit@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
include/net/mac80211.h | 10 ++++++----
net/mac80211/sta_info.c | 4 ++++
2 files changed, 10 insertions(+), 4 deletions(-)
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 76ff86ff9974..f07a4d262314 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -4741,11 +4741,13 @@ struct ieee80211_prep_tx_info {
* Note that removal of link should always succeed, so the return value
* will be ignored in a removal only case.
* This callback can sleep.
- * @change_sta_links: Change the valid links of a station, similar to
+ * @change_sta_links: Change the active links of a station, similar to
* @change_vif_links. This callback can sleep.
- * Note that a sta can also be inserted or removed with valid links,
- * i.e. passed to @sta_add/@sta_state with sta->valid_links not zero.
- * In fact, cannot change from having valid_links and not having them.
+ * Note that a sta can also be inserted or removed with active links,
+ * i.e. passed to @sta_add/@sta_state with sta->valid_links not zero
+ * (note vif->active_links needs to be considered with sta->valid_links).
+ * It cannot, in fact, change between having valid_links and not having
+ * any, since it either represents an MLD or not.
* @set_hw_timestamp: Enable/disable HW timestamping of TM/FTM frames. This is
* not restored at HW reset by mac80211 so drivers need to take care of
* that.
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 572455549c63..61aadc3c695d 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -3507,6 +3507,10 @@ int ieee80211_sta_set_link_valid(struct sta_info *sta, unsigned int link_id)
*/
ieee80211_sta_recalc_aggregates(&sta->sta);
+ /*
+ * Note: this is a no-op when new links are added that
+ * aren't actually active in the vif.
+ */
ret = drv_change_sta_links(sdata->local, sdata, &sta->sta,
old_links, new_links);
if (ret) {
--
2.56.0
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH wireless-next 3/7] wifi: mac80211: clarify change_vif_links() documentation
2026-11-02 21:42 [PATCH wireless-next 0/7] wifi: mac80211: station link handling for ST Johannes Berg
2026-11-02 21:42 ` [PATCH wireless-next 1/7] wifi: mac80211: rename ieee80211_sta_activate_link() Johannes Berg
2026-11-02 21:42 ` [PATCH wireless-next 2/7] wifi: mac80211: clarify station link handling Johannes Berg
@ 2026-11-02 21:42 ` Johannes Berg
2026-11-02 21:42 ` [PATCH wireless-next 4/7] wifi: mac80211: add link_sta::link_conf pointer Johannes Berg
` (3 subsequent siblings)
6 siblings, 0 replies; 12+ messages in thread
From: Johannes Berg @ 2026-11-02 21:42 UTC (permalink / raw)
To: linux-wireless; +Cc: Johannes Berg, Miriam Rachel Korenblit
From: Johannes Berg <johannes.berg@intel.com>
Thinking about SMD Transition and looking at this
documentation, and thinking about whether or not
this method can be re-used, I found the docs to be
misleading. Clarify the description.
Reviewed-by: Miriam Rachel Korenblit <miriam.rachel.korenblit@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
include/net/mac80211.h | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index f07a4d262314..2576f9a30b37 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -4732,10 +4732,11 @@ struct ieee80211_prep_tx_info {
* resolve a path for hardware flow offloading
* @can_activate_links: Checks if a specific active_links bitmap is
* supported by the driver.
- * @change_vif_links: Change the valid links on an interface, note that while
+ * @change_vif_links: Change the active links of an interface, note that while
* removing the old link information is still valid (link_conf pointer),
- * but may immediately disappear after the function returns. The old or
- * new links bitmaps may be 0 if going from/to a non-MLO situation.
+ * but may immediately disappear after the function returns if the link(s)
+ * is/are not just deactivated, but removed entirely. The old or new links
+ * bitmaps may be 0 if going from/to a non-MLO situation.
* The @old array contains pointers to the old bss_conf structures
* that were already removed, in case they're needed.
* Note that removal of link should always succeed, so the return value
--
2.56.0
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH wireless-next 4/7] wifi: mac80211: add link_sta::link_conf pointer
2026-11-02 21:42 [PATCH wireless-next 0/7] wifi: mac80211: station link handling for ST Johannes Berg
` (2 preceding siblings ...)
2026-11-02 21:42 ` [PATCH wireless-next 3/7] wifi: mac80211: clarify change_vif_links() documentation Johannes Berg
@ 2026-11-02 21:42 ` Johannes Berg
2026-11-02 21:42 ` [PATCH wireless-next 5/7] wifi: mac80211: add sta_info_alloc_with_links() Johannes Berg
` (2 subsequent siblings)
6 siblings, 0 replies; 12+ messages in thread
From: Johannes Berg @ 2026-11-02 21:42 UTC (permalink / raw)
To: linux-wireless; +Cc: Johannes Berg, Miriam Rachel Korenblit
From: Johannes Berg <johannes.berg@intel.com>
It's relatively simple to maintain this pointer back to the
interface's link_conf, since it has to exist when the link
is added to the station. On the other hand, it's not simple
for the driver to look it up indirectly through the vif and
it won't be possible to do so during SMD Transition.
Add the pointer and keep it pointing to the right place in
mac80211.
While already touching the function prototype anyway, get
rid of the gfp_t argument that's always GFP_KERNEL.
Reviewed-by: Miriam Rachel Korenblit <miriam.rachel.korenblit@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
include/net/mac80211.h | 4 ++++
net/mac80211/cfg.c | 25 ++++++++++++++++++-------
net/mac80211/mlme.c | 9 ++++-----
net/mac80211/sta_info.c | 41 ++++++++++++++++++++++++++++++++++-------
net/mac80211/sta_info.h | 9 ++++-----
5 files changed, 64 insertions(+), 24 deletions(-)
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 2576f9a30b37..e54fa07e2cbf 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -2619,6 +2619,9 @@ struct ieee80211_sta_aggregates {
* or a MLD STA(multiple entries) are stored here.
*
* @sta: reference to owning STA
+ * @link_conf: The per-link BSS configuration for the link that the
+ * station belongs to. During SMD Transition, this link might
+ * not be in vif->links[].
* @addr: MAC address of the Link STA. For non-MLO STA this is same as the addr
* in ieee80211_sta. For MLO Link STA this addr can be same or different
* from addr in ieee80211_sta (representing MLD STA addr)
@@ -2648,6 +2651,7 @@ struct ieee80211_sta_aggregates {
*/
struct ieee80211_link_sta {
struct ieee80211_sta *sta;
+ struct ieee80211_bss_conf *link_conf;
u8 addr[ETH_ALEN];
u8 link_id;
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index a4f242a23957..38898fd58692 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -2925,13 +2925,19 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct wireless_dev *wdev,
* but we need to have a link_mac in that case as well, so use the
* STA's MAC address in that case.
*/
- if (params->link_sta_params.link_id >= 0)
- sta = sta_info_alloc_with_link(sdata, mac,
- params->link_sta_params.link_id,
- params->link_sta_params.link_mac ?: mac,
- GFP_KERNEL);
- else
+ if (params->link_sta_params.link_id >= 0) {
+ struct ieee80211_link_data *link;
+
+ link = wiphy_dereference(wiphy,
+ sdata->link[params->link_sta_params.link_id]);
+ if (!link)
+ return -ENOLINK;
+
+ sta = sta_info_alloc_with_link(link, mac,
+ params->link_sta_params.link_mac ?: mac);
+ } else {
sta = sta_info_alloc(sdata, mac, GFP_KERNEL);
+ }
if (!sta)
return -ENOMEM;
@@ -6090,6 +6096,7 @@ ieee80211_add_link_station(struct wiphy *wiphy, struct net_device *dev,
{
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
struct ieee80211_local *local = wiphy_priv(wiphy);
+ struct ieee80211_link_data *link;
struct sta_info *sta;
int ret;
@@ -6105,6 +6112,10 @@ ieee80211_add_link_station(struct wiphy *wiphy, struct net_device *dev,
if (sta->sta.valid_links & BIT(params->link_id))
return -EALREADY;
+ link = wiphy_dereference(wiphy, sdata->link[params->link_id]);
+ if (!link)
+ return -ENOLINK;
+
ret = ieee80211_sta_allocate_link(sta, params->link_id);
if (ret)
return ret;
@@ -6123,7 +6134,7 @@ ieee80211_add_link_station(struct wiphy *wiphy, struct net_device *dev,
}
/* ieee80211_sta_set_link_valid frees the link upon failure */
- return ieee80211_sta_set_link_valid(sta, params->link_id);
+ return ieee80211_sta_set_link_valid(sta, link);
}
static int
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 2625103f6307..8b95a3277066 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -7223,7 +7223,7 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
}
if (link_id != assoc_data->assoc_link_id) {
- err = ieee80211_sta_set_link_valid(sta, link_id);
+ err = ieee80211_sta_set_link_valid(sta, link);
if (err)
goto out_err;
}
@@ -9764,9 +9764,8 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata,
if (!have_sta) {
if (mlo)
- new_sta = sta_info_alloc_with_link(sdata, ap_mld_addr,
- link_id, cbss->bssid,
- GFP_KERNEL);
+ new_sta = sta_info_alloc_with_link(link, ap_mld_addr,
+ cbss->bssid);
else
new_sta = sta_info_alloc(sdata, ap_mld_addr, GFP_KERNEL);
@@ -11218,7 +11217,7 @@ ieee80211_process_ml_reconf_resp(struct ieee80211_sub_if_data *sdata,
if (add_links_data->link[link_id].status != WLAN_STATUS_SUCCESS)
goto disconnect;
- if (ieee80211_sta_set_link_valid(sta, link_id))
+ if (ieee80211_sta_set_link_valid(sta, link))
goto disconnect;
changed |= ieee80211_link_set_associated(link, cbss);
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 61aadc3c695d..3c2e08808e99 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -629,8 +629,25 @@ static void sta_info_add_link(struct sta_info *sta,
link_sta->agg.max_rc_amsdu_len = IEEE80211_MAX_MPDU_LEN_HT_BA;
}
+static struct ieee80211_bss_conf *
+link_data_pub_link_conf(struct ieee80211_link_data *link)
+{
+ struct ieee80211_sub_if_data *sdata = link->sdata;
+ struct ieee80211_sub_if_data *bss_sdata = get_bss_sdata(sdata);
+
+ if (sdata == bss_sdata)
+ return link->conf;
+
+ if (link == &sdata->deflink)
+ return bss_sdata->deflink.conf;
+
+ return sdata_dereference(bss_sdata->vif.link_conf[link->link_id],
+ bss_sdata);
+}
+
static struct sta_info *
__sta_info_alloc(struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_link_data *link,
const u8 *addr, int link_id, const u8 *link_addr,
gfp_t gfp)
{
@@ -660,6 +677,9 @@ __sta_info_alloc(struct ieee80211_sub_if_data *sdata,
}
sta->sta.cur = &sta->sta.deflink.agg;
+ sta->sta.deflink.link_conf = link_data_pub_link_conf(link);
+ if (WARN_ON(!sta->sta.deflink.link_conf))
+ goto free;
spin_lock_init(&sta->lock);
spin_lock_init(&sta->ps_lock);
@@ -803,16 +823,15 @@ __sta_info_alloc(struct ieee80211_sub_if_data *sdata,
struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
const u8 *addr, gfp_t gfp)
{
- return __sta_info_alloc(sdata, addr, -1, addr, gfp);
+ return __sta_info_alloc(sdata, &sdata->deflink, addr, -1, addr, gfp);
}
-struct sta_info *sta_info_alloc_with_link(struct ieee80211_sub_if_data *sdata,
+struct sta_info *sta_info_alloc_with_link(struct ieee80211_link_data *link,
const u8 *mld_addr,
- unsigned int link_id,
- const u8 *link_addr,
- gfp_t gfp)
+ const u8 *link_addr)
{
- return __sta_info_alloc(sdata, mld_addr, link_id, link_addr, gfp);
+ return __sta_info_alloc(link->sdata, link, mld_addr, link->link_id,
+ link_addr, GFP_KERNEL);
}
static int sta_info_insert_check(struct sta_info *sta)
@@ -3473,12 +3492,15 @@ void ieee80211_sta_free_link(struct sta_info *sta, unsigned int link_id)
sta_remove_link(sta, link_id, false);
}
-int ieee80211_sta_set_link_valid(struct sta_info *sta, unsigned int link_id)
+int ieee80211_sta_set_link_valid(struct sta_info *sta,
+ struct ieee80211_link_data *link)
{
struct ieee80211_sub_if_data *sdata = sta->sdata;
struct link_sta_info *link_sta;
u16 old_links = sta->sta.valid_links;
+ int link_id = link->link_id;
u16 new_links = old_links | BIT(link_id);
+ struct ieee80211_bss_conf *link_conf;
int ret;
link_sta = rcu_dereference_protected(sta->link[link_id],
@@ -3495,6 +3517,11 @@ int ieee80211_sta_set_link_valid(struct sta_info *sta, unsigned int link_id)
/* we only modify under the mutex so this is fine */
rcu_read_unlock();
+ link_conf = link_data_pub_link_conf(link);
+ if (WARN_ON(!link_conf))
+ return -EINVAL;
+
+ link_sta->pub->link_conf = link_conf;
sta->sta.valid_links = new_links;
if (WARN_ON(!test_sta_flag(sta, WLAN_STA_INSERTED)))
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 0a286185125d..5187e3eadf30 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -925,11 +925,9 @@ struct sta_info *sta_info_get_by_idx(struct ieee80211_sub_if_data *sdata,
*/
struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
const u8 *addr, gfp_t gfp);
-struct sta_info *sta_info_alloc_with_link(struct ieee80211_sub_if_data *sdata,
+struct sta_info *sta_info_alloc_with_link(struct ieee80211_link_data *link,
const u8 *mld_addr,
- unsigned int link_id,
- const u8 *link_addr,
- gfp_t gfp);
+ const u8 *link_addr);
void sta_info_free(struct ieee80211_local *local, struct sta_info *sta);
@@ -1008,7 +1006,8 @@ void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata,
int ieee80211_sta_allocate_link(struct sta_info *sta, unsigned int link_id);
void ieee80211_sta_free_link(struct sta_info *sta, unsigned int link_id);
-int ieee80211_sta_set_link_valid(struct sta_info *sta, unsigned int link_id);
+int ieee80211_sta_set_link_valid(struct sta_info *sta,
+ struct ieee80211_link_data *link);
void ieee80211_sta_remove_link(struct sta_info *sta, unsigned int link_id);
void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta);
--
2.56.0
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH wireless-next 5/7] wifi: mac80211: add sta_info_alloc_with_links()
2026-11-02 21:42 [PATCH wireless-next 0/7] wifi: mac80211: station link handling for ST Johannes Berg
` (3 preceding siblings ...)
2026-11-02 21:42 ` [PATCH wireless-next 4/7] wifi: mac80211: add link_sta::link_conf pointer Johannes Berg
@ 2026-11-02 21:42 ` Johannes Berg
2026-11-02 21:42 ` [PATCH wireless-next 6/7] wifi: mac80211: track sta->active_links Johannes Berg
2026-11-02 21:42 ` [PATCH wireless-next 7/7] wifi: mac80211: use sta->active_links in for_each_sta_active_link() Johannes Berg
6 siblings, 0 replies; 12+ messages in thread
From: Johannes Berg @ 2026-11-02 21:42 UTC (permalink / raw)
To: linux-wireless; +Cc: Johannes Berg, Miriam Rachel Korenblit
From: Johannes Berg <johannes.berg@intel.com>
For SMD Transition, we'll need to allocate a station with
multiple links, refactor the existing code to add such a
function.
Reviewed-by: Miriam Rachel Korenblit <miriam.rachel.korenblit@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
net/mac80211/sta_info.c | 96 ++++++++++++++++++++++++++++++++++++++---
net/mac80211/sta_info.h | 8 ++++
2 files changed, 97 insertions(+), 7 deletions(-)
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 3c2e08808e99..a86da3c70152 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -677,9 +677,11 @@ __sta_info_alloc(struct ieee80211_sub_if_data *sdata,
}
sta->sta.cur = &sta->sta.deflink.agg;
- sta->sta.deflink.link_conf = link_data_pub_link_conf(link);
- if (WARN_ON(!sta->sta.deflink.link_conf))
- goto free;
+ if (link) {
+ sta->sta.deflink.link_conf = link_data_pub_link_conf(link);
+ if (WARN_ON(!sta->sta.deflink.link_conf))
+ goto free;
+ }
spin_lock_init(&sta->lock);
spin_lock_init(&sta->ps_lock);
@@ -826,6 +828,62 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
return __sta_info_alloc(sdata, &sdata->deflink, addr, -1, addr, gfp);
}
+struct sta_info *
+sta_info_alloc_with_links(struct ieee80211_sub_if_data *sdata,
+ const u8 *mld_addr,
+ const u8 *link_addrs[IEEE80211_MLD_MAX_NUM_LINKS])
+{
+ struct ieee80211_local *local = sdata->local;
+ struct sta_info *sta;
+ int first = -1;
+
+ if (WARN_ON(!link_addrs))
+ return NULL;
+
+ for (int link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++) {
+ if (!link_addrs[link_id])
+ continue;
+ first = link_id;
+ break;
+ }
+
+ if (WARN_ON(first < 0))
+ return NULL;
+
+ sta = __sta_info_alloc(sdata, NULL, mld_addr, first,
+ link_addrs[first], GFP_KERNEL);
+ if (!sta)
+ return NULL;
+
+ for (int link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++) {
+ struct sta_link_alloc *alloc;
+
+ if (!link_addrs[link_id] || link_id == first)
+ continue;
+
+ alloc = kzalloc_obj(*alloc);
+ if (!alloc)
+ goto free;
+
+ if (sta_info_alloc_link(local, &alloc->info, GFP_KERNEL)) {
+ kfree(alloc);
+ goto free;
+ }
+
+ sta_info_add_link(sta, link_id, &alloc->info, &alloc->sta);
+ memcpy(alloc->info.addr, link_addrs[link_id], ETH_ALEN);
+ memcpy(alloc->sta.addr, link_addrs[link_id], ETH_ALEN);
+
+ sta->sta.valid_links |= BIT(link_id);
+ }
+
+ return sta;
+
+free:
+ sta_info_free(local, sta);
+ return NULL;
+}
+
struct sta_info *sta_info_alloc_with_link(struct ieee80211_link_data *link,
const u8 *mld_addr,
const u8 *link_addr)
@@ -969,9 +1027,25 @@ static int sta_info_insert_finish(struct sta_info *sta) __acquires(RCU)
if (err)
goto out_drop_sta;
- if (sta->sta.valid_links) {
- err = link_sta_info_hash_add(local, &sta->deflink);
+ for (int i = 0; i < ARRAY_SIZE(sta->link); i++) {
+ struct link_sta_info *link_sta;
+
+ if (!(sta->sta.valid_links & BIT(i)))
+ continue;
+
+ link_sta = wiphy_dereference(local->hw.wiphy, sta->link[i]);
+ if (WARN_ON(!link_sta))
+ continue;
+
+ err = link_sta_info_hash_add(local, link_sta);
if (err) {
+ for (int j = 0; j < i; j++) {
+ link_sta = wiphy_dereference(local->hw.wiphy,
+ sta->link[j]);
+ if (link_sta)
+ link_sta_info_hash_del(local,
+ link_sta);
+ }
sta_info_hash_del(local, sta);
goto out_drop_sta;
}
@@ -1037,8 +1111,16 @@ static int sta_info_insert_finish(struct sta_info *sta) __acquires(RCU)
return 0;
out_remove:
- if (sta->sta.valid_links)
- link_sta_info_hash_del(local, &sta->deflink);
+ for (int i = 0; i < ARRAY_SIZE(sta->link); i++) {
+ struct link_sta_info *link_sta;
+
+ if (!(sta->sta.valid_links & BIT(i)))
+ continue;
+
+ link_sta = wiphy_dereference(local->hw.wiphy, sta->link[i]);
+ if (link_sta)
+ link_sta_info_hash_del(local, link_sta);
+ }
sta_info_hash_del(local, sta);
list_del_rcu(&sta->list);
out_drop_sta:
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 5187e3eadf30..110788c0d623 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -928,6 +928,14 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
struct sta_info *sta_info_alloc_with_link(struct ieee80211_link_data *link,
const u8 *mld_addr,
const u8 *link_addr);
+/*
+ * Note: Unlike sta_info_alloc_with_link(), none of the link stations
+ * actually get a link_conf pointer! Must be set later.
+ */
+struct sta_info *
+sta_info_alloc_with_links(struct ieee80211_sub_if_data *sdata,
+ const u8 *mld_addr,
+ const u8 *link_addrs[IEEE80211_MLD_MAX_NUM_LINKS]);
void sta_info_free(struct ieee80211_local *local, struct sta_info *sta);
--
2.56.0
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH wireless-next 6/7] wifi: mac80211: track sta->active_links
2026-11-02 21:42 [PATCH wireless-next 0/7] wifi: mac80211: station link handling for ST Johannes Berg
` (4 preceding siblings ...)
2026-11-02 21:42 ` [PATCH wireless-next 5/7] wifi: mac80211: add sta_info_alloc_with_links() Johannes Berg
@ 2026-11-02 21:42 ` Johannes Berg
2026-11-04 18:52 ` Johannes Berg
2026-11-02 21:42 ` [PATCH wireless-next 7/7] wifi: mac80211: use sta->active_links in for_each_sta_active_link() Johannes Berg
6 siblings, 1 reply; 12+ messages in thread
From: Johannes Berg @ 2026-11-02 21:42 UTC (permalink / raw)
To: linux-wireless; +Cc: Johannes Berg, Miriam Rachel Korenblit
From: Johannes Berg <johannes.berg@intel.com>
We've always assumed that a station has active_links
that are simply sta->valid_links & vif->active_links,
and while this should be true most of the time, during
SMD transition the target AP MLD will have a different
(set of) active link(s) than the vif, and needs to be
added so the state can be transferred over.
Add and track sta->active_links, and use it in a few
places. Upon allocation, a sta initially has no active
links, it's up to the caller to fix that; document it.
During link switch, the active links change with the
interface ones, do that in the drv_change_sta_links()
wrapper.
Reviewed-by: Miriam Rachel Korenblit <miriam.rachel.korenblit@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
include/net/mac80211.h | 3 +++
net/mac80211/cfg.c | 8 ++++++++
net/mac80211/driver-ops.c | 13 ++++++++++---
net/mac80211/key.c | 10 +++++++---
net/mac80211/mlme.c | 8 ++++++--
net/mac80211/sta_info.c | 12 ++++++++++--
net/mac80211/sta_info.h | 1 +
7 files changed, 45 insertions(+), 10 deletions(-)
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index e54fa07e2cbf..335eee075952 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -2727,6 +2727,8 @@ struct ieee80211_link_sta {
* would be assigned to link[link_id] where link_id is the id assigned
* by the AP.
* @valid_links: bitmap of valid links, or 0 for non-MLO
+ * @active_links: bitmap of active links, always a subset of @valid_links;
+ * unused (0) for non-MLO
* @spp_amsdu: indicates whether the STA uses SPP A-MSDU or not.
* @epp_peer: indicates that the peer is an EPP peer.
* @cip: indicates whether the STA uses control frame protection or not.
@@ -2762,6 +2764,7 @@ struct ieee80211_sta {
struct ieee80211_txq *txq[IEEE80211_NUM_TIDS + 1];
u16 valid_links;
+ u16 active_links;
u16 ext_mld_capa_ops;
bool epp_peer;
struct ieee80211_link_sta deflink;
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 38898fd58692..9e47360ee8f5 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -2935,6 +2935,14 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct wireless_dev *wdev,
sta = sta_info_alloc_with_link(link, mac,
params->link_sta_params.link_mac ?: mac);
+
+ /*
+ * In this path (AP side), the link the station is created for
+ * must be active, so just set the active links.
+ */
+ if (sta)
+ sta->sta.active_links =
+ BIT(params->link_sta_params.link_id);
} else {
sta = sta_info_alloc(sdata, mac, GFP_KERNEL);
}
diff --git a/net/mac80211/driver-ops.c b/net/mac80211/driver-ops.c
index 1f3e0765a8ab..e616bfbe687b 100644
--- a/net/mac80211/driver-ops.c
+++ b/net/mac80211/driver-ops.c
@@ -515,9 +515,14 @@ int drv_set_key(struct ieee80211_local *local,
if (!check_sdata_in_driver(sdata))
return -EIO;
- if (WARN_ON(key->link_id >= 0 && sdata->vif.active_links &&
- !(sdata->vif.active_links & BIT(key->link_id))))
- return -ENOLINK;
+ if (key->link_id >= 0) {
+ u16 active_links = sta ? sta->active_links :
+ sdata->vif.active_links;
+
+ if (WARN_ON(active_links &&
+ !(active_links & BIT(key->link_id))))
+ return -ENOLINK;
+ }
if (fips_enabled)
return -EOPNOTSUPP;
@@ -621,6 +626,8 @@ int drv_change_sta_links(struct ieee80211_local *local,
if (ret)
return ret;
+ sta->active_links = new_links;
+
/* during reconfig don't add it to debugfs again */
if (local->in_reconfig || local->resuming)
return 0;
diff --git a/net/mac80211/key.c b/net/mac80211/key.c
index d1e3fe37d2e3..9b6a1f0627c6 100644
--- a/net/mac80211/key.c
+++ b/net/mac80211/key.c
@@ -197,9 +197,13 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
}
}
- if (key->conf.link_id >= 0 && sdata->vif.active_links &&
- !(sdata->vif.active_links & BIT(key->conf.link_id)))
- return 0;
+ if (key->conf.link_id >= 0) {
+ u16 active_links = sta ? sta->sta.active_links :
+ sdata->vif.active_links;
+
+ if (active_links && !(active_links & BIT(key->conf.link_id)))
+ return 0;
+ }
ret = drv_set_key(key->local, SET_KEY, sdata,
sta ? &sta->sta : NULL, &key->conf);
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 8b95a3277066..4caa1853531a 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -9763,11 +9763,15 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata,
}
if (!have_sta) {
- if (mlo)
+ if (mlo) {
new_sta = sta_info_alloc_with_link(link, ap_mld_addr,
cbss->bssid);
- else
+ /* the auth/assoc link is currently the active link */
+ if (new_sta)
+ new_sta->sta.active_links = BIT(link_id);
+ } else {
new_sta = sta_info_alloc(sdata, ap_mld_addr, GFP_KERNEL);
+ }
if (!new_sta) {
err = -ENOMEM;
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index a86da3c70152..a9c0f873266d 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -672,6 +672,7 @@ __sta_info_alloc(struct ieee80211_sub_if_data *sdata,
sta_info_add_link(sta, link_id, &sta->deflink,
&sta->sta.deflink);
sta->sta.valid_links = BIT(link_id);
+ /* active_links isn't set yet */
} else {
sta_info_add_link(sta, 0, &sta->deflink, &sta->sta.deflink);
}
@@ -1087,7 +1088,7 @@ static int sta_info_insert_finish(struct sta_info *sta) __acquires(RCU)
continue;
ieee80211_link_sta_debugfs_add(link_sta);
- if (sdata->vif.active_links & BIT(i))
+ if (sta->sta.active_links & BIT(i))
ieee80211_link_sta_debugfs_drv_add(link_sta);
}
} else {
@@ -2598,7 +2599,7 @@ void ieee80211_sta_recalc_aggregates(struct ieee80211_sta *pubsta)
{
struct sta_info *sta = container_of(pubsta, struct sta_info, sta);
- __ieee80211_sta_recalc_aggregates(sta, sta->sdata->vif.active_links);
+ __ieee80211_sta_recalc_aggregates(sta, sta->sta.active_links);
}
EXPORT_SYMBOL(ieee80211_sta_recalc_aggregates);
@@ -3647,6 +3648,13 @@ void ieee80211_sta_remove_link(struct sta_info *sta, unsigned int link_id)
ieee80211_unlink_link_sta_keys(sta->local, link_sta);
sta->sta.valid_links &= ~BIT(link_id);
+ sta->sta.active_links &= ~BIT(link_id);
+
+ WARN(!sta->sta.valid_links || !sta->sta.active_links,
+ "STA %pM has no links after removing %d (valid:0x%x, active:0x%x)\n",
+ sta->sta.addr, link_id,
+ sta->sta.valid_links,
+ sta->sta.active_links);
if (!WARN_ON(!test_sta_flag(sta, WLAN_STA_INSERTED)))
drv_change_sta_links(sdata->local, sdata, &sta->sta,
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 110788c0d623..4b1c441b610e 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -922,6 +922,7 @@ struct sta_info *sta_info_get_by_idx(struct ieee80211_sub_if_data *sdata,
/*
* Create a new STA info, caller owns returned structure
* until sta_info_insert().
+ * Note: neither allocation function sets sta->sta.active_links!
*/
struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
const u8 *addr, gfp_t gfp);
--
2.56.0
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH wireless-next 7/7] wifi: mac80211: use sta->active_links in for_each_sta_active_link()
2026-11-02 21:42 [PATCH wireless-next 0/7] wifi: mac80211: station link handling for ST Johannes Berg
` (5 preceding siblings ...)
2026-11-02 21:42 ` [PATCH wireless-next 6/7] wifi: mac80211: track sta->active_links Johannes Berg
@ 2026-11-02 21:42 ` Johannes Berg
2026-11-03 19:08 ` kernel test robot
` (2 more replies)
6 siblings, 3 replies; 12+ messages in thread
From: Johannes Berg @ 2026-11-02 21:42 UTC (permalink / raw)
To: linux-wireless; +Cc: Johannes Berg, Miriam Rachel Korenblit
From: Johannes Berg <johannes.berg@intel.com>
With the new sta->active_links we can simplify the API
for for_each_sta_active_link() and no longer require
the vif to be passed in. This leads to bigger changes
in drivers, including removal of now unused variables.
It's mostly a cleanup, but will also allow drivers to
change code better in SMD Transition.
Reviewed-by: Miriam Rachel Korenblit <miriam.rachel.korenblit@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
drivers/net/wireless/intel/iwlwifi/mld/iface.c | 2 +-
drivers/net/wireless/intel/iwlwifi/mld/mac80211.c | 2 +-
drivers/net/wireless/intel/iwlwifi/mld/sta.c | 15 +++++----------
drivers/net/wireless/intel/iwlwifi/mld/tx.c | 2 +-
drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 12 ++++++------
drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c | 14 +++++++-------
drivers/net/wireless/intel/iwlwifi/mvm/sta.c | 2 +-
drivers/net/wireless/mediatek/mt76/mt7925/mcu.c | 4 ++--
.../net/wireless/mediatek/mt76/mt7996/debugfs.c | 5 +----
drivers/net/wireless/mediatek/mt76/mt7996/main.c | 6 +++---
include/net/mac80211.h | 6 +++---
11 files changed, 31 insertions(+), 39 deletions(-)
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/iface.c b/drivers/net/wireless/intel/iwlwifi/mld/iface.c
index 0307abff5644..1d66f106e7bd 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/iface.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/iface.c
@@ -155,7 +155,7 @@ static void iwl_mld_mac_wifi_gen_sta_iter(void *_data,
if (mld_sta->vif != data->vif)
return;
- for_each_sta_active_link(data->vif, sta, link_sta, link_id) {
+ for_each_sta_active_link(sta, link_sta, link_id) {
if (link_sta->he_cap.has_he)
data->support->he_support = 1;
if (link_sta->eht_cap.has_eht)
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c
index 99cbd279ce48..898e376e2979 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c
@@ -1745,7 +1745,7 @@ static void iwl_mld_link_set_2mhz_block(struct iwl_mld *mld,
struct ieee80211_link_sta *link_sta;
unsigned int link_id;
- for_each_sta_active_link(vif, sta, link_sta, link_id) {
+ for_each_sta_active_link(sta, link_sta, link_id) {
struct ieee80211_bss_conf *link_conf =
link_conf_dereference_protected(vif, link_id);
struct iwl_mld_link *mld_link =
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/sta.c b/drivers/net/wireless/intel/iwlwifi/mld/sta.c
index 97f013330f06..cf86f1da959b 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/sta.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/sta.c
@@ -720,7 +720,7 @@ int iwl_mld_update_all_link_stations(struct iwl_mld *mld,
struct ieee80211_link_sta *link_sta;
int link_id;
- for_each_sta_active_link(mld_sta->vif, sta, link_sta, link_id) {
+ for_each_sta_active_link(sta, link_sta, link_id) {
int ret = iwl_mld_add_modify_sta_cmd(mld, link_sta);
if (ret)
@@ -815,7 +815,6 @@ iwl_mld_init_sta(struct iwl_mld *mld, struct ieee80211_sta *sta,
int iwl_mld_add_sta(struct iwl_mld *mld, struct ieee80211_sta *sta,
struct ieee80211_vif *vif)
{
- struct iwl_mld_sta *mld_sta = iwl_mld_sta_from_mac80211(sta);
struct ieee80211_link_sta *link_sta;
enum iwl_fw_sta_type type;
int link_id;
@@ -841,7 +840,7 @@ int iwl_mld_add_sta(struct iwl_mld *mld, struct ieee80211_sta *sta,
* in the restart case if the single link that is active during
* reconfig is not the deflink one.
*/
- for_each_sta_active_link(mld_sta->vif, sta, link_sta, link_id) {
+ for_each_sta_active_link(sta, link_sta, link_id) {
ret = iwl_mld_add_link_sta(mld, link_sta);
if (ret)
goto destroy_sta;
@@ -857,11 +856,10 @@ int iwl_mld_add_sta(struct iwl_mld *mld, struct ieee80211_sta *sta,
void iwl_mld_flush_sta_txqs(struct iwl_mld *mld, struct ieee80211_sta *sta)
{
- struct iwl_mld_sta *mld_sta = iwl_mld_sta_from_mac80211(sta);
struct ieee80211_link_sta *link_sta;
int link_id;
- for_each_sta_active_link(mld_sta->vif, sta, link_sta, link_id) {
+ for_each_sta_active_link(sta, link_sta, link_id) {
int fw_sta_id = iwl_mld_fw_sta_id_from_link_sta(mld, link_sta);
if (fw_sta_id < 0)
@@ -892,8 +890,6 @@ void iwl_mld_wait_sta_txqs_empty(struct iwl_mld *mld, struct ieee80211_sta *sta)
void iwl_mld_remove_sta(struct iwl_mld *mld, struct ieee80211_sta *sta)
{
- struct iwl_mld_sta *mld_sta = iwl_mld_sta_from_mac80211(sta);
- struct ieee80211_vif *vif = mld_sta->vif;
struct ieee80211_link_sta *link_sta;
u8 link_id;
@@ -909,7 +905,7 @@ void iwl_mld_remove_sta(struct iwl_mld *mld, struct ieee80211_sta *sta)
for (int i = 0; i < ARRAY_SIZE(sta->txq); i++)
iwl_mld_remove_txq(mld, sta->txq[i]);
- for_each_sta_active_link(vif, sta, link_sta, link_id) {
+ for_each_sta_active_link(sta, link_sta, link_id) {
/* Mac8011 will remove the groupwise keys after the sta is
* removed, but FW expects all the keys to be removed before
* the STA is, so remove them all here.
@@ -926,7 +922,6 @@ void iwl_mld_remove_sta(struct iwl_mld *mld, struct ieee80211_sta *sta)
u32 iwl_mld_fw_sta_id_mask(struct iwl_mld *mld, struct ieee80211_sta *sta)
{
- struct ieee80211_vif *vif = iwl_mld_sta_from_mac80211(sta)->vif;
struct ieee80211_link_sta *link_sta;
unsigned int link_id;
u32 result = 0;
@@ -940,7 +935,7 @@ u32 iwl_mld_fw_sta_id_mask(struct iwl_mld *mld, struct ieee80211_sta *sta)
*/
lockdep_assert_wiphy(mld->wiphy);
- for_each_sta_active_link(vif, sta, link_sta, link_id) {
+ for_each_sta_active_link(sta, link_sta, link_id) {
int fw_id = iwl_mld_fw_sta_id_from_link_sta(mld, link_sta);
if (!(fw_id < 0))
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/tx.c b/drivers/net/wireless/intel/iwlwifi/mld/tx.c
index 44aa317b8e7d..882e36aa1ec6 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/tx.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/tx.c
@@ -182,7 +182,7 @@ iwl_mld_get_queue_size(struct iwl_mld *mld, struct ieee80211_txq *txq)
lockdep_assert_wiphy(mld->wiphy);
- for_each_sta_active_link(txq->vif, sta, link_sta, link_id) {
+ for_each_sta_active_link(sta, link_sta, link_id) {
if (link_sta->eht_cap.has_eht) {
max_size = IWL_DEFAULT_QUEUE_SIZE_EHT;
break;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
index 937232882ea2..0f7f03b03037 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
@@ -3692,7 +3692,7 @@ static bool iwl_mvm_vif_conf_from_sta(struct iwl_mvm *mvm,
* wpa_s will blocklist the AP...
*/
- for_each_sta_active_link(vif, sta, link_sta, link_id) {
+ for_each_sta_active_link(sta, link_sta, link_id) {
struct ieee80211_bss_conf *link_conf =
link_conf_dereference_protected(vif, link_id);
@@ -3721,7 +3721,7 @@ static void iwl_mvm_vif_set_he_support(struct ieee80211_hw *hw,
struct ieee80211_link_sta *link_sta;
unsigned int link_id;
- for_each_sta_active_link(vif, sta, link_sta, link_id) {
+ for_each_sta_active_link(sta, link_sta, link_id) {
struct ieee80211_bss_conf *link_conf =
link_conf_dereference_protected(vif, link_id);
@@ -3775,7 +3775,7 @@ iwl_mvm_sta_state_notexist_to_none(struct iwl_mvm *mvm,
if (ret)
return ret;
- for_each_sta_active_link(vif, sta, link_sta, i)
+ for_each_sta_active_link(sta, link_sta, i)
link_sta->agg.max_rc_amsdu_len = 1;
ieee80211_sta_recalc_aggregates(sta);
@@ -3833,7 +3833,7 @@ iwl_mvm_sta_state_auth_to_assoc(struct ieee80211_hw *hw,
if (!mvm->mld_api_is_used)
goto out;
- for_each_sta_active_link(vif, sta, link_sta, link_id) {
+ for_each_sta_active_link(sta, link_sta, link_id) {
struct ieee80211_bss_conf *link_conf =
link_conf_dereference_protected(vif, link_id);
@@ -4004,7 +4004,7 @@ int iwl_mvm_mac_sta_state_common(struct ieee80211_hw *hw,
* legit to have phy_ctxt = NULL. Don't bother not to WARN if we are in
* recovery flow since we spit tons of error messages anyway.
*/
- for_each_sta_active_link(vif, sta, link_sta, link_id) {
+ for_each_sta_active_link(sta, link_sta, link_id) {
if (WARN_ON_ONCE(!mvmvif->link[link_id] ||
!mvmvif->link[link_id]->phy_ctxt)) {
mutex_unlock(&mvm->mutex);
@@ -5752,7 +5752,7 @@ void iwl_mvm_mac_flush_sta(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
int link_id;
guard(mvm)(mvm);
- for_each_sta_active_link(vif, sta, link_sta, link_id) {
+ for_each_sta_active_link(sta, link_sta, link_id) {
mvm_link_sta = rcu_dereference_protected(mvmsta->link[link_id],
lockdep_is_held(&mvm->mutex));
if (!mvm_link_sta)
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c
index da7ed4639a93..483656d39bcc 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2022-2025 Intel Corporation
+ * Copyright (C) 2022-2026 Intel Corporation
*/
#include "mvm.h"
#include "time-sync.h"
@@ -573,7 +573,7 @@ static int iwl_mvm_mld_alloc_sta_links(struct iwl_mvm *mvm,
lockdep_assert_held(&mvm->mutex);
- for_each_sta_active_link(vif, sta, link_sta, link_id) {
+ for_each_sta_active_link(sta, link_sta, link_id) {
if (WARN_ON(mvm_sta->link[link_id]))
continue;
@@ -620,7 +620,7 @@ static int iwl_mvm_alloc_sta_after_restart(struct iwl_mvm *mvm,
* a valid station. Since we need a link_id to allocate a station,
* pick up the first valid one.
*/
- for_each_sta_active_link(vif, sta, link_sta, link_id) {
+ for_each_sta_active_link(sta, link_sta, link_id) {
struct iwl_mvm_vif_link_info *mvm_link;
struct ieee80211_bss_conf *link_conf =
link_conf_dereference_protected(vif, link_id);
@@ -685,7 +685,7 @@ int iwl_mvm_mld_add_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
if (ret)
goto err;
- for_each_sta_active_link(vif, sta, link_sta, link_id) {
+ for_each_sta_active_link(sta, link_sta, link_id) {
struct ieee80211_bss_conf *link_conf =
link_conf_dereference_protected(vif, link_id);
struct iwl_mvm_link_sta *mvm_link_sta =
@@ -736,7 +736,7 @@ int iwl_mvm_mld_update_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
lockdep_assert_held(&mvm->mutex);
- for_each_sta_active_link(vif, sta, link_sta, link_id) {
+ for_each_sta_active_link(sta, link_sta, link_id) {
struct ieee80211_bss_conf *link_conf =
link_conf_dereference_protected(vif, link_id);
struct iwl_mvm_link_sta *mvm_link_sta =
@@ -796,7 +796,7 @@ int iwl_mvm_mld_rm_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
lockdep_assert_held(&mvm->mutex);
/* flush its queues here since we are freeing mvm_sta */
- for_each_sta_active_link(vif, sta, link_sta, link_id) {
+ for_each_sta_active_link(sta, link_sta, link_id) {
struct iwl_mvm_link_sta *mvm_link_sta =
rcu_dereference_protected(mvm_sta->link[link_id],
lockdep_is_held(&mvm->mutex));
@@ -816,7 +816,7 @@ int iwl_mvm_mld_rm_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
iwl_mvm_mld_disable_sta_queues(mvm, vif, sta);
- for_each_sta_active_link(vif, sta, link_sta, link_id) {
+ for_each_sta_active_link(sta, link_sta, link_id) {
struct iwl_mvm_link_sta *mvm_link_sta =
rcu_dereference_protected(mvm_sta->link[link_id],
lockdep_is_held(&mvm->mutex));
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
index a66128a62546..45f5816abcb7 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
@@ -863,7 +863,7 @@ int iwl_mvm_tvqm_enable_txq(struct iwl_mvm *mvm,
unsigned int link_id;
rcu_read_lock();
- for_each_sta_active_link(mvmsta->vif, sta, link_sta, link_id) {
+ for_each_sta_active_link(sta, link_sta, link_id) {
struct iwl_mvm_link_sta *link =
rcu_dereference_protected(mvmsta->link[link_id],
lockdep_is_held(&mvm->mutex));
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c
index 26cdb3f0a98a..5c227e853d04 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c
@@ -767,7 +767,7 @@ int mt7925_mcu_uni_tx_ba(struct mt792x_dev *dev,
struct ieee80211_link_sta *link_sta;
unsigned int link_id;
- for_each_sta_active_link(vif, sta, link_sta, link_id) {
+ for_each_sta_active_link(sta, link_sta, link_id) {
struct mt792x_link_sta *mlink;
struct mt792x_bss_conf *mconf;
int ret;
@@ -801,7 +801,7 @@ int mt7925_mcu_uni_rx_ba(struct mt792x_dev *dev,
struct ieee80211_link_sta *link_sta;
unsigned int link_id;
- for_each_sta_active_link(vif, sta, link_sta, link_id) {
+ for_each_sta_active_link(sta, link_sta, link_id) {
struct mt792x_link_sta *mlink;
struct mt792x_bss_conf *mconf;
int ret;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7996/debugfs.c
index 644abd0a0216..44a653deedc0 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/debugfs.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/debugfs.c
@@ -776,14 +776,11 @@ mt7996_sta_hw_queue_read(void *data, struct ieee80211_sta *sta)
struct mt7996_vif *mvif = msta->vif;
struct ieee80211_link_sta *link_sta;
struct seq_file *s = data;
- struct ieee80211_vif *vif;
unsigned int link_id;
- vif = container_of((void *)mvif, struct ieee80211_vif, drv_priv);
-
rcu_read_lock();
- for_each_sta_active_link(vif, sta, link_sta, link_id) {
+ for_each_sta_active_link(sta, link_sta, link_id) {
struct mt7996_sta_link *msta_link;
struct mt76_vif_link *mlink;
struct mt7996_phy *phy;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
index 873c5aef4935..6ec862c01446 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
@@ -1338,7 +1338,7 @@ u16 mt7996_mac_sta_links(struct mt7996_dev *dev, struct ieee80211_vif *vif,
unsigned int link_id;
u16 links = 0;
- for_each_sta_active_link(vif, sta, link_sta, link_id) {
+ for_each_sta_active_link(sta, link_sta, link_id) {
struct mt7996_sta_link *msta_link;
msta_link = mt7996_sta_link_protected(dev, msta, link_id);
@@ -2522,7 +2522,7 @@ static void mt7996_sta_set_4addr(struct ieee80211_hw *hw,
mutex_lock(&dev->mt76.mutex);
assign_bit(MT_WCID_FLAG_4ADDR, &msta->wcid_flags, enabled);
- for_each_sta_active_link(vif, sta, link_sta, link_id) {
+ for_each_sta_active_link(sta, link_sta, link_id) {
struct mt7996_sta_link *msta_link;
struct mt7996_vif_link *link;
@@ -2558,7 +2558,7 @@ static void mt7996_sta_set_decap_offload(struct ieee80211_hw *hw,
mutex_lock(&dev->mt76.mutex);
assign_bit(MT_WCID_FLAG_HDR_TRANS, &msta->wcid_flags, enabled);
- for_each_sta_active_link(vif, sta, link_sta, link_id) {
+ for_each_sta_active_link(sta, link_sta, link_id) {
struct mt7996_sta_link *msta_link;
struct mt7996_vif_link *link;
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 335eee075952..f156af2210f3 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -2796,10 +2796,10 @@ static inline bool lockdep_sta_mutex_held(struct ieee80211_sta *pubsta)
rcu_dereference_check((sta)->link[link_id], \
lockdep_sta_mutex_held(sta))
-#define for_each_sta_active_link(vif, sta, link_sta, link_id) \
+#define for_each_sta_active_link(sta, link_sta, link_id) \
for (link_id = 0; link_id < ARRAY_SIZE((sta)->link); link_id++) \
- if ((!(vif)->active_links || \
- (vif)->active_links & BIT(link_id)) && \
+ if ((!(sta)->active_links || \
+ (sta)->active_links & BIT(link_id)) && \
((link_sta) = link_sta_dereference_check(sta, link_id)))
/**
--
2.56.0
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH wireless-next 7/7] wifi: mac80211: use sta->active_links in for_each_sta_active_link()
2026-11-02 21:42 ` [PATCH wireless-next 7/7] wifi: mac80211: use sta->active_links in for_each_sta_active_link() Johannes Berg
@ 2026-11-03 19:08 ` kernel test robot
2026-11-03 21:40 ` kernel test robot
2026-11-04 16:18 ` kernel test robot
2 siblings, 0 replies; 12+ messages in thread
From: kernel test robot @ 2026-11-03 19:08 UTC (permalink / raw)
To: Johannes Berg, linux-wireless
Cc: llvm, oe-kbuild-all, Johannes Berg, Miriam Rachel Korenblit
Hi Johannes,
kernel test robot noticed the following build errors:
[auto build test ERROR on wireless-next/main]
url: https://github.com/intel-lab-lkp/linux/commits/Johannes-Berg/wifi-mac80211-clarify-station-link-handling/20261102-224238
base: https://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next.git main
patch link: https://lore.kernel.org/r/20261102224349.e1d1ed2eef37.I0f5c26e0f6a05feaf5c578fa048ca5586530f0ba%40changeid
patch subject: [PATCH wireless-next 7/7] wifi: mac80211: use sta->active_links in for_each_sta_active_link()
config: loongarch-allmodconfig (https://download.01.org/0day-ci/archive/20261104/202611040250.cGDVGGwA-lkp@intel.com/config)
compiler: clang version 19.1.7 (https://github.com/llvm/llvm-project cd708029e0b2869e80abe31ddb175f7c35361f90)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20261104/202611040250.cGDVGGwA-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202611040250.cGDVGGwA-lkp@intel.com/
All errors (new ones prefixed by >>):
>> drivers/net/wireless/intel/iwlwifi/mld/sta.c:913:7: error: use of undeclared identifier 'vif'; did you mean 'if'?
913 | if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls)
| ^~~
| if
>> drivers/net/wireless/intel/iwlwifi/mld/sta.c:913:7: error: expected expression
drivers/net/wireless/intel/iwlwifi/mld/sta.c:914:32: error: use of undeclared identifier 'vif'; did you mean 'if'?
914 | iwl_mld_remove_ap_keys(mld, vif, sta, link_id);
| ^~~
| if
drivers/net/wireless/intel/iwlwifi/mld/sta.c:914:32: error: expected expression
4 errors generated.
vim +913 drivers/net/wireless/intel/iwlwifi/mld/sta.c
d1e879ec600f9b Miri Korenblit 2025-02-16 890
d1e879ec600f9b Miri Korenblit 2025-02-16 891 void iwl_mld_remove_sta(struct iwl_mld *mld, struct ieee80211_sta *sta)
d1e879ec600f9b Miri Korenblit 2025-02-16 892 {
d1e879ec600f9b Miri Korenblit 2025-02-16 893 struct ieee80211_link_sta *link_sta;
d1e879ec600f9b Miri Korenblit 2025-02-16 894 u8 link_id;
d1e879ec600f9b Miri Korenblit 2025-02-16 895
d1e879ec600f9b Miri Korenblit 2025-02-16 896 lockdep_assert_wiphy(mld->wiphy);
d1e879ec600f9b Miri Korenblit 2025-02-16 897
d1e879ec600f9b Miri Korenblit 2025-02-16 898 /* Tell the HW to flush the queues */
d1e879ec600f9b Miri Korenblit 2025-02-16 899 iwl_mld_flush_sta_txqs(mld, sta);
d1e879ec600f9b Miri Korenblit 2025-02-16 900
d1e879ec600f9b Miri Korenblit 2025-02-16 901 /* Wait for trans to empty its queues */
d1e879ec600f9b Miri Korenblit 2025-02-16 902 iwl_mld_wait_sta_txqs_empty(mld, sta);
d1e879ec600f9b Miri Korenblit 2025-02-16 903
d1e879ec600f9b Miri Korenblit 2025-02-16 904 /* Now we can remove the queues */
d1e879ec600f9b Miri Korenblit 2025-02-16 905 for (int i = 0; i < ARRAY_SIZE(sta->txq); i++)
d1e879ec600f9b Miri Korenblit 2025-02-16 906 iwl_mld_remove_txq(mld, sta->txq[i]);
d1e879ec600f9b Miri Korenblit 2025-02-16 907
83b0c8b2692d39 Johannes Berg 2026-11-02 908 for_each_sta_active_link(sta, link_sta, link_id) {
d1e879ec600f9b Miri Korenblit 2025-02-16 909 /* Mac8011 will remove the groupwise keys after the sta is
d1e879ec600f9b Miri Korenblit 2025-02-16 910 * removed, but FW expects all the keys to be removed before
d1e879ec600f9b Miri Korenblit 2025-02-16 911 * the STA is, so remove them all here.
d1e879ec600f9b Miri Korenblit 2025-02-16 912 */
67128af05c6419 Johannes Berg 2025-03-09 @913 if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls)
d1e879ec600f9b Miri Korenblit 2025-02-16 914 iwl_mld_remove_ap_keys(mld, vif, sta, link_id);
d1e879ec600f9b Miri Korenblit 2025-02-16 915
d1e879ec600f9b Miri Korenblit 2025-02-16 916 /* Remove the link_sta */
d1e879ec600f9b Miri Korenblit 2025-02-16 917 iwl_mld_remove_link_sta(mld, link_sta);
d1e879ec600f9b Miri Korenblit 2025-02-16 918 }
d1e879ec600f9b Miri Korenblit 2025-02-16 919
d1e879ec600f9b Miri Korenblit 2025-02-16 920 iwl_mld_destroy_sta(sta);
d1e879ec600f9b Miri Korenblit 2025-02-16 921 }
d1e879ec600f9b Miri Korenblit 2025-02-16 922
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH wireless-next 7/7] wifi: mac80211: use sta->active_links in for_each_sta_active_link()
2026-11-02 21:42 ` [PATCH wireless-next 7/7] wifi: mac80211: use sta->active_links in for_each_sta_active_link() Johannes Berg
2026-11-03 19:08 ` kernel test robot
@ 2026-11-03 21:40 ` kernel test robot
2026-11-04 16:18 ` kernel test robot
2 siblings, 0 replies; 12+ messages in thread
From: kernel test robot @ 2026-11-03 21:40 UTC (permalink / raw)
To: Johannes Berg, linux-wireless
Cc: oe-kbuild-all, Johannes Berg, Miriam Rachel Korenblit
Hi Johannes,
kernel test robot noticed the following build errors:
[auto build test ERROR on wireless-next/main]
url: https://github.com/intel-lab-lkp/linux/commits/Johannes-Berg/wifi-mac80211-clarify-station-link-handling/20261102-224238
base: https://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next.git main
patch link: https://lore.kernel.org/r/20261102224349.e1d1ed2eef37.I0f5c26e0f6a05feaf5c578fa048ca5586530f0ba%40changeid
patch subject: [PATCH wireless-next 7/7] wifi: mac80211: use sta->active_links in for_each_sta_active_link()
config: arc-allyesconfig (https://download.01.org/0day-ci/archive/20261104/202611040513.kvvNKVDo-lkp@intel.com/config)
compiler: arc-linux-gcc (GCC) 16.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20261104/202611040513.kvvNKVDo-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202611040513.kvvNKVDo-lkp@intel.com/
All errors (new ones prefixed by >>):
drivers/net/wireless/intel/iwlwifi/mld/sta.c: In function 'iwl_mld_remove_sta':
>> drivers/net/wireless/intel/iwlwifi/mld/sta.c:913:21: error: 'vif' undeclared (first use in this function)
913 | if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls)
| ^~~
drivers/net/wireless/intel/iwlwifi/mld/sta.c:913:21: note: each undeclared identifier is reported only once for each function it appears in
vim +/vif +913 drivers/net/wireless/intel/iwlwifi/mld/sta.c
d1e879ec600f9b Miri Korenblit 2025-02-16 890
d1e879ec600f9b Miri Korenblit 2025-02-16 891 void iwl_mld_remove_sta(struct iwl_mld *mld, struct ieee80211_sta *sta)
d1e879ec600f9b Miri Korenblit 2025-02-16 892 {
d1e879ec600f9b Miri Korenblit 2025-02-16 893 struct ieee80211_link_sta *link_sta;
d1e879ec600f9b Miri Korenblit 2025-02-16 894 u8 link_id;
d1e879ec600f9b Miri Korenblit 2025-02-16 895
d1e879ec600f9b Miri Korenblit 2025-02-16 896 lockdep_assert_wiphy(mld->wiphy);
d1e879ec600f9b Miri Korenblit 2025-02-16 897
d1e879ec600f9b Miri Korenblit 2025-02-16 898 /* Tell the HW to flush the queues */
d1e879ec600f9b Miri Korenblit 2025-02-16 899 iwl_mld_flush_sta_txqs(mld, sta);
d1e879ec600f9b Miri Korenblit 2025-02-16 900
d1e879ec600f9b Miri Korenblit 2025-02-16 901 /* Wait for trans to empty its queues */
d1e879ec600f9b Miri Korenblit 2025-02-16 902 iwl_mld_wait_sta_txqs_empty(mld, sta);
d1e879ec600f9b Miri Korenblit 2025-02-16 903
d1e879ec600f9b Miri Korenblit 2025-02-16 904 /* Now we can remove the queues */
d1e879ec600f9b Miri Korenblit 2025-02-16 905 for (int i = 0; i < ARRAY_SIZE(sta->txq); i++)
d1e879ec600f9b Miri Korenblit 2025-02-16 906 iwl_mld_remove_txq(mld, sta->txq[i]);
d1e879ec600f9b Miri Korenblit 2025-02-16 907
83b0c8b2692d39 Johannes Berg 2026-11-02 908 for_each_sta_active_link(sta, link_sta, link_id) {
d1e879ec600f9b Miri Korenblit 2025-02-16 909 /* Mac8011 will remove the groupwise keys after the sta is
d1e879ec600f9b Miri Korenblit 2025-02-16 910 * removed, but FW expects all the keys to be removed before
d1e879ec600f9b Miri Korenblit 2025-02-16 911 * the STA is, so remove them all here.
d1e879ec600f9b Miri Korenblit 2025-02-16 912 */
67128af05c6419 Johannes Berg 2025-03-09 @913 if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls)
d1e879ec600f9b Miri Korenblit 2025-02-16 914 iwl_mld_remove_ap_keys(mld, vif, sta, link_id);
d1e879ec600f9b Miri Korenblit 2025-02-16 915
d1e879ec600f9b Miri Korenblit 2025-02-16 916 /* Remove the link_sta */
d1e879ec600f9b Miri Korenblit 2025-02-16 917 iwl_mld_remove_link_sta(mld, link_sta);
d1e879ec600f9b Miri Korenblit 2025-02-16 918 }
d1e879ec600f9b Miri Korenblit 2025-02-16 919
d1e879ec600f9b Miri Korenblit 2025-02-16 920 iwl_mld_destroy_sta(sta);
d1e879ec600f9b Miri Korenblit 2025-02-16 921 }
d1e879ec600f9b Miri Korenblit 2025-02-16 922
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH wireless-next 7/7] wifi: mac80211: use sta->active_links in for_each_sta_active_link()
2026-11-02 21:42 ` [PATCH wireless-next 7/7] wifi: mac80211: use sta->active_links in for_each_sta_active_link() Johannes Berg
2026-11-03 19:08 ` kernel test robot
2026-11-03 21:40 ` kernel test robot
@ 2026-11-04 16:18 ` kernel test robot
2 siblings, 0 replies; 12+ messages in thread
From: kernel test robot @ 2026-11-04 16:18 UTC (permalink / raw)
To: Johannes Berg, linux-wireless
Cc: oe-kbuild-all, Johannes Berg, Miriam Rachel Korenblit
Hi Johannes,
kernel test robot noticed the following build errors:
[auto build test ERROR on wireless-next/main]
url: https://github.com/intel-lab-lkp/linux/commits/Johannes-Berg/wifi-mac80211-rename-ieee80211_sta_activate_link/20261102-224237
base: https://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next.git main
patch link: https://lore.kernel.org/r/20261102224349.e1d1ed2eef37.I0f5c26e0f6a05feaf5c578fa048ca5586530f0ba%40changeid
patch subject: [PATCH wireless-next 7/7] wifi: mac80211: use sta->active_links in for_each_sta_active_link()
config: openrisc-allmodconfig (https://download.01.org/0day-ci/archive/20261104/202611042348.ZiFAbrdl-lkp@intel.com/config)
compiler: or1k-linux-gcc (GCC) 16.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20261104/202611042348.ZiFAbrdl-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202611042348.ZiFAbrdl-lkp@intel.com/
All errors (new ones prefixed by >>):
drivers/net/wireless/intel/iwlwifi/mld/sta.c: In function 'iwl_mld_remove_sta':
>> drivers/net/wireless/intel/iwlwifi/mld/sta.c:913:21: error: 'vif' undeclared (first use in this function)
913 | if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls)
| ^~~
drivers/net/wireless/intel/iwlwifi/mld/sta.c:913:21: note: each undeclared identifier is reported only once for each function it appears in
vim +/vif +913 drivers/net/wireless/intel/iwlwifi/mld/sta.c
d1e879ec600f9b Miri Korenblit 2025-02-16 890
d1e879ec600f9b Miri Korenblit 2025-02-16 891 void iwl_mld_remove_sta(struct iwl_mld *mld, struct ieee80211_sta *sta)
d1e879ec600f9b Miri Korenblit 2025-02-16 892 {
d1e879ec600f9b Miri Korenblit 2025-02-16 893 struct ieee80211_link_sta *link_sta;
d1e879ec600f9b Miri Korenblit 2025-02-16 894 u8 link_id;
d1e879ec600f9b Miri Korenblit 2025-02-16 895
d1e879ec600f9b Miri Korenblit 2025-02-16 896 lockdep_assert_wiphy(mld->wiphy);
d1e879ec600f9b Miri Korenblit 2025-02-16 897
d1e879ec600f9b Miri Korenblit 2025-02-16 898 /* Tell the HW to flush the queues */
d1e879ec600f9b Miri Korenblit 2025-02-16 899 iwl_mld_flush_sta_txqs(mld, sta);
d1e879ec600f9b Miri Korenblit 2025-02-16 900
d1e879ec600f9b Miri Korenblit 2025-02-16 901 /* Wait for trans to empty its queues */
d1e879ec600f9b Miri Korenblit 2025-02-16 902 iwl_mld_wait_sta_txqs_empty(mld, sta);
d1e879ec600f9b Miri Korenblit 2025-02-16 903
d1e879ec600f9b Miri Korenblit 2025-02-16 904 /* Now we can remove the queues */
d1e879ec600f9b Miri Korenblit 2025-02-16 905 for (int i = 0; i < ARRAY_SIZE(sta->txq); i++)
d1e879ec600f9b Miri Korenblit 2025-02-16 906 iwl_mld_remove_txq(mld, sta->txq[i]);
d1e879ec600f9b Miri Korenblit 2025-02-16 907
4fa80ba223dd72 Johannes Berg 2026-11-02 908 for_each_sta_active_link(sta, link_sta, link_id) {
d1e879ec600f9b Miri Korenblit 2025-02-16 909 /* Mac8011 will remove the groupwise keys after the sta is
d1e879ec600f9b Miri Korenblit 2025-02-16 910 * removed, but FW expects all the keys to be removed before
d1e879ec600f9b Miri Korenblit 2025-02-16 911 * the STA is, so remove them all here.
d1e879ec600f9b Miri Korenblit 2025-02-16 912 */
67128af05c6419 Johannes Berg 2025-03-09 @913 if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls)
d1e879ec600f9b Miri Korenblit 2025-02-16 914 iwl_mld_remove_ap_keys(mld, vif, sta, link_id);
d1e879ec600f9b Miri Korenblit 2025-02-16 915
d1e879ec600f9b Miri Korenblit 2025-02-16 916 /* Remove the link_sta */
d1e879ec600f9b Miri Korenblit 2025-02-16 917 iwl_mld_remove_link_sta(mld, link_sta);
d1e879ec600f9b Miri Korenblit 2025-02-16 918 }
d1e879ec600f9b Miri Korenblit 2025-02-16 919
d1e879ec600f9b Miri Korenblit 2025-02-16 920 iwl_mld_destroy_sta(sta);
d1e879ec600f9b Miri Korenblit 2025-02-16 921 }
d1e879ec600f9b Miri Korenblit 2025-02-16 922
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH wireless-next 6/7] wifi: mac80211: track sta->active_links
2026-11-02 21:42 ` [PATCH wireless-next 6/7] wifi: mac80211: track sta->active_links Johannes Berg
@ 2026-11-04 18:52 ` Johannes Berg
0 siblings, 0 replies; 12+ messages in thread
From: Johannes Berg @ 2026-11-04 18:52 UTC (permalink / raw)
To: linux-wireless; +Cc: Miriam Rachel Korenblit
On Mon, 2026-11-02 at 22:42 +0100, Johannes Berg wrote:
> From: Johannes Berg <johannes.berg@intel.com>
>
> We've always assumed that a station has active_links
> that are simply sta->valid_links & vif->active_links,
> and while this should be true most of the time, during
> SMD transition the target AP MLD will have a different
> (set of) active link(s) than the vif, and needs to be
> added so the state can be transferred over.
>
> Add and track sta->active_links, and use it in a few
> places. Upon allocation, a sta initially has no active
> links, it's up to the caller to fix that; document it.
> During link switch, the active links change with the
> interface ones, do that in the drv_change_sta_links()
> wrapper.
This has a bug in HW restart and needs a fix like this:
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -2123,6 +2123,11 @@ int ieee80211_reconfig(struct ieee80211_local *local)
active_links = sdata->vif.active_links;
link_id = ffs(active_links) - 1;
sdata->vif.active_links = BIT(link_id);
+
+ list_for_each_entry(sta, &local->sta_list, list) {
+ if (sta->sdata == sdata)
+ sta->sta.active_links = BIT(link_id);
+ }
}
drv_change_vif_links(local, sdata, 0,
johannes
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2026-11-04 18:52 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-02 21:42 [PATCH wireless-next 0/7] wifi: mac80211: station link handling for ST Johannes Berg
2026-11-02 21:42 ` [PATCH wireless-next 1/7] wifi: mac80211: rename ieee80211_sta_activate_link() Johannes Berg
2026-11-02 21:42 ` [PATCH wireless-next 2/7] wifi: mac80211: clarify station link handling Johannes Berg
2026-11-02 21:42 ` [PATCH wireless-next 3/7] wifi: mac80211: clarify change_vif_links() documentation Johannes Berg
2026-11-02 21:42 ` [PATCH wireless-next 4/7] wifi: mac80211: add link_sta::link_conf pointer Johannes Berg
2026-11-02 21:42 ` [PATCH wireless-next 5/7] wifi: mac80211: add sta_info_alloc_with_links() Johannes Berg
2026-11-02 21:42 ` [PATCH wireless-next 6/7] wifi: mac80211: track sta->active_links Johannes Berg
2026-11-04 18:52 ` Johannes Berg
2026-11-02 21:42 ` [PATCH wireless-next 7/7] wifi: mac80211: use sta->active_links in for_each_sta_active_link() Johannes Berg
2026-11-03 19:08 ` kernel test robot
2026-11-03 21:40 ` kernel test robot
2026-11-04 16:18 ` kernel test robot
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox