[rdkb][common][bsp][Refactor and sync wifi from openwrt]
[Description]
d34487c3 [MAC80211][WiFi6][mt76][Add mt7981 mt7916 mt7915 fw_wm_info support]
327eaf76 [MAC80211][wifi7][Release][Update WiFi7 Filogic680/660 Firmware]
fa03d7ea [MAC80211][WiFi6][hostapd][Fix 2/6G channel switch fail issue]
c0bf67d9 [MAC80211][misc][Add Filogic 880 Non-MLO SDK Release]
e5d03217 [MAC80211][WiFi6][Rebase Patches][Refactor set_offchan_ctrl]
6cad79ae [MAC80211][WiFi6][hostapd][Add support for DFS channel switch with CSA sent]
cde50012 [MAC80211][WiFi6][core][Add DFS channel CSA flow]
0142fd16 [MAC80211][WiFi6][mt76][Add post channel switch callback for DFS channel switch support]
cb3f4c58 [MAC80211][WiFi6][mt76][Update Connac2 CSI Feature]
1b66ac4c [MAC80211][WiFi6][mt76][Refactor precal loading and binfile mode to align upstream]
0ece467b [MAC80211][WiFi6][mt76][Fix scs feature calltrace issue]
1dca03f1 [MAC80211][WiFi6/7][Misc][Change group mgmt cipher setting to align group cipher]
0aa52762 [MAC80211][WiFi6][mt76][Fix muru_onoff as all enabled by default]
c3e5f505 [MAC80211][WiFi6][hostapd][Fix mu_onoff was overwritten with unexpected values]
7090eabe [MAC80211][WiFi6/7][core][Add tx_burst option in wireless configuration file for Kite]
669d3071 [MAC80211][WiFi6][mt76][rebase patches]
c5d6b3e7 [mac80211][mt76][Fix patch fail]
55ef4059 [MAC80211][WiFi6][mt76][Fix TxS ACK is incorrectly reported]
e166eae1 [MAC80211][WiFi6][Misc][Add Filogic 820 Build]
118ffd7e [mac80211][wifi6][mt76][Fix crash caused by per-BSS counter updating]
68015098 [MAC80211][WiFi7][mt76][Add Eagle 2adie TBTC default bin]
eae6e8c0 [MAC80211][WiFi7][mt76][Add Eagle 2adie TBTC support in mt76 Makefile]
cccc8eb9 [MAC80211[WiFi6][hostapd][Fix wds AP interface adding issue]
173fe3b0 [MAC80211][WiFi6][mt76][Add scs feature for connac2 mt76]
1b8af8d9 [MAC80211][WiFi6][mt76][rebase patches]
6dc40325 [MAC80211][WiFi7][misc][fix hostapd udebug init fail]
aa4b39ae [[mt76][csi][mt7915][mt7986] update csi feature]
7d458da2 [MAC80211][WiFi6][hostapd][Auto Channel Selection channel time issue]
f0b5502f [MAC80211][WiFi7][misc][fix build error]
b63c9cf6 [MAC80211][WiFi6/7][misc][fix ucode and backport 6.5 patch fail]
ce056dc7 [mac80211][wifi6][mt76][Add variant support for Cheetah MT76]
c5ae3f9c [MAC80211][WiFi6/7][Misc][Add country setting consistent check before enable AP.]
d57d9c5a [mac80211][misc][wifi6/7][Update libubox to the latest version]
be7dbf21 [mac80211][misc][wifi7][Revert libubox to 20230523 to prevent build fail]
ae9b4428 [MAC80211][WiFi6][mt76][Add cal free data support]
52fd5d80 [MAC80211][WiFi7][Misc][Adjust MU EDCA timer in mac80211.sh]
66c649de [mac80211][hostapd][netifd][Revert udebug for build pass]
136c7f11 [MAC80211][hostapd][wifi7][Fix build fail]
8911e727 [MAC80211][WiFi6][hostapd][Auto Channel Selection issue and patch sync]
75161456 [MAC80211][WiFi7][mt76][Fix issue for testmode bit in eagle defaut bin]
4dc2d646 [MAC80211][WiFi6][mt76][Fix cheetah 5G ibf issue]
d4561158 [MAC80211][WiFi6][Misc][Add Filogic 820 Build]
2e5a1997 [MAC80211][WiFi6][hostapd][Backport hostapd ACS patches and some ACS fixes]
b0305b6e [MAC80211][WiFi6/7][Misc][Add 6g band default enable mbo IE]
[Release-log]
Change-Id: I872b422c1fc56ebd3a1cff3252cb403a2015eabe
diff --git a/recipes-wifi/hostapd/files/patches/bp-0001-ACS-Extract-bw40-80-160-freqs-out-of-acs_usable_bwXX.patch b/recipes-wifi/hostapd/files/patches/bp-0001-ACS-Extract-bw40-80-160-freqs-out-of-acs_usable_bwXX.patch
new file mode 100644
index 0000000..be0bc74
--- /dev/null
+++ b/recipes-wifi/hostapd/files/patches/bp-0001-ACS-Extract-bw40-80-160-freqs-out-of-acs_usable_bwXX.patch
@@ -0,0 +1,172 @@
+From 8df5520f49796e4e292de6895aa0bc518978b377 Mon Sep 17 00:00:00 2001
+From: Nicolas Escande <nico.escande@gmail.com>
+Date: Wed, 27 Apr 2022 15:36:59 +0200
+Subject: [PATCH 01/50] ACS: Extract bw40/80/160 freqs out of
+ acs_usable_bwXXX_chan()
+
+This extracts the 3 lists of allowed channels for 40/80/160 MHz
+bandwidth out of their respective functions. It also adds for each
+segment the frequency of the segment's last channel and the index of the
+segment's "center" channel.
+
+This is preparative work to allow selecting a channel which is not the
+first of its segment for 40/80/160 MHz. In addition, this adds the 5 GHz
+160 MHz channel defined for 5735-5895 MHz (channels 149-177).
+
+Signed-off-by: Nicolas Escande <nico.escande@gmail.com>
+---
+ src/ap/acs.c | 107 ++++++++++++++++++++++++++++++---------------------
+ 1 file changed, 63 insertions(+), 44 deletions(-)
+
+diff --git a/src/ap/acs.c b/src/ap/acs.c
+index 4a0a4c7..60c90e9 100644
+--- a/src/ap/acs.c
++++ b/src/ap/acs.c
+@@ -241,6 +241,57 @@
+ * [1] http://en.wikipedia.org/wiki/Near_and_far_field
+ */
+
++enum bw_type {
++ ACS_BW40,
++ ACS_BW80,
++ ACS_BW160,
++};
++
++struct bw_item {
++ int first;
++ int last;
++ int center_chan;
++};
++
++static const struct bw_item bw_40[] = {
++ { 5180, 5200, 38 }, { 5220, 5240, 46 }, { 5260, 5280, 54 },
++ { 5300, 5320, 62 }, { 5500, 5520, 102 }, { 5540, 5560, 110 },
++ { 5580, 5600, 110 }, { 5620, 5640, 126}, { 5660, 5680, 134 },
++ { 5700, 5720, 142 }, { 5745, 5765, 151 }, { 5785, 5805, 159 },
++ { 5825, 5845, 167 }, { 5865, 5885, 175 },
++ { 5955, 5975, 3 }, { 5995, 6015, 11 }, { 6035, 6055, 19 },
++ { 6075, 6095, 27 }, { 6115, 6135, 35 }, { 6155, 6175, 43 },
++ { 6195, 6215, 51 }, { 6235, 6255, 59 }, { 6275, 6295, 67 },
++ { 6315, 6335, 75 }, { 6355, 6375, 83 }, { 6395, 6415, 91 },
++ { 6435, 6455, 99 }, { 6475, 6495, 107 }, { 6515, 6535, 115 },
++ { 6555, 6575, 123 }, { 6595, 6615, 131 }, { 6635, 6655, 139 },
++ { 6675, 6695, 147 }, { 6715, 6735, 155 }, { 6755, 6775, 163 },
++ { 6795, 6815, 171 }, { 6835, 6855, 179 }, { 6875, 6895, 187 },
++ { 6915, 6935, 195 }, { 6955, 6975, 203 }, { 6995, 7015, 211 },
++ { 7035, 7055, 219 }, { 7075, 7095, 227}, { -1, -1, -1 }
++};
++static const struct bw_item bw_80[] = {
++ { 5180, 5240, 42 }, { 5260, 5320, 58 }, { 5500, 5560, 106 },
++ { 5580, 5640, 122 }, { 5660, 5720, 138 }, { 5745, 5805, 155 },
++ { 5825, 5885, 171},
++ { 5955, 6015, 7 }, { 6035, 6095, 23 }, { 6115, 6175, 39 },
++ { 6195, 6255, 55 }, { 6275, 6335, 71 }, { 6355, 6415, 87 },
++ { 6435, 6495, 103 }, { 6515, 6575, 119 }, { 6595, 6655, 135 },
++ { 6675, 6735, 151 }, { 6755, 6815, 167 }, { 6835, 6895, 183 },
++ { 6915, 6975, 199 }, { 6995, 7055, 215 }, { -1, -1, -1 }
++};
++static const struct bw_item bw_160[] = {
++ { 5180, 5320, 50 }, { 5500, 5640, 114 }, { 5745, 5885, 163 },
++ { 5955, 6095, 15 }, { 6115, 6255, 47 }, { 6275, 6415, 79 },
++ { 6435, 6575, 111 }, { 6595, 6735, 143 },
++ { 6755, 6895, 175 }, { 6915, 7055, 207 }, { -1, -1, -1 }
++};
++static const struct bw_item *bw_desc[] = {
++ [ACS_BW40] = bw_40,
++ [ACS_BW80] = bw_80,
++ [ACS_BW160] = bw_160,
++};
++
+
+ static int acs_request_scan(struct hostapd_iface *iface);
+ static int acs_survey_is_sufficient(struct freq_survey *survey);
+@@ -370,50 +421,18 @@ acs_survey_chan_interference_factor(struct hostapd_iface *iface,
+ }
+
+
+-static int acs_usable_bw40_chan(const struct hostapd_channel_data *chan)
++static bool acs_usable_bw_chan(const struct hostapd_channel_data *chan,
++ enum bw_type bw)
+ {
+- const int allowed[] = { 5180, 5220, 5260, 5300, 5500, 5540, 5580, 5620,
+- 5660, 5745, 5785, 4920, 4960, 5955, 5995, 6035,
+- 6075, 6115, 6155, 6195, 6235, 6275, 6315, 6355,
+- 6395, 6435, 6475, 6515, 6555, 6595, 6635, 6675,
+- 6715, 6755, 6795, 6835, 6875, 6915, 6955, 6995,
+- 7035, 7075 };
+- unsigned int i;
+-
+- for (i = 0; i < ARRAY_SIZE(allowed); i++)
+- if (chan->freq == allowed[i])
+- return 1;
+-
+- return 0;
+-}
+-
+-
+-static int acs_usable_bw80_chan(const struct hostapd_channel_data *chan)
+-{
+- const int allowed[] = { 5180, 5260, 5500, 5580, 5660, 5745, 5955, 6035,
+- 6115, 6195, 6275, 6355, 6435, 6515, 6595, 6675,
+- 6755, 6835, 6915, 6995 };
+- unsigned int i;
+-
+- for (i = 0; i < ARRAY_SIZE(allowed); i++)
+- if (chan->freq == allowed[i])
+- return 1;
+-
+- return 0;
+-}
+-
+-
+-static int acs_usable_bw160_chan(const struct hostapd_channel_data *chan)
+-{
+- const int allowed[] = { 5180, 5500, 5955, 6115, 6275, 6435, 6595, 6755,
+- 6915 };
+- unsigned int i;
++ unsigned int i = 0;
+
+- for (i = 0; i < ARRAY_SIZE(allowed); i++)
+- if (chan->freq == allowed[i])
+- return 1;
++ while (bw_desc[bw][i].first != -1) {
++ if (chan->freq == bw_desc[bw][i].first)
++ return true;
++ i++;
++ }
+
+- return 0;
++ return false;
+ }
+
+
+@@ -705,7 +724,7 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface,
+ ((iface->conf->ieee80211n &&
+ iface->conf->secondary_channel) ||
+ is_6ghz_freq(chan->freq)) &&
+- !acs_usable_bw40_chan(chan)) {
++ !acs_usable_bw_chan(chan, ACS_BW40)) {
+ wpa_printf(MSG_DEBUG,
+ "ACS: Channel %d: not allowed as primary channel for 40 MHz bandwidth",
+ chan->chan);
+@@ -716,7 +735,7 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface,
+ (iface->conf->ieee80211ac || iface->conf->ieee80211ax)) {
+ if (hostapd_get_oper_chwidth(iface->conf) ==
+ CONF_OPER_CHWIDTH_80MHZ &&
+- !acs_usable_bw80_chan(chan)) {
++ !acs_usable_bw_chan(chan, ACS_BW80)) {
+ wpa_printf(MSG_DEBUG,
+ "ACS: Channel %d: not allowed as primary channel for 80 MHz bandwidth",
+ chan->chan);
+@@ -725,7 +744,7 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface,
+
+ if (hostapd_get_oper_chwidth(iface->conf) ==
+ CONF_OPER_CHWIDTH_160MHZ &&
+- !acs_usable_bw160_chan(chan)) {
++ !acs_usable_bw_chan(chan, ACS_BW160)) {
+ wpa_printf(MSG_DEBUG,
+ "ACS: Channel %d: not allowed as primary channel for 160 MHz bandwidth",
+ chan->chan);
+--
+2.18.0
+
diff --git a/recipes-wifi/hostapd/files/patches/bp-0002-ACS-Introduce-acs_get_bw_center_chan.patch b/recipes-wifi/hostapd/files/patches/bp-0002-ACS-Introduce-acs_get_bw_center_chan.patch
new file mode 100644
index 0000000..15e8c98
--- /dev/null
+++ b/recipes-wifi/hostapd/files/patches/bp-0002-ACS-Introduce-acs_get_bw_center_chan.patch
@@ -0,0 +1,87 @@
+From 3e2fa0f4ab02538c66e61058749272565d94d111 Mon Sep 17 00:00:00 2001
+From: Nicolas Escande <nico.escande@gmail.com>
+Date: Wed, 27 Apr 2022 15:37:00 +0200
+Subject: [PATCH 02/50] ACS: Introduce acs_get_bw_center_chan()
+
+When using 40/80/160 MHz bandwidth, instead of computing the index of
+the segment center freq based on the selected channel, lets look it up
+in the bw_desc[] table.
+
+This is preparative work to allow selecting a primary channel which is
+not the first of the segment.
+
+Signed-off-by: Nicolas Escande <nico.escande@gmail.com>
+---
+ src/ap/acs.c | 33 +++++++++++++++++++++++++++------
+ 1 file changed, 27 insertions(+), 6 deletions(-)
+
+diff --git a/src/ap/acs.c b/src/ap/acs.c
+index 60c90e9..511200d 100644
+--- a/src/ap/acs.c
++++ b/src/ap/acs.c
+@@ -436,6 +436,21 @@ static bool acs_usable_bw_chan(const struct hostapd_channel_data *chan,
+ }
+
+
++static int acs_get_bw_center_chan(int freq, enum bw_type bw)
++{
++ unsigned int i = 0;
++
++ while (bw_desc[bw][i].first != -1) {
++ if (freq >= bw_desc[bw][i].first &&
++ freq <= bw_desc[bw][i].last)
++ return bw_desc[bw][i].center_chan;
++ i++;
++ }
++
++ return 0;
++}
++
++
+ static int acs_survey_is_sufficient(struct freq_survey *survey)
+ {
+ if (!(survey->filled & SURVEY_HAS_NF)) {
+@@ -936,19 +951,26 @@ bw_selected:
+
+ static void acs_adjust_center_freq(struct hostapd_iface *iface)
+ {
+- int offset;
++ int center;
+
+ wpa_printf(MSG_DEBUG, "ACS: Adjusting VHT center frequency");
+
+ switch (hostapd_get_oper_chwidth(iface->conf)) {
+ case CONF_OPER_CHWIDTH_USE_HT:
+- offset = 2 * iface->conf->secondary_channel;
++ if (iface->conf->secondary_channel &&
++ iface->freq >= 2400 && iface->freq < 2500)
++ center = iface->conf->channel +
++ 2 * iface->conf->secondary_channel;
++ else if (iface->conf->secondary_channel)
++ center = acs_get_bw_center_chan(iface->freq, ACS_BW40);
++ else
++ center = iface->conf->channel;
+ break;
+ case CONF_OPER_CHWIDTH_80MHZ:
+- offset = 6;
++ center = acs_get_bw_center_chan(iface->freq, ACS_BW80);
+ break;
+ case CONF_OPER_CHWIDTH_160MHZ:
+- offset = 14;
++ center = acs_get_bw_center_chan(iface->freq, ACS_BW160);
+ break;
+ default:
+ /* TODO: How can this be calculated? Adjust
+@@ -958,8 +980,7 @@ static void acs_adjust_center_freq(struct hostapd_iface *iface)
+ return;
+ }
+
+- hostapd_set_oper_centr_freq_seg0_idx(iface->conf,
+- iface->conf->channel + offset);
++ hostapd_set_oper_centr_freq_seg0_idx(iface->conf, center);
+ }
+
+
+--
+2.18.0
+
diff --git a/recipes-wifi/hostapd/files/patches/bp-0003-ACS-introduce-acs_adjust_secondary.patch b/recipes-wifi/hostapd/files/patches/bp-0003-ACS-introduce-acs_adjust_secondary.patch
new file mode 100644
index 0000000..b4ac1f0
--- /dev/null
+++ b/recipes-wifi/hostapd/files/patches/bp-0003-ACS-introduce-acs_adjust_secondary.patch
@@ -0,0 +1,92 @@
+From 03dd213b918218fec270e781d284ec394fb63ef1 Mon Sep 17 00:00:00 2001
+From: Nicolas Escande <nico.escande@gmail.com>
+Date: Wed, 27 Apr 2022 15:37:01 +0200
+Subject: [PATCH 03/50] ACS: introduce acs_adjust_secondary
+
+When using 40/80/160 MHz bandwidth on the 5 GHz or 6 GHz band, enforce
+the secondary channel to be the other channel of the corresponding 40
+MHz segment.
+
+Even if this is useless for now, this is preparatory work to allow ACS
+to select a primary channel which is not the first of its segment.
+
+Signed-off-by: Nicolas Escande <nico.escande@gmail.com>
+---
+ src/ap/acs.c | 46 +++++++++++++++++++++++++++++++++++++++++++++-
+ 1 file changed, 45 insertions(+), 1 deletion(-)
+
+diff --git a/src/ap/acs.c b/src/ap/acs.c
+index 511200d..78d1feb 100644
+--- a/src/ap/acs.c
++++ b/src/ap/acs.c
+@@ -634,6 +634,26 @@ acs_find_chan_mode(struct hostapd_hw_modes *mode, int freq)
+ }
+
+
++static enum hostapd_hw_mode
++acs_find_mode(struct hostapd_iface *iface, int freq)
++{
++ int i;
++ struct hostapd_hw_modes *mode;
++ struct hostapd_channel_data *chan;
++
++ for (i = 0; i < iface->num_hw_features; i++) {
++ mode = &iface->hw_features[i];
++ if (!hostapd_hw_skip_mode(iface, mode)) {
++ chan = acs_find_chan_mode(mode, freq);
++ if (chan)
++ return mode->mode;
++ }
++ }
++
++ return HOSTAPD_MODE_IEEE80211ANY;
++}
++
++
+ static struct hostapd_channel_data *
+ acs_find_chan(struct hostapd_iface *iface, int freq)
+ {
+@@ -949,6 +969,28 @@ bw_selected:
+ }
+
+
++static void acs_adjust_secondary(struct hostapd_iface *iface)
++{
++ unsigned int i;
++
++ /* When working with bandwidth over 20 MHz on the 5 GHz or 6 GHz band,
++ * ACS can return a secondary channel which is not the first channel of
++ * the segment and we need to adjust. */
++ if (!iface->conf->secondary_channel ||
++ acs_find_mode(iface, iface->freq) != HOSTAPD_MODE_IEEE80211A)
++ return;
++
++ wpa_printf(MSG_DEBUG, "ACS: Adjusting HT/VHT/HE secondary frequency");
++
++ for (i = 0; bw_desc[ACS_BW40][i].first != -1; i++) {
++ if (iface->freq == bw_desc[ACS_BW40][i].first)
++ iface->conf->secondary_channel = 1;
++ else if (iface->freq == bw_desc[ACS_BW40][i].last)
++ iface->conf->secondary_channel = -1;
++ }
++}
++
++
+ static void acs_adjust_center_freq(struct hostapd_iface *iface)
+ {
+ int center;
+@@ -1036,8 +1078,10 @@ static void acs_study(struct hostapd_iface *iface)
+ iface->conf->channel = ideal_chan->chan;
+ iface->freq = ideal_chan->freq;
+
+- if (iface->conf->ieee80211ac || iface->conf->ieee80211ax)
++ if (iface->conf->ieee80211ac || iface->conf->ieee80211ax) {
++ acs_adjust_secondary(iface);
+ acs_adjust_center_freq(iface);
++ }
+
+ err = 0;
+ fail:
+--
+2.18.0
+
diff --git a/recipes-wifi/hostapd/files/patches/bp-0004-ACS-Allow-selecting-a-better-channel-when-using-40-8.patch b/recipes-wifi/hostapd/files/patches/bp-0004-ACS-Allow-selecting-a-better-channel-when-using-40-8.patch
new file mode 100644
index 0000000..8da5856
--- /dev/null
+++ b/recipes-wifi/hostapd/files/patches/bp-0004-ACS-Allow-selecting-a-better-channel-when-using-40-8.patch
@@ -0,0 +1,78 @@
+From a615aa302064919791f3912a5cf1a908390414df Mon Sep 17 00:00:00 2001
+From: Nicolas Escande <nico.escande@gmail.com>
+Date: Wed, 27 Apr 2022 15:37:02 +0200
+Subject: [PATCH 04/50] ACS: Allow selecting a better channel when using
+ 40/80/160 MHz
+
+When considering a channel for a bandwidth of 40/80/160 MHZ on the 5 GHz
+or 6 GHz band, allow selecting one of the other channels in the segment
+instead of the first one. This is done only if the other channel's
+interference_factor is lower than the first one's.
+
+Signed-off-by: Nicolas Escande <nico.escande@gmail.com>
+---
+ src/ap/acs.c | 25 +++++++++++++++++++++++--
+ 1 file changed, 23 insertions(+), 2 deletions(-)
+
+diff --git a/src/ap/acs.c b/src/ap/acs.c
+index 78d1feb..130e135 100644
+--- a/src/ap/acs.c
++++ b/src/ap/acs.c
+@@ -712,7 +712,7 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface,
+ struct hostapd_channel_data **ideal_chan,
+ long double *ideal_factor)
+ {
+- struct hostapd_channel_data *chan, *adj_chan = NULL;
++ struct hostapd_channel_data *chan, *adj_chan = NULL, *best;
+ long double factor;
+ int i, j;
+ unsigned int k;
+@@ -720,8 +720,9 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface,
+ for (i = 0; i < mode->num_channels; i++) {
+ double total_weight;
+ struct acs_bias *bias, tmp_bias;
++ bool update_best = true;
+
+- chan = &mode->channels[i];
++ best = chan = &mode->channels[i];
+
+ /* Since in the current ACS implementation the first channel is
+ * always a primary channel, skip channels not available as
+@@ -807,7 +808,15 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface,
+ if (acs_usable_chan(adj_chan)) {
+ factor += adj_chan->interference_factor;
+ total_weight += 1;
++ } else {
++ update_best = false;
+ }
++
++ /* find the best channel in this segment */
++ if (update_best &&
++ adj_chan->interference_factor <
++ best->interference_factor)
++ best = adj_chan;
+ }
+
+ if (j != n_chans) {
+@@ -816,6 +825,18 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface,
+ continue;
+ }
+
++ /* 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 */
++ if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211A &&
++ chan != best) {
++ wpa_printf(MSG_DEBUG,
++ "ACS: promoting channel %d over %d (less interference %Lg/%Lg)",
++ best->chan, chan->chan,
++ chan->interference_factor,
++ best->interference_factor);
++ chan = best;
++ }
++
+ /* 2.4 GHz has overlapping 20 MHz channels. Include adjacent
+ * channel interference factor. */
+ if (is_24ghz_mode(mode->mode)) {
+--
+2.18.0
+
diff --git a/recipes-wifi/hostapd/files/patches/mtk-0006-hostapd-mtk-Add-hostapd-MU-SET-GET-control.patch b/recipes-wifi/hostapd/files/patches/mtk-0006-hostapd-mtk-Add-hostapd-MU-SET-GET-control.patch
index b3f4138..af6eaa5 100644
--- a/recipes-wifi/hostapd/files/patches/mtk-0006-hostapd-mtk-Add-hostapd-MU-SET-GET-control.patch
+++ b/recipes-wifi/hostapd/files/patches/mtk-0006-hostapd-mtk-Add-hostapd-MU-SET-GET-control.patch
@@ -1,11 +1,11 @@
-From 53a7b7af61b75ea0e3f9d12d3d6302cf40941a8a Mon Sep 17 00:00:00 2001
+From adc0d43ecd5ad2f8932c7a25c6b0e1dea336aef8 Mon Sep 17 00:00:00 2001
From: TomLiu <tomml.liu@mediatek.com>
Date: Tue, 9 Aug 2022 10:23:44 -0700
-Subject: [PATCH 06/37] hostapd: mtk: Add hostapd MU SET/GET control
+Subject: [PATCH] hostapd: mtk: Add hostapd MU SET/GET control
---
hostapd/config_file.c | 9 +++
- hostapd/ctrl_iface.c | 62 +++++++++++++++++
+ hostapd/ctrl_iface.c | 66 ++++++++++++++++++
hostapd/hostapd_cli.c | 18 +++++
src/ap/ap_config.c | 1 +
src/ap/ap_config.h | 1 +
@@ -17,7 +17,7 @@
src/drivers/driver_nl80211.c | 110 ++++++++++++++++++++++++++++++
src/drivers/driver_nl80211.h | 1 +
src/drivers/driver_nl80211_capa.c | 3 +
- 13 files changed, 251 insertions(+)
+ 13 files changed, 255 insertions(+)
diff --git a/hostapd/config_file.c b/hostapd/config_file.c
index b5024cc..62e8b33 100644
@@ -40,10 +40,10 @@
} else if (os_strcmp(buf, "max_listen_interval") == 0) {
bss->max_listen_interval = atoi(pos);
diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
-index 9c70d54..c72f336 100644
+index 9c70d54..894c47a 100644
--- a/hostapd/ctrl_iface.c
+++ b/hostapd/ctrl_iface.c
-@@ -3441,6 +3441,63 @@ hostapd_ctrl_iface_get_edcca(struct hostapd_data *hapd, char *cmd, char *buf,
+@@ -3441,6 +3441,67 @@ hostapd_ctrl_iface_get_edcca(struct hostapd_data *hapd, char *cmd, char *buf,
}
@@ -93,6 +93,10 @@
+ pos = buf;
+ end = buf + buflen;
+
++ if (hapd->iface->state != HAPD_IFACE_ENABLED)
++ return os_snprintf(pos, end - pos, "Not allowed to get_mu when current state is %s\n",
++ hostapd_state_text(hapd->iface->state));
++
+ if (hostapd_drv_mu_dump(hapd, &mu_onoff) == 0) {
+ hapd->iconf->mu_onoff = mu_onoff;
+ return os_snprintf(pos, end - pos, "[hostapd_cli] = UL MU-MIMO: %d, DL MU-MIMO: %d, UL OFDMA: %d, DL OFDMA: %d\n",
@@ -107,7 +111,7 @@
static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
char *buf, char *reply,
int reply_size,
-@@ -3993,6 +4050,11 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
+@@ -3993,6 +4054,11 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
} else if (os_strncmp(buf, "GET_EDCCA ", 10) == 0) {
reply_len = hostapd_ctrl_iface_get_edcca(hapd, buf+10, reply,
reply_size);
@@ -156,7 +160,7 @@
{ "dpp_qr_code", hostapd_cli_cmd_dpp_qr_code, NULL,
"report a scanned DPP URI from a QR Code" },
diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
-index 344585a..1b0e990 100644
+index 344585a..9e5a2ec 100644
--- a/src/ap/ap_config.c
+++ b/src/ap/ap_config.c
@@ -280,6 +280,7 @@ struct hostapd_config * hostapd_config_defaults(void)
@@ -446,5 +450,5 @@
}
--
-2.39.0
+2.18.0
diff --git a/recipes-wifi/hostapd/files/patches/mtk-0012-hostapd-mtk-Add-amsdu-set-get-ctrl.patch b/recipes-wifi/hostapd/files/patches/mtk-0012-hostapd-mtk-Add-amsdu-set-get-ctrl.patch
index aa72f2a..03793bb 100644
--- a/recipes-wifi/hostapd/files/patches/mtk-0012-hostapd-mtk-Add-amsdu-set-get-ctrl.patch
+++ b/recipes-wifi/hostapd/files/patches/mtk-0012-hostapd-mtk-Add-amsdu-set-get-ctrl.patch
@@ -1,7 +1,7 @@
-From 9b82b5966b57403f389759b6dfb8318dd862b480 Mon Sep 17 00:00:00 2001
+From 8b9963570219d1ba217da21d02fa193ee8aef4ae Mon Sep 17 00:00:00 2001
From: Evelyn Tsai <evelyn.tsai@mediatek.com>
Date: Fri, 16 Dec 2022 03:57:11 +0800
-Subject: [PATCH 12/35] hostapd: mtk: Add amsdu set get ctrl
+Subject: [PATCH] hostapd: mtk: Add amsdu set get ctrl
---
hostapd/config_file.c | 9 +++
@@ -40,10 +40,10 @@
wpa_printf(MSG_ERROR,
"Line %d: unknown configuration item '%s'",
diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
-index 37a1b2a..61c9e80 100644
+index fcbc4ae..8ed56e4 100644
--- a/hostapd/ctrl_iface.c
+++ b/hostapd/ctrl_iface.c
-@@ -3612,6 +3612,30 @@ hostapd_ctrl_iface_set_offchan_ctrl(struct hostapd_data *hapd, char *cmd,
+@@ -3542,6 +3542,30 @@ hostapd_ctrl_iface_set_dfs_detect_mode(struct hostapd_data *hapd, char *value,
}
@@ -74,10 +74,10 @@
static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
char *buf, char *reply,
int reply_size,
-@@ -4176,6 +4200,8 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
+@@ -4104,6 +4128,8 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
+ } else if (os_strncmp(buf, "DFS_DETECT_MODE ", 16) == 0) {
+ reply_len = hostapd_ctrl_iface_set_dfs_detect_mode(hapd, buf + 16,
reply, reply_size);
- } else if (os_strncmp(buf, "SET_OFFCHAN_CTRL", 16) == 0) {
- reply_len = hostapd_ctrl_iface_set_offchan_ctrl(hapd, buf + 16, reply, reply_size);
+ } else if (os_strncmp(buf, "GET_AMSDU", 9) == 0) {
+ reply_len = hostapd_ctrl_iface_get_amsdu(hapd, reply, reply_size);
} else {
@@ -111,7 +111,7 @@
};
diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
-index df90814..24fc0f5 100644
+index c47418a..b351edb 100644
--- a/src/ap/ap_config.c
+++ b/src/ap/ap_config.c
@@ -299,6 +299,7 @@ struct hostapd_config * hostapd_config_defaults(void)
diff --git a/recipes-wifi/hostapd/files/patches/mtk-0022-hostapd-mtk-Add-available-color-bitmap.patch b/recipes-wifi/hostapd/files/patches/mtk-0022-hostapd-mtk-Add-available-color-bitmap.patch
index 1b23579..6f4425f 100644
--- a/recipes-wifi/hostapd/files/patches/mtk-0022-hostapd-mtk-Add-available-color-bitmap.patch
+++ b/recipes-wifi/hostapd/files/patches/mtk-0022-hostapd-mtk-Add-available-color-bitmap.patch
@@ -1,7 +1,7 @@
-From 9b40b6ccf6fd2f4463b389df46d38610001df04e Mon Sep 17 00:00:00 2001
+From 2e7919e5e52fefa14a48e77fd739ef05371a26c9 Mon Sep 17 00:00:00 2001
From: Yi-Chia Hsieh <yi-chia.hsieh@mediatek.com>
Date: Thu, 26 Jan 2023 09:16:00 +0800
-Subject: [PATCH 22/35] hostapd: mtk: Add available color bitmap
+Subject: [PATCH] hostapd: mtk: Add available color bitmap
Signed-off-by: Yi-Chia Hsieh <yi-chia.hsieh@mediatek.com>
---
@@ -17,10 +17,10 @@
9 files changed, 192 insertions(+), 1 deletion(-)
diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
-index 9ba6992..e1e9270 100644
+index 2b7ac96..549c93a 100644
--- a/hostapd/ctrl_iface.c
+++ b/hostapd/ctrl_iface.c
-@@ -3645,6 +3645,76 @@ hostapd_ctrl_iface_get_amsdu(struct hostapd_data *hapd, char *buf,
+@@ -3575,6 +3575,76 @@ hostapd_ctrl_iface_get_amsdu(struct hostapd_data *hapd, char *buf,
return ret;
}
@@ -97,8 +97,8 @@
static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
char *buf, char *reply,
-@@ -4212,6 +4282,10 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
- reply_len = hostapd_ctrl_iface_set_offchan_ctrl(hapd, buf + 16, reply, reply_size);
+@@ -4140,6 +4210,10 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
+ reply, reply_size);
} else if (os_strncmp(buf, "GET_AMSDU", 9) == 0) {
reply_len = hostapd_ctrl_iface_get_amsdu(hapd, reply, reply_size);
+ } else if (os_strncmp(buf, "GET_BSS_COLOR", 13) == 0) {
diff --git a/recipes-wifi/hostapd/files/patches/mtk-0046-hostapd-mtk-ACS-Fix-2.4GHz-HT40-case-and-channel-swi.patch b/recipes-wifi/hostapd/files/patches/mtk-0046-hostapd-mtk-ACS-Fix-2.4GHz-HT40-case-and-channel-swi.patch
new file mode 100644
index 0000000..d968859
--- /dev/null
+++ b/recipes-wifi/hostapd/files/patches/mtk-0046-hostapd-mtk-ACS-Fix-2.4GHz-HT40-case-and-channel-swi.patch
@@ -0,0 +1,283 @@
+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
+ fail
+
+Issue#1. Add 2.4G HT40- support
+1. Add 2.4G HT40- support
+2. Fix issue: selected best channel is out of channels
+
+Issue#2. Fix chan_switch to usable DFS channel fail due to ACS
+
+Step and issue:
+1. Enable ACS in hostapd config;
+2. Bootup and then use hostapd_cli cmd switch channel to a DFS channel;
+3. Will do ACS again, and no work on channel specified in step 2.
+
+Root cause:
+When need do DFS-CAC, hostapd will do intf disable, then set the new
+channel into running config settings, and finally enable intf;
+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.
+---
+ src/ap/acs.c | 142 ++++++++++++++++++++++++++---------------------
+ src/ap/hostapd.c | 3 +
+ 2 files changed, 83 insertions(+), 62 deletions(-)
+
+diff --git a/src/ap/acs.c b/src/ap/acs.c
+index 130e135..65573b9 100644
+--- a/src/ap/acs.c
++++ b/src/ap/acs.c
+@@ -712,10 +712,19 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface,
+ struct hostapd_channel_data **ideal_chan,
+ long double *ideal_factor)
+ {
+- struct hostapd_channel_data *chan, *adj_chan = NULL, *best;
++ struct hostapd_channel_data *chan, *adj_chan = NULL, *tmp_chan = NULL, *best;
+ long double factor;
+ int i, j;
+ unsigned int k;
++ int ht40_plus = 1, sec_ch_factor = 1;
++
++ if (is_24ghz_mode(mode->mode)) {
++ ht40_plus = (iface->conf->secondary_channel == -1) ? 0 : 1;
++ sec_ch_factor = (iface->conf->secondary_channel == -1) ? -1 : 1;
++ }
++
++ wpa_printf(MSG_INFO, "%s:%d, bw(%u), n_chans(%d), num_channels(%d), sec_ch(%d)",
++ __func__, __LINE__, bw, n_chans, mode->num_channels, iface->conf->secondary_channel);
+
+ for (i = 0; i < mode->num_channels; i++) {
+ double total_weight;
+@@ -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,
++ "ACS: Channel[%d] %d: interference_factor %Lg",
++ i, chan->chan, chan->interference_factor);
+
+ /* Since in the current ACS implementation the first channel is
+ * always a primary channel, skip channels not available as
+@@ -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;
+
+- if (!chan_bw_allowed(chan, bw, 1, 1)) {
++ if (!chan_bw_allowed(chan, bw, ht40_plus, 1)) {
+ wpa_printf(MSG_DEBUG,
+ "ACS: Channel %d: BW %u is not supported",
+ chan->chan, bw);
+@@ -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;
+-
+- 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",
+- chan->chan, adj_chan->chan, bw);
+- break;
+- }
+-
+- if (acs_usable_chan(adj_chan)) {
+- factor += adj_chan->interference_factor;
++ if (!is_24ghz_mode(mode->mode)) {
++ /* 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 */
++ if (acs_usable_chan(chan)) {
++ factor += chan->interference_factor;
+ total_weight += 1;
+- } else {
+- update_best = false;
+ }
+
+- /* find the best channel in this segment */
+- if (update_best &&
+- adj_chan->interference_factor <
+- best->interference_factor)
+- best = adj_chan;
+- }
++ for (j = 1; j < n_chans; j++) {
++ adj_chan = acs_find_chan(iface, chan->freq + j * 20);
++ if (!adj_chan)
++ break;
+
+- if (j != n_chans) {
+- wpa_printf(MSG_DEBUG, "ACS: Channel %d: not enough bandwidth",
+- chan->chan);
+- continue;
+- }
++ 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 */
+- if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211A &&
+- chan != best) {
+- wpa_printf(MSG_DEBUG,
+- "ACS: promoting channel %d over %d (less interference %Lg/%Lg)",
+- best->chan, chan->chan,
+- chan->interference_factor,
+- 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;
++ } else {
++ update_best = false;
++ }
++
++ /* find the best channel in this segment */
++ if (update_best &&
++ adj_chan->interference_factor < best->interference_factor)
++ best = adj_chan;
++ }
++
++ if (j != n_chans) {
++ wpa_printf(MSG_DEBUG, "ACS: Channel %d: not enough bandwidth",
++ chan->chan);
++ continue;
++ }
++
++ if (chan != best) {
++ wpa_printf(MSG_INFO,
++ "ACS: promoting channel %d over %d (less interference %Lg/%Lg)",
++ best->chan, chan->chan,
++ chan->interference_factor,
++ best->interference_factor);
++ chan = best;
++ }
++ } else {
+ 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 * sec_ch_factor * 20));
++ if (tmp_chan && acs_usable_chan(tmp_chan)) {
++ factor += tmp_chan->interference_factor;
++ total_weight += 1;
++ }
++
++ /* 2.4 GHz has overlapping 20 MHz channels. Include adjacent channel
++ interference factor, separately for primary/secondary channel. */
+ adj_chan = acs_find_chan(iface, chan->freq +
+- (j * 20) - 5);
++ (j * sec_ch_factor * 20) - 5);
+ if (adj_chan && acs_usable_chan(adj_chan)) {
+ factor += ACS_ADJ_WEIGHT *
+ adj_chan->interference_factor;
+@@ -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 * sec_ch_factor * 20) - 10);
+ if (adj_chan && acs_usable_chan(adj_chan)) {
+ factor += ACS_NEXT_ADJ_WEIGHT *
+ adj_chan->interference_factor;
+@@ -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 * sec_ch_factor * 20) + 5);
+ if (adj_chan && acs_usable_chan(adj_chan)) {
+ factor += ACS_ADJ_WEIGHT *
+ adj_chan->interference_factor;
+@@ -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 * sec_ch_factor * 20) + 10);
+ if (adj_chan && acs_usable_chan(adj_chan)) {
+ factor += ACS_NEXT_ADJ_WEIGHT *
+ adj_chan->interference_factor;
+@@ -875,7 +900,8 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface,
+ }
+ }
+
+- factor /= total_weight;
++ if (total_weight)
++ factor /= total_weight;
+
+ bias = NULL;
+ if (iface->conf->acs_chan_bias) {
+@@ -894,11 +920,11 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface,
+
+ if (bias) {
+ factor *= bias->bias;
+- wpa_printf(MSG_DEBUG,
++ wpa_printf(MSG_INFO,
+ "ACS: * channel %d: total interference = %Lg (%f bias)",
+ chan->chan, factor, bias->bias);
+ } else {
+- wpa_printf(MSG_DEBUG,
++ wpa_printf(MSG_INFO,
+ "ACS: * channel %d: total interference = %Lg",
+ chan->chan, factor);
+ }
+@@ -939,14 +965,6 @@ acs_find_ideal_chan(struct hostapd_iface *iface)
+ goto bw_selected;
+ }
+
+- /* TODO: HT40- support */
+-
+- if (iface->conf->ieee80211n &&
+- iface->conf->secondary_channel == -1) {
+- wpa_printf(MSG_ERROR, "ACS: HT40- is not supported yet. Please try HT40+");
+- return NULL;
+- }
+-
+ if (iface->conf->ieee80211n &&
+ iface->conf->secondary_channel)
+ n_chans = 2;
+@@ -981,7 +999,7 @@ bw_selected:
+ }
+
+ if (ideal_chan) {
+- wpa_printf(MSG_DEBUG, "ACS: Ideal channel is %d (%d MHz) with total interference factor of %Lg",
++ wpa_printf(MSG_INFO, "ACS: Ideal channel is %d (%d MHz) with total interference factor of %Lg",
+ ideal_chan->chan, ideal_chan->freq, ideal_factor);
+ return ideal_chan;
+ }
+diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
+index f2eb638..250c168 100644
+--- a/src/ap/hostapd.c
++++ b/src/ap/hostapd.c
+@@ -3895,6 +3895,9 @@ hostapd_switch_channel_fallback(struct hostapd_iface *iface,
+
+ iface->freq = freq_params->freq;
+ iface->conf->channel = freq_params->channel;
++ if (iface->conf->channel != 0) /* If channel not zero, will disable acs. */
++ iface->conf->acs = 0;
++
+ iface->conf->secondary_channel = freq_params->sec_channel_offset;
+ hostapd_set_oper_centr_freq_seg0_idx(iface->conf, seg0_idx);
+ hostapd_set_oper_centr_freq_seg1_idx(iface->conf, seg1_idx);
+--
+2.18.0
+
diff --git a/recipes-wifi/hostapd/files/patches/mtk-0047-hostapd-mtk-Check-the-bridge-after-ioctl-SIOCBRADDIF_new.patch b/recipes-wifi/hostapd/files/patches/mtk-0047-hostapd-mtk-Check-the-bridge-after-ioctl-SIOCBRADDIF_new.patch
new file mode 100644
index 0000000..1937640
--- /dev/null
+++ b/recipes-wifi/hostapd/files/patches/mtk-0047-hostapd-mtk-Check-the-bridge-after-ioctl-SIOCBRADDIF_new.patch
@@ -0,0 +1,55 @@
+From 99159b174eb245a7162fe38900971cdff017cf75 Mon Sep 17 00:00:00 2001
+From: Michael Lee <michael-cy.lee@mediatek.com>
+Date: Thu, 13 Jul 2023 13:14:26 +0800
+Subject: [PATCH] hostapd: mtk: Check the bridge after ioctl SIOCBRADDIF failed
+
+If ioctl returns EBUSY on command SIOCBRADDIF, the interface might
+already be bridged by others, and linux_br_add_if should not indicate an
+error in the case.
+
+This patch checks whether the interface is correctly brigded when ioctl
+returns EBUSY.
+
+Signed-off-by: Michael Lee <michael-cy.lee@mediatek.com>
+---
+ src/drivers/linux_ioctl.c | 16 ++++++++++++++--
+ 1 file changed, 14 insertions(+), 2 deletions(-)
+
+diff --git a/src/drivers/linux_ioctl.c b/src/drivers/linux_ioctl.c
+index 7edb9df..b8c1af2 100644
+--- a/src/drivers/linux_ioctl.c
++++ b/src/drivers/linux_ioctl.c
+@@ -150,7 +150,8 @@ int linux_br_del(int sock, const char *brname)
+ int linux_br_add_if(int sock, const char *brname, const char *ifname)
+ {
+ struct ifreq ifr;
+- int ifindex;
++ int ifindex, ret;
++ char in_br[IFNAMSIZ];
+
+ ifindex = if_nametoindex(ifname);
+ if (ifindex == 0)
+@@ -164,8 +165,19 @@ int linux_br_add_if(int sock, const char *brname, const char *ifname)
+
+ wpa_printf(MSG_DEBUG, "Could not add interface %s into bridge "
+ "%s: %s", ifname, brname, strerror(errno));
++
++ /* If ioctl returns -EBUSY when adding interface into bridge,
++ * the interface might already be added by netifd, so here we
++ * check whether the interface is currently on the right
++ * bridge. */
++ if(errno == EBUSY && linux_br_get(in_br, ifname) == 0 &&
++ os_strcmp(in_br, brname) == 0)
++ ret = 0;
++ else
++ ret = -1;
++
+ errno = saved_errno;
+- return -1;
++ return ret;
+ }
+
+ return 0;
+--
+2.25.1
+
diff --git a/recipes-wifi/hostapd/files/patches/mtk-0047-hostapd-mtk-add-support-for-channel-switching-to-dfs.patch b/recipes-wifi/hostapd/files/patches/mtk-0047-hostapd-mtk-add-support-for-channel-switching-to-dfs.patch
new file mode 100644
index 0000000..82b66f4
--- /dev/null
+++ b/recipes-wifi/hostapd/files/patches/mtk-0047-hostapd-mtk-add-support-for-channel-switching-to-dfs.patch
@@ -0,0 +1,135 @@
+From 018d87d5b9b53b3e630032bf2cb7e6eaeae09d71 Mon Sep 17 00:00:00 2001
+From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+Date: Wed, 15 Nov 2023 15:06:00 +0800
+Subject: [PATCH 47/49] hostapd: mtk: add support for channel switching to dfs
+ with csa sent
+
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+---
+ hostapd/ctrl_iface.c | 26 ++------------------------
+ src/ap/beacon.c | 5 +++++
+ src/ap/dfs.c | 16 ++++++++++++----
+ src/ap/ieee802_11.c | 5 +++++
+ 4 files changed, 24 insertions(+), 28 deletions(-)
+
+diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
+index b521a08..0afa6a2 100644
+--- a/hostapd/ctrl_iface.c
++++ b/hostapd/ctrl_iface.c
+@@ -2747,7 +2747,6 @@ static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface,
+ int dfs_range = 0;
+ unsigned int i;
+ int bandwidth;
+- u8 chan;
+
+ ret = hostapd_parse_csa_settings(pos, &settings);
+ if (ret)
+@@ -2809,29 +2808,8 @@ static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface,
+ iface, bandwidth, settings.freq_params.center_freq2);
+
+ if (dfs_range) {
+- ret = ieee80211_freq_to_chan(settings.freq_params.freq, &chan);
+- if (ret == NUM_HOSTAPD_MODES) {
+- wpa_printf(MSG_ERROR,
+- "Failed to get channel for (freq=%d, sec_channel_offset=%d, bw=%d)",
+- settings.freq_params.freq,
+- settings.freq_params.sec_channel_offset,
+- settings.freq_params.bandwidth);
+- return -1;
+- }
+-
+- settings.freq_params.channel = chan;
+-
+- wpa_printf(MSG_DEBUG,
+- "DFS/CAC to (channel=%u, freq=%d, sec_channel_offset=%d, bw=%d, center_freq1=%d)",
+- settings.freq_params.channel,
+- settings.freq_params.freq,
+- settings.freq_params.sec_channel_offset,
+- settings.freq_params.bandwidth,
+- settings.freq_params.center_freq1);
+-
+- /* Perform CAC and switch channel */
+- hostapd_switch_channel_fallback(iface, &settings.freq_params);
+- return 0;
++ settings.cs_count = 5;
++ settings.block_tx = 1;
+ }
+
+ for (i = 0; i < iface->num_bss; i++) {
+diff --git a/src/ap/beacon.c b/src/ap/beacon.c
+index 02f4f87..f9c4924 100644
+--- a/src/ap/beacon.c
++++ b/src/ap/beacon.c
+@@ -2027,6 +2027,11 @@ static int __ieee802_11_set_beacon(struct hostapd_data *hapd)
+ return -1;
+ }
+
++ if (iface->cac_started) {
++ wpa_printf(MSG_DEBUG, "Ignore set beacons during CAC period");
++ return 0;
++ }
++
+ hapd->beacon_set_done = 1;
+
+ if (ieee802_11_build_ap_params(hapd, ¶ms) < 0)
+diff --git a/src/ap/dfs.c b/src/ap/dfs.c
+index 80d3605..012050c 100644
+--- a/src/ap/dfs.c
++++ b/src/ap/dfs.c
+@@ -1255,10 +1255,10 @@ int hostapd_dfs_complete_cac(struct hostapd_iface *iface, int success, int freq,
+ * another radio.
+ */
+ if (iface->state != HAPD_IFACE_ENABLED &&
+- hostapd_is_dfs_chan_available(iface)) {
++ hostapd_is_dfs_chan_available(iface))
+ hostapd_setup_interface_complete(iface, 0);
+- iface->cac_started = 0;
+- }
++
++ iface->cac_started = 0;
+
+ /*
+ * When background radar is enabled but the CAC completion
+@@ -1272,6 +1272,13 @@ int hostapd_dfs_complete_cac(struct hostapd_iface *iface, int success, int freq,
+ } else if (hostapd_dfs_is_background_event(iface, freq)) {
+ iface->radar_background.cac_started = 0;
+ hostpad_dfs_update_background_chain(iface);
++ } else {
++ int i;
++
++ iface->cac_started = 0;
++ /* Clear all CSA flags once channel switch to DFS channel fails */
++ for (i = 0; i < iface->num_bss; i++)
++ iface->bss[i]->csa_in_progress = 0;
+ }
+
+ return 0;
+@@ -1646,7 +1653,8 @@ int hostapd_dfs_start_cac(struct hostapd_iface *iface, int freq,
+ } else {
+ /* This is called when the driver indicates that an offloaded
+ * DFS has started CAC. */
+- hostapd_set_state(iface, HAPD_IFACE_DFS);
++ if (iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD)
++ hostapd_set_state(iface, HAPD_IFACE_DFS);
+ iface->cac_started = 1;
+ }
+ /* TODO: How to check CAC time for ETSI weather channels? */
+diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
+index 01ceb79..dd477fd 100644
+--- a/src/ap/ieee802_11.c
++++ b/src/ap/ieee802_11.c
+@@ -6352,6 +6352,11 @@ int ieee802_11_mgmt(struct hostapd_data *hapd, const u8 *buf, size_t len,
+ return 1;
+ }
+
++ if (hapd->iface->cac_started) {
++ wpa_printf(MSG_DEBUG, "MGMT: Ignore management frame during CAC");
++ return 1;
++ }
++
+ if (stype == WLAN_FC_STYPE_PROBE_REQ) {
+ handle_probe_req(hapd, mgmt, len, ssi_signal);
+ return 1;
+--
+2.18.0
+
diff --git a/recipes-wifi/hostapd/files/patches/mtk-0048-hostapd-mtk-add-support-for-channel-switching-with-c.patch b/recipes-wifi/hostapd/files/patches/mtk-0048-hostapd-mtk-add-support-for-channel-switching-with-c.patch
new file mode 100644
index 0000000..0dbdaca
--- /dev/null
+++ b/recipes-wifi/hostapd/files/patches/mtk-0048-hostapd-mtk-add-support-for-channel-switching-with-c.patch
@@ -0,0 +1,409 @@
+From a0538a9373ec7def76048e020fcb6ecfec53f3db Mon Sep 17 00:00:00 2001
+From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+Date: Thu, 16 Nov 2023 13:18:48 +0800
+Subject: [PATCH] hostapd: mtk: add support for channel switching with csa sent
+ when background radar is enabled
+
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+---
+ hostapd/ctrl_iface.c | 82 +++++++++++++++++-----
+ src/ap/ctrl_iface_ap.c | 5 +-
+ src/ap/dfs.c | 156 +++++++++++++++++++++++++++++++++++------
+ src/ap/dfs.h | 9 ++-
+ 4 files changed, 212 insertions(+), 40 deletions(-)
+
+diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
+index 0afa6a2..44903e0 100644
+--- a/hostapd/ctrl_iface.c
++++ b/hostapd/ctrl_iface.c
+@@ -2742,11 +2742,12 @@ static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface,
+ char *pos)
+ {
+ #ifdef NEED_AP_MLME
+- struct csa_settings settings;
++ struct csa_settings settings, background_settings;
+ int ret;
+- int dfs_range = 0;
++ int freq, state;
+ unsigned int i;
+- int bandwidth;
++ int bandwidth, oper_chwidth;
++ bool background_radar, bw_changed, cac_required = false;
+
+ ret = hostapd_parse_csa_settings(pos, &settings);
+ if (ret)
+@@ -2762,21 +2763,28 @@ static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface,
+ switch (settings.freq_params.bandwidth) {
+ case 40:
+ bandwidth = CHAN_WIDTH_40;
++ oper_chwidth = CONF_OPER_CHWIDTH_USE_HT;
+ break;
+ case 80:
+- if (settings.freq_params.center_freq2)
++ if (settings.freq_params.center_freq2) {
+ bandwidth = CHAN_WIDTH_80P80;
+- else
++ oper_chwidth = CONF_OPER_CHWIDTH_80P80MHZ;
++ } else {
+ bandwidth = CHAN_WIDTH_80;
++ oper_chwidth = CONF_OPER_CHWIDTH_80MHZ;
++ }
+ break;
+ case 160:
+ bandwidth = CHAN_WIDTH_160;
++ oper_chwidth = CONF_OPER_CHWIDTH_160MHZ;
+ break;
+ case 320:
+ bandwidth = CHAN_WIDTH_320;
++ oper_chwidth = CONF_OPER_CHWIDTH_320MHZ;
+ break;
+ default:
+ bandwidth = CHAN_WIDTH_20;
++ oper_chwidth = CONF_OPER_CHWIDTH_USE_HT;
+ break;
+ }
+
+@@ -2797,19 +2805,29 @@ static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface,
+ }
+
+ if (settings.freq_params.center_freq1)
+- dfs_range += hostapd_is_dfs_overlap(
+- iface, bandwidth, settings.freq_params.center_freq1);
++ freq = settings.freq_params.center_freq1;
+ else
+- dfs_range += hostapd_is_dfs_overlap(
+- iface, bandwidth, settings.freq_params.freq);
+-
+- if (settings.freq_params.center_freq2)
+- dfs_range += hostapd_is_dfs_overlap(
+- iface, bandwidth, settings.freq_params.center_freq2);
+-
+- if (dfs_range) {
+- settings.cs_count = 5;
+- settings.block_tx = 1;
++ freq = settings.freq_params.freq;
++
++ bw_changed = oper_chwidth != hostapd_get_oper_chwidth(iface->conf);
++ state = hostapd_dfs_get_target_state(iface, bandwidth, freq,
++ settings.freq_params.center_freq2);
++ switch (state) {
++ case HOSTAPD_CHAN_DFS_USABLE:
++ cac_required = true;
++ /* fallthrough */
++ case HOSTAPD_CHAN_DFS_AVAILABLE:
++ background_radar = hostapd_dfs_handle_csa(iface, &settings,
++ &background_settings,
++ cac_required,
++ bw_changed);
++ break;
++ case HOSTAPD_CHAN_DFS_UNAVAILABLE:
++ wpa_printf(MSG_INFO,
++ "chanswitch: target channel is UNAVAILABLE, so stop switching");
++ return -1;
++ default:
++ break;
+ }
+
+ for (i = 0; i < iface->num_bss; i++) {
+@@ -2826,6 +2844,36 @@ static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface,
+ }
+ }
+
++ if (background_radar) {
++ u8 seg0, seg1;
++
++ ieee80211_freq_to_chan(background_settings.freq_params.center_freq1, &seg0);
++ ieee80211_freq_to_chan(background_settings.freq_params.center_freq2, &seg1);
++ ret = hostapd_start_dfs_cac(iface, iface->conf->hw_mode,
++ background_settings.freq_params.freq,
++ background_settings.freq_params.channel,
++ background_settings.freq_params.ht_enabled,
++ background_settings.freq_params.vht_enabled,
++ background_settings.freq_params.he_enabled,
++ background_settings.freq_params.eht_enabled,
++ background_settings.freq_params.sec_channel_offset,
++ oper_chwidth, seg0, seg1, true);
++ if (ret) {
++ wpa_printf(MSG_ERROR, "Background radar start dfs cac failed, %d",
++ ret);
++ iface->radar_background.channel = -1;
++ return -1;
++ }
++
++ /* Cache background radar parameters. */
++ iface->radar_background.channel = background_settings.freq_params.channel;
++ iface->radar_background.secondary_channel =
++ background_settings.freq_params.sec_channel_offset;
++ iface->radar_background.freq = background_settings.freq_params.freq;
++ iface->radar_background.centr_freq_seg0_idx = seg0;
++ iface->radar_background.centr_freq_seg1_idx = seg1;
++ }
++
+ return 0;
+ #else /* NEED_AP_MLME */
+ return -1;
+diff --git a/src/ap/ctrl_iface_ap.c b/src/ap/ctrl_iface_ap.c
+index 86e8729..005c9fa 100644
+--- a/src/ap/ctrl_iface_ap.c
++++ b/src/ap/ctrl_iface_ap.c
+@@ -907,6 +907,7 @@ int hostapd_parse_csa_settings(const char *pos,
+ struct csa_settings *settings)
+ {
+ char *end;
++ int ret;
+
+ os_memset(settings, 0, sizeof(*settings));
+ settings->cs_count = strtol(pos, &end, 10);
+@@ -916,7 +917,9 @@ int hostapd_parse_csa_settings(const char *pos,
+ }
+
+ settings->freq_params.freq = atoi(end);
+- if (settings->freq_params.freq == 0) {
++ ret = ieee80211_freq_to_chan(settings->freq_params.freq,
++ &settings->freq_params.channel);
++ if (ret == NUM_HOSTAPD_MODES) {
+ wpa_printf(MSG_ERROR, "chanswitch: invalid freq provided");
+ return -1;
+ }
+diff --git a/src/ap/dfs.c b/src/ap/dfs.c
+index 012050c..5108e0a 100644
+--- a/src/ap/dfs.c
++++ b/src/ap/dfs.c
+@@ -248,14 +248,15 @@ 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, enum dfs_channel_type type)
++ int n_chans, int idx, enum dfs_channel_type type)
+ {
+ struct hostapd_hw_modes *mode;
+ struct hostapd_channel_data *chan;
+- int i, channel_idx = 0, n_chans, n_chans1;
++ int i, channel_idx = 0, n_chans1;
+
+ mode = iface->current_mode;
+- n_chans = dfs_get_used_n_chans(iface, &n_chans1);
++ if (!n_chans)
++ n_chans = dfs_get_used_n_chans(iface, &n_chans1);
+
+ wpa_printf(MSG_DEBUG, "DFS new chan checking %d channels", n_chans);
+ for (i = 0; i < mode->num_channels; i++) {
+@@ -548,7 +549,7 @@ dfs_get_valid_channel(struct hostapd_iface *iface,
+ return NULL;
+
+ /* Get the count first */
+- num_available_chandefs = dfs_find_channel(iface, NULL, 0, type);
++ num_available_chandefs = dfs_find_channel(iface, NULL, 0, 0, type);
+ wpa_printf(MSG_DEBUG, "DFS: num_available_chandefs=%d",
+ num_available_chandefs);
+ if (num_available_chandefs == 0)
+@@ -569,7 +570,7 @@ dfs_get_valid_channel(struct hostapd_iface *iface,
+ return NULL;
+
+ chan_idx = _rand % num_available_chandefs;
+- dfs_find_channel(iface, &chan, chan_idx, type);
++ dfs_find_channel(iface, &chan, 0, chan_idx, type);
+ if (!chan) {
+ wpa_printf(MSG_DEBUG, "DFS: no random channel found");
+ return NULL;
+@@ -599,7 +600,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, type);
++ dfs_find_channel(iface, &chan2, 0, chan_idx2, type);
+ if (chan2 && abs(chan2->chan - chan->chan) > 12) {
+ /* two channels are not adjacent */
+ sec_chan_idx_80p80 = chan2->chan;
+@@ -1302,6 +1303,9 @@ int hostapd_dfs_pre_cac_expired(struct hostapd_iface *iface, int freq,
+ set_dfs_state(iface, freq, ht_enabled, chan_offset, chan_width,
+ cf1, cf2, HOSTAPD_CHAN_DFS_USABLE);
+
++ if (dfs_use_radar_background(iface) && iface->radar_background.channel == -1)
++ hostpad_dfs_update_background_chain(iface);
++
+ return 0;
+ }
+
+@@ -1715,14 +1719,15 @@ int hostapd_handle_dfs_offload(struct hostapd_iface *iface)
+ }
+
+
+-int hostapd_is_dfs_overlap(struct hostapd_iface *iface, enum chan_width width,
+- int center_freq)
++int hostapd_dfs_get_target_state(struct hostapd_iface *iface, enum chan_width width,
++ int center_freq, int center_freq2)
+ {
+ struct hostapd_channel_data *chan;
+ struct hostapd_hw_modes *mode = iface->current_mode;
+- int half_width;
+- int res = 0;
++ int half_width, chan_state, state = 0;
++ int upper, lower;
+ int i;
++ bool in_range;
+
+ if (!iface->conf->ieee80211h || !mode ||
+ mode->mode != HOSTAPD_MODE_IEEE80211A)
+@@ -1755,18 +1760,129 @@ int hostapd_is_dfs_overlap(struct hostapd_iface *iface, enum chan_width width,
+ if (!(chan->flag & HOSTAPD_CHAN_RADAR))
+ continue;
+
+- if ((chan->flag & HOSTAPD_CHAN_DFS_MASK) ==
+- HOSTAPD_CHAN_DFS_AVAILABLE)
+- continue;
++ upper = chan->freq + half_width;
++ lower = chan->freq - half_width;
++ in_range = (lower < center_freq && center_freq < upper) ||
++ (center_freq2 && (lower < center_freq2 && center_freq2 < upper));
++ if (in_range) {
++ chan_state = chan->flag & HOSTAPD_CHAN_DFS_MASK;
++ switch (chan_state) {
++ case HOSTAPD_CHAN_DFS_USABLE:
++ state = HOSTAPD_CHAN_DFS_USABLE;
++ break;
++ case HOSTAPD_CHAN_DFS_AVAILABLE:
++ if (state != HOSTAPD_CHAN_DFS_USABLE)
++ state = HOSTAPD_CHAN_DFS_AVAILABLE;
++ break;
++ case HOSTAPD_CHAN_DFS_UNKNOWN:
++ wpa_printf(MSG_WARNING, "chan %d DFS state: UNKNOWN",
++ chan->freq);
++ /* fallthrough */
++ case HOSTAPD_CHAN_DFS_UNAVAILABLE:
++ default:
++ return HOSTAPD_CHAN_DFS_UNAVAILABLE;
++ }
++ }
++ }
+
+- if (center_freq - chan->freq < half_width &&
+- chan->freq - center_freq < half_width)
+- res++;
++ wpa_printf(MSG_DEBUG, "freq range (%d, %d) has DFS state %d",
++ center_freq - half_width, center_freq + half_width, state);
++
++ return state;
++}
++
++
++static struct hostapd_channel_data *
++dfs_get_csa_channel(struct hostapd_iface *iface,
++ int n_chans, int cur_center,
++ enum dfs_channel_type type)
++{
++ struct hostapd_channel_data *chan;
++ int avail_chan_num;
++ u32 _rand, idx;
++
++ if (os_get_random((u8 *)&_rand, sizeof(_rand)) < 0)
++ return NULL;
++
++ avail_chan_num = dfs_find_channel(iface, NULL, n_chans, 0, type);
++ if (!avail_chan_num)
++ return NULL;
++
++ idx = _rand % avail_chan_num;
++ dfs_find_channel(iface, &chan, n_chans, idx, type);
++ if (cur_center == chan->freq + (n_chans - 1) * 10) {
++ if (avail_chan_num == 1)
++ return NULL;
++
++ /* Get the next channel if the found channel is same as current channel */
++ idx = (idx + 1) % avail_chan_num;
++ dfs_find_channel(iface, &chan, n_chans, idx, type);
+ }
+
+- wpa_printf(MSG_DEBUG, "DFS CAC required: (%d, %d): in range: %s",
+- center_freq - half_width, center_freq + half_width,
+- res ? "yes" : "no");
++ return chan;
++}
+
+- return res;
++
++/*
++ * DFS handler for CSA
++ * 1 - update background radar with the filled setting
++ * 0 - background radar is not enabled / background radar remain at the same channel /
++ * disable background radar
++ */
++int hostapd_dfs_handle_csa(struct hostapd_iface *iface,
++ struct csa_settings *settings,
++ struct csa_settings *background_settings,
++ bool cac_required, bool bw_changed)
++{
++ struct hostapd_channel_data *chan;
++ struct hostapd_freq_params *freq_params = &settings->freq_params;
++ int center = settings->freq_params.center_freq1;
++ int background_center = 5000 + iface->radar_background.centr_freq_seg0_idx * 5;
++ int n_chans = settings->freq_params.bandwidth / 20;
++ bool update_background = false;
++
++ if (!dfs_use_radar_background(iface)) {
++ settings->cs_count = 5;
++ settings->block_tx = cac_required;
++ return 0;
++ }
++
++ if (!cac_required) {
++ if (!bw_changed && center != background_center)
++ return 0;
++ /* Update background radar due to bw change or channel overlapping */
++ update_background = true;
++ } else {
++ /*
++ * Get available channel for main channel.
++ * If no available channel for main channel, then perform
++ * the CAC of target channel on the main channel, and select
++ * an usable channel for background radar.
++ */
++ iface->radar_background.temp_ch = 1;
++ chan = dfs_get_csa_channel(iface, n_chans, 0, DFS_AVAILABLE);
++ if (!chan)
++ update_background = true;
++ }
++
++ if (update_background) {
++ chan = dfs_get_csa_channel(iface, n_chans, center, DFS_NO_CAC_YET);
++ if (!chan)
++ goto bkg_disable;
++ freq_params = &background_settings->freq_params;
++ iface->radar_background.temp_ch = 0;
++ }
++
++ memcpy(background_settings, settings, sizeof(*settings));
++ freq_params->freq = chan->freq;
++ freq_params->channel = chan->chan;
++ freq_params->sec_channel_offset = 1;
++ freq_params->center_freq1 = chan->freq + (n_chans - 1) * 10;
++ freq_params->center_freq2 = 0;
++
++ return 1;
++
++bkg_disable:
++ iface->radar_background.channel = -1;
++ return 0;
+ }
+diff --git a/src/ap/dfs.h b/src/ap/dfs.h
+index 1a0791f..0a7c25d 100644
+--- a/src/ap/dfs.h
++++ b/src/ap/dfs.h
+@@ -33,7 +33,12 @@ int hostapd_dfs_start_cac(struct hostapd_iface *iface, int freq,
+ int ht_enabled, int chan_offset, int chan_width,
+ int cf1, int cf2);
+ int hostapd_handle_dfs_offload(struct hostapd_iface *iface);
+-int hostapd_is_dfs_overlap(struct hostapd_iface *iface, enum chan_width width,
+- int center_freq);
++int hostapd_dfs_get_target_state(struct hostapd_iface *iface, enum chan_width width,
++ int center_freq, int center_freq2);
++int hostapd_dfs_handle_csa(struct hostapd_iface *iface,
++ struct csa_settings *settings,
++ struct csa_settings *background_settings,
++ bool cac_required, bool bw_changed);
++
+
+ #endif /* DFS_H */
+--
+2.18.0
+
diff --git a/recipes-wifi/hostapd/files/patches/mtk-0011-hostapd-mtk-Add-DFS-offchan-channel-switch.patch b/recipes-wifi/hostapd/files/patches/mtk-0049-hostapd-mtk-Add-DFS-offchan-channel-switch.patch
similarity index 80%
rename from recipes-wifi/hostapd/files/patches/mtk-0011-hostapd-mtk-Add-DFS-offchan-channel-switch.patch
rename to recipes-wifi/hostapd/files/patches/mtk-0049-hostapd-mtk-Add-DFS-offchan-channel-switch.patch
index 69f3fa2..bfd66a3 100644
--- a/recipes-wifi/hostapd/files/patches/mtk-0011-hostapd-mtk-Add-DFS-offchan-channel-switch.patch
+++ b/recipes-wifi/hostapd/files/patches/mtk-0049-hostapd-mtk-Add-DFS-offchan-channel-switch.patch
@@ -1,7 +1,7 @@
-From b087dbc78f6911b16c9c00ac0a9246a89871225f Mon Sep 17 00:00:00 2001
+From 49f5a5c4430e59dec7dc135773636da2e889ce05 Mon Sep 17 00:00:00 2001
From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
Date: Mon, 20 Feb 2023 14:56:55 +0800
-Subject: [PATCH 11/35] hostapd: mtk: Add DFS offchan channel switch
+Subject: [PATCH 49/49] hostapd: mtk: Add DFS offchan channel switch
Add DFS background chain channel switch command for testing purpose.
This feature is implemented via hostapd_cli command.
@@ -12,17 +12,17 @@
---
hostapd/ctrl_iface.c | 72 ++++++++++++++++++++++++++++++++++++++++++++
src/ap/dfs.c | 25 ++++++---------
- src/ap/dfs.h | 15 +++++++++
- 3 files changed, 96 insertions(+), 16 deletions(-)
+ src/ap/dfs.h | 16 +++++++++-
+ 3 files changed, 96 insertions(+), 17 deletions(-)
diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
-index fcbc4ae..37a1b2a 100644
+index 328f7c2..97d807a 100644
--- a/hostapd/ctrl_iface.c
+++ b/hostapd/ctrl_iface.c
-@@ -3542,6 +3542,76 @@ hostapd_ctrl_iface_set_dfs_detect_mode(struct hostapd_data *hapd, char *value,
+@@ -3951,6 +3951,76 @@ hostapd_ctrl_iface_dump_amnt(struct hostapd_data *hapd, char *cmd,
+ return pos - buf;
}
-
+static int
+hostapd_ctrl_iface_set_offchan_ctrl(struct hostapd_data *hapd, char *cmd,
+ char *buf, size_t buflen)
@@ -48,9 +48,9 @@
+ else
+ return -1;
+
-+ num_available_chandefs = dfs_find_channel(iface, NULL, 0, type);
++ num_available_chandefs = dfs_find_channel(iface, NULL, 0, 0, type);
+ for (i = 0; i < num_available_chandefs; i++) {
-+ dfs_find_channel(iface, &chan, i, type);
++ dfs_find_channel(iface, &chan, 0, i, type);
+ if (chan->chan == channel) {
+ chan_found = true;
+ break;
@@ -96,17 +96,17 @@
static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
char *buf, char *reply,
int reply_size,
-@@ -4104,6 +4174,8 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
- } else if (os_strncmp(buf, "DFS_DETECT_MODE ", 16) == 0) {
- reply_len = hostapd_ctrl_iface_set_dfs_detect_mode(hapd, buf + 16,
- reply, reply_size);
+@@ -4529,6 +4599,8 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
+ } else if (os_strncmp(buf, "DUMP_AMNT", 9) == 0) {
+ reply_len = hostapd_ctrl_iface_dump_amnt(hapd, buf+10,
+ reply, reply_size);
+ } else if (os_strncmp(buf, "SET_OFFCHAN_CTRL", 16) == 0) {
+ reply_len = hostapd_ctrl_iface_set_offchan_ctrl(hapd, buf + 16, reply, reply_size);
} else {
os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
reply_len = 16;
diff --git a/src/ap/dfs.c b/src/ap/dfs.c
-index 5cb7799..1c3f678 100644
+index a558d4e..bb5702b 100644
--- a/src/ap/dfs.c
+++ b/src/ap/dfs.c
@@ -19,13 +19,6 @@
@@ -123,20 +123,20 @@
static struct hostapd_channel_data *
dfs_downgrade_bandwidth(struct hostapd_iface *iface, int *secondary_channel,
u8 *oper_centr_freq_seg0_idx,
-@@ -238,9 +231,9 @@ static int is_in_chanlist(struct hostapd_iface *iface,
+@@ -246,9 +239,9 @@ static int is_in_chanlist(struct hostapd_iface *iface,
* - hapd->vht/he_oper_centr_freq_seg0_idx
* - hapd->vht/he_oper_centr_freq_seg1_idx
*/
-static int dfs_find_channel(struct hostapd_iface *iface,
- struct hostapd_channel_data **ret_chan,
-- int idx, enum dfs_channel_type type)
+- int n_chans, int idx, enum dfs_channel_type type)
+int dfs_find_channel(struct hostapd_iface *iface,
+ struct hostapd_channel_data **ret_chan,
-+ int idx, enum dfs_channel_type type)
++ int n_chans, int idx, enum dfs_channel_type type)
{
struct hostapd_hw_modes *mode;
struct hostapd_channel_data *chan;
-@@ -299,12 +292,12 @@ static int dfs_find_channel(struct hostapd_iface *iface,
+@@ -308,12 +301,12 @@ static int dfs_find_channel(struct hostapd_iface *iface,
}
@@ -156,7 +156,7 @@
if (!iface->conf->ieee80211ac && !iface->conf->ieee80211ax)
return;
diff --git a/src/ap/dfs.h b/src/ap/dfs.h
-index 606c1b3..c2556d2 100644
+index 0a7c25d..e88ea24 100644
--- a/src/ap/dfs.h
+++ b/src/ap/dfs.h
@@ -9,6 +9,12 @@
@@ -172,13 +172,14 @@
int hostapd_handle_dfs(struct hostapd_iface *iface);
int hostapd_dfs_complete_cac(struct hostapd_iface *iface, int success, int freq,
-@@ -32,5 +38,14 @@ int hostapd_dfs_start_cac(struct hostapd_iface *iface, int freq,
- int hostapd_handle_dfs_offload(struct hostapd_iface *iface);
- int hostapd_is_dfs_overlap(struct hostapd_iface *iface, enum chan_width width,
- int center_freq);
+@@ -39,6 +45,14 @@ int hostapd_dfs_handle_csa(struct hostapd_iface *iface,
+ struct csa_settings *settings,
+ struct csa_settings *background_settings,
+ bool cac_required, bool bw_changed);
+-
+int dfs_find_channel(struct hostapd_iface *iface,
+ struct hostapd_channel_data **ret_chan,
-+ int idx, enum dfs_channel_type type);
++ int n_chans, int idx, enum dfs_channel_type type);
+void dfs_adjust_center_freq(struct hostapd_iface *iface,
+ struct hostapd_channel_data *chan,
+ int secondary_channel,
diff --git a/recipes-wifi/hostapd/files/patches/patches.inc b/recipes-wifi/hostapd/files/patches/patches.inc
index 9121a2f..0a397fe 100644
--- a/recipes-wifi/hostapd/files/patches/patches.inc
+++ b/recipes-wifi/hostapd/files/patches/patches.inc
@@ -62,6 +62,10 @@
file://800-acs-don-t-select-indoor-channel-on-outdoor-operation.patch \
file://990-ctrl-make-WNM_AP-functions-dependant-on-CONFIG_AP.patch \
file://992-openssl-include-rsa.patch \
+ file://bp-0001-ACS-Extract-bw40-80-160-freqs-out-of-acs_usable_bwXX.patch \
+ file://bp-0002-ACS-Introduce-acs_get_bw_center_chan.patch \
+ file://bp-0003-ACS-introduce-acs_adjust_secondary.patch \
+ file://bp-0004-ACS-Allow-selecting-a-better-channel-when-using-40-8.patch \
file://mtk-0001-hostapd-mtk-Add-neighbor-report-and-BSS-Termination-.patch \
file://mtk-0002-hostapd-mtk-print-sae-groups-by-hostapd-ctrl.patch \
file://mtk-0003-hostapd-mtk-add-support-for-runtime-set-in-band-disc.patch \
@@ -72,7 +76,6 @@
file://mtk-0008-hostapd-mtk-Add-hostapd-iBF-control.patch \
file://mtk-0009-hostapd-mtk-Do-not-include-HE-capab-IE-if-associated.patch \
file://mtk-0010-hostapd-mtk-Add-DFS-detection-mode.patch \
- file://mtk-0011-hostapd-mtk-Add-DFS-offchan-channel-switch.patch \
file://mtk-0012-hostapd-mtk-Add-amsdu-set-get-ctrl.patch \
file://mtk-0013-hostapd-mtk-Add-he_ldpc-configuration.patch \
file://mtk-0014-hostapd-mtk-Add-the-broadcast-destination-address-of.patch \
@@ -107,4 +110,9 @@
file://mtk-0042-hostapd-mtk-avoid-unnecessary-beacon-update-for-6-GH.patch \
file://mtk-0044-hostapd-mtk-Add-ACS-chanlist-info-in-get_config.patch \
file://mtk-0045-hostapd-mtk-add-log-in-extender-mode.patch \
+ file://mtk-0046-hostapd-mtk-ACS-Fix-2.4GHz-HT40-case-and-channel-swi.patch \
+ file://mtk-0047-hostapd-mtk-Check-the-bridge-after-ioctl-SIOCBRADDIF_new.patch \
+ file://mtk-0047-hostapd-mtk-add-support-for-channel-switching-to-dfs.patch \
+ file://mtk-0048-hostapd-mtk-add-support-for-channel-switching-with-c.patch \
+ file://mtk-0049-hostapd-mtk-Add-DFS-offchan-channel-switch.patch \
"