[][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