[][MAC80211][hostapd][Fix ZW-DFS feature]

[Description]
Fix ZW-DFS feature in MAC80211

Hostapd v2.10 doesn't include ZW-DFS changes
Add hostapd ZW-DFS upstream patches from 800 to 811.
Synchronize nl80211 header difination sync in backport and hostapd

[Release-log]
N/A

Change-Id: I2a5c49bd822408788d8960c9090ebf27740d94ee
Reviewed-on: https://gerrit.mediatek.inc/c/openwrt/feeds/mtk_openwrt_feeds/+/6079111
diff --git a/autobuild_mac80211_release/package/kernel/mac80211/patches/subsys/908-mac80211-sync-nl80211-header-defination.patch b/autobuild_mac80211_release/package/kernel/mac80211/patches/subsys/908-mac80211-sync-nl80211-header-defination.patch
new file mode 100644
index 0000000..2f98ed3
--- /dev/null
+++ b/autobuild_mac80211_release/package/kernel/mac80211/patches/subsys/908-mac80211-sync-nl80211-header-defination.patch
@@ -0,0 +1,27 @@
+diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
+index 04e775e..e674aa7 100644
+--- a/include/uapi/linux/nl80211.h
++++ b/include/uapi/linux/nl80211.h
+@@ -6027,6 +6027,11 @@ enum nl80211_feature_flags {
+  * @NL80211_EXT_FEATURE_BSS_COLOR: The driver supports BSS color collision
+  *	detection and change announcemnts.
+  *
++ * @NL80211_EXT_FEATURE_FILS_CRYPTO_OFFLOAD: Driver running in AP mode supports
++ *	FILS encryption and decryption for (Re)Association Request and Response
++ *	frames. Userspace has to share FILS AAD details to the driver by using
++ *	@NL80211_CMD_SET_FILS_AAD.
++ *
+  * @NL80211_EXT_FEATURE_RADAR_BACKGROUND: Device supports background radar/CAC
+  *	detection.
+  *
+@@ -6095,6 +6100,7 @@ enum nl80211_ext_feature_index {
+ 	NL80211_EXT_FEATURE_SECURE_RTT,
+ 	NL80211_EXT_FEATURE_PROT_RANGE_NEGO_AND_MEASURE,
+ 	NL80211_EXT_FEATURE_BSS_COLOR,
++	NL80211_EXT_FEATURE_FILS_CRYPTO_OFFLOAD,
+ 	NL80211_EXT_FEATURE_RADAR_BACKGROUND,
+ 
+ 	/* add new features before the definition below */
+-- 
+2.29.2
+
diff --git a/autobuild_mac80211_release/package/network/services/hostapd/patches/800-DFS-Introduce-dfs_set_valid_channel-utility-routine.patch b/autobuild_mac80211_release/package/network/services/hostapd/patches/800-DFS-Introduce-dfs_set_valid_channel-utility-routine.patch
new file mode 100644
index 0000000..5edd2d1
--- /dev/null
+++ b/autobuild_mac80211_release/package/network/services/hostapd/patches/800-DFS-Introduce-dfs_set_valid_channel-utility-routine.patch
@@ -0,0 +1,84 @@
+From 3ebfdca86d2d4e45d8c72239819086e244cbd4f2 Mon Sep 17 00:00:00 2001
+From: Lorenzo Bianconi <lorenzo@kernel.org>
+Date: Mon, 20 Dec 2021 16:48:17 +0100
+Subject: [PATCH 900/911] DFS: Introduce dfs_set_valid_channel() utility
+ routine
+
+This is a preliminary change to introduce radar/CAC background detection
+support.
+
+Tested-by: Owen Peng <owen.peng@mediatek.com>
+Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
+---
+ src/ap/dfs.c | 38 ++++++++++++++++++++++++--------------
+ 1 file changed, 24 insertions(+), 14 deletions(-)
+
+diff --git a/src/ap/dfs.c b/src/ap/dfs.c
+index 53a50653b..09b2bb7d4 100644
+--- a/src/ap/dfs.c
++++ b/src/ap/dfs.c
+@@ -586,6 +586,29 @@ dfs_get_valid_channel(struct hostapd_iface *iface,
+ }
+ 
+ 
++static int dfs_set_valid_channel(struct hostapd_iface *iface, int skip_radar)
++{
++	struct hostapd_channel_data *channel;
++	u8 cf1 = 0, cf2 = 0;
++	int sec = 0;
++
++	channel = dfs_get_valid_channel(iface, &sec, &cf1, &cf2,
++					skip_radar);
++	if (!channel) {
++		wpa_printf(MSG_ERROR, "could not get valid channel");
++		return -1;
++	}
++
++	iface->freq = channel->freq;
++	iface->conf->channel = channel->chan;
++	iface->conf->secondary_channel = sec;
++	hostapd_set_oper_centr_freq_seg0_idx(iface->conf, cf1);
++	hostapd_set_oper_centr_freq_seg1_idx(iface->conf, cf2);
++
++	return 0;
++}
++
++
+ static int set_dfs_state_freq(struct hostapd_iface *iface, int freq, u32 state)
+ {
+ 	struct hostapd_hw_modes *mode;
+@@ -773,7 +796,6 @@ static unsigned int dfs_get_cac_time(struct hostapd_iface *iface,
+  */
+ int hostapd_handle_dfs(struct hostapd_iface *iface)
+ {
+-	struct hostapd_channel_data *channel;
+ 	int res, n_chans, n_chans1, start_chan_idx, start_chan_idx1;
+ 	int skip_radar = 0;
+ 
+@@ -828,22 +850,10 @@ int hostapd_handle_dfs(struct hostapd_iface *iface)
+ 		wpa_printf(MSG_DEBUG, "DFS %d chans unavailable - choose other channel: %s",
+ 			   res, res ? "yes": "no");
+ 		if (res) {
+-			int sec = 0;
+-			u8 cf1 = 0, cf2 = 0;
+-
+-			channel = dfs_get_valid_channel(iface, &sec, &cf1, &cf2,
+-							skip_radar);
+-			if (!channel) {
+-				wpa_printf(MSG_ERROR, "could not get valid channel");
++			if (dfs_set_valid_channel(iface, skip_radar) < 0) {
+ 				hostapd_set_state(iface, HAPD_IFACE_DFS);
+ 				return 0;
+ 			}
+-
+-			iface->freq = channel->freq;
+-			iface->conf->channel = channel->chan;
+-			iface->conf->secondary_channel = sec;
+-			hostapd_set_oper_centr_freq_seg0_idx(iface->conf, cf1);
+-			hostapd_set_oper_centr_freq_seg1_idx(iface->conf, cf2);
+ 		}
+ 	} while (res);
+ 
+-- 
+2.29.2
+
diff --git a/autobuild_mac80211_release/package/network/services/hostapd/patches/801-DFS-Add-capability-to-select-radar-only-channels.patch b/autobuild_mac80211_release/package/network/services/hostapd/patches/801-DFS-Add-capability-to-select-radar-only-channels.patch
new file mode 100644
index 0000000..22300fa
--- /dev/null
+++ b/autobuild_mac80211_release/package/network/services/hostapd/patches/801-DFS-Add-capability-to-select-radar-only-channels.patch
@@ -0,0 +1,171 @@
+From 119b1e4f41d2b983150f5f0cb6dcb2c060c6c3c8 Mon Sep 17 00:00:00 2001
+From: dzou <dzou@company.com>
+Date: Sun, 5 Jun 2022 23:13:20 +0800
+Subject: [PATCH 901/911] DFS: Add capability to select radar-only channels
+
+Introduce type parameter to dfs_get_valid_channel() routine to allow
+selection of a radar-only channel where the CAC detection has not been
+performed yet. This is a preliminary patch to enable background
+radar/CAC detection.
+
+Tested-by: Owen Peng <owen.peng@mediatek.com>
+Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
+---
+ src/ap/dfs.c | 50 ++++++++++++++++++++++++++++++++++++--------------
+ 1 file changed, 36 insertions(+), 14 deletions(-)
+
+diff --git a/src/ap/dfs.c b/src/ap/dfs.c
+index 09b2bb7d4..56564b901 100644
+--- a/src/ap/dfs.c
++++ b/src/ap/dfs.c
+@@ -52,15 +52,33 @@ static int dfs_get_used_n_chans(struct hostapd_iface *iface, int *seg1)
+ }
+ 
+ 
++enum dfs_channel_type {
++	DFS_ANY_CHANNEL,
++	DFS_AVAILABLE, /* non-radar or radar-available */
++	DFS_NO_CAC_YET, /* radar-not-yet-available */
++};
++
++/* dfs_channel_available: select new channel according to type parameter */
+ static int dfs_channel_available(struct hostapd_channel_data *chan,
+-				 int skip_radar)
++				 enum dfs_channel_type type)
+ {
++	if (type == DFS_NO_CAC_YET) {
++		/* Select only radar channel where CAC has not been
++		 * performed yet
++		 */
++		if ((chan->flag & HOSTAPD_CHAN_RADAR) &&
++		    (chan->flag & HOSTAPD_CHAN_DFS_MASK) ==
++		     HOSTAPD_CHAN_DFS_USABLE)
++			return 1;
++		return 0;
++	}
++
+ 	/*
+ 	 * When radar detection happens, CSA is performed. However, there's no
+ 	 * time for CAC, so radar channels must be skipped when finding a new
+ 	 * channel for CSA, unless they are available for immediate use.
+ 	 */
+-	if (skip_radar && (chan->flag & HOSTAPD_CHAN_RADAR) &&
++	if (type == DFS_AVAILABLE && (chan->flag & HOSTAPD_CHAN_RADAR) &&
+ 	    ((chan->flag & HOSTAPD_CHAN_DFS_MASK) !=
+ 	     HOSTAPD_CHAN_DFS_AVAILABLE))
+ 		return 0;
+@@ -139,7 +157,7 @@ dfs_get_chan_data(struct hostapd_hw_modes *mode, int freq, int first_chan_idx)
+ 
+ static int dfs_chan_range_available(struct hostapd_hw_modes *mode,
+ 				    int first_chan_idx, int num_chans,
+-				    int skip_radar)
++				    enum dfs_channel_type type)
+ {
+ 	struct hostapd_channel_data *first_chan, *chan;
+ 	int i;
+@@ -178,7 +196,7 @@ static int dfs_chan_range_available(struct hostapd_hw_modes *mode,
+ 			return 0;
+ 		}
+ 
+-		if (!dfs_channel_available(chan, skip_radar)) {
++		if (!dfs_channel_available(chan, type)) {
+ 			wpa_printf(MSG_DEBUG, "DFS: channel not available %d",
+ 				   first_chan->freq + i * 20);
+ 			return 0;
+@@ -208,7 +226,7 @@ static int is_in_chanlist(struct hostapd_iface *iface,
+  */
+ static int dfs_find_channel(struct hostapd_iface *iface,
+ 			    struct hostapd_channel_data **ret_chan,
+-			    int idx, int skip_radar)
++			    int idx, enum dfs_channel_type type)
+ {
+ 	struct hostapd_hw_modes *mode;
+ 	struct hostapd_channel_data *chan;
+@@ -233,7 +251,7 @@ static int dfs_find_channel(struct hostapd_iface *iface,
+ 		}
+ 
+ 		/* Skip incompatible chandefs */
+-		if (!dfs_chan_range_available(mode, i, n_chans, skip_radar)) {
++		if (!dfs_chan_range_available(mode, i, n_chans, type)) {
+ 			wpa_printf(MSG_DEBUG,
+ 				   "DFS: range not available for %d (%d)",
+ 				   chan->freq, chan->chan);
+@@ -476,7 +494,7 @@ dfs_get_valid_channel(struct hostapd_iface *iface,
+ 		      int *secondary_channel,
+ 		      u8 *oper_centr_freq_seg0_idx,
+ 		      u8 *oper_centr_freq_seg1_idx,
+-		      int skip_radar)
++		      enum dfs_channel_type type)
+ {
+ 	struct hostapd_hw_modes *mode;
+ 	struct hostapd_channel_data *chan = NULL;
+@@ -505,7 +523,7 @@ dfs_get_valid_channel(struct hostapd_iface *iface,
+ 		return NULL;
+ 
+ 	/* Get the count first */
+-	num_available_chandefs = dfs_find_channel(iface, NULL, 0, skip_radar);
++	num_available_chandefs = dfs_find_channel(iface, NULL, 0, type);
+ 	wpa_printf(MSG_DEBUG, "DFS: num_available_chandefs=%d",
+ 		   num_available_chandefs);
+ 	if (num_available_chandefs == 0)
+@@ -526,7 +544,7 @@ dfs_get_valid_channel(struct hostapd_iface *iface,
+ 		return NULL;
+ 
+ 	chan_idx = _rand % num_available_chandefs;
+-	dfs_find_channel(iface, &chan, chan_idx, skip_radar);
++	dfs_find_channel(iface, &chan, chan_idx, type);
+ 	if (!chan) {
+ 		wpa_printf(MSG_DEBUG, "DFS: no random channel found");
+ 		return NULL;
+@@ -555,7 +573,7 @@ dfs_get_valid_channel(struct hostapd_iface *iface,
+ 		for (i = 0; i < num_available_chandefs - 1; i++) {
+ 			/* start from chan_idx + 1, end when chan_idx - 1 */
+ 			chan_idx2 = (chan_idx + 1 + i) % num_available_chandefs;
+-			dfs_find_channel(iface, &chan2, chan_idx2, skip_radar);
++			dfs_find_channel(iface, &chan2, chan_idx2, type);
+ 			if (chan2 && abs(chan2->chan - chan->chan) > 12) {
+ 				/* two channels are not adjacent */
+ 				sec_chan_idx_80p80 = chan2->chan;
+@@ -593,7 +611,8 @@ static int dfs_set_valid_channel(struct hostapd_iface *iface, int skip_radar)
+ 	int sec = 0;
+ 
+ 	channel = dfs_get_valid_channel(iface, &sec, &cf1, &cf2,
+-					skip_radar);
++					skip_radar ? DFS_AVAILABLE :
++					DFS_ANY_CHANNEL);
+ 	if (!channel) {
+ 		wpa_printf(MSG_ERROR, "could not get valid channel");
+ 		return -1;
+@@ -976,7 +995,8 @@ dfs_downgrade_bandwidth(struct hostapd_iface *iface, int *secondary_channel,
+ 		channel = dfs_get_valid_channel(iface, secondary_channel,
+ 						oper_centr_freq_seg0_idx,
+ 						oper_centr_freq_seg1_idx,
+-						*skip_radar);
++						*skip_radar ? DFS_AVAILABLE :
++						DFS_ANY_CHANNEL);
+ 		if (channel) {
+ 			wpa_printf(MSG_DEBUG, "DFS: Selected channel: %d",
+ 				   channel->chan);
+@@ -1017,7 +1037,8 @@ static int hostapd_dfs_start_channel_switch_cac(struct hostapd_iface *iface)
+ 	channel = dfs_get_valid_channel(iface, &secondary_channel,
+ 					&oper_centr_freq_seg0_idx,
+ 					&oper_centr_freq_seg1_idx,
+-					skip_radar);
++					skip_radar ? DFS_AVAILABLE :
++					DFS_ANY_CHANNEL);
+ 
+ 	if (!channel) {
+ 		channel = dfs_downgrade_bandwidth(iface, &secondary_channel,
+@@ -1088,7 +1109,8 @@ static int hostapd_dfs_start_channel_switch(struct hostapd_iface *iface)
+ 	channel = dfs_get_valid_channel(iface, &secondary_channel,
+ 					&oper_centr_freq_seg0_idx,
+ 					&oper_centr_freq_seg1_idx,
+-					skip_radar);
++					skip_radar ? DFS_AVAILABLE :
++					DFS_ANY_CHANNEL);
+ 
+ 	if (!channel) {
+ 		/*
+-- 
+2.29.2
+
diff --git a/autobuild_mac80211_release/package/network/services/hostapd/patches/802-nl80211-Report-background-radar-CAC-detection-capabi.patch b/autobuild_mac80211_release/package/network/services/hostapd/patches/802-nl80211-Report-background-radar-CAC-detection-capabi.patch
new file mode 100644
index 0000000..1647f8f
--- /dev/null
+++ b/autobuild_mac80211_release/package/network/services/hostapd/patches/802-nl80211-Report-background-radar-CAC-detection-capabi.patch
@@ -0,0 +1,47 @@
+From 5fb4920aa49934d3a602556fbe35ab6ed11374d1 Mon Sep 17 00:00:00 2001
+From: dzou <dzou@company.com>
+Date: Sun, 5 Jun 2022 23:17:28 +0800
+Subject: [PATCH 902/911] nl80211: Report background radar/CAC detection
+ capability
+
+Report background radar/CAC detection capability if supported
+by the underlying driver/hardware.
+
+Tested-by: Owen Peng <owen.peng@mediatek.com>
+Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
+---
+ src/drivers/driver.h              | 2 ++
+ src/drivers/driver_nl80211_capa.c | 4 ++++
+ 2 files changed, 6 insertions(+)
+
+diff --git a/src/drivers/driver.h b/src/drivers/driver.h
+index 44304d487..68964c9d5 100644
+--- a/src/drivers/driver.h
++++ b/src/drivers/driver.h
+@@ -2032,6 +2032,8 @@ struct wpa_driver_capa {
+ #define WPA_DRIVER_FLAGS2_OCV			0x0000000000000080ULL
+ /** Driver expects user space implementation of SME in AP mode */
+ #define WPA_DRIVER_FLAGS2_AP_SME		0x0000000000000100ULL
++/** Driver supports background radar/CAC detection */
++#define WPA_DRIVER_RADAR_BACKGROUND            0x0000000000000400ULL
+ 	u64 flags2;
+ 
+ #define FULL_AP_CLIENT_STATE_SUPP(drv_flags) \
+diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c
+index 83868b78e..05703ec64 100644
+--- a/src/drivers/driver_nl80211_capa.c
++++ b/src/drivers/driver_nl80211_capa.c
+@@ -665,6 +665,10 @@ static void wiphy_info_ext_feature_flags(struct wiphy_info_data *info,
+ 	if (ext_feature_isset(ext_features, len,
+ 			      NL80211_EXT_FEATURE_OPERATING_CHANNEL_VALIDATION))
+ 		capa->flags2 |= WPA_DRIVER_FLAGS2_OCV;
++
++	if (ext_feature_isset(ext_features, len,
++			      NL80211_EXT_FEATURE_RADAR_BACKGROUND))
++		capa->flags2 |= WPA_DRIVER_RADAR_BACKGROUND;
+ }
+ 
+ 
+-- 
+2.29.2
+
diff --git a/autobuild_mac80211_release/package/network/services/hostapd/patches/803-DFS-Rely-on-channel_type-in-dfs_downgrade_bandwidth.patch b/autobuild_mac80211_release/package/network/services/hostapd/patches/803-DFS-Rely-on-channel_type-in-dfs_downgrade_bandwidth.patch
new file mode 100644
index 0000000..9c5d850
--- /dev/null
+++ b/autobuild_mac80211_release/package/network/services/hostapd/patches/803-DFS-Rely-on-channel_type-in-dfs_downgrade_bandwidth.patch
@@ -0,0 +1,135 @@
+From 18111f0a47b33da2f75cebd65f9201150bc3a1a9 Mon Sep 17 00:00:00 2001
+From: dzou <dzou@company.com>
+Date: Sun, 5 Jun 2022 23:18:45 +0800
+Subject: [PATCH 903/911] DFS: Rely on channel_type in
+ dfs_downgrade_bandwidth()
+
+Add the capability to specify all 3 channel type possibilities in
+dfs_downgrade_bandwidth(). This is a preliminary change to introduce
+radar/CAC background detection support.
+
+Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
+---
+ src/ap/dfs.c | 32 +++++++++++++++-----------------
+ 1 file changed, 15 insertions(+), 17 deletions(-)
+
+diff --git a/src/ap/dfs.c b/src/ap/dfs.c
+index 56564b901..05cb63ac4 100644
+--- a/src/ap/dfs.c
++++ b/src/ap/dfs.c
+@@ -987,7 +987,8 @@ int hostapd_dfs_pre_cac_expired(struct hostapd_iface *iface, int freq,
+ static struct hostapd_channel_data *
+ dfs_downgrade_bandwidth(struct hostapd_iface *iface, int *secondary_channel,
+ 			u8 *oper_centr_freq_seg0_idx,
+-			u8 *oper_centr_freq_seg1_idx, int *skip_radar)
++			u8 *oper_centr_freq_seg1_idx,
++			enum dfs_channel_type *channel_type)
+ {
+ 	struct hostapd_channel_data *channel;
+ 
+@@ -995,23 +996,22 @@ dfs_downgrade_bandwidth(struct hostapd_iface *iface, int *secondary_channel,
+ 		channel = dfs_get_valid_channel(iface, secondary_channel,
+ 						oper_centr_freq_seg0_idx,
+ 						oper_centr_freq_seg1_idx,
+-						*skip_radar ? DFS_AVAILABLE :
+-						DFS_ANY_CHANNEL);
++						*channel_type);
+ 		if (channel) {
+ 			wpa_printf(MSG_DEBUG, "DFS: Selected channel: %d",
+ 				   channel->chan);
+ 			return channel;
+ 		}
+ 
+-		if (*skip_radar) {
+-			*skip_radar = 0;
++		if (*channel_type != DFS_ANY_CHANNEL) {
++			*channel_type = DFS_ANY_CHANNEL;
+ 		} else {
+ 			int oper_chwidth;
+ 
+ 			oper_chwidth = hostapd_get_oper_chwidth(iface->conf);
+ 			if (oper_chwidth == CHANWIDTH_USE_HT)
+ 				break;
+-			*skip_radar = 1;
++			*channel_type = DFS_AVAILABLE;
+ 			hostapd_set_oper_chwidth(iface->conf, oper_chwidth - 1);
+ 		}
+ 	}
+@@ -1029,7 +1029,7 @@ static int hostapd_dfs_start_channel_switch_cac(struct hostapd_iface *iface)
+ 	int secondary_channel;
+ 	u8 oper_centr_freq_seg0_idx = 0;
+ 	u8 oper_centr_freq_seg1_idx = 0;
+-	int skip_radar = 0;
++	enum dfs_channel_type channel_type = DFS_ANY_CHANNEL;
+ 	int err = 1;
+ 
+ 	/* Radar detected during active CAC */
+@@ -1037,14 +1037,13 @@ static int hostapd_dfs_start_channel_switch_cac(struct hostapd_iface *iface)
+ 	channel = dfs_get_valid_channel(iface, &secondary_channel,
+ 					&oper_centr_freq_seg0_idx,
+ 					&oper_centr_freq_seg1_idx,
+-					skip_radar ? DFS_AVAILABLE :
+-					DFS_ANY_CHANNEL);
++					channel_type);
+ 
+ 	if (!channel) {
+ 		channel = dfs_downgrade_bandwidth(iface, &secondary_channel,
+ 						  &oper_centr_freq_seg0_idx,
+ 						  &oper_centr_freq_seg1_idx,
+-						  &skip_radar);
++						  &channel_type);
+ 		if (!channel) {
+ 			wpa_printf(MSG_ERROR, "No valid channel available");
+ 			return err;
+@@ -1078,7 +1077,7 @@ static int hostapd_dfs_start_channel_switch(struct hostapd_iface *iface)
+ 	u8 oper_centr_freq_seg0_idx;
+ 	u8 oper_centr_freq_seg1_idx;
+ 	u8 new_vht_oper_chwidth;
+-	int skip_radar = 1;
++	enum dfs_channel_type channel_type = DFS_AVAILABLE;
+ 	struct csa_settings csa_settings;
+ 	unsigned int i;
+ 	int err = 1;
+@@ -1103,14 +1102,13 @@ static int hostapd_dfs_start_channel_switch(struct hostapd_iface *iface)
+ 	 * uniform spreading.
+ 	 */
+ 	if (iface->dfs_domain == HOSTAPD_DFS_REGION_ETSI)
+-		skip_radar = 0;
++		channel_type = DFS_ANY_CHANNEL;
+ 
+ 	/* Perform channel switch/CSA */
+ 	channel = dfs_get_valid_channel(iface, &secondary_channel,
+ 					&oper_centr_freq_seg0_idx,
+ 					&oper_centr_freq_seg1_idx,
+-					skip_radar ? DFS_AVAILABLE :
+-					DFS_ANY_CHANNEL);
++					channel_type);
+ 
+ 	if (!channel) {
+ 		/*
+@@ -1118,11 +1116,11 @@ static int hostapd_dfs_start_channel_switch(struct hostapd_iface *iface)
+ 		 * there is another channel where we can switch even if it
+ 		 * requires to perform a CAC first.
+ 		 */
+-		skip_radar = 0;
++		channel_type = DFS_ANY_CHANNEL;
+ 		channel = dfs_downgrade_bandwidth(iface, &secondary_channel,
+ 						  &oper_centr_freq_seg0_idx,
+ 						  &oper_centr_freq_seg1_idx,
+-						  &skip_radar);
++						  &channel_type);
+ 		if (!channel) {
+ 			/*
+ 			 * Toggle interface state to enter DFS state
+@@ -1133,7 +1131,7 @@ static int hostapd_dfs_start_channel_switch(struct hostapd_iface *iface)
+ 			return 0;
+ 		}
+ 
+-		if (!skip_radar) {
++		if (channel_type == DFS_ANY_CHANNEL) {
+ 			iface->freq = channel->freq;
+ 			iface->conf->channel = channel->chan;
+ 			iface->conf->secondary_channel = secondary_channel;
+-- 
+2.29.2
+
diff --git a/autobuild_mac80211_release/package/network/services/hostapd/patches/804-nl80211-Radar-background-flag-setting.patch b/autobuild_mac80211_release/package/network/services/hostapd/patches/804-nl80211-Radar-background-flag-setting.patch
new file mode 100644
index 0000000..ace1b11
--- /dev/null
+++ b/autobuild_mac80211_release/package/network/services/hostapd/patches/804-nl80211-Radar-background-flag-setting.patch
@@ -0,0 +1,58 @@
+From 9ac9d78cb92dd3ffce4dd514f80d5a166d722ce0 Mon Sep 17 00:00:00 2001
+From: dzou <dzou@company.com>
+Date: Sun, 5 Jun 2022 23:19:45 +0800
+Subject: [PATCH 904/911] nl80211: Radar background flag setting
+
+Allow background radar detection flag to be set when specifying a
+channel. This is a preliminary change to introduce radar/CAC background
+detection support.
+
+Tested-by: Owen Peng <owen.peng@mediatek.com>
+Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
+---
+ src/drivers/driver.h         | 5 +++++
+ src/drivers/driver_nl80211.c | 5 +++++
+ 2 files changed, 10 insertions(+)
+
+diff --git a/src/drivers/driver.h b/src/drivers/driver.h
+index 68964c9d5..90adbf0f4 100644
+--- a/src/drivers/driver.h
++++ b/src/drivers/driver.h
+@@ -783,6 +783,11 @@ struct hostapd_freq_params {
+ 	 * for IEEE 802.11ay EDMG configuration.
+ 	 */
+ 	struct ieee80211_edmg_config edmg;
++
++	/**
++	 * radar_background - Whether radar/CAC background is requested
++	 */
++	bool radar_background;
+ };
+ 
+ /**
+diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
+index bf4fda770..6cf127ca7 100644
+--- a/src/drivers/driver_nl80211.c
++++ b/src/drivers/driver_nl80211.c
+@@ -4901,6 +4901,8 @@ static int nl80211_put_freq_params(struct nl_msg *msg,
+ 	wpa_printf(MSG_DEBUG, "  * he_enabled=%d", freq->he_enabled);
+ 	wpa_printf(MSG_DEBUG, "  * vht_enabled=%d", freq->vht_enabled);
+ 	wpa_printf(MSG_DEBUG, "  * ht_enabled=%d", freq->ht_enabled);
++	wpa_printf(MSG_DEBUG, "  * radar_background=%d",
++		   freq->radar_background);
+ 
+ 	hw_mode = ieee80211_freq_to_chan(freq->freq, &channel);
+ 	is_24ghz = hw_mode == HOSTAPD_MODE_IEEE80211G ||
+@@ -4978,6 +4980,9 @@ static int nl80211_put_freq_params(struct nl_msg *msg,
+ 				NL80211_CHAN_NO_HT))
+ 			return -ENOBUFS;
+ 	}
++	if (freq->radar_background)
++		nla_put_flag(msg, NL80211_ATTR_RADAR_BACKGROUND);
++
+ 	return 0;
+ }
+ 
+-- 
+2.29.2
+
diff --git a/autobuild_mac80211_release/package/network/services/hostapd/patches/805-DFS-Configure-background-radar-CAC-detection.patch b/autobuild_mac80211_release/package/network/services/hostapd/patches/805-DFS-Configure-background-radar-CAC-detection.patch
new file mode 100644
index 0000000..1d94fe0
--- /dev/null
+++ b/autobuild_mac80211_release/package/network/services/hostapd/patches/805-DFS-Configure-background-radar-CAC-detection.patch
@@ -0,0 +1,352 @@
+From e1171aa4bd128d019fc5d53431472abddeb5cca0 Mon Sep 17 00:00:00 2001
+From: dzou <dzou@company.com>
+Date: Sun, 5 Jun 2022 23:20:30 +0800
+Subject: [PATCH 905/911] DFS: Configure background radar/CAC detection
+
+Introduce the capability to perform radar/CAC detection on an offchannel
+radar chain available on some hardware (e.g., mt7915). This feature
+allows to avoid CAC downtime switching on a different channel during CAC
+detection on the selected radar channel.
+
+Tested-by: Owen Peng <owen.peng@mediatek.com>
+Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
+---
+ src/ap/ap_drv_ops.c |   9 ++-
+ src/ap/ap_drv_ops.h |   3 +-
+ src/ap/dfs.c        | 181 ++++++++++++++++++++++++++++++++++++++++----
+ src/ap/hostapd.h    |  15 ++++
+ 4 files changed, 189 insertions(+), 19 deletions(-)
+
+diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c
+index 033ad097e..1fc538104 100644
+--- a/src/ap/ap_drv_ops.c
++++ b/src/ap/ap_drv_ops.c
+@@ -810,7 +810,8 @@ int hostapd_start_dfs_cac(struct hostapd_iface *iface,
+ 			  int channel, int ht_enabled, int vht_enabled,
+ 			  int he_enabled,
+ 			  int sec_channel_offset, int oper_chwidth,
+-			  int center_segment0, int center_segment1)
++			  int center_segment0, int center_segment1,
++			  bool radar_background)
+ {
+ 	struct hostapd_data *hapd = iface->bss[0];
+ 	struct hostapd_freq_params data;
+@@ -836,10 +837,14 @@ int hostapd_start_dfs_cac(struct hostapd_iface *iface,
+ 		wpa_printf(MSG_ERROR, "Can't set freq params");
+ 		return -1;
+ 	}
++	data.radar_background = radar_background;
+ 
+ 	res = hapd->driver->start_dfs_cac(hapd->drv_priv, &data);
+ 	if (!res) {
+-		iface->cac_started = 1;
++		if (radar_background)
++			iface->radar_background.cac_started = 1;
++		else
++			iface->cac_started = 1;
+ 		os_get_reltime(&iface->dfs_cac_start);
+ 	}
+ 
+diff --git a/src/ap/ap_drv_ops.h b/src/ap/ap_drv_ops.h
+index 61c8f64eb..b4d6395ae 100644
+--- a/src/ap/ap_drv_ops.h
++++ b/src/ap/ap_drv_ops.h
+@@ -130,7 +130,8 @@ int hostapd_start_dfs_cac(struct hostapd_iface *iface,
+ 			  int channel, int ht_enabled, int vht_enabled,
+ 			  int he_enabled,
+ 			  int sec_channel_offset, int oper_chwidth,
+-			  int center_segment0, int center_segment1);
++			  int center_segment0, int center_segment1,
++			  bool radar_background);
+ int hostapd_drv_do_acs(struct hostapd_data *hapd);
+ int hostapd_drv_update_dh_ie(struct hostapd_data *hapd, const u8 *peer,
+ 			     u16 reason_code, const u8 *ie, size_t ielen);
+diff --git a/src/ap/dfs.c b/src/ap/dfs.c
+index 05cb63ac4..5dc261589 100644
+--- a/src/ap/dfs.c
++++ b/src/ap/dfs.c
+@@ -20,6 +20,25 @@
+ #include "crypto/crypto.h"
+ 
+ 
++enum dfs_channel_type {
++	DFS_ANY_CHANNEL,
++	DFS_AVAILABLE, /* non-radar or radar-available */
++	DFS_NO_CAC_YET, /* radar-not-yet-available */
++};
++
++static struct hostapd_channel_data *
++dfs_downgrade_bandwidth(struct hostapd_iface *iface, int *secondary_channel,
++			u8 *oper_centr_freq_seg0_idx,
++			u8 *oper_centr_freq_seg1_idx,
++			enum dfs_channel_type *channel_type);
++
++
++static bool dfs_use_radar_background(struct hostapd_iface *iface)
++{
++	return iface->drv_flags2 & WPA_DRIVER_RADAR_BACKGROUND;
++}
++
++
+ static int dfs_get_used_n_chans(struct hostapd_iface *iface, int *seg1)
+ {
+ 	int n_chans = 1;
+@@ -52,12 +71,6 @@ static int dfs_get_used_n_chans(struct hostapd_iface *iface, int *seg1)
+ }
+ 
+ 
+-enum dfs_channel_type {
+-	DFS_ANY_CHANNEL,
+-	DFS_AVAILABLE, /* non-radar or radar-available */
+-	DFS_NO_CAC_YET, /* radar-not-yet-available */
+-};
+-
+ /* dfs_channel_available: select new channel according to type parameter */
+ static int dfs_channel_available(struct hostapd_channel_data *chan,
+ 				 enum dfs_channel_type type)
+@@ -878,7 +891,8 @@ int hostapd_handle_dfs(struct hostapd_iface *iface)
+ 
+ 	/* Finally start CAC */
+ 	hostapd_set_state(iface, HAPD_IFACE_DFS);
+-	wpa_printf(MSG_DEBUG, "DFS start CAC on %d MHz", iface->freq);
++	wpa_printf(MSG_DEBUG, "DFS start CAC on %d MHz%s", iface->freq,
++		   dfs_use_radar_background(iface) ? " (background)" : "");
+ 	wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_CAC_START
+ 		"freq=%d chan=%d sec_chan=%d, width=%d, seg0=%d, seg1=%d, cac_time=%ds",
+ 		iface->freq,
+@@ -895,13 +909,37 @@ int hostapd_handle_dfs(struct hostapd_iface *iface)
+ 		iface->conf->secondary_channel,
+ 		hostapd_get_oper_chwidth(iface->conf),
+ 		hostapd_get_oper_centr_freq_seg0_idx(iface->conf),
+-		hostapd_get_oper_centr_freq_seg1_idx(iface->conf));
++		hostapd_get_oper_centr_freq_seg1_idx(iface->conf),
++		dfs_use_radar_background(iface));
+ 
+ 	if (res) {
+ 		wpa_printf(MSG_ERROR, "DFS start_dfs_cac() failed, %d", res);
+ 		return -1;
+ 	}
+ 
++	if (dfs_use_radar_background(iface)) {
++		/* Cache background radar parameters. */
++		iface->radar_background.channel = iface->conf->channel;
++		iface->radar_background.secondary_channel =
++			iface->conf->secondary_channel;
++		iface->radar_background.freq = iface->freq;
++		iface->radar_background.centr_freq_seg0_idx =
++			hostapd_get_oper_centr_freq_seg0_idx(iface->conf);
++		iface->radar_background.centr_freq_seg1_idx =
++			hostapd_get_oper_centr_freq_seg1_idx(iface->conf);
++
++		/*
++		 * Let's select a random channel according to the
++		 * regulations and perform CAC on dedicated radar chain.
++		 */
++		res = dfs_set_valid_channel(iface, 1);
++		if (res < 0)
++			return res;
++
++		iface->radar_background.temp_ch = 1;
++		return 1;
++	}
++
+ 	return 0;
+ }
+ 
+@@ -923,6 +961,86 @@ int hostapd_is_dfs_chan_available(struct hostapd_iface *iface)
+ }
+ 
+ 
++static void hostpad_dfs_update_background_chain(struct hostapd_iface *iface)
++{
++	int sec = 0;
++	enum dfs_channel_type channel_type = DFS_NO_CAC_YET;
++	struct hostapd_channel_data *channel;
++	u8 oper_centr_freq_seg0_idx = 0;
++	u8 oper_centr_freq_seg1_idx = 0;
++
++	/*
++	 * Allow selection of DFS channel in ETSI to comply with
++	 * uniform spreading.
++	 */
++	if (iface->dfs_domain == HOSTAPD_DFS_REGION_ETSI)
++		channel_type = DFS_ANY_CHANNEL;
++
++	channel = dfs_get_valid_channel(iface, &sec, &oper_centr_freq_seg0_idx,
++					&oper_centr_freq_seg1_idx,
++					channel_type);
++	if (!channel ||
++	    channel->chan == iface->conf->channel ||
++	    channel->chan == iface->radar_background.channel)
++		channel = dfs_downgrade_bandwidth(iface, &sec,
++						  &oper_centr_freq_seg0_idx,
++						  &oper_centr_freq_seg1_idx,
++						  &channel_type);
++	if (!channel ||
++	    hostapd_start_dfs_cac(iface, iface->conf->hw_mode,
++				  channel->freq, channel->chan,
++				  iface->conf->ieee80211n,
++				  iface->conf->ieee80211ac,
++				  iface->conf->ieee80211ax,
++				  sec, hostapd_get_oper_chwidth(iface->conf),
++				  oper_centr_freq_seg0_idx,
++				  oper_centr_freq_seg1_idx, true)) {
++		wpa_printf(MSG_ERROR, "DFS failed to start CAC offchannel");
++		iface->radar_background.channel = -1;
++		return;
++	}
++
++	iface->radar_background.channel = channel->chan;
++	iface->radar_background.freq = channel->freq;
++	iface->radar_background.secondary_channel = sec;
++	iface->radar_background.centr_freq_seg0_idx = oper_centr_freq_seg0_idx;
++	iface->radar_background.centr_freq_seg1_idx = oper_centr_freq_seg1_idx;
++
++	wpa_printf(MSG_DEBUG,
++		   "%s: setting background chain to chan %d (%d MHz)",
++		   __func__, channel->chan, channel->freq);
++}
++
++
++static bool
++hostapd_dfs_is_background_event(struct hostapd_iface *iface, int freq)
++{
++	return dfs_use_radar_background(iface) &&
++		iface->radar_background.channel != -1 &&
++		iface->radar_background.freq == freq;
++}
++
++
++static int
++hostapd_dfs_start_channel_switch_background(struct hostapd_iface *iface)
++{
++	iface->conf->channel = iface->radar_background.channel;
++	iface->freq = iface->radar_background.freq;
++	iface->conf->secondary_channel =
++		iface->radar_background.secondary_channel;
++	hostapd_set_oper_centr_freq_seg0_idx(
++		iface->conf, iface->radar_background.centr_freq_seg0_idx);
++	hostapd_set_oper_centr_freq_seg1_idx(
++		iface->conf, iface->radar_background.centr_freq_seg1_idx);
++
++	hostpad_dfs_update_background_chain(iface);
++	hostapd_disable_iface(iface);
++	hostapd_enable_iface(iface);
++
++	return 0;
++}
++
++
+ int hostapd_dfs_complete_cac(struct hostapd_iface *iface, int success, int freq,
+ 			     int ht_enabled, int chan_offset, int chan_width,
+ 			     int cf1, int cf2)
+@@ -943,6 +1061,22 @@ int hostapd_dfs_complete_cac(struct hostapd_iface *iface, int success, int freq,
+ 			set_dfs_state(iface, freq, ht_enabled, chan_offset,
+ 				      chan_width, cf1, cf2,
+ 				      HOSTAPD_CHAN_DFS_AVAILABLE);
++
++			/*
++			 * Radar event from background chain for the selected
++			 * channel. Perform CSA, move the main chain to the
++			 * selected channel and configure the background chain
++			 * to a new DFS channel.
++			 */
++			if (hostapd_dfs_is_background_event(iface, freq)) {
++				iface->radar_background.cac_started = 0;
++				if (!iface->radar_background.temp_ch)
++					return 0;
++
++				iface->radar_background.temp_ch = 0;
++				return hostapd_dfs_start_channel_switch_background(iface);
++			}
++
+ 			/*
+ 			 * Just mark the channel available when CAC completion
+ 			 * event is received in enabled state. CAC result could
+@@ -959,6 +1093,9 @@ int hostapd_dfs_complete_cac(struct hostapd_iface *iface, int success, int freq,
+ 				iface->cac_started = 0;
+ 			}
+ 		}
++	} else if (hostapd_dfs_is_background_event(iface, freq)) {
++		iface->radar_background.cac_started = 0;
++		hostpad_dfs_update_background_chain(iface);
+ 	}
+ 
+ 	return 0;
+@@ -1269,9 +1406,14 @@ int hostapd_dfs_nop_finished(struct hostapd_iface *iface, int freq,
+ 	set_dfs_state(iface, freq, ht_enabled, chan_offset, chan_width,
+ 		      cf1, cf2, HOSTAPD_CHAN_DFS_USABLE);
+ 
+-	/* Handle cases where all channels were initially unavailable */
+-	if (iface->state == HAPD_IFACE_DFS && !iface->cac_started)
++	if (iface->state == HAPD_IFACE_DFS && !iface->cac_started) {
++		/* Handle cases where all channels were initially unavailable */
+ 		hostapd_handle_dfs(iface);
++	} else if (dfs_use_radar_background(iface) &&
++		   iface->radar_background.channel == -1) {
++		/* Reset radar background chain if disabled */
++		hostpad_dfs_update_background_chain(iface);
++	}
+ 
+ 	return 0;
+ }
+@@ -1309,17 +1451,24 @@ int hostapd_dfs_start_cac(struct hostapd_iface *iface, int freq,
+ 			  int ht_enabled, int chan_offset, int chan_width,
+ 			  int cf1, int cf2)
+ {
+-	/* This is called when the driver indicates that an offloaded DFS has
+-	 * started CAC. */
+-	hostapd_set_state(iface, HAPD_IFACE_DFS);
++	if (hostapd_dfs_is_background_event(iface, freq)) {
++		iface->radar_background.cac_started = 1;
++	} else {
++		/* This is called when the driver indicates that an offloaded
++		 * DFS has started CAC. */
++		hostapd_set_state(iface, HAPD_IFACE_DFS);
++		iface->cac_started = 1;
++	}
+ 	/* TODO: How to check CAC time for ETSI weather channels? */
+ 	iface->dfs_cac_ms = 60000;
+ 	wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_CAC_START
+ 		"freq=%d chan=%d chan_offset=%d width=%d seg0=%d "
+-		"seg1=%d cac_time=%ds",
++		"seg1=%d cac_time=%ds%s",
+ 		freq, (freq - 5000) / 5, chan_offset, chan_width, cf1, cf2,
+-		iface->dfs_cac_ms / 1000);
+-	iface->cac_started = 1;
++		iface->dfs_cac_ms / 1000,
++		hostapd_dfs_is_background_event(iface, freq) ?
++		" (background)" : "");
++
+ 	os_get_reltime(&iface->dfs_cac_start);
+ 	return 0;
+ }
+diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h
+index a4ea32517..095524e49 100644
+--- a/src/ap/hostapd.h
++++ b/src/ap/hostapd.h
+@@ -541,6 +541,21 @@ struct hostapd_iface {
+ 	int *basic_rates;
+ 	int freq;
+ 
++	/* Background radar configuration */
++	struct {
++		int channel;
++		int secondary_channel;
++		int freq;
++		int centr_freq_seg0_idx;
++		int centr_freq_seg1_idx;
++		/* Main chain is on temporary channel during
++		 * CAC detection on radar offchain.
++		 */
++		unsigned int temp_ch:1;
++		/* CAC started on radar offchain */
++		unsigned int cac_started:1;
++	} radar_background;
++
+ 	u16 hw_flags;
+ 
+ 	/* Number of associated Non-ERP stations (i.e., stations using 802.11b
+-- 
+2.29.2
+
diff --git a/autobuild_mac80211_release/package/network/services/hostapd/patches/806-DFS-Introduce-hostapd_dfs_request_channel_switch.patch b/autobuild_mac80211_release/package/network/services/hostapd/patches/806-DFS-Introduce-hostapd_dfs_request_channel_switch.patch
new file mode 100644
index 0000000..da1cb94
--- /dev/null
+++ b/autobuild_mac80211_release/package/network/services/hostapd/patches/806-DFS-Introduce-hostapd_dfs_request_channel_switch.patch
@@ -0,0 +1,207 @@
+From 22eb74742a126bd356e6f25e3522e1c5bb5229ef Mon Sep 17 00:00:00 2001
+From: dzou <dzou@company.com>
+Date: Sun, 5 Jun 2022 23:21:17 +0800
+Subject: [PATCH 906/911] DFS: Introduce hostapd_dfs_request_channel_switch()
+
+This is a preliminary patch to add Channel Switch Announcement for
+background radar detection.
+
+Tested-by: Owen Peng <owen.peng@mediatek.com>
+Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
+---
+ src/ap/dfs.c | 163 ++++++++++++++++++++++++++++-----------------------
+ 1 file changed, 90 insertions(+), 73 deletions(-)
+
+diff --git a/src/ap/dfs.c b/src/ap/dfs.c
+index 5dc261589..000b411be 100644
+--- a/src/ap/dfs.c
++++ b/src/ap/dfs.c
+@@ -961,6 +961,90 @@ int hostapd_is_dfs_chan_available(struct hostapd_iface *iface)
+ }
+ 
+ 
++static int hostapd_dfs_request_channel_switch(struct hostapd_iface *iface,
++					      int channel, int freq,
++					      int secondary_channel,
++					      u8 current_vht_oper_chwidth,
++					      u8 oper_centr_freq_seg0_idx,
++					      u8 oper_centr_freq_seg1_idx)
++{
++	struct hostapd_hw_modes *cmode = iface->current_mode;
++	int ieee80211_mode = IEEE80211_MODE_AP, err;
++	struct csa_settings csa_settings;
++	u8 new_vht_oper_chwidth;
++	unsigned int i;
++
++	wpa_printf(MSG_DEBUG, "DFS will switch to a new channel %d", channel);
++	wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_NEW_CHANNEL
++		"freq=%d chan=%d sec_chan=%d", freq, channel,
++		secondary_channel);
++
++	new_vht_oper_chwidth = hostapd_get_oper_chwidth(iface->conf);
++	hostapd_set_oper_chwidth(iface->conf, current_vht_oper_chwidth);
++
++	/* Setup CSA request */
++	os_memset(&csa_settings, 0, sizeof(csa_settings));
++	csa_settings.cs_count = 5;
++	csa_settings.block_tx = 1;
++#ifdef CONFIG_MESH
++	if (iface->mconf)
++		ieee80211_mode = IEEE80211_MODE_MESH;
++#endif /* CONFIG_MESH */
++	err = hostapd_set_freq_params(&csa_settings.freq_params,
++				      iface->conf->hw_mode,
++				      freq, channel,
++				      iface->conf->enable_edmg,
++				      iface->conf->edmg_channel,
++				      iface->conf->ieee80211n,
++				      iface->conf->ieee80211ac,
++				      iface->conf->ieee80211ax,
++				      secondary_channel,
++				      new_vht_oper_chwidth,
++				      oper_centr_freq_seg0_idx,
++				      oper_centr_freq_seg1_idx,
++				      cmode->vht_capab,
++				      &cmode->he_capab[ieee80211_mode]);
++
++	if (err) {
++		wpa_printf(MSG_ERROR,
++			   "DFS failed to calculate CSA freq params");
++		hostapd_disable_iface(iface);
++		return err;
++	}
++
++	for (i = 0; i < iface->num_bss; i++) {
++		err = hostapd_switch_channel(iface->bss[i], &csa_settings);
++		if (err)
++			break;
++	}
++
++	if (err) {
++		wpa_printf(MSG_WARNING,
++			   "DFS failed to schedule CSA (%d) - trying fallback",
++			   err);
++		iface->freq = freq;
++		iface->conf->channel = channel;
++		iface->conf->secondary_channel = secondary_channel;
++		hostapd_set_oper_chwidth(iface->conf, new_vht_oper_chwidth);
++		hostapd_set_oper_centr_freq_seg0_idx(iface->conf,
++						     oper_centr_freq_seg0_idx);
++		hostapd_set_oper_centr_freq_seg1_idx(iface->conf,
++						     oper_centr_freq_seg1_idx);
++
++		hostapd_disable_iface(iface);
++		hostapd_enable_iface(iface);
++
++		return 0;
++	}
++
++	/* Channel configuration will be updated once CSA completes and
++	 * ch_switch_notify event is received */
++	wpa_printf(MSG_DEBUG, "DFS waiting channel switch event");
++
++	return 0;
++}
++
++
+ static void hostpad_dfs_update_background_chain(struct hostapd_iface *iface)
+ {
+ 	int sec = 0;
+@@ -1213,14 +1297,8 @@ static int hostapd_dfs_start_channel_switch(struct hostapd_iface *iface)
+ 	int secondary_channel;
+ 	u8 oper_centr_freq_seg0_idx;
+ 	u8 oper_centr_freq_seg1_idx;
+-	u8 new_vht_oper_chwidth;
+ 	enum dfs_channel_type channel_type = DFS_AVAILABLE;
+-	struct csa_settings csa_settings;
+-	unsigned int i;
+-	int err = 1;
+-	struct hostapd_hw_modes *cmode = iface->current_mode;
+ 	u8 current_vht_oper_chwidth = hostapd_get_oper_chwidth(iface->conf);
+-	int ieee80211_mode = IEEE80211_MODE_AP;
+ 
+ 	wpa_printf(MSG_DEBUG, "%s called (CAC active: %s, CSA active: %s)",
+ 		   __func__, iface->cac_started ? "yes" : "no",
+@@ -1283,73 +1361,12 @@ static int hostapd_dfs_start_channel_switch(struct hostapd_iface *iface)
+ 		}
+ 	}
+ 
+-	wpa_printf(MSG_DEBUG, "DFS will switch to a new channel %d",
+-		   channel->chan);
+-	wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_NEW_CHANNEL
+-		"freq=%d chan=%d sec_chan=%d", channel->freq,
+-		channel->chan, secondary_channel);
+-
+-	new_vht_oper_chwidth = hostapd_get_oper_chwidth(iface->conf);
+-	hostapd_set_oper_chwidth(iface->conf, current_vht_oper_chwidth);
+-
+-	/* Setup CSA request */
+-	os_memset(&csa_settings, 0, sizeof(csa_settings));
+-	csa_settings.cs_count = 5;
+-	csa_settings.block_tx = 1;
+-#ifdef CONFIG_MESH
+-	if (iface->mconf)
+-		ieee80211_mode = IEEE80211_MODE_MESH;
+-#endif /* CONFIG_MESH */
+-	err = hostapd_set_freq_params(&csa_settings.freq_params,
+-				      iface->conf->hw_mode,
+-				      channel->freq,
+-				      channel->chan,
+-				      iface->conf->enable_edmg,
+-				      iface->conf->edmg_channel,
+-				      iface->conf->ieee80211n,
+-				      iface->conf->ieee80211ac,
+-				      iface->conf->ieee80211ax,
+-				      secondary_channel,
+-				      new_vht_oper_chwidth,
+-				      oper_centr_freq_seg0_idx,
+-				      oper_centr_freq_seg1_idx,
+-				      cmode->vht_capab,
+-				      &cmode->he_capab[ieee80211_mode]);
+-
+-	if (err) {
+-		wpa_printf(MSG_ERROR, "DFS failed to calculate CSA freq params");
+-		hostapd_disable_iface(iface);
+-		return err;
+-	}
+-
+-	for (i = 0; i < iface->num_bss; i++) {
+-		err = hostapd_switch_channel(iface->bss[i], &csa_settings);
+-		if (err)
+-			break;
+-	}
+-
+-	if (err) {
+-		wpa_printf(MSG_WARNING, "DFS failed to schedule CSA (%d) - trying fallback",
+-			   err);
+-		iface->freq = channel->freq;
+-		iface->conf->channel = channel->chan;
+-		iface->conf->secondary_channel = secondary_channel;
+-		hostapd_set_oper_chwidth(iface->conf, new_vht_oper_chwidth);
+-		hostapd_set_oper_centr_freq_seg0_idx(iface->conf,
+-						     oper_centr_freq_seg0_idx);
+-		hostapd_set_oper_centr_freq_seg1_idx(iface->conf,
+-						     oper_centr_freq_seg1_idx);
+-
+-		hostapd_disable_iface(iface);
+-		hostapd_enable_iface(iface);
+-		return 0;
+-	}
+-
+-	/* Channel configuration will be updated once CSA completes and
+-	 * ch_switch_notify event is received */
+-
+-	wpa_printf(MSG_DEBUG, "DFS waiting channel switch event");
+-	return 0;
++	return hostapd_dfs_request_channel_switch(iface, channel->chan,
++						  channel->freq,
++						  secondary_channel,
++						  current_vht_oper_chwidth,
++						  oper_centr_freq_seg0_idx,
++						  oper_centr_freq_seg1_idx);
+ }
+ 
+ 
+-- 
+2.29.2
+
diff --git a/autobuild_mac80211_release/package/network/services/hostapd/patches/807-DFS-Enable-CSA-for-background-radar-detection.patch b/autobuild_mac80211_release/package/network/services/hostapd/patches/807-DFS-Enable-CSA-for-background-radar-detection.patch
new file mode 100644
index 0000000..bd258ad
--- /dev/null
+++ b/autobuild_mac80211_release/package/network/services/hostapd/patches/807-DFS-Enable-CSA-for-background-radar-detection.patch
@@ -0,0 +1,46 @@
+From 4445b818de45ca5511e81dc535606a368c97b86d Mon Sep 17 00:00:00 2001
+From: dzou <dzou@company.com>
+Date: Sun, 5 Jun 2022 23:22:12 +0800
+Subject: [PATCH 907/911] DFS: Enable CSA for background radar detection
+
+Rely on hostapd_dfs_request_channel_switch() to enable CSA for
+background radar detection switching back to the selected channel.
+
+Tested-by: Owen Peng <owen.peng@mediatek.com>
+Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
+---
+ src/ap/dfs.c | 10 +++++++---
+ 1 file changed, 7 insertions(+), 3 deletions(-)
+
+diff --git a/src/ap/dfs.c b/src/ap/dfs.c
+index 000b411be..1224acd31 100644
+--- a/src/ap/dfs.c
++++ b/src/ap/dfs.c
+@@ -1108,6 +1108,8 @@ hostapd_dfs_is_background_event(struct hostapd_iface *iface, int freq)
+ static int
+ hostapd_dfs_start_channel_switch_background(struct hostapd_iface *iface)
+ {
++	u8 current_vht_oper_chwidth = hostapd_get_oper_chwidth(iface->conf);
++
+ 	iface->conf->channel = iface->radar_background.channel;
+ 	iface->freq = iface->radar_background.freq;
+ 	iface->conf->secondary_channel =
+@@ -1118,10 +1120,12 @@ hostapd_dfs_start_channel_switch_background(struct hostapd_iface *iface)
+ 		iface->conf, iface->radar_background.centr_freq_seg1_idx);
+ 
+ 	hostpad_dfs_update_background_chain(iface);
+-	hostapd_disable_iface(iface);
+-	hostapd_enable_iface(iface);
+ 
+-	return 0;
++	return hostapd_dfs_request_channel_switch(
++		iface, iface->conf->channel, iface->freq,
++		iface->conf->secondary_channel, current_vht_oper_chwidth,
++		hostapd_get_oper_centr_freq_seg0_idx(iface->conf),
++		hostapd_get_oper_centr_freq_seg1_idx(iface->conf));
+ }
+ 
+ 
+-- 
+2.29.2
+
diff --git a/autobuild_mac80211_release/package/network/services/hostapd/patches/808-DFS-Switch-to-background-radar-channel-if-available.patch b/autobuild_mac80211_release/package/network/services/hostapd/patches/808-DFS-Switch-to-background-radar-channel-if-available.patch
new file mode 100644
index 0000000..b6b0b86
--- /dev/null
+++ b/autobuild_mac80211_release/package/network/services/hostapd/patches/808-DFS-Switch-to-background-radar-channel-if-available.patch
@@ -0,0 +1,104 @@
+From 5615f7c8b3abded17febe19e0d4f9914b561285c Mon Sep 17 00:00:00 2001
+From: dzou <dzou@company.com>
+Date: Sun, 5 Jun 2022 23:22:49 +0800
+Subject: [PATCH 908/911] DFS: Switch to background radar channel if available
+
+On radar detection on the main chain switch to the channel monitored
+by the background chain if we have already performed the CAC there.
+If a radar pattern is reported on the background chain, just select a
+new random channel according to the regulations for monitoring.
+
+Tested-by: Owen Peng <owen.peng@mediatek.com>
+Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
+---
+ src/ap/dfs.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++------
+ 1 file changed, 58 insertions(+), 7 deletions(-)
+
+diff --git a/src/ap/dfs.c b/src/ap/dfs.c
+index 1224acd31..d63caaee3 100644
+--- a/src/ap/dfs.c
++++ b/src/ap/dfs.c
+@@ -1295,6 +1295,53 @@ static int hostapd_dfs_start_channel_switch_cac(struct hostapd_iface *iface)
+ }
+ 
+ 
++static int
++hostapd_dfs_background_start_channel_switch(struct hostapd_iface *iface,
++					    int freq)
++{
++	if (!dfs_use_radar_background(iface))
++		return -1; /* Background radar chain not supported. */
++
++	wpa_printf(MSG_DEBUG,
++		   "%s called (background CAC active: %s, CSA active: %s)",
++		   __func__, iface->radar_background.cac_started ? "yes" : "no",
++		   hostapd_csa_in_progress(iface) ? "yes" : "no");
++
++	/* Check if CSA in progress */
++	if (hostapd_csa_in_progress(iface))
++		return 0;
++
++	if (hostapd_dfs_is_background_event(iface, freq)) {
++		/*
++		 * Radar pattern is reported on the background chain.
++		 * Just select a new random channel according to the
++		 * regulations for monitoring.
++		 */
++		hostpad_dfs_update_background_chain(iface);
++		return 0;
++	}
++
++	/*
++	 * If background radar detection is supported and the radar channel
++	 * monitored by the background chain is available switch to it without
++	 * waiting for the CAC.
++	 */
++	if (iface->radar_background.channel == -1)
++		return -1; /* Background radar chain not available. */
++
++	if (iface->radar_background.cac_started) {
++		/*
++		 * Background channel not available yet. Perform CAC on the
++		 * main chain.
++		 */
++		iface->radar_background.temp_ch = 1;
++		return -1;
++	}
++
++	return hostapd_dfs_start_channel_switch_background(iface);
++}
++
++
+ static int hostapd_dfs_start_channel_switch(struct hostapd_iface *iface)
+ {
+ 	struct hostapd_channel_data *channel;
+@@ -1399,15 +1446,19 @@ int hostapd_dfs_radar_detected(struct hostapd_iface *iface, int freq,
+ 	if (!res)
+ 		return 0;
+ 
+-	/* Skip if reported radar event not overlapped our channels */
+-	res = dfs_are_channels_overlapped(iface, freq, chan_width, cf1, cf2);
+-	if (!res)
+-		return 0;
++	if (!hostapd_dfs_is_background_event(iface, freq)) {
++		/* Skip if reported radar event not overlapped our channels */
++		if (!dfs_are_channels_overlapped(iface, freq, chan_width,
++						 cf1, cf2))
++			return 0;
++	}
+ 
+-	/* radar detected while operating, switch the channel. */
+-	res = hostapd_dfs_start_channel_switch(iface);
++	if (hostapd_dfs_background_start_channel_switch(iface, freq)) {
++		/* Radar detected while operating, switch the channel. */
++		return hostapd_dfs_start_channel_switch(iface);
++	}
+ 
+-	return res;
++	return 0;
+ }
+ 
+ 
+-- 
+2.29.2
+
diff --git a/autobuild_mac80211_release/package/network/services/hostapd/patches/809-hostapd-Allow-enabling-background-radar.patch b/autobuild_mac80211_release/package/network/services/hostapd/patches/809-hostapd-Allow-enabling-background-radar.patch
new file mode 100644
index 0000000..82ce87f
--- /dev/null
+++ b/autobuild_mac80211_release/package/network/services/hostapd/patches/809-hostapd-Allow-enabling-background-radar.patch
@@ -0,0 +1,81 @@
+From c9205badb2f9bc385c3cdfe74ceae033fc3e4923 Mon Sep 17 00:00:00 2001
+From: dzou <dzou@company.com>
+Date: Sun, 5 Jun 2022 23:23:40 +0800
+Subject: [PATCH 909/911] hostapd: Allow enabling background radar
+
+This feature does not work on all radios that advertise this feature
+with the current driver implementation, and possibly some users don't
+want to use it even if it works fine, so disable it by default for now,
+but let users enable it as desired with enable_background_radar=1.
+
+Signed-off-by: Ben Greear <greearb@candelatech.com>
+---
+ hostapd/config_file.c |  2 ++
+ hostapd/hostapd.conf  | 10 ++++++++++
+ src/ap/ap_config.h    |  1 +
+ src/ap/dfs.c          |  3 ++-
+ 4 files changed, 15 insertions(+), 1 deletion(-)
+
+diff --git a/hostapd/config_file.c b/hostapd/config_file.c
+index 0d3554375..b423789b8 100644
+--- a/hostapd/config_file.c
++++ b/hostapd/config_file.c
+@@ -3211,6 +3211,8 @@ static int hostapd_config_fill(struct hostapd_config *conf,
+ 		conf->acs_freq_list_present = 1;
+ 	} else if (os_strcmp(buf, "acs_exclude_6ghz_non_psc") == 0) {
+ 		conf->acs_exclude_6ghz_non_psc = atoi(pos);
++	} else if (os_strcmp(buf, "enable_background_radar") == 0) {
++		conf->enable_background_radar = atoi(pos);
+ 	} else if (os_strcmp(buf, "min_tx_power") == 0) {
+ 		int val = atoi(pos);
+ 
+diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf
+index 3c2019f73..f839ba708 100644
+--- a/hostapd/hostapd.conf
++++ b/hostapd/hostapd.conf
+@@ -225,6 +225,16 @@ channel=1
+ # Default behavior is to include all PSC and non-PSC channels.
+ #acs_exclude_6ghz_non_psc=1
+ 
++# Enable background radar feature
++# This feature allows CAC to be run on dedicated radio RF chains while the
++# radio(s) are otherwise running normal AP activities on other channels.
++# This requires that the driver and the radio support it before feature will
++# actually be enabled, i.e., this parameter value is ignored with drivers that
++# do not advertise support for the capability.
++# 0: Leave disabled (default)
++# 1: Enable it.
++#enable_background_radar=1
++
+ # Set minimum permitted max TX power (in dBm) for ACS and DFS channel selection.
+ # (default 0, i.e., not constraint)
+ #min_tx_power=20
+diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
+index f3aff369f..8ed7c2aa1 100644
+--- a/src/ap/ap_config.h
++++ b/src/ap/ap_config.h
+@@ -964,6 +964,7 @@ struct hostapd_config {
+ 	u8 min_tx_power;
+ 	enum hostapd_hw_mode hw_mode; /* HOSTAPD_MODE_IEEE80211A, .. */
+ 	int acs_exclude_6ghz_non_psc;
++	int enable_background_radar;
+ 	enum {
+ 		LONG_PREAMBLE = 0,
+ 		SHORT_PREAMBLE = 1
+diff --git a/src/ap/dfs.c b/src/ap/dfs.c
+index d63caaee3..48cd93507 100644
+--- a/src/ap/dfs.c
++++ b/src/ap/dfs.c
+@@ -35,7 +35,8 @@ dfs_downgrade_bandwidth(struct hostapd_iface *iface, int *secondary_channel,
+ 
+ static bool dfs_use_radar_background(struct hostapd_iface *iface)
+ {
+-	return iface->drv_flags2 & WPA_DRIVER_RADAR_BACKGROUND;
++	return (iface->drv_flags2 & WPA_DRIVER_RADAR_BACKGROUND) &&
++		iface->conf->enable_background_radar;
+ }
+ 
+ 
+-- 
+2.29.2
+
diff --git a/autobuild_mac80211_release/package/network/services/hostapd/patches/810-nl80211-Verify-that-nla_put_flag-succeeds-for-backgr.patch b/autobuild_mac80211_release/package/network/services/hostapd/patches/810-nl80211-Verify-that-nla_put_flag-succeeds-for-backgr.patch
new file mode 100644
index 0000000..d9561da
--- /dev/null
+++ b/autobuild_mac80211_release/package/network/services/hostapd/patches/810-nl80211-Verify-that-nla_put_flag-succeeds-for-backgr.patch
@@ -0,0 +1,30 @@
+From f16170300d304dbfc7c4d265101136ae2dc912b0 Mon Sep 17 00:00:00 2001
+From: dzou <dzou@company.com>
+Date: Sun, 5 Jun 2022 23:24:20 +0800
+Subject: [PATCH 910/911] nl80211: Verify that nla_put_flag() succeeds for
+ background radar
+
+Signed-off-by: Jouni Malinen <j@w1.fi>
+---
+ src/drivers/driver_nl80211.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
+index 6cf127ca7..9de01f391 100644
+--- a/src/drivers/driver_nl80211.c
++++ b/src/drivers/driver_nl80211.c
+@@ -4980,8 +4980,9 @@ static int nl80211_put_freq_params(struct nl_msg *msg,
+ 				NL80211_CHAN_NO_HT))
+ 			return -ENOBUFS;
+ 	}
+-	if (freq->radar_background)
+-		nla_put_flag(msg, NL80211_ATTR_RADAR_BACKGROUND);
++	if (freq->radar_background &&
++	    nla_put_flag(msg, NL80211_ATTR_RADAR_BACKGROUND))
++		return -ENOBUFS;
+ 
+ 	return 0;
+ }
+-- 
+2.29.2
+
diff --git a/autobuild_mac80211_release/package/network/services/hostapd/patches/811-Sync-with-mac80211-next.git-include-uapi-linux-nl802.patch b/autobuild_mac80211_release/package/network/services/hostapd/patches/811-Sync-with-mac80211-next.git-include-uapi-linux-nl802.patch
new file mode 100644
index 0000000..7d1ae65
--- /dev/null
+++ b/autobuild_mac80211_release/package/network/services/hostapd/patches/811-Sync-with-mac80211-next.git-include-uapi-linux-nl802.patch
@@ -0,0 +1,414 @@
+From 3204e0177e4d67fb1500c8296ee062110852383b Mon Sep 17 00:00:00 2001
+From: dzou <dzou@company.com>
+Date: Sun, 5 Jun 2022 23:46:07 +0800
+Subject: [PATCH 911/911] Sync with mac80211-next.git
+ include/uapi/linux/nl80211.h
+
+This brings in nl80211 definitions as of 2022-01-04. In addition, update
+nl80211_command_to_string() to cover the new defined commands.
+
+Signed-off-by: Jouni Malinen <j@w1.fi>
+---
+ src/drivers/driver_nl80211_event.c |   7 +
+ src/drivers/nl80211_copy.h         | 230 +++++++++++++++++++++++++++--
+ 2 files changed, 226 insertions(+), 11 deletions(-)
+
+diff --git a/src/drivers/driver_nl80211_event.c b/src/drivers/driver_nl80211_event.c
+index c44cc27e8..83d32ed6d 100644
+--- a/src/drivers/driver_nl80211_event.c
++++ b/src/drivers/driver_nl80211_event.c
+@@ -172,6 +172,13 @@ static const char * nl80211_command_to_string(enum nl80211_commands cmd)
+ 	C2S(NL80211_CMD_UNPROT_BEACON)
+ 	C2S(NL80211_CMD_CONTROL_PORT_FRAME_TX_STATUS)
+ 	C2S(NL80211_CMD_SET_SAR_SPECS)
++	C2S(NL80211_CMD_OBSS_COLOR_COLLISION)
++	C2S(NL80211_CMD_COLOR_CHANGE_REQUEST)
++	C2S(NL80211_CMD_COLOR_CHANGE_STARTED)
++	C2S(NL80211_CMD_COLOR_CHANGE_ABORTED)
++	C2S(NL80211_CMD_COLOR_CHANGE_COMPLETED)
++	C2S(NL80211_CMD_SET_FILS_AAD)
++	C2S(NL80211_CMD_ASSOC_COMEBACK)
+ 	C2S(__NL80211_CMD_AFTER_LAST)
+ 	}
+ #undef C2S
+diff --git a/src/drivers/nl80211_copy.h b/src/drivers/nl80211_copy.h
+index f962c06e9..195a238a3 100644
+--- a/src/drivers/nl80211_copy.h
++++ b/src/drivers/nl80211_copy.h
+@@ -11,7 +11,7 @@
+  * Copyright 2008 Jouni Malinen <jouni.malinen@atheros.com>
+  * Copyright 2008 Colin McCabe <colin@cozybit.com>
+  * Copyright 2015-2017	Intel Deutschland GmbH
+- * Copyright (C) 2018-2020 Intel Corporation
++ * Copyright (C) 2018-2021 Intel Corporation
+  *
+  * Permission to use, copy, modify, and/or distribute this software for any
+  * purpose with or without fee is hereby granted, provided that the above
+@@ -300,6 +300,29 @@
+  * the interface goes down.
+  */
+ 
++/**
++ * DOC: FILS shared key crypto offload
++ *
++ * This feature is applicable to drivers running in AP mode.
++ *
++ * FILS shared key crypto offload can be advertised by drivers by setting
++ * @NL80211_EXT_FEATURE_FILS_CRYPTO_OFFLOAD flag. The drivers that support
++ * FILS shared key crypto offload should be able to encrypt and decrypt
++ * association frames for FILS shared key authentication as per IEEE 802.11ai.
++ * With this capability, for FILS key derivation, drivers depend on userspace.
++ *
++ * After FILS key derivation, userspace shares the FILS AAD details with the
++ * driver and the driver stores the same to use in decryption of association
++ * request and in encryption of association response. The below parameters
++ * should be given to the driver in %NL80211_CMD_SET_FILS_AAD.
++ *	%NL80211_ATTR_MAC - STA MAC address, used for storing FILS AAD per STA
++ *	%NL80211_ATTR_FILS_KEK - Used for encryption or decryption
++ *	%NL80211_ATTR_FILS_NONCES - Used for encryption or decryption
++ *			(STA Nonce 16 bytes followed by AP Nonce 16 bytes)
++ *
++ * Once the association is done, the driver cleans the FILS AAD data.
++ */
++
+ /**
+  * enum nl80211_commands - supported nl80211 commands
+  *
+@@ -337,7 +360,10 @@
+  * @NL80211_CMD_DEL_INTERFACE: Virtual interface was deleted, has attributes
+  *	%NL80211_ATTR_IFINDEX and %NL80211_ATTR_WIPHY. Can also be sent from
+  *	userspace to request deletion of a virtual interface, then requires
+- *	attribute %NL80211_ATTR_IFINDEX.
++ *	attribute %NL80211_ATTR_IFINDEX. If multiple BSSID advertisements are
++ *	enabled using %NL80211_ATTR_MBSSID_CONFIG, %NL80211_ATTR_MBSSID_ELEMS,
++ *	and if this command is used for the transmitting interface, then all
++ *	the non-transmitting interfaces are deleted as well.
+  *
+  * @NL80211_CMD_GET_KEY: Get sequence counter information for a key specified
+  *	by %NL80211_ATTR_KEY_IDX and/or %NL80211_ATTR_MAC.
+@@ -1185,6 +1211,32 @@
+  *	passed using %NL80211_ATTR_SAR_SPEC. %NL80211_ATTR_WIPHY is used to
+  *	specify the wiphy index to be applied to.
+  *
++ * @NL80211_CMD_OBSS_COLOR_COLLISION: This notification is sent out whenever
++ *	mac80211/drv detects a bss color collision.
++ *
++ * @NL80211_CMD_COLOR_CHANGE_REQUEST: This command is used to indicate that
++ *	userspace wants to change the BSS color.
++ *
++ * @NL80211_CMD_COLOR_CHANGE_STARTED: Notify userland, that a color change has
++ *	started
++ *
++ * @NL80211_CMD_COLOR_CHANGE_ABORTED: Notify userland, that the color change has
++ *	been aborted
++ *
++ * @NL80211_CMD_COLOR_CHANGE_COMPLETED: Notify userland that the color change
++ *	has completed
++ *
++ * @NL80211_CMD_SET_FILS_AAD: Set FILS AAD data to the driver using -
++ *	&NL80211_ATTR_MAC - for STA MAC address
++ *	&NL80211_ATTR_FILS_KEK - for KEK
++ *	&NL80211_ATTR_FILS_NONCES - for FILS Nonces
++ *		(STA Nonce 16 bytes followed by AP Nonce 16 bytes)
++ *
++ * @NL80211_CMD_ASSOC_COMEBACK: notification about an association
++ *      temporal rejection with comeback. The event includes %NL80211_ATTR_MAC
++ *      to describe the BSSID address of the AP and %NL80211_ATTR_TIMEOUT to
++ *      specify the timeout value.
++ *
+  * @NL80211_CMD_MAX: highest used command number
+  * @__NL80211_CMD_AFTER_LAST: internal use
+  */
+@@ -1417,6 +1469,18 @@ enum nl80211_commands {
+ 
+ 	NL80211_CMD_SET_SAR_SPECS,
+ 
++	NL80211_CMD_OBSS_COLOR_COLLISION,
++
++	NL80211_CMD_COLOR_CHANGE_REQUEST,
++
++	NL80211_CMD_COLOR_CHANGE_STARTED,
++	NL80211_CMD_COLOR_CHANGE_ABORTED,
++	NL80211_CMD_COLOR_CHANGE_COMPLETED,
++
++	NL80211_CMD_SET_FILS_AAD,
++
++	NL80211_CMD_ASSOC_COMEBACK,
++
+ 	/* add new commands above here */
+ 
+ 	/* used to define NL80211_CMD_MAX below */
+@@ -2413,7 +2477,9 @@ enum nl80211_commands {
+  *	space supports external authentication. This attribute shall be used
+  *	with %NL80211_CMD_CONNECT and %NL80211_CMD_START_AP request. The driver
+  *	may offload authentication processing to user space if this capability
+- *	is indicated in the respective requests from the user space.
++ *	is indicated in the respective requests from the user space. (This flag
++ *	attribute deprecated for %NL80211_CMD_START_AP, use
++ *	%NL80211_ATTR_AP_SETTINGS_FLAGS)
+  *
+  * @NL80211_ATTR_NSS: Station's New/updated  RX_NSS value notified using this
+  *	u8 attribute. This is used with %NL80211_CMD_STA_OPMODE_CHANGED.
+@@ -2560,6 +2626,39 @@ enum nl80211_commands {
+  *	disassoc events to indicate that an immediate reconnect to the AP
+  *	is desired.
+  *
++ * @NL80211_ATTR_OBSS_COLOR_BITMAP: bitmap of the u64 BSS colors for the
++ *	%NL80211_CMD_OBSS_COLOR_COLLISION event.
++ *
++ * @NL80211_ATTR_COLOR_CHANGE_COUNT: u8 attribute specifying the number of TBTT's
++ *	until the color switch event.
++ * @NL80211_ATTR_COLOR_CHANGE_COLOR: u8 attribute specifying the color that we are
++ *	switching to
++ * @NL80211_ATTR_COLOR_CHANGE_ELEMS: Nested set of attributes containing the IE
++ *	information for the time while performing a color switch.
++ *
++ * @NL80211_ATTR_MBSSID_CONFIG: Nested attribute for multiple BSSID
++ *	advertisements (MBSSID) parameters in AP mode.
++ *	Kernel uses this attribute to indicate the driver's support for MBSSID
++ *	and enhanced multi-BSSID advertisements (EMA AP) to the userspace.
++ *	Userspace should use this attribute to configure per interface MBSSID
++ *	parameters.
++ *	See &enum nl80211_mbssid_config_attributes for details.
++ *
++ * @NL80211_ATTR_MBSSID_ELEMS: Nested parameter to pass multiple BSSID elements.
++ *	Mandatory parameter for the transmitting interface to enable MBSSID.
++ *	Optional for the non-transmitting interfaces.
++ *
++ * @NL80211_ATTR_RADAR_BACKGROUND: Configure dedicated offchannel chain
++ *	available for radar/CAC detection on some hw. This chain can't be used
++ *	to transmit or receive frames and it is bounded to a running wdev.
++ *	Background radar/CAC detection allows to avoid the CAC downtime
++ *	switching on a different channel during CAC detection on the selected
++ *	radar channel.
++ *
++ * @NL80211_ATTR_AP_SETTINGS_FLAGS: u32 attribute contains ap settings flags,
++ *	enumerated in &enum nl80211_ap_settings_flags. This attribute shall be
++ *	used with %NL80211_CMD_START_AP request.
++ *
+  * @NUM_NL80211_ATTR: total number of nl80211_attrs available
+  * @NL80211_ATTR_MAX: highest attribute number currently defined
+  * @__NL80211_ATTR_AFTER_LAST: internal use
+@@ -3057,6 +3156,19 @@ enum nl80211_attrs {
+ 
+ 	NL80211_ATTR_DISABLE_HE,
+ 
++	NL80211_ATTR_OBSS_COLOR_BITMAP,
++
++	NL80211_ATTR_COLOR_CHANGE_COUNT,
++	NL80211_ATTR_COLOR_CHANGE_COLOR,
++	NL80211_ATTR_COLOR_CHANGE_ELEMS,
++
++	NL80211_ATTR_MBSSID_CONFIG,
++	NL80211_ATTR_MBSSID_ELEMS,
++
++	NL80211_ATTR_RADAR_BACKGROUND,
++
++	NL80211_ATTR_AP_SETTINGS_FLAGS,
++
+ 	/* add attributes here, update the policy in nl80211.c */
+ 
+ 	__NL80211_ATTR_AFTER_LAST,
+@@ -3650,11 +3762,12 @@ enum nl80211_mpath_info {
+  *     capabilities IE
+  * @NL80211_BAND_IFTYPE_ATTR_HE_CAP_PPE: HE PPE thresholds information as
+  *     defined in HE capabilities IE
+- * @NL80211_BAND_IFTYPE_ATTR_MAX: highest band HE capability attribute currently
+- *     defined
+  * @NL80211_BAND_IFTYPE_ATTR_HE_6GHZ_CAPA: HE 6GHz band capabilities (__le16),
+  *	given for all 6 GHz band channels
++ * @NL80211_BAND_IFTYPE_ATTR_VENDOR_ELEMS: vendor element capabilities that are
++ *	advertised on this band/for this iftype (binary)
+  * @__NL80211_BAND_IFTYPE_ATTR_AFTER_LAST: internal use
++ * @NL80211_BAND_IFTYPE_ATTR_MAX: highest band attribute currently defined
+  */
+ enum nl80211_band_iftype_attr {
+ 	__NL80211_BAND_IFTYPE_ATTR_INVALID,
+@@ -3665,6 +3778,7 @@ enum nl80211_band_iftype_attr {
+ 	NL80211_BAND_IFTYPE_ATTR_HE_CAP_MCS_SET,
+ 	NL80211_BAND_IFTYPE_ATTR_HE_CAP_PPE,
+ 	NL80211_BAND_IFTYPE_ATTR_HE_6GHZ_CAPA,
++	NL80211_BAND_IFTYPE_ATTR_VENDOR_ELEMS,
+ 
+ 	/* keep last */
+ 	__NL80211_BAND_IFTYPE_ATTR_AFTER_LAST,
+@@ -4887,6 +5001,7 @@ enum nl80211_txrate_gi {
+  * @NL80211_BAND_60GHZ: around 60 GHz band (58.32 - 69.12 GHz)
+  * @NL80211_BAND_6GHZ: around 6 GHz band (5.9 - 7.2 GHz)
+  * @NL80211_BAND_S1GHZ: around 900MHz, supported by S1G PHYs
++ * @NL80211_BAND_LC: light communication band (placeholder)
+  * @NUM_NL80211_BANDS: number of bands, avoid using this in userspace
+  *	since newer kernel versions may support more bands
+  */
+@@ -4896,6 +5011,7 @@ enum nl80211_band {
+ 	NL80211_BAND_60GHZ,
+ 	NL80211_BAND_6GHZ,
+ 	NL80211_BAND_S1GHZ,
++	NL80211_BAND_LC,
+ 
+ 	NUM_NL80211_BANDS,
+ };
+@@ -5462,7 +5578,7 @@ enum nl80211_iface_limit_attrs {
+  *	=> allows 8 of AP/GO that can have BI gcd >= min gcd
+  *
+  *	numbers = [ #{STA} <= 2 ], channels = 2, max = 2
+- *	=> allows two STAs on different channels
++ *	=> allows two STAs on the same or on different channels
+  *
+  *	numbers = [ #{STA} <= 1, #{P2P-client,P2P-GO} <= 3 ], max = 4
+  *	=> allows a STA plus three P2P interfaces
+@@ -5507,7 +5623,7 @@ enum nl80211_if_combination_attrs {
+  * @NL80211_PLINK_ESTAB: mesh peer link is established
+  * @NL80211_PLINK_HOLDING: mesh peer link is being closed or cancelled
+  * @NL80211_PLINK_BLOCKED: all frames transmitted from this mesh
+- *	plink are discarded
++ *	plink are discarded, except for authentication frames
+  * @NUM_NL80211_PLINK_STATES: number of peer link states
+  * @MAX_NL80211_PLINK_STATES: highest numerical value of plink states
+  */
+@@ -5644,13 +5760,15 @@ enum nl80211_tdls_operation {
+ 	NL80211_TDLS_DISABLE_LINK,
+ };
+ 
+-/*
++/**
+  * enum nl80211_ap_sme_features - device-integrated AP features
+- * Reserved for future use, no bits are defined in
+- * NL80211_ATTR_DEVICE_AP_SME yet.
++ * @NL80211_AP_SME_SA_QUERY_OFFLOAD: SA Query procedures offloaded to driver
++ *	when user space indicates support for SA Query procedures offload during
++ *	"start ap" with %NL80211_AP_SETTINGS_SA_QUERY_OFFLOAD_SUPPORT.
++ */
+ enum nl80211_ap_sme_features {
++	NL80211_AP_SME_SA_QUERY_OFFLOAD		= 1 << 0,
+ };
+- */
+ 
+ /**
+  * enum nl80211_feature_flags - device/driver features
+@@ -5950,6 +6068,17 @@ enum nl80211_feature_flags {
+  *      frame protection for all management frames exchanged during the
+  *      negotiation and range measurement procedure.
+  *
++ * @NL80211_EXT_FEATURE_BSS_COLOR: The driver supports BSS color collision
++ *	detection and change announcemnts.
++ *
++ * @NL80211_EXT_FEATURE_FILS_CRYPTO_OFFLOAD: Driver running in AP mode supports
++ *	FILS encryption and decryption for (Re)Association Request and Response
++ *	frames. Userspace has to share FILS AAD details to the driver by using
++ *	@NL80211_CMD_SET_FILS_AAD.
++ *
++ * @NL80211_EXT_FEATURE_RADAR_BACKGROUND: Device supports background radar/CAC
++ *	detection.
++ *
+  * @NUM_NL80211_EXT_FEATURES: number of extended features.
+  * @MAX_NL80211_EXT_FEATURES: highest extended feature index.
+  */
+@@ -6014,6 +6143,9 @@ enum nl80211_ext_feature_index {
+ 	NL80211_EXT_FEATURE_SECURE_LTF,
+ 	NL80211_EXT_FEATURE_SECURE_RTT,
+ 	NL80211_EXT_FEATURE_PROT_RANGE_NEGO_AND_MEASURE,
++	NL80211_EXT_FEATURE_BSS_COLOR,
++	NL80211_EXT_FEATURE_FILS_CRYPTO_OFFLOAD,
++	NL80211_EXT_FEATURE_RADAR_BACKGROUND,
+ 
+ 	/* add new features before the definition below */
+ 	NUM_NL80211_EXT_FEATURES,
+@@ -6912,6 +7044,9 @@ enum nl80211_peer_measurement_ftm_capa {
+  * @NL80211_PMSR_FTM_REQ_ATTR_LMR_FEEDBACK: negotiate for LMR feedback. Only
+  *	valid if either %NL80211_PMSR_FTM_REQ_ATTR_TRIGGER_BASED or
+  *	%NL80211_PMSR_FTM_REQ_ATTR_NON_TRIGGER_BASED is set.
++ * @NL80211_PMSR_FTM_REQ_ATTR_BSS_COLOR: optional. The BSS color of the
++ *	responder. Only valid if %NL80211_PMSR_FTM_REQ_ATTR_NON_TRIGGER_BASED
++ *	or %NL80211_PMSR_FTM_REQ_ATTR_TRIGGER_BASED is set.
+  *
+  * @NUM_NL80211_PMSR_FTM_REQ_ATTR: internal
+  * @NL80211_PMSR_FTM_REQ_ATTR_MAX: highest attribute number
+@@ -6931,6 +7066,7 @@ enum nl80211_peer_measurement_ftm_req {
+ 	NL80211_PMSR_FTM_REQ_ATTR_TRIGGER_BASED,
+ 	NL80211_PMSR_FTM_REQ_ATTR_NON_TRIGGER_BASED,
+ 	NL80211_PMSR_FTM_REQ_ATTR_LMR_FEEDBACK,
++	NL80211_PMSR_FTM_REQ_ATTR_BSS_COLOR,
+ 
+ 	/* keep last */
+ 	NUM_NL80211_PMSR_FTM_REQ_ATTR,
+@@ -7299,4 +7435,76 @@ enum nl80211_sar_specs_attrs {
+ 	NL80211_SAR_ATTR_SPECS_MAX = __NL80211_SAR_ATTR_SPECS_LAST - 1,
+ };
+ 
++/**
++ * enum nl80211_mbssid_config_attributes - multiple BSSID (MBSSID) and enhanced
++ * multi-BSSID advertisements (EMA) in AP mode.
++ * Kernel uses some of these attributes to advertise driver's support for
++ * MBSSID and EMA.
++ * Remaining attributes should be used by the userspace to configure the
++ * features.
++ *
++ * @__NL80211_MBSSID_CONFIG_ATTR_INVALID: Invalid
++ *
++ * @NL80211_MBSSID_CONFIG_ATTR_MAX_INTERFACES: Used by the kernel to advertise
++ *	the maximum number of MBSSID interfaces supported by the driver.
++ *	Driver should indicate MBSSID support by setting
++ *	wiphy->mbssid_max_interfaces to a value more than or equal to 2.
++ *
++ * @NL80211_MBSSID_CONFIG_ATTR_MAX_EMA_PROFILE_PERIODICITY: Used by the kernel
++ *	to advertise the maximum profile periodicity supported by the driver
++ *	if EMA is enabled. Driver should indicate EMA support to the userspace
++ *	by setting wiphy->ema_max_profile_periodicity to
++ *	a non-zero value.
++ *
++ * @NL80211_MBSSID_CONFIG_ATTR_INDEX: Mandatory parameter to pass the index of
++ *	this BSS (u8) in the multiple BSSID set.
++ *	Value must be set to 0 for the transmitting interface and non-zero for
++ *	all non-transmitting interfaces. The userspace will be responsible
++ *	for using unique indices for the interfaces.
++ *	Range: 0 to wiphy->mbssid_max_interfaces-1.
++ *
++ * @NL80211_MBSSID_CONFIG_ATTR_TX_IFINDEX: Mandatory parameter for
++ *	a non-transmitted profile which provides the interface index (u32) of
++ *	the transmitted profile. The value must match one of the interface
++ *	indices advertised by the kernel. Optional if the interface being set up
++ *	is the transmitting one, however, if provided then the value must match
++ *	the interface index of the same.
++ *
++ * @NL80211_MBSSID_CONFIG_ATTR_EMA: Flag used to enable EMA AP feature.
++ *	Setting this flag is permitted only if the driver advertises EMA support
++ *	by setting wiphy->ema_max_profile_periodicity to non-zero.
++ *
++ * @__NL80211_MBSSID_CONFIG_ATTR_LAST: Internal
++ * @NL80211_MBSSID_CONFIG_ATTR_MAX: highest attribute
++ */
++enum nl80211_mbssid_config_attributes {
++	__NL80211_MBSSID_CONFIG_ATTR_INVALID,
++
++	NL80211_MBSSID_CONFIG_ATTR_MAX_INTERFACES,
++	NL80211_MBSSID_CONFIG_ATTR_MAX_EMA_PROFILE_PERIODICITY,
++	NL80211_MBSSID_CONFIG_ATTR_INDEX,
++	NL80211_MBSSID_CONFIG_ATTR_TX_IFINDEX,
++	NL80211_MBSSID_CONFIG_ATTR_EMA,
++
++	/* keep last */
++	__NL80211_MBSSID_CONFIG_ATTR_LAST,
++	NL80211_MBSSID_CONFIG_ATTR_MAX = __NL80211_MBSSID_CONFIG_ATTR_LAST - 1,
++};
++
++/**
++ * enum nl80211_ap_settings_flags - AP settings flags
++ *
++ * @NL80211_AP_SETTINGS_EXTERNAL_AUTH_SUPPORT: AP supports external
++ *	authentication.
++ * @NL80211_AP_SETTINGS_SA_QUERY_OFFLOAD_SUPPORT: Userspace supports SA Query
++ *	procedures offload to driver. If driver advertises
++ *	%NL80211_AP_SME_SA_QUERY_OFFLOAD in AP SME features, userspace shall
++ *	ignore SA Query procedures and validations when this flag is set by
++ *	userspace.
++ */
++enum nl80211_ap_settings_flags {
++	NL80211_AP_SETTINGS_EXTERNAL_AUTH_SUPPORT	= 1 << 0,
++	NL80211_AP_SETTINGS_SA_QUERY_OFFLOAD_SUPPORT	= 1 << 1,
++};
++
+ #endif /* __LINUX_NL80211_H */
+-- 
+2.29.2
+
diff --git a/autobuild_mac80211_release/package/network/services/hostapd/patches/900-master-sync-include-uapi-linux-nl80211.patch b/autobuild_mac80211_release/package/network/services/hostapd/patches/900-master-sync-include-uapi-linux-nl80211.patch
deleted file mode 100644
index fe47b57..0000000
--- a/autobuild_mac80211_release/package/network/services/hostapd/patches/900-master-sync-include-uapi-linux-nl80211.patch
+++ /dev/null
@@ -1,57 +0,0 @@
-diff --git a/src/drivers/nl80211_copy.h b/src/drivers/nl80211_copy.h
-index f962c06..f7be755 100644
---- a/src/drivers/nl80211_copy.h
-+++ b/src/drivers/nl80211_copy.h
-@@ -2560,6 +2560,19 @@ enum nl80211_commands {
-  *	disassoc events to indicate that an immediate reconnect to the AP
-  *	is desired.
-  *
-+ * @NL80211_ATTR_OBSS_COLOR_BITMAP: bitmap of the u64 BSS colors for the
-+ *	%NL80211_CMD_OBSS_COLOR_COLLISION event.
-+ *
-+ * @NL80211_ATTR_COLOR_CHANGE_COUNT: u8 attribute specifying the number of TBTT's
-+ *	until the color switch event.
-+ * @NL80211_ATTR_COLOR_CHANGE_COLOR: u8 attribute specifying the color that we are
-+ *	switching to
-+ * @NL80211_ATTR_COLOR_CHANGE_ELEMS: Nested set of attributes containing the IE
-+ *	information for the time while performing a color switch.
-+ *
-+ * @NL80211_ATTR_WIPHY_ANTENNA_GAIN: Configured antenna gain. Used to reduce
-+ *	transmit power to stay within regulatory limits. u32, dBi.
-+ *
-  * @NUM_NL80211_ATTR: total number of nl80211_attrs available
-  * @NL80211_ATTR_MAX: highest attribute number currently defined
-  * @__NL80211_ATTR_AFTER_LAST: internal use
-@@ -3057,6 +3070,14 @@ enum nl80211_attrs {
- 
- 	NL80211_ATTR_DISABLE_HE,
- 
-+	NL80211_ATTR_OBSS_COLOR_BITMAP,
-+
-+	NL80211_ATTR_COLOR_CHANGE_COUNT,
-+	NL80211_ATTR_COLOR_CHANGE_COLOR,
-+	NL80211_ATTR_COLOR_CHANGE_ELEMS,
-+
-+	NL80211_ATTR_WIPHY_ANTENNA_GAIN,
-+
- 	/* add attributes here, update the policy in nl80211.c */
- 
- 	__NL80211_ATTR_AFTER_LAST,
-@@ -5950,6 +5971,9 @@ enum nl80211_feature_flags {
-  *      frame protection for all management frames exchanged during the
-  *      negotiation and range measurement procedure.
-  *
-+ * @NL80211_EXT_FEATURE_BSS_COLOR: The driver supports BSS color collision
-+ *	detection and change announcemnts.
-+ *
-  * @NUM_NL80211_EXT_FEATURES: number of extended features.
-  * @MAX_NL80211_EXT_FEATURES: highest extended feature index.
-  */
-@@ -6014,6 +6038,7 @@ enum nl80211_ext_feature_index {
- 	NL80211_EXT_FEATURE_SECURE_LTF,
- 	NL80211_EXT_FEATURE_SECURE_RTT,
- 	NL80211_EXT_FEATURE_PROT_RANGE_NEGO_AND_MEASURE,
-+	NL80211_EXT_FEATURE_BSS_COLOR,
- 
- 	/* add new features before the definition below */
- 	NUM_NL80211_EXT_FEATURES,
diff --git a/autobuild_mac80211_release/package/network/services/hostapd/patches/901-master-zero-wait_dfs.patch b/autobuild_mac80211_release/package/network/services/hostapd/patches/901-master-zero-wait_dfs.patch
deleted file mode 100644
index cb11aee..0000000
--- a/autobuild_mac80211_release/package/network/services/hostapd/patches/901-master-zero-wait_dfs.patch
+++ /dev/null
@@ -1,851 +0,0 @@
-diff --git a/hostapd/config_file.c b/hostapd/config_file.c
-index 1e1b685..8f6281a 100644
---- a/hostapd/config_file.c
-+++ b/hostapd/config_file.c
-@@ -2476,6 +2476,8 @@ static int hostapd_config_fill(struct hostapd_config *conf,
- 		conf->ieee80211d = atoi(pos);
- 	} else if (os_strcmp(buf, "ieee80211h") == 0) {
- 		conf->ieee80211h = atoi(pos);
-+	} else if (os_strcmp(buf, "radar_offchan") == 0) {
-+		conf->radar_offchan = atoi(pos);
- 	} else if (os_strcmp(buf, "ieee8021x") == 0) {
- 		bss->ieee802_1x = atoi(pos);
- 	} else if (os_strcmp(buf, "eapol_version") == 0) {
-diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf
-index a89ce9b..0c951a9 100644
---- a/hostapd/hostapd.conf
-+++ b/hostapd/hostapd.conf
-@@ -143,6 +143,13 @@ ssid=test
- # ieee80211d=1 and local_pwr_constraint configured.
- #spectrum_mgmt_required=1
- 
-+# Enable radar/CAC detection through a dedicated offchannel chain available on
-+# some hw. The chain can't be used to transmits or receives frames.
-+# This feature allows to avoid CAC downtime switching on a different channel
-+# during CAC detection on the selected radar channel.
-+# (default: 0 = disabled, 1 = enabled)
-+#radar_offchan=0
-+
- # Operation mode (a = IEEE 802.11a (5 GHz), b = IEEE 802.11b (2.4 GHz),
- # g = IEEE 802.11g (2.4 GHz), ad = IEEE 802.11ad (60 GHz); a/g options are used
- # with IEEE 802.11n (HT), too, to specify band). For IEEE 802.11ac (VHT), this
-diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
-index 28b7efe..ffc3c2c 100644
---- a/src/ap/ap_config.h
-+++ b/src/ap/ap_config.h
-@@ -993,6 +993,7 @@ struct hostapd_config {
- 	int ieee80211d;
- 
- 	int ieee80211h; /* DFS */
-+	int radar_offchan;
- 
- 	/*
- 	 * Local power constraint is an octet encoded as an unsigned integer in
-diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c
-index bc49079..c97ee39 100644
---- a/src/ap/ap_drv_ops.c
-+++ b/src/ap/ap_drv_ops.c
-@@ -810,7 +810,8 @@ int hostapd_start_dfs_cac(struct hostapd_iface *iface,
- 			  int channel, int ht_enabled, int vht_enabled,
- 			  int he_enabled,
- 			  int sec_channel_offset, int oper_chwidth,
--			  int center_segment0, int center_segment1)
-+			  int center_segment0, int center_segment1,
-+			  int radar_offchan)
- {
- 	struct hostapd_data *hapd = iface->bss[0];
- 	struct hostapd_freq_params data;
-@@ -836,10 +837,14 @@ int hostapd_start_dfs_cac(struct hostapd_iface *iface,
- 		wpa_printf(MSG_ERROR, "Can't set freq params");
- 		return -1;
- 	}
-+	data.radar_offchan = radar_offchan;
- 
- 	res = hapd->driver->start_dfs_cac(hapd->drv_priv, &data);
- 	if (!res) {
--		iface->cac_started = 1;
-+		if (radar_offchan)
-+			iface->radar_offchan.cac_started = 1;
-+		else
-+			iface->cac_started = 1;
- 		os_get_reltime(&iface->dfs_cac_start);
- 	}
- 
-diff --git a/src/ap/ap_drv_ops.h b/src/ap/ap_drv_ops.h
-index 61c8f64..92842a1 100644
---- a/src/ap/ap_drv_ops.h
-+++ b/src/ap/ap_drv_ops.h
-@@ -130,7 +130,8 @@ int hostapd_start_dfs_cac(struct hostapd_iface *iface,
- 			  int channel, int ht_enabled, int vht_enabled,
- 			  int he_enabled,
- 			  int sec_channel_offset, int oper_chwidth,
--			  int center_segment0, int center_segment1);
-+			  int center_segment0, int center_segment1,
-+			  int radar_offchan);
- int hostapd_drv_do_acs(struct hostapd_data *hapd);
- int hostapd_drv_update_dh_ie(struct hostapd_data *hapd, const u8 *peer,
- 			     u16 reason_code, const u8 *ie, size_t ielen);
-diff --git a/src/ap/dfs.c b/src/ap/dfs.c
-index eccda1a..3b1276f 100644
---- a/src/ap/dfs.c
-+++ b/src/ap/dfs.c
-@@ -51,16 +51,31 @@ static int dfs_get_used_n_chans(struct hostapd_iface *iface, int *seg1)
- 	return n_chans;
- }
- 
--
-+/*
-+ * flags:
-+ * - 0: any channel
-+ * - 1: non-radar channel or radar available one
-+ * - 2: radar-only channel not yet available
-+ */
- static int dfs_channel_available(struct hostapd_channel_data *chan,
--				 int skip_radar)
-+				 int flags)
- {
-+	if (flags == 2) {
-+		/* Select only radar channel where CAC has not been
-+		 * performed yet
-+		 */
-+		if ((chan->flag & HOSTAPD_CHAN_RADAR) &&
-+		    (chan->flag & HOSTAPD_CHAN_DFS_MASK) ==
-+		     HOSTAPD_CHAN_DFS_USABLE)
-+			return 1;
-+		return 0;
-+	}
- 	/*
- 	 * When radar detection happens, CSA is performed. However, there's no
- 	 * time for CAC, so radar channels must be skipped when finding a new
- 	 * channel for CSA, unless they are available for immediate use.
- 	 */
--	if (skip_radar && (chan->flag & HOSTAPD_CHAN_RADAR) &&
-+	if (flags && (chan->flag & HOSTAPD_CHAN_RADAR) &&
- 	    ((chan->flag & HOSTAPD_CHAN_DFS_MASK) !=
- 	     HOSTAPD_CHAN_DFS_AVAILABLE))
- 		return 0;
-@@ -136,10 +151,15 @@ dfs_get_chan_data(struct hostapd_hw_modes *mode, int freq, int first_chan_idx)
- 	return NULL;
- }
- 
--
-+/*
-+ * flags:
-+ * - 0: any channel
-+ * - 1: non-radar channel or radar available one
-+ * - 2: radar-only channel not yet available
-+ */
- static int dfs_chan_range_available(struct hostapd_hw_modes *mode,
- 				    int first_chan_idx, int num_chans,
--				    int skip_radar)
-+				    int flags)
- {
- 	struct hostapd_channel_data *first_chan, *chan;
- 	int i;
-@@ -178,7 +198,7 @@ static int dfs_chan_range_available(struct hostapd_hw_modes *mode,
- 			return 0;
- 		}
- 
--		if (!dfs_channel_available(chan, skip_radar)) {
-+		if (!dfs_channel_available(chan, flags)) {
- 			wpa_printf(MSG_DEBUG, "DFS: channel not available %d",
- 				   first_chan->freq + i * 20);
- 			return 0;
-@@ -205,10 +225,15 @@ static int is_in_chanlist(struct hostapd_iface *iface,
-  *  - hapd->secondary_channel
-  *  - hapd->vht/he_oper_centr_freq_seg0_idx
-  *  - hapd->vht/he_oper_centr_freq_seg1_idx
-+ *
-+ * flags:
-+ * - 0: any channel
-+ * - 1: non-radar channel or radar available one
-+ * - 2: radar-only channel not yet available
-  */
- static int dfs_find_channel(struct hostapd_iface *iface,
- 			    struct hostapd_channel_data **ret_chan,
--			    int idx, int skip_radar)
-+			    int idx, int flags)
- {
- 	struct hostapd_hw_modes *mode;
- 	struct hostapd_channel_data *chan;
-@@ -233,7 +258,7 @@ static int dfs_find_channel(struct hostapd_iface *iface,
- 		}
- 
- 		/* Skip incompatible chandefs */
--		if (!dfs_chan_range_available(mode, i, n_chans, skip_radar)) {
-+		if (!dfs_chan_range_available(mode, i, n_chans, flags)) {
- 			wpa_printf(MSG_DEBUG,
- 				   "DFS: range not available for %d (%d)",
- 				   chan->freq, chan->chan);
-@@ -467,13 +492,18 @@ static int dfs_check_chans_unavailable(struct hostapd_iface *iface,
- 	return res;
- }
- 
--
-+/*
-+ * flags:
-+ * - 0: any channel
-+ * - 1: non-radar channel or radar available one
-+ * - 2: radar-only channel not yet available
-+ */
- static struct hostapd_channel_data *
- dfs_get_valid_channel(struct hostapd_iface *iface,
- 		      int *secondary_channel,
- 		      u8 *oper_centr_freq_seg0_idx,
- 		      u8 *oper_centr_freq_seg1_idx,
--		      int skip_radar)
-+		      int flags)
- {
- 	struct hostapd_hw_modes *mode;
- 	struct hostapd_channel_data *chan = NULL;
-@@ -502,7 +532,7 @@ dfs_get_valid_channel(struct hostapd_iface *iface,
- 		return NULL;
- 
- 	/* Get the count first */
--	num_available_chandefs = dfs_find_channel(iface, NULL, 0, skip_radar);
-+	num_available_chandefs = dfs_find_channel(iface, NULL, 0, flags);
- 	wpa_printf(MSG_DEBUG, "DFS: num_available_chandefs=%d",
- 		   num_available_chandefs);
- 	if (num_available_chandefs == 0)
-@@ -523,7 +553,7 @@ dfs_get_valid_channel(struct hostapd_iface *iface,
- 		return NULL;
- 
- 	chan_idx = _rand % num_available_chandefs;
--	dfs_find_channel(iface, &chan, chan_idx, skip_radar);
-+	dfs_find_channel(iface, &chan, chan_idx, flags);
- 	if (!chan) {
- 		wpa_printf(MSG_DEBUG, "DFS: no random channel found");
- 		return NULL;
-@@ -552,7 +582,7 @@ dfs_get_valid_channel(struct hostapd_iface *iface,
- 		for (i = 0; i < num_available_chandefs - 1; i++) {
- 			/* start from chan_idx + 1, end when chan_idx - 1 */
- 			chan_idx2 = (chan_idx + 1 + i) % num_available_chandefs;
--			dfs_find_channel(iface, &chan2, chan_idx2, skip_radar);
-+			dfs_find_channel(iface, &chan2, chan_idx2, flags);
- 			if (chan2 && abs(chan2->chan - chan->chan) > 12) {
- 				/* two channels are not adjacent */
- 				sec_chan_idx_80p80 = chan2->chan;
-@@ -582,6 +612,27 @@ dfs_get_valid_channel(struct hostapd_iface *iface,
- 	return chan;
- }
- 
-+static int dfs_set_valid_channel(struct hostapd_iface *iface, int skip_radar)
-+{
-+	struct hostapd_channel_data *channel;
-+	u8 cf1 = 0, cf2 = 0;
-+	int sec = 0;
-+
-+	channel = dfs_get_valid_channel(iface, &sec, &cf1, &cf2,
-+					skip_radar);
-+	if (!channel) {
-+		wpa_printf(MSG_ERROR, "could not get valid channel");
-+		return -1;
-+	}
-+
-+	iface->freq = channel->freq;
-+	iface->conf->channel = channel->chan;
-+	iface->conf->secondary_channel = sec;
-+	hostapd_set_oper_centr_freq_seg0_idx(iface->conf, cf1);
-+	hostapd_set_oper_centr_freq_seg1_idx(iface->conf, cf2);
-+
-+	return 0;
-+}
- 
- static int set_dfs_state_freq(struct hostapd_iface *iface, int freq, u32 state)
- {
-@@ -761,6 +812,11 @@ static unsigned int dfs_get_cac_time(struct hostapd_iface *iface,
- 	return cac_time_ms;
- }
- 
-+static int hostapd_is_radar_offchan_enabled(struct hostapd_iface *iface)
-+{
-+	return (iface->drv_flags2 & WPA_DRIVER_RADAR_OFFCHAN) &&
-+	       iface->conf->radar_offchan;
-+}
- 
- /*
-  * Main DFS handler
-@@ -770,9 +826,8 @@ static unsigned int dfs_get_cac_time(struct hostapd_iface *iface,
-  */
- int hostapd_handle_dfs(struct hostapd_iface *iface)
- {
--	struct hostapd_channel_data *channel;
- 	int res, n_chans, n_chans1, start_chan_idx, start_chan_idx1;
--	int skip_radar = 0;
-+	int skip_radar = 0, radar_offchan;
- 
- 	if (is_6ghz_freq(iface->freq))
- 		return 1;
-@@ -825,28 +880,18 @@ int hostapd_handle_dfs(struct hostapd_iface *iface)
- 		wpa_printf(MSG_DEBUG, "DFS %d chans unavailable - choose other channel: %s",
- 			   res, res ? "yes": "no");
- 		if (res) {
--			int sec = 0;
--			u8 cf1 = 0, cf2 = 0;
--
--			channel = dfs_get_valid_channel(iface, &sec, &cf1, &cf2,
--							skip_radar);
--			if (!channel) {
--				wpa_printf(MSG_ERROR, "could not get valid channel");
-+			if (dfs_set_valid_channel(iface, skip_radar) < 0) {
- 				hostapd_set_state(iface, HAPD_IFACE_DFS);
- 				return 0;
- 			}
--
--			iface->freq = channel->freq;
--			iface->conf->channel = channel->chan;
--			iface->conf->secondary_channel = sec;
--			hostapd_set_oper_centr_freq_seg0_idx(iface->conf, cf1);
--			hostapd_set_oper_centr_freq_seg1_idx(iface->conf, cf2);
- 		}
- 	} while (res);
- 
- 	/* Finally start CAC */
- 	hostapd_set_state(iface, HAPD_IFACE_DFS);
--	wpa_printf(MSG_DEBUG, "DFS start CAC on %d MHz", iface->freq);
-+	radar_offchan = hostapd_is_radar_offchan_enabled(iface);
-+	wpa_printf(MSG_DEBUG, "DFS start CAC on %d MHz offchan %d",
-+		   iface->freq, radar_offchan);
- 	wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_CAC_START
- 		"freq=%d chan=%d sec_chan=%d, width=%d, seg0=%d, seg1=%d, cac_time=%ds",
- 		iface->freq,
-@@ -863,13 +908,37 @@ int hostapd_handle_dfs(struct hostapd_iface *iface)
- 		iface->conf->secondary_channel,
- 		hostapd_get_oper_chwidth(iface->conf),
- 		hostapd_get_oper_centr_freq_seg0_idx(iface->conf),
--		hostapd_get_oper_centr_freq_seg1_idx(iface->conf));
-+		hostapd_get_oper_centr_freq_seg1_idx(iface->conf),
-+		radar_offchan);
- 
- 	if (res) {
- 		wpa_printf(MSG_ERROR, "DFS start_dfs_cac() failed, %d", res);
- 		return -1;
- 	}
- 
-+	if (radar_offchan) {
-+		/* Cache offchannel radar parameters */
-+		iface->radar_offchan.channel = iface->conf->channel;
-+		iface->radar_offchan.secondary_channel =
-+			iface->conf->secondary_channel;
-+		iface->radar_offchan.freq = iface->freq;
-+		iface->radar_offchan.centr_freq_seg0_idx =
-+			hostapd_get_oper_centr_freq_seg0_idx(iface->conf);
-+		iface->radar_offchan.centr_freq_seg1_idx =
-+			hostapd_get_oper_centr_freq_seg1_idx(iface->conf);
-+
-+		/*
-+		 * Let's select a random channel for the moment
-+		 * and perform CAC on dedicated radar chain
-+		 */
-+		res = dfs_set_valid_channel(iface, 1);
-+		if (res < 0)
-+			return res;
-+
-+		iface->radar_offchan.temp_ch = 1;
-+		return 1;
-+	}
-+
- 	return 0;
- }
- 
-@@ -890,6 +959,157 @@ int hostapd_is_dfs_chan_available(struct hostapd_iface *iface)
- 	return dfs_check_chans_available(iface, start_chan_idx, n_chans);
- }
- 
-+static int hostapd_dfs_request_channel_switch(struct hostapd_iface *iface,
-+					      int channel, int freq,
-+					      int secondary_channel,
-+					      u8 oper_centr_freq_seg0_idx,
-+					      u8 oper_centr_freq_seg1_idx)
-+{
-+	struct hostapd_hw_modes *cmode = iface->current_mode;
-+	int ieee80211_mode = IEEE80211_MODE_AP, err, i;
-+	struct csa_settings csa_settings;
-+	u8 new_vht_oper_chwidth;
-+
-+	wpa_printf(MSG_DEBUG, "DFS will switch to a new channel %d", channel);
-+	wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_NEW_CHANNEL
-+		"freq=%d chan=%d sec_chan=%d", freq, channel,
-+		secondary_channel);
-+
-+	new_vht_oper_chwidth = hostapd_get_oper_chwidth(iface->conf);
-+	hostapd_set_oper_chwidth(iface->conf,
-+				 hostapd_get_oper_chwidth(iface->conf));
-+
-+	/* Setup CSA request */
-+	os_memset(&csa_settings, 0, sizeof(csa_settings));
-+	csa_settings.cs_count = 5;
-+	csa_settings.block_tx = 1;
-+#ifdef CONFIG_MESH
-+	if (iface->mconf)
-+		ieee80211_mode = IEEE80211_MODE_MESH;
-+#endif /* CONFIG_MESH */
-+	err = hostapd_set_freq_params(&csa_settings.freq_params,
-+				      iface->conf->hw_mode,
-+				      freq, channel,
-+				      iface->conf->enable_edmg,
-+				      iface->conf->edmg_channel,
-+				      iface->conf->ieee80211n,
-+				      iface->conf->ieee80211ac,
-+				      iface->conf->ieee80211ax,
-+				      secondary_channel,
-+				      new_vht_oper_chwidth,
-+				      oper_centr_freq_seg0_idx,
-+				      oper_centr_freq_seg1_idx,
-+				      cmode->vht_capab,
-+				      &cmode->he_capab[ieee80211_mode]);
-+
-+	if (err) {
-+		wpa_printf(MSG_ERROR, "DFS failed to calculate CSA freq params");
-+		hostapd_disable_iface(iface);
-+		return err;
-+	}
-+
-+	for (i = 0; i < iface->num_bss; i++) {
-+		err = hostapd_switch_channel(iface->bss[i], &csa_settings);
-+		if (err)
-+			break;
-+	}
-+
-+	if (err) {
-+		wpa_printf(MSG_WARNING, "DFS failed to schedule CSA (%d) - trying fallback",
-+			   err);
-+		iface->freq = freq;
-+		iface->conf->channel = channel;
-+		iface->conf->secondary_channel = secondary_channel;
-+		hostapd_set_oper_chwidth(iface->conf, new_vht_oper_chwidth);
-+		hostapd_set_oper_centr_freq_seg0_idx(iface->conf,
-+						     oper_centr_freq_seg0_idx);
-+		hostapd_set_oper_centr_freq_seg1_idx(iface->conf,
-+						     oper_centr_freq_seg1_idx);
-+
-+		hostapd_disable_iface(iface);
-+		hostapd_enable_iface(iface);
-+
-+		return 0;
-+	}
-+
-+	/* Channel configuration will be updated once CSA completes and
-+	 * ch_switch_notify event is received */
-+	wpa_printf(MSG_DEBUG, "DFS waiting channel switch event");
-+
-+	return 0;
-+}
-+
-+static struct hostapd_channel_data *
-+dfs_downgrade_bandwidth(struct hostapd_iface *iface, int *secondary_channel,
-+			u8 *oper_centr_freq_seg0_idx,
-+			u8 *oper_centr_freq_seg1_idx, int *skip_radar);
-+
-+static void
-+hostpad_dfs_update_offchannel_chain(struct hostapd_iface *iface)
-+{
-+	struct hostapd_channel_data *channel;
-+	int sec = 0, flags = 2;
-+	u8 cf1 = 0, cf2 = 0;
-+
-+	channel = dfs_get_valid_channel(iface, &sec, &cf1, &cf2, 2);
-+	if (!channel || channel->chan == iface->conf->channel)
-+		channel = dfs_downgrade_bandwidth(iface, &sec, &cf1, &cf2,
-+						  &flags);
-+	if (!channel ||
-+	    hostapd_start_dfs_cac(iface, iface->conf->hw_mode,
-+				  channel->freq, channel->chan,
-+				  iface->conf->ieee80211n,
-+				  iface->conf->ieee80211ac,
-+				  iface->conf->ieee80211ax,
-+				  sec, hostapd_get_oper_chwidth(iface->conf),
-+				  cf1, cf2, 1)) {
-+		/*
-+		 * Toggle interface state to enter DFS state
-+		 * until NOP is finished.
-+		 */
-+		wpa_printf(MSG_ERROR, "DFS failed start CAC offchannel");
-+		return;
-+	}
-+
-+	wpa_printf(MSG_DEBUG, "%s: setting offchannel chain to chan %d (%d MHz)",
-+		   __func__, channel->chan, channel->freq);
-+
-+	iface->radar_offchan.channel = channel->chan;
-+	iface->radar_offchan.freq = channel->freq;
-+	iface->radar_offchan.secondary_channel = sec;
-+	iface->radar_offchan.centr_freq_seg0_idx = cf1;
-+	iface->radar_offchan.centr_freq_seg1_idx = cf2;
-+}
-+
-+/* FIXME: check if all channel bandwith */
-+static int
-+hostapd_dfs_is_offchan_event(struct hostapd_iface *iface, int freq)
-+{
-+	if (iface->radar_offchan.freq != freq)
-+		return 0;
-+
-+	return 1;
-+}
-+
-+static int
-+hostapd_dfs_start_channel_switch_offchan(struct hostapd_iface *iface)
-+{
-+	iface->conf->channel = iface->radar_offchan.channel;
-+	iface->freq = iface->radar_offchan.freq;
-+	iface->conf->secondary_channel =
-+		iface->radar_offchan.secondary_channel;
-+	hostapd_set_oper_centr_freq_seg0_idx(iface->conf,
-+			iface->radar_offchan.centr_freq_seg0_idx);
-+	hostapd_set_oper_centr_freq_seg1_idx(iface->conf,
-+			iface->radar_offchan.centr_freq_seg1_idx);
-+
-+	hostpad_dfs_update_offchannel_chain(iface);
-+
-+	return hostapd_dfs_request_channel_switch(iface, iface->conf->channel,
-+						  iface->freq, iface->conf->secondary_channel,
-+						  hostapd_get_oper_centr_freq_seg0_idx(iface->conf),
-+						  hostapd_get_oper_centr_freq_seg1_idx(iface->conf));
-+}
- 
- int hostapd_dfs_complete_cac(struct hostapd_iface *iface, int success, int freq,
- 			     int ht_enabled, int chan_offset, int chan_width,
-@@ -911,6 +1131,23 @@ int hostapd_dfs_complete_cac(struct hostapd_iface *iface, int success, int freq,
- 			set_dfs_state(iface, freq, ht_enabled, chan_offset,
- 				      chan_width, cf1, cf2,
- 				      HOSTAPD_CHAN_DFS_AVAILABLE);
-+
-+			/*
-+			 * radar event from offchannel chain for selected
-+			 * channel. Perfrom CSA, move main chain to selected
-+			 * channel and configure offchannel chain to a new DFS
-+			 * channel
-+			 */
-+			if (hostapd_is_radar_offchan_enabled(iface) &&
-+			    hostapd_dfs_is_offchan_event(iface, freq)) {
-+				iface->radar_offchan.cac_started = 0;
-+				if (iface->radar_offchan.temp_ch) {
-+					iface->radar_offchan.temp_ch = 0;
-+					return hostapd_dfs_start_channel_switch_offchan(iface);
-+				}
-+				return 0;
-+			}
-+
- 			/*
- 			 * Just mark the channel available when CAC completion
- 			 * event is received in enabled state. CAC result could
-@@ -927,6 +1164,10 @@ int hostapd_dfs_complete_cac(struct hostapd_iface *iface, int success, int freq,
- 				iface->cac_started = 0;
- 			}
- 		}
-+	} else if (hostapd_is_radar_offchan_enabled(iface) &&
-+		   hostapd_dfs_is_offchan_event(iface, freq)) {
-+		iface->radar_offchan.cac_started = 0;
-+		hostpad_dfs_update_offchannel_chain(iface);
- 	}
- 
- 	return 0;
-@@ -1036,6 +1277,44 @@ static int hostapd_dfs_start_channel_switch_cac(struct hostapd_iface *iface)
- 	return err;
- }
- 
-+static int
-+hostapd_dfs_offchan_start_channel_switch(struct hostapd_iface *iface, int freq)
-+{
-+	if (!hostapd_is_radar_offchan_enabled(iface))
-+		return -1; /* Offchannel chain not supported */
-+
-+	wpa_printf(MSG_DEBUG,
-+		   "%s called (offchannel CAC active: %s, CSA active: %s)",
-+		   __func__, iface->radar_offchan.cac_started ? "yes" : "no",
-+		   hostapd_csa_in_progress(iface) ? "yes" : "no");
-+
-+	/* Check if CSA in progress */
-+	if (hostapd_csa_in_progress(iface))
-+		return 0;
-+
-+	/*
-+	 * If offchannel radar detation is supported and radar channel
-+	 * monitored by offchain is available switch to it without waiting
-+	 * for the CAC otherwise let's keep a random channel.
-+	 * If radar pattern is reported on offchannel chain, just switch to
-+	 * monitor another radar channel.
-+	 */
-+	if (hostapd_dfs_is_offchan_event(iface, freq)) {
-+		hostpad_dfs_update_offchannel_chain(iface);
-+		return 0;
-+	}
-+
-+	/* Offchannel not availanle yet. Perform CAC on main chain */
-+	if (iface->radar_offchan.cac_started) {
-+		/* We want to switch to monitored channel as soon as
-+		 * CAC is completed.
-+		 */
-+		iface->radar_offchan.temp_ch = 1;
-+		return -1;
-+	}
-+
-+	return hostapd_dfs_start_channel_switch_offchan(iface);
-+}
- 
- static int hostapd_dfs_start_channel_switch(struct hostapd_iface *iface)
- {
-@@ -1043,13 +1322,7 @@ static int hostapd_dfs_start_channel_switch(struct hostapd_iface *iface)
- 	int secondary_channel;
- 	u8 oper_centr_freq_seg0_idx;
- 	u8 oper_centr_freq_seg1_idx;
--	u8 new_vht_oper_chwidth;
- 	int skip_radar = 1;
--	struct csa_settings csa_settings;
--	unsigned int i;
--	int err = 1;
--	struct hostapd_hw_modes *cmode = iface->current_mode;
--	u8 current_vht_oper_chwidth = hostapd_get_oper_chwidth(iface->conf);
- 	int ieee80211_mode = IEEE80211_MODE_AP;
- 
- 	wpa_printf(MSG_DEBUG, "%s called (CAC active: %s, CSA active: %s)",
-@@ -1113,73 +1386,16 @@ static int hostapd_dfs_start_channel_switch(struct hostapd_iface *iface)
- 		}
- 	}
- 
--	wpa_printf(MSG_DEBUG, "DFS will switch to a new channel %d",
--		   channel->chan);
--	wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_NEW_CHANNEL
--		"freq=%d chan=%d sec_chan=%d", channel->freq,
--		channel->chan, secondary_channel);
--
--	new_vht_oper_chwidth = hostapd_get_oper_chwidth(iface->conf);
--	hostapd_set_oper_chwidth(iface->conf, current_vht_oper_chwidth);
--
--	/* Setup CSA request */
--	os_memset(&csa_settings, 0, sizeof(csa_settings));
--	csa_settings.cs_count = 5;
--	csa_settings.block_tx = 1;
- #ifdef CONFIG_MESH
- 	if (iface->mconf)
- 		ieee80211_mode = IEEE80211_MODE_MESH;
- #endif /* CONFIG_MESH */
--	err = hostapd_set_freq_params(&csa_settings.freq_params,
--				      iface->conf->hw_mode,
--				      channel->freq,
--				      channel->chan,
--				      iface->conf->enable_edmg,
--				      iface->conf->edmg_channel,
--				      iface->conf->ieee80211n,
--				      iface->conf->ieee80211ac,
--				      iface->conf->ieee80211ax,
--				      secondary_channel,
--				      new_vht_oper_chwidth,
--				      oper_centr_freq_seg0_idx,
--				      oper_centr_freq_seg1_idx,
--				      cmode->vht_capab,
--				      &cmode->he_capab[ieee80211_mode]);
--
--	if (err) {
--		wpa_printf(MSG_ERROR, "DFS failed to calculate CSA freq params");
--		hostapd_disable_iface(iface);
--		return err;
--	}
- 
--	for (i = 0; i < iface->num_bss; i++) {
--		err = hostapd_switch_channel(iface->bss[i], &csa_settings);
--		if (err)
--			break;
--	}
--
--	if (err) {
--		wpa_printf(MSG_WARNING, "DFS failed to schedule CSA (%d) - trying fallback",
--			   err);
--		iface->freq = channel->freq;
--		iface->conf->channel = channel->chan;
--		iface->conf->secondary_channel = secondary_channel;
--		hostapd_set_oper_chwidth(iface->conf, new_vht_oper_chwidth);
--		hostapd_set_oper_centr_freq_seg0_idx(iface->conf,
--						     oper_centr_freq_seg0_idx);
--		hostapd_set_oper_centr_freq_seg1_idx(iface->conf,
--						     oper_centr_freq_seg1_idx);
--
--		hostapd_disable_iface(iface);
--		hostapd_enable_iface(iface);
--		return 0;
--	}
--
--	/* Channel configuration will be updated once CSA completes and
--	 * ch_switch_notify event is received */
--
--	wpa_printf(MSG_DEBUG, "DFS waiting channel switch event");
--	return 0;
-+	return hostapd_dfs_request_channel_switch(iface, channel->chan,
-+						  channel->freq,
-+						  secondary_channel,
-+						  oper_centr_freq_seg0_idx,
-+						  oper_centr_freq_seg1_idx);
- }
- 
- 
-@@ -1208,15 +1424,19 @@ int hostapd_dfs_radar_detected(struct hostapd_iface *iface, int freq,
- 	if (!res)
- 		return 0;
- 
--	/* Skip if reported radar event not overlapped our channels */
--	res = dfs_are_channels_overlapped(iface, freq, chan_width, cf1, cf2);
--	if (!res)
--		return 0;
-+	if (!hostapd_dfs_is_offchan_event(iface, freq)) {
-+		/* Skip if reported radar event not overlapped our channels */
-+		res = dfs_are_channels_overlapped(iface, freq, chan_width,
-+						  cf1, cf2);
-+		if (!res)
-+			return 0;
-+	}
- 
--	/* radar detected while operating, switch the channel. */
--	res = hostapd_dfs_start_channel_switch(iface);
-+	if (hostapd_dfs_offchan_start_channel_switch(iface, freq))
-+		/* radar detected while operating, switch the channel. */
-+		return hostapd_dfs_start_channel_switch(iface);
- 
--	return res;
-+	return 0;
- }
- 
- 
-@@ -1284,7 +1504,11 @@ int hostapd_dfs_start_cac(struct hostapd_iface *iface, int freq,
- 		"seg1=%d cac_time=%ds",
- 		freq, (freq - 5000) / 5, chan_offset, chan_width, cf1, cf2,
- 		iface->dfs_cac_ms / 1000);
--	iface->cac_started = 1;
-+
-+	if (hostapd_dfs_is_offchan_event(iface, freq))
-+		iface->radar_offchan.cac_started = 1;
-+	else
-+		iface->cac_started = 1;
- 	os_get_reltime(&iface->dfs_cac_start);
- 	return 0;
- }
-diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h
-index 27b985d..1c6c94e 100644
---- a/src/ap/hostapd.h
-+++ b/src/ap/hostapd.h
-@@ -521,6 +521,21 @@ struct hostapd_iface {
- 	int *basic_rates;
- 	int freq;
- 
-+	/* Offchanel chain configuration */
-+	struct {
-+		int channel;
-+		int secondary_channel;
-+		int freq;
-+		int centr_freq_seg0_idx;
-+		int centr_freq_seg1_idx;
-+		/* Main chain is on temporary channel during
-+		 * CAC detection on radar offchain
-+		 */
-+		unsigned int temp_ch:1;
-+		/* CAC started on radar offchain */
-+		unsigned int cac_started:1;
-+	} radar_offchan;
-+
- 	u16 hw_flags;
- 
- 	/* Number of associated Non-ERP stations (i.e., stations using 802.11b
-diff --git a/src/drivers/driver.h b/src/drivers/driver.h
-index 6d9194f..7ed47c0 100644
---- a/src/drivers/driver.h
-+++ b/src/drivers/driver.h
-@@ -777,6 +777,11 @@ struct hostapd_freq_params {
- 	 * for IEEE 802.11ay EDMG configuration.
- 	 */
- 	struct ieee80211_edmg_config edmg;
-+
-+	/**
-+	 * radar_offchan - Whether radar/CAC offchannel is requested
-+	 */
-+	int radar_offchan;
- };
- 
- /**
-@@ -2026,6 +2031,8 @@ struct wpa_driver_capa {
- #define WPA_DRIVER_FLAGS2_OCV			0x0000000000000080ULL
- /** Driver expects user space implementation of SME in AP mode */
- #define WPA_DRIVER_FLAGS2_AP_SME		0x0000000000000100ULL
-+/** Driver supports offchannel radar/CAC detection */
-+#define WPA_DRIVER_RADAR_OFFCHAN		0x0000000000000200ULL
- 	u64 flags2;
- 
- #define FULL_AP_CLIENT_STATE_SUPP(drv_flags) \
-diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
-index 4db8cce..62c3cd8 100644
---- a/src/drivers/driver_nl80211.c
-+++ b/src/drivers/driver_nl80211.c
-@@ -4885,6 +4885,7 @@ static int nl80211_put_freq_params(struct nl_msg *msg,
- 	wpa_printf(MSG_DEBUG, "  * he_enabled=%d", freq->he_enabled);
- 	wpa_printf(MSG_DEBUG, "  * vht_enabled=%d", freq->vht_enabled);
- 	wpa_printf(MSG_DEBUG, "  * ht_enabled=%d", freq->ht_enabled);
-+	wpa_printf(MSG_DEBUG, "  * radar_offchan=%d", freq->radar_offchan);
- 
- 	hw_mode = ieee80211_freq_to_chan(freq->freq, &channel);
- 	is_24ghz = hw_mode == HOSTAPD_MODE_IEEE80211G ||
-@@ -4962,6 +4963,9 @@ static int nl80211_put_freq_params(struct nl_msg *msg,
- 				NL80211_CHAN_NO_HT))
- 			return -ENOBUFS;
- 	}
-+	if (freq->radar_offchan)
-+		nla_put_flag(msg, NL80211_ATTR_RADAR_OFFCHAN);
-+
- 	return 0;
- }
- 
-diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c
-index cd596e3..e370ef3 100644
---- a/src/drivers/driver_nl80211_capa.c
-+++ b/src/drivers/driver_nl80211_capa.c
-@@ -665,6 +665,10 @@ static void wiphy_info_ext_feature_flags(struct wiphy_info_data *info,
- 	if (ext_feature_isset(ext_features, len,
- 			      NL80211_EXT_FEATURE_OPERATING_CHANNEL_VALIDATION))
- 		capa->flags2 |= WPA_DRIVER_FLAGS2_OCV;
-+
-+	if (ext_feature_isset(ext_features, len,
-+			      NL80211_EXT_FEATURE_RADAR_OFFCHAN))
-+		capa->flags2 |= WPA_DRIVER_RADAR_OFFCHAN;
- }
- 
- 
-diff --git a/src/drivers/nl80211_copy.h b/src/drivers/nl80211_copy.h
-index f7be755..736b483 100644
---- a/src/drivers/nl80211_copy.h
-+++ b/src/drivers/nl80211_copy.h
-@@ -2573,6 +2573,10 @@ enum nl80211_commands {
-  * @NL80211_ATTR_WIPHY_ANTENNA_GAIN: Configured antenna gain. Used to reduce
-  *	transmit power to stay within regulatory limits. u32, dBi.
-  *
-+ * @NL80211_ATTR_RADAR_OFFCHAN: Configure dedicated chain available for radar
-+ *	detection on some hw. The chain can't be used to transmits or receives
-+ *	frames. The driver is supposed to implement CAC management in sw or fw.
-+ *
-  * @NUM_NL80211_ATTR: total number of nl80211_attrs available
-  * @NL80211_ATTR_MAX: highest attribute number currently defined
-  * @__NL80211_ATTR_AFTER_LAST: internal use
-@@ -3078,6 +3082,8 @@ enum nl80211_attrs {
- 
- 	NL80211_ATTR_WIPHY_ANTENNA_GAIN,
- 
-+	NL80211_ATTR_RADAR_OFFCHAN,
-+
- 	/* add attributes here, update the policy in nl80211.c */
- 
- 	__NL80211_ATTR_AFTER_LAST,
-@@ -5974,6 +5980,9 @@ enum nl80211_feature_flags {
-  * @NL80211_EXT_FEATURE_BSS_COLOR: The driver supports BSS color collision
-  *	detection and change announcemnts.
-  *
-+ * @NL80211_EXT_FEATURE_RADAR_OFFCHAN: Device supports offchannel radar/CAC
-+ *	detection.
-+ *
-  * @NUM_NL80211_EXT_FEATURES: number of extended features.
-  * @MAX_NL80211_EXT_FEATURES: highest extended feature index.
-  */
-@@ -6039,6 +6048,7 @@ enum nl80211_ext_feature_index {
- 	NL80211_EXT_FEATURE_SECURE_RTT,
- 	NL80211_EXT_FEATURE_PROT_RANGE_NEGO_AND_MEASURE,
- 	NL80211_EXT_FEATURE_BSS_COLOR,
-+	NL80211_EXT_FEATURE_RADAR_OFFCHAN,
- 
- 	/* add new features before the definition below */
- 	NUM_NL80211_EXT_FEATURES,