2023-06-08 14:10:14

by Greenman, Gregory

[permalink] [raw]
Subject: [PATCH 00/15] cfg80211/mac80211 patches from our internal tree 2023-06-08

From: Gregory Greenman <[email protected]>

Hi

A bunch of patches from our internal tree with mac80211 and
cfg80211 changes. It's the usual developement, cleanups and
bugfixes.

Thanks,
Gregory

Anjaneyulu (1):
wifi: mac80211: pass roc->sdata to drv_cancel_remain_on_channel()

Benjamin Berg (3):
wifi: cfg80211: fix link del callback to call correct handler
wifi: mac80211: take lock before setting vif links
wifi: mac80211: fix CSA processing while scanning

Ilan Peer (5):
wifi: mac80211: Use active_links instead of valid_links in Tx
wifi: mac80211: Add getter functions for vif MLD state
wifi: mac80211_hwsim: Don't access vif valid links directly
wifi: cfg80211: Support association to AP MLD with disabled links
wifi: mac80211: Support disabled links during association

Johannes Berg (5):
wifi: mac80211: include key action/command in tracing
wifi: mac80211: fix link activation settings order
wifi: mac80211: mlme: clarify WMM messages
wifi: cfg80211: remove links only on AP
wifi: mac80211: don't update rx_stats.last_rate for NDP

Miri Korenblit (1):
wifi: mac80211: disable SMPS override via debugfs

drivers/net/wireless/virtual/mac80211_hwsim.c | 5 +-
include/net/cfg80211.h | 5 +-
include/net/mac80211.h | 28 ++++-
include/uapi/linux/nl80211.h | 7 +-
net/mac80211/cfg.c | 15 ++-
net/mac80211/debug.h | 8 +-
net/mac80211/debugfs_netdev.c | 5 +-
net/mac80211/ieee80211_i.h | 6 +-
net/mac80211/iface.c | 4 +-
net/mac80211/link.c | 46 ++++----
net/mac80211/mlme.c | 103 ++++++++++--------
net/mac80211/offchannel.c | 4 +-
net/mac80211/rx.c | 8 +-
net/mac80211/trace.h | 8 +-
net/mac80211/tx.c | 28 ++---
net/mac80211/util.c | 14 +--
net/wireless/nl80211.c | 13 ++-
net/wireless/rdev-ops.h | 6 +-
net/wireless/util.c | 9 +-
19 files changed, 204 insertions(+), 118 deletions(-)

--
2.38.1



2023-06-08 14:10:14

by Greenman, Gregory

[permalink] [raw]
Subject: [PATCH 01/15] wifi: mac80211: include key action/command in tracing

From: Johannes Berg <[email protected]>

We trace the key information and all, but not whether the key
is added or removed - add that information.

Signed-off-by: Johannes Berg <[email protected]>
Signed-off-by: Gregory Greenman <[email protected]>
---
net/mac80211/trace.h | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h
index db0d0132c58c..e5edf6fe576f 100644
--- a/net/mac80211/trace.h
+++ b/net/mac80211/trace.h
@@ -2,7 +2,7 @@
/*
* Portions of this file
* Copyright(c) 2016-2017 Intel Deutschland GmbH
- * Copyright (C) 2018 - 2022 Intel Corporation
+ * Copyright (C) 2018 - 2023 Intel Corporation
*/

#if !defined(__MAC80211_DRIVER_TRACE) || defined(TRACE_HEADER_MULTI_READ)
@@ -634,6 +634,7 @@ TRACE_EVENT(drv_set_key,
LOCAL_ENTRY
VIF_ENTRY
STA_ENTRY
+ __field(u32, cmd)
KEY_ENTRY
),

@@ -641,12 +642,13 @@ TRACE_EVENT(drv_set_key,
LOCAL_ASSIGN;
VIF_ASSIGN;
STA_ASSIGN;
+ __entry->cmd = cmd;
KEY_ASSIGN(key);
),

TP_printk(
- LOCAL_PR_FMT VIF_PR_FMT STA_PR_FMT KEY_PR_FMT,
- LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG, KEY_PR_ARG
+ LOCAL_PR_FMT VIF_PR_FMT STA_PR_FMT " cmd: %d" KEY_PR_FMT,
+ LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG, __entry->cmd, KEY_PR_ARG
)
);

--
2.38.1


2023-06-08 14:10:16

by Greenman, Gregory

[permalink] [raw]
Subject: [PATCH 03/15] wifi: mac80211: fix link activation settings order

From: Johannes Berg <[email protected]>

In the normal MLME code we always call
ieee80211_mgd_set_link_qos_params() before
ieee80211_link_info_change_notify() and some drivers,
notably iwlwifi, rely on that as they don't do anything
(but store the data) in their conf_tx.

Fix the order here to be the same as in the normal code
paths, so this isn't broken.

Fixes: 3d9011029227 ("wifi: mac80211: implement link switching")
Signed-off-by: Johannes Berg <[email protected]>
Signed-off-by: Gregory Greenman <[email protected]>
---
net/mac80211/link.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/net/mac80211/link.c b/net/mac80211/link.c
index e82db88a47f8..40f030b8ece9 100644
--- a/net/mac80211/link.c
+++ b/net/mac80211/link.c
@@ -2,7 +2,7 @@
/*
* MLO link handling
*
- * Copyright (C) 2022 Intel Corporation
+ * Copyright (C) 2022-2023 Intel Corporation
*/
#include <linux/slab.h>
#include <linux/kernel.h>
@@ -409,6 +409,7 @@ static int _ieee80211_set_active_links(struct ieee80211_sub_if_data *sdata,
IEEE80211_CHANCTX_SHARED);
WARN_ON_ONCE(ret);

+ ieee80211_mgd_set_link_qos_params(link);
ieee80211_link_info_change_notify(sdata, link,
BSS_CHANGED_ERP_CTS_PROT |
BSS_CHANGED_ERP_PREAMBLE |
@@ -423,7 +424,6 @@ static int _ieee80211_set_active_links(struct ieee80211_sub_if_data *sdata,
BSS_CHANGED_TWT |
BSS_CHANGED_HE_OBSS_PD |
BSS_CHANGED_HE_BSS_COLOR);
- ieee80211_mgd_set_link_qos_params(link);
}

old_active = sdata->vif.active_links;
--
2.38.1


2023-06-08 14:10:18

by Greenman, Gregory

[permalink] [raw]
Subject: [PATCH 06/15] wifi: mac80211: take lock before setting vif links

From: Benjamin Berg <[email protected]>

ieee80211_vif_set_links requires the sdata->local->mtx lock to be held.
Add the appropriate locking around the calls in both the link add and
remove handlers.

This causes a warning when e.g. ieee80211_link_release_channel is called
via ieee80211_link_stop from ieee80211_vif_update_links.

Fixes: 0d8c4a3c8688 ("wifi: mac80211: implement add/del interface link callbacks")
Signed-off-by: Benjamin Berg <[email protected]>
Signed-off-by: Gregory Greenman <[email protected]>
---
net/mac80211/cfg.c | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 1b78a2ae7a83..4aaead4895b7 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -4862,11 +4862,16 @@ static int ieee80211_add_intf_link(struct wiphy *wiphy,
unsigned int link_id)
{
struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
+ int res;

if (wdev->use_4addr)
return -EOPNOTSUPP;

- return ieee80211_vif_set_links(sdata, wdev->valid_links);
+ mutex_lock(&sdata->local->mtx);
+ res = ieee80211_vif_set_links(sdata, wdev->valid_links);
+ mutex_unlock(&sdata->local->mtx);
+
+ return res;
}

static void ieee80211_del_intf_link(struct wiphy *wiphy,
@@ -4875,7 +4880,9 @@ static void ieee80211_del_intf_link(struct wiphy *wiphy,
{
struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);

+ mutex_lock(&sdata->local->mtx);
ieee80211_vif_set_links(sdata, wdev->valid_links);
+ mutex_unlock(&sdata->local->mtx);
}

static int sta_add_link_station(struct ieee80211_local *local,
--
2.38.1


2023-06-08 14:10:22

by Greenman, Gregory

[permalink] [raw]
Subject: [PATCH 07/15] wifi: mac80211: fix CSA processing while scanning

From: Benjamin Berg <[email protected]>

The channel switch parsing code would simply return if a scan is
in-progress. Supposedly, this was because channel switch announcements
from other APs should be ignored.

For the beacon case, the function is already only called if we are
associated with the sender. For the action frame cases, add the
appropriate check whether the frame is coming from the AP we are
associated with. Finally, drop the scanning check from
ieee80211_sta_process_chanswitch.

Signed-off-by: Benjamin Berg <[email protected]>
Signed-off-by: Gregory Greenman <[email protected]>
---
net/mac80211/mlme.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index f13792994b4f..d1e30ff54c1f 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -1857,9 +1857,6 @@ ieee80211_sta_process_chanswitch(struct ieee80211_link_data *link,
if (!cbss)
return;

- if (local->scanning)
- return;
-
current_band = cbss->channel->band;
bss = (void *)cbss->priv;
res = ieee80211_parse_ch_switch_ie(sdata, elems, current_band,
@@ -5997,6 +5994,10 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
ieee80211_rx_mgmt_assoc_resp(sdata, mgmt, skb->len);
break;
case IEEE80211_STYPE_ACTION:
+ if (!sdata->u.mgd.associated ||
+ !ether_addr_equal(mgmt->bssid, sdata->vif.cfg.ap_addr))
+ break;
+
if (mgmt->u.action.category == WLAN_CATEGORY_SPECTRUM_MGMT) {
struct ieee802_11_elems *elems;

--
2.38.1


2023-06-08 14:10:25

by Greenman, Gregory

[permalink] [raw]
Subject: [PATCH 05/15] wifi: cfg80211: fix link del callback to call correct handler

From: Benjamin Berg <[email protected]>

The wrapper function was incorrectly calling the add handler instead of
the del handler. This had no negative side effect as the default
handlers are essentially identical.

Fixes: f2a0290b2df2 ("wifi: cfg80211: add optional link add/remove callbacks")
Signed-off-by: Benjamin Berg <[email protected]>
Signed-off-by: Gregory Greenman <[email protected]>
---
net/wireless/rdev-ops.h | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h
index 2e497cf26ef2..69b508743e57 100644
--- a/net/wireless/rdev-ops.h
+++ b/net/wireless/rdev-ops.h
@@ -2,7 +2,7 @@
/*
* Portions of this file
* Copyright(c) 2016-2017 Intel Deutschland GmbH
- * Copyright (C) 2018, 2021-2022 Intel Corporation
+ * Copyright (C) 2018, 2021-2023 Intel Corporation
*/
#ifndef __CFG80211_RDEV_OPS
#define __CFG80211_RDEV_OPS
@@ -1441,8 +1441,8 @@ rdev_del_intf_link(struct cfg80211_registered_device *rdev,
unsigned int link_id)
{
trace_rdev_del_intf_link(&rdev->wiphy, wdev, link_id);
- if (rdev->ops->add_intf_link)
- rdev->ops->add_intf_link(&rdev->wiphy, wdev, link_id);
+ if (rdev->ops->del_intf_link)
+ rdev->ops->del_intf_link(&rdev->wiphy, wdev, link_id);
trace_rdev_return_void(&rdev->wiphy);
}

--
2.38.1


2023-06-08 14:10:34

by Greenman, Gregory

[permalink] [raw]
Subject: [PATCH 08/15] wifi: cfg80211: remove links only on AP

From: Johannes Berg <[email protected]>

Since links are only controlled by userspace via cfg80211
in AP mode, also only remove them from the driver in that
case.

Signed-off-by: Johannes Berg <[email protected]>
Signed-off-by: Gregory Greenman <[email protected]>
---
net/wireless/util.c | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/net/wireless/util.c b/net/wireless/util.c
index 3bc0c3072e78..9755ef281040 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -5,7 +5,7 @@
* Copyright 2007-2009 Johannes Berg <[email protected]>
* Copyright 2013-2014 Intel Mobile Communications GmbH
* Copyright 2017 Intel Deutschland GmbH
- * Copyright (C) 2018-2022 Intel Corporation
+ * Copyright (C) 2018-2023 Intel Corporation
*/
#include <linux/export.h>
#include <linux/bitops.h>
@@ -2558,6 +2558,13 @@ void cfg80211_remove_links(struct wireless_dev *wdev)
{
unsigned int link_id;

+ /*
+ * links are controlled by upper layers (userspace/cfg)
+ * only for AP mode, so only remove them here for AP
+ */
+ if (wdev->iftype != NL80211_IFTYPE_AP)
+ return;
+
wdev_lock(wdev);
if (wdev->valid_links) {
for_each_valid_link(wdev, link_id)
--
2.38.1


2023-06-08 14:10:43

by Greenman, Gregory

[permalink] [raw]
Subject: [PATCH 10/15] wifi: mac80211: disable SMPS override via debugfs

From: Miri Korenblit <[email protected]>

There are cases in which we don't want the user to override the
smps mode, e.g. when SMPS should be disabled. Add a driver flag to
disable SMPS overriding and don't override if it is set

Signed-off-by: Miri Korenblit <[email protected]>
Signed-off-by: Gregory Greenman <[email protected]>
---
include/net/mac80211.h | 3 +++
net/mac80211/debugfs_netdev.c | 5 ++++-
2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 8ea23884a583..98cb2c532025 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -1755,12 +1755,15 @@ struct ieee80211_channel_switch {
* @IEEE80211_VIF_GET_NOA_UPDATE: request to handle NOA attributes
* and send P2P_PS notification to the driver if NOA changed, even
* this is not pure P2P vif.
+ * @IEEE80211_VIF_DISABLE_SMPS_OVERRIDE: disable user configuration of
+ * SMPS mode via debugfs.
*/
enum ieee80211_vif_flags {
IEEE80211_VIF_BEACON_FILTER = BIT(0),
IEEE80211_VIF_SUPPORTS_CQM_RSSI = BIT(1),
IEEE80211_VIF_SUPPORTS_UAPSD = BIT(2),
IEEE80211_VIF_GET_NOA_UPDATE = BIT(3),
+ IEEE80211_VIF_DISABLE_SMPS_OVERRIDE = BIT(4),
};


diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c
index b0cef37eb394..3fea86c9a276 100644
--- a/net/mac80211/debugfs_netdev.c
+++ b/net/mac80211/debugfs_netdev.c
@@ -2,7 +2,7 @@
/*
* Copyright (c) 2006 Jiri Benc <[email protected]>
* Copyright 2007 Johannes Berg <[email protected]>
- * Copyright (C) 2020-2022 Intel Corporation
+ * Copyright (C) 2020-2023 Intel Corporation
*/

#include <linux/kernel.h>
@@ -267,6 +267,9 @@ static int ieee80211_set_smps(struct ieee80211_link_data *link,
struct ieee80211_local *local = sdata->local;
int err;

+ if (sdata->vif.driver_flags & IEEE80211_VIF_DISABLE_SMPS_OVERRIDE)
+ return -EOPNOTSUPP;
+
if (!(local->hw.wiphy->features & NL80211_FEATURE_STATIC_SMPS) &&
smps_mode == IEEE80211_SMPS_STATIC)
return -EINVAL;
--
2.38.1


2023-06-08 14:10:52

by Greenman, Gregory

[permalink] [raw]
Subject: [PATCH 09/15] wifi: mac80211: don't update rx_stats.last_rate for NDP

From: Johannes Berg <[email protected]>

If we get an NDP (null data packet), there's reason to
believe the peer is just sending it to probe, and that
would happen at a low rate. Don't track this packet for
purposes of last RX rate reporting.

Signed-off-by: Johannes Berg <[email protected]>
Signed-off-by: Gregory Greenman <[email protected]>
---
net/mac80211/rx.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index ed9939466198..77c7dac760ba 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -6,7 +6,7 @@
* Copyright 2007-2010 Johannes Berg <[email protected]>
* Copyright 2013-2014 Intel Mobile Communications GmbH
* Copyright(c) 2015 - 2017 Intel Deutschland GmbH
- * Copyright (C) 2018-2022 Intel Corporation
+ * Copyright (C) 2018-2023 Intel Corporation
*/

#include <linux/jiffies.h>
@@ -1732,7 +1732,7 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
if (ether_addr_equal(bssid, rx->sdata->u.ibss.bssid) &&
test_sta_flag(sta, WLAN_STA_AUTHORIZED)) {
link_sta->rx_stats.last_rx = jiffies;
- if (ieee80211_is_data(hdr->frame_control) &&
+ if (ieee80211_is_data_present(hdr->frame_control) &&
!is_multicast_ether_addr(hdr->addr1))
link_sta->rx_stats.last_rate =
sta_stats_encode_rate(status);
@@ -1746,7 +1746,7 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
* match the current local configuration when processed.
*/
link_sta->rx_stats.last_rx = jiffies;
- if (ieee80211_is_data(hdr->frame_control))
+ if (ieee80211_is_data_present(hdr->frame_control))
link_sta->rx_stats.last_rate = sta_stats_encode_rate(status);
}

--
2.38.1


2023-06-08 14:10:57

by Greenman, Gregory

[permalink] [raw]
Subject: [PATCH 04/15] wifi: mac80211: mlme: clarify WMM messages

From: Johannes Berg <[email protected]>

These messages apply to a single link only, use link_info()
to indicate that.

Signed-off-by: Johannes Berg <[email protected]>
Signed-off-by: Gregory Greenman <[email protected]>
---
net/mac80211/mlme.c | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 270133883882..f13792994b4f 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -2639,9 +2639,9 @@ ieee80211_sta_wmm_params(struct ieee80211_local *local,
params[ac].aifs = pos[0] & 0x0f;

if (params[ac].aifs < 2) {
- sdata_info(sdata,
- "AP has invalid WMM params (AIFSN=%d for ACI %d), will use 2\n",
- params[ac].aifs, aci);
+ link_info(link,
+ "AP has invalid WMM params (AIFSN=%d for ACI %d), will use 2\n",
+ params[ac].aifs, aci);
params[ac].aifs = 2;
}
params[ac].cw_max = ecw2cw((pos[1] & 0xf0) >> 4);
@@ -2652,9 +2652,9 @@ ieee80211_sta_wmm_params(struct ieee80211_local *local,

if (params[ac].cw_min == 0 ||
params[ac].cw_min > params[ac].cw_max) {
- sdata_info(sdata,
- "AP has invalid WMM params (CWmin/max=%d/%d for ACI %d), using defaults\n",
- params[ac].cw_min, params[ac].cw_max, aci);
+ link_info(link,
+ "AP has invalid WMM params (CWmin/max=%d/%d for ACI %d), using defaults\n",
+ params[ac].cw_min, params[ac].cw_max, aci);
return false;
}
ieee80211_regulatory_limit_wmm_params(sdata, &params[ac], ac);
@@ -2663,9 +2663,9 @@ ieee80211_sta_wmm_params(struct ieee80211_local *local,
/* WMM specification requires all 4 ACIs. */
for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
if (params[ac].cw_min == 0) {
- sdata_info(sdata,
- "AP has invalid WMM params (missing AC %d), using defaults\n",
- ac);
+ link_info(link,
+ "AP has invalid WMM params (missing AC %d), using defaults\n",
+ ac);
return false;
}
}
--
2.38.1


2023-06-08 14:10:57

by Greenman, Gregory

[permalink] [raw]
Subject: [PATCH 11/15] wifi: mac80211: Use active_links instead of valid_links in Tx

From: Ilan Peer <[email protected]>

Fix few places on the Tx path where the valid_links were used instead
of active links.

Signed-off-by: Ilan Peer <[email protected]>
Signed-off-by: Gregory Greenman <[email protected]>
---
net/mac80211/tx.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 148a0e2aa740..7972de64e779 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -4429,7 +4429,7 @@ static void ieee80211_mlo_multicast_tx(struct net_device *dev,
struct sk_buff *skb)
{
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
- unsigned long links = sdata->vif.valid_links;
+ unsigned long links = sdata->vif.active_links;
unsigned int link;
u32 ctrl_flags = IEEE80211_TX_CTRL_MCAST_MLO_FIRST_TX;

@@ -6024,7 +6024,7 @@ void __ieee80211_tx_skb_tid_band(struct ieee80211_sub_if_data *sdata,
rcu_read_unlock();

if (WARN_ON_ONCE(link == ARRAY_SIZE(sdata->vif.link_conf)))
- link = ffs(sdata->vif.valid_links) - 1;
+ link = ffs(sdata->vif.active_links) - 1;
}

IEEE80211_SKB_CB(skb)->control.flags |=
@@ -6060,7 +6060,7 @@ void ieee80211_tx_skb_tid(struct ieee80211_sub_if_data *sdata,
band = chanctx_conf->def.chan->band;
} else {
WARN_ON(link_id >= 0 &&
- !(sdata->vif.valid_links & BIT(link_id)));
+ !(sdata->vif.active_links & BIT(link_id)));
/* MLD transmissions must not rely on the band */
band = 0;
}
--
2.38.1


2023-06-08 14:11:05

by Greenman, Gregory

[permalink] [raw]
Subject: [PATCH 13/15] wifi: mac80211_hwsim: Don't access vif valid links directly

From: Ilan Peer <[email protected]>

And instead use the vif getter functions, as a preparation for
supporting disabled/dormant links.

Signed-off-by: Ilan Peer <[email protected]>
Signed-off-by: Gregory Greenman <[email protected]>
---
drivers/net/wireless/virtual/mac80211_hwsim.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/virtual/mac80211_hwsim.c b/drivers/net/wireless/virtual/mac80211_hwsim.c
index 37bf392ae9a2..f446fd0e8cd0 100644
--- a/drivers/net/wireless/virtual/mac80211_hwsim.c
+++ b/drivers/net/wireless/virtual/mac80211_hwsim.c
@@ -1860,7 +1860,7 @@ mac80211_hwsim_select_tx_link(struct mac80211_hwsim_data *data,
struct hwsim_sta_priv *sp = (void *)sta->drv_priv;
int i;

- if (!vif->valid_links)
+ if (!ieee80211_vif_is_mld(vif))
return &vif->bss_conf;

WARN_ON(is_multicast_ether_addr(hdr->addr1));
@@ -2636,7 +2636,8 @@ static int mac80211_hwsim_sta_state(struct ieee80211_hw *hw,
*/
if (vif->type == NL80211_IFTYPE_STATION &&
new_state == IEEE80211_STA_AUTHORIZED && !sta->tdls)
- ieee80211_set_active_links_async(vif, vif->valid_links);
+ ieee80211_set_active_links_async(vif,
+ ieee80211_vif_usable_links(vif));

return 0;
}
--
2.38.1


2023-06-08 14:11:06

by Greenman, Gregory

[permalink] [raw]
Subject: [PATCH 02/15] wifi: mac80211: pass roc->sdata to drv_cancel_remain_on_channel()

From: Anjaneyulu <[email protected]>

In suspend flow "sdata" is NULL, destroy all roc's which are started.
pass "roc->sdata" to drv_cancel_remain_on_channel() to avoid NULL
dereference and destroy that roc

Signed-off-by: Anjaneyulu <[email protected]>
Signed-off-by: Gregory Greenman <[email protected]>
---
net/mac80211/offchannel.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c
index d78c82d6b696..cdf991e74ab9 100644
--- a/net/mac80211/offchannel.c
+++ b/net/mac80211/offchannel.c
@@ -8,7 +8,7 @@
* Copyright 2006-2007 Jiri Benc <[email protected]>
* Copyright 2007, Michael Wu <[email protected]>
* Copyright 2009 Johannes Berg <[email protected]>
- * Copyright (C) 2019, 2022 Intel Corporation
+ * Copyright (C) 2019, 2022-2023 Intel Corporation
*/
#include <linux/export.h>
#include <net/mac80211.h>
@@ -1014,7 +1014,7 @@ void ieee80211_roc_purge(struct ieee80211_local *local,
if (roc->started) {
if (local->ops->remain_on_channel) {
/* can race, so ignore return value */
- drv_cancel_remain_on_channel(local, sdata);
+ drv_cancel_remain_on_channel(local, roc->sdata);
ieee80211_roc_notify_destroy(roc);
} else {
roc->abort = true;
--
2.38.1


2023-06-08 14:11:14

by Greenman, Gregory

[permalink] [raw]
Subject: [PATCH 14/15] wifi: cfg80211: Support association to AP MLD with disabled links

From: Ilan Peer <[email protected]>

An AP part of an AP MLD might be temporarily disabled, and might be
enabled later. Such a link should be included in the association
exchange, but should not be used until enabled.

Extend the NL80211_CMD_ASSOCIATE to also indicate disabled links.

Signed-off-by: Ilan Peer <[email protected]>
Signed-off-by: Gregory Greenman <[email protected]>
---
include/net/cfg80211.h | 5 ++++-
include/uapi/linux/nl80211.h | 7 ++++++-
net/wireless/nl80211.c | 13 ++++++++++++-
3 files changed, 22 insertions(+), 3 deletions(-)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 1b8619685bf6..6d5b104212b3 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -7,7 +7,7 @@
* Copyright 2006-2010 Johannes Berg <[email protected]>
* Copyright 2013-2014 Intel Mobile Communications GmbH
* Copyright 2015-2017 Intel Deutschland GmbH
- * Copyright (C) 2018-2021 Intel Corporation
+ * Copyright (C) 2018-2021, 2023 Intel Corporation
*/

#include <linux/ethtool.h>
@@ -2870,11 +2870,14 @@ struct cfg80211_auth_request {
* if this is %NULL for a link, that link is not requested
* @elems: extra elements for the per-STA profile for this link
* @elems_len: length of the elements
+ * @disabled: If set this link should be included during association etc. but it
+ * should not be used until enabled by the AP MLD.
*/
struct cfg80211_assoc_link {
struct cfg80211_bss *bss;
const u8 *elems;
size_t elems_len;
+ bool disabled;
};

/**
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index c59fec406da5..c3b674cee312 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -11,7 +11,7 @@
* Copyright 2008 Jouni Malinen <[email protected]>
* Copyright 2008 Colin McCabe <[email protected]>
* Copyright 2015-2017 Intel Deutschland GmbH
- * Copyright (C) 2018-2022 Intel Corporation
+ * Copyright (C) 2018-2023 Intel Corporation
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -2805,6 +2805,9 @@ enum nl80211_commands {
* index. If the userspace includes more RNR elements than number of
* MBSSID elements then these will be added in every EMA beacon.
*
+ * @NL80211_ATTR_MLO_LINK_DISABLED: Flag attribute indicating that the link is
+ * disabled.
+ *
* @NUM_NL80211_ATTR: total number of nl80211_attrs available
* @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use
@@ -3341,6 +3344,8 @@ enum nl80211_attrs {

NL80211_ATTR_EMA_RNR_ELEMS,

+ NL80211_ATTR_MLO_LINK_DISABLED,
+
/* add attributes here, update the policy in nl80211.c */

__NL80211_ATTR_AFTER_LAST,
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 772671b9bc42..2941187a7a3d 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -5,7 +5,7 @@
* Copyright 2006-2010 Johannes Berg <[email protected]>
* Copyright 2013-2014 Intel Mobile Communications GmbH
* Copyright 2015-2017 Intel Deutschland GmbH
- * Copyright (C) 2018-2022 Intel Corporation
+ * Copyright (C) 2018-2023 Intel Corporation
*/

#include <linux/if.h>
@@ -816,6 +816,7 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
[NL80211_ATTR_MAX_HW_TIMESTAMP_PEERS] = { .type = NLA_U16 },
[NL80211_ATTR_HW_TIMESTAMP_ENABLED] = { .type = NLA_FLAG },
[NL80211_ATTR_EMA_RNR_ELEMS] = { .type = NLA_NESTED },
+ [NL80211_ATTR_MLO_LINK_DISABLED] = { .type = NLA_FLAG },
};

/* policy for the key attributes */
@@ -11115,6 +11116,9 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
goto free;
}
}
+
+ req.links[link_id].disabled =
+ nla_get_flag(attrs[NL80211_ATTR_MLO_LINK_DISABLED]);
}

if (!req.links[req.link_id].bss) {
@@ -11129,6 +11133,13 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
goto free;
}

+ if (req.links[req.link_id].disabled) {
+ GENL_SET_ERR_MSG(info,
+ "cannot have assoc link disabled");
+ err = -EINVAL;
+ goto free;
+ }
+
kfree(attrs);
attrs = NULL;
} else {
--
2.38.1


2023-06-08 14:11:15

by Greenman, Gregory

[permalink] [raw]
Subject: [PATCH 15/15] wifi: mac80211: Support disabled links during association

From: Ilan Peer <[email protected]>

When the association is complete, do not configure disabled
links, and track them as part of the interface data.

Signed-off-by: Ilan Peer <[email protected]>
Signed-off-by: Gregory Greenman <[email protected]>
---
include/net/mac80211.h | 6 ++++--
net/mac80211/cfg.c | 4 ++--
net/mac80211/ieee80211_i.h | 4 +++-
net/mac80211/link.c | 38 +++++++++++++++++++++++---------------
net/mac80211/mlme.c | 35 ++++++++++++++++++++++-------------
5 files changed, 54 insertions(+), 33 deletions(-)

diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 5424301df3c8..b5704ef4308f 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -1846,6 +1846,8 @@ struct ieee80211_vif_cfg {
* @active_links: The bitmap of active links, or 0 for non-MLO.
* The driver shouldn't change this directly, but use the
* API calls meant for that purpose.
+ * @dormant_links: bitmap of valid but disabled links, or 0 for non-MLO.
+ * Must be a subset of valid_links.
* @addr: address of this interface
* @p2p: indicates whether this AP or STA interface is a p2p
* interface, i.e. a GO or p2p-sta respectively
@@ -1883,7 +1885,7 @@ struct ieee80211_vif {
struct ieee80211_vif_cfg cfg;
struct ieee80211_bss_conf bss_conf;
struct ieee80211_bss_conf __rcu *link_conf[IEEE80211_MLD_MAX_NUM_LINKS];
- u16 valid_links, active_links;
+ u16 valid_links, active_links, dormant_links;
u8 addr[ETH_ALEN] __aligned(2);
bool p2p;

@@ -1916,7 +1918,7 @@ struct ieee80211_vif {
*/
static inline u16 ieee80211_vif_usable_links(const struct ieee80211_vif *vif)
{
- return vif->valid_links;
+ return vif->valid_links & ~vif->dormant_links;
}

/**
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index ca6d53d5751d..359589d525d5 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -4868,7 +4868,7 @@ static int ieee80211_add_intf_link(struct wiphy *wiphy,
return -EOPNOTSUPP;

mutex_lock(&sdata->local->mtx);
- res = ieee80211_vif_set_links(sdata, wdev->valid_links);
+ res = ieee80211_vif_set_links(sdata, wdev->valid_links, 0);
mutex_unlock(&sdata->local->mtx);

return res;
@@ -4881,7 +4881,7 @@ static void ieee80211_del_intf_link(struct wiphy *wiphy,
struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);

mutex_lock(&sdata->local->mtx);
- ieee80211_vif_set_links(sdata, wdev->valid_links);
+ ieee80211_vif_set_links(sdata, wdev->valid_links, 0);
mutex_unlock(&sdata->local->mtx);
}

diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index f55cec0e6b2d..561a2980f92f 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -410,6 +410,8 @@ struct ieee80211_mgd_assoc_data {
ieee80211_conn_flags_t conn_flags;

u16 status;
+
+ bool disabled;
} link[IEEE80211_MLD_MAX_NUM_LINKS];

u8 ap_addr[ETH_ALEN] __aligned(2);
@@ -2019,7 +2021,7 @@ void ieee80211_link_init(struct ieee80211_sub_if_data *sdata,
struct ieee80211_bss_conf *link_conf);
void ieee80211_link_stop(struct ieee80211_link_data *link);
int ieee80211_vif_set_links(struct ieee80211_sub_if_data *sdata,
- u16 new_links);
+ u16 new_links, u16 dormant_links);
void ieee80211_vif_clear_links(struct ieee80211_sub_if_data *sdata);

/* tx handling */
diff --git a/net/mac80211/link.c b/net/mac80211/link.c
index 55cba3760ef5..d090ecc41ea2 100644
--- a/net/mac80211/link.c
+++ b/net/mac80211/link.c
@@ -142,25 +142,34 @@ static int ieee80211_check_dup_link_addrs(struct ieee80211_sub_if_data *sdata)
}

static void ieee80211_set_vif_links_bitmaps(struct ieee80211_sub_if_data *sdata,
- u16 links)
+ u16 valid_links, u16 dormant_links)
{
- sdata->vif.valid_links = links;
-
- if (!links) {
+ sdata->vif.valid_links = valid_links;
+ sdata->vif.dormant_links = dormant_links;
+
+ if (!valid_links ||
+ WARN((~valid_links & dormant_links) ||
+ !(valid_links & ~dormant_links),
+ "Invalid links: valid=0x%x, dormant=0x%x",
+ valid_links, dormant_links)) {
sdata->vif.active_links = 0;
+ sdata->vif.dormant_links = 0;
return;
}

switch (sdata->vif.type) {
case NL80211_IFTYPE_AP:
/* in an AP all links are always active */
- sdata->vif.active_links = links;
+ sdata->vif.active_links = valid_links;
+
+ /* AP links are not expected to be disabled */
+ WARN_ON(dormant_links);
break;
case NL80211_IFTYPE_STATION:
if (sdata->vif.active_links)
break;
- WARN_ON(hweight16(links) > 1);
- sdata->vif.active_links = links;
+ sdata->vif.active_links = valid_links & ~dormant_links;
+ WARN_ON(hweight16(sdata->vif.active_links) > 1);
break;
default:
WARN_ON(1);
@@ -169,7 +178,7 @@ static void ieee80211_set_vif_links_bitmaps(struct ieee80211_sub_if_data *sdata,

static int ieee80211_vif_update_links(struct ieee80211_sub_if_data *sdata,
struct link_container **to_free,
- u16 new_links)
+ u16 new_links, u16 dormant_links)
{
u16 old_links = sdata->vif.valid_links;
u16 old_active = sdata->vif.active_links;
@@ -245,7 +254,7 @@ static int ieee80211_vif_update_links(struct ieee80211_sub_if_data *sdata,
/* for keys we will not be able to undo this */
ieee80211_tear_down_links(sdata, to_free, rem);

- ieee80211_set_vif_links_bitmaps(sdata, new_links);
+ ieee80211_set_vif_links_bitmaps(sdata, new_links, dormant_links);

/* tell the driver */
ret = drv_change_vif_links(sdata->local, sdata,
@@ -258,7 +267,7 @@ static int ieee80211_vif_update_links(struct ieee80211_sub_if_data *sdata,
/* restore config */
memcpy(sdata->link, old_data, sizeof(old_data));
memcpy(sdata->vif.link_conf, old, sizeof(old));
- ieee80211_set_vif_links_bitmaps(sdata, old_links);
+ ieee80211_set_vif_links_bitmaps(sdata, old_links, dormant_links);
/* and free (only) the newly allocated links */
memset(to_free, 0, sizeof(links));
goto free;
@@ -282,12 +291,13 @@ static int ieee80211_vif_update_links(struct ieee80211_sub_if_data *sdata,
}

int ieee80211_vif_set_links(struct ieee80211_sub_if_data *sdata,
- u16 new_links)
+ u16 new_links, u16 dormant_links)
{
struct link_container *links[IEEE80211_MLD_MAX_NUM_LINKS];
int ret;

- ret = ieee80211_vif_update_links(sdata, links, new_links);
+ ret = ieee80211_vif_update_links(sdata, links, new_links,
+ dormant_links);
ieee80211_free_links(sdata, links);

return ret;
@@ -304,7 +314,7 @@ void ieee80211_vif_clear_links(struct ieee80211_sub_if_data *sdata)
*/

sdata_lock(sdata);
- ieee80211_vif_update_links(sdata, links, 0);
+ ieee80211_vif_update_links(sdata, links, 0, 0);
sdata_unlock(sdata);

ieee80211_free_links(sdata, links);
@@ -328,7 +338,6 @@ static int _ieee80211_set_active_links(struct ieee80211_sub_if_data *sdata,
if (sdata->vif.type != NL80211_IFTYPE_STATION)
return -EINVAL;

- /* cannot activate links that don't exist */
if (active_links & ~ieee80211_vif_usable_links(&sdata->vif))
return -EINVAL;

@@ -484,7 +493,6 @@ void ieee80211_set_active_links_async(struct ieee80211_vif *vif,
if (sdata->vif.type != NL80211_IFTYPE_STATION)
return;

- /* cannot activate links that don't exist */
if (active_links & ~ieee80211_vif_usable_links(&sdata->vif))
return;

diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index fdd80f73e6cb..6970d5e7ac8f 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -2817,6 +2817,10 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
assoc_data->link[link_id].status != WLAN_STATUS_SUCCESS)
continue;

+ if (ieee80211_vif_is_mld(&sdata->vif) &&
+ !(ieee80211_vif_usable_links(&sdata->vif) & BIT(link_id)))
+ continue;
+
link = sdata_dereference(sdata->link[link_id], sdata);
if (WARN_ON(!link))
return;
@@ -2843,6 +2847,8 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
struct cfg80211_bss *cbss = assoc_data->link[link_id].bss;

if (!cbss ||
+ !(BIT(link_id) &
+ ieee80211_vif_usable_links(&sdata->vif)) ||
assoc_data->link[link_id].status != WLAN_STATUS_SUCCESS)
continue;

@@ -3057,7 +3063,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
memset(sdata->vif.bss_conf.tx_pwr_env, 0,
sizeof(sdata->vif.bss_conf.tx_pwr_env));

- ieee80211_vif_set_links(sdata, 0);
+ ieee80211_vif_set_links(sdata, 0, 0);
}

static void ieee80211_reset_ap_probe(struct ieee80211_sub_if_data *sdata)
@@ -3510,7 +3516,7 @@ static void ieee80211_destroy_auth_data(struct ieee80211_sub_if_data *sdata,

mutex_lock(&sdata->local->mtx);
ieee80211_link_release_channel(&sdata->deflink);
- ieee80211_vif_set_links(sdata, 0);
+ ieee80211_vif_set_links(sdata, 0, 0);
mutex_unlock(&sdata->local->mtx);
}

@@ -3569,7 +3575,7 @@ static void ieee80211_destroy_assoc_data(struct ieee80211_sub_if_data *sdata,

mutex_lock(&sdata->local->mtx);
ieee80211_link_release_channel(&sdata->deflink);
- ieee80211_vif_set_links(sdata, 0);
+ ieee80211_vif_set_links(sdata, 0, 0);
mutex_unlock(&sdata->local->mtx);
}

@@ -4978,7 +4984,7 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
unsigned int link_id;
struct sta_info *sta;
u64 changed[IEEE80211_MLD_MAX_NUM_LINKS] = {};
- u16 valid_links = 0;
+ u16 valid_links = 0, dormant_links = 0;
int err;

mutex_lock(&sdata->local->sta_mtx);
@@ -4994,16 +5000,18 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++) {
if (!assoc_data->link[link_id].bss)
continue;
- valid_links |= BIT(link_id);

- if (link_id != assoc_data->assoc_link_id) {
+ valid_links |= BIT(link_id);
+ if (assoc_data->link[link_id].disabled) {
+ dormant_links |= BIT(link_id);
+ } else if (link_id != assoc_data->assoc_link_id) {
err = ieee80211_sta_allocate_link(sta, link_id);
if (err)
goto out_err;
}
}

- ieee80211_vif_set_links(sdata, valid_links);
+ ieee80211_vif_set_links(sdata, valid_links, dormant_links);
}

for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++) {
@@ -5011,7 +5019,7 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
struct ieee80211_link_data *link;
struct link_sta_info *link_sta;

- if (!cbss)
+ if (!cbss || assoc_data->link[link_id].disabled)
continue;

link = sdata_dereference(sdata->link[link_id], sdata);
@@ -5083,7 +5091,7 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
}

/* links might have changed due to rejected ones, set them again */
- ieee80211_vif_set_links(sdata, valid_links);
+ ieee80211_vif_set_links(sdata, valid_links, dormant_links);

rate_control_rate_init(sta);

@@ -6626,12 +6634,12 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata,
mlo = true;
if (WARN_ON(!ap_mld_addr))
return -EINVAL;
- err = ieee80211_vif_set_links(sdata, BIT(link_id));
+ err = ieee80211_vif_set_links(sdata, BIT(link_id), 0);
} else {
if (WARN_ON(ap_mld_addr))
return -EINVAL;
ap_mld_addr = cbss->bssid;
- err = ieee80211_vif_set_links(sdata, 0);
+ err = ieee80211_vif_set_links(sdata, 0, 0);
link_id = 0;
mlo = false;
}
@@ -6783,7 +6791,7 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata,

out_err:
ieee80211_link_release_channel(&sdata->deflink);
- ieee80211_vif_set_links(sdata, 0);
+ ieee80211_vif_set_links(sdata, 0, 0);
return err;
}

@@ -7323,10 +7331,11 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
for (i = 0; i < ARRAY_SIZE(assoc_data->link); i++) {
assoc_data->link[i].conn_flags = conn_flags;
assoc_data->link[i].bss = req->links[i].bss;
+ assoc_data->link[i].disabled = req->links[i].disabled;
}

/* if there was no authentication, set up the link */
- err = ieee80211_vif_set_links(sdata, BIT(assoc_link_id));
+ err = ieee80211_vif_set_links(sdata, BIT(assoc_link_id), 0);
if (err)
goto err_clear;
} else {
--
2.38.1


2023-06-08 14:11:18

by Greenman, Gregory

[permalink] [raw]
Subject: [PATCH 12/15] wifi: mac80211: Add getter functions for vif MLD state

From: Ilan Peer <[email protected]>

As a preparation to support disabled/dormant links, add the
following function:

- ieee80211_vif_usable_links(): returns the bitmap of the links
that can be activated. Use this function in all the places that
the bitmap of the usable links is needed.

- ieee80211_vif_is_mld(): returns true iff the vif is an MLD.
Use this function in all the places where an indication that the
connection is a MLD is needed.

Signed-off-by: Ilan Peer <[email protected]>
Signed-off-by: Gregory Greenman <[email protected]>
---
include/net/mac80211.h | 21 +++++++++++++++++++
net/mac80211/cfg.c | 4 ++--
net/mac80211/debug.h | 8 +++----
net/mac80211/ieee80211_i.h | 2 +-
net/mac80211/iface.c | 4 ++--
net/mac80211/link.c | 4 ++--
net/mac80211/mlme.c | 43 +++++++++++++++++++-------------------
net/mac80211/rx.c | 2 +-
net/mac80211/tx.c | 22 +++++++++----------
net/mac80211/util.c | 14 ++++++-------
10 files changed, 73 insertions(+), 51 deletions(-)

diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 98cb2c532025..5424301df3c8 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -1909,6 +1909,27 @@ struct ieee80211_vif {
u8 drv_priv[] __aligned(sizeof(void *));
};

+/**
+ * ieee80211_vif_usable_links - Return the usable links for the vif
+ * @vif: the vif for which the usable links are requested
+ * Return: the usable link bitmap
+ */
+static inline u16 ieee80211_vif_usable_links(const struct ieee80211_vif *vif)
+{
+ return vif->valid_links;
+}
+
+/**
+ * ieee80211_vif_is_mld - Returns true iff the vif is an MLD one
+ * @vif: the vif
+ * Return: %true if the vif is an MLD, %false otherwise.
+ */
+static inline bool ieee80211_vif_is_mld(const struct ieee80211_vif *vif)
+{
+ /* valid_links != 0 indicates this vif is an MLD */
+ return vif->valid_links != 0;
+}
+
#define for_each_vif_active_link(vif, link, link_id) \
for (link_id = 0; link_id < ARRAY_SIZE((vif)->link_conf); link_id++) \
if ((!(vif)->active_links || \
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 4aaead4895b7..ca6d53d5751d 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -35,7 +35,7 @@ ieee80211_link_or_deflink(struct ieee80211_sub_if_data *sdata, int link_id,
* the return value at all (if it's not a pairwise key),
* so in that case (require_valid==false) don't error.
*/
- if (require_valid && sdata->vif.valid_links)
+ if (require_valid && ieee80211_vif_is_mld(&sdata->vif))
return ERR_PTR(-EINVAL);

return &sdata->deflink;
@@ -228,7 +228,7 @@ static int ieee80211_change_iface(struct wiphy *wiphy,
return 0;

/* FIXME: no support for 4-addr MLO yet */
- if (sdata->vif.valid_links)
+ if (ieee80211_vif_is_mld(&sdata->vif))
return -EOPNOTSUPP;

sdata->u.mgd.use_4addr = params->use_4addr;
diff --git a/net/mac80211/debug.h b/net/mac80211/debug.h
index b4c20f5e778e..d49894df2351 100644
--- a/net/mac80211/debug.h
+++ b/net/mac80211/debug.h
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Portions
- * Copyright (C) 2022 Intel Corporation
+ * Copyright (C) 2022 - 2023 Intel Corporation
*/
#ifndef __MAC80211_DEBUG_H
#define __MAC80211_DEBUG_H
@@ -136,7 +136,7 @@ do { \

#define link_info(link, fmt, ...) \
do { \
- if ((link)->sdata->vif.valid_links) \
+ if (ieee80211_vif_is_mld(&(link)->sdata->vif)) \
_sdata_info((link)->sdata, "[link %d] " fmt, \
(link)->link_id, \
##__VA_ARGS__); \
@@ -145,7 +145,7 @@ do { \
} while (0)
#define link_err(link, fmt, ...) \
do { \
- if ((link)->sdata->vif.valid_links) \
+ if (ieee80211_vif_is_mld(&(link)->sdata->vif)) \
_sdata_err((link)->sdata, "[link %d] " fmt, \
(link)->link_id, \
##__VA_ARGS__); \
@@ -154,7 +154,7 @@ do { \
} while (0)
#define link_dbg(link, fmt, ...) \
do { \
- if ((link)->sdata->vif.valid_links) \
+ if (ieee80211_vif_is_mld(&(link)->sdata->vif)) \
_sdata_dbg(1, (link)->sdata, "[link %d] " fmt, \
(link)->link_id, \
##__VA_ARGS__); \
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index f918e73469a7..f55cec0e6b2d 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1614,7 +1614,7 @@ ieee80211_get_sband(struct ieee80211_sub_if_data *sdata)
struct ieee80211_chanctx_conf *chanctx_conf;
enum nl80211_band band;

- WARN_ON(sdata->vif.valid_links);
+ WARN_ON(ieee80211_vif_is_mld(&sdata->vif));

rcu_read_lock();
chanctx_conf = rcu_dereference(sdata->vif.bss_conf.chanctx_conf);
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 5b67b44e3f89..9518acf9643b 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -521,7 +521,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, bool going_do
cancel_work_sync(&sdata->recalc_smps);

sdata_lock(sdata);
- WARN(sdata->vif.valid_links,
+ WARN(ieee80211_vif_is_mld(&sdata->vif),
"destroying interface with valid links 0x%04x\n",
sdata->vif.valid_links);

@@ -1815,7 +1815,7 @@ static int ieee80211_runtime_change_iftype(struct ieee80211_sub_if_data *sdata,
return -EBUSY;

/* for now, don't support changing while links exist */
- if (sdata->vif.valid_links)
+ if (ieee80211_vif_is_mld(&sdata->vif))
return -EBUSY;

switch (sdata->vif.type) {
diff --git a/net/mac80211/link.c b/net/mac80211/link.c
index 40f030b8ece9..55cba3760ef5 100644
--- a/net/mac80211/link.c
+++ b/net/mac80211/link.c
@@ -329,7 +329,7 @@ static int _ieee80211_set_active_links(struct ieee80211_sub_if_data *sdata,
return -EINVAL;

/* cannot activate links that don't exist */
- if (active_links & ~sdata->vif.valid_links)
+ if (active_links & ~ieee80211_vif_usable_links(&sdata->vif))
return -EINVAL;

/* nothing to do */
@@ -485,7 +485,7 @@ void ieee80211_set_active_links_async(struct ieee80211_vif *vif,
return;

/* cannot activate links that don't exist */
- if (active_links & ~sdata->vif.valid_links)
+ if (active_links & ~ieee80211_vif_usable_links(&sdata->vif))
return;

/* nothing to do */
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index d1e30ff54c1f..fdd80f73e6cb 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -1282,7 +1282,7 @@ static void ieee80211_assoc_add_ml_elem(struct ieee80211_sub_if_data *sdata,
u8 *ml_elem_len;
void *capab_pos;

- if (!sdata->vif.valid_links)
+ if (!ieee80211_vif_is_mld(&sdata->vif))
return;

ift_ext_capa = cfg80211_get_iftype_ext_capa(local->hw.wiphy,
@@ -1456,7 +1456,7 @@ static int ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
capab |= WLAN_CAPABILITY_PRIVACY;
}

- if (sdata->vif.valid_links) {
+ if (ieee80211_vif_is_mld(&sdata->vif)) {
/* consider the multi-link element with STA profile */
size += sizeof(struct ieee80211_multi_link_elem);
/* max common info field in basic multi-link element */
@@ -1789,7 +1789,7 @@ void ieee80211_chswitch_done(struct ieee80211_vif *vif, bool success)
struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;

- if (WARN_ON(sdata->vif.valid_links))
+ if (WARN_ON(ieee80211_vif_is_mld(&sdata->vif)))
success = false;

trace_api_chswitch_done(sdata, success);
@@ -2835,7 +2835,7 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
if (vif_cfg->arp_addr_cnt)
vif_changed |= BSS_CHANGED_ARP_FILTER;

- if (sdata->vif.valid_links) {
+ if (ieee80211_vif_is_mld(&sdata->vif)) {
for (link_id = 0;
link_id < IEEE80211_MLD_MAX_NUM_LINKS;
link_id++) {
@@ -2867,7 +2867,7 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
mutex_unlock(&local->iflist_mtx);

/* leave this here to not change ordering in non-MLO cases */
- if (!sdata->vif.valid_links)
+ if (!ieee80211_vif_is_mld(&sdata->vif))
ieee80211_recalc_smps(sdata, &sdata->deflink);
ieee80211_recalc_ps_vif(sdata);

@@ -2963,7 +2963,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
sta_info_flush(sdata);

/* finally reset all BSS / config parameters */
- if (!sdata->vif.valid_links)
+ if (!ieee80211_vif_is_mld(&sdata->vif))
changed |= ieee80211_reset_erp_info(sdata);

ieee80211_led_assoc(local, 0);
@@ -2988,7 +2988,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
sizeof(sdata->vif.bss_conf.mu_group.membership));
memset(sdata->vif.bss_conf.mu_group.position, 0,
sizeof(sdata->vif.bss_conf.mu_group.position));
- if (!sdata->vif.valid_links)
+ if (!ieee80211_vif_is_mld(&sdata->vif))
changed |= BSS_CHANGED_MU_GROUPS;
sdata->vif.bss_conf.mu_mimo_owner = false;

@@ -3002,7 +3002,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
changed |= BSS_CHANGED_ARP_FILTER;

sdata->vif.bss_conf.qos = false;
- if (!sdata->vif.valid_links) {
+ if (!ieee80211_vif_is_mld(&sdata->vif)) {
changed |= BSS_CHANGED_QOS;
/* The BSSID (not really interesting) and HT changed */
changed |= BSS_CHANGED_BSSID | BSS_CHANGED_HT;
@@ -3171,7 +3171,7 @@ static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata)
u8 unicast_limit = max(1, max_probe_tries - 3);
struct sta_info *sta;

- if (WARN_ON(sdata->vif.valid_links))
+ if (WARN_ON(ieee80211_vif_is_mld(&sdata->vif)))
return;

/*
@@ -3219,7 +3219,7 @@ static void ieee80211_mgd_probe_ap(struct ieee80211_sub_if_data *sdata,
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
bool already = false;

- if (WARN_ON_ONCE(sdata->vif.valid_links))
+ if (WARN_ON_ONCE(ieee80211_vif_is_mld(&sdata->vif)))
return;

if (!ieee80211_sdata_running(sdata))
@@ -3294,7 +3294,7 @@ struct sk_buff *ieee80211_ap_probereq_get(struct ieee80211_hw *hw,
int ssid_len;

if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION ||
- sdata->vif.valid_links))
+ ieee80211_vif_is_mld(&sdata->vif)))
return NULL;

sdata_assert_lock(sdata);
@@ -3359,7 +3359,8 @@ static void __ieee80211_disconnect(struct ieee80211_sub_if_data *sdata)
}

/* in MLO assume we have a link where we can TX the frame */
- tx = sdata->vif.valid_links || !sdata->deflink.csa_block_tx;
+ tx = ieee80211_vif_is_mld(&sdata->vif) ||
+ !sdata->deflink.csa_block_tx;

if (!ifmgd->driver_disconnect) {
unsigned int link_id;
@@ -3560,7 +3561,7 @@ static void ieee80211_destroy_assoc_data(struct ieee80211_sub_if_data *sdata,
for (i = 0; i < ARRAY_SIZE(data.bss); i++)
data.bss[i] = assoc_data->link[i].bss;

- if (sdata->vif.valid_links)
+ if (ieee80211_vif_is_mld(&sdata->vif))
data.ap_mld_addr = assoc_data->ap_addr;

cfg80211_assoc_failure(sdata->dev, &data);
@@ -4989,7 +4990,7 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
if (WARN_ON(!sta))
goto out_err;

- if (sdata->vif.valid_links) {
+ if (ieee80211_vif_is_mld(&sdata->vif)) {
for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++) {
if (!assoc_data->link[link_id].bss)
continue;
@@ -5017,7 +5018,7 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
if (WARN_ON(!link))
goto out_err;

- if (sdata->vif.valid_links)
+ if (ieee80211_vif_is_mld(&sdata->vif))
link_info(link,
"local address %pM, AP link address %pM%s\n",
link->conf->addr,
@@ -5266,7 +5267,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
ifmgd->broken_ap = true;
}

- if (sdata->vif.valid_links) {
+ if (ieee80211_vif_is_mld(&sdata->vif)) {
if (!elems->multi_link) {
sdata_info(sdata,
"MLO association with %pM but no multi-link element in response!\n",
@@ -5333,7 +5334,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
resp.uapsd_queues |= ieee80211_ac_to_qos_mask[ac];
}

- if (sdata->vif.valid_links) {
+ if (ieee80211_vif_is_mld(&sdata->vif)) {
ether_addr_copy(ap_mld_addr, sdata->vif.cfg.ap_addr);
resp.ap_mld_addr = ap_mld_addr;
}
@@ -5659,7 +5660,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_link_data *link,
rcu_read_unlock();

if (ifmgd->assoc_data && ifmgd->assoc_data->need_beacon &&
- !WARN_ON(sdata->vif.valid_links) &&
+ !WARN_ON(ieee80211_vif_is_mld(&sdata->vif)) &&
ieee80211_rx_our_beacon(bssid, ifmgd->assoc_data->link[0].bss)) {
parse_params.bss = ifmgd->assoc_data->link[0].bss;
elems = ieee802_11_parse_elems_full(&parse_params);
@@ -6357,7 +6358,7 @@ static void ieee80211_sta_bcn_mon_timer(struct timer_list *t)
struct ieee80211_sub_if_data *sdata =
from_timer(sdata, t, u.mgd.bcn_mon_timer);

- if (WARN_ON(sdata->vif.valid_links))
+ if (WARN_ON(ieee80211_vif_is_mld(&sdata->vif)))
return;

if (sdata->vif.bss_conf.csa_active &&
@@ -6381,7 +6382,7 @@ static void ieee80211_sta_conn_mon_timer(struct timer_list *t)
struct sta_info *sta;
unsigned long timeout;

- if (WARN_ON(sdata->vif.valid_links))
+ if (WARN_ON(ieee80211_vif_is_mld(&sdata->vif)))
return;

if (sdata->vif.bss_conf.csa_active &&
@@ -6937,7 +6938,7 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
return 0;

err_clear:
- if (!sdata->vif.valid_links) {
+ if (!ieee80211_vif_is_mld(&sdata->vif)) {
eth_zero_addr(sdata->deflink.u.mgd.bssid);
ieee80211_link_info_change_notify(sdata, &sdata->deflink,
BSS_CHANGED_BSSID);
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 77c7dac760ba..6ebec32b4ebc 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -2505,7 +2505,7 @@ bool ieee80211_is_our_addr(struct ieee80211_sub_if_data *sdata,
if (ether_addr_equal(sdata->vif.addr, addr))
return true;

- if (!sdata->vif.valid_links)
+ if (!ieee80211_vif_is_mld(&sdata->vif))
return false;

for (link_id = 0; link_id < ARRAY_SIZE(sdata->vif.link_conf); link_id++) {
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 7972de64e779..d8460a14b6bd 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -844,7 +844,7 @@ ieee80211_tx_h_sequence(struct ieee80211_tx_data *tx)

/* SNS11 from 802.11be 10.3.2.14 */
if (unlikely(is_multicast_ether_addr(hdr->addr1) &&
- info->control.vif->valid_links &&
+ ieee80211_vif_is_mld(info->control.vif) &&
info->control.vif->type == NL80211_IFTYPE_AP)) {
if (info->control.flags & IEEE80211_TX_CTRL_MCAST_MLO_FIRST_TX)
tx->sdata->mld_mcast_seq += 0x10;
@@ -2610,7 +2610,7 @@ static struct sk_buff *ieee80211_build_hdr(struct ieee80211_sub_if_data *sdata,
ethertype = (skb->data[12] << 8) | skb->data[13];
fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA);

- if (!sdata->vif.valid_links)
+ if (!ieee80211_vif_is_mld(&sdata->vif))
chanctx_conf =
rcu_dereference(sdata->vif.bss_conf.chanctx_conf);

@@ -2627,7 +2627,7 @@ static struct sk_buff *ieee80211_build_hdr(struct ieee80211_sub_if_data *sdata,
authorized = test_sta_flag(sta, WLAN_STA_AUTHORIZED);
wme_sta = sta->sta.wme;
}
- if (!sdata->vif.valid_links) {
+ if (!ieee80211_vif_is_mld(&sdata->vif)) {
struct ieee80211_sub_if_data *ap_sdata;

/* override chanctx_conf from AP (we don't have one) */
@@ -2645,7 +2645,7 @@ static struct sk_buff *ieee80211_build_hdr(struct ieee80211_sub_if_data *sdata,
/* DA BSSID SA */
memcpy(hdr.addr1, skb->data, ETH_ALEN);

- if (sdata->vif.valid_links && sta && !sta->sta.mlo) {
+ if (ieee80211_vif_is_mld(&sdata->vif) && sta && !sta->sta.mlo) {
struct ieee80211_link_data *link;

link_id = sta->deflink.link_id;
@@ -2797,7 +2797,7 @@ static struct sk_buff *ieee80211_build_hdr(struct ieee80211_sub_if_data *sdata,
}

if (!chanctx_conf) {
- if (!sdata->vif.valid_links) {
+ if (!ieee80211_vif_is_mld(&sdata->vif)) {
ret = -ENOTCONN;
goto free;
}
@@ -3039,7 +3039,7 @@ void ieee80211_check_fast_xmit(struct sta_info *sta)
!ieee80211_hw_check(&local->hw, SUPPORTS_TX_FRAG))
goto out;

- if (!sdata->vif.valid_links) {
+ if (!ieee80211_vif_is_mld(&sdata->vif)) {
rcu_read_lock();
chanctx_conf =
rcu_dereference(sdata->vif.bss_conf.chanctx_conf);
@@ -3110,7 +3110,7 @@ void ieee80211_check_fast_xmit(struct sta_info *sta)
fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS);
/* DA BSSID SA */
build.da_offs = offsetof(struct ieee80211_hdr, addr1);
- if (sta->sta.mlo || !sdata->vif.valid_links) {
+ if (sta->sta.mlo || !ieee80211_vif_is_mld(&sdata->vif)) {
memcpy(hdr->addr2, sdata->vif.addr, ETH_ALEN);
} else {
unsigned int link_id = sta->deflink.link_id;
@@ -4479,7 +4479,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
__ieee80211_subif_start_xmit(skb, dev, 0,
IEEE80211_TX_CTRL_MLO_LINK_UNSPEC,
NULL);
- } else if (sdata->vif.valid_links &&
+ } else if (ieee80211_vif_is_mld(&sdata->vif) &&
sdata->vif.type == NL80211_IFTYPE_AP &&
!ieee80211_hw_check(&sdata->local->hw, MLO_MCAST_MULTI_LINK_TX)) {
ieee80211_mlo_multicast_tx(dev, skb);
@@ -4755,7 +4755,7 @@ static bool ieee80211_tx_pending_skb(struct ieee80211_local *local,

if (info->control.flags & IEEE80211_TX_INTCFL_NEED_TXPROCESSING) {
/* update band only for non-MLD */
- if (!sdata->vif.valid_links) {
+ if (!ieee80211_vif_is_mld(&sdata->vif)) {
chanctx_conf =
rcu_dereference(sdata->vif.bss_conf.chanctx_conf);
if (unlikely(!chanctx_conf)) {
@@ -6002,7 +6002,7 @@ void __ieee80211_tx_skb_tid_band(struct ieee80211_sub_if_data *sdata,
BUILD_BUG_ON(!FIELD_FIT(IEEE80211_TX_CTRL_MLO_LINK,
IEEE80211_LINK_UNSPECIFIED));

- if (!sdata->vif.valid_links) {
+ if (!ieee80211_vif_is_mld(&sdata->vif)) {
link = 0;
} else if (link_id >= 0) {
link = link_id;
@@ -6048,7 +6048,7 @@ void ieee80211_tx_skb_tid(struct ieee80211_sub_if_data *sdata,
enum nl80211_band band;

rcu_read_lock();
- if (!sdata->vif.valid_links) {
+ if (!ieee80211_vif_is_mld(&sdata->vif)) {
WARN_ON(link_id >= 0);
chanctx_conf =
rcu_dereference(sdata->vif.bss_conf.chanctx_conf);
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index a5be07a4dbe3..3aa363bdb6e0 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -1824,7 +1824,7 @@ void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata,
struct ieee80211_local *local = sdata->local;
struct sk_buff *skb;
struct ieee80211_mgmt *mgmt;
- bool multi_link = sdata->vif.valid_links;
+ bool multi_link = ieee80211_vif_is_mld(&sdata->vif);
struct {
u8 id;
u8 len;
@@ -2671,7 +2671,7 @@ int ieee80211_reconfig(struct ieee80211_local *local)
continue;

sdata_lock(sdata);
- if (sdata->vif.valid_links) {
+ if (ieee80211_vif_is_mld(&sdata->vif)) {
struct ieee80211_bss_conf *old[IEEE80211_MLD_MAX_NUM_LINKS] = {
[0] = &sdata->vif.bss_conf,
};
@@ -2691,7 +2691,7 @@ int ieee80211_reconfig(struct ieee80211_local *local)
for (link_id = 0;
link_id < ARRAY_SIZE(sdata->vif.link_conf);
link_id++) {
- if (sdata->vif.valid_links &&
+ if (ieee80211_vif_is_mld(&sdata->vif) &&
!(sdata->vif.active_links & BIT(link_id)))
continue;

@@ -2723,12 +2723,12 @@ int ieee80211_reconfig(struct ieee80211_local *local)
if (sdata->vif.bss_conf.mu_mimo_owner)
changed |= BSS_CHANGED_MU_GROUPS;

- if (!sdata->vif.valid_links)
+ if (!ieee80211_vif_is_mld(&sdata->vif))
changed |= BSS_CHANGED_IDLE;

switch (sdata->vif.type) {
case NL80211_IFTYPE_STATION:
- if (!sdata->vif.valid_links) {
+ if (!ieee80211_vif_is_mld(&sdata->vif)) {
changed |= BSS_CHANGED_ASSOC |
BSS_CHANGED_ARP_FILTER |
BSS_CHANGED_PS;
@@ -2766,7 +2766,7 @@ int ieee80211_reconfig(struct ieee80211_local *local)
case NL80211_IFTYPE_AP:
changed |= BSS_CHANGED_P2P_PS;

- if (sdata->vif.valid_links)
+ if (ieee80211_vif_is_mld(&sdata->vif))
ieee80211_vif_cfg_change_notify(sdata,
BSS_CHANGED_SSID);
else
@@ -2780,7 +2780,7 @@ int ieee80211_reconfig(struct ieee80211_local *local)
if (sdata->vif.type == NL80211_IFTYPE_AP) {
changed |= BSS_CHANGED_AP_PROBE_RESP;

- if (sdata->vif.valid_links) {
+ if (ieee80211_vif_is_mld(&sdata->vif)) {
ieee80211_reconfig_ap_links(local,
sdata,
changed);
--
2.38.1