[][MAC80211][core][Add ZWDFS support for DFS commands]

[Description]
Add ZWDFS support for DFS commands

[Release-log]
N/A

Change-Id: I844257ed160c612239e61e32307838806ea45791
Reviewed-on: https://gerrit.mediatek.inc/c/openwrt/feeds/mtk_openwrt_feeds/+/6654906
Build: srv_hbgsm110
diff --git a/autobuild_mac80211_release/package/kernel/mac80211/patches/subsys/912-cfg80211-mtk-implement-DFS-status-show-cac-and-nop-skip-.patch b/autobuild_mac80211_release/package/kernel/mac80211/patches/subsys/912-cfg80211-mtk-implement-DFS-status-show-cac-and-nop-skip-.patch
index 904b7e0..d60e8d8 100644
--- a/autobuild_mac80211_release/package/kernel/mac80211/patches/subsys/912-cfg80211-mtk-implement-DFS-status-show-cac-and-nop-skip-.patch
+++ b/autobuild_mac80211_release/package/kernel/mac80211/patches/subsys/912-cfg80211-mtk-implement-DFS-status-show-cac-and-nop-skip-.patch
@@ -1,4 +1,4 @@
-From c9fc7a7b46040370d6f140749f141daa0964d0ba Mon Sep 17 00:00:00 2001
+From 3ff7c67f8b03762e096ed9ac6eaa5d9d6c80bb65 Mon Sep 17 00:00:00 2001
 From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
 Date: Thu, 22 Sep 2022 14:27:41 +0800
 Subject: [PATCH 912/914] cfg80211: implement DFS status show, cac and nop skip
@@ -6,21 +6,96 @@
 
 Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
 ---
- net/wireless/debugfs.c | 228 +++++++++++++++++++++++++++++++++++++++--
- 1 file changed, 221 insertions(+), 7 deletions(-)
+ include/net/cfg80211.h  |   1 +
+ net/mac80211/cfg.c      |  19 +++
+ net/wireless/core.h     |   3 +
+ net/wireless/debugfs.c  | 270 ++++++++++++++++++++++++++++++++++++++--
+ net/wireless/mlme.c     |   6 +
+ net/wireless/rdev-ops.h |  14 +++
+ net/wireless/trace.h    |  12 ++
+ 7 files changed, 318 insertions(+), 7 deletions(-)
 
+diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
+index f594914..7d20b98 100644
+--- a/include/net/cfg80211.h
++++ b/include/net/cfg80211.h
+@@ -4401,6 +4401,7 @@ struct cfg80211_ops {
+ 				struct cfg80211_color_change_settings *params);
+ 	int	(*set_radar_background)(struct wiphy *wiphy,
+ 					struct cfg80211_chan_def *chandef);
++	void	(*skip_cac)(struct wireless_dev *wdev);
+ };
+ 
+ /*
+diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
+index 1328827..d1fc54d 100644
+--- a/net/mac80211/cfg.c
++++ b/net/mac80211/cfg.c
+@@ -4517,6 +4517,24 @@ ieee80211_set_radar_background(struct wiphy *wiphy,
+ 	return local->ops->set_radar_background(&local->hw, chandef);
+ }
+ 
++static void
++ieee80211_skip_cac(struct wireless_dev *wdev)
++{
++	struct net_device *dev = wdev->netdev;
++	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++	unsigned int cac_time_ms;
++
++	cancel_delayed_work(&sdata->dfs_cac_timer_work);
++	if (wdev->cac_started) {
++		ieee80211_vif_release_channel(sdata);
++		cac_time_ms = wdev->cac_time_ms;
++		wdev->cac_start_time = jiffies -
++				       msecs_to_jiffies(cac_time_ms + 1);
++		cfg80211_cac_event(wdev->netdev, &wdev->chandef,
++				   NL80211_RADAR_CAC_FINISHED, GFP_KERNEL);
++	}
++}
++
+ const struct cfg80211_ops mac80211_config_ops = {
+ 	.add_virtual_intf = ieee80211_add_iface,
+ 	.del_virtual_intf = ieee80211_del_iface,
+@@ -4623,4 +4641,5 @@ const struct cfg80211_ops mac80211_config_ops = {
+ 	.set_sar_specs = ieee80211_set_sar_specs,
+ 	.color_change = ieee80211_color_change,
+ 	.set_radar_background = ieee80211_set_radar_background,
++	.skip_cac = ieee80211_skip_cac,
+ };
+diff --git a/net/wireless/core.h b/net/wireless/core.h
+index b588e5a..10e8981 100644
+--- a/net/wireless/core.h
++++ b/net/wireless/core.h
+@@ -86,6 +86,9 @@ struct cfg80211_registered_device {
+ 
+ 	struct wireless_dev *background_radar_wdev;
+ 	struct cfg80211_chan_def background_radar_chandef;
++	bool background_cac_started;
++	unsigned long background_cac_start_time;
++	unsigned int background_cac_time_ms;
+ 	struct delayed_work background_cac_done_wk;
+ 	struct work_struct background_cac_abort_wk;
+ 
 diff --git a/net/wireless/debugfs.c b/net/wireless/debugfs.c
-index aab4346..19c3091 100644
+index aab4346..517e09f 100644
 --- a/net/wireless/debugfs.c
 +++ b/net/wireless/debugfs.c
-@@ -95,16 +95,230 @@ static const struct file_operations ht40allow_map_ops = {
+@@ -9,6 +9,7 @@
+ #include <linux/slab.h>
+ #include "core.h"
+ #include "debugfs.h"
++#include "rdev-ops.h"
+ 
+ #define DEBUGFS_READONLY_FILE(name, buflen, fmt, value...)		\
+ static ssize_t name## _read(struct file *file, char __user *userbuf,	\
+@@ -95,16 +96,271 @@ static const struct file_operations ht40allow_map_ops = {
  	.llseek = default_llseek,
  };
  
 -#define DEBUGFS_ADD(name)						\
 -	debugfs_create_file(#name, 0444, phyd, &rdev->wiphy, &name## _ops)
-+static int dfs_print_chan(struct ieee80211_channel *chan, int remain_time,
-+			  char *buf, int buf_size, int offset)
++static int dfs_print_chan(struct ieee80211_channel *chan, int remain_time, int wait_time,
++			  char *buf, int buf_size, int offset, bool is_background)
 +{
 +	if (WARN_ON(offset > buf_size))
 +		return 0;
@@ -31,44 +106,49 @@
 +				    chan->hw_value);
 +		if (remain_time > 0)
 +			offset += scnprintf(buf + offset, buf_size - offset,
-+					    ", Non-occupancy Remain Time = %d [sec]\n",
-+					    remain_time);
++					    ", Non-occupancy Remain Time = %d / %d [sec]",
++					    remain_time, wait_time);
 +		else
 +			offset += scnprintf(buf + offset, buf_size - offset,
-+					    ", Changing state...\n");
++					    ", Changing state...");
 +	} else if (chan->dfs_state == NL80211_DFS_USABLE) {
 +		offset += scnprintf(buf + offset, buf_size - offset,
 +				    "	Channel = %d, DFS_state = Usable",
 +				    chan->hw_value);
 +		if (remain_time > 0)
 +			offset += scnprintf(buf + offset, buf_size - offset,
-+					    ", CAC Remain Time = %d [sec]\n",
-+					    remain_time);
-+		else
-+			offset += scnprintf(buf + offset, buf_size - offset,
-+					    "\n");
++					    ", CAC Remain Time = %d / %d [sec]",
++					    remain_time, wait_time);
 +	} else if (chan->dfs_state == NL80211_DFS_AVAILABLE) {
 +		offset += scnprintf(buf + offset, buf_size - offset,
-+				    "	Channel = %d, DFS_state = Available\n",
++				    "	Channel = %d, DFS_state = Available",
 +				    chan->hw_value);
 +	} else {
 +		offset += scnprintf(buf + offset, buf_size - offset,
-+				    "	Channel = %d, DFS_state = Unknown\n",
++				    "	Channel = %d, DFS_state = Unknown",
 +				    chan->hw_value);
 +	}
 +
++	if (is_background)
++		offset += scnprintf(buf + offset, buf_size - offset,
++				    " (background chain)");
++	offset += scnprintf(buf + offset, buf_size - offset, "\n");
++
 +	return offset;
 +}
 +
 +static int dfs_status_read_wdev(struct wiphy *wiphy, struct wireless_dev *wdev, char *buf,
 +				unsigned int buf_size, unsigned int offset)
 +{
-+	struct cfg80211_chan_def *chandef;
++	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
++	struct cfg80211_chan_def *chandef = &wdev->chandef;
++	struct cfg80211_chan_def *background_chandef = &rdev->background_radar_chandef;
 +	enum nl80211_band band;
 +	struct ieee80211_supported_band *sband;
 +	struct ieee80211_channel *chan;
 +	unsigned long jiffies_passed;
-+	int i, remain_time = 0;
++	int i, remain_time = 0, wait_time_ms = 0;
++	bool is_background;
 +
 +	offset += scnprintf(buf + offset, buf_size - offset, "DFS Channel:\n");
 +
@@ -77,6 +157,7 @@
 +		if (!sband)
 +			continue;
 +		for (i = 0; i < sband->n_channels; i++) {
++			is_background = false;
 +			chan = &sband->channels[i];
 +
 +			if (!(chan->flags & IEEE80211_CHAN_RADAR))
@@ -84,21 +165,39 @@
 +
 +			if (chan->dfs_state == NL80211_DFS_UNAVAILABLE) {
 +				jiffies_passed = jiffies - chan->dfs_state_entered;
-+				remain_time = (IEEE80211_DFS_MIN_NOP_TIME_MS -
-+					       jiffies_to_msecs(jiffies_passed));
-+				if (remain_time > IEEE80211_DFS_MIN_NOP_TIME_MS)
++				wait_time_ms = IEEE80211_DFS_MIN_NOP_TIME_MS;
++				remain_time = (wait_time_ms - jiffies_to_msecs(jiffies_passed));
++				if (remain_time > wait_time_ms)
 +					remain_time = 0;
 +			} else if (chan->dfs_state == NL80211_DFS_USABLE) {
-+				chandef = &wdev->chandef;
 +				if (wdev->cac_started && cfg80211_is_sub_chan(chandef, chan)) {
 +					jiffies_passed = jiffies - wdev->cac_start_time;
-+					remain_time = (wdev->cac_time_ms -
-+							jiffies_to_msecs(jiffies_passed));
++					wait_time_ms = wdev->cac_time_ms;
++					remain_time = (wait_time_ms -
++						       jiffies_to_msecs(jiffies_passed));
++				}
++
++				if (rdev->background_radar_wdev == wdev &&
++				    rdev->background_cac_started &&
++				    cfg80211_is_sub_chan(background_chandef, chan)) {
++					jiffies_passed = jiffies - rdev->background_cac_start_time;
++					wait_time_ms = rdev->background_cac_time_ms;
++					remain_time = (wait_time_ms -
++						       jiffies_to_msecs(jiffies_passed));
++					is_background = true;
 +				}
-+				if (remain_time > wdev->cac_time_ms)
++
++				if (remain_time > wait_time_ms)
 +					remain_time = 0;
++
++			} else {
++				if (rdev->background_radar_wdev == wdev &&
++				    cfg80211_is_sub_chan(background_chandef, chan))
++					is_background = true;
 +			}
-+			offset = dfs_print_chan(chan, remain_time / 1000, buf, buf_size, offset);
++
++			offset = dfs_print_chan(chan, remain_time / 1000, wait_time_ms / 1000,
++						buf, buf_size, offset, is_background);
 +			remain_time = 0;
 +		}
 +	}
@@ -198,28 +297,45 @@
 +static int
 +dfs_cac_skip(void *data, u64 val)
 +{
++#define CAC_SKIP_MASK			BIT(0)
++#define CAC_SKIP_BACKGROUND_MASK	BIT(1)
 +	struct wiphy *wiphy = data;
++	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
 +	struct wireless_dev *wdev;
 +	struct cfg80211_chan_def *chandef;
-+	bool en = !!val;
++	unsigned int skip_mode = val;
++	unsigned long cac_time;
 +	struct ieee80211_channel *chan;
 +
-+	if (!en)
++	if (!skip_mode || skip_mode > (CAC_SKIP_MASK | CAC_SKIP_BACKGROUND_MASK))
 +		return 0;
 +
 +	list_for_each_entry(wdev, &wiphy->wdev_list, list) {
-+		chandef = &wdev->chandef;
-+		if (chandef->chan) {
++		if ((skip_mode & CAC_SKIP_MASK) && wdev->chandef.chan) {
++			chandef = &wdev->chandef;
 +			chan = chandef->chan;
-+			if (!(chan->flags & IEEE80211_CHAN_RADAR))
-+				continue;
++
++			if ((chan->flags & IEEE80211_CHAN_RADAR) &&
++			    chan->dfs_state == NL80211_DFS_USABLE && wdev->cac_started) {
++				rdev_skip_cac(rdev, wdev);
++			}
++		}
++
++		if ((skip_mode & CAC_SKIP_BACKGROUND_MASK) &&
++		    rdev->background_radar_wdev == wdev &&
++		    rdev->background_radar_chandef.chan) {
++			chandef = &rdev->background_radar_chandef;
++			chan = chandef->chan;
 +
-+			if (chan->dfs_state == NL80211_DFS_USABLE && wdev->cac_started) {
++			if ((chan->flags & IEEE80211_CHAN_RADAR) &&
++			    chan->dfs_state == NL80211_DFS_USABLE &&
++			    rdev->background_cac_started) {
 +				// Let current jiffies > dfs_state_entered_jiffies + CAC time
-+				wdev->cac_start_time = jiffies -
-+						       msecs_to_jiffies(wdev->cac_time_ms + 1);
-+				cfg80211_cac_event(wdev->netdev, chandef,
-+						   NL80211_RADAR_CAC_FINISHED, GFP_KERNEL);
++				cac_time = rdev->background_cac_time_ms;
++				rdev->background_cac_start_time = jiffies -
++								  msecs_to_jiffies(cac_time + 1);
++				cancel_delayed_work(&rdev->background_cac_done_wk);
++				queue_delayed_work(cfg80211_wq, &rdev->background_cac_done_wk, 0);
 +			}
 +		}
 +	}
@@ -251,6 +367,92 @@
 +	DEBUGFS_ADD(dfs_skip_nop, 0600);
 +	DEBUGFS_ADD(dfs_skip_cac, 0600);
  }
+diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
+index 00370ca..205c1bc 100644
+--- a/net/wireless/mlme.c
++++ b/net/wireless/mlme.c
+@@ -998,13 +998,16 @@ __cfg80211_background_cac_event(struct cfg80211_registered_device *rdev,
+ 		queue_work(cfg80211_wq, &rdev->propagate_cac_done_wk);
+ 		cfg80211_sched_dfs_chan_update(rdev);
+ 		wdev = rdev->background_radar_wdev;
++		rdev->background_cac_started = false;
+ 		break;
+ 	case NL80211_RADAR_CAC_ABORTED:
+ 		if (!cancel_delayed_work(&rdev->background_cac_done_wk))
+ 			return;
+ 		wdev = rdev->background_radar_wdev;
++		rdev->background_cac_started = false;
+ 		break;
+ 	case NL80211_RADAR_CAC_STARTED:
++		rdev->background_cac_started = true;
+ 		break;
+ 	default:
+ 		return;
+@@ -1024,6 +1027,7 @@ cfg80211_background_cac_event(struct cfg80211_registered_device *rdev,
+ 					chandef, event);
+ 	wiphy_unlock(&rdev->wiphy);
+ }
++EXPORT_SYMBOL(cfg80211_background_cac_event);
+ 
+ void cfg80211_background_cac_done_wk(struct work_struct *work)
+ {
+@@ -1085,8 +1089,10 @@ cfg80211_start_background_radar_detection(struct cfg80211_registered_device *rde
+ 	if (!cac_time_ms)
+ 		cac_time_ms = IEEE80211_DFS_MIN_CAC_TIME_MS;
+ 
++	rdev->background_cac_time_ms = cac_time_ms;
+ 	rdev->background_radar_chandef = *chandef;
+ 	rdev->background_radar_wdev = wdev; /* Get offchain ownership */
++	rdev->background_cac_start_time = jiffies;
+ 
+ 	__cfg80211_background_cac_event(rdev, wdev, chandef,
+ 					NL80211_RADAR_CAC_STARTED);
+diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h
+index 8555468..26f4604 100644
+--- a/net/wireless/rdev-ops.h
++++ b/net/wireless/rdev-ops.h
+@@ -1398,4 +1398,18 @@ rdev_set_radar_background(struct cfg80211_registered_device *rdev,
+ 	return ret;
+ }
+ 
++static inline int
++rdev_skip_cac(struct cfg80211_registered_device *rdev,
++	      struct wireless_dev *wdev)
++{
++	if (!rdev->ops->skip_cac)
++		return -EOPNOTSUPP;
++
++	trace_rdev_skip_cac(wdev);
++	rdev->ops->skip_cac(wdev);
++	trace_rdev_return_void(&rdev->wiphy);
++
++	return 0;
++}
++
+ #endif /* __CFG80211_RDEV_OPS */
+diff --git a/net/wireless/trace.h b/net/wireless/trace.h
+index 97a2937..eadabfa 100644
+--- a/net/wireless/trace.h
++++ b/net/wireless/trace.h
+@@ -3665,6 +3665,18 @@ TRACE_EVENT(rdev_set_radar_background,
+ 		  WIPHY_PR_ARG, CHAN_DEF_PR_ARG)
+ );
+ 
++TRACE_EVENT(rdev_skip_cac,
++	    TP_PROTO(struct wireless_dev *wdev),
++
++	    TP_ARGS(wdev),
++
++	    TP_STRUCT__entry(WDEV_ENTRY),
++
++	    TP_fast_assign(WDEV_ASSIGN;),
++
++	    TP_printk(WDEV_PR_FMT, WDEV_PR_ARG)
++);
++
+ #endif /* !__RDEV_OPS_TRACE || TRACE_HEADER_MULTI_READ */
+ 
+ #undef TRACE_INCLUDE_PATH
 -- 
 2.18.0
 
diff --git a/autobuild_mac80211_release/package/kernel/mac80211/patches/subsys/913-mac80211-mtk-Set-TWT-Information-Frame-Disabled-bit-as-1.patch b/autobuild_mac80211_release/package/kernel/mac80211/patches/subsys/913-mac80211-mtk-Set-TWT-Information-Frame-Disabled-bit-as-1.patch
index 31b339c..a5d1de6 100644
--- a/autobuild_mac80211_release/package/kernel/mac80211/patches/subsys/913-mac80211-mtk-Set-TWT-Information-Frame-Disabled-bit-as-1.patch
+++ b/autobuild_mac80211_release/package/kernel/mac80211/patches/subsys/913-mac80211-mtk-Set-TWT-Information-Frame-Disabled-bit-as-1.patch
@@ -1,4 +1,4 @@
-From dd8ee0ad8ef8ddd76b9c0abaf6db66c386affd71 Mon Sep 17 00:00:00 2001
+From 4b13f8c000233eaca0dfb184724ff787148fc2bc Mon Sep 17 00:00:00 2001
 From: Howard Hsu <howard-yh.hsu@mediatek.com>
 Date: Tue, 4 Oct 2022 10:47:05 +0800
 Subject: [PATCH 913/914] mac80211: Set TWT Information Frame Disabled bit as
diff --git a/autobuild_mac80211_release/package/kernel/mac80211/patches/subsys/914-mac80211-mtk-fix-the-issue-of-AP-and-STA-starting-on-DFS.patch b/autobuild_mac80211_release/package/kernel/mac80211/patches/subsys/914-mac80211-mtk-fix-the-issue-of-AP-and-STA-starting-on-DFS.patch
index b13e584..8022163 100644
--- a/autobuild_mac80211_release/package/kernel/mac80211/patches/subsys/914-mac80211-mtk-fix-the-issue-of-AP-and-STA-starting-on-DFS.patch
+++ b/autobuild_mac80211_release/package/kernel/mac80211/patches/subsys/914-mac80211-mtk-fix-the-issue-of-AP-and-STA-starting-on-DFS.patch
@@ -1,4 +1,4 @@
-From 31b9460ba394aa6dde2ba1eee715832a9688c494 Mon Sep 17 00:00:00 2001
+From 4cd2b159ef1f560721a830d6c0e0ae69169521b4 Mon Sep 17 00:00:00 2001
 From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
 Date: Wed, 5 Oct 2022 19:13:43 +0800
 Subject: [PATCH 914/914] mac80211: fix the issue of AP and STA starting on DFS
@@ -6,18 +6,18 @@
 
 Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
 ---
- include/net/cfg80211.h       | 21 ++++++++++++++++
+ include/net/cfg80211.h       | 21 +++++++++++++++++
  include/uapi/linux/nl80211.h |  2 +-
- net/mac80211/cfg.c           | 48 ++++++++++++++++++++++++++++++++++++
+ net/mac80211/cfg.c           | 44 ++++++++++++++++++++++++++++++++++++
  net/mac80211/chan.c          |  2 +-
  net/wireless/chan.c          |  6 ++---
- net/wireless/nl80211.c       |  8 ++++++
- net/wireless/rdev-ops.h      | 16 ++++++++++++
- net/wireless/trace.h         | 15 +++++++++++
- 8 files changed, 113 insertions(+), 5 deletions(-)
+ net/wireless/nl80211.c       |  8 +++++++
+ net/wireless/rdev-ops.h      | 16 +++++++++++++
+ net/wireless/trace.h         | 15 ++++++++++++
+ 8 files changed, 109 insertions(+), 5 deletions(-)
 
 diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
-index f594914..0af069d 100644
+index 7d20b98..defce1e 100644
 --- a/include/net/cfg80211.h
 +++ b/include/net/cfg80211.h
 @@ -800,6 +800,24 @@ cfg80211_chandef_identical(const struct cfg80211_chan_def *chandef1,
@@ -45,16 +45,16 @@
  /**
   * cfg80211_chandef_is_edmg - check if chandef represents an EDMG channel
   *
-@@ -4401,6 +4419,8 @@ struct cfg80211_ops {
- 				struct cfg80211_color_change_settings *params);
+@@ -4402,6 +4420,8 @@ struct cfg80211_ops {
  	int	(*set_radar_background)(struct wiphy *wiphy,
  					struct cfg80211_chan_def *chandef);
+ 	void	(*skip_cac)(struct wireless_dev *wdev);
 +	void	(*check_cac_skip)(struct wiphy *wiphy,
 +				  struct cfg80211_chan_def *chandef);
  };
  
  /*
-@@ -5554,6 +5574,7 @@ struct wireless_dev {
+@@ -5555,6 +5575,7 @@ struct wireless_dev {
  	struct work_struct pmsr_free_wk;
  
  	unsigned long unprot_beacon_reported;
@@ -76,11 +76,11 @@
  	NUM_NL80211_ATTR = __NL80211_ATTR_AFTER_LAST,
  	NL80211_ATTR_MAX = __NL80211_ATTR_AFTER_LAST - 1
 diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
-index 1328827..ff0659c 100644
+index d1fc54d..c40256d 100644
 --- a/net/mac80211/cfg.c
 +++ b/net/mac80211/cfg.c
-@@ -4517,6 +4517,53 @@ ieee80211_set_radar_background(struct wiphy *wiphy,
- 	return local->ops->set_radar_background(&local->hw, chandef);
+@@ -4535,6 +4535,49 @@ ieee80211_skip_cac(struct wireless_dev *wdev)
+ 	}
  }
  
 +static void
@@ -117,11 +117,7 @@
 +				    chan->dfs_state == NL80211_DFS_USABLE && wdev->cac_started &&
 +				    cfg80211_chan_fully_overlap(&sdata_sta->vif.bss_conf.chandef,
 +								&s2->vif.bss_conf.chandef)) {
-+					cac_time_ms = wdev->cac_time_ms;
-+					wdev->cac_start_time = jiffies -
-+							       msecs_to_jiffies(cac_time_ms + 1);
-+					cfg80211_cac_event(wdev->netdev, &wdev->chandef,
-+							   NL80211_RADAR_CAC_FINISHED, GFP_KERNEL);
++					ieee80211_skip_cac(wdev);
 +					sdata_info(s2, "Skip CAC on the associated STA's chan\n");
 +				}
 +			}
@@ -133,10 +129,10 @@
  const struct cfg80211_ops mac80211_config_ops = {
  	.add_virtual_intf = ieee80211_add_iface,
  	.del_virtual_intf = ieee80211_del_iface,
-@@ -4623,4 +4670,5 @@ const struct cfg80211_ops mac80211_config_ops = {
- 	.set_sar_specs = ieee80211_set_sar_specs,
+@@ -4642,4 +4685,5 @@ const struct cfg80211_ops mac80211_config_ops = {
  	.color_change = ieee80211_color_change,
  	.set_radar_background = ieee80211_set_radar_background,
+ 	.skip_cac = ieee80211_skip_cac,
 +	.check_cac_skip = ieee80211_check_cac_skip,
  };
 diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c
@@ -207,11 +203,11 @@
  unlock:
  	wiphy_unlock(wiphy);
 diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h
-index 8555468..e7d0064 100644
+index 26f4604..c38aea1 100644
 --- a/net/wireless/rdev-ops.h
 +++ b/net/wireless/rdev-ops.h
-@@ -1398,4 +1398,20 @@ rdev_set_radar_background(struct cfg80211_registered_device *rdev,
- 	return ret;
+@@ -1412,4 +1412,20 @@ rdev_skip_cac(struct cfg80211_registered_device *rdev,
+ 	return 0;
  }
  
 +static inline int
@@ -232,11 +228,11 @@
 +
  #endif /* __CFG80211_RDEV_OPS */
 diff --git a/net/wireless/trace.h b/net/wireless/trace.h
-index 97a2937..e3f1c79 100644
+index eadabfa..a7b0c82 100644
 --- a/net/wireless/trace.h
 +++ b/net/wireless/trace.h
-@@ -3665,6 +3665,21 @@ TRACE_EVENT(rdev_set_radar_background,
- 		  WIPHY_PR_ARG, CHAN_DEF_PR_ARG)
+@@ -3677,6 +3677,21 @@ TRACE_EVENT(rdev_skip_cac,
+ 	    TP_printk(WDEV_PR_FMT, WDEV_PR_ARG)
  );
  
 +TRACE_EVENT(rdev_check_cac_skip,