Commit 7ef8f682 authored by Johannes Berg's avatar Johannes Berg

wifi: mac80211: mlme: handle cross-link CSA

If we see a channel switch announcement on one link for
another, handle that case and start the CSA. The driver
can react to this in whatever way it needs. The stack
will have the ability to track it via the RNR/MLE in the
reporting link's beacon if it sees it for inactive links
and adjust everything accordingly.

Note that currently the timings for the CSA aren't set,
the values are only used by the Intel drivers, and they
don't need this for newer devices that support MLO, so
I've left it out for now.
Signed-off-by: default avatarMiri Korenblit <miriam.rachel.korenblit@intel.com>
Link: https://msgid.link/20240415112355.4d34b6a31be7.Ie8453979f5805873a8411c99346bcc3810cd6476@changeidSigned-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 2d33ecf5
......@@ -1150,6 +1150,9 @@ drv_pre_channel_switch(struct ieee80211_sub_if_data *sdata,
if (!check_sdata_in_driver(sdata))
return -EIO;
if (!ieee80211_vif_link_active(&sdata->vif, ch_switch->link_id))
return 0;
trace_drv_pre_channel_switch(local, sdata, ch_switch);
if (local->ops->pre_channel_switch)
ret = local->ops->pre_channel_switch(&local->hw, &sdata->vif,
......@@ -1171,6 +1174,9 @@ drv_post_channel_switch(struct ieee80211_link_data *link)
if (!check_sdata_in_driver(sdata))
return -EIO;
if (!ieee80211_vif_link_active(&sdata->vif, link->link_id))
return 0;
trace_drv_post_channel_switch(local, sdata);
if (local->ops->post_channel_switch)
ret = local->ops->post_channel_switch(&local->hw, &sdata->vif,
......@@ -1191,6 +1197,9 @@ drv_abort_channel_switch(struct ieee80211_link_data *link)
if (!check_sdata_in_driver(sdata))
return;
if (!ieee80211_vif_link_active(&sdata->vif, link->link_id))
return;
trace_drv_abort_channel_switch(local, sdata);
if (local->ops->abort_channel_switch)
......@@ -1210,6 +1219,9 @@ drv_channel_switch_rx_beacon(struct ieee80211_sub_if_data *sdata,
if (!check_sdata_in_driver(sdata))
return;
if (!ieee80211_vif_link_active(&sdata->vif, ch_switch->link_id))
return;
trace_drv_channel_switch_rx_beacon(local, sdata, ch_switch);
if (local->ops->channel_switch_rx_beacon)
local->ops->channel_switch_rx_beacon(&local->hw, &sdata->vif,
......
......@@ -978,6 +978,7 @@ struct ieee80211_link_data_managed {
bool csa_waiting_bcn;
bool csa_ignored_same_chan;
bool csa_blocked_tx;
unsigned long csa_time;
struct wiphy_delayed_work chswitch_work;
struct wiphy_work request_smps_work;
......
......@@ -357,6 +357,18 @@ static int _ieee80211_set_active_links(struct ieee80211_sub_if_data *sdata,
ieee80211_teardown_tdls_peers(link);
__ieee80211_link_release_channel(link, true);
/*
* If CSA is (still) active while the link is deactivated,
* just schedule the channel switch work for the time we
* had previously calculated, and we'll take the process
* from there.
*/
if (link->conf->csa_active)
wiphy_delayed_work_queue(local->hw.wiphy,
&link->u.mgd.chswitch_work,
link->u.mgd.csa_time -
jiffies);
}
list_for_each_entry(sta, &local->sta_list, list) {
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment