wifi: mac80211: handle color change per link

In order to support color change with MLO, handle the link ID now
passed from cfg80211, adjust the code to do everything per link
and call the notifications to cfg80211 correctly.

Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
Link: https://msgid.link/20240422053412.2024075-4-quic_adisi@quicinc.com
Link: https://msgid.link/20240422053412.2024075-5-quic_adisi@quicinc.com
Link: https://msgid.link/20240422053412.2024075-6-quic_adisi@quicinc.com
Link: https://msgid.link/20240422053412.2024075-7-quic_adisi@quicinc.com
[squash, move API call updates to this patch]
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
Aditya Kumar Singh 2024-04-22 11:04:08 +05:30 committed by Johannes Berg
parent 91d2b6ee13
commit 414e736c3d
7 changed files with 111 additions and 55 deletions

View File

@ -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;
}

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -5615,12 +5615,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
@ -7533,6 +7534,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
@ -7540,7 +7542,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

View File

@ -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) {
@ -4666,20 +4666,22 @@ static int ieee80211_set_sar_specs(struct wiphy *wiphy,
}
static int
ieee80211_set_after_color_change_beacon(struct ieee80211_sub_if_data *sdata,
ieee80211_set_after_color_change_beacon(struct ieee80211_link_data *link,
u64 *changed)
{
struct ieee80211_sub_if_data *sdata = link->sdata;
switch (sdata->vif.type) {
case NL80211_IFTYPE_AP: {
int ret;
if (!sdata->deflink.u.ap.next_beacon)
if (!link->u.ap.next_beacon)
return -EINVAL;
ret = ieee80211_assign_beacon(sdata, &sdata->deflink,
sdata->deflink.u.ap.next_beacon,
ret = ieee80211_assign_beacon(sdata, link,
link->u.ap.next_beacon,
NULL, NULL, changed);
ieee80211_free_next_beacon(&sdata->deflink);
ieee80211_free_next_beacon(link);
if (ret < 0)
return ret;
@ -4695,18 +4697,19 @@ ieee80211_set_after_color_change_beacon(struct ieee80211_sub_if_data *sdata,
}
static int
ieee80211_set_color_change_beacon(struct ieee80211_sub_if_data *sdata,
ieee80211_set_color_change_beacon(struct ieee80211_link_data *link,
struct cfg80211_color_change_settings *params,
u64 *changed)
{
struct ieee80211_sub_if_data *sdata = link->sdata;
struct ieee80211_color_change_settings color_change = {};
int err;
switch (sdata->vif.type) {
case NL80211_IFTYPE_AP:
sdata->deflink.u.ap.next_beacon =
link->u.ap.next_beacon =
cfg80211_beacon_dup(&params->beacon_next);
if (!sdata->deflink.u.ap.next_beacon)
if (!link->u.ap.next_beacon)
return -ENOMEM;
if (params->count <= 1)
@ -4718,11 +4721,11 @@ ieee80211_set_color_change_beacon(struct ieee80211_sub_if_data *sdata,
params->counter_offset_presp;
color_change.count = params->count;
err = ieee80211_assign_beacon(sdata, &sdata->deflink,
err = ieee80211_assign_beacon(sdata, link,
&params->beacon_color_change,
NULL, &color_change, changed);
if (err < 0) {
ieee80211_free_next_beacon(&sdata->deflink);
ieee80211_free_next_beacon(link);
return err;
}
break;
@ -4734,16 +4737,18 @@ ieee80211_set_color_change_beacon(struct ieee80211_sub_if_data *sdata,
}
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;
@ -4760,26 +4765,27 @@ ieee80211_color_change_bss_config_notify(struct ieee80211_sub_if_data *sdata,
}
}
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, &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,
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;
}
@ -4787,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)
@ -4812,30 +4820,60 @@ 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, 0);
cfg80211_obss_color_collision_notify(sdata->dev, link->color_bitmap,
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
@ -4844,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);
@ -4853,36 +4893,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, 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, 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:

View File

@ -3368,7 +3368,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;
@ -3380,7 +3380,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;
@ -3393,7 +3393,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);
}
}