2024-04-22 05:34:57

by Aditya Kumar Singh

[permalink] [raw]
Subject: [PATCH v2 0/7] wifi: cfg80211/mac80211: add support for HE BSS color handling with Multi-Link Operation

Currently, deflink (or link_id 0) is always considered while handling HE
BSS color. However, with Multi-Link Operation (MLO), there is a need to
handle link specific data structures based on the actual operational
link_id.

Hence, add support for the same. Non-MLO based operations will continue to
use link_id as 0 or deflink member as applicable.

At the same time, add support for BSS color by mac80211_hwsim.

Aditya Kumar Singh (7):
wifi: cfg80211: send link id in color_change ops
wifi: cfg80211: notify link ID in bss_color_notify
wifi: mac80211: handle set color_change/after_color_change beacon on
per link basis
wifi: mac80211: handle color_change_abort and bss_config_notify on per
link
wifi: mac80211: start and finalize color change on link basis
wifi: mac80211: add support to call color_change and OBSS collision on
a link
wifi: mac80211_hwsim: add support for BSS color
---
v2: * Rebased on ToT
* Fix sparse warning -
warning: context imbalance in 'ieee80211_obss_color_collision_notify'
- different lock contexts for basic block

---
drivers/net/wireless/ath/ath11k/mac.c | 2 +-
drivers/net/wireless/ath/ath11k/wmi.c | 3 +-
.../net/wireless/mediatek/mt76/mt7915/mcu.c | 2 +-
.../net/wireless/mediatek/mt76/mt7996/mcu.c | 2 +-
drivers/net/wireless/virtual/mac80211_hwsim.c | 6 +
include/net/cfg80211.h | 29 ++--
include/net/mac80211.h | 6 +-
net/mac80211/cfg.c | 144 ++++++++++++------
net/mac80211/rx.c | 7 +-
net/wireless/nl80211.c | 10 +-
net/wireless/trace.h | 6 +-
11 files changed, 149 insertions(+), 68 deletions(-)


base-commit: b0d2d8f996c1ce3d4c8a1c8cb7d634536e7c2118
--
2.34.1



2024-04-22 05:34:59

by Aditya Kumar Singh

[permalink] [raw]
Subject: [PATCH v2 4/7] wifi: mac80211: handle color_change_abort and bss_config_notify on per link

With MLO, there is a requirement to handle functions
ieee80211_color_change_abort() and
ieee80211_color_change_bss_config_notify() on a per link basis.

Currently, deflink would only be passed. Proper link data will be passed in
a subsequent change.

Signed-off-by: Aditya Kumar Singh <[email protected]>
---
net/mac80211/cfg.c | 24 +++++++++++++-----------
1 file changed, 13 insertions(+), 11 deletions(-)

diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 3ae7c409ac77..5339a8e884ac 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -3918,13 +3918,13 @@ static int ieee80211_set_csa_beacon(struct ieee80211_link_data *link_data,
return 0;
}

-static void ieee80211_color_change_abort(struct ieee80211_sub_if_data *sdata)
+static void ieee80211_color_change_abort(struct ieee80211_link_data *link)
{
- sdata->vif.bss_conf.color_change_active = false;
+ link->conf->color_change_active = false;

- ieee80211_free_next_beacon(&sdata->deflink);
+ ieee80211_free_next_beacon(link);

- cfg80211_color_change_aborted_notify(sdata->dev, 0);
+ cfg80211_color_change_aborted_notify(link->sdata->dev, link->link_id);
}

static int
@@ -4008,7 +4008,7 @@ __ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,

/* if there is a color change in progress, abort it */
if (link_conf->color_change_active)
- ieee80211_color_change_abort(sdata);
+ ieee80211_color_change_abort(link_data);

err = ieee80211_set_csa_beacon(link_data, params, &changed);
if (err) {
@@ -4737,16 +4737,18 @@ ieee80211_set_color_change_beacon(struct ieee80211_link_data *link,
}

static void
-ieee80211_color_change_bss_config_notify(struct ieee80211_sub_if_data *sdata,
+ieee80211_color_change_bss_config_notify(struct ieee80211_link_data *link,
u8 color, int enable, u64 changed)
{
+ struct ieee80211_sub_if_data *sdata = link->sdata;
+
lockdep_assert_wiphy(sdata->local->hw.wiphy);

- sdata->vif.bss_conf.he_bss_color.color = color;
- sdata->vif.bss_conf.he_bss_color.enabled = enable;
+ link->conf->he_bss_color.color = color;
+ link->conf->he_bss_color.enabled = enable;
changed |= BSS_CHANGED_HE_BSS_COLOR;

- ieee80211_link_info_change_notify(sdata, &sdata->deflink, changed);
+ ieee80211_link_info_change_notify(sdata, link, changed);

if (!sdata->vif.bss_conf.nontransmitted && sdata->vif.mbssid_tx_vif) {
struct ieee80211_sub_if_data *child;
@@ -4779,7 +4781,7 @@ static int ieee80211_color_change_finalize(struct ieee80211_sub_if_data *sdata)
return err;
}

- ieee80211_color_change_bss_config_notify(sdata,
+ ieee80211_color_change_bss_config_notify(&sdata->deflink,
sdata->vif.bss_conf.color_change_color,
1, changed);
cfg80211_color_change_notify(sdata->dev, 0);
@@ -4883,7 +4885,7 @@ ieee80211_color_change(struct wiphy *wiphy, struct net_device *dev,
cfg80211_color_change_started_notify(sdata->dev, params->count, 0);

if (changed)
- ieee80211_color_change_bss_config_notify(sdata, 0, 0, changed);
+ ieee80211_color_change_bss_config_notify(&sdata->deflink, 0, 0, changed);
else
/* if the beacon didn't change, we can finalize immediately */
ieee80211_color_change_finalize(sdata);
--
2.34.1


2024-04-22 05:35:12

by Aditya Kumar Singh

[permalink] [raw]
Subject: [PATCH v2 1/7] wifi: cfg80211: send link id in color_change ops

Currently, during color change, no link id information is passed down.
In order to support color change during Multi Link Operation, it is
required to pass link id as well.

Add changes to pass link id in the color_change cfg80211_ops.

Signed-off-by: Aditya Kumar Singh <[email protected]>
---
include/net/cfg80211.h | 3 +++
net/wireless/nl80211.c | 4 +++-
net/wireless/trace.h | 6 ++++--
3 files changed, 10 insertions(+), 3 deletions(-)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 0112d645a2b4..9716a8090f47 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -1577,6 +1577,8 @@ struct cfg80211_csa_settings {
* @beacon_next: beacon data to be used after the color change
* @count: number of beacons until the color change
* @color: the color used after the change
+ * @link_id: defines the link on which color change is expected during MLO.
+ * 0 in case of non-MLO.
*/
struct cfg80211_color_change_settings {
struct cfg80211_beacon_data beacon_color_change;
@@ -1585,6 +1587,7 @@ struct cfg80211_color_change_settings {
struct cfg80211_beacon_data beacon_next;
u8 count;
u8 color;
+ u8 link_id;
};

/**
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index e5d8ea4211ea..995904f71be3 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -16030,6 +16030,7 @@ static int nl80211_color_change(struct sk_buff *skb, struct genl_info *info)
params.counter_offset_presp = offset;
}

+ params.link_id = nl80211_link_id(info->attrs);
err = rdev_color_change(rdev, dev, &params);

out:
@@ -17432,7 +17433,8 @@ static const struct genl_small_ops nl80211_small_ops[] = {
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_color_change,
.flags = GENL_UNS_ADMIN_PERM,
- .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
+ NL80211_FLAG_MLO_VALID_LINK_ID),
},
{
.cmd = NL80211_CMD_SET_FILS_AAD,
diff --git a/net/wireless/trace.h b/net/wireless/trace.h
index cbbf347c6b2e..db4d9f567ad0 100644
--- a/net/wireless/trace.h
+++ b/net/wireless/trace.h
@@ -2842,6 +2842,7 @@ TRACE_EVENT(rdev_color_change,
__field(u8, count)
__field(u16, bcn_ofs)
__field(u16, pres_ofs)
+ __field(u8, link_id)
),
TP_fast_assign(
WIPHY_ASSIGN;
@@ -2849,11 +2850,12 @@ TRACE_EVENT(rdev_color_change,
__entry->count = params->count;
__entry->bcn_ofs = params->counter_offset_beacon;
__entry->pres_ofs = params->counter_offset_presp;
+ __entry->link_id = params->link_id;
),
TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT
- ", count: %u",
+ ", count: %u, link_id: %d",
WIPHY_PR_ARG, NETDEV_PR_ARG,
- __entry->count)
+ __entry->count, __entry->link_id)
);

TRACE_EVENT(rdev_set_radar_background,
--
2.34.1


2024-04-22 05:37:55

by Aditya Kumar Singh

[permalink] [raw]
Subject: [PATCH v2 2/7] wifi: cfg80211: notify link ID in bss_color_notify

Add changes to send link ID as well in bss color notify during MLO.
Userspace application can make use of this to take necessary actions.

For now, pass 0 as link ID. Appropriate link ID will be passed in a
subsequent change.

Signed-off-by: Aditya Kumar Singh <[email protected]>
---
include/net/cfg80211.h | 26 +++++++++++++++++---------
net/mac80211/cfg.c | 11 ++++++-----
net/wireless/nl80211.c | 6 +++++-
3 files changed, 28 insertions(+), 15 deletions(-)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 9716a8090f47..cbf1664dc569 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -9428,70 +9428,78 @@ void cfg80211_bss_flush(struct wiphy *wiphy);
* @cmd: the actual event we want to notify
* @count: the number of TBTTs until the color change happens
* @color_bitmap: representations of the colors that the local BSS is aware of
+ * @link_id: valid link_id in case of MLO or 0 for non-MLO.
*
* Return: 0 on success. Non-zero on error.
*/
int cfg80211_bss_color_notify(struct net_device *dev,
enum nl80211_commands cmd, u8 count,
- u64 color_bitmap);
+ u64 color_bitmap, u8 link_id);

/**
* cfg80211_obss_color_collision_notify - notify about bss color collision
* @dev: network device
* @color_bitmap: representations of the colors that the local BSS is aware of
+ * @link_id: valid link_id in case of MLO or 0 for non-MLO.
*
* Return: 0 on success. Non-zero on error.
*/
static inline int cfg80211_obss_color_collision_notify(struct net_device *dev,
- u64 color_bitmap)
+ u64 color_bitmap,
+ u8 link_id)
{
return cfg80211_bss_color_notify(dev, NL80211_CMD_OBSS_COLOR_COLLISION,
- 0, color_bitmap);
+ 0, color_bitmap, link_id);
}

/**
* cfg80211_color_change_started_notify - notify color change start
* @dev: the device on which the color is switched
* @count: the number of TBTTs until the color change happens
+ * @link_id: valid link_id in case of MLO or 0 for non-MLO.
*
* Inform the userspace about the color change that has started.
*
* Return: 0 on success. Non-zero on error.
*/
static inline int cfg80211_color_change_started_notify(struct net_device *dev,
- u8 count)
+ u8 count, u8 link_id)
{
return cfg80211_bss_color_notify(dev, NL80211_CMD_COLOR_CHANGE_STARTED,
- count, 0);
+ count, 0, link_id);
}

/**
* cfg80211_color_change_aborted_notify - notify color change abort
* @dev: the device on which the color is switched
+ * @link_id: valid link_id in case of MLO or 0 for non-MLO.
*
* Inform the userspace about the color change that has aborted.
*
* Return: 0 on success. Non-zero on error.
*/
-static inline int cfg80211_color_change_aborted_notify(struct net_device *dev)
+static inline int cfg80211_color_change_aborted_notify(struct net_device *dev,
+ u8 link_id)
{
return cfg80211_bss_color_notify(dev, NL80211_CMD_COLOR_CHANGE_ABORTED,
- 0, 0);
+ 0, 0, link_id);
}

/**
* cfg80211_color_change_notify - notify color change completion
* @dev: the device on which the color was switched
+ * @link_id: valid link_id in case of MLO or 0 for non-MLO.
*
* Inform the userspace about the color change that has completed.
*
* Return: 0 on success. Non-zero on error.
*/
-static inline int cfg80211_color_change_notify(struct net_device *dev)
+static inline int cfg80211_color_change_notify(struct net_device *dev,
+ u8 link_id)
{
return cfg80211_bss_color_notify(dev,
NL80211_CMD_COLOR_CHANGE_COMPLETED,
- 0, 0);
+ 0, 0, link_id);
}

/**
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 44971a62d798..6eee239d5909 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -3924,7 +3924,7 @@ static void ieee80211_color_change_abort(struct ieee80211_sub_if_data *sdata)

ieee80211_free_next_beacon(&sdata->deflink);

- cfg80211_color_change_aborted_notify(sdata->dev);
+ cfg80211_color_change_aborted_notify(sdata->dev, 0);
}

static int
@@ -4772,14 +4772,14 @@ static int ieee80211_color_change_finalize(struct ieee80211_sub_if_data *sdata)

err = ieee80211_set_after_color_change_beacon(sdata, &changed);
if (err) {
- cfg80211_color_change_aborted_notify(sdata->dev);
+ cfg80211_color_change_aborted_notify(sdata->dev, 0);
return err;
}

ieee80211_color_change_bss_config_notify(sdata,
sdata->vif.bss_conf.color_change_color,
1, changed);
- cfg80211_color_change_notify(sdata->dev);
+ cfg80211_color_change_notify(sdata->dev, 0);

return 0;
}
@@ -4812,7 +4812,8 @@ void ieee80211_color_collision_detection_work(struct work_struct *work)
color_collision_detect_work);
struct ieee80211_sub_if_data *sdata = link->sdata;

- cfg80211_obss_color_collision_notify(sdata->dev, link->color_bitmap);
+ cfg80211_obss_color_collision_notify(sdata->dev, link->color_bitmap,
+ link->link_id);
}

void ieee80211_color_change_finish(struct ieee80211_vif *vif)
@@ -4876,7 +4877,7 @@ ieee80211_color_change(struct wiphy *wiphy, struct net_device *dev,
sdata->vif.bss_conf.color_change_active = true;
sdata->vif.bss_conf.color_change_color = params->color;

- cfg80211_color_change_started_notify(sdata->dev, params->count);
+ cfg80211_color_change_started_notify(sdata->dev, params->count, 0);

if (changed)
ieee80211_color_change_bss_config_notify(sdata, 0, 0, changed);
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 995904f71be3..92afbd64682d 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -19456,7 +19456,7 @@ EXPORT_SYMBOL(cfg80211_ch_switch_started_notify);

int cfg80211_bss_color_notify(struct net_device *dev,
enum nl80211_commands cmd, u8 count,
- u64 color_bitmap)
+ u64 color_bitmap, u8 link_id)
{
struct wireless_dev *wdev = dev->ieee80211_ptr;
struct wiphy *wiphy = wdev->wiphy;
@@ -19479,6 +19479,10 @@ int cfg80211_bss_color_notify(struct net_device *dev,
if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex))
goto nla_put_failure;

+ if (wdev->valid_links &&
+ nla_put_u8(msg, NL80211_ATTR_MLO_LINK_ID, link_id))
+ goto nla_put_failure;
+
if (cmd == NL80211_CMD_COLOR_CHANGE_STARTED &&
nla_put_u32(msg, NL80211_ATTR_COLOR_CHANGE_COUNT, count))
goto nla_put_failure;
--
2.34.1


2024-04-22 05:38:23

by Aditya Kumar Singh

[permalink] [raw]
Subject: [PATCH v2 6/7] wifi: mac80211: add support to call color_change and OBSS collision on a link

Currently ieee80211_color_change_finish() function finalizes color change
by scheduling a finalizing worker using the deflink. Similarly, function
ieee80211_obss_color_collision_notify() notifies the mac80211 about color
collision on deflink. With MLO, there is a need to do it on a given link
basis.

Pass link ID of the link on which color change needs to be finalized or
OBSS color collision is detected.

Signed-off-by: Aditya Kumar Singh <[email protected]>
---
drivers/net/wireless/ath/ath11k/mac.c | 2 +-
drivers/net/wireless/ath/ath11k/wmi.c | 3 +-
.../net/wireless/mediatek/mt76/mt7915/mcu.c | 2 +-
.../net/wireless/mediatek/mt76/mt7996/mcu.c | 2 +-
include/net/mac80211.h | 6 ++-
net/mac80211/cfg.c | 43 ++++++++++++++++---
net/mac80211/rx.c | 7 +--
7 files changed, 50 insertions(+), 15 deletions(-)

diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c
index c32be587000d..40c3ba6c445b 100644
--- a/drivers/net/wireless/ath/ath11k/mac.c
+++ b/drivers/net/wireless/ath/ath11k/mac.c
@@ -1659,7 +1659,7 @@ void ath11k_mac_bcn_tx_event(struct ath11k_vif *arvif)
if (vif->bss_conf.color_change_active &&
ieee80211_beacon_cntdwn_is_complete(vif, 0)) {
arvif->bcca_zero_sent = true;
- ieee80211_color_change_finish(vif);
+ ieee80211_color_change_finish(vif, 0);
return;
}

diff --git a/drivers/net/wireless/ath/ath11k/wmi.c b/drivers/net/wireless/ath/ath11k/wmi.c
index c74aa3f95658..3761dfce1f64 100644
--- a/drivers/net/wireless/ath/ath11k/wmi.c
+++ b/drivers/net/wireless/ath/ath11k/wmi.c
@@ -4064,7 +4064,8 @@ ath11k_wmi_obss_color_collision_event(struct ath11k_base *ab, struct sk_buff *sk

switch (ev->evt_type) {
case WMI_BSS_COLOR_COLLISION_DETECTION:
- ieee80211_obss_color_collision_notify(arvif->vif, ev->obss_color_bitmap);
+ ieee80211_obss_color_collision_notify(arvif->vif, ev->obss_color_bitmap,
+ 0);
ath11k_dbg(ab, ATH11K_DBG_WMI,
"OBSS color collision detected vdev:%d, event:%d, bitmap:%08llx\n",
ev->vdev_id, ev->evt_type, ev->obss_color_bitmap);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
index d90f98c50039..6442e3e5d45b 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
@@ -331,7 +331,7 @@ mt7915_mcu_cca_finish(void *priv, u8 *mac, struct ieee80211_vif *vif)
if (!vif->bss_conf.color_change_active || vif->type == NL80211_IFTYPE_STATION)
return;

- ieee80211_color_change_finish(vif);
+ ieee80211_color_change_finish(vif, 0);
}

static void
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
index b44abe2acc81..163b822a477c 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
@@ -418,7 +418,7 @@ mt7996_mcu_cca_finish(void *priv, u8 *mac, struct ieee80211_vif *vif)
if (!vif->bss_conf.color_change_active || vif->type == NL80211_IFTYPE_STATION)
return;

- ieee80211_color_change_finish(vif);
+ ieee80211_color_change_finish(vif, 0);
}

static void
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 41f135a793ab..6be62cc2caf6 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -5612,12 +5612,13 @@ bool ieee80211_beacon_cntdwn_is_complete(struct ieee80211_vif *vif,
/**
* ieee80211_color_change_finish - notify mac80211 about color change
* @vif: &struct ieee80211_vif pointer from the add_interface callback.
+ * @link_id: valid link_id during MLO or 0 for non-MLO
*
* After a color change announcement was scheduled and the counter in this
* announcement hits 1, this function must be called by the driver to
* notify mac80211 that the color can be changed
*/
-void ieee80211_color_change_finish(struct ieee80211_vif *vif);
+void ieee80211_color_change_finish(struct ieee80211_vif *vif, u8 link_id);

/**
* ieee80211_proberesp_get - retrieve a Probe Response template
@@ -7530,6 +7531,7 @@ ieee80211_get_unsol_bcast_probe_resp_tmpl(struct ieee80211_hw *hw,
/**
* ieee80211_obss_color_collision_notify - notify userland about a BSS color
* collision.
+ * @link_id: valid link_id during MLO or 0 for non-MLO
*
* @vif: &struct ieee80211_vif pointer from the add_interface callback.
* @color_bitmap: a 64 bit bitmap representing the colors that the local BSS is
@@ -7537,7 +7539,7 @@ ieee80211_get_unsol_bcast_probe_resp_tmpl(struct ieee80211_hw *hw,
*/
void
ieee80211_obss_color_collision_notify(struct ieee80211_vif *vif,
- u64 color_bitmap);
+ u64 color_bitmap, u8 link_id);

/**
* ieee80211_is_tx_data - check if frame is a data frame
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index b30d842e5068..b08e5d7687e3 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -4824,27 +4824,56 @@ void ieee80211_color_collision_detection_work(struct work_struct *work)
link->link_id);
}

-void ieee80211_color_change_finish(struct ieee80211_vif *vif)
+void ieee80211_color_change_finish(struct ieee80211_vif *vif, u8 link_id)
{
struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
+ struct ieee80211_link_data *link;
+
+ if (WARN_ON(link_id >= IEEE80211_MLD_MAX_NUM_LINKS))
+ return;
+
+ rcu_read_lock();
+
+ link = rcu_dereference(sdata->link[link_id]);
+ if (WARN_ON(!link)) {
+ rcu_read_unlock();
+ return;
+ }

wiphy_work_queue(sdata->local->hw.wiphy,
- &sdata->deflink.color_change_finalize_work);
+ &link->color_change_finalize_work);
+
+ rcu_read_unlock();
}
EXPORT_SYMBOL_GPL(ieee80211_color_change_finish);

void
ieee80211_obss_color_collision_notify(struct ieee80211_vif *vif,
- u64 color_bitmap)
+ u64 color_bitmap, u8 link_id)
{
struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
- struct ieee80211_link_data *link = &sdata->deflink;
+ struct ieee80211_link_data *link;

- if (sdata->vif.bss_conf.color_change_active || sdata->vif.bss_conf.csa_active)
+ if (WARN_ON(link_id >= IEEE80211_MLD_MAX_NUM_LINKS))
return;

- if (delayed_work_pending(&link->color_collision_detect_work))
+ rcu_read_lock();
+
+ link = rcu_dereference(sdata->link[link_id]);
+ if (WARN_ON(!link)) {
+ rcu_read_unlock();
return;
+ }
+
+ if (link->conf->color_change_active || link->conf->csa_active) {
+ rcu_read_unlock();
+ return;
+ }
+
+ if (delayed_work_pending(&link->color_collision_detect_work)) {
+ rcu_read_unlock();
+ return;
+ }

link->color_bitmap = color_bitmap;
/* queue the color collision detection event every 500 ms in order to
@@ -4853,6 +4882,8 @@ ieee80211_obss_color_collision_notify(struct ieee80211_vif *vif,
ieee80211_queue_delayed_work(&sdata->local->hw,
&link->color_collision_detect_work,
msecs_to_jiffies(500));
+
+ rcu_read_unlock();
}
EXPORT_SYMBOL_GPL(ieee80211_obss_color_collision_notify);

diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 4b4cbd8bf35d..e2b561a9a751 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -3361,7 +3361,7 @@ ieee80211_rx_check_bss_color_collision(struct ieee80211_rx_data *rx)
if (ieee80211_hw_check(&rx->local->hw, DETECTS_COLOR_COLLISION))
return;

- if (rx->sdata->vif.bss_conf.csa_active)
+ if (rx->link->conf->csa_active)
return;

baselen = mgmt->u.beacon.variable - rx->skb->data;
@@ -3373,7 +3373,7 @@ ieee80211_rx_check_bss_color_collision(struct ieee80211_rx_data *rx)
rx->skb->len - baselen);
if (ie && ie->datalen >= sizeof(struct ieee80211_he_operation) &&
ie->datalen >= ieee80211_he_oper_size(ie->data + 1)) {
- struct ieee80211_bss_conf *bss_conf = &rx->sdata->vif.bss_conf;
+ struct ieee80211_bss_conf *bss_conf = rx->link->conf;
const struct ieee80211_he_operation *he_oper;
u8 color;

@@ -3386,7 +3386,8 @@ ieee80211_rx_check_bss_color_collision(struct ieee80211_rx_data *rx)
IEEE80211_HE_OPERATION_BSS_COLOR_MASK);
if (color == bss_conf->he_bss_color.color)
ieee80211_obss_color_collision_notify(&rx->sdata->vif,
- BIT_ULL(color));
+ BIT_ULL(color),
+ bss_conf->link_id);
}
}

--
2.34.1


2024-04-22 05:38:30

by Aditya Kumar Singh

[permalink] [raw]
Subject: [PATCH v2 7/7] wifi: mac80211_hwsim: add support for BSS color

Advertise support for BSS color and then once the countdown reaches 0,
call color change finish.

Signed-off-by: Aditya Kumar Singh <[email protected]>
---
drivers/net/wireless/virtual/mac80211_hwsim.c | 6 ++++++
1 file changed, 6 insertions(+)

diff --git a/drivers/net/wireless/virtual/mac80211_hwsim.c b/drivers/net/wireless/virtual/mac80211_hwsim.c
index f5aed44ec80a..64eeda1c398c 100644
--- a/drivers/net/wireless/virtual/mac80211_hwsim.c
+++ b/drivers/net/wireless/virtual/mac80211_hwsim.c
@@ -2313,6 +2313,10 @@ static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac,

if (link_conf->csa_active && ieee80211_beacon_cntdwn_is_complete(vif, link_id))
ieee80211_csa_finish(vif, link_id);
+
+ if (link_conf->color_change_active &&
+ ieee80211_beacon_cntdwn_is_complete(vif, link_id))
+ ieee80211_color_change_finish(vif, link_id);
}

static enum hrtimer_restart
@@ -5323,6 +5327,8 @@ static int mac80211_hwsim_new_radio(struct genl_info *info,

wiphy_ext_feature_set(hw->wiphy,
NL80211_EXT_FEATURE_SCAN_MIN_PREQ_CONTENT);
+ wiphy_ext_feature_set(hw->wiphy,
+ NL80211_EXT_FEATURE_BSS_COLOR);

hw->wiphy->interface_modes = param->iftypes;

--
2.34.1


2024-04-22 05:38:35

by Aditya Kumar Singh

[permalink] [raw]
Subject: [PATCH v2 5/7] wifi: mac80211: start and finalize color change on link basis

Add changes to start a color change as well as finalize it on link basis
in order to support switching color with MLO as well.

Signed-off-by: Aditya Kumar Singh <[email protected]>
---
net/mac80211/cfg.c | 55 +++++++++++++++++++++++++++++-----------------
1 file changed, 35 insertions(+), 20 deletions(-)

diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 5339a8e884ac..b30d842e5068 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -4765,26 +4765,27 @@ ieee80211_color_change_bss_config_notify(struct ieee80211_link_data *link,
}
}

-static int ieee80211_color_change_finalize(struct ieee80211_sub_if_data *sdata)
+static int ieee80211_color_change_finalize(struct ieee80211_link_data *link)
{
+ struct ieee80211_sub_if_data *sdata = link->sdata;
struct ieee80211_local *local = sdata->local;
u64 changed = 0;
int err;

lockdep_assert_wiphy(local->hw.wiphy);

- sdata->vif.bss_conf.color_change_active = false;
+ link->conf->color_change_active = false;

- err = ieee80211_set_after_color_change_beacon(&sdata->deflink, &changed);
+ err = ieee80211_set_after_color_change_beacon(link, &changed);
if (err) {
- cfg80211_color_change_aborted_notify(sdata->dev, 0);
+ cfg80211_color_change_aborted_notify(sdata->dev, link->link_id);
return err;
}

- ieee80211_color_change_bss_config_notify(&sdata->deflink,
- sdata->vif.bss_conf.color_change_color,
+ ieee80211_color_change_bss_config_notify(link,
+ link->conf->color_change_color,
1, changed);
- cfg80211_color_change_notify(sdata->dev, 0);
+ cfg80211_color_change_notify(sdata->dev, link->link_id);

return 0;
}
@@ -4792,21 +4793,23 @@ static int ieee80211_color_change_finalize(struct ieee80211_sub_if_data *sdata)
void ieee80211_color_change_finalize_work(struct wiphy *wiphy,
struct wiphy_work *work)
{
- struct ieee80211_sub_if_data *sdata =
- container_of(work, struct ieee80211_sub_if_data,
- deflink.color_change_finalize_work);
+ struct ieee80211_link_data *link =
+ container_of(work, struct ieee80211_link_data,
+ color_change_finalize_work);
+ struct ieee80211_sub_if_data *sdata = link->sdata;
+ struct ieee80211_bss_conf *link_conf = link->conf;
struct ieee80211_local *local = sdata->local;

lockdep_assert_wiphy(local->hw.wiphy);

/* AP might have been stopped while waiting for the lock. */
- if (!sdata->vif.bss_conf.color_change_active)
+ if (!link_conf->color_change_active)
return;

if (!ieee80211_sdata_running(sdata))
return;

- ieee80211_color_change_finalize(sdata);
+ ieee80211_color_change_finalize(link);
}

void ieee80211_color_collision_detection_work(struct work_struct *work)
@@ -4859,36 +4862,48 @@ ieee80211_color_change(struct wiphy *wiphy, struct net_device *dev,
{
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
struct ieee80211_local *local = sdata->local;
+ struct ieee80211_bss_conf *link_conf;
+ struct ieee80211_link_data *link;
+ u8 link_id = params->link_id;
u64 changed = 0;
int err;

lockdep_assert_wiphy(local->hw.wiphy);

- if (sdata->vif.bss_conf.nontransmitted)
+ if (WARN_ON(link_id >= IEEE80211_MLD_MAX_NUM_LINKS))
+ return -EINVAL;
+
+ link = wiphy_dereference(wiphy, sdata->link[link_id]);
+ if (!link)
+ return -ENOLINK;
+
+ link_conf = link->conf;
+
+ if (link_conf->nontransmitted)
return -EINVAL;

/* don't allow another color change if one is already active or if csa
* is active
*/
- if (sdata->vif.bss_conf.color_change_active || sdata->vif.bss_conf.csa_active) {
+ if (link_conf->color_change_active || link_conf->csa_active) {
err = -EBUSY;
goto out;
}

- err = ieee80211_set_color_change_beacon(&sdata->deflink, params, &changed);
+ err = ieee80211_set_color_change_beacon(link, params, &changed);
if (err)
goto out;

- sdata->vif.bss_conf.color_change_active = true;
- sdata->vif.bss_conf.color_change_color = params->color;
+ link_conf->color_change_active = true;
+ link_conf->color_change_color = params->color;

- cfg80211_color_change_started_notify(sdata->dev, params->count, 0);
+ cfg80211_color_change_started_notify(sdata->dev, params->count, link_id);

if (changed)
- ieee80211_color_change_bss_config_notify(&sdata->deflink, 0, 0, changed);
+ ieee80211_color_change_bss_config_notify(link, 0, 0, changed);
else
/* if the beacon didn't change, we can finalize immediately */
- ieee80211_color_change_finalize(sdata);
+ ieee80211_color_change_finalize(link);

out:

--
2.34.1


2024-04-23 18:54:06

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH v2 6/7] wifi: mac80211: add support to call color_change and OBSS collision on a link

On Tue, 2024-04-23 at 11:46 -0700, Jeff Johnson wrote:
>
> Johannes, how do you feel about the new cleanup.h functionality? I ask because
> if we change this to just be:
>
> guard(rcu)();
>
> then we can remove all of the explicit rcu_read_unlock() calls --
> rcu_read_unlock() will be called automatically when the function goes out of
> scope.

Sounds like a good idea to me.

Jakub doesn't like it so much, see this thread:
https://lore.kernel.org/netdev/[email protected]/

But ultimately I don't think he'll stop us from doing it here,
especially if we use it carefully enough that we actually do need the
guard for the whole scope.

johannes

2024-04-23 19:14:27

by Jeff Johnson

[permalink] [raw]
Subject: Re: [PATCH v2 6/7] wifi: mac80211: add support to call color_change and OBSS collision on a link

On 4/21/2024 10:34 PM, Aditya Kumar Singh wrote:
> Currently ieee80211_color_change_finish() function finalizes color change
> by scheduling a finalizing worker using the deflink. Similarly, function
> ieee80211_obss_color_collision_notify() notifies the mac80211 about color
> collision on deflink. With MLO, there is a need to do it on a given link
> basis.
>
> Pass link ID of the link on which color change needs to be finalized or
> OBSS color collision is detected.
>
> Signed-off-by: Aditya Kumar Singh <[email protected]>
> ---
[...]
> void
> ieee80211_obss_color_collision_notify(struct ieee80211_vif *vif,
> - u64 color_bitmap)
> + u64 color_bitmap, u8 link_id)
> {
> struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
> - struct ieee80211_link_data *link = &sdata->deflink;
> + struct ieee80211_link_data *link;
>
> - if (sdata->vif.bss_conf.color_change_active || sdata->vif.bss_conf.csa_active)
> + if (WARN_ON(link_id >= IEEE80211_MLD_MAX_NUM_LINKS))
> return;
>
> - if (delayed_work_pending(&link->color_collision_detect_work))
> + rcu_read_lock();

Johannes, how do you feel about the new cleanup.h functionality? I ask because
if we change this to just be:

guard(rcu)();

then we can remove all of the explicit rcu_read_unlock() calls --
rcu_read_unlock() will be called automatically when the function goes out of
scope.

> +
> + link = rcu_dereference(sdata->link[link_id]);
> + if (WARN_ON(!link)) {
> + rcu_read_unlock();
> return;
> + }
> +
> + if (link->conf->color_change_active || link->conf->csa_active) {
> + rcu_read_unlock();
> + return;
> + }
> +
> + if (delayed_work_pending(&link->color_collision_detect_work)) {
> + rcu_read_unlock();
> + return;
> + }
>
> link->color_bitmap = color_bitmap;
> /* queue the color collision detection event every 500 ms in order to
> @@ -4853,6 +4882,8 @@ ieee80211_obss_color_collision_notify(struct ieee80211_vif *vif,
> ieee80211_queue_delayed_work(&sdata->local->hw,
> &link->color_collision_detect_work,
> msecs_to_jiffies(500));
> +
> + rcu_read_unlock();
> }
> EXPORT_SYMBOL_GPL(ieee80211_obss_color_collision_notify);