mac80211: backport upstream DFS fixes
Mostly MLO related Signed-off-by: Felix Fietkau <nbd@nbd.name>
This commit is contained in:
		@@ -1,5 +1,14 @@
 | 
			
		||||
--- a/ath10k-6.9/mac.c
 | 
			
		||||
+++ b/ath10k-6.9/mac.c
 | 
			
		||||
@@ -1675,7 +1675,7 @@ static void ath10k_recalc_radar_detectio
 | 
			
		||||
 		 * by indicating that radar was detected.
 | 
			
		||||
 		 */
 | 
			
		||||
 		ath10k_warn(ar, "failed to start CAC: %d\n", ret);
 | 
			
		||||
-		ieee80211_radar_detected(ar->hw);
 | 
			
		||||
+		ieee80211_radar_detected(ar->hw, NULL);
 | 
			
		||||
 	}
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
@@ -6238,7 +6238,7 @@ err:
 | 
			
		||||
 	return ret;
 | 
			
		||||
 }
 | 
			
		||||
@@ -9,3 +18,25 @@
 | 
			
		||||
 {
 | 
			
		||||
 	struct ath10k *ar = hw->priv;
 | 
			
		||||
 	u32 opt;
 | 
			
		||||
--- a/ath10k-6.9/debug.c
 | 
			
		||||
+++ b/ath10k-6.9/debug.c
 | 
			
		||||
@@ -3319,7 +3319,7 @@ static ssize_t ath10k_write_simulate_rad
 | 
			
		||||
 	if (!arvif->is_started)
 | 
			
		||||
 		return -EINVAL;
 | 
			
		||||
 
 | 
			
		||||
-	ieee80211_radar_detected(ar->hw);
 | 
			
		||||
+	ieee80211_radar_detected(ar->hw, NULL);
 | 
			
		||||
 
 | 
			
		||||
 	return count;
 | 
			
		||||
 }
 | 
			
		||||
--- a/ath10k-6.9/wmi.c
 | 
			
		||||
+++ b/ath10k-6.9/wmi.c
 | 
			
		||||
@@ -4402,7 +4402,7 @@ static void ath10k_radar_detected(struct
 | 
			
		||||
 	if (ar->dfs_block_radar_events)
 | 
			
		||||
 		ath10k_info(ar, "DFS Radar detected, but ignored as requested\n");
 | 
			
		||||
 	else
 | 
			
		||||
-		ieee80211_radar_detected(ar->hw);
 | 
			
		||||
+		ieee80211_radar_detected(ar->hw, NULL);
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
 static void ath10k_radar_confirmation_work(struct work_struct *work)
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,64 @@
 | 
			
		||||
From: Issam Hamdi <ih@simonwunderlich.de>
 | 
			
		||||
Date: Fri, 16 Aug 2024 16:24:18 +0200
 | 
			
		||||
Subject: [PATCH] wifi: cfg80211: Set correct chandef when starting CAC
 | 
			
		||||
 | 
			
		||||
When starting CAC in a mode other than AP mode, it return a
 | 
			
		||||
"WARNING: CPU: 0 PID: 63 at cfg80211_chandef_dfs_usable+0x20/0xaf [cfg80211]"
 | 
			
		||||
caused by the chandef.chan being null at the end of CAC.
 | 
			
		||||
 | 
			
		||||
Solution: Ensure the channel definition is set for the different modes
 | 
			
		||||
when starting CAC to avoid getting a NULL 'chan' at the end of CAC.
 | 
			
		||||
 | 
			
		||||
 Call Trace:
 | 
			
		||||
  ? show_regs.part.0+0x14/0x16
 | 
			
		||||
  ? __warn+0x67/0xc0
 | 
			
		||||
  ? cfg80211_chandef_dfs_usable+0x20/0xaf [cfg80211]
 | 
			
		||||
  ? report_bug+0xa7/0x130
 | 
			
		||||
  ? exc_overflow+0x30/0x30
 | 
			
		||||
  ? handle_bug+0x27/0x50
 | 
			
		||||
  ? exc_invalid_op+0x18/0x60
 | 
			
		||||
  ? handle_exception+0xf6/0xf6
 | 
			
		||||
  ? exc_overflow+0x30/0x30
 | 
			
		||||
  ? cfg80211_chandef_dfs_usable+0x20/0xaf [cfg80211]
 | 
			
		||||
  ? exc_overflow+0x30/0x30
 | 
			
		||||
  ? cfg80211_chandef_dfs_usable+0x20/0xaf [cfg80211]
 | 
			
		||||
  ? regulatory_propagate_dfs_state.cold+0x1b/0x4c [cfg80211]
 | 
			
		||||
  ? cfg80211_propagate_cac_done_wk+0x1a/0x30 [cfg80211]
 | 
			
		||||
  ? process_one_work+0x165/0x280
 | 
			
		||||
  ? worker_thread+0x120/0x3f0
 | 
			
		||||
  ? kthread+0xc2/0xf0
 | 
			
		||||
  ? process_one_work+0x280/0x280
 | 
			
		||||
  ? kthread_complete_and_exit+0x20/0x20
 | 
			
		||||
  ? ret_from_fork+0x19/0x24
 | 
			
		||||
 | 
			
		||||
Reported-by: Kretschmer Mathias <mathias.kretschmer@fit.fraunhofer.de>
 | 
			
		||||
Signed-off-by: Issam Hamdi <ih@simonwunderlich.de>
 | 
			
		||||
Link: https://patch.msgid.link/20240816142418.3381951-1-ih@simonwunderlich.de
 | 
			
		||||
[shorten subject, remove OCB, reorder cases to match previous list]
 | 
			
		||||
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
 | 
			
		||||
---
 | 
			
		||||
 | 
			
		||||
--- a/net/wireless/nl80211.c
 | 
			
		||||
+++ b/net/wireless/nl80211.c
 | 
			
		||||
@@ -10144,7 +10144,20 @@ static int nl80211_start_radar_detection
 | 
			
		||||
 
 | 
			
		||||
 	err = rdev_start_radar_detection(rdev, dev, &chandef, cac_time_ms);
 | 
			
		||||
 	if (!err) {
 | 
			
		||||
-		wdev->links[0].ap.chandef = chandef;
 | 
			
		||||
+		switch (wdev->iftype) {
 | 
			
		||||
+		case NL80211_IFTYPE_AP:
 | 
			
		||||
+		case NL80211_IFTYPE_P2P_GO:
 | 
			
		||||
+			wdev->links[0].ap.chandef = chandef;
 | 
			
		||||
+			break;
 | 
			
		||||
+		case NL80211_IFTYPE_ADHOC:
 | 
			
		||||
+			wdev->u.ibss.chandef = chandef;
 | 
			
		||||
+			break;
 | 
			
		||||
+		case NL80211_IFTYPE_MESH_POINT:
 | 
			
		||||
+			wdev->u.mesh.chandef = chandef;
 | 
			
		||||
+			break;
 | 
			
		||||
+		default:
 | 
			
		||||
+			break;
 | 
			
		||||
+		}
 | 
			
		||||
 		wdev->cac_started = true;
 | 
			
		||||
 		wdev->cac_start_time = jiffies;
 | 
			
		||||
 		wdev->cac_time_ms = cac_time_ms;
 | 
			
		||||
@@ -0,0 +1,136 @@
 | 
			
		||||
From: Aditya Kumar Singh <quic_adisi@quicinc.com>
 | 
			
		||||
Date: Fri, 6 Sep 2024 12:14:19 +0530
 | 
			
		||||
Subject: [PATCH] Revert "wifi: mac80211: move radar detect work to sdata"
 | 
			
		||||
MIME-Version: 1.0
 | 
			
		||||
Content-Type: text/plain; charset=UTF-8
 | 
			
		||||
Content-Transfer-Encoding: 8bit
 | 
			
		||||
 | 
			
		||||
This reverts commit ce9e660ef32e ("wifi: mac80211: move radar detect work to sdata").
 | 
			
		||||
 | 
			
		||||
To enable radar detection with MLO, it’s essential to handle it on a
 | 
			
		||||
per-link basis. This is because when using MLO, multiple links may already
 | 
			
		||||
be active and beaconing. In this scenario, another link should be able to
 | 
			
		||||
initiate a radar detection. Also, if underlying links are associated with
 | 
			
		||||
different hardware devices but grouped together for MLO, they could
 | 
			
		||||
potentially start radar detection simultaneously. Therefore, it makes
 | 
			
		||||
sense to manage radar detection settings separately for each link by moving
 | 
			
		||||
them back to a per-link data structure.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
 | 
			
		||||
Link: https://patch.msgid.link/20240906064426.2101315-2-quic_adisi@quicinc.com
 | 
			
		||||
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
 | 
			
		||||
---
 | 
			
		||||
 | 
			
		||||
--- a/net/mac80211/cfg.c
 | 
			
		||||
+++ b/net/mac80211/cfg.c
 | 
			
		||||
@@ -1658,7 +1658,7 @@ static int ieee80211_stop_ap(struct wiph
 | 
			
		||||
 
 | 
			
		||||
 	if (sdata->wdev.cac_started) {
 | 
			
		||||
 		chandef = link_conf->chanreq.oper;
 | 
			
		||||
-		wiphy_delayed_work_cancel(wiphy, &sdata->dfs_cac_timer_work);
 | 
			
		||||
+		wiphy_delayed_work_cancel(wiphy, &link->dfs_cac_timer_work);
 | 
			
		||||
 		cfg80211_cac_event(sdata->dev, &chandef,
 | 
			
		||||
 				   NL80211_RADAR_CAC_ABORTED,
 | 
			
		||||
 				   GFP_KERNEL);
 | 
			
		||||
@@ -3482,7 +3482,7 @@ static int ieee80211_start_radar_detecti
 | 
			
		||||
 	if (err)
 | 
			
		||||
 		goto out_unlock;
 | 
			
		||||
 
 | 
			
		||||
-	wiphy_delayed_work_queue(wiphy, &sdata->dfs_cac_timer_work,
 | 
			
		||||
+	wiphy_delayed_work_queue(wiphy, &sdata->deflink.dfs_cac_timer_work,
 | 
			
		||||
 				 msecs_to_jiffies(cac_time_ms));
 | 
			
		||||
 
 | 
			
		||||
  out_unlock:
 | 
			
		||||
@@ -3499,7 +3499,7 @@ static void ieee80211_end_cac(struct wip
 | 
			
		||||
 
 | 
			
		||||
 	list_for_each_entry(sdata, &local->interfaces, list) {
 | 
			
		||||
 		wiphy_delayed_work_cancel(wiphy,
 | 
			
		||||
-					  &sdata->dfs_cac_timer_work);
 | 
			
		||||
+					  &sdata->deflink.dfs_cac_timer_work);
 | 
			
		||||
 
 | 
			
		||||
 		if (sdata->wdev.cac_started) {
 | 
			
		||||
 			ieee80211_link_release_channel(&sdata->deflink);
 | 
			
		||||
--- a/net/mac80211/ieee80211_i.h
 | 
			
		||||
+++ b/net/mac80211/ieee80211_i.h
 | 
			
		||||
@@ -1069,6 +1069,7 @@ struct ieee80211_link_data {
 | 
			
		||||
 	int ap_power_level; /* in dBm */
 | 
			
		||||
 
 | 
			
		||||
 	bool radar_required;
 | 
			
		||||
+	struct wiphy_delayed_work dfs_cac_timer_work;
 | 
			
		||||
 
 | 
			
		||||
 	union {
 | 
			
		||||
 		struct ieee80211_link_data_managed mgd;
 | 
			
		||||
@@ -1167,8 +1168,6 @@ struct ieee80211_sub_if_data {
 | 
			
		||||
 	struct ieee80211_link_data deflink;
 | 
			
		||||
 	struct ieee80211_link_data __rcu *link[IEEE80211_MLD_MAX_NUM_LINKS];
 | 
			
		||||
 
 | 
			
		||||
-	struct wiphy_delayed_work dfs_cac_timer_work;
 | 
			
		||||
-
 | 
			
		||||
 	/* for ieee80211_set_active_links_async() */
 | 
			
		||||
 	struct wiphy_work activate_links_work;
 | 
			
		||||
 	u16 desired_active_links;
 | 
			
		||||
--- a/net/mac80211/iface.c
 | 
			
		||||
+++ b/net/mac80211/iface.c
 | 
			
		||||
@@ -551,7 +551,7 @@ static void ieee80211_do_stop(struct iee
 | 
			
		||||
 	wiphy_work_cancel(local->hw.wiphy,
 | 
			
		||||
 			  &sdata->deflink.color_change_finalize_work);
 | 
			
		||||
 	wiphy_delayed_work_cancel(local->hw.wiphy,
 | 
			
		||||
-				  &sdata->dfs_cac_timer_work);
 | 
			
		||||
+				  &sdata->deflink.dfs_cac_timer_work);
 | 
			
		||||
 
 | 
			
		||||
 	if (sdata->wdev.cac_started) {
 | 
			
		||||
 		chandef = sdata->vif.bss_conf.chanreq.oper;
 | 
			
		||||
@@ -1744,8 +1744,6 @@ static void ieee80211_setup_sdata(struct
 | 
			
		||||
 	wiphy_work_init(&sdata->work, ieee80211_iface_work);
 | 
			
		||||
 	wiphy_work_init(&sdata->activate_links_work,
 | 
			
		||||
 			ieee80211_activate_links_work);
 | 
			
		||||
-	wiphy_delayed_work_init(&sdata->dfs_cac_timer_work,
 | 
			
		||||
-				ieee80211_dfs_cac_timer_work);
 | 
			
		||||
 
 | 
			
		||||
 	switch (type) {
 | 
			
		||||
 	case NL80211_IFTYPE_P2P_GO:
 | 
			
		||||
--- a/net/mac80211/link.c
 | 
			
		||||
+++ b/net/mac80211/link.c
 | 
			
		||||
@@ -45,6 +45,8 @@ void ieee80211_link_init(struct ieee8021
 | 
			
		||||
 			  ieee80211_color_collision_detection_work);
 | 
			
		||||
 	INIT_LIST_HEAD(&link->assigned_chanctx_list);
 | 
			
		||||
 	INIT_LIST_HEAD(&link->reserved_chanctx_list);
 | 
			
		||||
+	wiphy_delayed_work_init(&link->dfs_cac_timer_work,
 | 
			
		||||
+				ieee80211_dfs_cac_timer_work);
 | 
			
		||||
 
 | 
			
		||||
 	if (!deflink) {
 | 
			
		||||
 		switch (sdata->vif.type) {
 | 
			
		||||
--- a/net/mac80211/mlme.c
 | 
			
		||||
+++ b/net/mac80211/mlme.c
 | 
			
		||||
@@ -3031,15 +3031,16 @@ void ieee80211_dynamic_ps_timer(struct t
 | 
			
		||||
 
 | 
			
		||||
 void ieee80211_dfs_cac_timer_work(struct wiphy *wiphy, struct wiphy_work *work)
 | 
			
		||||
 {
 | 
			
		||||
-	struct ieee80211_sub_if_data *sdata =
 | 
			
		||||
-		container_of(work, struct ieee80211_sub_if_data,
 | 
			
		||||
+	struct ieee80211_link_data *link =
 | 
			
		||||
+		container_of(work, struct ieee80211_link_data,
 | 
			
		||||
 			     dfs_cac_timer_work.work);
 | 
			
		||||
-	struct cfg80211_chan_def chandef = sdata->vif.bss_conf.chanreq.oper;
 | 
			
		||||
+	struct cfg80211_chan_def chandef = link->conf->chanreq.oper;
 | 
			
		||||
+	struct ieee80211_sub_if_data *sdata = link->sdata;
 | 
			
		||||
 
 | 
			
		||||
 	lockdep_assert_wiphy(sdata->local->hw.wiphy);
 | 
			
		||||
 
 | 
			
		||||
 	if (sdata->wdev.cac_started) {
 | 
			
		||||
-		ieee80211_link_release_channel(&sdata->deflink);
 | 
			
		||||
+		ieee80211_link_release_channel(link);
 | 
			
		||||
 		cfg80211_cac_event(sdata->dev, &chandef,
 | 
			
		||||
 				   NL80211_RADAR_CAC_FINISHED,
 | 
			
		||||
 				   GFP_KERNEL);
 | 
			
		||||
--- a/net/mac80211/util.c
 | 
			
		||||
+++ b/net/mac80211/util.c
 | 
			
		||||
@@ -3460,7 +3460,7 @@ void ieee80211_dfs_cac_cancel(struct iee
 | 
			
		||||
 
 | 
			
		||||
 	list_for_each_entry(sdata, &local->interfaces, list) {
 | 
			
		||||
 		wiphy_delayed_work_cancel(local->hw.wiphy,
 | 
			
		||||
-					  &sdata->dfs_cac_timer_work);
 | 
			
		||||
+					  &sdata->deflink.dfs_cac_timer_work);
 | 
			
		||||
 
 | 
			
		||||
 		if (sdata->wdev.cac_started) {
 | 
			
		||||
 			chandef = sdata->vif.bss_conf.chanreq.oper;
 | 
			
		||||
@@ -0,0 +1,50 @@
 | 
			
		||||
From: Aditya Kumar Singh <quic_adisi@quicinc.com>
 | 
			
		||||
Date: Fri, 6 Sep 2024 12:14:20 +0530
 | 
			
		||||
Subject: [PATCH] wifi: mac80211: remove label usage in
 | 
			
		||||
 ieee80211_start_radar_detection()
 | 
			
		||||
 | 
			
		||||
After locks rework [1], ieee80211_start_radar_detection() function is no
 | 
			
		||||
longer acquiring any lock as such explicitly. Hence, it is not unlocking
 | 
			
		||||
anything as well. However, label "out_unlock" is still used which creates
 | 
			
		||||
confusion. Also, now there is no need of goto label as such.
 | 
			
		||||
 | 
			
		||||
Get rid of the goto logic and use direct return statements.
 | 
			
		||||
 | 
			
		||||
[1]: https://lore.kernel.org/all/20230828135928.b1c6efffe9ad.I4aec875e25abc9ef0b5ad1e70b5747fd483fbd3c@changeid/
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
 | 
			
		||||
Link: https://patch.msgid.link/20240906064426.2101315-3-quic_adisi@quicinc.com
 | 
			
		||||
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
 | 
			
		||||
---
 | 
			
		||||
 | 
			
		||||
--- a/net/mac80211/cfg.c
 | 
			
		||||
+++ b/net/mac80211/cfg.c
 | 
			
		||||
@@ -3468,10 +3468,8 @@ static int ieee80211_start_radar_detecti
 | 
			
		||||
 
 | 
			
		||||
 	lockdep_assert_wiphy(local->hw.wiphy);
 | 
			
		||||
 
 | 
			
		||||
-	if (!list_empty(&local->roc_list) || local->scanning) {
 | 
			
		||||
-		err = -EBUSY;
 | 
			
		||||
-		goto out_unlock;
 | 
			
		||||
-	}
 | 
			
		||||
+	if (!list_empty(&local->roc_list) || local->scanning)
 | 
			
		||||
+		return -EBUSY;
 | 
			
		||||
 
 | 
			
		||||
 	/* whatever, but channel contexts should not complain about that one */
 | 
			
		||||
 	sdata->deflink.smps_mode = IEEE80211_SMPS_OFF;
 | 
			
		||||
@@ -3480,13 +3478,12 @@ static int ieee80211_start_radar_detecti
 | 
			
		||||
 	err = ieee80211_link_use_channel(&sdata->deflink, &chanreq,
 | 
			
		||||
 					 IEEE80211_CHANCTX_SHARED);
 | 
			
		||||
 	if (err)
 | 
			
		||||
-		goto out_unlock;
 | 
			
		||||
+		return err;
 | 
			
		||||
 
 | 
			
		||||
 	wiphy_delayed_work_queue(wiphy, &sdata->deflink.dfs_cac_timer_work,
 | 
			
		||||
 				 msecs_to_jiffies(cac_time_ms));
 | 
			
		||||
 
 | 
			
		||||
- out_unlock:
 | 
			
		||||
-	return err;
 | 
			
		||||
+	return 0;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
 static void ieee80211_end_cac(struct wiphy *wiphy,
 | 
			
		||||
@@ -0,0 +1,42 @@
 | 
			
		||||
From: Aditya Kumar Singh <quic_adisi@quicinc.com>
 | 
			
		||||
Date: Fri, 6 Sep 2024 12:14:21 +0530
 | 
			
		||||
Subject: [PATCH] wifi: trace: unlink rdev_end_cac trace event from
 | 
			
		||||
 wiphy_netdev_evt class
 | 
			
		||||
 | 
			
		||||
rdev_end_cac trace event is linked with wiphy_netdev_evt event class.
 | 
			
		||||
There is no option to pass link ID currently to wiphy_netdev_evt class.
 | 
			
		||||
A subsequent change would pass link ID to rdev_end_cac event and hence
 | 
			
		||||
it can no longer derive the event class from wiphy_netdev_evt.
 | 
			
		||||
 | 
			
		||||
Therefore, unlink rdev_end_cac event from wiphy_netdev_evt and define it's
 | 
			
		||||
own independent trace event. Link ID would be passed in subsequent change.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
 | 
			
		||||
Link: https://patch.msgid.link/20240906064426.2101315-4-quic_adisi@quicinc.com
 | 
			
		||||
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
 | 
			
		||||
---
 | 
			
		||||
 | 
			
		||||
--- a/net/wireless/trace.h
 | 
			
		||||
+++ b/net/wireless/trace.h
 | 
			
		||||
@@ -805,9 +805,18 @@ DEFINE_EVENT(wiphy_netdev_evt, rdev_flus
 | 
			
		||||
 	TP_ARGS(wiphy, netdev)
 | 
			
		||||
 );
 | 
			
		||||
 
 | 
			
		||||
-DEFINE_EVENT(wiphy_netdev_evt, rdev_end_cac,
 | 
			
		||||
-	     TP_PROTO(struct wiphy *wiphy, struct net_device *netdev),
 | 
			
		||||
-	     TP_ARGS(wiphy, netdev)
 | 
			
		||||
+TRACE_EVENT(rdev_end_cac,
 | 
			
		||||
+	TP_PROTO(struct wiphy *wiphy, struct net_device *netdev),
 | 
			
		||||
+	TP_ARGS(wiphy, netdev),
 | 
			
		||||
+	TP_STRUCT__entry(
 | 
			
		||||
+		WIPHY_ENTRY
 | 
			
		||||
+		NETDEV_ENTRY
 | 
			
		||||
+	),
 | 
			
		||||
+	TP_fast_assign(
 | 
			
		||||
+		WIPHY_ASSIGN;
 | 
			
		||||
+		NETDEV_ASSIGN;
 | 
			
		||||
+	),
 | 
			
		||||
+	TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT, WIPHY_PR_ARG, NETDEV_PR_ARG)
 | 
			
		||||
 );
 | 
			
		||||
 
 | 
			
		||||
 DECLARE_EVENT_CLASS(station_add_change,
 | 
			
		||||
@@ -0,0 +1,309 @@
 | 
			
		||||
From: Aditya Kumar Singh <quic_adisi@quicinc.com>
 | 
			
		||||
Date: Fri, 6 Sep 2024 12:14:22 +0530
 | 
			
		||||
Subject: [PATCH] wifi: cfg80211: move DFS related members to links[] in
 | 
			
		||||
 wireless_dev
 | 
			
		||||
 | 
			
		||||
A few members related to DFS handling are currently under per wireless
 | 
			
		||||
device data structure. However, in order to support DFS with MLO, there is
 | 
			
		||||
a need to have them on a per-link manner.
 | 
			
		||||
 | 
			
		||||
Hence, as a preliminary step, move members cac_started, cac_start_time
 | 
			
		||||
and cac_time_ms to be on a per-link basis.
 | 
			
		||||
 | 
			
		||||
Since currently, link ID is not known at all places, use default value of
 | 
			
		||||
0 for now.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
 | 
			
		||||
Link: https://patch.msgid.link/20240906064426.2101315-5-quic_adisi@quicinc.com
 | 
			
		||||
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
 | 
			
		||||
---
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/wireless/marvell/mwifiex/11h.c
 | 
			
		||||
+++ b/drivers/net/wireless/marvell/mwifiex/11h.c
 | 
			
		||||
@@ -117,7 +117,7 @@ void mwifiex_dfs_cac_work_queue(struct w
 | 
			
		||||
 				     dfs_cac_work);
 | 
			
		||||
 
 | 
			
		||||
 	chandef = priv->dfs_chandef;
 | 
			
		||||
-	if (priv->wdev.cac_started) {
 | 
			
		||||
+	if (priv->wdev.links[0].cac_started) {
 | 
			
		||||
 		mwifiex_dbg(priv->adapter, MSG,
 | 
			
		||||
 			    "CAC timer finished; No radar detected\n");
 | 
			
		||||
 		cfg80211_cac_event(priv->netdev, &chandef,
 | 
			
		||||
@@ -174,7 +174,7 @@ int mwifiex_stop_radar_detection(struct
 | 
			
		||||
  */
 | 
			
		||||
 void mwifiex_abort_cac(struct mwifiex_private *priv)
 | 
			
		||||
 {
 | 
			
		||||
-	if (priv->wdev.cac_started) {
 | 
			
		||||
+	if (priv->wdev.links[0].cac_started) {
 | 
			
		||||
 		if (mwifiex_stop_radar_detection(priv, &priv->dfs_chandef))
 | 
			
		||||
 			mwifiex_dbg(priv->adapter, ERROR,
 | 
			
		||||
 				    "failed to stop CAC in FW\n");
 | 
			
		||||
--- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c
 | 
			
		||||
+++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
 | 
			
		||||
@@ -1880,7 +1880,7 @@ mwifiex_cfg80211_del_station(struct wiph
 | 
			
		||||
 	struct mwifiex_sta_node *sta_node;
 | 
			
		||||
 	u8 deauth_mac[ETH_ALEN];
 | 
			
		||||
 
 | 
			
		||||
-	if (!priv->bss_started && priv->wdev.cac_started) {
 | 
			
		||||
+	if (!priv->bss_started && priv->wdev.links[0].cac_started) {
 | 
			
		||||
 		mwifiex_dbg(priv->adapter, INFO, "%s: abort CAC!\n", __func__);
 | 
			
		||||
 		mwifiex_abort_cac(priv);
 | 
			
		||||
 	}
 | 
			
		||||
@@ -3978,7 +3978,7 @@ mwifiex_cfg80211_channel_switch(struct w
 | 
			
		||||
 		return -EBUSY;
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
-	if (priv->wdev.cac_started)
 | 
			
		||||
+	if (priv->wdev.links[0].cac_started)
 | 
			
		||||
 		return -EBUSY;
 | 
			
		||||
 
 | 
			
		||||
 	if (cfg80211_chandef_identical(¶ms->chandef,
 | 
			
		||||
--- a/drivers/net/wireless/quantenna/qtnfmac/event.c
 | 
			
		||||
+++ b/drivers/net/wireless/quantenna/qtnfmac/event.c
 | 
			
		||||
@@ -520,21 +520,21 @@ static int qtnf_event_handle_radar(struc
 | 
			
		||||
 		cfg80211_radar_event(wiphy, &chandef, GFP_KERNEL);
 | 
			
		||||
 		break;
 | 
			
		||||
 	case QLINK_RADAR_CAC_FINISHED:
 | 
			
		||||
-		if (!vif->wdev.cac_started)
 | 
			
		||||
+		if (!vif->wdev.links[0].cac_started)
 | 
			
		||||
 			break;
 | 
			
		||||
 
 | 
			
		||||
 		cfg80211_cac_event(vif->netdev, &chandef,
 | 
			
		||||
 				   NL80211_RADAR_CAC_FINISHED, GFP_KERNEL);
 | 
			
		||||
 		break;
 | 
			
		||||
 	case QLINK_RADAR_CAC_ABORTED:
 | 
			
		||||
-		if (!vif->wdev.cac_started)
 | 
			
		||||
+		if (!vif->wdev.links[0].cac_started)
 | 
			
		||||
 			break;
 | 
			
		||||
 
 | 
			
		||||
 		cfg80211_cac_event(vif->netdev, &chandef,
 | 
			
		||||
 				   NL80211_RADAR_CAC_ABORTED, GFP_KERNEL);
 | 
			
		||||
 		break;
 | 
			
		||||
 	case QLINK_RADAR_CAC_STARTED:
 | 
			
		||||
-		if (vif->wdev.cac_started)
 | 
			
		||||
+		if (vif->wdev.links[0].cac_started)
 | 
			
		||||
 			break;
 | 
			
		||||
 
 | 
			
		||||
 		if (!wiphy_ext_feature_isset(wiphy,
 | 
			
		||||
--- a/include/net/cfg80211.h
 | 
			
		||||
+++ b/include/net/cfg80211.h
 | 
			
		||||
@@ -6198,9 +6198,6 @@ enum ieee80211_ap_reg_power {
 | 
			
		||||
  * @address: The address for this device, valid only if @netdev is %NULL
 | 
			
		||||
  * @is_running: true if this is a non-netdev device that has been started, e.g.
 | 
			
		||||
  *	the P2P Device.
 | 
			
		||||
- * @cac_started: true if DFS channel availability check has been started
 | 
			
		||||
- * @cac_start_time: timestamp (jiffies) when the dfs state was entered.
 | 
			
		||||
- * @cac_time_ms: CAC time in ms
 | 
			
		||||
  * @ps: powersave mode is enabled
 | 
			
		||||
  * @ps_timeout: dynamic powersave timeout
 | 
			
		||||
  * @ap_unexpected_nlportid: (private) netlink port ID of application
 | 
			
		||||
@@ -6224,6 +6221,11 @@ enum ieee80211_ap_reg_power {
 | 
			
		||||
  *	unprotected beacon report
 | 
			
		||||
  * @links: array of %IEEE80211_MLD_MAX_NUM_LINKS elements containing @addr
 | 
			
		||||
  *	@ap and @client for each link
 | 
			
		||||
+ * @links[].cac_started: true if DFS channel availability check has been
 | 
			
		||||
+ *	started
 | 
			
		||||
+ * @links[].cac_start_time: timestamp (jiffies) when the dfs state was
 | 
			
		||||
+ *	entered.
 | 
			
		||||
+ * @links[].cac_time_ms: CAC time in ms
 | 
			
		||||
  * @valid_links: bitmap describing what elements of @links are valid
 | 
			
		||||
  */
 | 
			
		||||
 struct wireless_dev {
 | 
			
		||||
@@ -6265,11 +6267,6 @@ struct wireless_dev {
 | 
			
		||||
 	u32 owner_nlportid;
 | 
			
		||||
 	bool nl_owner_dead;
 | 
			
		||||
 
 | 
			
		||||
-	/* FIXME: need to rework radar detection for MLO */
 | 
			
		||||
-	bool cac_started;
 | 
			
		||||
-	unsigned long cac_start_time;
 | 
			
		||||
-	unsigned int cac_time_ms;
 | 
			
		||||
-
 | 
			
		||||
 #ifdef CPTCFG_CFG80211_WEXT
 | 
			
		||||
 	/* wext data */
 | 
			
		||||
 	struct {
 | 
			
		||||
@@ -6336,6 +6333,10 @@ struct wireless_dev {
 | 
			
		||||
 				struct cfg80211_internal_bss *current_bss;
 | 
			
		||||
 			} client;
 | 
			
		||||
 		};
 | 
			
		||||
+
 | 
			
		||||
+		bool cac_started;
 | 
			
		||||
+		unsigned long cac_start_time;
 | 
			
		||||
+		unsigned int cac_time_ms;
 | 
			
		||||
 	} links[IEEE80211_MLD_MAX_NUM_LINKS];
 | 
			
		||||
 	u16 valid_links;
 | 
			
		||||
 };
 | 
			
		||||
--- a/net/mac80211/cfg.c
 | 
			
		||||
+++ b/net/mac80211/cfg.c
 | 
			
		||||
@@ -1656,7 +1656,7 @@ static int ieee80211_stop_ap(struct wiph
 | 
			
		||||
 	ieee80211_link_info_change_notify(sdata, link,
 | 
			
		||||
 					  BSS_CHANGED_BEACON_ENABLED);
 | 
			
		||||
 
 | 
			
		||||
-	if (sdata->wdev.cac_started) {
 | 
			
		||||
+	if (sdata->wdev.links[0].cac_started) {
 | 
			
		||||
 		chandef = link_conf->chanreq.oper;
 | 
			
		||||
 		wiphy_delayed_work_cancel(wiphy, &link->dfs_cac_timer_work);
 | 
			
		||||
 		cfg80211_cac_event(sdata->dev, &chandef,
 | 
			
		||||
@@ -3498,9 +3498,9 @@ static void ieee80211_end_cac(struct wip
 | 
			
		||||
 		wiphy_delayed_work_cancel(wiphy,
 | 
			
		||||
 					  &sdata->deflink.dfs_cac_timer_work);
 | 
			
		||||
 
 | 
			
		||||
-		if (sdata->wdev.cac_started) {
 | 
			
		||||
+		if (sdata->wdev.links[0].cac_started) {
 | 
			
		||||
 			ieee80211_link_release_channel(&sdata->deflink);
 | 
			
		||||
-			sdata->wdev.cac_started = false;
 | 
			
		||||
+			sdata->wdev.links[0].cac_started = false;
 | 
			
		||||
 		}
 | 
			
		||||
 	}
 | 
			
		||||
 }
 | 
			
		||||
@@ -3955,7 +3955,7 @@ __ieee80211_channel_switch(struct wiphy
 | 
			
		||||
 	if (!list_empty(&local->roc_list) || local->scanning)
 | 
			
		||||
 		return -EBUSY;
 | 
			
		||||
 
 | 
			
		||||
-	if (sdata->wdev.cac_started)
 | 
			
		||||
+	if (sdata->wdev.links[0].cac_started)
 | 
			
		||||
 		return -EBUSY;
 | 
			
		||||
 
 | 
			
		||||
 	if (WARN_ON(link_id >= IEEE80211_MLD_MAX_NUM_LINKS))
 | 
			
		||||
--- a/net/mac80211/iface.c
 | 
			
		||||
+++ b/net/mac80211/iface.c
 | 
			
		||||
@@ -553,7 +553,7 @@ static void ieee80211_do_stop(struct iee
 | 
			
		||||
 	wiphy_delayed_work_cancel(local->hw.wiphy,
 | 
			
		||||
 				  &sdata->deflink.dfs_cac_timer_work);
 | 
			
		||||
 
 | 
			
		||||
-	if (sdata->wdev.cac_started) {
 | 
			
		||||
+	if (sdata->wdev.links[0].cac_started) {
 | 
			
		||||
 		chandef = sdata->vif.bss_conf.chanreq.oper;
 | 
			
		||||
 		WARN_ON(local->suspended);
 | 
			
		||||
 		ieee80211_link_release_channel(&sdata->deflink);
 | 
			
		||||
--- a/net/mac80211/mlme.c
 | 
			
		||||
+++ b/net/mac80211/mlme.c
 | 
			
		||||
@@ -3039,7 +3039,7 @@ void ieee80211_dfs_cac_timer_work(struct
 | 
			
		||||
 
 | 
			
		||||
 	lockdep_assert_wiphy(sdata->local->hw.wiphy);
 | 
			
		||||
 
 | 
			
		||||
-	if (sdata->wdev.cac_started) {
 | 
			
		||||
+	if (sdata->wdev.links[0].cac_started) {
 | 
			
		||||
 		ieee80211_link_release_channel(link);
 | 
			
		||||
 		cfg80211_cac_event(sdata->dev, &chandef,
 | 
			
		||||
 				   NL80211_RADAR_CAC_FINISHED,
 | 
			
		||||
--- a/net/mac80211/scan.c
 | 
			
		||||
+++ b/net/mac80211/scan.c
 | 
			
		||||
@@ -585,7 +585,7 @@ static bool __ieee80211_can_leave_ch(str
 | 
			
		||||
 		return false;
 | 
			
		||||
 
 | 
			
		||||
 	list_for_each_entry(sdata_iter, &local->interfaces, list) {
 | 
			
		||||
-		if (sdata_iter->wdev.cac_started)
 | 
			
		||||
+		if (sdata_iter->wdev.links[0].cac_started)
 | 
			
		||||
 			return false;
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
--- a/net/mac80211/util.c
 | 
			
		||||
+++ b/net/mac80211/util.c
 | 
			
		||||
@@ -3462,7 +3462,7 @@ void ieee80211_dfs_cac_cancel(struct iee
 | 
			
		||||
 		wiphy_delayed_work_cancel(local->hw.wiphy,
 | 
			
		||||
 					  &sdata->deflink.dfs_cac_timer_work);
 | 
			
		||||
 
 | 
			
		||||
-		if (sdata->wdev.cac_started) {
 | 
			
		||||
+		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,
 | 
			
		||||
--- a/net/wireless/ibss.c
 | 
			
		||||
+++ b/net/wireless/ibss.c
 | 
			
		||||
@@ -94,7 +94,7 @@ int __cfg80211_join_ibss(struct cfg80211
 | 
			
		||||
 
 | 
			
		||||
 	lockdep_assert_held(&rdev->wiphy.mtx);
 | 
			
		||||
 
 | 
			
		||||
-	if (wdev->cac_started)
 | 
			
		||||
+	if (wdev->links[0].cac_started)
 | 
			
		||||
 		return -EBUSY;
 | 
			
		||||
 
 | 
			
		||||
 	if (wdev->u.ibss.ssid_len)
 | 
			
		||||
--- a/net/wireless/mesh.c
 | 
			
		||||
+++ b/net/wireless/mesh.c
 | 
			
		||||
@@ -127,7 +127,7 @@ int __cfg80211_join_mesh(struct cfg80211
 | 
			
		||||
 	if (!rdev->ops->join_mesh)
 | 
			
		||||
 		return -EOPNOTSUPP;
 | 
			
		||||
 
 | 
			
		||||
-	if (wdev->cac_started)
 | 
			
		||||
+	if (wdev->links[0].cac_started)
 | 
			
		||||
 		return -EBUSY;
 | 
			
		||||
 
 | 
			
		||||
 	if (!setup->chandef.chan) {
 | 
			
		||||
--- a/net/wireless/mlme.c
 | 
			
		||||
+++ b/net/wireless/mlme.c
 | 
			
		||||
@@ -1124,13 +1124,14 @@ void cfg80211_cac_event(struct net_devic
 | 
			
		||||
 
 | 
			
		||||
 	trace_cfg80211_cac_event(netdev, event);
 | 
			
		||||
 
 | 
			
		||||
-	if (WARN_ON(!wdev->cac_started && event != NL80211_RADAR_CAC_STARTED))
 | 
			
		||||
+	if (WARN_ON(!wdev->links[0].cac_started &&
 | 
			
		||||
+		    event != NL80211_RADAR_CAC_STARTED))
 | 
			
		||||
 		return;
 | 
			
		||||
 
 | 
			
		||||
 	switch (event) {
 | 
			
		||||
 	case NL80211_RADAR_CAC_FINISHED:
 | 
			
		||||
-		timeout = wdev->cac_start_time +
 | 
			
		||||
-			  msecs_to_jiffies(wdev->cac_time_ms);
 | 
			
		||||
+		timeout = wdev->links[0].cac_start_time +
 | 
			
		||||
+			  msecs_to_jiffies(wdev->links[0].cac_time_ms);
 | 
			
		||||
 		WARN_ON(!time_after_eq(jiffies, timeout));
 | 
			
		||||
 		cfg80211_set_dfs_state(wiphy, chandef, NL80211_DFS_AVAILABLE);
 | 
			
		||||
 		memcpy(&rdev->cac_done_chandef, chandef,
 | 
			
		||||
@@ -1139,10 +1140,10 @@ void cfg80211_cac_event(struct net_devic
 | 
			
		||||
 		cfg80211_sched_dfs_chan_update(rdev);
 | 
			
		||||
 		fallthrough;
 | 
			
		||||
 	case NL80211_RADAR_CAC_ABORTED:
 | 
			
		||||
-		wdev->cac_started = false;
 | 
			
		||||
+		wdev->links[0].cac_started = false;
 | 
			
		||||
 		break;
 | 
			
		||||
 	case NL80211_RADAR_CAC_STARTED:
 | 
			
		||||
-		wdev->cac_started = true;
 | 
			
		||||
+		wdev->links[0].cac_started = true;
 | 
			
		||||
 		break;
 | 
			
		||||
 	default:
 | 
			
		||||
 		WARN_ON(1);
 | 
			
		||||
--- a/net/wireless/nl80211.c
 | 
			
		||||
+++ b/net/wireless/nl80211.c
 | 
			
		||||
@@ -6066,7 +6066,7 @@ static int nl80211_start_ap(struct sk_bu
 | 
			
		||||
 	if (!rdev->ops->start_ap)
 | 
			
		||||
 		return -EOPNOTSUPP;
 | 
			
		||||
 
 | 
			
		||||
-	if (wdev->cac_started)
 | 
			
		||||
+	if (wdev->links[0].cac_started)
 | 
			
		||||
 		return -EBUSY;
 | 
			
		||||
 
 | 
			
		||||
 	if (wdev->links[link_id].ap.beacon_interval)
 | 
			
		||||
@@ -10122,7 +10122,7 @@ static int nl80211_start_radar_detection
 | 
			
		||||
 		goto unlock;
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
-	if (cfg80211_beaconing_iface_active(wdev) || wdev->cac_started) {
 | 
			
		||||
+	if (cfg80211_beaconing_iface_active(wdev) || wdev->links[0].cac_started) {
 | 
			
		||||
 		err = -EBUSY;
 | 
			
		||||
 		goto unlock;
 | 
			
		||||
 	}
 | 
			
		||||
@@ -10158,9 +10158,9 @@ static int nl80211_start_radar_detection
 | 
			
		||||
 		default:
 | 
			
		||||
 			break;
 | 
			
		||||
 		}
 | 
			
		||||
-		wdev->cac_started = true;
 | 
			
		||||
-		wdev->cac_start_time = jiffies;
 | 
			
		||||
-		wdev->cac_time_ms = cac_time_ms;
 | 
			
		||||
+		wdev->links[0].cac_started = true;
 | 
			
		||||
+		wdev->links[0].cac_start_time = jiffies;
 | 
			
		||||
+		wdev->links[0].cac_time_ms = cac_time_ms;
 | 
			
		||||
 	}
 | 
			
		||||
 unlock:
 | 
			
		||||
 	wiphy_unlock(wiphy);
 | 
			
		||||
--- a/net/wireless/reg.c
 | 
			
		||||
+++ b/net/wireless/reg.c
 | 
			
		||||
@@ -4241,7 +4241,7 @@ static void cfg80211_check_and_end_cac(s
 | 
			
		||||
 	list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
 | 
			
		||||
 		struct cfg80211_chan_def *chandef;
 | 
			
		||||
 
 | 
			
		||||
-		if (!wdev->cac_started)
 | 
			
		||||
+		if (!wdev->links[0].cac_started)
 | 
			
		||||
 			continue;
 | 
			
		||||
 
 | 
			
		||||
 		/* FIXME: radar detection is tied to link 0 for now */
 | 
			
		||||
@@ -0,0 +1,435 @@
 | 
			
		||||
From: Aditya Kumar Singh <quic_adisi@quicinc.com>
 | 
			
		||||
Date: Fri, 6 Sep 2024 12:14:23 +0530
 | 
			
		||||
Subject: [PATCH] wifi: cfg80211: handle DFS per link
 | 
			
		||||
 | 
			
		||||
Currently, during starting a radar detection, no link id information is
 | 
			
		||||
parsed and passed down. In order to support starting radar detection
 | 
			
		||||
during Multi Link Operation, it is required to pass link id as well.
 | 
			
		||||
 | 
			
		||||
Add changes to first parse and then pass link id in the start radar
 | 
			
		||||
detection path.
 | 
			
		||||
 | 
			
		||||
Additionally, update notification APIs to allow drivers/mac80211 to
 | 
			
		||||
pass the link ID.
 | 
			
		||||
 | 
			
		||||
However, everything is handled at link 0 only until all API's are ready to
 | 
			
		||||
handle it per link.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
 | 
			
		||||
Link: https://patch.msgid.link/20240906064426.2101315-6-quic_adisi@quicinc.com
 | 
			
		||||
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
 | 
			
		||||
---
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/wireless/marvell/mwifiex/11h.c
 | 
			
		||||
+++ b/drivers/net/wireless/marvell/mwifiex/11h.c
 | 
			
		||||
@@ -122,7 +122,7 @@ void mwifiex_dfs_cac_work_queue(struct w
 | 
			
		||||
 			    "CAC timer finished; No radar detected\n");
 | 
			
		||||
 		cfg80211_cac_event(priv->netdev, &chandef,
 | 
			
		||||
 				   NL80211_RADAR_CAC_FINISHED,
 | 
			
		||||
-				   GFP_KERNEL);
 | 
			
		||||
+				   GFP_KERNEL, 0);
 | 
			
		||||
 	}
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
@@ -182,7 +182,8 @@ void mwifiex_abort_cac(struct mwifiex_pr
 | 
			
		||||
 			    "Aborting delayed work for CAC.\n");
 | 
			
		||||
 		cancel_delayed_work_sync(&priv->dfs_cac_work);
 | 
			
		||||
 		cfg80211_cac_event(priv->netdev, &priv->dfs_chandef,
 | 
			
		||||
-				   NL80211_RADAR_CAC_ABORTED, GFP_KERNEL);
 | 
			
		||||
+				   NL80211_RADAR_CAC_ABORTED, GFP_KERNEL,
 | 
			
		||||
+				   0);
 | 
			
		||||
 	}
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
@@ -221,7 +222,7 @@ int mwifiex_11h_handle_chanrpt_ready(str
 | 
			
		||||
 				cfg80211_cac_event(priv->netdev,
 | 
			
		||||
 						   &priv->dfs_chandef,
 | 
			
		||||
 						   NL80211_RADAR_DETECTED,
 | 
			
		||||
-						   GFP_KERNEL);
 | 
			
		||||
+						   GFP_KERNEL, 0);
 | 
			
		||||
 			}
 | 
			
		||||
 			break;
 | 
			
		||||
 		default:
 | 
			
		||||
--- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c
 | 
			
		||||
+++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
 | 
			
		||||
@@ -4145,7 +4145,7 @@ static int
 | 
			
		||||
 mwifiex_cfg80211_start_radar_detection(struct wiphy *wiphy,
 | 
			
		||||
 				       struct net_device *dev,
 | 
			
		||||
 				       struct cfg80211_chan_def *chandef,
 | 
			
		||||
-				       u32 cac_time_ms)
 | 
			
		||||
+				       u32 cac_time_ms, int link_id)
 | 
			
		||||
 {
 | 
			
		||||
 	struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
 | 
			
		||||
 	struct mwifiex_radar_params radar_params;
 | 
			
		||||
--- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
 | 
			
		||||
+++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
 | 
			
		||||
@@ -837,7 +837,7 @@ static int qtnf_channel_switch(struct wi
 | 
			
		||||
 static int qtnf_start_radar_detection(struct wiphy *wiphy,
 | 
			
		||||
 				      struct net_device *ndev,
 | 
			
		||||
 				      struct cfg80211_chan_def *chandef,
 | 
			
		||||
-				      u32 cac_time_ms)
 | 
			
		||||
+				      u32 cac_time_ms, int link_id)
 | 
			
		||||
 {
 | 
			
		||||
 	struct qtnf_vif *vif = qtnf_netdev_get_priv(ndev);
 | 
			
		||||
 	int ret;
 | 
			
		||||
--- a/drivers/net/wireless/quantenna/qtnfmac/event.c
 | 
			
		||||
+++ b/drivers/net/wireless/quantenna/qtnfmac/event.c
 | 
			
		||||
@@ -524,14 +524,14 @@ static int qtnf_event_handle_radar(struc
 | 
			
		||||
 			break;
 | 
			
		||||
 
 | 
			
		||||
 		cfg80211_cac_event(vif->netdev, &chandef,
 | 
			
		||||
-				   NL80211_RADAR_CAC_FINISHED, GFP_KERNEL);
 | 
			
		||||
+				   NL80211_RADAR_CAC_FINISHED, GFP_KERNEL, 0);
 | 
			
		||||
 		break;
 | 
			
		||||
 	case QLINK_RADAR_CAC_ABORTED:
 | 
			
		||||
 		if (!vif->wdev.links[0].cac_started)
 | 
			
		||||
 			break;
 | 
			
		||||
 
 | 
			
		||||
 		cfg80211_cac_event(vif->netdev, &chandef,
 | 
			
		||||
-				   NL80211_RADAR_CAC_ABORTED, GFP_KERNEL);
 | 
			
		||||
+				   NL80211_RADAR_CAC_ABORTED, GFP_KERNEL, 0);
 | 
			
		||||
 		break;
 | 
			
		||||
 	case QLINK_RADAR_CAC_STARTED:
 | 
			
		||||
 		if (vif->wdev.links[0].cac_started)
 | 
			
		||||
@@ -542,7 +542,7 @@ static int qtnf_event_handle_radar(struc
 | 
			
		||||
 			break;
 | 
			
		||||
 
 | 
			
		||||
 		cfg80211_cac_event(vif->netdev, &chandef,
 | 
			
		||||
-				   NL80211_RADAR_CAC_STARTED, GFP_KERNEL);
 | 
			
		||||
+				   NL80211_RADAR_CAC_STARTED, GFP_KERNEL, 0);
 | 
			
		||||
 		break;
 | 
			
		||||
 	default:
 | 
			
		||||
 		pr_warn("%s: unhandled radar event %u\n",
 | 
			
		||||
--- a/include/net/cfg80211.h
 | 
			
		||||
+++ b/include/net/cfg80211.h
 | 
			
		||||
@@ -4841,9 +4841,9 @@ struct cfg80211_ops {
 | 
			
		||||
 	int	(*start_radar_detection)(struct wiphy *wiphy,
 | 
			
		||||
 					 struct net_device *dev,
 | 
			
		||||
 					 struct cfg80211_chan_def *chandef,
 | 
			
		||||
-					 u32 cac_time_ms);
 | 
			
		||||
+					 u32 cac_time_ms, int link_id);
 | 
			
		||||
 	void	(*end_cac)(struct wiphy *wiphy,
 | 
			
		||||
-				struct net_device *dev);
 | 
			
		||||
+			   struct net_device *dev, unsigned int link_id);
 | 
			
		||||
 	int	(*update_ft_ies)(struct wiphy *wiphy, struct net_device *dev,
 | 
			
		||||
 				 struct cfg80211_update_ft_ies_params *ftie);
 | 
			
		||||
 	int	(*crit_proto_start)(struct wiphy *wiphy,
 | 
			
		||||
@@ -8745,6 +8745,7 @@ void cfg80211_sta_opmode_change_notify(s
 | 
			
		||||
  * @chandef: chandef for the current channel
 | 
			
		||||
  * @event: type of event
 | 
			
		||||
  * @gfp: context flags
 | 
			
		||||
+ * @link_id: valid link_id for MLO operation or 0 otherwise.
 | 
			
		||||
  *
 | 
			
		||||
  * This function is called when a Channel availability check (CAC) is finished
 | 
			
		||||
  * or aborted. This must be called to notify the completion of a CAC process,
 | 
			
		||||
@@ -8752,7 +8753,8 @@ void cfg80211_sta_opmode_change_notify(s
 | 
			
		||||
  */
 | 
			
		||||
 void cfg80211_cac_event(struct net_device *netdev,
 | 
			
		||||
 			const struct cfg80211_chan_def *chandef,
 | 
			
		||||
-			enum nl80211_radar_event event, gfp_t gfp);
 | 
			
		||||
+			enum nl80211_radar_event event, gfp_t gfp,
 | 
			
		||||
+			unsigned int link_id);
 | 
			
		||||
 
 | 
			
		||||
 /**
 | 
			
		||||
  * cfg80211_background_cac_abort - Channel Availability Check offchan abort event
 | 
			
		||||
--- a/net/mac80211/cfg.c
 | 
			
		||||
+++ b/net/mac80211/cfg.c
 | 
			
		||||
@@ -1661,7 +1661,7 @@ static int ieee80211_stop_ap(struct wiph
 | 
			
		||||
 		wiphy_delayed_work_cancel(wiphy, &link->dfs_cac_timer_work);
 | 
			
		||||
 		cfg80211_cac_event(sdata->dev, &chandef,
 | 
			
		||||
 				   NL80211_RADAR_CAC_ABORTED,
 | 
			
		||||
-				   GFP_KERNEL);
 | 
			
		||||
+				   GFP_KERNEL, 0);
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
 	drv_stop_ap(sdata->local, sdata, link_conf);
 | 
			
		||||
@@ -3459,7 +3459,7 @@ static int ieee80211_set_bitrate_mask(st
 | 
			
		||||
 static int ieee80211_start_radar_detection(struct wiphy *wiphy,
 | 
			
		||||
 					   struct net_device *dev,
 | 
			
		||||
 					   struct cfg80211_chan_def *chandef,
 | 
			
		||||
-					   u32 cac_time_ms)
 | 
			
		||||
+					   u32 cac_time_ms, int link_id)
 | 
			
		||||
 {
 | 
			
		||||
 	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 | 
			
		||||
 	struct ieee80211_chan_req chanreq = { .oper = *chandef };
 | 
			
		||||
@@ -3487,7 +3487,7 @@ static int ieee80211_start_radar_detecti
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
 static void ieee80211_end_cac(struct wiphy *wiphy,
 | 
			
		||||
-			      struct net_device *dev)
 | 
			
		||||
+			      struct net_device *dev, unsigned int link_id)
 | 
			
		||||
 {
 | 
			
		||||
 	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 | 
			
		||||
 	struct ieee80211_local *local = sdata->local;
 | 
			
		||||
--- a/net/mac80211/iface.c
 | 
			
		||||
+++ b/net/mac80211/iface.c
 | 
			
		||||
@@ -559,7 +559,7 @@ static void ieee80211_do_stop(struct iee
 | 
			
		||||
 		ieee80211_link_release_channel(&sdata->deflink);
 | 
			
		||||
 		cfg80211_cac_event(sdata->dev, &chandef,
 | 
			
		||||
 				   NL80211_RADAR_CAC_ABORTED,
 | 
			
		||||
-				   GFP_KERNEL);
 | 
			
		||||
+				   GFP_KERNEL, 0);
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
 	if (sdata->vif.type == NL80211_IFTYPE_AP) {
 | 
			
		||||
--- a/net/mac80211/mlme.c
 | 
			
		||||
+++ b/net/mac80211/mlme.c
 | 
			
		||||
@@ -3043,7 +3043,7 @@ void ieee80211_dfs_cac_timer_work(struct
 | 
			
		||||
 		ieee80211_link_release_channel(link);
 | 
			
		||||
 		cfg80211_cac_event(sdata->dev, &chandef,
 | 
			
		||||
 				   NL80211_RADAR_CAC_FINISHED,
 | 
			
		||||
-				   GFP_KERNEL);
 | 
			
		||||
+				   GFP_KERNEL, 0);
 | 
			
		||||
 	}
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
--- a/net/mac80211/util.c
 | 
			
		||||
+++ b/net/mac80211/util.c
 | 
			
		||||
@@ -3468,7 +3468,7 @@ void ieee80211_dfs_cac_cancel(struct iee
 | 
			
		||||
 			cfg80211_cac_event(sdata->dev,
 | 
			
		||||
 					   &chandef,
 | 
			
		||||
 					   NL80211_RADAR_CAC_ABORTED,
 | 
			
		||||
-					   GFP_KERNEL);
 | 
			
		||||
+					   GFP_KERNEL, 0);
 | 
			
		||||
 		}
 | 
			
		||||
 	}
 | 
			
		||||
 }
 | 
			
		||||
--- a/net/wireless/mlme.c
 | 
			
		||||
+++ b/net/wireless/mlme.c
 | 
			
		||||
@@ -1111,18 +1111,19 @@ EXPORT_SYMBOL(__cfg80211_radar_event);
 | 
			
		||||
 
 | 
			
		||||
 void cfg80211_cac_event(struct net_device *netdev,
 | 
			
		||||
 			const struct cfg80211_chan_def *chandef,
 | 
			
		||||
-			enum nl80211_radar_event event, gfp_t gfp)
 | 
			
		||||
+			enum nl80211_radar_event event, gfp_t gfp,
 | 
			
		||||
+			unsigned int link_id)
 | 
			
		||||
 {
 | 
			
		||||
 	struct wireless_dev *wdev = netdev->ieee80211_ptr;
 | 
			
		||||
 	struct wiphy *wiphy = wdev->wiphy;
 | 
			
		||||
 	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
 | 
			
		||||
 	unsigned long timeout;
 | 
			
		||||
 
 | 
			
		||||
-	/* not yet supported */
 | 
			
		||||
-	if (wdev->valid_links)
 | 
			
		||||
+	if (WARN_ON(wdev->valid_links &&
 | 
			
		||||
+		    !(wdev->valid_links & BIT(link_id))))
 | 
			
		||||
 		return;
 | 
			
		||||
 
 | 
			
		||||
-	trace_cfg80211_cac_event(netdev, event);
 | 
			
		||||
+	trace_cfg80211_cac_event(netdev, event, link_id);
 | 
			
		||||
 
 | 
			
		||||
 	if (WARN_ON(!wdev->links[0].cac_started &&
 | 
			
		||||
 		    event != NL80211_RADAR_CAC_STARTED))
 | 
			
		||||
--- a/net/wireless/nl80211.c
 | 
			
		||||
+++ b/net/wireless/nl80211.c
 | 
			
		||||
@@ -10122,7 +10122,20 @@ static int nl80211_start_radar_detection
 | 
			
		||||
 		goto unlock;
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
-	if (cfg80211_beaconing_iface_active(wdev) || wdev->links[0].cac_started) {
 | 
			
		||||
+	if (cfg80211_beaconing_iface_active(wdev)) {
 | 
			
		||||
+		/* During MLO other link(s) can beacon, only the current link
 | 
			
		||||
+		 * can not already beacon
 | 
			
		||||
+		 */
 | 
			
		||||
+		if (wdev->valid_links &&
 | 
			
		||||
+		    !wdev->links[0].ap.beacon_interval) {
 | 
			
		||||
+			/* nothing */
 | 
			
		||||
+		} else {
 | 
			
		||||
+			err = -EBUSY;
 | 
			
		||||
+			goto unlock;
 | 
			
		||||
+		}
 | 
			
		||||
+	}
 | 
			
		||||
+
 | 
			
		||||
+	if (wdev->links[0].cac_started) {
 | 
			
		||||
 		err = -EBUSY;
 | 
			
		||||
 		goto unlock;
 | 
			
		||||
 	}
 | 
			
		||||
@@ -10142,7 +10155,8 @@ static int nl80211_start_radar_detection
 | 
			
		||||
 	if (WARN_ON(!cac_time_ms))
 | 
			
		||||
 		cac_time_ms = IEEE80211_DFS_MIN_CAC_TIME_MS;
 | 
			
		||||
 
 | 
			
		||||
-	err = rdev_start_radar_detection(rdev, dev, &chandef, cac_time_ms);
 | 
			
		||||
+	err = rdev_start_radar_detection(rdev, dev, &chandef, cac_time_ms,
 | 
			
		||||
+					 0);
 | 
			
		||||
 	if (!err) {
 | 
			
		||||
 		switch (wdev->iftype) {
 | 
			
		||||
 		case NL80211_IFTYPE_AP:
 | 
			
		||||
@@ -16512,10 +16526,10 @@ nl80211_set_ttlm(struct sk_buff *skb, st
 | 
			
		||||
 	SELECTOR(__sel, NETDEV_UP_NOTMX,		\
 | 
			
		||||
 		 NL80211_FLAG_NEED_NETDEV_UP |		\
 | 
			
		||||
 		 NL80211_FLAG_NO_WIPHY_MTX)		\
 | 
			
		||||
-	SELECTOR(__sel, NETDEV_UP_NOTMX_NOMLO,		\
 | 
			
		||||
+	SELECTOR(__sel, NETDEV_UP_NOTMX_MLO,		\
 | 
			
		||||
 		 NL80211_FLAG_NEED_NETDEV_UP |		\
 | 
			
		||||
 		 NL80211_FLAG_NO_WIPHY_MTX |		\
 | 
			
		||||
-		 NL80211_FLAG_MLO_UNSUPPORTED)		\
 | 
			
		||||
+		 NL80211_FLAG_MLO_VALID_LINK_ID)	\
 | 
			
		||||
 	SELECTOR(__sel, NETDEV_UP_CLEAR,		\
 | 
			
		||||
 		 NL80211_FLAG_NEED_NETDEV_UP |		\
 | 
			
		||||
 		 NL80211_FLAG_CLEAR_SKB)		\
 | 
			
		||||
@@ -17410,7 +17424,7 @@ static const struct genl_small_ops nl802
 | 
			
		||||
 		.flags = GENL_UNS_ADMIN_PERM,
 | 
			
		||||
 		.internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
 | 
			
		||||
 					 NL80211_FLAG_NO_WIPHY_MTX |
 | 
			
		||||
-					 NL80211_FLAG_MLO_UNSUPPORTED),
 | 
			
		||||
+					 NL80211_FLAG_MLO_VALID_LINK_ID),
 | 
			
		||||
 	},
 | 
			
		||||
 	{
 | 
			
		||||
 		.cmd = NL80211_CMD_GET_PROTOCOL_FEATURES,
 | 
			
		||||
--- a/net/wireless/rdev-ops.h
 | 
			
		||||
+++ b/net/wireless/rdev-ops.h
 | 
			
		||||
@@ -1200,26 +1200,27 @@ static inline int
 | 
			
		||||
 rdev_start_radar_detection(struct cfg80211_registered_device *rdev,
 | 
			
		||||
 			   struct net_device *dev,
 | 
			
		||||
 			   struct cfg80211_chan_def *chandef,
 | 
			
		||||
-			   u32 cac_time_ms)
 | 
			
		||||
+			   u32 cac_time_ms, int link_id)
 | 
			
		||||
 {
 | 
			
		||||
 	int ret = -EOPNOTSUPP;
 | 
			
		||||
 
 | 
			
		||||
 	trace_rdev_start_radar_detection(&rdev->wiphy, dev, chandef,
 | 
			
		||||
-					 cac_time_ms);
 | 
			
		||||
+					 cac_time_ms, link_id);
 | 
			
		||||
 	if (rdev->ops->start_radar_detection)
 | 
			
		||||
 		ret = rdev->ops->start_radar_detection(&rdev->wiphy, dev,
 | 
			
		||||
-						       chandef, cac_time_ms);
 | 
			
		||||
+						       chandef, cac_time_ms,
 | 
			
		||||
+						       link_id);
 | 
			
		||||
 	trace_rdev_return_int(&rdev->wiphy, ret);
 | 
			
		||||
 	return ret;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
 static inline void
 | 
			
		||||
 rdev_end_cac(struct cfg80211_registered_device *rdev,
 | 
			
		||||
-	     struct net_device *dev)
 | 
			
		||||
+	     struct net_device *dev, unsigned int link_id)
 | 
			
		||||
 {
 | 
			
		||||
-	trace_rdev_end_cac(&rdev->wiphy, dev);
 | 
			
		||||
+	trace_rdev_end_cac(&rdev->wiphy, dev, link_id);
 | 
			
		||||
 	if (rdev->ops->end_cac)
 | 
			
		||||
-		rdev->ops->end_cac(&rdev->wiphy, dev);
 | 
			
		||||
+		rdev->ops->end_cac(&rdev->wiphy, dev, link_id);
 | 
			
		||||
 	trace_rdev_return_void(&rdev->wiphy);
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
--- a/net/wireless/reg.c
 | 
			
		||||
+++ b/net/wireless/reg.c
 | 
			
		||||
@@ -4229,6 +4229,8 @@ EXPORT_SYMBOL(regulatory_pre_cac_allowed
 | 
			
		||||
 static void cfg80211_check_and_end_cac(struct cfg80211_registered_device *rdev)
 | 
			
		||||
 {
 | 
			
		||||
 	struct wireless_dev *wdev;
 | 
			
		||||
+	unsigned int link_id;
 | 
			
		||||
+
 | 
			
		||||
 	/* If we finished CAC or received radar, we should end any
 | 
			
		||||
 	 * CAC running on the same channels.
 | 
			
		||||
 	 * the check !cfg80211_chandef_dfs_usable contain 2 options:
 | 
			
		||||
@@ -4241,16 +4243,17 @@ static void cfg80211_check_and_end_cac(s
 | 
			
		||||
 	list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
 | 
			
		||||
 		struct cfg80211_chan_def *chandef;
 | 
			
		||||
 
 | 
			
		||||
-		if (!wdev->links[0].cac_started)
 | 
			
		||||
-			continue;
 | 
			
		||||
+		for_each_valid_link(wdev, link_id) {
 | 
			
		||||
+			if (!wdev->links[link_id].cac_started)
 | 
			
		||||
+				continue;
 | 
			
		||||
 
 | 
			
		||||
-		/* FIXME: radar detection is tied to link 0 for now */
 | 
			
		||||
-		chandef = wdev_chandef(wdev, 0);
 | 
			
		||||
-		if (!chandef)
 | 
			
		||||
-			continue;
 | 
			
		||||
+			chandef = wdev_chandef(wdev, link_id);
 | 
			
		||||
+			if (!chandef)
 | 
			
		||||
+				continue;
 | 
			
		||||
 
 | 
			
		||||
-		if (!cfg80211_chandef_dfs_usable(&rdev->wiphy, chandef))
 | 
			
		||||
-			rdev_end_cac(rdev, wdev->netdev);
 | 
			
		||||
+			if (!cfg80211_chandef_dfs_usable(&rdev->wiphy, chandef))
 | 
			
		||||
+				rdev_end_cac(rdev, wdev->netdev, link_id);
 | 
			
		||||
+		}
 | 
			
		||||
 	}
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
--- a/net/wireless/trace.h
 | 
			
		||||
+++ b/net/wireless/trace.h
 | 
			
		||||
@@ -806,17 +806,21 @@ DEFINE_EVENT(wiphy_netdev_evt, rdev_flus
 | 
			
		||||
 );
 | 
			
		||||
 
 | 
			
		||||
 TRACE_EVENT(rdev_end_cac,
 | 
			
		||||
-	TP_PROTO(struct wiphy *wiphy, struct net_device *netdev),
 | 
			
		||||
-	TP_ARGS(wiphy, netdev),
 | 
			
		||||
+	TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
 | 
			
		||||
+		 unsigned int link_id),
 | 
			
		||||
+	TP_ARGS(wiphy, netdev, link_id),
 | 
			
		||||
 	TP_STRUCT__entry(
 | 
			
		||||
 		WIPHY_ENTRY
 | 
			
		||||
 		NETDEV_ENTRY
 | 
			
		||||
+		__field(unsigned int, link_id)
 | 
			
		||||
 	),
 | 
			
		||||
 	TP_fast_assign(
 | 
			
		||||
 		WIPHY_ASSIGN;
 | 
			
		||||
 		NETDEV_ASSIGN;
 | 
			
		||||
+		__entry->link_id = link_id;
 | 
			
		||||
 	),
 | 
			
		||||
-	TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT, WIPHY_PR_ARG, NETDEV_PR_ARG)
 | 
			
		||||
+	TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", link_id: %d",
 | 
			
		||||
+		  WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->link_id)
 | 
			
		||||
 );
 | 
			
		||||
 
 | 
			
		||||
 DECLARE_EVENT_CLASS(station_add_change,
 | 
			
		||||
@@ -2661,24 +2665,26 @@ TRACE_EVENT(rdev_external_auth,
 | 
			
		||||
 TRACE_EVENT(rdev_start_radar_detection,
 | 
			
		||||
 	TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
 | 
			
		||||
 		 struct cfg80211_chan_def *chandef,
 | 
			
		||||
-		 u32 cac_time_ms),
 | 
			
		||||
-	TP_ARGS(wiphy, netdev, chandef, cac_time_ms),
 | 
			
		||||
+		 u32 cac_time_ms, int link_id),
 | 
			
		||||
+	TP_ARGS(wiphy, netdev, chandef, cac_time_ms, link_id),
 | 
			
		||||
 	TP_STRUCT__entry(
 | 
			
		||||
 		WIPHY_ENTRY
 | 
			
		||||
 		NETDEV_ENTRY
 | 
			
		||||
 		CHAN_DEF_ENTRY
 | 
			
		||||
 		__field(u32, cac_time_ms)
 | 
			
		||||
+		__field(int, link_id)
 | 
			
		||||
 	),
 | 
			
		||||
 	TP_fast_assign(
 | 
			
		||||
 		WIPHY_ASSIGN;
 | 
			
		||||
 		NETDEV_ASSIGN;
 | 
			
		||||
 		CHAN_DEF_ASSIGN(chandef);
 | 
			
		||||
 		__entry->cac_time_ms = cac_time_ms;
 | 
			
		||||
+		__entry->link_id = link_id;
 | 
			
		||||
 	),
 | 
			
		||||
 	TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", " CHAN_DEF_PR_FMT
 | 
			
		||||
-		  ", cac_time_ms=%u",
 | 
			
		||||
+		  ", cac_time_ms=%u, link_id=%d",
 | 
			
		||||
 		  WIPHY_PR_ARG, NETDEV_PR_ARG, CHAN_DEF_PR_ARG,
 | 
			
		||||
-		  __entry->cac_time_ms)
 | 
			
		||||
+		  __entry->cac_time_ms, __entry->link_id)
 | 
			
		||||
 );
 | 
			
		||||
 
 | 
			
		||||
 TRACE_EVENT(rdev_set_mcast_rate,
 | 
			
		||||
@@ -3492,18 +3498,21 @@ TRACE_EVENT(cfg80211_radar_event,
 | 
			
		||||
 );
 | 
			
		||||
 
 | 
			
		||||
 TRACE_EVENT(cfg80211_cac_event,
 | 
			
		||||
-	TP_PROTO(struct net_device *netdev, enum nl80211_radar_event evt),
 | 
			
		||||
-	TP_ARGS(netdev, evt),
 | 
			
		||||
+	TP_PROTO(struct net_device *netdev, enum nl80211_radar_event evt,
 | 
			
		||||
+		 unsigned int link_id),
 | 
			
		||||
+	TP_ARGS(netdev, evt, link_id),
 | 
			
		||||
 	TP_STRUCT__entry(
 | 
			
		||||
 		NETDEV_ENTRY
 | 
			
		||||
 		__field(enum nl80211_radar_event, evt)
 | 
			
		||||
+		__field(unsigned int, link_id)
 | 
			
		||||
 	),
 | 
			
		||||
 	TP_fast_assign(
 | 
			
		||||
 		NETDEV_ASSIGN;
 | 
			
		||||
 		__entry->evt = evt;
 | 
			
		||||
+		__entry->link_id = link_id;
 | 
			
		||||
 	),
 | 
			
		||||
-	TP_printk(NETDEV_PR_FMT ",  event: %d",
 | 
			
		||||
-		  NETDEV_PR_ARG, __entry->evt)
 | 
			
		||||
+	TP_printk(NETDEV_PR_FMT ",  event: %d, link_id=%u",
 | 
			
		||||
+		  NETDEV_PR_ARG, __entry->evt, __entry->link_id)
 | 
			
		||||
 );
 | 
			
		||||
 
 | 
			
		||||
 DECLARE_EVENT_CLASS(cfg80211_rx_evt,
 | 
			
		||||
@@ -0,0 +1,134 @@
 | 
			
		||||
From: Aditya Kumar Singh <quic_adisi@quicinc.com>
 | 
			
		||||
Date: Fri, 6 Sep 2024 12:14:24 +0530
 | 
			
		||||
Subject: [PATCH] wifi: mac80211: handle DFS per link
 | 
			
		||||
 | 
			
		||||
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>
 | 
			
		||||
---
 | 
			
		||||
 | 
			
		||||
--- a/net/mac80211/cfg.c
 | 
			
		||||
+++ b/net/mac80211/cfg.c
 | 
			
		||||
@@ -3464,6 +3464,7 @@ static int ieee80211_start_radar_detecti
 | 
			
		||||
 	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_detecti
 | 
			
		||||
 	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 wip
 | 
			
		||||
 {
 | 
			
		||||
 	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;
 | 
			
		||||
 		}
 | 
			
		||||
 	}
 | 
			
		||||
 }
 | 
			
		||||
--- a/net/mac80211/link.c
 | 
			
		||||
+++ b/net/mac80211/link.c
 | 
			
		||||
@@ -77,6 +77,16 @@ void ieee80211_link_stop(struct ieee8021
 | 
			
		||||
 			  &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);
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
--- a/net/mac80211/util.c
 | 
			
		||||
+++ b/net/mac80211/util.c
 | 
			
		||||
@@ -3455,20 +3455,30 @@ void ieee80211_dfs_cac_cancel(struct iee
 | 
			
		||||
 {
 | 
			
		||||
 	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);
 | 
			
		||||
+		for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS;
 | 
			
		||||
+		     link_id++) {
 | 
			
		||||
+			link = sdata_dereference(sdata->link[link_id],
 | 
			
		||||
+						 sdata);
 | 
			
		||||
+			if (!link)
 | 
			
		||||
+				continue;
 | 
			
		||||
 
 | 
			
		||||
-		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,
 | 
			
		||||
+			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);
 | 
			
		||||
 		}
 | 
			
		||||
 	}
 | 
			
		||||
 }
 | 
			
		||||
@@ -0,0 +1,168 @@
 | 
			
		||||
From: Aditya Kumar Singh <quic_adisi@quicinc.com>
 | 
			
		||||
Date: Fri, 6 Sep 2024 12:14:25 +0530
 | 
			
		||||
Subject: [PATCH] wifi: cfg80211/mac80211: use proper link ID for DFS
 | 
			
		||||
 | 
			
		||||
Now that all APIs have support to handle DFS per link, use proper link ID
 | 
			
		||||
instead of 0.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
 | 
			
		||||
Link: https://patch.msgid.link/20240906064426.2101315-8-quic_adisi@quicinc.com
 | 
			
		||||
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
 | 
			
		||||
---
 | 
			
		||||
 | 
			
		||||
--- a/net/mac80211/cfg.c
 | 
			
		||||
+++ b/net/mac80211/cfg.c
 | 
			
		||||
@@ -1656,12 +1656,12 @@ static int ieee80211_stop_ap(struct wiph
 | 
			
		||||
 	ieee80211_link_info_change_notify(sdata, link,
 | 
			
		||||
 					  BSS_CHANGED_BEACON_ENABLED);
 | 
			
		||||
 
 | 
			
		||||
-	if (sdata->wdev.links[0].cac_started) {
 | 
			
		||||
+	if (sdata->wdev.links[link_id].cac_started) {
 | 
			
		||||
 		chandef = link_conf->chanreq.oper;
 | 
			
		||||
 		wiphy_delayed_work_cancel(wiphy, &link->dfs_cac_timer_work);
 | 
			
		||||
 		cfg80211_cac_event(sdata->dev, &chandef,
 | 
			
		||||
 				   NL80211_RADAR_CAC_ABORTED,
 | 
			
		||||
-				   GFP_KERNEL, 0);
 | 
			
		||||
+				   GFP_KERNEL, link_id);
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
 	drv_stop_ap(sdata->local, sdata, link_conf);
 | 
			
		||||
@@ -3965,7 +3965,7 @@ __ieee80211_channel_switch(struct wiphy
 | 
			
		||||
 	if (!list_empty(&local->roc_list) || local->scanning)
 | 
			
		||||
 		return -EBUSY;
 | 
			
		||||
 
 | 
			
		||||
-	if (sdata->wdev.links[0].cac_started)
 | 
			
		||||
+	if (sdata->wdev.links[link_id].cac_started)
 | 
			
		||||
 		return -EBUSY;
 | 
			
		||||
 
 | 
			
		||||
 	if (WARN_ON(link_id >= IEEE80211_MLD_MAX_NUM_LINKS))
 | 
			
		||||
--- a/net/mac80211/mlme.c
 | 
			
		||||
+++ b/net/mac80211/mlme.c
 | 
			
		||||
@@ -3039,11 +3039,11 @@ void ieee80211_dfs_cac_timer_work(struct
 | 
			
		||||
 
 | 
			
		||||
 	lockdep_assert_wiphy(sdata->local->hw.wiphy);
 | 
			
		||||
 
 | 
			
		||||
-	if (sdata->wdev.links[0].cac_started) {
 | 
			
		||||
+	if (sdata->wdev.links[link->link_id].cac_started) {
 | 
			
		||||
 		ieee80211_link_release_channel(link);
 | 
			
		||||
 		cfg80211_cac_event(sdata->dev, &chandef,
 | 
			
		||||
 				   NL80211_RADAR_CAC_FINISHED,
 | 
			
		||||
-				   GFP_KERNEL, 0);
 | 
			
		||||
+				   GFP_KERNEL, link->link_id);
 | 
			
		||||
 	}
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
--- a/net/mac80211/scan.c
 | 
			
		||||
+++ b/net/mac80211/scan.c
 | 
			
		||||
@@ -575,6 +575,7 @@ static bool __ieee80211_can_leave_ch(str
 | 
			
		||||
 {
 | 
			
		||||
 	struct ieee80211_local *local = sdata->local;
 | 
			
		||||
 	struct ieee80211_sub_if_data *sdata_iter;
 | 
			
		||||
+	unsigned int link_id;
 | 
			
		||||
 
 | 
			
		||||
 	lockdep_assert_wiphy(local->hw.wiphy);
 | 
			
		||||
 
 | 
			
		||||
@@ -585,8 +586,9 @@ static bool __ieee80211_can_leave_ch(str
 | 
			
		||||
 		return false;
 | 
			
		||||
 
 | 
			
		||||
 	list_for_each_entry(sdata_iter, &local->interfaces, list) {
 | 
			
		||||
-		if (sdata_iter->wdev.links[0].cac_started)
 | 
			
		||||
-			return false;
 | 
			
		||||
+		for_each_valid_link(&sdata_iter->wdev, link_id)
 | 
			
		||||
+			if (sdata_iter->wdev.links[link_id].cac_started)
 | 
			
		||||
+				return false;
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
 	return true;
 | 
			
		||||
--- a/net/wireless/mlme.c
 | 
			
		||||
+++ b/net/wireless/mlme.c
 | 
			
		||||
@@ -1125,14 +1125,14 @@ void cfg80211_cac_event(struct net_devic
 | 
			
		||||
 
 | 
			
		||||
 	trace_cfg80211_cac_event(netdev, event, link_id);
 | 
			
		||||
 
 | 
			
		||||
-	if (WARN_ON(!wdev->links[0].cac_started &&
 | 
			
		||||
+	if (WARN_ON(!wdev->links[link_id].cac_started &&
 | 
			
		||||
 		    event != NL80211_RADAR_CAC_STARTED))
 | 
			
		||||
 		return;
 | 
			
		||||
 
 | 
			
		||||
 	switch (event) {
 | 
			
		||||
 	case NL80211_RADAR_CAC_FINISHED:
 | 
			
		||||
-		timeout = wdev->links[0].cac_start_time +
 | 
			
		||||
-			  msecs_to_jiffies(wdev->links[0].cac_time_ms);
 | 
			
		||||
+		timeout = wdev->links[link_id].cac_start_time +
 | 
			
		||||
+			  msecs_to_jiffies(wdev->links[link_id].cac_time_ms);
 | 
			
		||||
 		WARN_ON(!time_after_eq(jiffies, timeout));
 | 
			
		||||
 		cfg80211_set_dfs_state(wiphy, chandef, NL80211_DFS_AVAILABLE);
 | 
			
		||||
 		memcpy(&rdev->cac_done_chandef, chandef,
 | 
			
		||||
@@ -1141,10 +1141,10 @@ void cfg80211_cac_event(struct net_devic
 | 
			
		||||
 		cfg80211_sched_dfs_chan_update(rdev);
 | 
			
		||||
 		fallthrough;
 | 
			
		||||
 	case NL80211_RADAR_CAC_ABORTED:
 | 
			
		||||
-		wdev->links[0].cac_started = false;
 | 
			
		||||
+		wdev->links[link_id].cac_started = false;
 | 
			
		||||
 		break;
 | 
			
		||||
 	case NL80211_RADAR_CAC_STARTED:
 | 
			
		||||
-		wdev->links[0].cac_started = true;
 | 
			
		||||
+		wdev->links[link_id].cac_started = true;
 | 
			
		||||
 		break;
 | 
			
		||||
 	default:
 | 
			
		||||
 		WARN_ON(1);
 | 
			
		||||
--- a/net/wireless/nl80211.c
 | 
			
		||||
+++ b/net/wireless/nl80211.c
 | 
			
		||||
@@ -6066,7 +6066,7 @@ static int nl80211_start_ap(struct sk_bu
 | 
			
		||||
 	if (!rdev->ops->start_ap)
 | 
			
		||||
 		return -EOPNOTSUPP;
 | 
			
		||||
 
 | 
			
		||||
-	if (wdev->links[0].cac_started)
 | 
			
		||||
+	if (wdev->links[link_id].cac_started)
 | 
			
		||||
 		return -EBUSY;
 | 
			
		||||
 
 | 
			
		||||
 	if (wdev->links[link_id].ap.beacon_interval)
 | 
			
		||||
@@ -10073,6 +10073,7 @@ static int nl80211_start_radar_detection
 | 
			
		||||
 	struct cfg80211_registered_device *rdev = info->user_ptr[0];
 | 
			
		||||
 	struct net_device *dev = info->user_ptr[1];
 | 
			
		||||
 	struct wireless_dev *wdev = dev->ieee80211_ptr;
 | 
			
		||||
+	int link_id = nl80211_link_id(info->attrs);
 | 
			
		||||
 	struct wiphy *wiphy = wdev->wiphy;
 | 
			
		||||
 	struct cfg80211_chan_def chandef;
 | 
			
		||||
 	enum nl80211_dfs_regions dfs_region;
 | 
			
		||||
@@ -10127,7 +10128,7 @@ static int nl80211_start_radar_detection
 | 
			
		||||
 		 * can not already beacon
 | 
			
		||||
 		 */
 | 
			
		||||
 		if (wdev->valid_links &&
 | 
			
		||||
-		    !wdev->links[0].ap.beacon_interval) {
 | 
			
		||||
+		    !wdev->links[link_id].ap.beacon_interval) {
 | 
			
		||||
 			/* nothing */
 | 
			
		||||
 		} else {
 | 
			
		||||
 			err = -EBUSY;
 | 
			
		||||
@@ -10135,7 +10136,7 @@ static int nl80211_start_radar_detection
 | 
			
		||||
 		}
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
-	if (wdev->links[0].cac_started) {
 | 
			
		||||
+	if (wdev->links[link_id].cac_started) {
 | 
			
		||||
 		err = -EBUSY;
 | 
			
		||||
 		goto unlock;
 | 
			
		||||
 	}
 | 
			
		||||
@@ -10156,7 +10157,7 @@ static int nl80211_start_radar_detection
 | 
			
		||||
 		cac_time_ms = IEEE80211_DFS_MIN_CAC_TIME_MS;
 | 
			
		||||
 
 | 
			
		||||
 	err = rdev_start_radar_detection(rdev, dev, &chandef, cac_time_ms,
 | 
			
		||||
-					 0);
 | 
			
		||||
+					 link_id);
 | 
			
		||||
 	if (!err) {
 | 
			
		||||
 		switch (wdev->iftype) {
 | 
			
		||||
 		case NL80211_IFTYPE_AP:
 | 
			
		||||
@@ -10172,9 +10173,9 @@ static int nl80211_start_radar_detection
 | 
			
		||||
 		default:
 | 
			
		||||
 			break;
 | 
			
		||||
 		}
 | 
			
		||||
-		wdev->links[0].cac_started = true;
 | 
			
		||||
-		wdev->links[0].cac_start_time = jiffies;
 | 
			
		||||
-		wdev->links[0].cac_time_ms = cac_time_ms;
 | 
			
		||||
+		wdev->links[link_id].cac_started = true;
 | 
			
		||||
+		wdev->links[link_id].cac_start_time = jiffies;
 | 
			
		||||
+		wdev->links[link_id].cac_time_ms = cac_time_ms;
 | 
			
		||||
 	}
 | 
			
		||||
 unlock:
 | 
			
		||||
 	wiphy_unlock(wiphy);
 | 
			
		||||
@@ -0,0 +1,360 @@
 | 
			
		||||
From: Aditya Kumar Singh <quic_adisi@quicinc.com>
 | 
			
		||||
Date: Fri, 6 Sep 2024 12:14:26 +0530
 | 
			
		||||
Subject: [PATCH] wifi: mac80211: handle ieee80211_radar_detected() for MLO
 | 
			
		||||
 | 
			
		||||
Currently DFS works under assumption there could be only one channel
 | 
			
		||||
context in the hardware. Hence, drivers just calls the function
 | 
			
		||||
ieee80211_radar_detected() passing the hardware structure. However, with
 | 
			
		||||
MLO, this obviously will not work since number of channel contexts will be
 | 
			
		||||
more than one and hence drivers would need to pass the channel information
 | 
			
		||||
as well on which the radar is detected.
 | 
			
		||||
 | 
			
		||||
Also, when radar is detected in one of the links, other link's CAC should
 | 
			
		||||
not be cancelled.
 | 
			
		||||
 | 
			
		||||
Hence, in order to support DFS with MLO, do the following changes -
 | 
			
		||||
  * Add channel context conf pointer as an argument to the function
 | 
			
		||||
    ieee80211_radar_detected(). During MLO, drivers would have to pass on
 | 
			
		||||
    which channel context conf radar is detected. Otherwise, drivers could
 | 
			
		||||
    just pass NULL.
 | 
			
		||||
  * ieee80211_radar_detected() will iterate over all channel contexts
 | 
			
		||||
    present and
 | 
			
		||||
  	* if channel context conf is passed, only mark that as radar
 | 
			
		||||
  	  detected
 | 
			
		||||
  	* if NULL is passed, then mark all channel contexts as radar
 | 
			
		||||
  	  detected
 | 
			
		||||
  	* Then as usual, schedule the radar detected work.
 | 
			
		||||
  * In the worker, go over all the contexts again and for all such context
 | 
			
		||||
    which is marked with radar detected, cancel the ongoing CAC by calling
 | 
			
		||||
    ieee80211_dfs_cac_cancel() and then notify cfg80211 via
 | 
			
		||||
    cfg80211_radar_event().
 | 
			
		||||
  * To cancel the CAC, pass the channel context as well where radar is
 | 
			
		||||
    detected to ieee80211_dfs_cac_cancel(). This ensures that CAC is
 | 
			
		||||
    canceled only on the links using the provided context, leaving other
 | 
			
		||||
    links unaffected.
 | 
			
		||||
 | 
			
		||||
This would also help in scenarios where there is split phy 5 GHz radio,
 | 
			
		||||
which is capable of DFS channels in both lower and upper band. In this
 | 
			
		||||
case, simultaneous radars can be detected.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
 | 
			
		||||
Link: https://patch.msgid.link/20240906064426.2101315-9-quic_adisi@quicinc.com
 | 
			
		||||
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
 | 
			
		||||
---
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/wireless/ath/ath10k/debug.c
 | 
			
		||||
+++ b/drivers/net/wireless/ath/ath10k/debug.c
 | 
			
		||||
@@ -3,7 +3,7 @@
 | 
			
		||||
  * Copyright (c) 2005-2011 Atheros Communications Inc.
 | 
			
		||||
  * Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
 | 
			
		||||
  * Copyright (c) 2018, The Linux Foundation. All rights reserved.
 | 
			
		||||
- * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
 | 
			
		||||
+ * Copyright (c) 2022, 2024 Qualcomm Innovation Center, Inc. All rights reserved.
 | 
			
		||||
  */
 | 
			
		||||
 
 | 
			
		||||
 #include <linux/module.h>
 | 
			
		||||
@@ -1774,7 +1774,7 @@ static ssize_t ath10k_write_simulate_rad
 | 
			
		||||
 	if (!arvif->is_started)
 | 
			
		||||
 		return -EINVAL;
 | 
			
		||||
 
 | 
			
		||||
-	ieee80211_radar_detected(ar->hw);
 | 
			
		||||
+	ieee80211_radar_detected(ar->hw, NULL);
 | 
			
		||||
 
 | 
			
		||||
 	return count;
 | 
			
		||||
 }
 | 
			
		||||
--- a/drivers/net/wireless/ath/ath10k/mac.c
 | 
			
		||||
+++ b/drivers/net/wireless/ath/ath10k/mac.c
 | 
			
		||||
@@ -1437,7 +1437,7 @@ static void ath10k_recalc_radar_detectio
 | 
			
		||||
 		 * by indicating that radar was detected.
 | 
			
		||||
 		 */
 | 
			
		||||
 		ath10k_warn(ar, "failed to start CAC: %d\n", ret);
 | 
			
		||||
-		ieee80211_radar_detected(ar->hw);
 | 
			
		||||
+		ieee80211_radar_detected(ar->hw, NULL);
 | 
			
		||||
 	}
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
--- a/drivers/net/wireless/ath/ath10k/wmi.c
 | 
			
		||||
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
 | 
			
		||||
@@ -3990,7 +3990,7 @@ static void ath10k_radar_detected(struct
 | 
			
		||||
 	if (ar->dfs_block_radar_events)
 | 
			
		||||
 		ath10k_info(ar, "DFS Radar detected, but ignored as requested\n");
 | 
			
		||||
 	else
 | 
			
		||||
-		ieee80211_radar_detected(ar->hw);
 | 
			
		||||
+		ieee80211_radar_detected(ar->hw, NULL);
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
 static void ath10k_radar_confirmation_work(struct work_struct *work)
 | 
			
		||||
--- a/drivers/net/wireless/ath/ath11k/wmi.c
 | 
			
		||||
+++ b/drivers/net/wireless/ath/ath11k/wmi.c
 | 
			
		||||
@@ -8358,7 +8358,7 @@ ath11k_wmi_pdev_dfs_radar_detected_event
 | 
			
		||||
 	if (ar->dfs_block_radar_events)
 | 
			
		||||
 		ath11k_info(ab, "DFS Radar detected, but ignored as requested\n");
 | 
			
		||||
 	else
 | 
			
		||||
-		ieee80211_radar_detected(ar->hw);
 | 
			
		||||
+		ieee80211_radar_detected(ar->hw, NULL);
 | 
			
		||||
 
 | 
			
		||||
 exit:
 | 
			
		||||
 	rcu_read_unlock();
 | 
			
		||||
--- a/drivers/net/wireless/ath/ath12k/wmi.c
 | 
			
		||||
+++ b/drivers/net/wireless/ath/ath12k/wmi.c
 | 
			
		||||
@@ -6789,7 +6789,7 @@ ath12k_wmi_pdev_dfs_radar_detected_event
 | 
			
		||||
 	if (ar->dfs_block_radar_events)
 | 
			
		||||
 		ath12k_info(ab, "DFS Radar detected, but ignored as requested\n");
 | 
			
		||||
 	else
 | 
			
		||||
-		ieee80211_radar_detected(ath12k_ar_to_hw(ar));
 | 
			
		||||
+		ieee80211_radar_detected(ath12k_ar_to_hw(ar), NULL);
 | 
			
		||||
 
 | 
			
		||||
 exit:
 | 
			
		||||
 	rcu_read_unlock();
 | 
			
		||||
--- a/drivers/net/wireless/ath/ath9k/dfs.c
 | 
			
		||||
+++ b/drivers/net/wireless/ath/ath9k/dfs.c
 | 
			
		||||
@@ -280,7 +280,7 @@ ath9k_dfs_process_radar_pulse(struct ath
 | 
			
		||||
 	if (!pd->add_pulse(pd, pe, NULL))
 | 
			
		||||
 		return;
 | 
			
		||||
 	DFS_STAT_INC(sc, radar_detected);
 | 
			
		||||
-	ieee80211_radar_detected(sc->hw);
 | 
			
		||||
+	ieee80211_radar_detected(sc->hw, NULL);
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
 /*
 | 
			
		||||
--- a/drivers/net/wireless/ath/ath9k/dfs_debug.c
 | 
			
		||||
+++ b/drivers/net/wireless/ath/ath9k/dfs_debug.c
 | 
			
		||||
@@ -116,7 +116,7 @@ static ssize_t write_file_simulate_radar
 | 
			
		||||
 {
 | 
			
		||||
 	struct ath_softc *sc = file->private_data;
 | 
			
		||||
 
 | 
			
		||||
-	ieee80211_radar_detected(sc->hw);
 | 
			
		||||
+	ieee80211_radar_detected(sc->hw, NULL);
 | 
			
		||||
 
 | 
			
		||||
 	return count;
 | 
			
		||||
 }
 | 
			
		||||
--- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c
 | 
			
		||||
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c
 | 
			
		||||
@@ -394,7 +394,7 @@ mt7615_mcu_rx_radar_detected(struct mt76
 | 
			
		||||
 	if (mt76_phy_dfs_state(mphy) < MT_DFS_STATE_CAC)
 | 
			
		||||
 		return;
 | 
			
		||||
 
 | 
			
		||||
-	ieee80211_radar_detected(mphy->hw);
 | 
			
		||||
+	ieee80211_radar_detected(mphy->hw, NULL);
 | 
			
		||||
 	dev->hw_pattern++;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.c
 | 
			
		||||
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.c
 | 
			
		||||
@@ -630,7 +630,7 @@ static void mt76x02_dfs_tasklet(struct t
 | 
			
		||||
 		radar_detected = mt76x02_dfs_check_detection(dev);
 | 
			
		||||
 		if (radar_detected) {
 | 
			
		||||
 			/* sw detector rx radar pattern */
 | 
			
		||||
-			ieee80211_radar_detected(dev->mt76.hw);
 | 
			
		||||
+			ieee80211_radar_detected(dev->mt76.hw, NULL);
 | 
			
		||||
 			mt76x02_dfs_detector_reset(dev);
 | 
			
		||||
 
 | 
			
		||||
 			return;
 | 
			
		||||
@@ -658,7 +658,7 @@ static void mt76x02_dfs_tasklet(struct t
 | 
			
		||||
 
 | 
			
		||||
 		/* hw detector rx radar pattern */
 | 
			
		||||
 		dfs_pd->stats[i].hw_pattern++;
 | 
			
		||||
-		ieee80211_radar_detected(dev->mt76.hw);
 | 
			
		||||
+		ieee80211_radar_detected(dev->mt76.hw, NULL);
 | 
			
		||||
 		mt76x02_dfs_detector_reset(dev);
 | 
			
		||||
 
 | 
			
		||||
 		return;
 | 
			
		||||
--- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
 | 
			
		||||
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
 | 
			
		||||
@@ -293,7 +293,7 @@ mt7915_mcu_rx_radar_detected(struct mt79
 | 
			
		||||
 						&dev->rdd2_chandef,
 | 
			
		||||
 						GFP_ATOMIC);
 | 
			
		||||
 	else
 | 
			
		||||
-		ieee80211_radar_detected(mphy->hw);
 | 
			
		||||
+		ieee80211_radar_detected(mphy->hw, NULL);
 | 
			
		||||
 	dev->hw_pattern++;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
 | 
			
		||||
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
 | 
			
		||||
@@ -371,7 +371,7 @@ mt7996_mcu_rx_radar_detected(struct mt79
 | 
			
		||||
 						&dev->rdd2_chandef,
 | 
			
		||||
 						GFP_ATOMIC);
 | 
			
		||||
 	else
 | 
			
		||||
-		ieee80211_radar_detected(mphy->hw);
 | 
			
		||||
+		ieee80211_radar_detected(mphy->hw, NULL);
 | 
			
		||||
 	dev->hw_pattern++;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
--- a/drivers/net/wireless/ti/wl18xx/event.c
 | 
			
		||||
+++ b/drivers/net/wireless/ti/wl18xx/event.c
 | 
			
		||||
@@ -142,7 +142,7 @@ int wl18xx_process_mailbox_events(struct
 | 
			
		||||
 			    wl18xx_radar_type_decode(mbox->radar_type));
 | 
			
		||||
 
 | 
			
		||||
 		if (!wl->radar_debug_mode)
 | 
			
		||||
-			ieee80211_radar_detected(wl->hw);
 | 
			
		||||
+			ieee80211_radar_detected(wl->hw, NULL);
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
 	if (vector & PERIODIC_SCAN_REPORT_EVENT_ID) {
 | 
			
		||||
--- a/drivers/net/wireless/virtual/mac80211_hwsim.c
 | 
			
		||||
+++ b/drivers/net/wireless/virtual/mac80211_hwsim.c
 | 
			
		||||
@@ -1146,7 +1146,7 @@ static int hwsim_write_simulate_radar(vo
 | 
			
		||||
 {
 | 
			
		||||
 	struct mac80211_hwsim_data *data = dat;
 | 
			
		||||
 
 | 
			
		||||
-	ieee80211_radar_detected(data->hw);
 | 
			
		||||
+	ieee80211_radar_detected(data->hw, NULL);
 | 
			
		||||
 
 | 
			
		||||
 	return 0;
 | 
			
		||||
 }
 | 
			
		||||
--- a/include/net/mac80211.h
 | 
			
		||||
+++ b/include/net/mac80211.h
 | 
			
		||||
@@ -6717,8 +6717,11 @@ void ieee80211_cqm_beacon_loss_notify(st
 | 
			
		||||
  * ieee80211_radar_detected - inform that a radar was detected
 | 
			
		||||
  *
 | 
			
		||||
  * @hw: pointer as obtained from ieee80211_alloc_hw()
 | 
			
		||||
+ * @chanctx_conf: Channel context on which radar is detected. Mandatory to
 | 
			
		||||
+ *	pass a valid pointer during MLO. For non-MLO %NULL can be passed
 | 
			
		||||
  */
 | 
			
		||||
-void ieee80211_radar_detected(struct ieee80211_hw *hw);
 | 
			
		||||
+void ieee80211_radar_detected(struct ieee80211_hw *hw,
 | 
			
		||||
+			      struct ieee80211_chanctx_conf *chanctx_conf);
 | 
			
		||||
 
 | 
			
		||||
 /**
 | 
			
		||||
  * ieee80211_chswitch_done - Complete channel switch process
 | 
			
		||||
--- a/net/mac80211/chan.c
 | 
			
		||||
+++ b/net/mac80211/chan.c
 | 
			
		||||
@@ -681,6 +681,7 @@ ieee80211_alloc_chanctx(struct ieee80211
 | 
			
		||||
 	ctx->mode = mode;
 | 
			
		||||
 	ctx->conf.radar_enabled = false;
 | 
			
		||||
 	ctx->conf.radio_idx = radio_idx;
 | 
			
		||||
+	ctx->radar_detected = false;
 | 
			
		||||
 	_ieee80211_recalc_chanctx_min_def(local, ctx, NULL, false);
 | 
			
		||||
 
 | 
			
		||||
 	return ctx;
 | 
			
		||||
--- a/net/mac80211/ieee80211_i.h
 | 
			
		||||
+++ b/net/mac80211/ieee80211_i.h
 | 
			
		||||
@@ -895,6 +895,8 @@ struct ieee80211_chanctx {
 | 
			
		||||
 	struct ieee80211_chan_req req;
 | 
			
		||||
 
 | 
			
		||||
 	struct ieee80211_chanctx_conf conf;
 | 
			
		||||
+
 | 
			
		||||
+	bool radar_detected;
 | 
			
		||||
 };
 | 
			
		||||
 
 | 
			
		||||
 struct mac80211_qos_map {
 | 
			
		||||
@@ -2632,7 +2634,8 @@ void ieee80211_recalc_chanctx_min_def(st
 | 
			
		||||
 bool ieee80211_is_radar_required(struct ieee80211_local *local);
 | 
			
		||||
 
 | 
			
		||||
 void ieee80211_dfs_cac_timer_work(struct wiphy *wiphy, struct wiphy_work *work);
 | 
			
		||||
-void ieee80211_dfs_cac_cancel(struct ieee80211_local *local);
 | 
			
		||||
+void ieee80211_dfs_cac_cancel(struct ieee80211_local *local,
 | 
			
		||||
+			      struct ieee80211_chanctx *chanctx);
 | 
			
		||||
 void ieee80211_dfs_radar_detected_work(struct wiphy *wiphy,
 | 
			
		||||
 				       struct wiphy_work *work);
 | 
			
		||||
 int ieee80211_send_action_csa(struct ieee80211_sub_if_data *sdata,
 | 
			
		||||
--- a/net/mac80211/pm.c
 | 
			
		||||
+++ b/net/mac80211/pm.c
 | 
			
		||||
@@ -32,7 +32,7 @@ int __ieee80211_suspend(struct ieee80211
 | 
			
		||||
 
 | 
			
		||||
 	ieee80211_scan_cancel(local);
 | 
			
		||||
 
 | 
			
		||||
-	ieee80211_dfs_cac_cancel(local);
 | 
			
		||||
+	ieee80211_dfs_cac_cancel(local, NULL);
 | 
			
		||||
 
 | 
			
		||||
 	ieee80211_roc_purge(local, NULL);
 | 
			
		||||
 
 | 
			
		||||
--- a/net/mac80211/util.c
 | 
			
		||||
+++ b/net/mac80211/util.c
 | 
			
		||||
@@ -3451,11 +3451,16 @@ u64 ieee80211_calculate_rx_timestamp(str
 | 
			
		||||
 	return ts;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
-void ieee80211_dfs_cac_cancel(struct ieee80211_local *local)
 | 
			
		||||
+/* Cancel CAC for the interfaces under the specified @local. If @ctx is
 | 
			
		||||
+ * also provided, only the interfaces using that ctx will be canceled.
 | 
			
		||||
+ */
 | 
			
		||||
+void ieee80211_dfs_cac_cancel(struct ieee80211_local *local,
 | 
			
		||||
+			      struct ieee80211_chanctx *ctx)
 | 
			
		||||
 {
 | 
			
		||||
 	struct ieee80211_sub_if_data *sdata;
 | 
			
		||||
 	struct cfg80211_chan_def chandef;
 | 
			
		||||
 	struct ieee80211_link_data *link;
 | 
			
		||||
+	struct ieee80211_chanctx_conf *chanctx_conf;
 | 
			
		||||
 	unsigned int link_id;
 | 
			
		||||
 
 | 
			
		||||
 	lockdep_assert_wiphy(local->hw.wiphy);
 | 
			
		||||
@@ -3468,6 +3473,11 @@ void ieee80211_dfs_cac_cancel(struct iee
 | 
			
		||||
 			if (!link)
 | 
			
		||||
 				continue;
 | 
			
		||||
 
 | 
			
		||||
+			chanctx_conf = sdata_dereference(link->conf->chanctx_conf,
 | 
			
		||||
+							 sdata);
 | 
			
		||||
+			if (ctx && &ctx->conf != chanctx_conf)
 | 
			
		||||
+				continue;
 | 
			
		||||
+
 | 
			
		||||
 			wiphy_delayed_work_cancel(local->hw.wiphy,
 | 
			
		||||
 						  &link->dfs_cac_timer_work);
 | 
			
		||||
 
 | 
			
		||||
@@ -3488,9 +3498,8 @@ void ieee80211_dfs_radar_detected_work(s
 | 
			
		||||
 {
 | 
			
		||||
 	struct ieee80211_local *local =
 | 
			
		||||
 		container_of(work, struct ieee80211_local, radar_detected_work);
 | 
			
		||||
-	struct cfg80211_chan_def chandef = local->hw.conf.chandef;
 | 
			
		||||
+	struct cfg80211_chan_def chandef;
 | 
			
		||||
 	struct ieee80211_chanctx *ctx;
 | 
			
		||||
-	int num_chanctx = 0;
 | 
			
		||||
 
 | 
			
		||||
 	lockdep_assert_wiphy(local->hw.wiphy);
 | 
			
		||||
 
 | 
			
		||||
@@ -3498,25 +3507,46 @@ void ieee80211_dfs_radar_detected_work(s
 | 
			
		||||
 		if (ctx->replace_state == IEEE80211_CHANCTX_REPLACES_OTHER)
 | 
			
		||||
 			continue;
 | 
			
		||||
 
 | 
			
		||||
-		num_chanctx++;
 | 
			
		||||
+		if (!ctx->radar_detected)
 | 
			
		||||
+			continue;
 | 
			
		||||
+
 | 
			
		||||
+		ctx->radar_detected = false;
 | 
			
		||||
+
 | 
			
		||||
 		chandef = ctx->conf.def;
 | 
			
		||||
+
 | 
			
		||||
+		ieee80211_dfs_cac_cancel(local, ctx);
 | 
			
		||||
+		cfg80211_radar_event(local->hw.wiphy, &chandef, GFP_KERNEL);
 | 
			
		||||
 	}
 | 
			
		||||
+}
 | 
			
		||||
 
 | 
			
		||||
-	ieee80211_dfs_cac_cancel(local);
 | 
			
		||||
+static void
 | 
			
		||||
+ieee80211_radar_mark_chan_ctx_iterator(struct ieee80211_hw *hw,
 | 
			
		||||
+				       struct ieee80211_chanctx_conf *chanctx_conf,
 | 
			
		||||
+				       void *data)
 | 
			
		||||
+{
 | 
			
		||||
+	struct ieee80211_chanctx *ctx =
 | 
			
		||||
+		container_of(chanctx_conf, struct ieee80211_chanctx,
 | 
			
		||||
+			     conf);
 | 
			
		||||
 
 | 
			
		||||
-	if (num_chanctx > 1)
 | 
			
		||||
-		/* XXX: multi-channel is not supported yet */
 | 
			
		||||
-		WARN_ON(1);
 | 
			
		||||
-	else
 | 
			
		||||
-		cfg80211_radar_event(local->hw.wiphy, &chandef, GFP_KERNEL);
 | 
			
		||||
+	if (ctx->replace_state == IEEE80211_CHANCTX_REPLACES_OTHER)
 | 
			
		||||
+		return;
 | 
			
		||||
+
 | 
			
		||||
+	if (data && data != chanctx_conf)
 | 
			
		||||
+		return;
 | 
			
		||||
+
 | 
			
		||||
+	ctx->radar_detected = true;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
-void ieee80211_radar_detected(struct ieee80211_hw *hw)
 | 
			
		||||
+void ieee80211_radar_detected(struct ieee80211_hw *hw,
 | 
			
		||||
+			      struct ieee80211_chanctx_conf *chanctx_conf)
 | 
			
		||||
 {
 | 
			
		||||
 	struct ieee80211_local *local = hw_to_local(hw);
 | 
			
		||||
 
 | 
			
		||||
 	trace_api_radar_detected(local);
 | 
			
		||||
 
 | 
			
		||||
+	ieee80211_iter_chan_contexts_atomic(hw, ieee80211_radar_mark_chan_ctx_iterator,
 | 
			
		||||
+					    chanctx_conf);
 | 
			
		||||
+
 | 
			
		||||
 	wiphy_work_queue(hw->wiphy, &local->radar_detected_work);
 | 
			
		||||
 }
 | 
			
		||||
 EXPORT_SYMBOL(ieee80211_radar_detected);
 | 
			
		||||
@@ -9,3 +9,56 @@
 | 
			
		||||
 		head = &wcid->tx_offchannel;
 | 
			
		||||
 	else
 | 
			
		||||
 		head = &wcid->tx_pending;
 | 
			
		||||
--- a/mt7615/mcu.c
 | 
			
		||||
+++ b/mt7615/mcu.c
 | 
			
		||||
@@ -394,7 +394,7 @@ mt7615_mcu_rx_radar_detected(struct mt76
 | 
			
		||||
 	if (mt76_phy_dfs_state(mphy) < MT_DFS_STATE_CAC)
 | 
			
		||||
 		return;
 | 
			
		||||
 
 | 
			
		||||
-	ieee80211_radar_detected(mphy->hw);
 | 
			
		||||
+	ieee80211_radar_detected(mphy->hw, NULL);
 | 
			
		||||
 	dev->hw_pattern++;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
--- a/mt76x02_dfs.c
 | 
			
		||||
+++ b/mt76x02_dfs.c
 | 
			
		||||
@@ -630,7 +630,7 @@ static void mt76x02_dfs_tasklet(struct t
 | 
			
		||||
 		radar_detected = mt76x02_dfs_check_detection(dev);
 | 
			
		||||
 		if (radar_detected) {
 | 
			
		||||
 			/* sw detector rx radar pattern */
 | 
			
		||||
-			ieee80211_radar_detected(dev->mt76.hw);
 | 
			
		||||
+			ieee80211_radar_detected(dev->mt76.hw, NULL);
 | 
			
		||||
 			mt76x02_dfs_detector_reset(dev);
 | 
			
		||||
 
 | 
			
		||||
 			return;
 | 
			
		||||
@@ -658,7 +658,7 @@ static void mt76x02_dfs_tasklet(struct t
 | 
			
		||||
 
 | 
			
		||||
 		/* hw detector rx radar pattern */
 | 
			
		||||
 		dfs_pd->stats[i].hw_pattern++;
 | 
			
		||||
-		ieee80211_radar_detected(dev->mt76.hw);
 | 
			
		||||
+		ieee80211_radar_detected(dev->mt76.hw, NULL);
 | 
			
		||||
 		mt76x02_dfs_detector_reset(dev);
 | 
			
		||||
 
 | 
			
		||||
 		return;
 | 
			
		||||
--- a/mt7915/mcu.c
 | 
			
		||||
+++ b/mt7915/mcu.c
 | 
			
		||||
@@ -297,7 +297,7 @@ mt7915_mcu_rx_radar_detected(struct mt79
 | 
			
		||||
 						&dev->rdd2_chandef,
 | 
			
		||||
 						GFP_ATOMIC);
 | 
			
		||||
 	else
 | 
			
		||||
-		ieee80211_radar_detected(mphy->hw);
 | 
			
		||||
+		ieee80211_radar_detected(mphy->hw, NULL);
 | 
			
		||||
 	dev->hw_pattern++;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
--- a/mt7996/mcu.c
 | 
			
		||||
+++ b/mt7996/mcu.c
 | 
			
		||||
@@ -383,7 +383,7 @@ mt7996_mcu_rx_radar_detected(struct mt79
 | 
			
		||||
 						&dev->rdd2_chandef,
 | 
			
		||||
 						GFP_ATOMIC);
 | 
			
		||||
 	else
 | 
			
		||||
-		ieee80211_radar_detected(mphy->hw);
 | 
			
		||||
+		ieee80211_radar_detected(mphy->hw, NULL);
 | 
			
		||||
 	dev->hw_pattern++;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
 
 | 
			
		||||
@@ -68,6 +68,15 @@
 | 
			
		||||
 			sta->tdls,
 | 
			
		||||
 			sta->tdls_initiator,
 | 
			
		||||
 			sta->wme,
 | 
			
		||||
@@ -1158,7 +1158,7 @@ static ssize_t mwl_debugfs_dfs_radar_wri
 | 
			
		||||
 	struct mwl_priv *priv = (struct mwl_priv *)file->private_data;
 | 
			
		||||
 
 | 
			
		||||
 	wiphy_info(priv->hw->wiphy, "simulate radar detected\n");
 | 
			
		||||
-	ieee80211_radar_detected(priv->hw);
 | 
			
		||||
+	ieee80211_radar_detected(priv->hw, NULL);
 | 
			
		||||
 
 | 
			
		||||
 	return count;
 | 
			
		||||
 }
 | 
			
		||||
--- a/hif/fwcmd.c
 | 
			
		||||
+++ b/hif/fwcmd.c
 | 
			
		||||
@@ -633,11 +633,15 @@ einval:
 | 
			
		||||
@@ -491,3 +500,32 @@
 | 
			
		||||
 
 | 
			
		||||
 	switch (format) {
 | 
			
		||||
 	case TX_RATE_FORMAT_LEGACY:
 | 
			
		||||
--- a/hif/pcie/pcie.c
 | 
			
		||||
+++ b/hif/pcie/pcie.c
 | 
			
		||||
@@ -546,7 +546,7 @@ static irqreturn_t pcie_isr_8864(struct
 | 
			
		||||
 
 | 
			
		||||
 		if (int_status & MACREG_A2HRIC_BIT_RADAR_DETECT) {
 | 
			
		||||
 			wiphy_info(hw->wiphy, "radar detected by firmware\n");
 | 
			
		||||
-			ieee80211_radar_detected(hw);
 | 
			
		||||
+			ieee80211_radar_detected(hw, NULL);
 | 
			
		||||
 		}
 | 
			
		||||
 
 | 
			
		||||
 		if (int_status & MACREG_A2HRIC_BIT_CHAN_SWITCH) ieee80211_queue_work(hw, &priv->chnl_switch_handle);
 | 
			
		||||
@@ -593,7 +593,7 @@ static irqreturn_t pcie_isr_8997(struct
 | 
			
		||||
 
 | 
			
		||||
 		if (int_status & MACREG_A2HRIC_BIT_RADAR_DETECT) {
 | 
			
		||||
 			wiphy_info(hw->wiphy, "radar detected by firmware\n");
 | 
			
		||||
-			ieee80211_radar_detected(hw);
 | 
			
		||||
+			ieee80211_radar_detected(hw, NULL);
 | 
			
		||||
 		}
 | 
			
		||||
 
 | 
			
		||||
 		if (int_status & MACREG_A2HRIC_BIT_CHAN_SWITCH)
 | 
			
		||||
@@ -1071,7 +1071,7 @@ static irqreturn_t pcie_isr_ndp(struct i
 | 
			
		||||
 
 | 
			
		||||
 		if (int_status & MACREG_A2HRIC_NEWDP_DFS) {
 | 
			
		||||
 			wiphy_info(hw->wiphy, "radar detected by firmware\n");
 | 
			
		||||
-			ieee80211_radar_detected(hw);
 | 
			
		||||
+			ieee80211_radar_detected(hw, NULL);
 | 
			
		||||
 		}
 | 
			
		||||
 
 | 
			
		||||
 		if (int_status & MACREG_A2HRIC_NEWDP_CHANNEL_SWITCH)
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user