[][MAC80211][WiFi6][hostapd][Auto Channel Selection issue and patch sync]

[Description]
Fix ACS issues in WiFi6 Codebase.

Fix Issue#1. channels should qualify the whole bw group in ACS algo
Fix Issue#2. Fix ACS channel time too long on duty channel

[Release-log]
N/A

Change-Id: I1f2e16ebb584165015b3b1d582009e32fca85e39
Reviewed-on: https://gerrit.mediatek.inc/c/openwrt/feeds/mtk_openwrt_feeds/+/8269149
diff --git a/autobuild_mac80211_release/package/kernel/mt76/patches/0010-wifi-mt76-ACS-channel-time-too-long-on-duty-channel.patch b/autobuild_mac80211_release/package/kernel/mt76/patches/0010-wifi-mt76-ACS-channel-time-too-long-on-duty-channel.patch
new file mode 100644
index 0000000..5995490
--- /dev/null
+++ b/autobuild_mac80211_release/package/kernel/mt76/patches/0010-wifi-mt76-ACS-channel-time-too-long-on-duty-channel.patch
@@ -0,0 +1,36 @@
+From 063ffcd8a8fdb835e3d74082b4dc411750f2a234 Mon Sep 17 00:00:00 2001
+From: Evelyn Tsai <evelyn.tsai@mediatek.com>
+Date: Sat, 18 Nov 2023 07:36:45 +0800
+Subject: [PATCH] wifi: mt76: ACS channel time too long on duty channel
+
+Step and issue:
+1. Set channel to 36 in hostapd config;
+2. Bootup;
+3. Enable ACS through UCI command and reload;
+4. Check hostapd log, channel 36 channel_time is much longer than other channels.
+
+Root cause:
+The reset chan_stat condition missed duty channel.
+
+Solution:
+When scan start, need to reset chan_stat in each channel switch.
+---
+ mac80211.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/mac80211.c b/mac80211.c
+index aaaf6a9..0b13602 100644
+--- a/mac80211.c
++++ b/mac80211.c
+@@ -931,7 +931,7 @@ void mt76_set_channel(struct mt76_phy *phy)
+ 	if (!offchannel)
+ 		phy->main_chan = chandef->chan;
+ 
+-	if (chandef->chan != phy->main_chan)
++	if (chandef->chan != phy->main_chan || test_bit(MT76_SCANNING, &phy->state))
+ 		memset(phy->chan_state, 0, sizeof(*phy->chan_state));
+ }
+ EXPORT_SYMBOL_GPL(mt76_set_channel);
+-- 
+2.18.0
+
diff --git a/autobuild_mac80211_release/package/network/services/hostapd/patches/mtk-0046-hostapd-mtk-ACS-Fix-2.4GHz-HT40-case-and-channel-swi.patch b/autobuild_mac80211_release/package/network/services/hostapd/patches/mtk-0046-hostapd-mtk-ACS-Fix-2.4GHz-HT40-case-and-channel-swi.patch
index 31e92e6..d968859 100644
--- a/autobuild_mac80211_release/package/network/services/hostapd/patches/mtk-0046-hostapd-mtk-ACS-Fix-2.4GHz-HT40-case-and-channel-swi.patch
+++ b/autobuild_mac80211_release/package/network/services/hostapd/patches/mtk-0046-hostapd-mtk-ACS-Fix-2.4GHz-HT40-case-and-channel-swi.patch
@@ -1,4 +1,4 @@
-From 97b4dbb136ff86dd6ca7fac5fb4ce9356337a8bd Mon Sep 17 00:00:00 2001
+From 920a20927f1537ae2a6ce9c7123ef189e83cd0a0 Mon Sep 17 00:00:00 2001
 From: Evelyn Tsai <evelyn.tsai@mediatek.com>
 Date: Sat, 11 Nov 2023 11:42:59 +0800
 Subject: [PATCH] hostapd: mtk: ACS: Fix 2.4GHz HT40 case and channel switch
@@ -21,31 +21,16 @@
 In the test case, new DFS channel is set to runnint config settings, but
 another param "acs" is still 1 (enable), caused the ACS running when
 intf enabled.
-
-CR-Id: WCNCR00240772
 ---
- src/ap/acs.c     | 170 +++++++++++++++++++++++++----------------------
+ src/ap/acs.c     | 142 ++++++++++++++++++++++++++---------------------
  src/ap/hostapd.c |   3 +
- 2 files changed, 93 insertions(+), 80 deletions(-)
+ 2 files changed, 83 insertions(+), 62 deletions(-)
 
 diff --git a/src/ap/acs.c b/src/ap/acs.c
-index 130e135..73d2195 100644
+index 130e135..65573b9 100644
 --- a/src/ap/acs.c
 +++ b/src/ap/acs.c
-@@ -577,12 +577,6 @@ static void acs_survey_mode_interference_factor(
- 		    iface->conf->acs_exclude_dfs)
- 			continue;
- 
--		if (!is_in_chanlist(iface, chan))
--			continue;
--
--		if (!is_in_freqlist(iface, chan))
--			continue;
--
- 		if (chan->max_tx_power < iface->conf->min_tx_power)
- 			continue;
- 
-@@ -712,17 +706,29 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface,
+@@ -712,10 +712,19 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface,
  			 struct hostapd_channel_data **ideal_chan,
  			 long double *ideal_factor)
  {
@@ -66,9 +51,8 @@
  
  	for (i = 0; i < mode->num_channels; i++) {
  		double total_weight;
- 		struct acs_bias *bias, tmp_bias;
--		bool update_best = true;
-+		bool update_best = true, has_candidate = true;
+@@ -723,6 +732,9 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface,
+ 		bool update_best = true;
  
  		best = chan = &mode->channels[i];
 +		wpa_printf(MSG_INFO,
@@ -77,25 +61,7 @@
  
  		/* Since in the current ACS implementation the first channel is
  		 * always a primary channel, skip channels not available as
-@@ -735,11 +741,12 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface,
- 		    iface->conf->acs_exclude_dfs)
- 			continue;
- 
--		if (!is_in_chanlist(iface, chan))
--			continue;
--
--		if (!is_in_freqlist(iface, chan))
--			continue;
-+		if (!is_in_chanlist(iface, chan) || !is_in_freqlist(iface, chan)) {
-+			if (is_24ghz_mode(mode->mode))
-+				continue;
-+			else
-+				has_candidate = false;
-+		}
- 
- 		if (chan->max_tx_power < iface->conf->min_tx_power)
- 			continue;
-@@ -747,7 +754,7 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface,
+@@ -747,7 +759,7 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface,
  		if (chan->flag & HOSTAPD_CHAN_INDOOR_ONLY && iface->conf->country[2] == 0x4f)
  			continue;
  
@@ -104,20 +70,20 @@
  			wpa_printf(MSG_DEBUG,
  				   "ACS: Channel %d: BW %u is not supported",
  				   chan->chan, bw);
-@@ -789,60 +796,76 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface,
+@@ -789,60 +801,73 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface,
  		}
  
  		factor = 0;
 -		if (acs_usable_chan(chan))
 -			factor = chan->interference_factor;
 -		total_weight = 1;
-+		total_weight = 0;
- 
+-
 -		for (j = 1; j < n_chans; j++) {
 -			adj_chan = acs_find_chan(iface, chan->freq + (j * 20));
 -			if (!adj_chan)
 -				break;
--
++		total_weight = 0;
+ 
 -			if (!chan_bw_allowed(adj_chan, bw, 1, 0)) {
 -				wpa_printf(MSG_DEBUG,
 -					   "ACS: PRI Channel %d: secondary channel %d BW %u is not supported",
@@ -153,12 +119,8 @@
 -				   chan->chan);
 -			continue;
 -		}
-+				if (!chan_bw_allowed(adj_chan, bw, 1, 0)) {
-+					wpa_printf(MSG_DEBUG,
-+						   "ACS: PRI Channel %d: secondary channel %d BW %u is not supported",
-+						   chan->chan, adj_chan->chan, bw);
++				if (!is_in_chanlist(iface, adj_chan) || !is_in_freqlist(iface, adj_chan))
 +					break;
-+				}
  
 -		/* If the AP is in the 5 GHz or 6 GHz band, lets prefer a less
 -		 * crowded primary channel if one was found in the segment */
@@ -171,30 +133,31 @@
 -				   best->interference_factor);
 -			chan = best;
 -		}
++				if (!chan_bw_allowed(adj_chan, bw, 1, 0)) {
++					wpa_printf(MSG_DEBUG,
++						   "ACS: PRI Channel %d: secondary channel %d BW %u is not supported",
++						   chan->chan, adj_chan->chan, bw);
++					break;
++				}
+ 
+-		/* 2.4 GHz has overlapping 20 MHz channels. Include adjacent
+-		 * channel interference factor. */
+-		if (is_24ghz_mode(mode->mode)) {
 +				update_best = true;
 +				if (acs_usable_chan(adj_chan)) {
 +					factor += adj_chan->interference_factor;
 +					total_weight += 1;
-+
-+					if (!is_in_chanlist(iface, adj_chan) ||
-+						!is_in_freqlist(iface, adj_chan))
-+						update_best = false;
 +				} else {
 +					update_best = false;
 +				}
 +
 +				/* find the best channel in this segment */
-+				if (update_best && (!has_candidate ||
-+					adj_chan->interference_factor < best->interference_factor)) {
++				if (update_best &&
++					adj_chan->interference_factor < best->interference_factor)
 +					best = adj_chan;
-+					has_candidate = true;
-+				}
 +			}
- 
--		/* 2.4 GHz has overlapping 20 MHz channels. Include adjacent
--		 * channel interference factor. */
--		if (is_24ghz_mode(mode->mode)) {
-+			if (j != n_chans || !has_candidate) {
++
++			if (j != n_chans) {
 +				wpa_printf(MSG_DEBUG, "ACS: Channel %d: not enough bandwidth",
 +					   chan->chan);
 +				continue;
@@ -212,7 +175,7 @@
  			for (j = 0; j < n_chans; j++) {
 +				/* Will set primary_channel / secondary_channel(40M case) weight to 1 */
 +				tmp_chan = acs_find_chan(iface, chan->freq +
-+							 (j * 20) * sec_ch_factor);
++							 (j * sec_ch_factor * 20));
 +				if (tmp_chan && acs_usable_chan(tmp_chan)) {
 +					factor += tmp_chan->interference_factor;
 +					total_weight += 1;
@@ -222,38 +185,38 @@
 +				interference factor, separately for primary/secondary channel. */
  				adj_chan = acs_find_chan(iface, chan->freq +
 -							 (j * 20) - 5);
-+							 ((j * 20) - 5) * sec_ch_factor);
++							  (j * sec_ch_factor * 20) - 5);
  				if (adj_chan && acs_usable_chan(adj_chan)) {
  					factor += ACS_ADJ_WEIGHT *
  						adj_chan->interference_factor;
-@@ -850,7 +873,7 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface,
+@@ -850,7 +875,7 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface,
  				}
  
  				adj_chan = acs_find_chan(iface, chan->freq +
 -							 (j * 20) - 10);
-+							 ((j * 20) - 10) * sec_ch_factor);
++							  (j * sec_ch_factor * 20) - 10);
  				if (adj_chan && acs_usable_chan(adj_chan)) {
  					factor += ACS_NEXT_ADJ_WEIGHT *
  						adj_chan->interference_factor;
-@@ -858,7 +881,7 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface,
+@@ -858,7 +883,7 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface,
  				}
  
  				adj_chan = acs_find_chan(iface, chan->freq +
 -							 (j * 20) + 5);
-+							 ((j * 20) + 5) * sec_ch_factor);
++							 (j * sec_ch_factor * 20) + 5);
  				if (adj_chan && acs_usable_chan(adj_chan)) {
  					factor += ACS_ADJ_WEIGHT *
  						adj_chan->interference_factor;
-@@ -866,7 +889,7 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface,
+@@ -866,7 +891,7 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface,
  				}
  
  				adj_chan = acs_find_chan(iface, chan->freq +
 -							 (j * 20) + 10);
-+							 ((j * 20) + 10) * sec_ch_factor);
++							 (j * sec_ch_factor * 20) + 10);
  				if (adj_chan && acs_usable_chan(adj_chan)) {
  					factor += ACS_NEXT_ADJ_WEIGHT *
  						adj_chan->interference_factor;
-@@ -875,7 +898,8 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface,
+@@ -875,7 +900,8 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface,
  			}
  		}
  
@@ -263,7 +226,7 @@
  
  		bias = NULL;
  		if (iface->conf->acs_chan_bias) {
-@@ -894,11 +918,11 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface,
+@@ -894,11 +920,11 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface,
  
  		if (bias) {
  			factor *= bias->bias;
@@ -277,7 +240,7 @@
  				   "ACS:  * channel %d: total interference = %Lg",
  				   chan->chan, factor);
  		}
-@@ -939,14 +963,6 @@ acs_find_ideal_chan(struct hostapd_iface *iface)
+@@ -939,14 +965,6 @@ acs_find_ideal_chan(struct hostapd_iface *iface)
  		goto bw_selected;
  	}
  
@@ -292,7 +255,7 @@
  	if (iface->conf->ieee80211n &&
  	    iface->conf->secondary_channel)
  		n_chans = 2;
-@@ -981,7 +997,7 @@ bw_selected:
+@@ -981,7 +999,7 @@ bw_selected:
  	}
  
  	if (ideal_chan) {
@@ -301,19 +264,6 @@
  			   ideal_chan->chan, ideal_chan->freq, ideal_factor);
  		return ideal_chan;
  	}
-@@ -1169,12 +1185,6 @@ static int * acs_request_scan_add_freqs(struct hostapd_iface *iface,
- 		     iface->conf->acs_exclude_dfs))
- 			continue;
- 
--		if (!is_in_chanlist(iface, chan))
--			continue;
--
--		if (!is_in_freqlist(iface, chan))
--			continue;
--
- 		if (chan->max_tx_power < iface->conf->min_tx_power)
- 			continue;
- 
 diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
 index f2eb638..250c168 100644
 --- a/src/ap/hostapd.c