wifi: mac80211: handle DFS per link
authorAditya Kumar Singh <quic_adisi@quicinc.com>
Fri, 6 Sep 2024 06:44:24 +0000 (12:14 +0530)
committerJohannes Berg <johannes.berg@intel.com>
Fri, 6 Sep 2024 11:01:05 +0000 (13:01 +0200)
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@quicinc.com>
Link: https://patch.msgid.link/20240906064426.2101315-7-quic_adisi@quicinc.com
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
net/mac80211/cfg.c
net/mac80211/link.c
net/mac80211/util.c

index 67dd780530fbe620520115fbaa0374a3da229a66..57e66c671e2e8001458346029e5cc510a15dab4e 100644 (file)
@@ -3467,6 +3467,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);
@@ -3474,16 +3475,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;
@@ -3494,16 +3499,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;
                }
        }
 }
index b4378969cbf19a6d387ca239843bfb801be16b9c..0bbac64d5fa0132b748f775256d9c93b55ecc07d 100644 (file)
@@ -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);
 }
 
index c4fd60fbcfd41d5ce86ab55def42bfc991d1afa5..2e37d26390745eef8b0281031b5371728ef67a9a 100644 (file)
@@ -3471,20 +3471,30 @@ 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;
+       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);
-
-               if (sdata->wdev.links[0].cac_started) {
-                       chandef = sdata->vif.bss_conf.chanreq.oper;
-                       ieee80211_link_release_channel(&sdata->deflink);
-                       cfg80211_cac_event(sdata->dev,
-                                          &chandef,
+               for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS;
+                    link_id++) {
+                       link = sdata_dereference(sdata->link[link_id],
+                                                sdata);
+                       if (!link)
+                               continue;
+
+                       wiphy_delayed_work_cancel(local->hw.wiphy,
+                                                 &link->dfs_cac_timer_work);
+
+                       if (!sdata->wdev.links[link_id].cac_started)
+                               continue;
+
+                       chandef = link->conf->chanreq.oper;
+                       ieee80211_link_release_channel(link);
+                       cfg80211_cac_event(sdata->dev, &chandef,
                                           NL80211_RADAR_CAC_ABORTED,
-                                          GFP_KERNEL, 0);
+                                          GFP_KERNEL, link_id);
                }
        }
 }