In order to support DFS 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@xxxxxxxxxxx> --- net/mac80211/cfg.c | 26 ++++++++++++++++++-------- net/mac80211/link.c | 10 ++++++++++ net/mac80211/util.c | 29 +++++++++++++++++++++++------ 3 files changed, 51 insertions(+), 14 deletions(-) diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 57539e03d7d7..726cfb1f9061 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -3464,6 +3464,7 @@ static int ieee80211_start_radar_detection(struct wiphy *wiphy, struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_chan_req chanreq = { .oper = *chandef }; struct ieee80211_local *local = sdata->local; + struct ieee80211_link_data *link_data; int err; lockdep_assert_wiphy(local->hw.wiphy); @@ -3471,16 +3472,20 @@ static int ieee80211_start_radar_detection(struct wiphy *wiphy, if (!list_empty(&local->roc_list) || local->scanning) return -EBUSY; + link_data = sdata_dereference(sdata->link[link_id], sdata); + if (!link_data) + return -ENOLINK; + /* whatever, but channel contexts should not complain about that one */ - sdata->deflink.smps_mode = IEEE80211_SMPS_OFF; - sdata->deflink.needed_rx_chains = local->rx_chains; + link_data->smps_mode = IEEE80211_SMPS_OFF; + link_data->needed_rx_chains = local->rx_chains; - err = ieee80211_link_use_channel(&sdata->deflink, &chanreq, + err = ieee80211_link_use_channel(link_data, &chanreq, IEEE80211_CHANCTX_SHARED); if (err) return err; - wiphy_delayed_work_queue(wiphy, &sdata->deflink.dfs_cac_timer_work, + wiphy_delayed_work_queue(wiphy, &link_data->dfs_cac_timer_work, msecs_to_jiffies(cac_time_ms)); return 0; @@ -3491,16 +3496,21 @@ static void ieee80211_end_cac(struct wiphy *wiphy, { struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_local *local = sdata->local; + struct ieee80211_link_data *link_data; lockdep_assert_wiphy(local->hw.wiphy); list_for_each_entry(sdata, &local->interfaces, list) { + link_data = sdata_dereference(sdata->link[link_id], sdata); + if (!link_data) + continue; + wiphy_delayed_work_cancel(wiphy, - &sdata->deflink.dfs_cac_timer_work); + &link_data->dfs_cac_timer_work); - if (sdata->wdev.links[0].cac_started) { - ieee80211_link_release_channel(&sdata->deflink); - sdata->wdev.links[0].cac_started = false; + if (sdata->wdev.links[link_id].cac_started) { + ieee80211_link_release_channel(link_data); + sdata->wdev.links[link_id].cac_started = false; } } } diff --git a/net/mac80211/link.c b/net/mac80211/link.c index b4378969cbf1..0bbac64d5fa0 100644 --- a/net/mac80211/link.c +++ b/net/mac80211/link.c @@ -77,6 +77,16 @@ void ieee80211_link_stop(struct ieee80211_link_data *link) &link->color_change_finalize_work); wiphy_work_cancel(link->sdata->local->hw.wiphy, &link->csa.finalize_work); + + if (link->sdata->wdev.links[link->link_id].cac_started) { + wiphy_delayed_work_cancel(link->sdata->local->hw.wiphy, + &link->dfs_cac_timer_work); + cfg80211_cac_event(link->sdata->dev, + &link->conf->chanreq.oper, + NL80211_RADAR_CAC_ABORTED, + GFP_KERNEL, link->link_id); + } + ieee80211_link_release_channel(link); } diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 5996ea728096..59dde0393f81 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -3455,20 +3455,37 @@ void ieee80211_dfs_cac_cancel(struct ieee80211_local *local) { struct ieee80211_sub_if_data *sdata; struct cfg80211_chan_def chandef; + struct ieee80211_link_data *link_data; + struct ieee80211_bss_conf *link_conf; + unsigned int link_id; lockdep_assert_wiphy(local->hw.wiphy); list_for_each_entry(sdata, &local->interfaces, list) { - wiphy_delayed_work_cancel(local->hw.wiphy, - &sdata->deflink.dfs_cac_timer_work); + for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; + link_id++) { + link_data = sdata_dereference(sdata->link[link_id], + sdata); + if (!link_data) + continue; + + wiphy_delayed_work_cancel(local->hw.wiphy, + &link_data->dfs_cac_timer_work); + + if (!sdata->wdev.links[link_id].cac_started) + continue; + + link_conf = + rcu_dereference(sdata->vif.link_conf[link_id]); + if (!link_conf) + continue; - if (sdata->wdev.links[0].cac_started) { - chandef = sdata->vif.bss_conf.chanreq.oper; - ieee80211_link_release_channel(&sdata->deflink); + chandef = link_conf->chanreq.oper; + ieee80211_link_release_channel(link_data); cfg80211_cac_event(sdata->dev, &chandef, NL80211_RADAR_CAC_ABORTED, - GFP_KERNEL, 0); + GFP_KERNEL, link_id); } } } -- 2.34.1