[][MAC80211][hostapd][rebase patch based on 2023-03-29]
[Description]
Refactor patches based on 2023-03-29
[Release-log]
N/A
Change-Id: Ib9fb4ae566e213da8cb14dda1574ff711fdd3749
Reviewed-on: https://gerrit.mediatek.inc/c/openwrt/feeds/mtk_openwrt_feeds/+/7477769
diff --git a/autobuild_mac80211_release/lede-build-sanity.sh b/autobuild_mac80211_release/lede-build-sanity.sh
index 8ed34b0..5f7954d 100755
--- a/autobuild_mac80211_release/lede-build-sanity.sh
+++ b/autobuild_mac80211_release/lede-build-sanity.sh
@@ -167,9 +167,16 @@
prepare_mac80211() {
rm -rf ${BUILD_DIR}/package/network/services/hostapd
- #cp -fpR ${BUILD_DIR}/./../mac80211_package/package/network/services/hostapd ${BUILD_DIR}/package/network/services
- tar xvf ${MTK_FEED_DIR}/autobuild_mac80211_release/package/network/services/hostapd/hostapd_v2.10_07730ff3.tar.gz -C ${BUILD_DIR}/package/network/services/
- rm -rf ${MTK_FEED_DIR}/autobuild_mac80211_release/package/network/services/hostapd/hostapd_v2.10_07730ff3.tar.gz
+ if [ $2 = "1" ]; then
+ echo "========================Hostapd_v2.10_20230329===================="
+ cp -fpR ${BUILD_DIR}/./../mac80211_package/package/network/services/hostapd ${BUILD_DIR}/package/network/services
+ rm -rf ${MTK_FEED_DIR}/autobuild_mac80211_release/package/network/services/hostapd
+ mv ${MTK_FEED_DIR}/autobuild_mac80211_release/package/network/services/hostapd_new ${MTK_FEED_DIR}/autobuild_mac80211_release/package/network/services/hostapd
+ else
+ echo "========================Hostapd_v2.10_20220729==================="
+ tar xvf ${MTK_FEED_DIR}/autobuild_mac80211_release/package/network/services/hostapd/hostapd_v2.10_07730ff3.tar.gz -C ${BUILD_DIR}/package/network/services/
+ rm -rf ${MTK_FEED_DIR}/autobuild_mac80211_release/package/network/services/hostapd/hostapd_v2.10_07730ff3.tar.gz
+ fi
rm -rf ${BUILD_DIR}/package/libs/libnl-tiny
cp -fpR ${BUILD_DIR}/./../mac80211_package/package/libs/libnl-tiny ${BUILD_DIR}/package/libs
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/lede-branch-build-sanity.sh b/autobuild_mac80211_release/mt7988_mt7996_mac80211/lede-branch-build-sanity.sh
index 80dfa41..d0f10fa 100755
--- a/autobuild_mac80211_release/mt7988_mt7996_mac80211/lede-branch-build-sanity.sh
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/lede-branch-build-sanity.sh
@@ -6,6 +6,7 @@
branch_name=${temp##*/}
hwpath=0
backport_new=1
+hostapd_new=1
args=
for arg in $*; do
@@ -45,7 +46,7 @@
prepare_flowoffload
#prepare mac80211 mt76 wifi stuff
-prepare_mac80211 ${backport_new}
+prepare_mac80211 ${backport_new} ${hostapd_new}
# find ${BUILD_DIR}/package/kernel/mt76/patches -name "*-mt76-*.patch" -delete
rm -rf ${BUILD_DIR}/package/kernel/mt76/patches/*
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/network/services/hostapd/patches/mtk-0100-hostapd-mtk-update-eht-operation-elem.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/network/services/hostapd/patches/mtk-0100-hostapd-mtk-update-eht-operation-elem.patch
deleted file mode 100644
index bbb52ed..0000000
--- a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/network/services/hostapd/patches/mtk-0100-hostapd-mtk-update-eht-operation-elem.patch
+++ /dev/null
@@ -1,51 +0,0 @@
-From 6251cf18a39e56eb5b240f967d36a397573e5b3e Mon Sep 17 00:00:00 2001
-From: Peter Chiu <chui-hao.chiu@mediatek.com>
-Date: Fri, 30 Sep 2022 00:16:21 +0800
-Subject: [PATCH] hostapd: mtk: update eht operation elem
-
----
- src/ap/ieee802_11_eht.c | 5 +++--
- src/common/ieee802_11_defs.h | 1 +
- 2 files changed, 4 insertions(+), 2 deletions(-)
-
-diff --git a/src/ap/ieee802_11_eht.c b/src/ap/ieee802_11_eht.c
-index ec36a9e..fc472b8 100644
---- a/src/ap/ieee802_11_eht.c
-+++ b/src/ap/ieee802_11_eht.c
-@@ -183,7 +183,7 @@ u8 * hostapd_eid_eht_operation(struct hostapd_data *hapd, u8 *eid)
- return eid;
-
- *pos++ = WLAN_EID_EXTENSION;
-- *pos++ = 5;
-+ *pos++ = 9;
- *pos++ = WLAN_EID_EXT_EHT_OPERATION;
-
- oper = (struct ieee80211_eht_operation *) pos;
-@@ -224,10 +224,11 @@ u8 * hostapd_eid_eht_operation(struct hostapd_data *hapd, u8 *eid)
- return eid;
- }
-
-+ oper->mcs_nss_set = 0x11111111;
- oper->oper_info.ccfs0 = seg0 ? seg0 : hapd->iconf->channel;
- oper->oper_info.ccfs1 = seg1;
-
-- return pos + 4;
-+ return pos + 8;
- }
-
-
-diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h
-index 0bbbca9..f7ec11b 100644
---- a/src/common/ieee802_11_defs.h
-+++ b/src/common/ieee802_11_defs.h
-@@ -2440,6 +2440,7 @@ struct ieee80211_eht_oper_info {
- /* Figure 9-1002a: EHT Operation element format */
- struct ieee80211_eht_operation {
- u8 oper_params; /* EHT Operation Parameters: EHT_OPER_* bits */
-+ le32 mcs_nss_set;
- struct ieee80211_eht_oper_info oper_info; /* 0 or 3 or 5 octets */
- } STRUCT_PACKED;
-
---
-2.18.0
-
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/network/services/hostapd/patches/mtk-0100-hostapd-mtk-update-eht-operation-element.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/network/services/hostapd/patches/mtk-0100-hostapd-mtk-update-eht-operation-element.patch
new file mode 100644
index 0000000..d8cdf15
--- /dev/null
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/network/services/hostapd/patches/mtk-0100-hostapd-mtk-update-eht-operation-element.patch
@@ -0,0 +1,29 @@
+From ea9c7bda66bcd7819e106d5f672345b941365d15 Mon Sep 17 00:00:00 2001
+From: Evelyn Tsai <evelyn.tsai@mediatek.com>
+Date: Wed, 10 May 2023 13:11:34 +0800
+Subject: [PATCH 100/103] hostapd: mtk: update eht operation element
+
+---
+ src/ap/ieee802_11_eht.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/src/ap/ieee802_11_eht.c b/src/ap/ieee802_11_eht.c
+index 6ebe0f9..c14c5e2 100644
+--- a/src/ap/ieee802_11_eht.c
++++ b/src/ap/ieee802_11_eht.c
+@@ -214,9 +214,9 @@ u8 * hostapd_eid_eht_operation(struct hostapd_data *hapd, u8 *eid)
+
+ /* TODO: Fill in appropriate EHT-MCS max Nss information */
+ oper->basic_eht_mcs_nss_set[0] = 0x11;
+- oper->basic_eht_mcs_nss_set[1] = 0x00;
+- oper->basic_eht_mcs_nss_set[2] = 0x00;
+- oper->basic_eht_mcs_nss_set[3] = 0x00;
++ oper->basic_eht_mcs_nss_set[1] = 0x11;
++ oper->basic_eht_mcs_nss_set[2] = 0x11;
++ oper->basic_eht_mcs_nss_set[3] = 0x11;
+
+ if (is_6ghz_op_class(conf->op_class))
+ chwidth = op_class_to_ch_width(conf->op_class);
+--
+2.18.0
+
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/network/services/hostapd/patches/mtk-0101-hostapd-mtk-Fix-CCA-issue.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/network/services/hostapd/patches/mtk-0101-hostapd-mtk-Fix-CCA-issue.patch
new file mode 100644
index 0000000..9b46d70
--- /dev/null
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/network/services/hostapd/patches/mtk-0101-hostapd-mtk-Fix-CCA-issue.patch
@@ -0,0 +1,97 @@
+From 39a0dd44653f12ce13af68de81bfae683669623a Mon Sep 17 00:00:00 2001
+From: Evelyn Tsai <evelyn.tsai@mediatek.com>
+Date: Thu, 11 May 2023 14:08:59 +0800
+Subject: [PATCH 101/103] hostapd: mtk: Fix CCA issue
+
+When receiving CCA related nl80211 command, hostapd used to work on
+struct wpa_driver_nl80211_data, whose ctx always points to
+hostpad_iface->bss[0]. However, CCA command is sent on per-BSS based.
+This patch makes hostapd handle CCA related commands on per-BSS based.
+
+Signed-off-by: Michael Lee <michael-cy.lee@mediatek.com>
+---
+ src/drivers/driver_nl80211_event.c | 24 ++++++++++++------------
+ 1 file changed, 12 insertions(+), 12 deletions(-)
+
+diff --git a/src/drivers/driver_nl80211_event.c b/src/drivers/driver_nl80211_event.c
+index 67d9ce2..bcce9f5 100644
+--- a/src/drivers/driver_nl80211_event.c
++++ b/src/drivers/driver_nl80211_event.c
+@@ -3418,7 +3418,7 @@ static void nl80211_assoc_comeback(struct wpa_driver_nl80211_data *drv,
+
+ #ifdef CONFIG_IEEE80211AX
+
+-static void nl80211_obss_color_collision(struct wpa_driver_nl80211_data *drv,
++static void nl80211_obss_color_collision(struct i802_bss *bss,
+ struct nlattr *tb[])
+ {
+ union wpa_event_data data;
+@@ -3432,37 +3432,37 @@ static void nl80211_obss_color_collision(struct wpa_driver_nl80211_data *drv,
+
+ wpa_printf(MSG_DEBUG, "nl80211: BSS color collision - bitmap %08llx",
+ (long long unsigned int) data.bss_color_collision.bitmap);
+- wpa_supplicant_event(drv->ctx, EVENT_BSS_COLOR_COLLISION, &data);
++ wpa_supplicant_event(bss->ctx, EVENT_BSS_COLOR_COLLISION, &data);
+ }
+
+
+ static void
+-nl80211_color_change_announcement_started(struct wpa_driver_nl80211_data *drv)
++nl80211_color_change_announcement_started(struct i802_bss *bss)
+ {
+ union wpa_event_data data = {};
+
+ wpa_printf(MSG_DEBUG, "nl80211: CCA started");
+- wpa_supplicant_event(drv->ctx, EVENT_CCA_STARTED_NOTIFY, &data);
++ wpa_supplicant_event(bss->ctx, EVENT_CCA_STARTED_NOTIFY, &data);
+ }
+
+
+ static void
+-nl80211_color_change_announcement_aborted(struct wpa_driver_nl80211_data *drv)
++nl80211_color_change_announcement_aborted(struct i802_bss *bss)
+ {
+ union wpa_event_data data = {};
+
+ wpa_printf(MSG_DEBUG, "nl80211: CCA aborted");
+- wpa_supplicant_event(drv->ctx, EVENT_CCA_ABORTED_NOTIFY, &data);
++ wpa_supplicant_event(bss->ctx, EVENT_CCA_ABORTED_NOTIFY, &data);
+ }
+
+
+ static void
+-nl80211_color_change_announcement_completed(struct wpa_driver_nl80211_data *drv)
++nl80211_color_change_announcement_completed(struct i802_bss *bss)
+ {
+ union wpa_event_data data = {};
+
+ wpa_printf(MSG_DEBUG, "nl80211: CCA completed");
+- wpa_supplicant_event(drv->ctx, EVENT_CCA_NOTIFY, &data);
++ wpa_supplicant_event(bss->ctx, EVENT_CCA_NOTIFY, &data);
+ }
+
+ #endif /* CONFIG_IEEE80211AX */
+@@ -3724,16 +3724,16 @@ static void do_process_drv_event(struct i802_bss *bss, int cmd,
+ break;
+ #ifdef CONFIG_IEEE80211AX
+ case NL80211_CMD_OBSS_COLOR_COLLISION:
+- nl80211_obss_color_collision(drv, tb);
++ nl80211_obss_color_collision(bss, tb);
+ break;
+ case NL80211_CMD_COLOR_CHANGE_STARTED:
+- nl80211_color_change_announcement_started(drv);
++ nl80211_color_change_announcement_started(bss);
+ break;
+ case NL80211_CMD_COLOR_CHANGE_ABORTED:
+- nl80211_color_change_announcement_aborted(drv);
++ nl80211_color_change_announcement_aborted(bss);
+ break;
+ case NL80211_CMD_COLOR_CHANGE_COMPLETED:
+- nl80211_color_change_announcement_completed(drv);
++ nl80211_color_change_announcement_completed(bss);
+ break;
+ #endif /* CONFIG_IEEE80211AX */
+ default:
+--
+2.18.0
+
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/network/services/hostapd/patches/mtk-0102-hostapd-mtk-Fix-unexpected-AP-beacon-state-transitio.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/network/services/hostapd/patches/mtk-0102-hostapd-mtk-Fix-unexpected-AP-beacon-state-transitio.patch
new file mode 100644
index 0000000..4075531
--- /dev/null
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/network/services/hostapd/patches/mtk-0102-hostapd-mtk-Fix-unexpected-AP-beacon-state-transitio.patch
@@ -0,0 +1,37 @@
+From 097b204ffed838a4bbf7649fb23310f64ace22ad Mon Sep 17 00:00:00 2001
+From: Evelyn Tsai <evelyn.tsai@mediatek.com>
+Date: Thu, 11 May 2023 14:12:44 +0800
+Subject: [PATCH 102/103] hostapd: mtk: Fix unexpected AP beacon state
+ transition
+
+When AP fails setting the beacon, it assigns bss->beacon_set to 0 no
+matter what the error number is.
+However, in the case that the error number is -EBUSY, the driver might
+not free the beacon and expect a later beacon re-setting. If hostapd set
+a new beacon under this case, driver will return -EALREADY.
+This patch checks the error number after hostapd fails setting the
+beacon. If the error number is -EBUSY, bss->beacon_set will not be
+assigned to 0.
+
+Signed-off-by: Michael Lee <michael-cy.lee@mediatek.com>
+---
+ src/drivers/driver_nl80211.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
+index 8400e57..ccfc2d0 100644
+--- a/src/drivers/driver_nl80211.c
++++ b/src/drivers/driver_nl80211.c
+@@ -5126,7 +5126,8 @@ static int wpa_driver_nl80211_set_ap(void *priv,
+ ret, strerror(-ret));
+ if (!bss->flink->beacon_set)
+ ret = 0;
+- bss->flink->beacon_set = 0;
++ if (ret != -EBUSY)
++ bss->flink->beacon_set = 0;
+ } else {
+ bss->flink->beacon_set = 1;
+ nl80211_set_bss(bss, params->cts_protect, params->preamble,
+--
+2.18.0
+
diff --git a/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/network/services/hostapd/patches/mtk-0103-hostapd-mtk-Add-BW320-channel-switch-command.patch b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/network/services/hostapd/patches/mtk-0103-hostapd-mtk-Add-BW320-channel-switch-command.patch
new file mode 100644
index 0000000..5d38688
--- /dev/null
+++ b/autobuild_mac80211_release/mt7988_mt7996_mac80211/package/network/services/hostapd/patches/mtk-0103-hostapd-mtk-Add-BW320-channel-switch-command.patch
@@ -0,0 +1,107 @@
+From e61b734969cd94121434adef85f241f835aa1f5a Mon Sep 17 00:00:00 2001
+From: Evelyn Tsai <evelyn.tsai@mediatek.com>
+Date: Thu, 11 May 2023 14:16:57 +0800
+Subject: [PATCH 103/103] hostapd: mtk: Add BW320 channel switch command
+
+---
+ hostapd/ctrl_iface.c | 32 +++++++++++++++++++++++++++++++
+ src/ap/drv_callbacks.c | 3 ++-
+ src/ap/hostapd.c | 4 ++++
+ src/drivers/driver_nl80211_capa.c | 2 ++
+ 4 files changed, 40 insertions(+), 1 deletion(-)
+
+diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
+index 2d99647..274d079 100644
+--- a/hostapd/ctrl_iface.c
++++ b/hostapd/ctrl_iface.c
+@@ -2713,6 +2713,38 @@ static int hostapd_ctrl_check_freq_params(struct hostapd_freq_params *params,
+ return -1;
+ }
+ break;
++ case 320:
++ if (!params->center_freq1 || params->center_freq2 ||
++ !params->sec_channel_offset)
++ return -1;
++
++ switch (params->sec_channel_offset) {
++ case 1:
++ if (params->freq + 150 != params->center_freq1 &&
++ params->freq + 110 != params->center_freq1 &&
++ params->freq + 70 != params->center_freq1 &&
++ params->freq + 30 != params->center_freq1 &&
++ params->freq - 10 != params->center_freq1 &&
++ params->freq - 50 != params->center_freq1 &&
++ params->freq - 90 != params->center_freq1 &&
++ params->freq - 130 != params->center_freq1)
++ return -1;
++ break;
++ case -1:
++ if (params->freq + 130 != params->center_freq1 &&
++ params->freq + 90 != params->center_freq1 &&
++ params->freq + 50 != params->center_freq1 &&
++ params->freq + 10 != params->center_freq1 &&
++ params->freq - 30 != params->center_freq1 &&
++ params->freq - 70 != params->center_freq1 &&
++ params->freq - 110 != params->center_freq1 &&
++ params->freq - 150 != params->center_freq1)
++ return -1;
++ break;
++ default:
++ return -1;
++ }
++ break;
+ default:
+ return -1;
+ }
+diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c
+index c1f9a0e..dccbdb6 100644
+--- a/src/ap/drv_callbacks.c
++++ b/src/ap/drv_callbacks.c
+@@ -988,7 +988,8 @@ void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht,
+ hapd->iconf->ch_switch_eht_config = 0;
+
+ if (width == CHAN_WIDTH_40 || width == CHAN_WIDTH_80 ||
+- width == CHAN_WIDTH_80P80 || width == CHAN_WIDTH_160)
++ width == CHAN_WIDTH_80P80 || width == CHAN_WIDTH_160 ||
++ width == CHAN_WIDTH_320)
+ hapd->iconf->ht_capab |= HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET;
+ else if (width == CHAN_WIDTH_20 || width == CHAN_WIDTH_20_NOHT)
+ hapd->iconf->ht_capab &= ~HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET;
+diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
+index 9bd81d3..6fd5947 100644
+--- a/src/ap/hostapd.c
++++ b/src/ap/hostapd.c
+@@ -3705,6 +3705,7 @@ static int hostapd_change_config_freq(struct hostapd_data *hapd,
+ case 40:
+ case 80:
+ case 160:
++ case 320:
+ conf->ht_capab |= HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET;
+ break;
+ default:
+@@ -3777,6 +3778,9 @@ static int hostapd_fill_csa_settings(struct hostapd_data *hapd,
+ case 160:
+ bandwidth = CONF_OPER_CHWIDTH_160MHZ;
+ break;
++ case 320:
++ bandwidth = CONF_OPER_CHWIDTH_320MHZ;
++ break;
+ default:
+ bandwidth = CONF_OPER_CHWIDTH_USE_HT;
+ break;
+diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c
+index 7b5079b..1a53ade 100644
+--- a/src/drivers/driver_nl80211_capa.c
++++ b/src/drivers/driver_nl80211_capa.c
+@@ -1701,6 +1701,8 @@ static void phy_info_freq(struct hostapd_hw_modes *mode,
+ chan->allowed_bw &= ~HOSTAPD_CHAN_WIDTH_80;
+ if (tb_freq[NL80211_FREQUENCY_ATTR_NO_160MHZ])
+ chan->allowed_bw &= ~HOSTAPD_CHAN_WIDTH_160;
++ if (tb_freq[NL80211_FREQUENCY_ATTR_NO_320MHZ])
++ chan->allowed_bw &= ~HOSTAPD_CHAN_WIDTH_320;
+
+ if (tb_freq[NL80211_FREQUENCY_ATTR_DFS_STATE]) {
+ enum nl80211_dfs_state state =
+--
+2.18.0
+
diff --git a/autobuild_mac80211_release/package/network/services/hostapd_new/patches/mtk-0001-hostapd-mtk-Add-neighbor-report-and-BSS-Termination-.patch b/autobuild_mac80211_release/package/network/services/hostapd_new/patches/mtk-0001-hostapd-mtk-Add-neighbor-report-and-BSS-Termination-.patch
new file mode 100644
index 0000000..22e4841
--- /dev/null
+++ b/autobuild_mac80211_release/package/network/services/hostapd_new/patches/mtk-0001-hostapd-mtk-Add-neighbor-report-and-BSS-Termination-.patch
@@ -0,0 +1,475 @@
+From cb7b7459ac276c5713dae22b8fe19365c2895de1 Mon Sep 17 00:00:00 2001
+From: "howard.hsu" <howard-yh.hsu@mediatek.com>
+Date: Wed, 19 Jan 2022 19:18:07 +0800
+Subject: [PATCH 01/28] hostapd: mtk: Add neighbor report and BSS Termination
+ for MBO certification
+
+1. Add hostapd_neighbor_count() and hostapd_neighbor_insert_buffer ()
+The first function can count the number of neighbor report in neighbore report
+database. The second can iterate neighbor report database to build up neighbor
+report data.
+
+2. Support including neighbor report elements in ANQP response
+3. Support including neignbor report elements in BTM response
+4. Support configuring BSS Termination TSF by using hostapd_cli command
+5. Disable interface if BSS Termination TSF is set
+6. Add set_send_disassoc_frame_timer() to send disassociate frame
+Function set_disassoc_timer() may fail if key was deleted first. This new
+function will not ask to delete key as set_disassoc_timer() did.
+7. Support including neighbor report elements in BTM request
+8. Add hostapd_neighbor_set_own_report_pref()
+9. Add hostapd_neighbor_set_pref_by_non_pref_chan()
+---
+ hostapd/ctrl_iface.c | 5 ++
+ src/ap/ap_config.c | 1 +
+ src/ap/ap_config.h | 1 +
+ src/ap/ctrl_iface_ap.c | 19 ++++++-
+ src/ap/gas_serv.c | 29 ++++++++++
+ src/ap/gas_serv.h | 2 +
+ src/ap/neighbor_db.c | 119 +++++++++++++++++++++++++++++++++++++++++
+ src/ap/neighbor_db.h | 9 ++++
+ src/ap/wnm_ap.c | 72 +++++++++++++++++++++++--
+ 9 files changed, 252 insertions(+), 5 deletions(-)
+
+diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
+index a0e4ecd..0355e8b 100644
+--- a/hostapd/ctrl_iface.c
++++ b/hostapd/ctrl_iface.c
+@@ -1347,6 +1347,11 @@ static int hostapd_ctrl_iface_set(struct hostapd_data *hapd, char *cmd)
+ #endif /* CONFIG_DPP */
+ } else if (os_strcasecmp(cmd, "setband") == 0) {
+ ret = hostapd_ctrl_iface_set_band(hapd, value);
++ } else if (os_strcasecmp(cmd, "bss_termination_tsf") == 0) {
++ int termination_sec = atoi(value);
++ hapd->conf->bss_termination_tsf = termination_sec;
++ wpa_printf(MSG_DEBUG, "BSS Termination TSF: value = %d",
++ termination_sec);
+ } else {
+ ret = hostapd_set_iface(hapd->iconf, hapd->conf, cmd, value);
+ if (ret)
+diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
+index 2755146..9f450f6 100644
+--- a/src/ap/ap_config.c
++++ b/src/ap/ap_config.c
+@@ -170,6 +170,7 @@ void hostapd_config_defaults_bss(struct hostapd_bss_config *bss)
+ /* comeback after 10 TUs */
+ bss->pasn_comeback_after = 10;
+ #endif /* CONFIG_PASN */
++ bss->bss_termination_tsf = 0;
+ }
+
+
+diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
+index 7774360..af9bf92 100644
+--- a/src/ap/ap_config.h
++++ b/src/ap/ap_config.h
+@@ -558,6 +558,7 @@ struct hostapd_bss_config {
+ int wnm_sleep_mode;
+ int wnm_sleep_mode_no_keys;
+ int bss_transition;
++ unsigned int bss_termination_tsf;
+
+ /* IEEE 802.11u - Interworking */
+ int interworking;
+diff --git a/src/ap/ctrl_iface_ap.c b/src/ap/ctrl_iface_ap.c
+index d46de44..38fc8e4 100644
+--- a/src/ap/ctrl_iface_ap.c
++++ b/src/ap/ctrl_iface_ap.c
+@@ -1265,6 +1265,10 @@ int hostapd_ctrl_iface_bss_tm_req(struct hostapd_data *hapd,
+ wpa_printf(MSG_DEBUG, "Invalid bss_term data");
+ return -1;
+ }
++ if (hapd->conf->bss_termination_tsf) {
++ WPA_PUT_LE64(&bss_term_dur[2], hapd->conf->bss_termination_tsf);
++ }
++
+ end++;
+ WPA_PUT_LE16(&bss_term_dur[10], atoi(end));
+ }
+@@ -1291,14 +1295,25 @@ int hostapd_ctrl_iface_bss_tm_req(struct hostapd_data *hapd,
+ req_mode |= WNM_BSS_TM_REQ_ESS_DISASSOC_IMMINENT;
+ }
+
+- if (os_strstr(cmd, " pref=1"))
++ if (os_strstr(cmd, " pref=1")) {
+ req_mode |= WNM_BSS_TM_REQ_PREF_CAND_LIST_INCLUDED;
++ if (nei_len == 0) {
++ // Add neigibor report from neighbor report db to nei_rep buffer
++ nei_len = hostapd_neighbor_insert_buffer (hapd, nei_rep, 1000);
++ }
++ }
+ if (os_strstr(cmd, " abridged=1"))
+ req_mode |= WNM_BSS_TM_REQ_ABRIDGED;
+- if (os_strstr(cmd, " disassoc_imminent=1"))
++ if (os_strstr(cmd, " disassoc_imminent=1")) {
+ req_mode |= WNM_BSS_TM_REQ_DISASSOC_IMMINENT;
++ /* Set own BSS neighbor report preference value as 0 */
++ hostapd_neighbor_set_own_report_pref(hapd, nei_rep, nei_len, 0);
++ }
++
+
+ #ifdef CONFIG_MBO
++ hostapd_neighbor_set_pref_by_non_pref_chan(hapd, sta, nei_rep, nei_len);
++
+ pos = os_strstr(cmd, "mbo=");
+ if (pos) {
+ unsigned int mbo_reason, cell_pref, reassoc_delay;
+diff --git a/src/ap/gas_serv.c b/src/ap/gas_serv.c
+index 4642e49..cce6df4 100644
+--- a/src/ap/gas_serv.c
++++ b/src/ap/gas_serv.c
+@@ -19,6 +19,7 @@
+ #include "dpp_hostapd.h"
+ #include "sta_info.h"
+ #include "gas_serv.h"
++#include "neighbor_db.h"
+
+
+ #ifdef CONFIG_DPP
+@@ -369,6 +370,24 @@ static void anqp_add_network_auth_type(struct hostapd_data *hapd,
+ }
+ }
+
++static void anqp_add_neighbor_report(struct hostapd_data *hapd,
++ struct wpabuf *buf)
++{
++ struct hostapd_neighbor_entry *nr;
++ u8 *len_pos = gas_anqp_add_element(buf, ANQP_NEIGHBOR_REPORT);
++ if (dl_list_empty(&hapd->nr_db)) {
++ wpabuf_put_le16(buf, 0);
++ }
++ else {
++ dl_list_for_each(nr, &hapd->nr_db, struct hostapd_neighbor_entry, list ) {
++ wpabuf_put_u8(buf, WLAN_EID_NEIGHBOR_REPORT);
++ wpabuf_put_u8(buf, wpabuf_len(nr->nr));
++ wpabuf_put_buf(buf, nr->nr);
++ }
++ }
++ gas_anqp_set_element_len(buf, len_pos);
++}
++
+
+ static void anqp_add_roaming_consortium(struct hostapd_data *hapd,
+ struct wpabuf *buf)
+@@ -986,6 +1005,9 @@ gas_serv_build_gas_resp_payload(struct hostapd_data *hapd,
+ len += 1000;
+ if (request & ANQP_REQ_ICON_REQUEST)
+ len += 65536;
++ if (request & ANQP_REQ_NEIGHBOR_REPORT) {
++ len += (40 * hostapd_neighbor_count(hapd));
++ }
+ #ifdef CONFIG_FILS
+ if (request & ANQP_FILS_REALM_INFO)
+ len += 2 * dl_list_len(&hapd->conf->fils_realms);
+@@ -1028,6 +1050,8 @@ gas_serv_build_gas_resp_payload(struct hostapd_data *hapd,
+ anqp_add_elem(hapd, buf, ANQP_TDLS_CAPABILITY);
+ if (request & ANQP_REQ_EMERGENCY_NAI)
+ anqp_add_elem(hapd, buf, ANQP_EMERGENCY_NAI);
++ if (request & ANQP_REQ_NEIGHBOR_REPORT)
++ anqp_add_neighbor_report(hapd, buf);
+
+ for (i = 0; i < num_extra_req; i++) {
+ #ifdef CONFIG_FILS
+@@ -1172,6 +1196,11 @@ static void rx_anqp_query_list_id(struct hostapd_data *hapd, u16 info_id,
+ "Emergency NAI",
+ get_anqp_elem(hapd, info_id) != NULL, qi);
+ break;
++ case ANQP_NEIGHBOR_REPORT:
++ set_anqp_req(ANQP_REQ_NEIGHBOR_REPORT,
++ "Neighbor Report",
++ get_anqp_elem(hapd, info_id) != NULL, qi);
++ break;
+ default:
+ #ifdef CONFIG_FILS
+ if (info_id == ANQP_FILS_REALM_INFO &&
+diff --git a/src/ap/gas_serv.h b/src/ap/gas_serv.h
+index 7646a98..ce492b5 100644
+--- a/src/ap/gas_serv.h
++++ b/src/ap/gas_serv.h
+@@ -40,6 +40,8 @@
+ (1 << (ANQP_TDLS_CAPABILITY - ANQP_QUERY_LIST))
+ #define ANQP_REQ_EMERGENCY_NAI \
+ (1 << (ANQP_EMERGENCY_NAI - ANQP_QUERY_LIST))
++#define ANQP_REQ_NEIGHBOR_REPORT \
++ (1 << (ANQP_NEIGHBOR_REPORT - ANQP_QUERY_LIST))
+ /*
+ * First 15 Hotspot 2.0 vendor specific ANQP-elements can be included in the
+ * optimized bitmap.
+diff --git a/src/ap/neighbor_db.c b/src/ap/neighbor_db.c
+index 5b276e8..1c14b32 100644
+--- a/src/ap/neighbor_db.c
++++ b/src/ap/neighbor_db.c
+@@ -89,6 +89,38 @@ int hostapd_neighbor_show(struct hostapd_data *hapd, char *buf, size_t buflen)
+ }
+
+
++int hostapd_neighbor_count(struct hostapd_data *hapd)
++{
++ struct hostapd_neighbor_entry *nr;
++ int count = 0;
++
++ dl_list_for_each(nr, &hapd->nr_db, struct hostapd_neighbor_entry,
++ list) {
++ count++;
++ }
++ return count;
++}
++
++
++int hostapd_neighbor_insert_buffer(struct hostapd_data *hapd, char *buf,
++ size_t buflen)
++{
++ struct hostapd_neighbor_entry *nr;
++ char *pos = buf;
++
++ dl_list_for_each(nr, &hapd->nr_db, struct hostapd_neighbor_entry,
++ list) {
++ /* For neighbor report IE, we only need bssid and nr*/
++ *pos++ = WLAN_EID_NEIGHBOR_REPORT;
++ *pos++ = wpabuf_len(nr->nr);
++ os_memcpy(pos, wpabuf_head(nr->nr), wpabuf_len(nr->nr));
++ pos += wpabuf_len(nr->nr);
++ }
++
++ return pos - buf;
++}
++
++
+ static void hostapd_neighbor_clear_entry(struct hostapd_neighbor_entry *nr)
+ {
+ wpabuf_free(nr->nr);
+@@ -325,3 +357,90 @@ void hostapd_neighbor_set_own_report(struct hostapd_data *hapd)
+ wpabuf_free(nr);
+ #endif /* NEED_AP_MLME */
+ }
++
++
++void hostapd_neighbor_set_own_report_pref(struct hostapd_data *hapd, char *nei_buf,
++ size_t buflen, const int pref)
++{
++ struct hostapd_neighbor_entry *nr;
++ char *pos, *next_nr;
++
++ pos = nei_buf;
++ next_nr = nei_buf;
++
++ dl_list_for_each(nr, &hapd->nr_db, struct hostapd_neighbor_entry,
++ list) {
++ pos = next_nr;
++ next_nr = pos + 2 + wpabuf_len(nr->nr);
++ /* Shift 2 bytes for Element ID and Neighbor report length */
++ pos = pos + 2;
++ if(os_memcmp(pos, hapd->own_addr, ETH_ALEN) == 0) {
++ /* Shift for BSSID + BSSID info + Op_class + channel num + PHY type */
++ pos = pos + 6 + 4 + 1 + 1 + 1;
++
++ /* Iterate Subelement */
++ while (next_nr - pos > 0) {
++ if (*pos == 3) {
++ pos = pos + 2;
++ *pos = pref;
++ return;
++ } else {
++ pos++;
++ int shift_len = *pos++;
++ pos = pos + shift_len;
++ }
++ }
++ }
++ }
++}
++
++#ifdef CONFIG_MBO
++void hostapd_neighbor_set_pref_by_non_pref_chan(struct hostapd_data *hapd,
++ struct sta_info* sta, char *nei_buf, size_t buflen)
++{
++ struct hostapd_neighbor_entry *nr;
++ struct mbo_non_pref_chan_info *info;
++ u8 i;
++
++ for(info = sta->non_pref_chan; info; info = info->next) {
++ /* Check OP_Class and Channel num */
++ for(i = 0; i < info->num_channels; i++) {
++ char *pos, *next_nr;
++
++ pos = nei_buf;
++ next_nr = nei_buf;
++
++ /* Iterate Neighbor report database */
++ dl_list_for_each(nr, &hapd->nr_db, struct hostapd_neighbor_entry,
++ list) {
++ pos = next_nr;
++ next_nr = pos + 2 + wpabuf_len(nr->nr);
++ /**
++ * Shift 12 bytes for Element ID, Neighbor report length,
++ * BSSID and BSSID info.
++ */
++ pos = pos + 12;
++ int nr_op_class = *pos++;
++ int nr_channel = *pos;
++ if(info->op_class == nr_op_class && info->channels[i] == nr_channel) {
++ /* Shift for Channel Num + PHY type */
++ pos = pos + 1 + 1;
++
++ // Iterate Subelement
++ while(next_nr - pos > 0) {
++ if(*pos == 3) {
++ pos = pos + 2;
++ *pos = info->pref;
++ break;
++ }else {
++ pos++;
++ int shift_len = *pos++;
++ pos = pos + shift_len;
++ }
++ }
++ }
++ }
++ }
++ }
++}
++#endif
+diff --git a/src/ap/neighbor_db.h b/src/ap/neighbor_db.h
+index 992671b..a1ddc07 100644
+--- a/src/ap/neighbor_db.h
++++ b/src/ap/neighbor_db.h
+@@ -24,4 +24,13 @@ int hostapd_neighbor_remove(struct hostapd_data *hapd, const u8 *bssid,
+ const struct wpa_ssid_value *ssid);
+ void hostapd_free_neighbor_db(struct hostapd_data *hapd);
+
++int hostapd_neighbor_count(struct hostapd_data *hapd);
++int hostapd_neighbor_insert_buffer(struct hostapd_data *hapd, char *buf,
++ size_t buflen);
++void hostapd_neighbor_set_own_report_pref(struct hostapd_data *hapd, char *nei_buf,
++ size_t buflen, const int pref);
++#ifdef CONFIG_MBO
++void hostapd_neighbor_set_pref_by_non_pref_chan(struct hostapd_data *hapd,
++ struct sta_info* sta, char *nei_buf, size_t buflen);
++#endif
+ #endif /* NEIGHBOR_DB_H */
+diff --git a/src/ap/wnm_ap.c b/src/ap/wnm_ap.c
+index ba1dd2e..32ccf14 100644
+--- a/src/ap/wnm_ap.c
++++ b/src/ap/wnm_ap.c
+@@ -20,6 +20,7 @@
+ #include "ap/wpa_auth.h"
+ #include "mbo_ap.h"
+ #include "wnm_ap.h"
++#include "ap/neighbor_db.h"
+
+ #define MAX_TFS_IE_LEN 1024
+
+@@ -370,9 +371,21 @@ static int ieee802_11_send_bss_trans_mgmt_request(struct hostapd_data *hapd,
+ u8 *pos;
+ int res;
+
+- mgmt = os_zalloc(sizeof(*mgmt));
+- if (mgmt == NULL)
++ int nr_num = hostapd_neighbor_count(hapd);
++ int nr_size = ETH_ALEN + 4 + 1 + 1 + 1 + 5;
++ int total_nr_size = nr_num * nr_size;
++ u8 *nr_data = os_malloc(total_nr_size);
++ int nr_data_len = 0;
++ if(nr_data == NULL) {
++ wpa_printf (MSG_ERROR, "Failed to allocate memory");
++ } else {
++ nr_data_len = hostapd_neighbor_insert_buffer(hapd, nr_data, total_nr_size);
++ }
++ mgmt = os_zalloc(sizeof(*mgmt) + nr_data_len);
++ if (mgmt == NULL) {
++ wpa_printf (MSG_ERROR, "Failed to allocate memory for mgmt frame");
+ return -1;
++ }
+ os_memcpy(mgmt->da, addr, ETH_ALEN);
+ os_memcpy(mgmt->sa, hapd->own_addr, ETH_ALEN);
+ os_memcpy(mgmt->bssid, hapd->own_addr, ETH_ALEN);
+@@ -382,10 +395,18 @@ static int ieee802_11_send_bss_trans_mgmt_request(struct hostapd_data *hapd,
+ mgmt->u.action.u.bss_tm_req.action = WNM_BSS_TRANS_MGMT_REQ;
+ mgmt->u.action.u.bss_tm_req.dialog_token = dialog_token;
+ mgmt->u.action.u.bss_tm_req.req_mode = 0;
++ if(nr_num) {
++ mgmt->u.action.u.bss_tm_req.req_mode |= WNM_BSS_TM_REQ_PREF_CAND_LIST_INCLUDED;
++ }
+ mgmt->u.action.u.bss_tm_req.disassoc_timer = host_to_le16(0);
+ mgmt->u.action.u.bss_tm_req.validity_interval = 1;
+ pos = mgmt->u.action.u.bss_tm_req.variable;
+
++ if(nr_num) {
++ os_memcpy(pos, nr_data, nr_data_len);
++ pos += nr_data_len;
++ }
++
+ hapd->openwrt_stats.wnm.bss_transition_request_tx++;
+ wpa_printf(MSG_DEBUG, "WNM: Send BSS Transition Management Request to "
+ MACSTR " dialog_token=%u req_mode=0x%x disassoc_timer=%u "
+@@ -890,6 +911,50 @@ static void set_disassoc_timer(struct hostapd_data *hapd, struct sta_info *sta,
+ }
+
+
++static void set_send_disassoc_frame_timer(struct hostapd_data *hapd, struct sta_info *sta,
++ int disassoc_timer)
++{
++ int timeout, beacon_int;
++
++ /*
++ * Prevent STA from reconnecting using cached PMKSA to force
++ * full authentication with the authentication server (which may
++ * decide to reject the connection),
++ */
++ wpa_auth_pmksa_remove(hapd->wpa_auth, sta->addr);
++
++ beacon_int = hapd->iconf->beacon_int;
++ if (beacon_int < 1)
++ beacon_int = 100; /* best guess */
++ /* Calculate timeout in ms based on beacon_int in TU */
++ timeout = disassoc_timer * beacon_int * 128 / 125;
++ wpa_printf(MSG_DEBUG, "Disassociation timer for " MACSTR
++ " set to %d ms", MAC2STR(sta->addr), timeout);
++
++ u16 reason = WLAN_REASON_PREV_AUTH_NOT_VALID;
++
++ hostapd_drv_sta_disassoc(hapd, sta->addr, reason);
++ if (sta)
++ ap_sta_disassociate(hapd, sta, reason);
++}
++
++
++void bss_termination_disable_iface(void *eloop_ctx, void *timeout_ctx)
++{
++ struct hostapd_data *hapd = eloop_ctx;
++ hostapd_disable_iface(hapd->iface);
++}
++
++
++static void set_disable_iface_timer(struct hostapd_data *hapd, struct sta_info *sta,
++ int disable_iface_timer)
++{
++ wpa_printf(MSG_DEBUG, "Disable interface timer set to %d secs", disable_iface_timer);
++ eloop_register_timeout(disable_iface_timer, 0,
++ bss_termination_disable_iface, hapd, NULL);
++}
++
++
+ int wnm_send_ess_disassoc_imminent(struct hostapd_data *hapd,
+ struct sta_info *sta, const char *url,
+ int disassoc_timer)
+@@ -934,7 +999,7 @@ int wnm_send_ess_disassoc_imminent(struct hostapd_data *hapd,
+ hapd->openwrt_stats.wnm.bss_transition_request_tx++;
+ if (disassoc_timer) {
+ /* send disassociation frame after time-out */
+- set_disassoc_timer(hapd, sta, disassoc_timer);
++ set_send_disassoc_frame_timer(hapd, sta, disassoc_timer);
+ }
+
+ return 0;
+@@ -979,6 +1044,7 @@ int wnm_send_bss_tm_req(struct hostapd_data *hapd, struct sta_info *sta,
+ bss_term_dur) {
+ os_memcpy(pos, bss_term_dur, 12);
+ pos += 12;
++ set_disable_iface_timer(hapd, sta, hapd->conf->bss_termination_tsf);
+ }
+
+ if (url) {
+--
+2.18.0
+
diff --git a/autobuild_mac80211_release/package/network/services/hostapd_new/patches/mtk-0002-hostapd-mtk-print-sae-groups-by-hostapd-ctrl.patch b/autobuild_mac80211_release/package/network/services/hostapd_new/patches/mtk-0002-hostapd-mtk-print-sae-groups-by-hostapd-ctrl.patch
new file mode 100644
index 0000000..d5ebb61
--- /dev/null
+++ b/autobuild_mac80211_release/package/network/services/hostapd_new/patches/mtk-0002-hostapd-mtk-print-sae-groups-by-hostapd-ctrl.patch
@@ -0,0 +1,36 @@
+From 41cf77cdfd1b260a688592a8ae4c1474d492d6e4 Mon Sep 17 00:00:00 2001
+From: Shayne Chen <shayne.chen@mediatek.com>
+Date: Tue, 20 Sep 2022 19:33:45 +0800
+Subject: [PATCH 02/28] hostapd: mtk: print sae groups by hostapd ctrl
+
+---
+ hostapd/ctrl_iface.c | 13 +++++++++++++
+ 1 file changed, 13 insertions(+)
+
+diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
+index 0355e8b..8e8a1a7 100644
+--- a/hostapd/ctrl_iface.c
++++ b/hostapd/ctrl_iface.c
+@@ -1421,6 +1421,19 @@ static int hostapd_ctrl_iface_get(struct hostapd_data *hapd, char *cmd,
+ if (os_snprintf_error(buflen, res))
+ return -1;
+ return res;
++ } else if (os_strcmp(cmd, "sae_group_capability") == 0) {
++#ifdef CONFIG_SAE
++ /* see sae_set_group() */
++ res = os_snprintf(buf, buflen, "%s%s%s%s19 20 21",
++ dh_groups_get(15) ? "15 ": "",
++ dh_groups_get(16) ? "16 ": "",
++ dh_groups_get(17) ? "17 ": "",
++ dh_groups_get(18) ? "18 ": "");
++
++ if (os_snprintf_error(buflen, res))
++ return -1;
++ return res;
++#endif /* CONFIG_SAE */
+ }
+
+ return -1;
+--
+2.18.0
+
diff --git a/autobuild_mac80211_release/package/network/services/hostapd_new/patches/mtk-0003-hostapd-mtk-add-support-for-runtime-set-in-band-disc.patch b/autobuild_mac80211_release/package/network/services/hostapd_new/patches/mtk-0003-hostapd-mtk-add-support-for-runtime-set-in-band-disc.patch
new file mode 100644
index 0000000..94bc2b9
--- /dev/null
+++ b/autobuild_mac80211_release/package/network/services/hostapd_new/patches/mtk-0003-hostapd-mtk-add-support-for-runtime-set-in-band-disc.patch
@@ -0,0 +1,211 @@
+From c7e5ad8609443c3e484ea06df88755de55f5bda0 Mon Sep 17 00:00:00 2001
+From: MeiChia Chiu <meichia.chiu@mediatek.com>
+Date: Tue, 31 May 2022 21:15:54 +0800
+Subject: [PATCH 03/28] hostapd: mtk: add support for runtime set in-band
+ discovery
+
+Usage:
+hostapd_cli unsolic_probe_resp [tx_type] [interval]
+
+0: disable all in-band discovery
+1: enable unsolicited probe response
+2: enable FILS discovery
+
+Signed-off-by: MeiChia Chiu <MeiChia.Chiu@mediatek.com>
+---
+ hostapd/ctrl_iface.c | 66 ++++++++++++++++++++++++++++++++++++
+ hostapd/hostapd_cli.c | 20 +++++++++++
+ src/ap/beacon.c | 5 ++-
+ src/drivers/driver_nl80211.c | 10 ++++--
+ src/drivers/nl80211_copy.h | 1 +
+ 5 files changed, 98 insertions(+), 4 deletions(-)
+
+diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
+index 8e8a1a7..c4e344e 100644
+--- a/hostapd/ctrl_iface.c
++++ b/hostapd/ctrl_iface.c
+@@ -827,6 +827,69 @@ static int hostapd_ctrl_iface_send_qos_map_conf(struct hostapd_data *hapd,
+
+ #endif /* CONFIG_INTERWORKING */
+
++static int hostapd_ctrl_iface_inband_discovery(struct hostapd_data *hapd,
++ const char *cmd)
++{
++ struct hostapd_bss_config *conf = hapd->conf;
++ const char *pos = cmd;
++ int tx_type, interval, ret;
++
++ tx_type = atoi(pos);
++ if (tx_type < 0 || tx_type > 2) {
++ wpa_printf(MSG_ERROR, "Invalid tx type\n");
++ return -1;
++ }
++
++ pos = os_strchr(pos, ' ');
++ if(!pos)
++ return -1;
++ pos++;
++ interval = atoi(pos);
++ if (interval < 0 || interval > 20) {
++ wpa_printf(MSG_ERROR, "Invalid interval value\n");
++ return -1;
++ }
++
++ wpa_printf(MSG_ERROR, "Set inband discovery type:%d, interval:%d\n",
++ tx_type, interval);
++
++#define DISABLE_INBAND_DISC 0
++#define UNSOL_PROBE_RESP 1
++#define FILS_DISCOVERY 2
++
++#ifdef CONFIG_FILS
++ conf->fils_discovery_max_int = 0;
++ conf->fils_discovery_min_int = 0;
++#endif /* CONFIG_FILS */
++ conf->unsol_bcast_probe_resp_interval = 0;
++
++ switch (tx_type) {
++ case DISABLE_INBAND_DISC:
++ default:
++ /* Disable both Unsolicited probe response and FILS discovery*/
++ break;
++ case UNSOL_PROBE_RESP:
++ /* Enable Unsolicited probe response */
++ conf->unsol_bcast_probe_resp_interval = interval;
++ break;
++#ifdef CONFIG_FILS
++ case FILS_DISCOVERY:
++ /* Enable FILS discovery */
++ conf->fils_discovery_min_int = interval;
++ conf->fils_discovery_max_int = interval;
++ break;
++#endif /* CONFIG_FILS */
++ }
++
++ ret = ieee802_11_update_beacons(hapd->iface);
++ if(ret) {
++ wpa_printf(MSG_DEBUG,
++ "Failed to update with inband discovery parameters\n");
++ return -1;
++ }
++
++ return 0;
++}
+
+ #ifdef CONFIG_WNM_AP
+
+@@ -3511,6 +3574,9 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
+ if (hostapd_ctrl_iface_coloc_intf_req(hapd, buf + 15))
+ reply_len = -1;
+ #endif /* CONFIG_WNM_AP */
++ } else if (os_strncmp(buf, "INBAND_DISCOVERY ", 17) == 0) {
++ if (hostapd_ctrl_iface_inband_discovery(hapd, buf + 17))
++ reply_len = -1;
+ } else if (os_strcmp(buf, "GET_CONFIG") == 0) {
+ reply_len = hostapd_ctrl_iface_get_config(hapd, reply,
+ reply_size);
+diff --git a/hostapd/hostapd_cli.c b/hostapd/hostapd_cli.c
+index bc8993f..05ac5ac 100644
+--- a/hostapd/hostapd_cli.c
++++ b/hostapd/hostapd_cli.c
+@@ -655,6 +655,24 @@ static int hostapd_cli_cmd_wps_config(struct wpa_ctrl *ctrl, int argc,
+ return wpa_ctrl_command(ctrl, buf);
+ }
+
++static int hostapd_cli_cmd_inband_discovery(struct wpa_ctrl *ctrl, int argc,
++ char *argv[])
++{
++ char buf[300];
++ int res;
++
++ if (argc < 2) {
++ printf("Invalid 'inband_discovery' command - two arguments"
++ "tx_type interval\n");
++ return -1;
++ }
++
++ res = os_snprintf(buf, sizeof(buf), "INBAND_DISCOVERY %s %s",
++ argv[0], argv[1]);
++ if (os_snprintf_error(sizeof(buf), res))
++ return -1;
++ return wpa_ctrl_command(ctrl, buf);
++}
+
+ static int hostapd_cli_cmd_disassoc_imminent(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+@@ -1773,6 +1791,8 @@ static const struct hostapd_cli_cmd hostapd_cli_commands[] = {
+ { "driver", hostapd_cli_cmd_driver, NULL,
+ "<driver sub command> [<hex formatted data>] = send driver command data" },
+ #endif /* ANDROID */
++ { "inband_discovery", hostapd_cli_cmd_inband_discovery, NULL,
++ "<tx type(0/1/2)> <interval> = runtime set inband discovery" },
+ { NULL, NULL, NULL, NULL }
+ };
+
+diff --git a/src/ap/beacon.c b/src/ap/beacon.c
+index 73ab31c..ddb5d03 100644
+--- a/src/ap/beacon.c
++++ b/src/ap/beacon.c
+@@ -1618,6 +1618,8 @@ static u8 * hostapd_fils_discovery(struct hostapd_data *hapd,
+ struct wpa_driver_ap_params *params)
+ {
+ params->fd_max_int = hapd->conf->fils_discovery_max_int;
++ params->unsol_bcast_probe_resp_interval =
++ hapd->conf->unsol_bcast_probe_resp_interval;
+ if (is_6ghz_op_class(hapd->iconf->op_class) &&
+ params->fd_max_int > FD_MAX_INTERVAL_6GHZ)
+ params->fd_max_int = FD_MAX_INTERVAL_6GHZ;
+@@ -1626,7 +1628,8 @@ static u8 * hostapd_fils_discovery(struct hostapd_data *hapd,
+ if (params->fd_min_int > params->fd_max_int)
+ params->fd_min_int = params->fd_max_int;
+
+- if (params->fd_max_int)
++ if (params->fd_max_int || (is_6ghz_op_class(hapd->iconf->op_class) &&
++ !params->unsol_bcast_probe_resp_interval))
+ return hostapd_gen_fils_discovery(hapd,
+ ¶ms->fd_frame_tmpl_len);
+
+diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
+index 4377165..d79929b 100644
+--- a/src/drivers/driver_nl80211.c
++++ b/src/drivers/driver_nl80211.c
+@@ -4631,9 +4631,10 @@ static int nl80211_fils_discovery(struct i802_bss *bss, struct nl_msg *msg,
+ params->fd_max_int) ||
+ (params->fd_frame_tmpl &&
+ nla_put(msg, NL80211_FILS_DISCOVERY_ATTR_TMPL,
+- params->fd_frame_tmpl_len, params->fd_frame_tmpl)))
++ params->fd_frame_tmpl_len, params->fd_frame_tmpl)) ||
++ nla_put_u32(msg, NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_INTE,
++ params->unsol_bcast_probe_resp_interval))
+ return -1;
+-
+ nla_nest_end(msg, attr);
+ return 0;
+ }
+@@ -5038,7 +5039,10 @@ static int wpa_driver_nl80211_set_ap(void *priv,
+ #endif /* CONFIG_SAE */
+
+ #ifdef CONFIG_FILS
+- if (params->fd_max_int && nl80211_fils_discovery(bss, msg, params) < 0)
++ if ((params->fd_max_int ||
++ ((params->freq->freq > 5950 && params->freq->freq <= 7115) &&
++ !(params->unsol_bcast_probe_resp_interval))) &&
++ nl80211_fils_discovery(bss, msg, params) < 0)
+ goto fail;
+ #endif /* CONFIG_FILS */
+
+diff --git a/src/drivers/nl80211_copy.h b/src/drivers/nl80211_copy.h
+index 9a0ac03..12fc6a9 100644
+--- a/src/drivers/nl80211_copy.h
++++ b/src/drivers/nl80211_copy.h
+@@ -7569,6 +7569,7 @@ enum nl80211_fils_discovery_attributes {
+ NL80211_FILS_DISCOVERY_ATTR_INT_MIN,
+ NL80211_FILS_DISCOVERY_ATTR_INT_MAX,
+ NL80211_FILS_DISCOVERY_ATTR_TMPL,
++ NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_INTE,
+
+ /* keep last */
+ __NL80211_FILS_DISCOVERY_ATTR_LAST,
+--
+2.18.0
+
diff --git a/autobuild_mac80211_release/package/network/services/hostapd_new/patches/mtk-0004-hostapd-mtk-Add-mtk_vendor.h.patch b/autobuild_mac80211_release/package/network/services/hostapd_new/patches/mtk-0004-hostapd-mtk-Add-mtk_vendor.h.patch
new file mode 100644
index 0000000..e9d1726
--- /dev/null
+++ b/autobuild_mac80211_release/package/network/services/hostapd_new/patches/mtk-0004-hostapd-mtk-Add-mtk_vendor.h.patch
@@ -0,0 +1,214 @@
+From e478ae5563a043f3d18be4bbbed682ac04e48d22 Mon Sep 17 00:00:00 2001
+From: Howard Hsu <howard-yh.hsu@mediatek.com>
+Date: Mon, 30 May 2022 15:04:57 +0800
+Subject: [PATCH 04/28] hostapd: mtk: Add mtk_vendor.h
+
+---
+ src/common/mtk_vendor.h | 195 ++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 195 insertions(+)
+ create mode 100644 src/common/mtk_vendor.h
+
+diff --git a/src/common/mtk_vendor.h b/src/common/mtk_vendor.h
+new file mode 100644
+index 0000000..528387f
+--- /dev/null
++++ b/src/common/mtk_vendor.h
+@@ -0,0 +1,195 @@
++// SPDX-License-Identifier: ISC
++/* Copyright (C) 2020 Felix Fietkau <nbd@nbd.name> */
++#ifndef MTK_VENDOR_H
++#define MTK_VENDOR_H
++
++#define OUI_MTK 0x000ce7
++
++enum mtk_nl80211_vendor_subcmds {
++ MTK_NL80211_VENDOR_SUBCMD_AMNT_CTRL = 0xae,
++ MTK_NL80211_VENDOR_SUBCMD_CSI_CTRL = 0xc2,
++ MTK_NL80211_VENDOR_SUBCMD_RFEATURE_CTRL = 0xc3,
++ MTK_NL80211_VENDOR_SUBCMD_WIRELESS_CTRL = 0xc4,
++ MTK_NL80211_VENDOR_SUBCMD_EDCCA_CTRL = 0xc7,
++};
++
++enum mtk_vendor_attr_edcca_ctrl {
++ MTK_VENDOR_ATTR_EDCCA_THRESHOLD_INVALID = 0,
++
++ MTK_VENDOR_ATTR_EDCCA_CTRL_MODE,
++ MTK_VENDOR_ATTR_EDCCA_CTRL_PRI20_VAL,
++ MTK_VENDOR_ATTR_EDCCA_CTRL_SEC20_VAL,
++ MTK_VENDOR_ATTR_EDCCA_CTRL_SEC40_VAL,
++ MTK_VENDOR_ATTR_EDCCA_CTRL_SEC80_VAL,
++ MTK_VENDOR_ATTR_EDCCA_CTRL_COMPENSATE,
++
++ /* keep last */
++ NUM_MTK_VENDOR_ATTRS_EDCCA_CTRL,
++ MTK_VENDOR_ATTR_EDCCA_CTRL_MAX =
++ NUM_MTK_VENDOR_ATTRS_EDCCA_CTRL - 1
++};
++
++enum mtk_vendor_attr_edcca_ctrl_mode {
++ EDCCA_CTRL_SET_EN = 0,
++ EDCCA_CTRL_SET_THERS,
++ EDCCA_CTRL_GET_EN,
++ EDCCA_CTRL_GET_THERS,
++ EDCCA_CTRL_NUM,
++};
++
++static struct nla_policy edcca_ctrl_policy[NUM_MTK_VENDOR_ATTRS_EDCCA_CTRL] = {
++ [MTK_VENDOR_ATTR_EDCCA_CTRL_MODE] = { .type = NLA_U8 },
++ [MTK_VENDOR_ATTR_EDCCA_CTRL_PRI20_VAL] = { .type = NLA_U8 },
++ [MTK_VENDOR_ATTR_EDCCA_CTRL_SEC20_VAL] = { .type = NLA_U8 },
++ [MTK_VENDOR_ATTR_EDCCA_CTRL_SEC40_VAL] = { .type = NLA_U8 },
++ [MTK_VENDOR_ATTR_EDCCA_CTRL_SEC80_VAL] = { .type = NLA_U8 },
++ [MTK_VENDOR_ATTR_EDCCA_CTRL_COMPENSATE] = { .type = NLA_U8 },
++};
++
++enum mtk_vendor_attr_csi_ctrl {
++ MTK_VENDOR_ATTR_CSI_CTRL_UNSPEC,
++
++ MTK_VENDOR_ATTR_CSI_CTRL_CFG,
++ MTK_VENDOR_ATTR_CSI_CTRL_CFG_MODE,
++ MTK_VENDOR_ATTR_CSI_CTRL_CFG_TYPE,
++ MTK_VENDOR_ATTR_CSI_CTRL_CFG_VAL1,
++ MTK_VENDOR_ATTR_CSI_CTRL_CFG_VAL2,
++ MTK_VENDOR_ATTR_CSI_CTRL_MAC_ADDR,
++ MTK_VENDOR_ATTR_CSI_CTRL_INTERVAL,
++
++ MTK_VENDOR_ATTR_CSI_CTRL_DUMP_NUM,
++
++ MTK_VENDOR_ATTR_CSI_CTRL_DATA,
++
++ /* keep last */
++ NUM_MTK_VENDOR_ATTRS_CSI_CTRL,
++ MTK_VENDOR_ATTR_CSI_CTRL_MAX =
++ NUM_MTK_VENDOR_ATTRS_CSI_CTRL - 1
++};
++
++enum mtk_vendor_attr_csi_data {
++ MTK_VENDOR_ATTR_CSI_DATA_UNSPEC,
++ MTK_VENDOR_ATTR_CSI_DATA_PAD,
++
++ MTK_VENDOR_ATTR_CSI_DATA_VER,
++ MTK_VENDOR_ATTR_CSI_DATA_TS,
++ MTK_VENDOR_ATTR_CSI_DATA_RSSI,
++ MTK_VENDOR_ATTR_CSI_DATA_SNR,
++ MTK_VENDOR_ATTR_CSI_DATA_BW,
++ MTK_VENDOR_ATTR_CSI_DATA_CH_IDX,
++ MTK_VENDOR_ATTR_CSI_DATA_TA,
++ MTK_VENDOR_ATTR_CSI_DATA_I,
++ MTK_VENDOR_ATTR_CSI_DATA_Q,
++ MTK_VENDOR_ATTR_CSI_DATA_INFO,
++ MTK_VENDOR_ATTR_CSI_DATA_RSVD1,
++ MTK_VENDOR_ATTR_CSI_DATA_RSVD2,
++ MTK_VENDOR_ATTR_CSI_DATA_RSVD3,
++ MTK_VENDOR_ATTR_CSI_DATA_RSVD4,
++ MTK_VENDOR_ATTR_CSI_DATA_TX_ANT,
++ MTK_VENDOR_ATTR_CSI_DATA_RX_ANT,
++ MTK_VENDOR_ATTR_CSI_DATA_MODE,
++ MTK_VENDOR_ATTR_CSI_DATA_H_IDX,
++
++ /* keep last */
++ NUM_MTK_VENDOR_ATTRS_CSI_DATA,
++ MTK_VENDOR_ATTR_CSI_DATA_MAX =
++ NUM_MTK_VENDOR_ATTRS_CSI_DATA - 1
++};
++
++enum mtk_vendor_attr_mnt_ctrl {
++ MTK_VENDOR_ATTR_AMNT_CTRL_UNSPEC,
++
++ MTK_VENDOR_ATTR_AMNT_CTRL_SET,
++ MTK_VENDOR_ATTR_AMNT_CTRL_DUMP,
++ /* keep last */
++ NUM_MTK_VENDOR_ATTRS_AMNT_CTRL,
++ MTK_VENDOR_ATTR_AMNT_CTRL_MAX =
++ NUM_MTK_VENDOR_ATTRS_AMNT_CTRL - 1
++};
++
++enum mtk_vendor_attr_mnt_set {
++ MTK_VENDOR_ATTR_AMNT_SET_UNSPEC,
++
++ MTK_VENDOR_ATTR_AMNT_SET_INDEX,
++ MTK_VENDOR_ATTR_AMNT_SET_MACADDR,
++
++ /* keep last */
++ NUM_MTK_VENDOR_ATTRS_AMNT_SET,
++ MTK_VENDOR_ATTR_AMNT_SET_MAX =
++ NUM_MTK_VENDOR_ATTRS_AMNT_SET - 1
++};
++
++enum mtk_vendor_attr_mnt_dump {
++ MTK_VENDOR_ATTR_AMNT_DUMP_UNSPEC,
++
++ MTK_VENDOR_ATTR_AMNT_DUMP_INDEX,
++ MTK_VENDOR_ATTR_AMNT_DUMP_LEN,
++ MTK_VENDOR_ATTR_AMNT_DUMP_RESULT,
++
++ /* keep last */
++ NUM_MTK_VENDOR_ATTRS_AMNT_DUMP,
++ MTK_VENDOR_ATTR_AMNT_DUMP_MAX =
++ NUM_MTK_VENDOR_ATTRS_AMNT_DUMP - 1
++};
++
++enum mtk_vendor_attr_wireless_ctrl {
++ MTK_VENDOR_ATTR_WIRELESS_CTRL_UNSPEC,
++
++ MTK_VENDOR_ATTR_WIRELESS_CTRL_FIXED_MCS,
++ MTK_VENDOR_ATTR_WIRELESS_CTRL_FIXED_OFDMA,
++ MTK_VENDOR_ATTR_WIRELESS_CTRL_PPDU_TX_TYPE,
++ MTK_VENDOR_ATTR_WIRELESS_CTRL_NUSERS_OFDMA,
++ MTK_VENDOR_ATTR_WIRELESS_CTRL_BA_BUFFER_SIZE,
++ MTK_VENDOR_ATTR_WIRELESS_CTRL_MIMO,
++ MTK_VENDOR_ATTR_WIRELESS_CTRL_AMPDU,
++ MTK_VENDOR_ATTR_WIRELESS_CTRL_AMSDU,
++ MTK_VENDOR_ATTR_WIRELESS_CTRL_CERT,
++
++ /* keep last */
++ NUM_MTK_VENDOR_ATTRS_WIRELESS_CTRL,
++ MTK_VENDOR_ATTR_WIRELESS_CTRL_MAX =
++ NUM_MTK_VENDOR_ATTRS_WIRELESS_CTRL - 1
++};
++
++enum mtk_vendor_attr_rfeature_ctrl {
++ MTK_VENDOR_ATTR_RFEATURE_CTRL_UNSPEC,
++
++ MTK_VENDOR_ATTR_RFEATURE_CTRL_HE_GI,
++ MTK_VENDOR_ATTR_RFEATURE_CTRL_HE_LTF,
++ MTK_VENDOR_ATTR_RFEATURE_CTRL_TRIG_TYPE_CFG,
++ MTK_VENDOR_ATTR_RFEATURE_CTRL_TRIG_TYPE_EN,
++ MTK_VENDOR_ATTR_RFEATURE_CTRL_TRIG_TYPE,
++ MTK_VENDOR_ATTR_RFEATURE_CTRL_ACK_PLCY,
++
++ /* keep last */
++ NUM_MTK_VENDOR_ATTRS_RFEATURE_CTRL,
++ MTK_VENDOR_ATTR_RFEATURE_CTRL_MAX =
++ NUM_MTK_VENDOR_ATTRS_RFEATURE_CTRL - 1
++};
++
++#define CSI_MAX_COUNT 256
++#define ETH_ALEN 6
++
++struct csi_data {
++ s16 data_i[CSI_MAX_COUNT];
++ s16 data_q[CSI_MAX_COUNT];
++ s8 rssi;
++ u8 snr;
++ u32 ts;
++ u8 data_bw;
++ u8 pri_ch_idx;
++ u8 ta[ETH_ALEN];
++ u32 info;
++ u8 rx_mode;
++ u32 h_idx;
++ u16 tx_idx;
++ u16 rx_idx;
++};
++
++struct amnt_data {
++ u8 idx;
++ u8 addr[ETH_ALEN];
++ s8 rssi[4];
++ u32 last_seen;
++};
++#endif /* MTK_VENDOR_H */
+--
+2.18.0
+
diff --git a/autobuild_mac80211_release/package/network/services/hostapd_new/patches/mtk-0005-hostapd-mtk-Support-EDCCA-hostapd-configuration.patch b/autobuild_mac80211_release/package/network/services/hostapd_new/patches/mtk-0005-hostapd-mtk-Support-EDCCA-hostapd-configuration.patch
new file mode 100644
index 0000000..751ad04
--- /dev/null
+++ b/autobuild_mac80211_release/package/network/services/hostapd_new/patches/mtk-0005-hostapd-mtk-Support-EDCCA-hostapd-configuration.patch
@@ -0,0 +1,618 @@
+From 15420724ea5d0aef0296e562c96be19262485575 Mon Sep 17 00:00:00 2001
+From: Howard Hsu <howard-yh.hsu@mediatek.com>
+Date: Mon, 30 May 2022 16:31:34 +0800
+Subject: [PATCH 05/28] hostapd: mtk: Support EDCCA hostapd configuration
+
+edcca_enable and edcca_compensation and implement edcca related handlers.
+---
+ hostapd/config_file.c | 32 ++++++
+ hostapd/ctrl_iface.c | 125 ++++++++++++++++++++++
+ src/ap/ap_config.c | 4 +
+ src/ap/ap_config.h | 29 ++++++
+ src/ap/ap_drv_ops.c | 24 +++++
+ src/ap/ap_drv_ops.h | 4 +
+ src/ap/hostapd.c | 7 ++
+ src/common/mtk_vendor.h | 19 ++--
+ src/drivers/driver.h | 4 +
+ src/drivers/driver_nl80211.c | 165 ++++++++++++++++++++++++++++++
+ src/drivers/driver_nl80211.h | 1 +
+ src/drivers/driver_nl80211_capa.c | 7 ++
+ 12 files changed, 415 insertions(+), 6 deletions(-)
+
+diff --git a/hostapd/config_file.c b/hostapd/config_file.c
+index 11a3a1a..a48034b 100644
+--- a/hostapd/config_file.c
++++ b/hostapd/config_file.c
+@@ -4799,6 +4799,38 @@ static int hostapd_config_fill(struct hostapd_config *conf,
+ }
+ conf->punct_acs_threshold = val;
+ #endif /* CONFIG_IEEE80211BE */
++ } else if (os_strcmp(buf, "edcca_threshold") == 0) {
++ if (hostapd_parse_intlist(&conf->edcca_threshold, pos) ||
++ conf->edcca_threshold[0] < EDCCA_MIN_CONFIG_THRES ||
++ conf->edcca_threshold[0] > EDCCA_MAX_CONFIG_THRES ||
++ conf->edcca_threshold[1] < EDCCA_MIN_CONFIG_THRES ||
++ conf->edcca_threshold[1] > EDCCA_MAX_CONFIG_THRES ||
++ conf->edcca_threshold[2] < EDCCA_MIN_CONFIG_THRES ||
++ conf->edcca_threshold[2] > EDCCA_MAX_CONFIG_THRES) {
++ wpa_printf(MSG_ERROR, "Line %d: invalid edcca threshold",
++ line);
++ return 1;
++ }
++ } else if (os_strcmp(buf, "edcca_enable") == 0) {
++ int mode = atoi(pos);
++ if (mode < EDCCA_MODE_FORCE_DISABLE || mode > EDCCA_MODE_AUTO) {
++ wpa_printf(MSG_ERROR, "Line %d: Invalid edcca_enable %d;"
++ " allowed value 0 (Force Disable) or 1(Auto) ",
++ line, mode);
++ return 1;
++ }
++ conf->edcca_enable = (u8) mode;
++ } else if (os_strcmp(buf, "edcca_compensation") == 0) {
++ int val = atoi(pos);
++ if (val < EDCCA_MIN_COMPENSATION ||
++ val > EDCCA_MAX_COMPENSATION) {
++ wpa_printf(MSG_ERROR, "Line %d: Invalid compensation"
++ " value %d; allowed value %d ~ %d.",
++ line, val, EDCCA_MIN_COMPENSATION,
++ EDCCA_MAX_COMPENSATION);
++ return 1;
++ }
++ conf->edcca_compensation = (s8) val;
+ } else {
+ wpa_printf(MSG_ERROR,
+ "Line %d: unknown configuration item '%s'",
+diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
+index c4e344e..c5c0e91 100644
+--- a/hostapd/ctrl_iface.c
++++ b/hostapd/ctrl_iface.c
+@@ -599,6 +599,19 @@ static const char * pbc_status_str(enum pbc_status status)
+ }
+
+
++static const char * edcca_mode_str(enum edcca_mode status)
++{
++ switch (status) {
++ case EDCCA_MODE_FORCE_DISABLE:
++ return "Force Disable";
++ case EDCCA_MODE_AUTO:
++ return "Auto";
++ default:
++ return "Unknown";
++ }
++}
++
++
+ static int hostapd_ctrl_iface_wps_get_status(struct hostapd_data *hapd,
+ char *buf, size_t buflen)
+ {
+@@ -3397,6 +3410,112 @@ static int hostapd_ctrl_iface_driver_cmd(struct hostapd_data *hapd, char *cmd,
+ #endif /* ANDROID */
+
+
++static int
++hostapd_ctrl_iface_set_edcca(struct hostapd_data *hapd, char *cmd,
++ char *buf, size_t buflen)
++{
++ char *pos, *config, *value;
++ config = cmd;
++ pos = os_strchr(config, ' ');
++ if (pos == NULL)
++ return -1;
++ *pos++ = '\0';
++
++ if(pos == NULL)
++ return -1;
++ value = pos;
++
++ if (os_strcmp(config, "enable") == 0) {
++ int mode = atoi(value);
++ if (mode < EDCCA_MODE_FORCE_DISABLE || mode > EDCCA_MODE_AUTO) {
++ wpa_printf(MSG_ERROR, "Invalid value for edcca enable");
++ return -1;
++ }
++ hapd->iconf->edcca_enable = (u8) mode;
++ if (hostapd_drv_configure_edcca_enable(hapd) != 0)
++ return -1;
++ } else if (os_strcmp(config, "compensation") == 0) {
++ int compensation = atoi(value);
++ if (compensation < EDCCA_MIN_COMPENSATION ||
++ compensation > EDCCA_MAX_COMPENSATION) {
++ wpa_printf(MSG_ERROR, "Invalid value for edcca compensation");
++ return -1;
++ }
++ hapd->iconf->edcca_compensation = (s8) compensation;
++ if (hostapd_drv_configure_edcca_enable(hapd) != 0)
++ return -1;
++ } else if (os_strcmp(config, "threshold") == 0) {
++ char *thres_value;
++ thres_value = os_strchr(value, ':');
++ if (thres_value == NULL)
++ return -1;
++ *thres_value++ = '\0';
++
++ if(thres_value == NULL)
++ return -1;
++ int bw_idx= atoi(value);
++ int threshold = atoi(thres_value);
++
++ if (bw_idx < EDCCA_BW_20 || bw_idx > EDCCA_BW_80) {
++ wpa_printf(MSG_ERROR,
++ "Unsupported Bandwidth idx %d for SET_EDCCA",
++ bw_idx);
++ return -1;
++ }
++ if (threshold < EDCCA_MIN_CONFIG_THRES ||
++ threshold > EDCCA_MAX_CONFIG_THRES) {
++ wpa_printf(MSG_ERROR,
++ "Unsupported threshold %d for SET_EDCCA",
++ threshold);
++ return -1;
++ }
++
++ int threshold_arr[EDCCA_MAX_BW_NUM];
++ /* 0x7f means keep the origival value in firmware */
++ os_memset(threshold_arr, 0x7f, sizeof(threshold_arr));
++ threshold_arr[bw_idx] = threshold;
++
++ if (hostapd_drv_configure_edcca_threshold(hapd, threshold_arr) != 0)
++ return -1;
++ } else {
++ wpa_printf(MSG_ERROR,
++ "Unsupported parameter %s for SET_EDCCA", config);
++ return -1;
++ }
++ return os_snprintf(buf, buflen, "OK\n");
++}
++
++
++static int
++hostapd_ctrl_iface_get_edcca(struct hostapd_data *hapd, char *cmd, char *buf,
++ size_t buflen)
++{
++ char *pos, *end;
++
++ pos = buf;
++ end = buf + buflen;
++ u8 value[EDCCA_MAX_BW_NUM] = {0};
++
++ if (os_strcmp(cmd, "enable") == 0) {
++ return os_snprintf(pos, end - pos, "Enable: %s\n",
++ edcca_mode_str(hapd->iconf->edcca_enable));
++ } else if (os_strcmp(cmd, "compensation") == 0) {
++ return os_snprintf(pos, end - pos, "Compensation: %d\n",
++ hapd->iconf->edcca_compensation);
++ } else if (os_strcmp(cmd, "threshold") == 0) {
++ if (hostapd_drv_get_edcca(hapd, EDCCA_CTRL_GET_THRES, &value) != 0)
++ return -1;
++ return os_snprintf(pos, end - pos,
++ "Threshold BW20: 0x%x, BW40: 0x%x, BW80: 0x%x\n",
++ value[0], value[1], value[2]);
++ } else {
++ wpa_printf(MSG_ERROR,
++ "Unsupported parameter %s for GET_EDCCA", cmd);
++ return -1;
++ }
++}
++
++
+ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
+ char *buf, char *reply,
+ int reply_size,
+@@ -3952,6 +4071,12 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
+ reply_len = hostapd_ctrl_iface_driver_cmd(hapd, buf + 7, reply,
+ reply_size);
+ #endif /* ANDROID */
++ } else if (os_strncmp(buf, "SET_EDCCA ", 10) == 0) {
++ reply_len = hostapd_ctrl_iface_set_edcca(hapd, buf+10, reply,
++ reply_size);
++ } else if (os_strncmp(buf, "GET_EDCCA ", 10) == 0) {
++ reply_len = hostapd_ctrl_iface_get_edcca(hapd, buf+10, reply,
++ reply_size);
+ } else {
+ os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
+ reply_len = 16;
+diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
+index 9f450f6..55c35c7 100644
+--- a/src/ap/ap_config.c
++++ b/src/ap/ap_config.c
+@@ -294,6 +294,9 @@ struct hostapd_config * hostapd_config_defaults(void)
+ conf->airtime_update_interval = AIRTIME_DEFAULT_UPDATE_INTERVAL;
+ #endif /* CONFIG_AIRTIME_POLICY */
+
++ conf->edcca_enable = EDCCA_MODE_AUTO;
++ conf->edcca_compensation = EDCCA_DEFAULT_COMPENSATION;
++
+ return conf;
+ }
+
+@@ -1008,6 +1011,7 @@ void hostapd_config_free(struct hostapd_config *conf)
+ #ifdef CONFIG_ACS
+ os_free(conf->acs_chan_bias);
+ #endif /* CONFIG_ACS */
++ os_free(conf->edcca_threshold);
+ wpabuf_free(conf->lci);
+ wpabuf_free(conf->civic);
+
+diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
+index af9bf92..22b1276 100644
+--- a/src/ap/ap_config.h
++++ b/src/ap/ap_config.h
+@@ -1180,8 +1180,37 @@ struct hostapd_config {
+ MBSSID_ENABLED = 1,
+ ENHANCED_MBSSID_ENABLED = 2,
+ } mbssid;
++
++ u8 edcca_enable;
++ s8 edcca_compensation;
++ int *edcca_threshold;
++};
++
++enum edcca_mode {
++ EDCCA_MODE_FORCE_DISABLE = 0,
++ EDCCA_MODE_AUTO = 1,
++};
++
++enum edcca_bw_id {
++ EDCCA_BW_20 = 0,
++ EDCCA_BW_40,
++ EDCCA_BW_80,
++ EDCCA_MAX_BW_NUM,
++};
++
++enum mtk_vendor_attr_edcca_ctrl_mode {
++ EDCCA_CTRL_SET_EN = 0,
++ EDCCA_CTRL_SET_THRES,
++ EDCCA_CTRL_GET_EN,
++ EDCCA_CTRL_GET_THRES,
++ EDCCA_CTRL_NUM,
+ };
+
++#define EDCCA_DEFAULT_COMPENSATION -6
++#define EDCCA_MIN_COMPENSATION -126
++#define EDCCA_MAX_COMPENSATION 126
++#define EDCCA_MIN_CONFIG_THRES -126
++#define EDCCA_MAX_CONFIG_THRES 0
+
+ static inline enum oper_chan_width
+ hostapd_get_oper_chwidth(struct hostapd_config *conf)
+diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c
+index ab84a63..af6944b 100644
+--- a/src/ap/ap_drv_ops.c
++++ b/src/ap/ap_drv_ops.c
+@@ -1054,3 +1054,27 @@ int hostapd_drv_set_secure_ranging_ctx(struct hostapd_data *hapd,
+ return hapd->driver->set_secure_ranging_ctx(hapd->drv_priv, ¶ms);
+ }
+ #endif /* CONFIG_PASN */
++
++int hostapd_drv_configure_edcca_enable(struct hostapd_data *hapd)
++{
++ if (!hapd->driver || !hapd->driver->configure_edcca_enable)
++ return 0;
++ return hapd->driver->configure_edcca_enable(hapd->drv_priv,
++ hapd->iconf->edcca_enable,
++ hapd->iconf->edcca_compensation);
++}
++
++int hostapd_drv_configure_edcca_threshold(struct hostapd_data *hapd,
++ const int *threshold)
++{
++ if (!hapd->driver || !hapd->driver->configure_edcca_threshold)
++ return 0;
++ return hapd->driver->configure_edcca_threshold(hapd->drv_priv, threshold);
++}
++
++int hostapd_drv_get_edcca(struct hostapd_data *hapd, const u8 mode, u8 *value)
++{
++ if (!hapd->driver || !hapd->driver->get_edcca)
++ return 0;
++ return hapd->driver->get_edcca(hapd->drv_priv, mode, value);
++}
+diff --git a/src/ap/ap_drv_ops.h b/src/ap/ap_drv_ops.h
+index 93b2244..b89ad6e 100644
+--- a/src/ap/ap_drv_ops.h
++++ b/src/ap/ap_drv_ops.h
+@@ -144,6 +144,10 @@ int hostapd_drv_set_secure_ranging_ctx(struct hostapd_data *hapd,
+ u8 ltf_keyseed_len,
+ const u8 *ltf_keyseed, u32 action);
+
++int hostapd_drv_configure_edcca_enable(struct hostapd_data *hapd);
++int hostapd_drv_configure_edcca_threshold(struct hostapd_data *hapd,
++ const int *threshold);
++int hostapd_drv_get_edcca(struct hostapd_data *hapd, const u8 mode, u8 *value);
+
+ #include "drivers/driver.h"
+
+diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
+index f5da65a..cd0a0c9 100644
+--- a/src/ap/hostapd.c
++++ b/src/ap/hostapd.c
+@@ -2390,6 +2390,13 @@ dfs_offload:
+ }
+ #endif /* CONFIG_MESH */
+
++ if (hostapd_drv_configure_edcca_enable(hapd) < 0)
++ goto fail;
++
++ if (hostapd_drv_configure_edcca_threshold(hapd,
++ hapd->iconf->edcca_threshold) < 0)
++ goto fail;
++
+ wpa_printf(MSG_DEBUG, "%s: Setup of interface done.",
+ iface->bss[0]->conf->iface);
+ if (iface->interfaces && iface->interfaces->terminate_on_error > 0)
+diff --git a/src/common/mtk_vendor.h b/src/common/mtk_vendor.h
+index 528387f..7056126 100644
+--- a/src/common/mtk_vendor.h
++++ b/src/common/mtk_vendor.h
+@@ -29,14 +29,21 @@ enum mtk_vendor_attr_edcca_ctrl {
+ NUM_MTK_VENDOR_ATTRS_EDCCA_CTRL - 1
+ };
+
+-enum mtk_vendor_attr_edcca_ctrl_mode {
+- EDCCA_CTRL_SET_EN = 0,
+- EDCCA_CTRL_SET_THERS,
+- EDCCA_CTRL_GET_EN,
+- EDCCA_CTRL_GET_THERS,
+- EDCCA_CTRL_NUM,
++enum mtk_vendor_attr_edcca_dump {
++ MTK_VENDOR_ATTR_EDCCA_DUMP_UNSPEC = 0,
++
++ MTK_VENDOR_ATTR_EDCCA_DUMP_MODE,
++ MTK_VENDOR_ATTR_EDCCA_DUMP_PRI20_VAL,
++ MTK_VENDOR_ATTR_EDCCA_DUMP_SEC40_VAL,
++ MTK_VENDOR_ATTR_EDCCA_DUMP_SEC80_VAL,
++
++ /* keep last */
++ NUM_MTK_VENDOR_ATTRS_EDCCA_DUMP,
++ MTK_VENDOR_ATTR_EDCCA_DUMP_MAX =
++ NUM_MTK_VENDOR_ATTRS_EDCCA_DUMP - 1
+ };
+
++
+ static struct nla_policy edcca_ctrl_policy[NUM_MTK_VENDOR_ATTRS_EDCCA_CTRL] = {
+ [MTK_VENDOR_ATTR_EDCCA_CTRL_MODE] = { .type = NLA_U8 },
+ [MTK_VENDOR_ATTR_EDCCA_CTRL_PRI20_VAL] = { .type = NLA_U8 },
+diff --git a/src/drivers/driver.h b/src/drivers/driver.h
+index 2f91d30..73c7bb4 100644
+--- a/src/drivers/driver.h
++++ b/src/drivers/driver.h
+@@ -5001,6 +5001,10 @@ struct wpa_driver_ops {
+ const u8 *match, size_t match_len,
+ bool multicast);
+ #endif /* CONFIG_TESTING_OPTIONS */
++ int (*configure_edcca_enable)(void *priv, const u8 edcca_enable,
++ const s8 edcca_compensation);
++ int (*configure_edcca_threshold)(void *priv, const int *threshold);
++ int (*get_edcca)(void *priv, const u8 mode, u8 *value);
+ };
+
+ /**
+diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
+index d79929b..f5c95e1 100644
+--- a/src/drivers/driver_nl80211.c
++++ b/src/drivers/driver_nl80211.c
+@@ -37,6 +37,8 @@
+ #include "radiotap_iter.h"
+ #include "rfkill.h"
+ #include "driver_nl80211.h"
++#include "common/mtk_vendor.h"
++#include "ap/ap_config.h"
+
+
+ #ifndef NETLINK_CAP_ACK
+@@ -13366,6 +13368,165 @@ static int testing_nl80211_radio_disable(void *priv, int disabled)
+
+ #endif /* CONFIG_TESTING_OPTIONS */
+
++static int nl80211_configure_edcca_enable(void *priv,
++ const u8 edcca_enable,
++ const s8 edcca_compensation)
++{
++ struct i802_bss *bss = priv;
++ struct wpa_driver_nl80211_data *drv = bss->drv;
++ struct nl_msg *msg;
++ struct nlattr *data;
++ int ret;
++
++ if (!drv->mtk_edcca_vendor_cmd_avail) {
++ wpa_printf(MSG_INFO,
++ "nl80211: Driver does not support setting EDCCA enable");
++ return 0;
++ }
++
++ if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR)) ||
++ nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_MTK) ||
++ nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
++ MTK_NL80211_VENDOR_SUBCMD_EDCCA_CTRL) ||
++ !(data = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA)) ||
++ nla_put_u8(msg, MTK_VENDOR_ATTR_EDCCA_CTRL_MODE, EDCCA_CTRL_SET_EN) ||
++ nla_put_u8(msg, MTK_VENDOR_ATTR_EDCCA_CTRL_PRI20_VAL, edcca_enable) ||
++ nla_put_u8(msg, MTK_VENDOR_ATTR_EDCCA_CTRL_COMPENSATE,
++ edcca_compensation)) {
++ wpa_printf (MSG_ERROR, "Prepare nl80211 msg fail");
++ nlmsg_free(msg);
++ return -ENOBUFS;
++ }
++ nla_nest_end(msg, data);
++ ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
++ if (ret) {
++ wpa_printf(MSG_ERROR, "Failed to configure EDCCA enable. ret=%d (%s) ",
++ ret, strerror(-ret));
++ }
++ return ret;
++}
++
++static int nl80211_configure_edcca_threshold(void *priv, const int *threshold)
++{
++ struct i802_bss *bss = priv;
++ struct wpa_driver_nl80211_data *drv = bss->drv;
++ struct nl_msg *msg;
++ struct nlattr *data;
++ int ret;
++
++ if (!drv->mtk_edcca_vendor_cmd_avail) {
++ wpa_printf(MSG_INFO,
++ "nl80211: Driver does not support setting EDCCA threshold");
++ return 0;
++ }
++
++ if (!threshold) {
++ wpa_printf(MSG_INFO,
++ "nl80211: Input EDCCA threshold is empty!");
++ return 0;
++ }
++
++ if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR)) ||
++ nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_MTK) ||
++ nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
++ MTK_NL80211_VENDOR_SUBCMD_EDCCA_CTRL) ||
++ !(data = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA)) ||
++ nla_put_u8(msg, MTK_VENDOR_ATTR_EDCCA_CTRL_MODE, EDCCA_CTRL_SET_THRES) ||
++ nla_put_u8(msg, MTK_VENDOR_ATTR_EDCCA_CTRL_PRI20_VAL, threshold[0] & 0xff) ||
++ nla_put_u8(msg, MTK_VENDOR_ATTR_EDCCA_CTRL_SEC40_VAL, threshold[1] & 0xff) ||
++ nla_put_u8(msg, MTK_VENDOR_ATTR_EDCCA_CTRL_SEC80_VAL, threshold[2] & 0xff)) {
++ wpa_printf (MSG_ERROR, "Prepare nl80211 msg fail");
++ nlmsg_free(msg);
++ return -ENOBUFS;
++ }
++ nla_nest_end(msg, data);
++ ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
++ if (ret) {
++ wpa_printf(MSG_ERROR, "Failed to configure EDCCA threshold. ret=%d (%s) ",
++ ret, strerror(-ret));
++ }
++ return ret;
++}
++
++
++static int edcca_info_handler(struct nl_msg *msg, void *arg)
++{
++ u8 *info = (u8*) arg;
++ struct nlattr *tb[NL80211_ATTR_MAX + 1];
++ struct nlattr *tb_vendor[MTK_VENDOR_ATTR_EDCCA_DUMP_MAX + 1];
++ struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
++ struct nlattr *nl_vend, *attr;
++
++ nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
++ genlmsg_attrlen(gnlh, 0), NULL);
++
++ nl_vend = tb[NL80211_ATTR_VENDOR_DATA];
++ if (!nl_vend)
++ return NL_SKIP;
++
++ nla_parse(tb_vendor, MTK_VENDOR_ATTR_EDCCA_DUMP_MAX,
++ nla_data(nl_vend), nla_len(nl_vend), NULL);
++
++ attr = tb_vendor[MTK_VENDOR_ATTR_EDCCA_DUMP_PRI20_VAL];
++ if (!attr) {
++ wpa_printf(MSG_ERROR, "nl80211: MTK_VENDOR_ATTR_EDCCA_DUMP_PRI20_VAL");
++ return NL_SKIP;
++ }
++
++ *info++ = nla_get_u8(attr);
++
++ attr = tb_vendor[MTK_VENDOR_ATTR_EDCCA_DUMP_SEC40_VAL];
++ if (!attr) {
++ wpa_printf(MSG_ERROR, "nl80211: MTK_VENDOR_ATTR_EDCCA_DUMP_SEC40_VAL");
++ return NL_SKIP;
++ }
++
++ *info++ = nla_get_u8(attr);
++
++ attr = tb_vendor[MTK_VENDOR_ATTR_EDCCA_DUMP_SEC80_VAL];
++ if (!attr) {
++ wpa_printf(MSG_ERROR, "nl80211: MTK_VENDOR_ATTR_EDCCA_DUMP_SEC80_VAL");
++ return NL_SKIP;
++ }
++
++ *info = nla_get_u8(attr);
++ return NL_SKIP;
++}
++
++
++static int nl80211_get_edcca(void *priv, const u8 mode, u8 *value)
++{
++ struct i802_bss *bss = priv;
++ struct wpa_driver_nl80211_data *drv = bss->drv;
++ struct nl_msg *msg;
++ struct nlattr *data;
++ int ret;
++
++ if (!drv->mtk_edcca_vendor_cmd_avail) {
++ wpa_printf(MSG_INFO,
++ "nl80211: Driver does not support setting EDCCA threshold");
++ return 0;
++ }
++
++ if (!(msg = nl80211_drv_msg(drv, NLM_F_DUMP, NL80211_CMD_VENDOR)) ||
++ nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_MTK) ||
++ nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
++ MTK_NL80211_VENDOR_SUBCMD_EDCCA_CTRL) ||
++ !(data = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA | NLA_F_NESTED)) ||
++ nla_put_u8(msg, MTK_VENDOR_ATTR_EDCCA_CTRL_MODE, mode)) {
++ wpa_printf (MSG_ERROR, "Prepare nl80211 msg fail");
++ nlmsg_free(msg);
++ return -ENOBUFS;
++ }
++ nla_nest_end(msg, data);
++ ret = send_and_recv_msgs(drv, msg, edcca_info_handler, value, NULL, NULL);
++ if (ret) {
++ wpa_printf(MSG_ERROR, "Failed to get EDCCA configuration. ret=%d (%s)",
++ ret, strerror(-ret));
++ }
++ return ret;
++}
++
+
+ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
+ .name = "nl80211",
+@@ -13519,4 +13680,8 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
+ .register_frame = testing_nl80211_register_frame,
+ .radio_disable = testing_nl80211_radio_disable,
+ #endif /* CONFIG_TESTING_OPTIONS */
++/* Need ifdef CONFIG_DRIVER_NL80211_MTK */
++ .configure_edcca_enable = nl80211_configure_edcca_enable,
++ .configure_edcca_threshold = nl80211_configure_edcca_threshold,
++ .get_edcca = nl80211_get_edcca,
+ };
+diff --git a/src/drivers/driver_nl80211.h b/src/drivers/driver_nl80211.h
+index 8bfbdd5..55c29cc 100644
+--- a/src/drivers/driver_nl80211.h
++++ b/src/drivers/driver_nl80211.h
+@@ -199,6 +199,7 @@ struct wpa_driver_nl80211_data {
+ unsigned int uses_6ghz:1;
+ unsigned int secure_ranging_ctx_vendor_cmd_avail:1;
+ unsigned int puncturing:1;
++ unsigned int mtk_edcca_vendor_cmd_avail:1;
+
+ u64 vendor_scan_cookie;
+ u64 remain_on_chan_cookie;
+diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c
+index 27ab1d9..efe7ae4 100644
+--- a/src/drivers/driver_nl80211_capa.c
++++ b/src/drivers/driver_nl80211_capa.c
+@@ -18,6 +18,7 @@
+ #include "common/qca-vendor-attr.h"
+ #include "common/brcm_vendor.h"
+ #include "driver_nl80211.h"
++#include "common/mtk_vendor.h"
+
+
+ static int protocol_feature_handler(struct nl_msg *msg, void *arg)
+@@ -1099,6 +1100,12 @@ static int wiphy_info_handler(struct nl_msg *msg, void *arg)
+ break;
+ }
+ #endif /* CONFIG_DRIVER_NL80211_BRCM */
++ } else if (vinfo->vendor_id == OUI_MTK) {
++ switch (vinfo->subcmd) {
++ case MTK_NL80211_VENDOR_SUBCMD_EDCCA_CTRL :
++ drv->mtk_edcca_vendor_cmd_avail = 1;
++ break;
++ }
+ }
+
+ wpa_printf(MSG_DEBUG, "nl80211: Supported vendor command: vendor_id=0x%x subcmd=%u",
+--
+2.18.0
+
diff --git a/autobuild_mac80211_release/package/network/services/hostapd_new/patches/mtk-0006-hostapd-mtk-Add-hostapd-MU-SET-GET-control.patch b/autobuild_mac80211_release/package/network/services/hostapd_new/patches/mtk-0006-hostapd-mtk-Add-hostapd-MU-SET-GET-control.patch
new file mode 100644
index 0000000..a79555a
--- /dev/null
+++ b/autobuild_mac80211_release/package/network/services/hostapd_new/patches/mtk-0006-hostapd-mtk-Add-hostapd-MU-SET-GET-control.patch
@@ -0,0 +1,450 @@
+From fd2df638591cc86c21153e94abe8fc00451703b8 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/28] hostapd: mtk: Add hostapd MU SET/GET control
+
+---
+ hostapd/config_file.c | 9 +++
+ hostapd/ctrl_iface.c | 62 +++++++++++++++++
+ hostapd/hostapd_cli.c | 18 +++++
+ src/ap/ap_config.c | 1 +
+ src/ap/ap_config.h | 1 +
+ src/ap/ap_drv_ops.c | 14 ++++
+ src/ap/ap_drv_ops.h | 2 +
+ src/ap/hostapd.c | 2 +
+ src/common/mtk_vendor.h | 15 ++++
+ src/drivers/driver.h | 13 ++++
+ src/drivers/driver_nl80211.c | 110 ++++++++++++++++++++++++++++++
+ src/drivers/driver_nl80211.h | 1 +
+ src/drivers/driver_nl80211_capa.c | 3 +
+ 13 files changed, 251 insertions(+)
+
+diff --git a/hostapd/config_file.c b/hostapd/config_file.c
+index a48034b..12741f8 100644
+--- a/hostapd/config_file.c
++++ b/hostapd/config_file.c
+@@ -3679,6 +3679,15 @@ static int hostapd_config_fill(struct hostapd_config *conf,
+ return 1;
+ }
+ conf->mbssid = mbssid;
++ } else if (os_strcmp(buf, "mu_onoff") == 0) {
++ int val = atoi(pos);
++ if (val < 0 || val > 15) {
++ wpa_printf(MSG_ERROR,
++ "Line %d: invalid mu_onoff value",
++ line);
++ return 1;
++ }
++ conf->mu_onoff = val;
+ #endif /* CONFIG_IEEE80211AX */
+ } 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 c5c0e91..b317a65 100644
+--- a/hostapd/ctrl_iface.c
++++ b/hostapd/ctrl_iface.c
+@@ -3516,6 +3516,63 @@ hostapd_ctrl_iface_get_edcca(struct hostapd_data *hapd, char *cmd, char *buf,
+ }
+
+
++static int
++hostapd_ctrl_iface_set_mu(struct hostapd_data *hapd, char *cmd,
++ char *buf, size_t buflen)
++{
++ char *pos, *config, *value;
++ config = cmd;
++ pos = os_strchr(config, ' ');
++ if (pos == NULL)
++ return -1;
++ *pos++ = '\0';
++
++ if(pos == NULL)
++ return -1;
++ value = pos;
++
++ if (os_strcmp(config, "onoff") == 0) {
++ int mu = atoi(value);
++ if (mu < 0 || mu > 15) {
++ wpa_printf(MSG_ERROR, "Invalid value for mu");
++ return -1;
++ }
++ hapd->iconf->mu_onoff = (u8) mu;
++ } else {
++ wpa_printf(MSG_ERROR,
++ "Unsupported parameter %s for SET_MU", config);
++ return -1;
++ }
++
++ if(hostapd_drv_mu_ctrl(hapd) == 0) {
++ return os_snprintf(buf, buflen, "OK\n");
++ } else {
++ return -1;
++ }
++}
++
++
++static int
++hostapd_ctrl_iface_get_mu(struct hostapd_data *hapd, char *buf,
++ size_t buflen)
++{
++ u8 mu_onoff;
++ char *pos, *end;
++
++ pos = buf;
++ end = buf + buflen;
++
++ 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",
++ !!(mu_onoff&BIT(3)), !!(mu_onoff&BIT(2)), !!(mu_onoff&BIT(1)), !!(mu_onoff&BIT(0)));
++ } else {
++ wpa_printf(MSG_INFO, "ctrl iface failed to call");
++ return -1;
++ }
++}
++
++
+ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
+ char *buf, char *reply,
+ int reply_size,
+@@ -4077,6 +4134,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);
++ } else if (os_strncmp(buf, "SET_MU ", 7) == 0) {
++ reply_len = hostapd_ctrl_iface_set_mu(hapd, buf + 7, reply,
++ reply_size);
++ } else if (os_strncmp(buf, "GET_MU", 6) == 0) {
++ reply_len = hostapd_ctrl_iface_get_mu(hapd, reply, reply_size);
+ } else {
+ os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
+ reply_len = 16;
+diff --git a/hostapd/hostapd_cli.c b/hostapd/hostapd_cli.c
+index 05ac5ac..285aeba 100644
+--- a/hostapd/hostapd_cli.c
++++ b/hostapd/hostapd_cli.c
+@@ -1400,6 +1400,20 @@ static int hostapd_cli_cmd_driver_flags(struct wpa_ctrl *ctrl, int argc,
+ }
+
+
++static int hostapd_cli_cmd_set_mu(struct wpa_ctrl *ctrl, int argc,
++ char *argv[])
++{
++ return hostapd_cli_cmd(ctrl, "SET_MU", 1, argc, argv);
++}
++
++
++static int hostapd_cli_cmd_get_mu(struct wpa_ctrl *ctrl, int argc,
++ char *argv[])
++{
++ return hostapd_cli_cmd(ctrl, "GET_MU", 0, NULL, NULL);
++}
++
++
+ #ifdef CONFIG_DPP
+
+ static int hostapd_cli_cmd_dpp_qr_code(struct wpa_ctrl *ctrl, int argc,
+@@ -1729,6 +1743,10 @@ static const struct hostapd_cli_cmd hostapd_cli_commands[] = {
+ " = send FTM range request"},
+ { "driver_flags", hostapd_cli_cmd_driver_flags, NULL,
+ " = show supported driver flags"},
++ { "set_mu", hostapd_cli_cmd_set_mu, NULL,
++ "<value> [0-15] bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0)"},
++ { "get_mu", hostapd_cli_cmd_get_mu, NULL,
++ " = show mu onoff value in 0-15 bitmap"},
+ #ifdef CONFIG_DPP
+ { "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 55c35c7..1cad303 100644
+--- a/src/ap/ap_config.c
++++ b/src/ap/ap_config.c
+@@ -280,6 +280,7 @@ struct hostapd_config * hostapd_config_defaults(void)
+ conf->he_6ghz_max_ampdu_len_exp = 7;
+ conf->he_6ghz_rx_ant_pat = 1;
+ conf->he_6ghz_tx_ant_pat = 1;
++ conf->mu_onoff = 13;
+ #endif /* CONFIG_IEEE80211AX */
+
+ /* The third octet of the country string uses an ASCII space character
+diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
+index 22b1276..2077c67 100644
+--- a/src/ap/ap_config.h
++++ b/src/ap/ap_config.h
+@@ -1133,6 +1133,7 @@ struct hostapd_config {
+ u8 he_6ghz_tx_ant_pat;
+ u8 he_6ghz_reg_pwr_type;
+ bool require_he;
++ u8 mu_onoff;
+ #endif /* CONFIG_IEEE80211AX */
+
+ /* VHT enable/disable config from CHAN_SWITCH */
+diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c
+index af6944b..d290a00 100644
+--- a/src/ap/ap_drv_ops.c
++++ b/src/ap/ap_drv_ops.c
+@@ -1078,3 +1078,17 @@ int hostapd_drv_get_edcca(struct hostapd_data *hapd, const u8 mode, u8 *value)
+ return 0;
+ return hapd->driver->get_edcca(hapd->drv_priv, mode, value);
+ }
++
++int hostapd_drv_mu_ctrl(struct hostapd_data *hapd)
++{
++ if (!hapd->driver || !hapd->driver->mu_ctrl)
++ return 0;
++ return hapd->driver->mu_ctrl(hapd->drv_priv, hapd->iconf->mu_onoff);
++}
++
++int hostapd_drv_mu_dump(struct hostapd_data *hapd, u8 *mu_onoff)
++{
++ if (!hapd->driver || !hapd->driver->mu_dump)
++ return 0;
++ return hapd->driver->mu_dump(hapd->drv_priv, mu_onoff);
++}
+diff --git a/src/ap/ap_drv_ops.h b/src/ap/ap_drv_ops.h
+index b89ad6e..1565bfa 100644
+--- a/src/ap/ap_drv_ops.h
++++ b/src/ap/ap_drv_ops.h
+@@ -148,6 +148,8 @@ int hostapd_drv_configure_edcca_enable(struct hostapd_data *hapd);
+ int hostapd_drv_configure_edcca_threshold(struct hostapd_data *hapd,
+ const int *threshold);
+ int hostapd_drv_get_edcca(struct hostapd_data *hapd, const u8 mode, u8 *value);
++int hostapd_drv_mu_ctrl(struct hostapd_data *hapd);
++int hostapd_drv_mu_dump(struct hostapd_data *hapd, u8 *mu_onoff);
+
+ #include "drivers/driver.h"
+
+diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
+index cd0a0c9..21aba48 100644
+--- a/src/ap/hostapd.c
++++ b/src/ap/hostapd.c
+@@ -2396,6 +2396,8 @@ dfs_offload:
+ if (hostapd_drv_configure_edcca_threshold(hapd,
+ hapd->iconf->edcca_threshold) < 0)
+ goto fail;
++ if (hostapd_drv_mu_ctrl(hapd) < 0)
++ goto fail;
+
+ wpa_printf(MSG_DEBUG, "%s: Setup of interface done.",
+ iface->bss[0]->conf->iface);
+diff --git a/src/common/mtk_vendor.h b/src/common/mtk_vendor.h
+index 7056126..ef8618e 100644
+--- a/src/common/mtk_vendor.h
++++ b/src/common/mtk_vendor.h
+@@ -10,6 +10,8 @@ enum mtk_nl80211_vendor_subcmds {
+ MTK_NL80211_VENDOR_SUBCMD_CSI_CTRL = 0xc2,
+ MTK_NL80211_VENDOR_SUBCMD_RFEATURE_CTRL = 0xc3,
+ MTK_NL80211_VENDOR_SUBCMD_WIRELESS_CTRL = 0xc4,
++ MTK_NL80211_VENDOR_SUBCMD_MU_CTRL = 0xc5,
++ MTK_NL80211_VENDOR_SUBCMD_PHY_CAPA_CTRL= 0xc6,
+ MTK_NL80211_VENDOR_SUBCMD_EDCCA_CTRL = 0xc7,
+ };
+
+@@ -174,6 +176,19 @@ enum mtk_vendor_attr_rfeature_ctrl {
+ NUM_MTK_VENDOR_ATTRS_RFEATURE_CTRL - 1
+ };
+
++enum mtk_vendor_attr_mu_ctrl {
++ MTK_VENDOR_ATTR_MU_CTRL_UNSPEC,
++
++ MTK_VENDOR_ATTR_MU_CTRL_ONOFF,
++ MTK_VENDOR_ATTR_MU_CTRL_DUMP,
++
++ /* keep last */
++ NUM_MTK_VENDOR_ATTRS_MU_CTRL,
++ MTK_VENDOR_ATTR_MU_CTRL_MAX =
++ NUM_MTK_VENDOR_ATTRS_MU_CTRL - 1
++};
++
++
+ #define CSI_MAX_COUNT 256
+ #define ETH_ALEN 6
+
+diff --git a/src/drivers/driver.h b/src/drivers/driver.h
+index 73c7bb4..1a3f070 100644
+--- a/src/drivers/driver.h
++++ b/src/drivers/driver.h
+@@ -1730,6 +1730,11 @@ struct wpa_driver_ap_params {
+ * subchannel is punctured, otherwise active.
+ */
+ u16 punct_bitmap;
++
++ /**
++ * mu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
++ */
++ u8 mu_onoff;
+ };
+
+ struct wpa_driver_mesh_bss_params {
+@@ -5005,6 +5010,14 @@ struct wpa_driver_ops {
+ const s8 edcca_compensation);
+ int (*configure_edcca_threshold)(void *priv, const int *threshold);
+ int (*get_edcca)(void *priv, const u8 mode, u8 *value);
++
++ /**
++ * mu_ctrl - ctrl on off for UL/DL MURU
++ * @priv: Private driver interface data
++ *
++ */
++ int (*mu_ctrl)(void *priv, u8 mu_onoff);
++ int (*mu_dump)(void *priv, u8 *mu_onoff);
+ };
+
+ /**
+diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
+index f5c95e1..fc8422c 100644
+--- a/src/drivers/driver_nl80211.c
++++ b/src/drivers/driver_nl80211.c
+@@ -13231,6 +13231,114 @@ fail:
+ }
+
+
++#ifdef CONFIG_IEEE80211AX
++static int nl80211_mu_onoff(void *priv, u8 mu_onoff)
++{
++ struct i802_bss *bss = priv;
++ struct wpa_driver_nl80211_data *drv = bss->drv;
++ struct nl_msg *msg;
++ struct nlattr *data;
++ int ret;
++
++ if (!drv->mtk_mu_vendor_cmd_avail) {
++ wpa_printf(MSG_INFO,
++ "nl80211: Driver does not support setting mu control");
++ return 0;
++ }
++
++ if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR)) ||
++ nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_MTK) ||
++ nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD, MTK_NL80211_VENDOR_SUBCMD_MU_CTRL) ||
++ !(data = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA)) ||
++ nla_put_u8(msg, MTK_VENDOR_ATTR_MU_CTRL_ONOFF, mu_onoff)) {
++ nlmsg_free(msg);
++ return -ENOBUFS;
++ }
++ nla_nest_end(msg, data);
++ ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
++ if(ret){
++ wpa_printf(MSG_ERROR, "Failed to set mu_onoff. ret=%d (%s)", ret, strerror(-ret));
++ }
++ return ret;
++}
++
++
++static int mu_dump_handler(struct nl_msg *msg, void *arg)
++{
++ u8 *mu_onoff = (u8 *) arg;
++ struct nlattr *tb[NL80211_ATTR_MAX + 1];
++ struct nlattr *tb_vendor[MTK_VENDOR_ATTR_MU_CTRL_MAX + 1];
++ struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
++ struct nlattr *nl_vend, *attr;
++
++ static const struct nla_policy
++ mu_ctrl_policy[NUM_MTK_VENDOR_ATTRS_MU_CTRL + 1] = {
++ [MTK_VENDOR_ATTR_MU_CTRL_ONOFF] = {.type = NLA_U8 },
++ [MTK_VENDOR_ATTR_MU_CTRL_DUMP] = {.type = NLA_U8 },
++ };
++
++ nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
++ genlmsg_attrlen(gnlh, 0), NULL);
++
++ nl_vend = tb[NL80211_ATTR_VENDOR_DATA];
++ if (!nl_vend)
++ return NL_SKIP;
++
++ nla_parse(tb_vendor, MTK_VENDOR_ATTR_MU_CTRL_MAX,
++ nla_data(nl_vend), nla_len(nl_vend), NULL);
++
++ attr = tb_vendor[MTK_VENDOR_ATTR_MU_CTRL_DUMP];
++ if (!attr) {
++ wpa_printf(MSG_ERROR, "nl80211: cannot find MTK_VENDOR_ATTR_MU_CTRL_DUMP");
++ return NL_SKIP;
++ }
++
++ *mu_onoff = nla_get_u8(attr);
++ wpa_printf(MSG_DEBUG, "nla_get mu_onoff: %d\n", *mu_onoff);
++
++ return 0;
++}
++
++static int nl80211_mu_dump(void *priv, u8 *mu_onoff)
++{
++ struct i802_bss *bss = priv;
++ struct wpa_driver_nl80211_data *drv = bss->drv;
++ struct nl_msg *msg;
++ struct nlattr *attr;
++ int ret;
++
++ if (!drv->mtk_mu_vendor_cmd_avail) {
++ wpa_printf(MSG_INFO,
++ "nl80211: Driver does not support setting mu control");
++ return 0;
++ }
++
++ if (!(msg = nl80211_drv_msg(drv, NLM_F_DUMP, NL80211_CMD_VENDOR)) ||
++ nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_MTK) ||
++ nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD, MTK_NL80211_VENDOR_SUBCMD_MU_CTRL)) {
++ nlmsg_free(msg);
++ return -ENOBUFS;
++ }
++
++ attr = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA);
++ if (!attr) {
++ nlmsg_free(msg);
++ return -1;
++ }
++
++ nla_nest_end(msg, attr);
++
++ ret = send_and_recv_msgs(drv, msg, mu_dump_handler, mu_onoff, NULL, NULL);
++
++ if(ret){
++ wpa_printf(MSG_ERROR, "Failed to get mu_onoff. ret=%d (%s)", ret, strerror(-ret));
++ }
++
++ return ret;
++}
++#endif /* CONFIG_IEEE80211AX */
++
++
+ #ifdef CONFIG_DPP
+ static int nl80211_dpp_listen(void *priv, bool enable)
+ {
+@@ -13671,6 +13779,8 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
+ .update_connect_params = nl80211_update_connection_params,
+ .send_external_auth_status = nl80211_send_external_auth_status,
+ .set_4addr_mode = nl80211_set_4addr_mode,
++ .mu_ctrl = nl80211_mu_onoff,
++ .mu_dump = nl80211_mu_dump,
+ #ifdef CONFIG_DPP
+ .dpp_listen = nl80211_dpp_listen,
+ #endif /* CONFIG_DPP */
+diff --git a/src/drivers/driver_nl80211.h b/src/drivers/driver_nl80211.h
+index 55c29cc..f3a45ec 100644
+--- a/src/drivers/driver_nl80211.h
++++ b/src/drivers/driver_nl80211.h
+@@ -200,6 +200,7 @@ struct wpa_driver_nl80211_data {
+ unsigned int secure_ranging_ctx_vendor_cmd_avail:1;
+ unsigned int puncturing:1;
+ unsigned int mtk_edcca_vendor_cmd_avail:1;
++ unsigned int mtk_mu_vendor_cmd_avail:1;
+
+ u64 vendor_scan_cookie;
+ u64 remain_on_chan_cookie;
+diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c
+index efe7ae4..dcd1bcd 100644
+--- a/src/drivers/driver_nl80211_capa.c
++++ b/src/drivers/driver_nl80211_capa.c
+@@ -1105,6 +1105,9 @@ static int wiphy_info_handler(struct nl_msg *msg, void *arg)
+ case MTK_NL80211_VENDOR_SUBCMD_EDCCA_CTRL :
+ drv->mtk_edcca_vendor_cmd_avail = 1;
+ break;
++ case MTK_NL80211_VENDOR_SUBCMD_MU_CTRL :
++ drv->mtk_mu_vendor_cmd_avail = 1;
++ break;
+ }
+ }
+
+--
+2.18.0
+
diff --git a/autobuild_mac80211_release/package/network/services/hostapd_new/patches/mtk-0007-hostapd-mtk-Add-three-wire-PTA-ctrl-hostapd-vendor-c.patch b/autobuild_mac80211_release/package/network/services/hostapd_new/patches/mtk-0007-hostapd-mtk-Add-three-wire-PTA-ctrl-hostapd-vendor-c.patch
new file mode 100644
index 0000000..398e058
--- /dev/null
+++ b/autobuild_mac80211_release/package/network/services/hostapd_new/patches/mtk-0007-hostapd-mtk-Add-three-wire-PTA-ctrl-hostapd-vendor-c.patch
@@ -0,0 +1,247 @@
+From 84d1dfb1adee1da3435b445e557396cc5318787d Mon Sep 17 00:00:00 2001
+From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+Date: Fri, 2 Sep 2022 01:03:23 +0800
+Subject: [PATCH 07/28] hostapd: mtk: Add three wire PTA ctrl hostapd vendor
+ command
+
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+---
+ hostapd/config_file.c | 4 ++++
+ src/ap/ap_config.c | 1 +
+ src/ap/ap_config.h | 13 ++++++++++++
+ src/ap/ap_drv_ops.c | 11 +++++++++++
+ src/ap/ap_drv_ops.h | 1 +
+ src/ap/hostapd.c | 2 ++
+ src/common/mtk_vendor.h | 16 +++++++++++++++
+ src/drivers/driver.h | 8 ++++++++
+ src/drivers/driver_nl80211.c | 33 +++++++++++++++++++++++++++++++
+ src/drivers/driver_nl80211.h | 1 +
+ src/drivers/driver_nl80211_capa.c | 3 +++
+ 11 files changed, 93 insertions(+)
+
+diff --git a/hostapd/config_file.c b/hostapd/config_file.c
+index 12741f8..860beee 100644
+--- a/hostapd/config_file.c
++++ b/hostapd/config_file.c
+@@ -4840,6 +4840,10 @@ static int hostapd_config_fill(struct hostapd_config *conf,
+ return 1;
+ }
+ conf->edcca_compensation = (s8) val;
++ } else if (os_strcmp(buf, "three_wire_enable") == 0) {
++ u8 en = atoi(pos);
++
++ conf->three_wire_enable = en;
+ } else {
+ wpa_printf(MSG_ERROR,
+ "Line %d: unknown configuration item '%s'",
+diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
+index 1cad303..2c447ba 100644
+--- a/src/ap/ap_config.c
++++ b/src/ap/ap_config.c
+@@ -297,6 +297,7 @@ struct hostapd_config * hostapd_config_defaults(void)
+
+ conf->edcca_enable = EDCCA_MODE_AUTO;
+ conf->edcca_compensation = EDCCA_DEFAULT_COMPENSATION;
++ conf->three_wire_enable = THREE_WIRE_MODE_DISABLE;
+
+ return conf;
+ }
+diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
+index 2077c67..e784629 100644
+--- a/src/ap/ap_config.h
++++ b/src/ap/ap_config.h
+@@ -1185,6 +1185,19 @@ struct hostapd_config {
+ u8 edcca_enable;
+ s8 edcca_compensation;
+ int *edcca_threshold;
++ u8 three_wire_enable;
++};
++
++enum three_wire_mode {
++ THREE_WIRE_MODE_DISABLE,
++ THREE_WIRE_MODE_EXT0_ENABLE,
++ THREE_WIRE_MODE_EXT1_ENABLE,
++ THREE_WIRE_MODE_ALL_ENABLE,
++
++ /* keep last */
++ NUM_THREE_WIRE_MODE,
++ THREE_WIRE_MODE_MAX =
++ NUM_THREE_WIRE_MODE - 1
+ };
+
+ enum edcca_mode {
+diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c
+index d290a00..ff2c6f8 100644
+--- a/src/ap/ap_drv_ops.c
++++ b/src/ap/ap_drv_ops.c
+@@ -1092,3 +1092,14 @@ int hostapd_drv_mu_dump(struct hostapd_data *hapd, u8 *mu_onoff)
+ return 0;
+ return hapd->driver->mu_dump(hapd->drv_priv, mu_onoff);
+ }
++
++int hostapd_drv_three_wire_ctrl(struct hostapd_data *hapd)
++{
++ if (!hapd->driver || !hapd->driver->three_wire_ctrl)
++ return 0;
++ if (hapd->iconf->three_wire_enable > THREE_WIRE_MODE_MAX) {
++ wpa_printf(MSG_INFO, "Invalid value for three wire enable\n");
++ return 0;
++ }
++ return hapd->driver->three_wire_ctrl(hapd->drv_priv, hapd->iconf->three_wire_enable);
++}
+diff --git a/src/ap/ap_drv_ops.h b/src/ap/ap_drv_ops.h
+index 1565bfa..e760658 100644
+--- a/src/ap/ap_drv_ops.h
++++ b/src/ap/ap_drv_ops.h
+@@ -150,6 +150,7 @@ int hostapd_drv_configure_edcca_threshold(struct hostapd_data *hapd,
+ int hostapd_drv_get_edcca(struct hostapd_data *hapd, const u8 mode, u8 *value);
+ int hostapd_drv_mu_ctrl(struct hostapd_data *hapd);
+ int hostapd_drv_mu_dump(struct hostapd_data *hapd, u8 *mu_onoff);
++int hostapd_drv_three_wire_ctrl(struct hostapd_data *hapd);
+
+ #include "drivers/driver.h"
+
+diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
+index 21aba48..2bf9fb2 100644
+--- a/src/ap/hostapd.c
++++ b/src/ap/hostapd.c
+@@ -2398,6 +2398,8 @@ dfs_offload:
+ goto fail;
+ if (hostapd_drv_mu_ctrl(hapd) < 0)
+ goto fail;
++ if (hostapd_drv_three_wire_ctrl(hapd) < 0)
++ goto fail;
+
+ wpa_printf(MSG_DEBUG, "%s: Setup of interface done.",
+ iface->bss[0]->conf->iface);
+diff --git a/src/common/mtk_vendor.h b/src/common/mtk_vendor.h
+index ef8618e..ed47487 100644
+--- a/src/common/mtk_vendor.h
++++ b/src/common/mtk_vendor.h
+@@ -13,6 +13,7 @@ enum mtk_nl80211_vendor_subcmds {
+ MTK_NL80211_VENDOR_SUBCMD_MU_CTRL = 0xc5,
+ MTK_NL80211_VENDOR_SUBCMD_PHY_CAPA_CTRL= 0xc6,
+ MTK_NL80211_VENDOR_SUBCMD_EDCCA_CTRL = 0xc7,
++ MTK_NL80211_VENDOR_SUBCMD_3WIRE_CTRL = 0xc8
+ };
+
+ enum mtk_vendor_attr_edcca_ctrl {
+@@ -55,6 +56,21 @@ static struct nla_policy edcca_ctrl_policy[NUM_MTK_VENDOR_ATTRS_EDCCA_CTRL] = {
+ [MTK_VENDOR_ATTR_EDCCA_CTRL_COMPENSATE] = { .type = NLA_U8 },
+ };
+
++enum mtk_vendor_attr_3wire_ctrl {
++ MTK_VENDOR_ATTR_3WIRE_CTRL_UNSPEC,
++
++ MTK_VENDOR_ATTR_3WIRE_CTRL_MODE,
++
++ /* keep last */
++ NUM_MTK_VENDOR_ATTRS_3WIRE_CTRL,
++ MTK_VENDOR_ATTR_3WIRE_CTRL_MAX =
++ NUM_MTK_VENDOR_ATTRS_3WIRE_CTRL - 1
++};
++
++static struct nla_policy three_wire_ctrl_policy[NUM_MTK_VENDOR_ATTRS_3WIRE_CTRL] = {
++ [MTK_VENDOR_ATTR_3WIRE_CTRL_MODE] = {.type = NLA_U8 },
++};
++
+ enum mtk_vendor_attr_csi_ctrl {
+ MTK_VENDOR_ATTR_CSI_CTRL_UNSPEC,
+
+diff --git a/src/drivers/driver.h b/src/drivers/driver.h
+index 1a3f070..2ced065 100644
+--- a/src/drivers/driver.h
++++ b/src/drivers/driver.h
+@@ -5018,6 +5018,14 @@ struct wpa_driver_ops {
+ */
+ int (*mu_ctrl)(void *priv, u8 mu_onoff);
+ int (*mu_dump)(void *priv, u8 *mu_onoff);
++
++ /**
++ * three_wire_ctrl - set three_wire_ctrl mode
++ * @priv: Private driver interface data
++ * @three_wire_enable: three_wire_ctrl mode
++ *
++ */
++ int (*three_wire_ctrl)(void *priv, u8 three_wire_enable);
+ };
+
+ /**
+diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
+index fc8422c..34bc9ac 100644
+--- a/src/drivers/driver_nl80211.c
++++ b/src/drivers/driver_nl80211.c
+@@ -13635,6 +13635,38 @@ static int nl80211_get_edcca(void *priv, const u8 mode, u8 *value)
+ return ret;
+ }
+
++static int nl80211_enable_three_wire(void *priv, const u8 three_wire_enable)
++{
++ struct i802_bss *bss = priv;
++ struct wpa_driver_nl80211_data *drv = bss->drv;
++ /* Prepare nl80211 cmd */
++ struct nl_msg *msg;
++ struct nlattr *data;
++ int ret;
++
++ if (!drv->mtk_3wire_vendor_cmd_avail) {
++ wpa_printf(MSG_INFO,
++ "nl80211: Driver does not support setting three wire control");
++ return 0;
++ }
++
++ if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR)) ||
++ nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_MTK) ||
++ nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
++ MTK_NL80211_VENDOR_SUBCMD_3WIRE_CTRL) ||
++ !(data = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA)) ||
++ nla_put_u8(msg, MTK_VENDOR_ATTR_3WIRE_CTRL_MODE, three_wire_enable)) {
++ nlmsg_free(msg);
++ return -ENOBUFS;
++ }
++ nla_nest_end(msg, data);
++ ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
++ if (ret) {
++ wpa_printf(MSG_ERROR, "Failed to enable three wire. ret=%d (%s) ",
++ ret, strerror(-ret));
++ }
++ return ret;
++}
+
+ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
+ .name = "nl80211",
+@@ -13794,4 +13826,5 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
+ .configure_edcca_enable = nl80211_configure_edcca_enable,
+ .configure_edcca_threshold = nl80211_configure_edcca_threshold,
+ .get_edcca = nl80211_get_edcca,
++ .three_wire_ctrl = nl80211_enable_three_wire,
+ };
+diff --git a/src/drivers/driver_nl80211.h b/src/drivers/driver_nl80211.h
+index f3a45ec..92da450 100644
+--- a/src/drivers/driver_nl80211.h
++++ b/src/drivers/driver_nl80211.h
+@@ -201,6 +201,7 @@ struct wpa_driver_nl80211_data {
+ unsigned int puncturing:1;
+ unsigned int mtk_edcca_vendor_cmd_avail:1;
+ unsigned int mtk_mu_vendor_cmd_avail:1;
++ unsigned int mtk_3wire_vendor_cmd_avail:1;
+
+ u64 vendor_scan_cookie;
+ u64 remain_on_chan_cookie;
+diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c
+index dcd1bcd..3b25754 100644
+--- a/src/drivers/driver_nl80211_capa.c
++++ b/src/drivers/driver_nl80211_capa.c
+@@ -1108,6 +1108,9 @@ static int wiphy_info_handler(struct nl_msg *msg, void *arg)
+ case MTK_NL80211_VENDOR_SUBCMD_MU_CTRL :
+ drv->mtk_mu_vendor_cmd_avail = 1;
+ break;
++ case MTK_NL80211_VENDOR_SUBCMD_3WIRE_CTRL :
++ drv->mtk_3wire_vendor_cmd_avail = 1;
++ break;
+ }
+ }
+
+--
+2.18.0
+
diff --git a/autobuild_mac80211_release/package/network/services/hostapd_new/patches/mtk-0008-hostapd-mtk-Add-hostapd-iBF-control.patch b/autobuild_mac80211_release/package/network/services/hostapd_new/patches/mtk-0008-hostapd-mtk-Add-hostapd-iBF-control.patch
new file mode 100644
index 0000000..acb40a7
--- /dev/null
+++ b/autobuild_mac80211_release/package/network/services/hostapd_new/patches/mtk-0008-hostapd-mtk-Add-hostapd-iBF-control.patch
@@ -0,0 +1,431 @@
+From 7011a7a5503e76228d475060a72b3a168fac1b54 Mon Sep 17 00:00:00 2001
+From: mtk27835 <shurong.wen@mediatek.com>
+Date: Wed, 7 Sep 2022 14:41:51 -0700
+Subject: [PATCH 08/28] hostapd: mtk: Add hostapd iBF control
+
+Signed-off-by: mtk27835 <shurong.wen@mediatek.com>
+---
+ hostapd/config_file.c | 3 +
+ hostapd/ctrl_iface.c | 26 +++++++
+ hostapd/hostapd_cli.c | 9 +++
+ src/ap/ap_config.c | 1 +
+ src/ap/ap_config.h | 2 +
+ src/ap/ap_drv_ops.c | 14 ++++
+ src/ap/ap_drv_ops.h | 2 +
+ src/ap/hostapd.c | 2 +
+ src/common/mtk_vendor.h | 35 +++++++++-
+ src/drivers/driver.h | 19 ++++++
+ src/drivers/driver_nl80211.c | 108 ++++++++++++++++++++++++++++++
+ src/drivers/driver_nl80211.h | 1 +
+ src/drivers/driver_nl80211_capa.c | 3 +
+ 13 files changed, 224 insertions(+), 1 deletion(-)
+
+diff --git a/hostapd/config_file.c b/hostapd/config_file.c
+index 860beee..e1dd540 100644
+--- a/hostapd/config_file.c
++++ b/hostapd/config_file.c
+@@ -4844,6 +4844,9 @@ static int hostapd_config_fill(struct hostapd_config *conf,
+ u8 en = atoi(pos);
+
+ conf->three_wire_enable = en;
++ } else if (os_strcmp(buf, "ibf_enable") == 0) { /*ibf setting is per device*/
++ int val = atoi(pos);
++ conf->ibf_enable = !!val;
+ } else {
+ wpa_printf(MSG_ERROR,
+ "Line %d: unknown configuration item '%s'",
+diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
+index b317a65..45797cd 100644
+--- a/hostapd/ctrl_iface.c
++++ b/hostapd/ctrl_iface.c
+@@ -3573,6 +3573,30 @@ hostapd_ctrl_iface_get_mu(struct hostapd_data *hapd, char *buf,
+ }
+
+
++static int
++hostapd_ctrl_iface_get_ibf(struct hostapd_data *hapd, char *buf,
++ size_t buflen)
++{
++ u8 ibf_enable;
++ int ret;
++ char *pos, *end;
++
++ pos = buf;
++ end = buf + buflen;
++
++ if (hostapd_drv_ibf_dump(hapd, &ibf_enable) == 0) {
++ hapd->iconf->ibf_enable = ibf_enable;
++ ret = os_snprintf(pos, end - pos, "ibf_enable: %u\n",
++ ibf_enable);
++ }
++
++ if (os_snprintf_error(end - pos, ret))
++ return 0;
++
++ return ret;
++}
++
++
+ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
+ char *buf, char *reply,
+ int reply_size,
+@@ -4139,6 +4163,8 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
+ reply_size);
+ } else if (os_strncmp(buf, "GET_MU", 6) == 0) {
+ reply_len = hostapd_ctrl_iface_get_mu(hapd, reply, reply_size);
++ } else if (os_strncmp(buf, "GET_IBF", 7) == 0) {
++ reply_len = hostapd_ctrl_iface_get_ibf(hapd, reply, reply_size);
+ } else {
+ os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
+ reply_len = 16;
+diff --git a/hostapd/hostapd_cli.c b/hostapd/hostapd_cli.c
+index 285aeba..5922fe3 100644
+--- a/hostapd/hostapd_cli.c
++++ b/hostapd/hostapd_cli.c
+@@ -1606,6 +1606,13 @@ static int hostapd_cli_cmd_driver(struct wpa_ctrl *ctrl, int argc, char *argv[])
+ #endif /* ANDROID */
+
+
++static int hostapd_cli_cmd_get_ibf(struct wpa_ctrl *ctrl, int argc,
++ char *argv[])
++{
++ return hostapd_cli_cmd(ctrl, "GET_IBF", 0, NULL, NULL);
++}
++
++
+ struct hostapd_cli_cmd {
+ const char *cmd;
+ int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
+@@ -1811,6 +1818,8 @@ static const struct hostapd_cli_cmd hostapd_cli_commands[] = {
+ #endif /* ANDROID */
+ { "inband_discovery", hostapd_cli_cmd_inband_discovery, NULL,
+ "<tx type(0/1/2)> <interval> = runtime set inband discovery" },
++ { "get_ibf", hostapd_cli_cmd_get_ibf, NULL,
++ " = show iBF state (enabled/disabled)"},
+ { NULL, NULL, NULL, NULL }
+ };
+
+diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
+index 2c447ba..a9f77e0 100644
+--- a/src/ap/ap_config.c
++++ b/src/ap/ap_config.c
+@@ -298,6 +298,7 @@ struct hostapd_config * hostapd_config_defaults(void)
+ conf->edcca_enable = EDCCA_MODE_AUTO;
+ conf->edcca_compensation = EDCCA_DEFAULT_COMPENSATION;
+ conf->three_wire_enable = THREE_WIRE_MODE_DISABLE;
++ conf->ibf_enable = IBF_DEFAULT_ENABLE;
+
+ return conf;
+ }
+diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
+index e784629..c88c8ae 100644
+--- a/src/ap/ap_config.h
++++ b/src/ap/ap_config.h
+@@ -1186,6 +1186,7 @@ struct hostapd_config {
+ s8 edcca_compensation;
+ int *edcca_threshold;
+ u8 three_wire_enable;
++ u8 ibf_enable;
+ };
+
+ enum three_wire_mode {
+@@ -1310,6 +1311,7 @@ hostapd_set_oper_centr_freq_seg1_idx(struct hostapd_config *conf,
+ conf->vht_oper_centr_freq_seg1_idx = oper_centr_freq_seg1_idx;
+ }
+
++#define IBF_DEFAULT_ENABLE 0
+
+ int hostapd_mac_comp(const void *a, const void *b);
+ struct hostapd_config * hostapd_config_defaults(void);
+diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c
+index ff2c6f8..91ade16 100644
+--- a/src/ap/ap_drv_ops.c
++++ b/src/ap/ap_drv_ops.c
+@@ -1103,3 +1103,17 @@ int hostapd_drv_three_wire_ctrl(struct hostapd_data *hapd)
+ }
+ return hapd->driver->three_wire_ctrl(hapd->drv_priv, hapd->iconf->three_wire_enable);
+ }
++
++int hostapd_drv_ibf_ctrl(struct hostapd_data *hapd)
++{
++ if (!hapd->driver || !hapd->driver->ibf_ctrl)
++ return 0;
++ return hapd->driver->ibf_ctrl(hapd->drv_priv, hapd->iconf->ibf_enable);
++}
++
++int hostapd_drv_ibf_dump(struct hostapd_data *hapd, u8 *ibf_enable)
++{
++ if (!hapd->driver || !hapd->driver->ibf_dump)
++ return 0;
++ return hapd->driver->ibf_dump(hapd->drv_priv, ibf_enable);
++}
+\ No newline at end of file
+diff --git a/src/ap/ap_drv_ops.h b/src/ap/ap_drv_ops.h
+index e760658..2cc39b7 100644
+--- a/src/ap/ap_drv_ops.h
++++ b/src/ap/ap_drv_ops.h
+@@ -151,6 +151,8 @@ int hostapd_drv_get_edcca(struct hostapd_data *hapd, const u8 mode, u8 *value);
+ int hostapd_drv_mu_ctrl(struct hostapd_data *hapd);
+ int hostapd_drv_mu_dump(struct hostapd_data *hapd, u8 *mu_onoff);
+ int hostapd_drv_three_wire_ctrl(struct hostapd_data *hapd);
++int hostapd_drv_ibf_ctrl(struct hostapd_data *hapd);
++int hostapd_drv_ibf_dump(struct hostapd_data *hapd, u8 *ibf_enable);
+
+ #include "drivers/driver.h"
+
+diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
+index 2bf9fb2..2deb9a3 100644
+--- a/src/ap/hostapd.c
++++ b/src/ap/hostapd.c
+@@ -2400,6 +2400,8 @@ dfs_offload:
+ goto fail;
+ if (hostapd_drv_three_wire_ctrl(hapd) < 0)
+ goto fail;
++ if (hostapd_drv_ibf_ctrl(hapd) < 0)
++ goto fail;
+
+ wpa_printf(MSG_DEBUG, "%s: Setup of interface done.",
+ iface->bss[0]->conf->iface);
+diff --git a/src/common/mtk_vendor.h b/src/common/mtk_vendor.h
+index ed47487..7b7aeaa 100644
+--- a/src/common/mtk_vendor.h
++++ b/src/common/mtk_vendor.h
+@@ -13,7 +13,8 @@ enum mtk_nl80211_vendor_subcmds {
+ MTK_NL80211_VENDOR_SUBCMD_MU_CTRL = 0xc5,
+ MTK_NL80211_VENDOR_SUBCMD_PHY_CAPA_CTRL= 0xc6,
+ MTK_NL80211_VENDOR_SUBCMD_EDCCA_CTRL = 0xc7,
+- MTK_NL80211_VENDOR_SUBCMD_3WIRE_CTRL = 0xc8
++ MTK_NL80211_VENDOR_SUBCMD_3WIRE_CTRL = 0xc8,
++ MTK_NL80211_VENDOR_SUBCMD_IBF_CTRL = 0xc9,
+ };
+
+ enum mtk_vendor_attr_edcca_ctrl {
+@@ -204,6 +205,38 @@ enum mtk_vendor_attr_mu_ctrl {
+ NUM_MTK_VENDOR_ATTRS_MU_CTRL - 1
+ };
+
++enum mtk_vendor_attr_ibf_ctrl {
++ MTK_VENDOR_ATTR_IBF_CTRL_UNSPEC,
++
++ MTK_VENDOR_ATTR_IBF_CTRL_ENABLE,
++
++ /* keep last */
++ NUM_MTK_VENDOR_ATTRS_IBF_CTRL,
++ MTK_VENDOR_ATTR_IBF_CTRL_MAX =
++ NUM_MTK_VENDOR_ATTRS_IBF_CTRL - 1
++};
++
++enum mtk_vendor_attr_ibf_dump {
++ MTK_VENDOR_ATTR_IBF_DUMP_UNSPEC,
++
++ MTK_VENDOR_ATTR_IBF_DUMP_ENABLE,
++
++ /* keep last */
++ NUM_MTK_VENDOR_ATTRS_IBF_DUMP,
++ MTK_VENDOR_ATTR_IBF_DUMP_MAX =
++ NUM_MTK_VENDOR_ATTRS_IBF_DUMP - 1
++};
++
++static struct nla_policy
++ibf_ctrl_policy[NUM_MTK_VENDOR_ATTRS_IBF_CTRL] = {
++ [MTK_VENDOR_ATTR_IBF_CTRL_ENABLE] = { .type = NLA_U8 },
++};
++
++static struct nla_policy
++ibf_dump_policy[NUM_MTK_VENDOR_ATTRS_IBF_DUMP] = {
++ [MTK_VENDOR_ATTR_IBF_DUMP_ENABLE] = { .type = NLA_U8 },
++};
++
+
+ #define CSI_MAX_COUNT 256
+ #define ETH_ALEN 6
+diff --git a/src/drivers/driver.h b/src/drivers/driver.h
+index 2ced065..9e12e42 100644
+--- a/src/drivers/driver.h
++++ b/src/drivers/driver.h
+@@ -1735,6 +1735,11 @@ struct wpa_driver_ap_params {
+ * mu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
+ */
+ u8 mu_onoff;
++
++ /**
++ * ibf_enable=<val>
++ */
++ u8 ibf_enable;
+ };
+
+ struct wpa_driver_mesh_bss_params {
+@@ -5026,6 +5031,20 @@ struct wpa_driver_ops {
+ *
+ */
+ int (*three_wire_ctrl)(void *priv, u8 three_wire_enable);
++
++ /**
++ * ibf_ctrl - ctrl disable/enable for ibf
++ * @priv: Private driver interface data
++ *
++ */
++ int (*ibf_ctrl)(void *priv, u8 ibf_enable);
++
++ /**
++ * ibf_dump - dump ibf
++ * @priv: Private driver interface data
++ *
++ */
++ int (*ibf_dump)(void *priv, u8 *ibf_enable);
+ };
+
+ /**
+diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
+index 34bc9ac..641b894 100644
+--- a/src/drivers/driver_nl80211.c
++++ b/src/drivers/driver_nl80211.c
+@@ -13668,6 +13668,112 @@ static int nl80211_enable_three_wire(void *priv, const u8 three_wire_enable)
+ return ret;
+ }
+
++static int nl80211_ibf_enable(void *priv, u8 ibf_enable)
++{
++ struct i802_bss *bss = priv;
++ struct wpa_driver_nl80211_data *drv = bss->drv;
++ struct nl_msg *msg;
++ struct nlattr *data;
++ int ret;
++
++ if (!drv->mtk_ibf_vendor_cmd_avail) {
++ wpa_printf(MSG_INFO,
++ "nl80211: Driver does not support setting ibf control");
++ return 0;
++ }
++
++ msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR);
++ if (!msg)
++ goto fail;
++
++ if (nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_MTK) ||
++ nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD, MTK_NL80211_VENDOR_SUBCMD_IBF_CTRL))
++ goto fail;
++
++ data = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA);
++ if (!data)
++ goto fail;
++
++ nla_put_u8(msg, MTK_VENDOR_ATTR_IBF_CTRL_ENABLE, ibf_enable);
++
++ nla_nest_end(msg, data);
++ ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
++ if (ret) {
++ wpa_printf(MSG_ERROR, "Failed to set ibf_enable. ret=%d (%s)", ret, strerror(-ret));
++ }
++
++ return ret;
++
++fail:
++ nlmsg_free(msg);
++ return -ENOBUFS;
++}
++
++static int ibf_dump_handler(struct nl_msg *msg, void *arg)
++{
++ u8 *ibf_enable = (u8 *) arg;
++ struct nlattr *tb[NL80211_ATTR_MAX + 1];
++ struct nlattr *tb_vendor[MTK_VENDOR_ATTR_IBF_DUMP_MAX + 1];
++ struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
++ struct nlattr *nl_vend, *attr;
++
++ nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
++ genlmsg_attrlen(gnlh, 0), NULL);
++
++ nl_vend = tb[NL80211_ATTR_VENDOR_DATA];
++ if (!nl_vend)
++ return NL_SKIP;
++
++ nla_parse(tb_vendor, MTK_VENDOR_ATTR_IBF_DUMP_MAX,
++ nla_data(nl_vend), nla_len(nl_vend), NULL);
++
++ attr = tb_vendor[MTK_VENDOR_ATTR_IBF_DUMP_ENABLE];
++ if (!attr) {
++ wpa_printf(MSG_ERROR, "nl80211: cannot find MTK_VENDOR_ATTR_IBF_DUMP_ENABLE");
++ return NL_SKIP;
++ }
++
++ *ibf_enable = nla_get_u8(attr);
++
++ return NL_SKIP;
++}
++
++static int
++nl80211_ibf_dump(void *priv, u8 *ibf_enable)
++{
++ struct i802_bss *bss = priv;
++ struct wpa_driver_nl80211_data *drv = bss->drv;
++ struct nl_msg *msg;
++ struct nlattr *data;
++ int ret;
++
++ msg = nl80211_drv_msg(drv, NLM_F_DUMP, NL80211_CMD_VENDOR);
++ if (!msg)
++ goto fail;
++
++ if (nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_MTK) ||
++ nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD, MTK_NL80211_VENDOR_SUBCMD_IBF_CTRL))
++ goto fail;
++
++ data = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA | NLA_F_NESTED);
++ if (!data)
++ goto fail;
++
++ nla_nest_end(msg, data);
++
++ ret = send_and_recv_msgs(drv, msg, ibf_dump_handler, ibf_enable, NULL, NULL);
++
++ if (ret) {
++ wpa_printf(MSG_ERROR, "Failed to dump ibf_enable. ret=%d (%s)", ret, strerror(-ret));
++ }
++
++ return ret;
++
++fail:
++ nlmsg_free(msg);
++ return -ENOBUFS;
++}
++
+ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
+ .name = "nl80211",
+ .desc = "Linux nl80211/cfg80211",
+@@ -13827,4 +13933,6 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
+ .configure_edcca_threshold = nl80211_configure_edcca_threshold,
+ .get_edcca = nl80211_get_edcca,
+ .three_wire_ctrl = nl80211_enable_three_wire,
++ .ibf_ctrl = nl80211_ibf_enable,
++ .ibf_dump = nl80211_ibf_dump,
+ };
+diff --git a/src/drivers/driver_nl80211.h b/src/drivers/driver_nl80211.h
+index 92da450..9ef313b 100644
+--- a/src/drivers/driver_nl80211.h
++++ b/src/drivers/driver_nl80211.h
+@@ -202,6 +202,7 @@ struct wpa_driver_nl80211_data {
+ unsigned int mtk_edcca_vendor_cmd_avail:1;
+ unsigned int mtk_mu_vendor_cmd_avail:1;
+ unsigned int mtk_3wire_vendor_cmd_avail:1;
++ unsigned int mtk_ibf_vendor_cmd_avail:1;
+
+ u64 vendor_scan_cookie;
+ u64 remain_on_chan_cookie;
+diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c
+index 3b25754..5c6bb36 100644
+--- a/src/drivers/driver_nl80211_capa.c
++++ b/src/drivers/driver_nl80211_capa.c
+@@ -1111,6 +1111,9 @@ static int wiphy_info_handler(struct nl_msg *msg, void *arg)
+ case MTK_NL80211_VENDOR_SUBCMD_3WIRE_CTRL :
+ drv->mtk_3wire_vendor_cmd_avail = 1;
+ break;
++ case MTK_NL80211_VENDOR_SUBCMD_IBF_CTRL:
++ drv->mtk_ibf_vendor_cmd_avail = 1;
++ break;
+ }
+ }
+
+--
+2.18.0
+
diff --git a/autobuild_mac80211_release/package/network/services/hostapd_new/patches/mtk-0009-hostapd-mtk-Do-not-include-HE-capab-IE-if-associated.patch b/autobuild_mac80211_release/package/network/services/hostapd_new/patches/mtk-0009-hostapd-mtk-Do-not-include-HE-capab-IE-if-associated.patch
new file mode 100644
index 0000000..8c4b67f
--- /dev/null
+++ b/autobuild_mac80211_release/package/network/services/hostapd_new/patches/mtk-0009-hostapd-mtk-Do-not-include-HE-capab-IE-if-associated.patch
@@ -0,0 +1,27 @@
+From fd9094f2ca304f391f9ea5569a60e563703fa907 Mon Sep 17 00:00:00 2001
+From: Howard Hsu <howard-yh.hsu@mediatek.com>
+Date: Thu, 22 Sep 2022 16:08:09 +0800
+Subject: [PATCH 09/28] hostapd: mtk: Do not include HE capab IE if associated
+ sta's HE capab IE is invalid
+
+---
+ src/ap/ieee802_11.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
+index 5b40b13..b5dfad9 100644
+--- a/src/ap/ieee802_11.c
++++ b/src/ap/ieee802_11.c
+@@ -4399,7 +4399,8 @@ static u16 send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta,
+ #endif /* CONFIG_IEEE80211AC */
+
+ #ifdef CONFIG_IEEE80211AX
+- if (hapd->iconf->ieee80211ax && !hapd->conf->disable_11ax) {
++ if (hapd->iconf->ieee80211ax && !hapd->conf->disable_11ax &&
++ sta->flags & WLAN_STA_HE) {
+ p = hostapd_eid_he_capab(hapd, p, IEEE80211_MODE_AP);
+ p = hostapd_eid_he_operation(hapd, p);
+ p = hostapd_eid_cca(hapd, p);
+--
+2.18.0
+
diff --git a/autobuild_mac80211_release/package/network/services/hostapd_new/patches/mtk-0010-hostapd-mtk-Add-DFS-detection-mode.patch b/autobuild_mac80211_release/package/network/services/hostapd_new/patches/mtk-0010-hostapd-mtk-Add-DFS-detection-mode.patch
new file mode 100644
index 0000000..41cdcf6
--- /dev/null
+++ b/autobuild_mac80211_release/package/network/services/hostapd_new/patches/mtk-0010-hostapd-mtk-Add-DFS-detection-mode.patch
@@ -0,0 +1,136 @@
+From 246c1629481117413fd4648cdfc25f6fb24a5502 Mon Sep 17 00:00:00 2001
+From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+Date: Mon, 20 Feb 2023 14:55:49 +0800
+Subject: [PATCH 10/28] hostapd: mtk: Add DFS detection mode
+
+Add DFS detection mode for testing radar detection rate.
+If DFS detection mode is on, AP will not switch channels when receiving
+a radar signal.
+This detection mode also supports background chain.
+
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+---
+ hostapd/config_file.c | 4 ++++
+ hostapd/ctrl_iface.c | 23 +++++++++++++++++++++++
+ src/ap/ap_config.h | 13 +++++++++++++
+ src/ap/dfs.c | 10 ++++++++++
+ 4 files changed, 50 insertions(+)
+
+diff --git a/hostapd/config_file.c b/hostapd/config_file.c
+index e1dd540..09b5605 100644
+--- a/hostapd/config_file.c
++++ b/hostapd/config_file.c
+@@ -4847,6 +4847,10 @@ static int hostapd_config_fill(struct hostapd_config *conf,
+ } else if (os_strcmp(buf, "ibf_enable") == 0) { /*ibf setting is per device*/
+ int val = atoi(pos);
+ conf->ibf_enable = !!val;
++ } else if (os_strcmp(buf, "dfs_detect_mode") == 0) { /*bypass channel switch*/
++ u8 en = strtol(pos, NULL, 10);
++
++ conf->dfs_detect_mode = en;
+ } else {
+ wpa_printf(MSG_ERROR,
+ "Line %d: unknown configuration item '%s'",
+diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
+index 45797cd..5ea8934 100644
+--- a/hostapd/ctrl_iface.c
++++ b/hostapd/ctrl_iface.c
+@@ -3597,6 +3597,26 @@ hostapd_ctrl_iface_get_ibf(struct hostapd_data *hapd, char *buf,
+ }
+
+
++static int
++hostapd_ctrl_iface_set_dfs_detect_mode(struct hostapd_data *hapd, char *value,
++ char *buf, size_t buflen)
++{
++ u8 dfs_detect_mode;
++
++ if (!value)
++ return -1;
++
++ dfs_detect_mode = strtol(value, NULL, 10);
++ if (dfs_detect_mode > DFS_DETECT_MODE_MAX) {
++ wpa_printf(MSG_ERROR, "Invalid value for dfs detect mode");
++ return -1;
++ }
++ hapd->iconf->dfs_detect_mode = dfs_detect_mode;
++
++ return os_snprintf(buf, buflen, "OK\n");
++}
++
++
+ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
+ char *buf, char *reply,
+ int reply_size,
+@@ -4165,6 +4185,9 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
+ reply_len = hostapd_ctrl_iface_get_mu(hapd, reply, reply_size);
+ } else if (os_strncmp(buf, "GET_IBF", 7) == 0) {
+ reply_len = hostapd_ctrl_iface_get_ibf(hapd, reply, reply_size);
++ } 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 {
+ os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
+ reply_len = 16;
+diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
+index c88c8ae..d651bfb 100644
+--- a/src/ap/ap_config.h
++++ b/src/ap/ap_config.h
+@@ -1187,6 +1187,7 @@ struct hostapd_config {
+ int *edcca_threshold;
+ u8 three_wire_enable;
+ u8 ibf_enable;
++ u8 dfs_detect_mode;
+ };
+
+ enum three_wire_mode {
+@@ -1201,6 +1202,18 @@ enum three_wire_mode {
+ NUM_THREE_WIRE_MODE - 1
+ };
+
++enum dfs_mode {
++ DFS_DETECT_MODE_DISABLE,
++ DFS_DETECT_MODE_AP_ENABLE,
++ DFS_DETECT_MODE_BACKGROUND_ENABLE,
++ DFS_DETECT_MODE_ALL_ENABLE,
++
++ /* keep last */
++ NUM_DFS_DETECT_MODE,
++ DFS_DETECT_MODE_MAX =
++ NUM_DFS_DETECT_MODE - 1
++};
++
+ enum edcca_mode {
+ EDCCA_MODE_FORCE_DISABLE = 0,
+ EDCCA_MODE_AUTO = 1,
+diff --git a/src/ap/dfs.c b/src/ap/dfs.c
+index a19afb0..644a7ea 100644
+--- a/src/ap/dfs.c
++++ b/src/ap/dfs.c
+@@ -1322,6 +1322,11 @@ hostapd_dfs_background_start_channel_switch(struct hostapd_iface *iface,
+ __func__, iface->radar_background.cac_started ? "yes" : "no",
+ hostapd_csa_in_progress(iface) ? "yes" : "no");
+
++ /* Skip channel switch when background dfs detect mode is on */
++ if (iface->conf->dfs_detect_mode == DFS_DETECT_MODE_BACKGROUND_ENABLE ||
++ iface->conf->dfs_detect_mode == DFS_DETECT_MODE_ALL_ENABLE)
++ return 0;
++
+ /* Check if CSA in progress */
+ if (hostapd_csa_in_progress(iface))
+ return 0;
+@@ -1370,6 +1375,11 @@ static int hostapd_dfs_start_channel_switch(struct hostapd_iface *iface)
+ __func__, iface->cac_started ? "yes" : "no",
+ hostapd_csa_in_progress(iface) ? "yes" : "no");
+
++ /* Skip channel switch when dfs detect mode is on */
++ if (iface->conf->dfs_detect_mode == DFS_DETECT_MODE_AP_ENABLE ||
++ iface->conf->dfs_detect_mode == DFS_DETECT_MODE_ALL_ENABLE)
++ return 0;
++
+ /* Check if CSA in progress */
+ if (hostapd_csa_in_progress(iface))
+ return 0;
+--
+2.18.0
+
diff --git a/autobuild_mac80211_release/package/network/services/hostapd_new/patches/mtk-0011-hostapd-mtk-Add-DFS-offchan-channel-switch.patch b/autobuild_mac80211_release/package/network/services/hostapd_new/patches/mtk-0011-hostapd-mtk-Add-DFS-offchan-channel-switch.patch
new file mode 100644
index 0000000..03f32ec
--- /dev/null
+++ b/autobuild_mac80211_release/package/network/services/hostapd_new/patches/mtk-0011-hostapd-mtk-Add-DFS-offchan-channel-switch.patch
@@ -0,0 +1,192 @@
+From b0a253a420b901e3f5b7b069a85a135835a702ff 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/28] 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.
+Command format:
+hostapd_cli -i <interface> raw SET_OFFCHAN_CTRL chan=<dfs_channel>
+
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+---
+ hostapd/ctrl_iface.c | 72 ++++++++++++++++++++++++++++++++++++++++++++
+ src/ap/dfs.c | 25 ++++++---------
+ src/ap/dfs.h | 15 +++++++++
+ 3 files changed, 96 insertions(+), 16 deletions(-)
+
+diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
+index 5ea8934..40fb0d4 100644
+--- a/hostapd/ctrl_iface.c
++++ b/hostapd/ctrl_iface.c
+@@ -3617,6 +3617,76 @@ hostapd_ctrl_iface_set_dfs_detect_mode(struct hostapd_data *hapd, char *value,
+ }
+
+
++static int
++hostapd_ctrl_iface_set_offchan_ctrl(struct hostapd_data *hapd, char *cmd,
++ char *buf, size_t buflen)
++{
++ struct hostapd_iface *iface = hapd->iface;
++ char *pos, *param;
++ enum hostapd_hw_mode hw_mode;
++ bool chan_found = false;
++ int i, num_available_chandefs, channel, chan_width, sec = 0;
++ int sec_chan_idx_80p80 = -1;
++ u8 oper_centr_freq_seg0_idx, oper_centr_freq_seg1_idx;
++ struct hostapd_channel_data *chan;
++ enum dfs_channel_type type = DFS_NO_CAC_YET;
++
++ param = os_strchr(cmd, ' ');
++ if (!param)
++ return -1;
++ *param++ = '\0';
++
++ pos = os_strstr(param, "chan=");
++ if (pos)
++ channel = strtol(pos + 5, NULL, 10);
++ else
++ return -1;
++
++ num_available_chandefs = dfs_find_channel(iface, NULL, 0, type);
++ for (i = 0; i < num_available_chandefs; i++) {
++ dfs_find_channel(iface, &chan, i, type);
++ if (chan->chan == channel) {
++ chan_found = true;
++ break;
++ }
++ }
++
++ if (!chan_found)
++ return -1;
++
++ if (iface->conf->secondary_channel)
++ sec = 1;
++
++ dfs_adjust_center_freq(iface, chan,
++ sec,
++ sec_chan_idx_80p80,
++ &oper_centr_freq_seg0_idx,
++ &oper_centr_freq_seg1_idx);
++
++ if (hostapd_start_dfs_cac(iface, iface->conf->hw_mode,
++ chan->freq, chan->chan,
++ iface->conf->ieee80211n,
++ iface->conf->ieee80211ac,
++ iface->conf->ieee80211ax,
++ iface->conf->ieee80211be,
++ 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 -1;
++ }
++
++ iface->radar_background.channel = chan->chan;
++ iface->radar_background.freq = chan->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;
++
++ return os_snprintf(buf, buflen, "OK\n");
++}
++
++
+ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
+ char *buf, char *reply,
+ int reply_size,
+@@ -4188,6 +4258,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 {
+ os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
+ reply_len = 16;
+diff --git a/src/ap/dfs.c b/src/ap/dfs.c
+index 644a7ea..48c5fc9 100644
+--- a/src/ap/dfs.c
++++ b/src/ap/dfs.c
+@@ -19,13 +19,6 @@
+ #include "dfs.h"
+ #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,
+@@ -238,9 +231,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 dfs_find_channel(struct hostapd_iface *iface,
++ struct hostapd_channel_data **ret_chan,
++ int idx, enum dfs_channel_type type)
+ {
+ struct hostapd_hw_modes *mode;
+ struct hostapd_channel_data *chan;
+@@ -300,12 +293,12 @@ static int dfs_find_channel(struct hostapd_iface *iface,
+ }
+
+
+-static void dfs_adjust_center_freq(struct hostapd_iface *iface,
+- struct hostapd_channel_data *chan,
+- int secondary_channel,
+- int sec_chan_idx_80p80,
+- u8 *oper_centr_freq_seg0_idx,
+- u8 *oper_centr_freq_seg1_idx)
++void dfs_adjust_center_freq(struct hostapd_iface *iface,
++ struct hostapd_channel_data *chan,
++ int secondary_channel,
++ int sec_chan_idx_80p80,
++ u8 *oper_centr_freq_seg0_idx,
++ u8 *oper_centr_freq_seg1_idx)
+ {
+ if (!iface->conf->ieee80211ac && !iface->conf->ieee80211ax)
+ return;
+diff --git a/src/ap/dfs.h b/src/ap/dfs.h
+index 606c1b3..c2556d2 100644
+--- a/src/ap/dfs.h
++++ b/src/ap/dfs.h
+@@ -9,6 +9,12 @@
+ #ifndef DFS_H
+ #define DFS_H
+
++enum dfs_channel_type {
++ DFS_ANY_CHANNEL,
++ DFS_AVAILABLE, /* non-radar or radar-available */
++ DFS_NO_CAC_YET, /* radar-not-yet-available */
++};
++
+ 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);
++int dfs_find_channel(struct hostapd_iface *iface,
++ struct hostapd_channel_data **ret_chan,
++ int idx, enum dfs_channel_type type);
++void dfs_adjust_center_freq(struct hostapd_iface *iface,
++ struct hostapd_channel_data *chan,
++ int secondary_channel,
++ int sec_chan_idx_80p80,
++ u8 *oper_centr_freq_seg0_idx,
++ u8 *oper_centr_freq_seg1_idx);
+
+ #endif /* DFS_H */
+--
+2.18.0
+
diff --git a/autobuild_mac80211_release/package/network/services/hostapd_new/patches/mtk-0012-hostapd-mtk-Add-amsdu-set-get-ctrl.patch b/autobuild_mac80211_release/package/network/services/hostapd_new/patches/mtk-0012-hostapd-mtk-Add-amsdu-set-get-ctrl.patch
new file mode 100644
index 0000000..230cbaa
--- /dev/null
+++ b/autobuild_mac80211_release/package/network/services/hostapd_new/patches/mtk-0012-hostapd-mtk-Add-amsdu-set-get-ctrl.patch
@@ -0,0 +1,400 @@
+From e906e5508fc01ce8c518431728218d04670a1ca3 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/28] hostapd: mtk: Add amsdu set get ctrl
+
+---
+ hostapd/config_file.c | 9 +++
+ hostapd/ctrl_iface.c | 26 +++++++
+ hostapd/hostapd_cli.c | 9 +++
+ src/ap/ap_config.c | 1 +
+ src/ap/ap_config.h | 1 +
+ src/ap/ap_drv_ops.c | 14 ++++
+ src/ap/ap_drv_ops.h | 2 +
+ src/ap/hostapd.c | 2 +
+ src/common/mtk_vendor.h | 17 ++++-
+ src/drivers/driver.h | 9 +++
+ src/drivers/driver_nl80211.c | 114 ++++++++++++++++++++++++++++++
+ src/drivers/driver_nl80211.h | 1 +
+ src/drivers/driver_nl80211_capa.c | 3 +
+ 13 files changed, 207 insertions(+), 1 deletion(-)
+
+diff --git a/hostapd/config_file.c b/hostapd/config_file.c
+index 09b5605..dc3defe 100644
+--- a/hostapd/config_file.c
++++ b/hostapd/config_file.c
+@@ -4851,6 +4851,15 @@ static int hostapd_config_fill(struct hostapd_config *conf,
+ u8 en = strtol(pos, NULL, 10);
+
+ conf->dfs_detect_mode = en;
++ } else if (os_strcmp(buf, "amsdu") == 0) {
++ int val = atoi(pos);
++ if (val < 0 || val > 1) {
++ wpa_printf(MSG_ERROR,
++ "Line %d: invalid amsdu value",
++ line);
++ return 1;
++ }
++ conf->amsdu = val;
+ } else {
+ wpa_printf(MSG_ERROR,
+ "Line %d: unknown configuration item '%s'",
+diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
+index 40fb0d4..07de0ad 100644
+--- a/hostapd/ctrl_iface.c
++++ b/hostapd/ctrl_iface.c
+@@ -3687,6 +3687,30 @@ hostapd_ctrl_iface_set_offchan_ctrl(struct hostapd_data *hapd, char *cmd,
+ }
+
+
++static int
++hostapd_ctrl_iface_get_amsdu(struct hostapd_data *hapd, char *buf,
++ size_t buflen)
++{
++ u8 amsdu;
++ int ret;
++ char *pos, *end;
++
++ pos = buf;
++ end = buf + buflen;
++
++ if (hostapd_drv_amsdu_dump(hapd, &amsdu) == 0) {
++ hapd->iconf->amsdu = amsdu;
++ ret = os_snprintf(pos, end - pos, "[hostapd_cli] AMSDU: %u\n",
++ hapd->iconf->amsdu);
++ }
++
++ if (os_snprintf_error(end - pos, ret))
++ return 0;
++
++ return ret;
++}
++
++
+ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
+ char *buf, char *reply,
+ int reply_size,
+@@ -4260,6 +4284,8 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
+ 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 {
+ os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
+ reply_len = 16;
+diff --git a/hostapd/hostapd_cli.c b/hostapd/hostapd_cli.c
+index 5922fe3..04451f5 100644
+--- a/hostapd/hostapd_cli.c
++++ b/hostapd/hostapd_cli.c
+@@ -1613,6 +1613,13 @@ static int hostapd_cli_cmd_get_ibf(struct wpa_ctrl *ctrl, int argc,
+ }
+
+
++static int hostapd_cli_cmd_get_amsdu(struct wpa_ctrl *ctrl, int argc,
++ char *argv[])
++{
++ return hostapd_cli_cmd(ctrl, "GET_AMSDU", 0, NULL, NULL);
++}
++
++
+ struct hostapd_cli_cmd {
+ const char *cmd;
+ int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
+@@ -1820,6 +1827,8 @@ static const struct hostapd_cli_cmd hostapd_cli_commands[] = {
+ "<tx type(0/1/2)> <interval> = runtime set inband discovery" },
+ { "get_ibf", hostapd_cli_cmd_get_ibf, NULL,
+ " = show iBF state (enabled/disabled)"},
++ { "get_amsdu", hostapd_cli_cmd_get_amsdu, NULL,
++ " = show AMSDU state"},
+ { NULL, NULL, NULL, NULL }
+ };
+
+diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
+index a9f77e0..f437f9f 100644
+--- a/src/ap/ap_config.c
++++ b/src/ap/ap_config.c
+@@ -299,6 +299,7 @@ struct hostapd_config * hostapd_config_defaults(void)
+ conf->edcca_compensation = EDCCA_DEFAULT_COMPENSATION;
+ conf->three_wire_enable = THREE_WIRE_MODE_DISABLE;
+ conf->ibf_enable = IBF_DEFAULT_ENABLE;
++ conf->amsdu = 1;
+
+ return conf;
+ }
+diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
+index d651bfb..7732af0 100644
+--- a/src/ap/ap_config.h
++++ b/src/ap/ap_config.h
+@@ -1188,6 +1188,7 @@ struct hostapd_config {
+ u8 three_wire_enable;
+ u8 ibf_enable;
+ u8 dfs_detect_mode;
++ u8 amsdu;
+ };
+
+ enum three_wire_mode {
+diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c
+index 91ade16..00492b8 100644
+--- a/src/ap/ap_drv_ops.c
++++ b/src/ap/ap_drv_ops.c
+@@ -1116,4 +1116,18 @@ int hostapd_drv_ibf_dump(struct hostapd_data *hapd, u8 *ibf_enable)
+ if (!hapd->driver || !hapd->driver->ibf_dump)
+ return 0;
+ return hapd->driver->ibf_dump(hapd->drv_priv, ibf_enable);
++}
++
++int hostapd_drv_amsdu_ctrl(struct hostapd_data *hapd)
++{
++ if (!hapd->driver || !hapd->driver->amsdu_ctrl)
++ return 0;
++ return hapd->driver->amsdu_ctrl(hapd->drv_priv, hapd->iconf->amsdu);
++}
++
++int hostapd_drv_amsdu_dump(struct hostapd_data *hapd, u8 *amsdu)
++{
++ if (!hapd->driver || !hapd->driver->amsdu_dump)
++ return 0;
++ return hapd->driver->amsdu_dump(hapd->drv_priv, amsdu);
+ }
+\ No newline at end of file
+diff --git a/src/ap/ap_drv_ops.h b/src/ap/ap_drv_ops.h
+index 2cc39b7..2b8b587 100644
+--- a/src/ap/ap_drv_ops.h
++++ b/src/ap/ap_drv_ops.h
+@@ -153,6 +153,8 @@ int hostapd_drv_mu_dump(struct hostapd_data *hapd, u8 *mu_onoff);
+ int hostapd_drv_three_wire_ctrl(struct hostapd_data *hapd);
+ int hostapd_drv_ibf_ctrl(struct hostapd_data *hapd);
+ int hostapd_drv_ibf_dump(struct hostapd_data *hapd, u8 *ibf_enable);
++int hostapd_drv_amsdu_ctrl(struct hostapd_data *hapd);
++int hostapd_drv_amsdu_dump(struct hostapd_data *hapd, u8 *amsdu);
+
+ #include "drivers/driver.h"
+
+diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
+index 2deb9a3..88eb984 100644
+--- a/src/ap/hostapd.c
++++ b/src/ap/hostapd.c
+@@ -2402,6 +2402,8 @@ dfs_offload:
+ goto fail;
+ if (hostapd_drv_ibf_ctrl(hapd) < 0)
+ goto fail;
++ if (hostapd_drv_amsdu_ctrl(hapd) < 0)
++ goto fail;
+
+ wpa_printf(MSG_DEBUG, "%s: Setup of interface done.",
+ iface->bss[0]->conf->iface);
+diff --git a/src/common/mtk_vendor.h b/src/common/mtk_vendor.h
+index 7b7aeaa..97c5a47 100644
+--- a/src/common/mtk_vendor.h
++++ b/src/common/mtk_vendor.h
+@@ -167,7 +167,6 @@ enum mtk_vendor_attr_wireless_ctrl {
+ MTK_VENDOR_ATTR_WIRELESS_CTRL_NUSERS_OFDMA,
+ MTK_VENDOR_ATTR_WIRELESS_CTRL_BA_BUFFER_SIZE,
+ MTK_VENDOR_ATTR_WIRELESS_CTRL_MIMO,
+- MTK_VENDOR_ATTR_WIRELESS_CTRL_AMPDU,
+ MTK_VENDOR_ATTR_WIRELESS_CTRL_AMSDU,
+ MTK_VENDOR_ATTR_WIRELESS_CTRL_CERT,
+
+@@ -177,6 +176,22 @@ enum mtk_vendor_attr_wireless_ctrl {
+ NUM_MTK_VENDOR_ATTRS_WIRELESS_CTRL - 1
+ };
+
++enum mtk_vendor_attr_wireless_dump {
++ MTK_VENDOR_ATTR_WIRELESS_DUMP_UNSPEC,
++
++ MTK_VENDOR_ATTR_WIRELESS_DUMP_AMSDU,
++
++ /* keep last */
++ NUM_MTK_VENDOR_ATTRS_WIRELESS_DUMP,
++ MTK_VENDOR_ATTR_WIRELESS_DUMP_MAX =
++ NUM_MTK_VENDOR_ATTRS_WIRELESS_DUMP - 1
++};
++
++static const struct nla_policy
++wireless_dump_policy[NUM_MTK_VENDOR_ATTRS_WIRELESS_DUMP] = {
++ [MTK_VENDOR_ATTR_WIRELESS_DUMP_AMSDU] = { .type = NLA_U8 },
++};
++
+ enum mtk_vendor_attr_rfeature_ctrl {
+ MTK_VENDOR_ATTR_RFEATURE_CTRL_UNSPEC,
+
+diff --git a/src/drivers/driver.h b/src/drivers/driver.h
+index 9e12e42..2144cc4 100644
+--- a/src/drivers/driver.h
++++ b/src/drivers/driver.h
+@@ -5045,6 +5045,15 @@ struct wpa_driver_ops {
+ *
+ */
+ int (*ibf_dump)(void *priv, u8 *ibf_enable);
++
++ /**
++ * amsdu_ctrl - enable/disable amsdu
++ * amsdu_dump - get current amsdu status
++ * @priv: Private driver interface data
++ *
++ */
++ int (*amsdu_ctrl)(void *priv, u8 amsdu);
++ int (*amsdu_dump)(void *priv, u8 *amsdu);
+ };
+
+ /**
+diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
+index 641b894..7c20b14 100644
+--- a/src/drivers/driver_nl80211.c
++++ b/src/drivers/driver_nl80211.c
+@@ -13774,6 +13774,118 @@ fail:
+ return -ENOBUFS;
+ }
+
++static int nl80211_enable_amsdu(void *priv, u8 amsdu)
++{
++ struct i802_bss *bss = priv;
++ struct wpa_driver_nl80211_data *drv = bss->drv;
++ struct nl_msg *msg;
++ struct nlattr *data;
++ int ret;
++
++ if (!drv->mtk_wireless_vendor_cmd_avail) {
++ wpa_printf(MSG_INFO,
++ "nl80211: Driver does not support setting ap wireless control");
++ return 0;
++ }
++
++ msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR);
++ if (!msg)
++ goto fail;
++
++ if (nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_MTK) ||
++ nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD, MTK_NL80211_VENDOR_SUBCMD_WIRELESS_CTRL))
++ goto fail;
++
++ data = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA);
++ if (!data)
++ goto fail;
++
++ nla_put_u8(msg, MTK_VENDOR_ATTR_WIRELESS_CTRL_AMSDU, amsdu);
++
++ nla_nest_end(msg, data);
++ ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
++ if (ret) {
++ wpa_printf(MSG_ERROR, "Failed to set amsdu. ret=%d (%s)", ret, strerror(-ret));
++ }
++
++ return ret;
++
++fail:
++ nlmsg_free(msg);
++ return -ENOBUFS;
++}
++
++static int dump_amsdu_handler(struct nl_msg *msg, void *arg)
++{
++ u8 *amsdu = (u8 *) arg;
++ struct nlattr *tb[NL80211_ATTR_MAX + 1];
++ struct nlattr *tb_vendor[MTK_VENDOR_ATTR_WIRELESS_DUMP_MAX + 1];
++ struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
++ struct nlattr *nl_vend, *attr_amsdu;
++
++ nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
++ genlmsg_attrlen(gnlh, 0), NULL);
++
++ nl_vend = tb[NL80211_ATTR_VENDOR_DATA];
++ if (!nl_vend)
++ return NL_SKIP;
++
++ nla_parse(tb_vendor, MTK_VENDOR_ATTR_WIRELESS_DUMP_MAX,
++ nla_data(nl_vend), nla_len(nl_vend), NULL);
++
++ attr_amsdu = tb_vendor[MTK_VENDOR_ATTR_WIRELESS_DUMP_AMSDU];
++ if (!attr_amsdu ){
++ wpa_printf(MSG_ERROR, "nl80211: cannot find vendor attributes");
++ return NL_SKIP;
++ }
++
++ *amsdu = nla_get_u8(attr_amsdu);
++
++ return NL_SKIP;
++}
++
++static int
++nl80211_dump_amsdu(void *priv, u8 *amsdu)
++{
++ struct i802_bss *bss = priv;
++ struct wpa_driver_nl80211_data *drv = bss->drv;
++ struct nl_msg *msg;
++ struct nlattr *data;
++ int ret;
++
++ if (!drv->mtk_wireless_vendor_cmd_avail) {
++ wpa_printf(MSG_INFO,
++ "nl80211: Driver does not support ap_wireless control");
++ return 0;
++ }
++
++ msg = nl80211_drv_msg(drv, NLM_F_DUMP, NL80211_CMD_VENDOR);
++ if (!msg)
++ goto fail;
++
++ if (nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_MTK) ||
++ nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD, MTK_NL80211_VENDOR_SUBCMD_WIRELESS_CTRL))
++ goto fail;
++
++ data = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA);
++ if (!data)
++ goto fail;
++
++ nla_nest_end(msg, data);
++
++ ret = send_and_recv_msgs(drv, msg, dump_amsdu_handler, amsdu, NULL, NULL);
++
++ if (ret) {
++ wpa_printf(MSG_ERROR, "Failed to dump amsdu. ret=%d (%s)", ret, strerror(-ret));
++ }
++
++ return ret;
++
++fail:
++ nlmsg_free(msg);
++ return -ENOBUFS;
++}
++
+ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
+ .name = "nl80211",
+ .desc = "Linux nl80211/cfg80211",
+@@ -13935,4 +14047,6 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
+ .three_wire_ctrl = nl80211_enable_three_wire,
+ .ibf_ctrl = nl80211_ibf_enable,
+ .ibf_dump = nl80211_ibf_dump,
++ .amsdu_ctrl = nl80211_enable_amsdu,
++ .amsdu_dump = nl80211_dump_amsdu,
+ };
+diff --git a/src/drivers/driver_nl80211.h b/src/drivers/driver_nl80211.h
+index 9ef313b..3bcc770 100644
+--- a/src/drivers/driver_nl80211.h
++++ b/src/drivers/driver_nl80211.h
+@@ -203,6 +203,7 @@ struct wpa_driver_nl80211_data {
+ unsigned int mtk_mu_vendor_cmd_avail:1;
+ unsigned int mtk_3wire_vendor_cmd_avail:1;
+ unsigned int mtk_ibf_vendor_cmd_avail:1;
++ unsigned int mtk_wireless_vendor_cmd_avail:1;
+
+ u64 vendor_scan_cookie;
+ u64 remain_on_chan_cookie;
+diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c
+index 5c6bb36..dee99f0 100644
+--- a/src/drivers/driver_nl80211_capa.c
++++ b/src/drivers/driver_nl80211_capa.c
+@@ -1114,6 +1114,9 @@ static int wiphy_info_handler(struct nl_msg *msg, void *arg)
+ case MTK_NL80211_VENDOR_SUBCMD_IBF_CTRL:
+ drv->mtk_ibf_vendor_cmd_avail = 1;
+ break;
++ case MTK_NL80211_VENDOR_SUBCMD_WIRELESS_CTRL:
++ drv->mtk_wireless_vendor_cmd_avail = 1;
++ break;
+ }
+ }
+
+--
+2.18.0
+
diff --git a/autobuild_mac80211_release/package/network/services/hostapd_new/patches/mtk-0013-hostapd-mtk-Add-he_ldpc-configuration.patch b/autobuild_mac80211_release/package/network/services/hostapd_new/patches/mtk-0013-hostapd-mtk-Add-he_ldpc-configuration.patch
new file mode 100644
index 0000000..0f096d4
--- /dev/null
+++ b/autobuild_mac80211_release/package/network/services/hostapd_new/patches/mtk-0013-hostapd-mtk-Add-he_ldpc-configuration.patch
@@ -0,0 +1,102 @@
+From cacedd3d26510c3eaf923d19ac16813162ff7727 Mon Sep 17 00:00:00 2001
+From: MeiChia Chiu <meichia.chiu@mediatek.com>
+Date: Thu, 12 Jan 2023 15:18:19 +0800
+Subject: [PATCH 13/28] hostapd: mtk: Add he_ldpc configuration
+
+---
+ hostapd/config_file.c | 2 ++
+ hostapd/hostapd.conf | 5 +++++
+ src/ap/ap_config.c | 1 +
+ src/ap/ap_config.h | 1 +
+ src/ap/ieee802_11_he.c | 7 +++++++
+ src/common/ieee802_11_defs.h | 3 +++
+ 6 files changed, 19 insertions(+)
+
+diff --git a/hostapd/config_file.c b/hostapd/config_file.c
+index dc3defe..ac8359a 100644
+--- a/hostapd/config_file.c
++++ b/hostapd/config_file.c
+@@ -3517,6 +3517,8 @@ static int hostapd_config_fill(struct hostapd_config *conf,
+ conf->he_phy_capab.he_su_beamformee = atoi(pos);
+ } else if (os_strcmp(buf, "he_mu_beamformer") == 0) {
+ conf->he_phy_capab.he_mu_beamformer = atoi(pos);
++ } else if (os_strcmp(buf, "he_ldpc") == 0) {
++ conf->he_phy_capab.he_ldpc = atoi(pos);
+ } else if (os_strcmp(buf, "he_bss_color") == 0) {
+ conf->he_op.he_bss_color = atoi(pos) & 0x3f;
+ conf->he_op.he_bss_color_disabled = 0;
+diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf
+index bc4a0f6..d95a11e 100644
+--- a/hostapd/hostapd.conf
++++ b/hostapd/hostapd.conf
+@@ -833,6 +833,11 @@ wmm_ac_vo_acm=0
+ # 1 = supported
+ #he_mu_beamformer=1
+
++#he_ldpc: HE LDPC support
++# 0 = not supported
++# 1 = supported (default)
++#he_ldpc=1
++
+ # he_bss_color: BSS color (1-63)
+ #he_bss_color=1
+
+diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
+index f437f9f..26d6770 100644
+--- a/src/ap/ap_config.c
++++ b/src/ap/ap_config.c
+@@ -268,6 +268,7 @@ struct hostapd_config * hostapd_config_defaults(void)
+ #endif /* CONFIG_ACS */
+
+ #ifdef CONFIG_IEEE80211AX
++ conf->he_phy_capab.he_ldpc = 1;
+ conf->he_op.he_rts_threshold = HE_OPERATION_RTS_THRESHOLD_MASK >>
+ HE_OPERATION_RTS_THRESHOLD_OFFSET;
+ /* Set default basic MCS/NSS set to single stream MCS 0-7 */
+diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
+index 7732af0..b9aaa85 100644
+--- a/src/ap/ap_config.h
++++ b/src/ap/ap_config.h
+@@ -945,6 +945,7 @@ struct hostapd_bss_config {
+ * struct he_phy_capabilities_info - HE PHY capabilities
+ */
+ struct he_phy_capabilities_info {
++ bool he_ldpc;
+ bool he_su_beamformer;
+ bool he_su_beamformee;
+ bool he_mu_beamformer;
+diff --git a/src/ap/ieee802_11_he.c b/src/ap/ieee802_11_he.c
+index 548a448..9407dd6 100644
+--- a/src/ap/ieee802_11_he.c
++++ b/src/ap/ieee802_11_he.c
+@@ -138,6 +138,13 @@ u8 * hostapd_eid_he_capab(struct hostapd_data *hapd, u8 *eid,
+ os_memcpy(&cap->optional[mcs_nss_size],
+ mode->he_capab[opmode].ppet, ppet_size);
+
++ if (hapd->iface->conf->he_phy_capab.he_ldpc)
++ cap->he_phy_capab_info[HE_PHYCAP_LDPC_CODING_IN_PAYLOAD_IDX] |=
++ HE_PHYCAP_LDPC_CODING_IN_PAYLOAD;
++ else
++ cap->he_phy_capab_info[HE_PHYCAP_LDPC_CODING_IN_PAYLOAD_IDX] &=
++ ~HE_PHYCAP_LDPC_CODING_IN_PAYLOAD;
++
+ if (hapd->iface->conf->he_phy_capab.he_su_beamformer)
+ cap->he_phy_capab_info[HE_PHYCAP_SU_BEAMFORMER_CAPAB_IDX] |=
+ HE_PHYCAP_SU_BEAMFORMER_CAPAB;
+diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h
+index dfad0b7..bc8fe05 100644
+--- a/src/common/ieee802_11_defs.h
++++ b/src/common/ieee802_11_defs.h
+@@ -2355,6 +2355,9 @@ struct ieee80211_spatial_reuse {
+ #define HE_PHYCAP_CHANNEL_WIDTH_SET_160MHZ_IN_5G ((u8) BIT(3))
+ #define HE_PHYCAP_CHANNEL_WIDTH_SET_80PLUS80MHZ_IN_5G ((u8) BIT(4))
+
++#define HE_PHYCAP_LDPC_CODING_IN_PAYLOAD_IDX 1
++#define HE_PHYCAP_LDPC_CODING_IN_PAYLOAD ((u8) BIT(5))
++
+ #define HE_PHYCAP_SU_BEAMFORMER_CAPAB_IDX 3
+ #define HE_PHYCAP_SU_BEAMFORMER_CAPAB ((u8) BIT(7))
+ #define HE_PHYCAP_SU_BEAMFORMEE_CAPAB_IDX 4
+--
+2.18.0
+
diff --git a/autobuild_mac80211_release/package/network/services/hostapd_new/patches/mtk-0014-hostapd-mtk-Add-vendor-command-attribute-for-RTS-BW-.patch b/autobuild_mac80211_release/package/network/services/hostapd_new/patches/mtk-0014-hostapd-mtk-Add-vendor-command-attribute-for-RTS-BW-.patch
new file mode 100644
index 0000000..6b22222
--- /dev/null
+++ b/autobuild_mac80211_release/package/network/services/hostapd_new/patches/mtk-0014-hostapd-mtk-Add-vendor-command-attribute-for-RTS-BW-.patch
@@ -0,0 +1,26 @@
+From 6bf2c734595e9faa8ba39bdda119e292fb747107 Mon Sep 17 00:00:00 2001
+From: "himanshu.goyal" <himanshu.goyal@mediatek.com>
+Date: Tue, 24 Jan 2023 19:06:44 +0800
+Subject: [PATCH 14/28] hostapd: mtk: Add vendor command attribute for RTS BW
+ signaling.
+
+Signed-off-by: himanshu.goyal <himanshu.goyal@mediatek.com>
+---
+ src/common/mtk_vendor.h | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/src/common/mtk_vendor.h b/src/common/mtk_vendor.h
+index 97c5a47..62d79cb 100644
+--- a/src/common/mtk_vendor.h
++++ b/src/common/mtk_vendor.h
+@@ -169,6 +169,7 @@ enum mtk_vendor_attr_wireless_ctrl {
+ MTK_VENDOR_ATTR_WIRELESS_CTRL_MIMO,
+ MTK_VENDOR_ATTR_WIRELESS_CTRL_AMSDU,
+ MTK_VENDOR_ATTR_WIRELESS_CTRL_CERT,
++ MTK_VENDOR_ATTR_WIRELESS_CTRL_RTS_SIGTA,
+
+ /* keep last */
+ NUM_MTK_VENDOR_ATTRS_WIRELESS_CTRL,
+--
+2.18.0
+
diff --git a/autobuild_mac80211_release/package/network/services/hostapd_new/patches/mtk-0015-hostapd-mtk-6G-band-does-not-require-DFS.patch b/autobuild_mac80211_release/package/network/services/hostapd_new/patches/mtk-0015-hostapd-mtk-6G-band-does-not-require-DFS.patch
new file mode 100644
index 0000000..f17fe17
--- /dev/null
+++ b/autobuild_mac80211_release/package/network/services/hostapd_new/patches/mtk-0015-hostapd-mtk-6G-band-does-not-require-DFS.patch
@@ -0,0 +1,24 @@
+From 0d48d01ab386b4999a7914009d3b0878823535e7 Mon Sep 17 00:00:00 2001
+From: Peter Chiu <chui-hao.chiu@mediatek.com>
+Date: Mon, 13 Feb 2023 11:03:53 +0800
+Subject: [PATCH 15/28] hostapd: mtk: 6G band does not require DFS
+
+---
+ src/ap/dfs.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/src/ap/dfs.c b/src/ap/dfs.c
+index 48c5fc9..dcf89ce 100644
+--- a/src/ap/dfs.c
++++ b/src/ap/dfs.c
+@@ -1511,6 +1511,7 @@ int hostapd_is_dfs_required(struct hostapd_iface *iface)
+ if ((!(iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD) &&
+ !iface->conf->ieee80211h) ||
+ !iface->current_mode ||
++ is_6ghz_freq(iface->freq) ||
+ iface->current_mode->mode != HOSTAPD_MODE_IEEE80211A)
+ return 0;
+
+--
+2.18.0
+
diff --git a/autobuild_mac80211_release/package/network/services/hostapd_new/patches/mtk-0016-hostapd-mtk-Fix-sending-wrong-VHT-operation-IE-in-CS.patch b/autobuild_mac80211_release/package/network/services/hostapd_new/patches/mtk-0016-hostapd-mtk-Fix-sending-wrong-VHT-operation-IE-in-CS.patch
new file mode 100644
index 0000000..08b8327
--- /dev/null
+++ b/autobuild_mac80211_release/package/network/services/hostapd_new/patches/mtk-0016-hostapd-mtk-Fix-sending-wrong-VHT-operation-IE-in-CS.patch
@@ -0,0 +1,46 @@
+From ded7bc8b684fa76874abc1ba47f59ecdf7126bdb Mon Sep 17 00:00:00 2001
+From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+Date: Mon, 20 Feb 2023 11:01:18 +0800
+Subject: [PATCH 16/28] hostapd: mtk: Fix sending wrong VHT operation IE in CSA
+ while using ZWDFS
+
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+---
+ src/ap/dfs.c | 14 +++++++++-----
+ 1 file changed, 9 insertions(+), 5 deletions(-)
+
+diff --git a/src/ap/dfs.c b/src/ap/dfs.c
+index dcf89ce..e5ed645 100644
+--- a/src/ap/dfs.c
++++ b/src/ap/dfs.c
+@@ -1115,6 +1115,14 @@ static int
+ hostapd_dfs_start_channel_switch_background(struct hostapd_iface *iface)
+ {
+ u8 current_vht_oper_chwidth = hostapd_get_oper_chwidth(iface->conf);
++ int ret;
++
++ ret = hostapd_dfs_request_channel_switch(iface, iface->radar_background.channel,
++ iface->radar_background.freq,
++ iface->radar_background.secondary_channel,
++ current_vht_oper_chwidth,
++ iface->radar_background.centr_freq_seg0_idx,
++ iface->radar_background.centr_freq_seg1_idx);
+
+ iface->conf->channel = iface->radar_background.channel;
+ iface->freq = iface->radar_background.freq;
+@@ -1127,11 +1135,7 @@ hostapd_dfs_start_channel_switch_background(struct hostapd_iface *iface)
+
+ hostpad_dfs_update_background_chain(iface);
+
+- 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));
++ return ret;
+ }
+
+
+--
+2.18.0
+
diff --git a/autobuild_mac80211_release/package/network/services/hostapd_new/patches/mtk-0017-hostapd-mtk-Add-sta-assisted-DFS-state-update-mechan.patch b/autobuild_mac80211_release/package/network/services/hostapd_new/patches/mtk-0017-hostapd-mtk-Add-sta-assisted-DFS-state-update-mechan.patch
new file mode 100644
index 0000000..5259512
--- /dev/null
+++ b/autobuild_mac80211_release/package/network/services/hostapd_new/patches/mtk-0017-hostapd-mtk-Add-sta-assisted-DFS-state-update-mechan.patch
@@ -0,0 +1,189 @@
+From dda8da5352e042ff4fb1621c58624981ee00dce7 Mon Sep 17 00:00:00 2001
+From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+Date: Mon, 20 Feb 2023 10:51:47 +0800
+Subject: [PATCH 17/28] hostapd: mtk: Add sta-assisted DFS state update
+ mechanism
+
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+---
+ src/ap/dfs.c | 20 ++++++++++++++++++++
+ src/ap/dfs.h | 3 +++
+ src/ap/drv_callbacks.c | 28 ++++++++++++++++++++++++++++
+ src/common/wpa_ctrl.h | 1 +
+ src/drivers/driver.h | 14 ++++++++++++++
+ src/drivers/driver_nl80211_event.c | 6 ++++++
+ src/drivers/nl80211_copy.h | 6 ++++++
+ 7 files changed, 78 insertions(+)
+
+diff --git a/src/ap/dfs.c b/src/ap/dfs.c
+index e5ed645..d52a60e 100644
+--- a/src/ap/dfs.c
++++ b/src/ap/dfs.c
+@@ -1508,6 +1508,26 @@ int hostapd_dfs_nop_finished(struct hostapd_iface *iface, int freq,
+ }
+
+
++int hostapd_dfs_sta_update_state(struct hostapd_iface *iface, int freq,
++ int ht_enabled, int chan_offset, int chan_width,
++ int cf1, int cf2, u32 state)
++{
++ wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_STA_UPDATE
++ "freq=%d ht_enabled=%d chan_offset=%d chan_width=%d cf1=%d cf2=%d state=%s",
++ freq, ht_enabled, chan_offset, chan_width, cf1, cf2,
++ (state == HOSTAPD_CHAN_DFS_AVAILABLE) ? "available" : "usable");
++
++ /* Proceed only if DFS is not offloaded to the driver */
++ if (iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD)
++ return 0;
++
++ set_dfs_state(iface, freq, ht_enabled, chan_offset, chan_width,
++ cf1, cf2, state);
++
++ return 0;
++}
++
++
+ int hostapd_is_dfs_required(struct hostapd_iface *iface)
+ {
+ int n_chans, n_chans1, start_chan_idx, start_chan_idx1, res;
+diff --git a/src/ap/dfs.h b/src/ap/dfs.h
+index c2556d2..25ba29c 100644
+--- a/src/ap/dfs.h
++++ b/src/ap/dfs.h
+@@ -30,6 +30,9 @@ int hostapd_dfs_radar_detected(struct hostapd_iface *iface, int freq,
+ int hostapd_dfs_nop_finished(struct hostapd_iface *iface, int freq,
+ int ht_enabled,
+ int chan_offset, int chan_width, int cf1, int cf2);
++int hostapd_dfs_sta_update_state(struct hostapd_iface *iface, int freq,
++ int ht_enabled, int chan_offset, int chan_width,
++ int cf1, int cf2, u32 state);
+ int hostapd_is_dfs_required(struct hostapd_iface *iface);
+ int hostapd_is_dfs_chan_available(struct hostapd_iface *iface);
+ int hostapd_dfs_start_cac(struct hostapd_iface *iface, int freq,
+diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c
+index ede88b2..c1f9a0e 100644
+--- a/src/ap/drv_callbacks.c
++++ b/src/ap/drv_callbacks.c
+@@ -1805,6 +1805,24 @@ static void hostapd_event_dfs_cac_started(struct hostapd_data *hapd,
+ radar->cf1, radar->cf2);
+ }
+
++static void hostapd_event_dfs_sta_cac_skipped(struct hostapd_data *hapd,
++ struct dfs_event *radar)
++{
++ wpa_printf(MSG_DEBUG, "DFS CAC skipped (by STA) on %d MHz", radar->freq);
++ hostapd_dfs_sta_update_state(hapd->iface, radar->freq, radar->ht_enabled,
++ radar->chan_offset, radar->chan_width,
++ radar->cf1, radar->cf2, HOSTAPD_CHAN_DFS_AVAILABLE);
++}
++
++static void hostapd_event_dfs_sta_cac_expired(struct hostapd_data *hapd,
++ struct dfs_event *radar)
++{
++ wpa_printf(MSG_DEBUG, "DFS CAC expired (by STA) on %d MHz", radar->freq);
++ hostapd_dfs_sta_update_state(hapd->iface, radar->freq, radar->ht_enabled,
++ radar->chan_offset, radar->chan_width,
++ radar->cf1, radar->cf2, HOSTAPD_CHAN_DFS_USABLE);
++}
++
+ #endif /* NEED_AP_MLME */
+
+
+@@ -2080,6 +2098,16 @@ void hostapd_wpa_event(void *ctx, enum wpa_event_type event,
+ break;
+ hostapd_event_dfs_nop_finished(hapd, &data->dfs_event);
+ break;
++ case EVENT_DFS_STA_CAC_SKIPPED:
++ if (!data)
++ break;
++ hostapd_event_dfs_sta_cac_skipped(hapd, &data->dfs_event);
++ break;
++ case EVENT_DFS_STA_CAC_EXPIRED:
++ if (!data)
++ break;
++ hostapd_event_dfs_sta_cac_expired(hapd, &data->dfs_event);
++ break;
+ case EVENT_CHANNEL_LIST_CHANGED:
+ /* channel list changed (regulatory?), update channel list */
+ /* TODO: check this. hostapd_get_hw_features() initializes
+diff --git a/src/common/wpa_ctrl.h b/src/common/wpa_ctrl.h
+index 4ab2a1b..866ae0b 100644
+--- a/src/common/wpa_ctrl.h
++++ b/src/common/wpa_ctrl.h
+@@ -369,6 +369,7 @@ extern "C" {
+ #define DFS_EVENT_CAC_COMPLETED "DFS-CAC-COMPLETED "
+ #define DFS_EVENT_NOP_FINISHED "DFS-NOP-FINISHED "
+ #define DFS_EVENT_PRE_CAC_EXPIRED "DFS-PRE-CAC-EXPIRED "
++#define DFS_EVENT_STA_UPDATE "DFS-STA-UPDATE "
+
+ #define AP_CSA_FINISHED "AP-CSA-FINISHED "
+
+diff --git a/src/drivers/driver.h b/src/drivers/driver.h
+index 2144cc4..faa4b7b 100644
+--- a/src/drivers/driver.h
++++ b/src/drivers/driver.h
+@@ -5666,6 +5666,20 @@ enum wpa_event_type {
+ * Described in wpa_event_data.ch_switch.
+ */
+ EVENT_LINK_CH_SWITCH_STARTED,
++
++ /**
++ * EVENT_DFS_STA_CAC_SKIPPED - Notification that CAC has been skipped
++ *
++ * The channel in the notification is now marked as available.
++ */
++ EVENT_DFS_STA_CAC_SKIPPED,
++
++ /**
++ * EVENT_DFS_STA_CAC_EXPIRED - Notification that CAC has expired
++ *
++ * The channel in the notification is now marked as usable.
++ */
++ EVENT_DFS_STA_CAC_EXPIRED,
+ };
+
+
+diff --git a/src/drivers/driver_nl80211_event.c b/src/drivers/driver_nl80211_event.c
+index a45804c..67d9ce2 100644
+--- a/src/drivers/driver_nl80211_event.c
++++ b/src/drivers/driver_nl80211_event.c
+@@ -2217,6 +2217,12 @@ static void nl80211_radar_event(struct wpa_driver_nl80211_data *drv,
+ case NL80211_RADAR_CAC_STARTED:
+ wpa_supplicant_event(drv->ctx, EVENT_DFS_CAC_STARTED, &data);
+ break;
++ case NL80211_RADAR_STA_CAC_SKIPPED:
++ wpa_supplicant_event(drv->ctx, EVENT_DFS_STA_CAC_SKIPPED, &data);
++ break;
++ case NL80211_RADAR_STA_CAC_EXPIRED:
++ wpa_supplicant_event(drv->ctx, EVENT_DFS_STA_CAC_EXPIRED, &data);
++ break;
+ default:
+ wpa_printf(MSG_DEBUG, "nl80211: Unknown radar event %d "
+ "received", event_type);
+diff --git a/src/drivers/nl80211_copy.h b/src/drivers/nl80211_copy.h
+index 12fc6a9..6493023 100644
+--- a/src/drivers/nl80211_copy.h
++++ b/src/drivers/nl80211_copy.h
+@@ -6621,6 +6621,10 @@ enum nl80211_smps_mode {
+ * applicable for ETSI dfs domain where pre-CAC is valid for ever.
+ * @NL80211_RADAR_CAC_STARTED: Channel Availability Check has been started,
+ * should be generated by HW if NL80211_EXT_FEATURE_DFS_OFFLOAD is enabled.
++ * @NL80211_RADAR_STA_CAC_SKIPPED: STA set the DFS state to available
++ * when receiving CSA/assoc resp
++ * @NL80211_RADAR_STA_CAC_EXPIRED: STA set the DFS state to usable
++ * when STA is disconnected or leaving the channel
+ */
+ enum nl80211_radar_event {
+ NL80211_RADAR_DETECTED,
+@@ -6629,6 +6633,8 @@ enum nl80211_radar_event {
+ NL80211_RADAR_NOP_FINISHED,
+ NL80211_RADAR_PRE_CAC_EXPIRED,
+ NL80211_RADAR_CAC_STARTED,
++ NL80211_RADAR_STA_CAC_SKIPPED,
++ NL80211_RADAR_STA_CAC_EXPIRED,
+ };
+
+ /**
+--
+2.18.0
+
diff --git a/autobuild_mac80211_release/package/network/services/hostapd_new/patches/mtk-0018-hostapd-mtk-Fix-auto-ht-issue-when-switching-to-DFS-.patch b/autobuild_mac80211_release/package/network/services/hostapd_new/patches/mtk-0018-hostapd-mtk-Fix-auto-ht-issue-when-switching-to-DFS-.patch
new file mode 100644
index 0000000..c53b55a
--- /dev/null
+++ b/autobuild_mac80211_release/package/network/services/hostapd_new/patches/mtk-0018-hostapd-mtk-Fix-auto-ht-issue-when-switching-to-DFS-.patch
@@ -0,0 +1,44 @@
+From 3237a993233da052219018eec10ca82d79225fdb Mon Sep 17 00:00:00 2001
+From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+Date: Mon, 20 Feb 2023 16:58:20 +0800
+Subject: [PATCH 18/28] hostapd: mtk: Fix auto ht issue when switching to DFS
+ channel
+
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+---
+ hostapd/ctrl_iface.c | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
+index 07de0ad..be86f6c 100644
+--- a/hostapd/ctrl_iface.c
++++ b/hostapd/ctrl_iface.c
+@@ -2773,6 +2773,12 @@ static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface,
+ break;
+ }
+
++ if (os_strstr(pos, " auto-ht")) {
++ settings.freq_params.ht_enabled = iface->conf->ieee80211n;
++ settings.freq_params.vht_enabled = iface->conf->ieee80211ac;
++ settings.freq_params.he_enabled = iface->conf->ieee80211ax;
++ }
++
+ if (settings.freq_params.center_freq1)
+ dfs_range += hostapd_is_dfs_overlap(
+ iface, bandwidth, settings.freq_params.center_freq1);
+@@ -2810,12 +2816,6 @@ static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface,
+ return 0;
+ }
+
+- if (os_strstr(pos, " auto-ht")) {
+- settings.freq_params.ht_enabled = iface->conf->ieee80211n;
+- settings.freq_params.vht_enabled = iface->conf->ieee80211ac;
+- settings.freq_params.he_enabled = iface->conf->ieee80211ax;
+- }
+-
+ for (i = 0; i < iface->num_bss; i++) {
+
+ /* Save CHAN_SWITCH VHT, HE, and EHT config */
+--
+2.18.0
+
diff --git a/autobuild_mac80211_release/package/network/services/hostapd_new/patches/mtk-0019-hostapd-mtk-Mark-DFS-channel-as-available-for-CSA.patch b/autobuild_mac80211_release/package/network/services/hostapd_new/patches/mtk-0019-hostapd-mtk-Mark-DFS-channel-as-available-for-CSA.patch
new file mode 100644
index 0000000..d38e758
--- /dev/null
+++ b/autobuild_mac80211_release/package/network/services/hostapd_new/patches/mtk-0019-hostapd-mtk-Mark-DFS-channel-as-available-for-CSA.patch
@@ -0,0 +1,60 @@
+From 5832d4ddc23f535932b590f5e8d16c349b4c4a51 Mon Sep 17 00:00:00 2001
+From: "himanshu.goyal" <himanshu.goyal@mediatek.com>
+Date: Fri, 3 Mar 2023 12:45:42 +0800
+Subject: [PATCH 19/28] hostapd: mtk: Mark DFS channel as available for CSA.
+
+---
+ hostapd/ctrl_iface.c | 10 ++++++++++
+ hostapd/hostapd_cli.c | 2 +-
+ src/ap/ctrl_iface_ap.c | 1 +
+ 3 files changed, 12 insertions(+), 1 deletion(-)
+
+diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
+index be86f6c..d09c22f 100644
+--- a/hostapd/ctrl_iface.c
++++ b/hostapd/ctrl_iface.c
+@@ -2779,6 +2779,16 @@ static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface,
+ settings.freq_params.he_enabled = iface->conf->ieee80211ax;
+ }
+
++ if (settings.freq_params.radar_background) {
++ hostapd_dfs_sta_update_state(iface,
++ settings.freq_params.freq,
++ settings.freq_params.ht_enabled,
++ settings.freq_params.sec_channel_offset,
++ bandwidth, settings.freq_params.center_freq1,
++ settings.freq_params.center_freq2,
++ HOSTAPD_CHAN_DFS_AVAILABLE);
++ }
++
+ if (settings.freq_params.center_freq1)
+ dfs_range += hostapd_is_dfs_overlap(
+ iface, bandwidth, settings.freq_params.center_freq1);
+diff --git a/hostapd/hostapd_cli.c b/hostapd/hostapd_cli.c
+index 04451f5..36d19d8 100644
+--- a/hostapd/hostapd_cli.c
++++ b/hostapd/hostapd_cli.c
+@@ -1715,7 +1715,7 @@ static const struct hostapd_cli_cmd hostapd_cli_commands[] = {
+ "<addr> = send QoS Map Configure frame" },
+ { "chan_switch", hostapd_cli_cmd_chan_switch, NULL,
+ "<cs_count> <freq> [sec_channel_offset=] [center_freq1=]\n"
+- " [center_freq2=] [bandwidth=] [blocktx] [ht|vht]\n"
++ " [center_freq2=] [bandwidth=] [blocktx] [ht|vht] [skip_cac]\n"
+ " = initiate channel switch announcement" },
+ { "hs20_wnm_notif", hostapd_cli_cmd_hs20_wnm_notif, NULL,
+ "<addr> <url>\n"
+diff --git a/src/ap/ctrl_iface_ap.c b/src/ap/ctrl_iface_ap.c
+index 38fc8e4..fed5473 100644
+--- a/src/ap/ctrl_iface_ap.c
++++ b/src/ap/ctrl_iface_ap.c
+@@ -999,6 +999,7 @@ int hostapd_parse_csa_settings(const char *pos,
+ settings->freq_params.vht_enabled = !!os_strstr(pos, " vht");
+ settings->freq_params.he_enabled = !!os_strstr(pos, " he");
+ settings->freq_params.eht_enabled = !!os_strstr(pos, " eht");
++ settings->freq_params.radar_background = !!os_strstr(pos, " skip_cac");
+ settings->block_tx = !!os_strstr(pos, " blocktx");
+ #undef SET_CSA_SETTING
+ #undef SET_CSA_SETTING_EXT
+--
+2.18.0
+
diff --git a/autobuild_mac80211_release/package/network/services/hostapd_new/patches/mtk-0020-hostapd-mtk-Add-available-color-bitmap.patch b/autobuild_mac80211_release/package/network/services/hostapd_new/patches/mtk-0020-hostapd-mtk-Add-available-color-bitmap.patch
new file mode 100644
index 0000000..ffdab20
--- /dev/null
+++ b/autobuild_mac80211_release/package/network/services/hostapd_new/patches/mtk-0020-hostapd-mtk-Add-available-color-bitmap.patch
@@ -0,0 +1,477 @@
+From e3a3b2a33385a97229956f83574b1ae60f39d2cc 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 20/28] hostapd: mtk: Add available color bitmap
+
+Signed-off-by: Yi-Chia Hsieh <yi-chia.hsieh@mediatek.com>
+---
+ hostapd/ctrl_iface.c | 74 +++++++++++
+ hostapd/hostapd_cli.c | 18 +++
+ src/ap/ap_drv_ops.c | 10 +-
+ src/ap/ap_drv_ops.h | 2 +
+ src/common/mtk_vendor.h | 11 ++
+ src/drivers/driver.h | 8 ++
+ src/drivers/driver_nl80211.c | 199 +++++++++++++++++++++++++++++-
+ src/drivers/driver_nl80211.h | 1 +
+ src/drivers/driver_nl80211_capa.c | 3 +
+ 9 files changed, 324 insertions(+), 2 deletions(-)
+
+diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
+index d09c22f..bc7a97b 100644
+--- a/hostapd/ctrl_iface.c
++++ b/hostapd/ctrl_iface.c
+@@ -3720,6 +3720,76 @@ hostapd_ctrl_iface_get_amsdu(struct hostapd_data *hapd, char *buf,
+ return ret;
+ }
+
++static int
++hostapd_ctrl_iface_get_bss_color(struct hostapd_data *hapd, char *buf,
++ size_t buflen)
++{
++ int ret;
++ char *pos, *end;
++ int i;
++
++ pos = buf;
++ end = buf + buflen;
++
++ if (hapd->iface->conf->he_op.he_bss_color_disabled)
++ ret = os_snprintf(buf, buflen, "BSS Color disabled\n");
++ else
++ ret = os_snprintf(buf, buflen, "BSS Color=%u\n",
++ hapd->iface->conf->he_op.he_bss_color);
++
++ pos += ret;
++
++ return pos - buf;
++}
++
++
++static int
++hostapd_ctrl_iface_get_aval_color_bmp(struct hostapd_data *hapd, char *buf,
++ size_t buflen)
++{
++ int ret;
++ char *pos, *end;
++ int i;
++ u64 aval_color_bmp = 0;
++
++ hostapd_drv_get_aval_bss_color_bmp(hapd, &aval_color_bmp);
++ hapd->color_collision_bitmap = ~aval_color_bmp;
++
++ pos = buf;
++ end = buf + buflen;
++
++ ret = os_snprintf(buf, buflen,
++ "available color bitmap=0x%llx\n",
++ aval_color_bmp);
++ if (os_snprintf_error(end - pos, ret))
++ return pos - buf;
++ pos += ret;
++
++ for (i = 0; i < HE_OPERATION_BSS_COLOR_MAX; i++) {
++ int bit = !!((aval_color_bmp >> i) & 1LLU);
++
++ if (i % 8 == 0) {
++ ret = os_snprintf(pos, end - pos, "%2d: ", i);
++ if (os_snprintf_error(end - pos, ret))
++ return pos - buf;
++ pos += ret;
++ }
++
++ ret = os_snprintf(pos, end - pos, "%d ", bit);
++ if (os_snprintf_error(end - pos, ret))
++ return pos - buf;
++ pos += ret;
++
++ if (i % 8 == 7) {
++ ret = os_snprintf(pos, end - pos, "\n");
++ if (os_snprintf_error(end - pos, ret))
++ return pos - buf;
++ pos += ret;
++ }
++ }
++ return pos - buf;
++}
++
+
+ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
+ char *buf, char *reply,
+@@ -4296,6 +4366,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);
+ } 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) {
++ reply_len = hostapd_ctrl_iface_get_bss_color(hapd, reply, reply_size);
++ } else if (os_strncmp(buf, "AVAL_COLOR_BMP", 14) == 0) {
++ reply_len = hostapd_ctrl_iface_get_aval_color_bmp(hapd, reply, reply_size);
+ } else {
+ os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
+ reply_len = 16;
+diff --git a/hostapd/hostapd_cli.c b/hostapd/hostapd_cli.c
+index 36d19d8..dc01ad9 100644
+--- a/hostapd/hostapd_cli.c
++++ b/hostapd/hostapd_cli.c
+@@ -1598,6 +1598,20 @@ static int hostapd_cli_cmd_reload_wpa_psk(struct wpa_ctrl *ctrl, int argc,
+ }
+
+
++static int hostapd_cli_cmd_get_bss_color(struct wpa_ctrl *ctrl, int argc,
++ char *argv[])
++{
++ return wpa_ctrl_command(ctrl, "GET_BSS_COLOR");
++}
++
++
++static int hostapd_cli_cmd_get_aval_color_bmp(struct wpa_ctrl *ctrl, int argc,
++ char *argv[])
++{
++ return wpa_ctrl_command(ctrl, "AVAL_COLOR_BMP");
++}
++
++
+ #ifdef ANDROID
+ static int hostapd_cli_cmd_driver(struct wpa_ctrl *ctrl, int argc, char *argv[])
+ {
+@@ -1819,6 +1833,10 @@ static const struct hostapd_cli_cmd hostapd_cli_commands[] = {
+ "<addr> [req_mode=] <measurement request hexdump> = send a Beacon report request to a station" },
+ { "reload_wpa_psk", hostapd_cli_cmd_reload_wpa_psk, NULL,
+ "= reload wpa_psk_file only" },
++ { "get_bss_color", hostapd_cli_cmd_get_bss_color, NULL,
++ "= get current BSS color" },
++ { "get_color_bmp", hostapd_cli_cmd_get_aval_color_bmp, NULL,
++ "= get available BSS color bitmap" },
+ #ifdef ANDROID
+ { "driver", hostapd_cli_cmd_driver, NULL,
+ "<driver sub command> [<hex formatted data>] = send driver command data" },
+diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c
+index 00492b8..7b686e5 100644
+--- a/src/ap/ap_drv_ops.c
++++ b/src/ap/ap_drv_ops.c
+@@ -1130,4 +1130,12 @@ int hostapd_drv_amsdu_dump(struct hostapd_data *hapd, u8 *amsdu)
+ if (!hapd->driver || !hapd->driver->amsdu_dump)
+ return 0;
+ return hapd->driver->amsdu_dump(hapd->drv_priv, amsdu);
+-}
+\ No newline at end of file
++}
++
++int hostapd_drv_get_aval_bss_color_bmp(struct hostapd_data *hapd, u64 *aval_color_bmp)
++{
++ if (!hapd->driver || !hapd->driver->get_aval_color_bmp ||
++ hapd->iface->conf->he_op.he_bss_color_disabled)
++ return 0;
++ return hapd->driver->get_aval_color_bmp(hapd->drv_priv, aval_color_bmp);
++}
+diff --git a/src/ap/ap_drv_ops.h b/src/ap/ap_drv_ops.h
+index 2b8b587..47356ab 100644
+--- a/src/ap/ap_drv_ops.h
++++ b/src/ap/ap_drv_ops.h
+@@ -155,6 +155,8 @@ int hostapd_drv_ibf_ctrl(struct hostapd_data *hapd);
+ int hostapd_drv_ibf_dump(struct hostapd_data *hapd, u8 *ibf_enable);
+ int hostapd_drv_amsdu_ctrl(struct hostapd_data *hapd);
+ int hostapd_drv_amsdu_dump(struct hostapd_data *hapd, u8 *amsdu);
++int hostapd_drv_get_aval_bss_color_bmp(struct hostapd_data *hapd,
++ u64 *aval_color_bmp);
+
+ #include "drivers/driver.h"
+
+diff --git a/src/common/mtk_vendor.h b/src/common/mtk_vendor.h
+index 62d79cb..a99e6f2 100644
+--- a/src/common/mtk_vendor.h
++++ b/src/common/mtk_vendor.h
+@@ -15,6 +15,7 @@ enum mtk_nl80211_vendor_subcmds {
+ MTK_NL80211_VENDOR_SUBCMD_EDCCA_CTRL = 0xc7,
+ MTK_NL80211_VENDOR_SUBCMD_3WIRE_CTRL = 0xc8,
+ MTK_NL80211_VENDOR_SUBCMD_IBF_CTRL = 0xc9,
++ MTK_NL80211_VENDOR_SUBCMD_BSS_COLOR_CTRL = 0xca,
+ };
+
+ enum mtk_vendor_attr_edcca_ctrl {
+@@ -253,6 +254,16 @@ ibf_dump_policy[NUM_MTK_VENDOR_ATTRS_IBF_DUMP] = {
+ [MTK_VENDOR_ATTR_IBF_DUMP_ENABLE] = { .type = NLA_U8 },
+ };
+
++enum mtk_vendor_attr_bss_color_ctrl {
++ MTK_VENDOR_ATTR_BSS_COLOR_CTRL_UNSPEC,
++
++ MTK_VENDOR_ATTR_AVAL_BSS_COLOR_BMP,
++
++ /* keep last */
++ NUM_MTK_VENDOR_ATTRS_BSS_COLOR_CTRL,
++ MTK_VENDOR_ATTR_BSS_COLOR_CTRL_MAX =
++ NUM_MTK_VENDOR_ATTRS_BSS_COLOR_CTRL - 1
++};
+
+ #define CSI_MAX_COUNT 256
+ #define ETH_ALEN 6
+diff --git a/src/drivers/driver.h b/src/drivers/driver.h
+index faa4b7b..f9f9fb5 100644
+--- a/src/drivers/driver.h
++++ b/src/drivers/driver.h
+@@ -5054,6 +5054,14 @@ struct wpa_driver_ops {
+ */
+ int (*amsdu_ctrl)(void *priv, u8 amsdu);
+ int (*amsdu_dump)(void *priv, u8 *amsdu);
++
++ /**
++ * get_aval_color_bmp - get available BSS color bitmap
++ * @priv: Private driver interface data
++ * @aval_color_bmp: available bss color bitmap
++ *
++ */
++ int (*get_aval_color_bmp)(void *priv, u64 *aval_color_bmp);
+ };
+
+ /**
+diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
+index 7c20b14..18a5647 100644
+--- a/src/drivers/driver_nl80211.c
++++ b/src/drivers/driver_nl80211.c
+@@ -12498,7 +12498,6 @@ static void nl80211_parse_btm_candidate_info(struct candidate_list *candidate,
+ num, MAC2STR(candidate->bssid), buf);
+ }
+
+-
+ static int
+ nl80211_get_bss_transition_status_handler(struct nl_msg *msg, void *arg)
+ {
+@@ -13886,6 +13885,203 @@ fail:
+ return -ENOBUFS;
+ }
+
++static int nl80211_get_aval_color_bmp_handler(struct nl_msg *msg, void *arg)
++{
++ u64 *aval_color_bmp = arg;
++ struct nlattr *tb[NL80211_ATTR_MAX + 1];
++ struct nlattr *tb_vendor[MTK_VENDOR_ATTR_BSS_COLOR_CTRL_MAX + 1];
++ struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
++ struct nlattr *nl_vend, *attr;
++
++ static const struct nla_policy
++ bss_color_ctrl_policy[NUM_MTK_VENDOR_ATTRS_BSS_COLOR_CTRL + 1] = {
++ [MTK_VENDOR_ATTR_AVAL_BSS_COLOR_BMP] = { .type = NLA_U64 },
++ };
++
++ nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
++ genlmsg_attrlen(gnlh, 0), NULL);
++
++ nl_vend = tb[NL80211_ATTR_VENDOR_DATA];
++ if (!nl_vend)
++ return NL_SKIP;
++
++ nla_parse(tb_vendor, MTK_VENDOR_ATTR_BSS_COLOR_CTRL_MAX,
++ nla_data(nl_vend), nla_len(nl_vend), NULL);
++
++ *aval_color_bmp = nla_get_u64(tb_vendor[MTK_VENDOR_ATTR_AVAL_BSS_COLOR_BMP]);
++
++ return 0;
++}
++
++static int nl80211_get_aval_color_bmp(void *priv, u64 *aval_color_bmp)
++{
++ struct i802_bss *bss = priv;
++ struct wpa_driver_nl80211_data *drv = bss->drv;
++ struct nl_msg *msg;
++ struct nlattr *attr;
++ int ret;
++
++ if (!drv->mtk_bss_color_vendor_cmd_avail) {
++ wpa_printf(MSG_INFO,
++ "nl80211: Driver does not support BSS COLOR vendor cmd");
++ return 0;
++ }
++
++ if (!(msg = nl80211_drv_msg(drv, NLM_F_DUMP, NL80211_CMD_VENDOR)) ||
++ nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_MTK) ||
++ nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
++ MTK_NL80211_VENDOR_SUBCMD_BSS_COLOR_CTRL))
++ return -ENOBUFS;
++
++ attr = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA);
++ if (!attr) {
++ nlmsg_free(msg);
++ return -1;
++ }
++
++ nla_nest_end(msg, attr);
++
++ ret = send_and_recv_msgs(drv, msg,
++ nl80211_get_aval_color_bmp_handler, aval_color_bmp, NULL, NULL);
++
++ if (ret) {
++ wpa_printf(MSG_ERROR, "Failed to send BSS COLOR vendor cmd. ret=%d (%s) ",
++ ret, strerror(-ret));
++ }
++ return ret;
++}
++
++static int nl80211_ap_wireless(void *priv, u8 sub_vendor_id, int value)
++{
++ struct i802_bss *bss = priv;
++ struct wpa_driver_nl80211_data *drv = bss->drv;
++ struct nl_msg *msg;
++ struct nlattr *data;
++ int ret;
++
++ if (!drv->mtk_wireless_vendor_cmd_avail) {
++ wpa_printf(MSG_INFO,
++ "nl80211: Driver does not support setting ap wireless control");
++ return 0;
++ }
++
++ msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR);
++ if (!msg)
++ goto fail;
++
++ if (nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_MTK) ||
++ nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD, MTK_NL80211_VENDOR_SUBCMD_WIRELESS_CTRL))
++ goto fail;
++
++ data = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA);
++ if (!data)
++ goto fail;
++
++ if (sub_vendor_id == MTK_VENDOR_ATTR_WIRELESS_CTRL_BA_BUFFER_SIZE)
++ nla_put_u16(msg, sub_vendor_id, (u16) value);
++ else
++ nla_put_u8(msg, sub_vendor_id, (u8) value);
++
++ nla_nest_end(msg, data);
++ ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
++ if (ret)
++ wpa_printf(MSG_ERROR, "Failed to set ap_wireless. ret=%d (%s)", ret, strerror(-ret));
++
++ return ret;
++
++fail:
++ nlmsg_free(msg);
++ return -ENOBUFS;
++}
++
++static int nl80211_ap_rfeatures(void *priv, u8 sub_vendor_id, int value)
++{
++ struct i802_bss *bss = priv;
++ struct wpa_driver_nl80211_data *drv = bss->drv;
++ struct nl_msg *msg;
++ struct nlattr *data;
++ int ret;
++
++ if (!drv->mtk_rfeatures_vendor_cmd_avail) {
++ wpa_printf(MSG_INFO,
++ "nl80211: Driver does not support setting ap rfeatures control");
++ return 0;
++ }
++
++ msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR);
++ if (!msg)
++ goto fail;
++
++ if (nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_MTK) ||
++ nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD, MTK_NL80211_VENDOR_SUBCMD_RFEATURE_CTRL))
++ goto fail;
++
++ data = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA);
++ if (!data)
++ goto fail;
++
++ nla_put_u8(msg, sub_vendor_id, (u8) value);
++
++ nla_nest_end(msg, data);
++
++ ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
++ if (ret)
++ wpa_printf(MSG_ERROR, "Failed to set rf_features. ret=%d (%s)", ret, strerror(-ret));
++
++ return ret;
++
++fail:
++ nlmsg_free(msg);
++ return -ENOBUFS;
++}
++
++static int nl80211_ap_trigtype(void *priv, u8 enable, u8 type)
++{
++ struct i802_bss *bss = priv;
++ struct wpa_driver_nl80211_data *drv = bss->drv;
++ struct nl_msg *msg;
++ struct nlattr *data, *data2;
++ int ret;
++
++ if (!drv->mtk_rfeatures_vendor_cmd_avail) {
++ wpa_printf(MSG_INFO,
++ "nl80211: Driver does not support setting ap rfeatures control");
++ return 0;
++ }
++
++ msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR);
++ if (!msg)
++ goto fail;
++
++ if (nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_MTK) ||
++ nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD, MTK_NL80211_VENDOR_SUBCMD_RFEATURE_CTRL))
++ goto fail;
++
++ data = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA);
++ if (!data)
++ goto fail;
++
++ data2 = nla_nest_start(msg, MTK_VENDOR_ATTR_RFEATURE_CTRL_TRIG_TYPE_CFG);
++ if (!data2)
++ goto fail;
++
++ nla_put_u8(msg, MTK_VENDOR_ATTR_RFEATURE_CTRL_TRIG_TYPE_EN, enable);
++ nla_put_u8(msg, MTK_VENDOR_ATTR_RFEATURE_CTRL_TRIG_TYPE, type);
++
++ nla_nest_end(msg, data2);
++ nla_nest_end(msg, data);
++
++ ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
++ if (ret)
++ wpa_printf(MSG_ERROR, "Failed to set trig_type. ret=%d (%s)", ret, strerror(-ret));
++
++ return ret;
++
++fail:
++ nlmsg_free(msg);
++ return -ENOBUFS;
++}
++
+ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
+ .name = "nl80211",
+ .desc = "Linux nl80211/cfg80211",
+@@ -14049,4 +14245,5 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
+ .ibf_dump = nl80211_ibf_dump,
+ .amsdu_ctrl = nl80211_enable_amsdu,
+ .amsdu_dump = nl80211_dump_amsdu,
++ .get_aval_color_bmp = nl80211_get_aval_color_bmp,
+ };
+diff --git a/src/drivers/driver_nl80211.h b/src/drivers/driver_nl80211.h
+index 3bcc770..190e7a5 100644
+--- a/src/drivers/driver_nl80211.h
++++ b/src/drivers/driver_nl80211.h
+@@ -204,6 +204,7 @@ struct wpa_driver_nl80211_data {
+ unsigned int mtk_3wire_vendor_cmd_avail:1;
+ unsigned int mtk_ibf_vendor_cmd_avail:1;
+ unsigned int mtk_wireless_vendor_cmd_avail:1;
++ unsigned int mtk_bss_color_vendor_cmd_avail:1;
+
+ u64 vendor_scan_cookie;
+ u64 remain_on_chan_cookie;
+diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c
+index dee99f0..a266926 100644
+--- a/src/drivers/driver_nl80211_capa.c
++++ b/src/drivers/driver_nl80211_capa.c
+@@ -1117,6 +1117,9 @@ static int wiphy_info_handler(struct nl_msg *msg, void *arg)
+ case MTK_NL80211_VENDOR_SUBCMD_WIRELESS_CTRL:
+ drv->mtk_wireless_vendor_cmd_avail = 1;
+ break;
++ case MTK_NL80211_VENDOR_SUBCMD_BSS_COLOR_CTRL :
++ drv->mtk_bss_color_vendor_cmd_avail = 1;
++ break;
+ }
+ }
+
+--
+2.18.0
+
diff --git a/autobuild_mac80211_release/package/network/services/hostapd_new/patches/mtk-0021-hostapd-mtk-Add-channel-information-for-hostapd-relo.patch b/autobuild_mac80211_release/package/network/services/hostapd_new/patches/mtk-0021-hostapd-mtk-Add-channel-information-for-hostapd-relo.patch
new file mode 100644
index 0000000..bf3a442
--- /dev/null
+++ b/autobuild_mac80211_release/package/network/services/hostapd_new/patches/mtk-0021-hostapd-mtk-Add-channel-information-for-hostapd-relo.patch
@@ -0,0 +1,79 @@
+From 8374019111ad6232db54e19e36f0fc1357612712 Mon Sep 17 00:00:00 2001
+From: Michael Lee <michael-cy.lee@mediatek.com>
+Date: Wed, 22 Mar 2023 13:59:29 +0800
+Subject: [PATCH 21/28] hostapd: mtk: Add channel information for hostapd
+ reload
+
+Add center channel, operating class, and bandwidth into the UPDATE
+command when wpa_supplciant reloads hostapd.
+Hostapd can correctly update its channel information.
+
+Signed-off-by: Michael Lee <michael-cy.lee@mediatek.com>
+---
+ hostapd/ctrl_iface.c | 11 +++++++++++
+ wpa_supplicant/wpa_supplicant.c | 17 ++++++++++++++---
+ 2 files changed, 25 insertions(+), 3 deletions(-)
+
+diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
+index bc7a97b..da6e727 100644
+--- a/hostapd/ctrl_iface.c
++++ b/hostapd/ctrl_iface.c
+@@ -171,6 +171,17 @@ static struct hostapd_config *hostapd_ctrl_iface_config_read(const char *fname)
+ conf->hw_mode = atoi(val);
+ else if ((val = get_option(opt, "ieee80211n=")))
+ conf->ieee80211n = atoi(val);
++ else if ((val = get_option(opt, "center_segment0=")))
++ hostapd_set_oper_centr_freq_seg0_idx(conf, atoi(val));
++ else if ((val = get_option(opt, "center_segment1=")))
++ hostapd_set_oper_centr_freq_seg1_idx(conf, atoi(val));
++ else if ((val = get_option(opt, "op_class="))) {
++ enum oper_chan_width ch_width;
++
++ conf->op_class = atoi(val);
++ ch_width = op_class_to_ch_width(conf->op_class);
++ hostapd_set_oper_chwidth(conf, ch_width);
++ }
+ else
+ break;
+ }
+diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
+index b67b5ad..bec8db8 100644
+--- a/wpa_supplicant/wpa_supplicant.c
++++ b/wpa_supplicant/wpa_supplicant.c
+@@ -150,9 +150,10 @@ static int hostapd_reload(struct wpa_supplicant *wpa_s, struct wpa_bss *bss)
+ char buf[256];
+ size_t len = sizeof(buf);
+ enum hostapd_hw_mode hw_mode;
+- u8 channel;
++ u8 channel, center_segment0, center_segment1 = 0, op_class;
+ int sec_chan = 0;
+ int ret;
++ struct wpa_channel_info ci;
+
+ if (!bss)
+ return -1;
+@@ -165,9 +166,19 @@ static int hostapd_reload(struct wpa_supplicant *wpa_s, struct wpa_bss *bss)
+ sec_chan = -1;
+ }
+
++ ret = wpa_drv_channel_info(wpa_s, &ci);
++ if (ret)
++ return -1;
++
++ ieee80211_freq_to_chan(ci.center_frq1, ¢er_segment0);
++ ieee80211_freq_to_chan(ci.center_frq2, ¢er_segment1);
++ ieee80211_chaninfo_to_channel(ci.frequency, ci.chanwidth, sec_chan,
++ &op_class, &channel);
+ hw_mode = ieee80211_freq_to_chan(bss->freq, &channel);
+- if (asprintf(&cmd, "UPDATE channel=%d sec_chan=%d hw_mode=%d",
+- channel, sec_chan, hw_mode) < 0)
++ if (asprintf(&cmd, "UPDATE channel=%d center_segment0=%d "
++ "center_segment1=%d sec_chan=%d hw_mode=%d op_class=%d",
++ channel, center_segment0, center_segment1, sec_chan,
++ hw_mode, op_class) < 0)
+ return -1;
+
+ ret = wpa_ctrl_request(wpa_s->hostapd, cmd, os_strlen(cmd), buf, &len, NULL);
+--
+2.18.0
+
diff --git a/autobuild_mac80211_release/package/network/services/hostapd_new/patches/mtk-0022-hostapd-mtk-Fix-ZWDFS-issue-in-BW-160.patch b/autobuild_mac80211_release/package/network/services/hostapd_new/patches/mtk-0022-hostapd-mtk-Fix-ZWDFS-issue-in-BW-160.patch
new file mode 100644
index 0000000..d4fd615
--- /dev/null
+++ b/autobuild_mac80211_release/package/network/services/hostapd_new/patches/mtk-0022-hostapd-mtk-Fix-ZWDFS-issue-in-BW-160.patch
@@ -0,0 +1,210 @@
+From f1a0b030838b8e6e6505b74bbabd7af9fa7913dc Mon Sep 17 00:00:00 2001
+From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+Date: Mon, 20 Mar 2023 16:08:30 +0800
+Subject: [PATCH 22/28] hostapd: mtk: Fix ZWDFS issue in BW 160
+
+When background radar is enabled and bandwidth is set to 160, AP will
+fail to startup due to the lack of non-DFS channel.
+Under this circumstance, AP should perform CAC itself, and the background
+chain could also perform CAC simultaneously.
+
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+---
+ src/ap/dfs.c | 98 ++++++++++++++++++++++++++++++++++++++++++----------
+ 1 file changed, 79 insertions(+), 19 deletions(-)
+
+diff --git a/src/ap/dfs.c b/src/ap/dfs.c
+index d52a60e..2f5c86e 100644
+--- a/src/ap/dfs.c
++++ b/src/ap/dfs.c
+@@ -69,15 +69,22 @@ static int dfs_get_used_n_chans(struct hostapd_iface *iface, int *seg1)
+ static int dfs_channel_available(struct hostapd_channel_data *chan,
+ enum dfs_channel_type type)
+ {
++ int dfs_status = chan->flag & HOSTAPD_CHAN_DFS_MASK;
++
++ if (chan->flag & HOSTAPD_CHAN_DISABLED)
++ return -1;
++
+ 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)
++ if (!(chan->flag & HOSTAPD_CHAN_RADAR))
++ return 0;
++
++ if (dfs_status == HOSTAPD_CHAN_DFS_USABLE)
+ return 1;
+- return 0;
++
++ return -1;
+ }
+
+ /*
+@@ -86,16 +93,14 @@ static int dfs_channel_available(struct hostapd_channel_data *chan,
+ * channel for CSA, unless they are available for immediate use.
+ */
+ if (type == DFS_AVAILABLE && (chan->flag & HOSTAPD_CHAN_RADAR) &&
+- ((chan->flag & HOSTAPD_CHAN_DFS_MASK) !=
+- HOSTAPD_CHAN_DFS_AVAILABLE))
+- return 0;
++ (dfs_status != HOSTAPD_CHAN_DFS_AVAILABLE))
++ return -1;
+
+- if (chan->flag & HOSTAPD_CHAN_DISABLED)
+- return 0;
+ if ((chan->flag & HOSTAPD_CHAN_RADAR) &&
+- ((chan->flag & HOSTAPD_CHAN_DFS_MASK) ==
+- HOSTAPD_CHAN_DFS_UNAVAILABLE))
+- return 0;
++ ((dfs_status == HOSTAPD_CHAN_DFS_UNAVAILABLE) ||
++ (dfs_status == HOSTAPD_CHAN_DFS_UNKNOWN)))
++ return -1;
++
+ return 1;
+ }
+
+@@ -167,7 +172,7 @@ static int dfs_chan_range_available(struct hostapd_hw_modes *mode,
+ enum dfs_channel_type type)
+ {
+ struct hostapd_channel_data *first_chan, *chan;
+- int i;
++ int i, available = 0, ret = 0;
+ u32 bw = num_chan_to_bw(num_chans);
+
+ if (first_chan_idx + num_chans > mode->num_channels) {
+@@ -203,14 +208,17 @@ static int dfs_chan_range_available(struct hostapd_hw_modes *mode,
+ return 0;
+ }
+
+- if (!dfs_channel_available(chan, type)) {
++ ret = dfs_channel_available(chan, type);
++ if (ret < 0) {
+ wpa_printf(MSG_DEBUG, "DFS: channel not available %d",
+ first_chan->freq + i * 20);
+ return 0;
+ }
++
++ available |= ret;
+ }
+
+- return 1;
++ return available;
+ }
+
+
+@@ -831,8 +839,12 @@ 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 sec = 0, skip_radar = 0;
++ u8 cf1 = 0, cf2 = 0;
++ bool use_radar_background = dfs_use_radar_background(iface);
++ enum dfs_channel_type channel_type = DFS_NO_CAC_YET;
+
+ if (is_6ghz_freq(iface->freq))
+ return 1;
+@@ -895,7 +907,7 @@ 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%s", iface->freq,
+- dfs_use_radar_background(iface) ? " (background)" : "");
++ use_radar_background ? " (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,
+@@ -905,6 +917,16 @@ int hostapd_handle_dfs(struct hostapd_iface *iface)
+ hostapd_get_oper_centr_freq_seg1_idx(iface->conf),
+ iface->dfs_cac_ms / 1000);
+
++ if (use_radar_background) {
++ channel = dfs_get_valid_channel(iface, &sec, &cf1, &cf2, DFS_AVAILABLE);
++ /*
++ * AP cannot get any random available channel.
++ * Let AP and dedicated radar chain both perform CAC.
++ */
++ if (!channel)
++ use_radar_background = false;
++ }
++
+ res = hostapd_start_dfs_cac(
+ iface, iface->conf->hw_mode, iface->freq, iface->conf->channel,
+ iface->conf->ieee80211n, iface->conf->ieee80211ac,
+@@ -913,14 +935,14 @@ int hostapd_handle_dfs(struct hostapd_iface *iface)
+ hostapd_get_oper_chwidth(iface->conf),
+ hostapd_get_oper_centr_freq_seg0_idx(iface->conf),
+ hostapd_get_oper_centr_freq_seg1_idx(iface->conf),
+- dfs_use_radar_background(iface));
++ use_radar_background);
+
+ if (res) {
+ wpa_printf(MSG_ERROR, "DFS start_dfs_cac() failed, %d", res);
+ return -1;
+ }
+
+- if (dfs_use_radar_background(iface)) {
++ if (use_radar_background) {
+ /* Cache background radar parameters. */
+ iface->radar_background.channel = iface->conf->channel;
+ iface->radar_background.secondary_channel =
+@@ -941,6 +963,35 @@ int hostapd_handle_dfs(struct hostapd_iface *iface)
+
+ iface->radar_background.temp_ch = 1;
+ return 1;
++ } else if (dfs_use_radar_background(iface)) {
++ if (iface->dfs_domain == HOSTAPD_DFS_REGION_ETSI)
++ channel_type = DFS_ANY_CHANNEL;
++
++ channel = dfs_get_valid_channel(iface, &sec, &cf1, &cf2, channel_type);
++
++ if (!channel ||
++ (channel->chan == iface->conf->channel &&
++ cf1 == hostapd_get_oper_centr_freq_seg0_idx(iface->conf) &&
++ cf2 == hostapd_get_oper_centr_freq_seg1_idx(iface->conf))) {
++ wpa_printf(MSG_ERROR, "Background radar could not get valid channel\n");
++ iface->radar_background.channel = -1;
++ return 0;
++ }
++
++ hostapd_start_dfs_cac(iface, iface->conf->hw_mode,
++ channel->freq, channel->chan,
++ iface->conf->ieee80211n,
++ iface->conf->ieee80211ac,
++ iface->conf->ieee80211ax,
++ iface->conf->ieee80211be,
++ sec, hostapd_get_oper_chwidth(iface->conf),
++ cf1, cf2, true);
++
++ 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 = cf1;
++ iface->radar_background.centr_freq_seg1_idx = cf2;
+ }
+
+ return 0;
+@@ -1190,6 +1241,15 @@ int hostapd_dfs_complete_cac(struct hostapd_iface *iface, int success, int freq,
+ hostapd_setup_interface_complete(iface, 0);
+ iface->cac_started = 0;
+ }
++
++ /*
++ * When background radar is enabled but the CAC completion
++ * is not received from the background chain.
++ * Then, reset radar background chain.
++ */
++ if (dfs_use_radar_background(iface) &&
++ iface->radar_background.channel == -1)
++ hostpad_dfs_update_background_chain(iface);
+ }
+ } else if (hostapd_dfs_is_background_event(iface, freq)) {
+ iface->radar_background.cac_started = 0;
+--
+2.18.0
+
diff --git a/autobuild_mac80211_release/package/network/services/hostapd_new/patches/mtk-0023-hostapd-mtk-Add-vendor-for-CAPI-certification-comman.patch b/autobuild_mac80211_release/package/network/services/hostapd_new/patches/mtk-0023-hostapd-mtk-Add-vendor-for-CAPI-certification-comman.patch
new file mode 100644
index 0000000..386ce8d
--- /dev/null
+++ b/autobuild_mac80211_release/package/network/services/hostapd_new/patches/mtk-0023-hostapd-mtk-Add-vendor-for-CAPI-certification-comman.patch
@@ -0,0 +1,390 @@
+From 934c90729e00901fe6785727dc9004315725b587 Mon Sep 17 00:00:00 2001
+From: Evelyn Tsai <evelyn.tsai@mediatek.com>
+Date: Fri, 17 Mar 2023 16:17:14 +0800
+Subject: [PATCH 23/28] hostapd: mtk: Add vendor for CAPI certification
+ commands
+
+---
+ hostapd/ctrl_iface.c | 95 +++++++++++++++++++++++++++++++
+ src/ap/ap_drv_ops.c | 21 +++++++
+ src/ap/ap_drv_ops.h | 3 +
+ src/common/mtk_vendor.h | 32 +----------
+ src/drivers/driver.h | 22 +++++++
+ src/drivers/driver_nl80211.c | 54 ++++++++++++++++++
+ src/drivers/driver_nl80211.h | 1 +
+ src/drivers/driver_nl80211_capa.c | 3 +
+ 8 files changed, 201 insertions(+), 30 deletions(-)
+
+diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
+index da6e727..79457d7 100644
+--- a/hostapd/ctrl_iface.c
++++ b/hostapd/ctrl_iface.c
+@@ -70,6 +70,7 @@
+ #include "ctrl_iface.h"
+ #include "config_file.h"
+
++#include "common/mtk_vendor.h"
+
+ #define HOSTAPD_CLI_DUP_VALUE_MAX_LEN 256
+
+@@ -3801,6 +3802,96 @@ hostapd_ctrl_iface_get_aval_color_bmp(struct hostapd_data *hapd, char *buf,
+ return pos - buf;
+ }
+
++static int
++hostapd_ctrl_iface_ap_wireless(struct hostapd_data *hapd, char *cmd,
++ char *buf, size_t buflen)
++{
++ char *pos, *value, *config = cmd;
++ enum mtk_vendor_attr_wireless_ctrl sub_cmd;
++
++ pos = os_strchr(config, '=');
++ if (pos == NULL)
++ return -1;
++ *pos++ = '\0';
++
++ if(pos == NULL)
++ return -1;
++ value = pos;
++
++ if (os_strncmp(config, "fixed_mcs", 9) == 0)
++ sub_cmd = MTK_VENDOR_ATTR_WIRELESS_CTRL_FIXED_MCS;
++ else if (os_strncmp(config, "ofdma", 5) == 0)
++ sub_cmd = MTK_VENDOR_ATTR_WIRELESS_CTRL_FIXED_OFDMA;
++ else if (os_strncmp(config, "ppdu_type", 9) == 0)
++ sub_cmd = MTK_VENDOR_ATTR_WIRELESS_CTRL_PPDU_TX_TYPE;
++ else if (os_strncmp(config, "nusers_ofdma", 12) == 0)
++ sub_cmd = MTK_VENDOR_ATTR_WIRELESS_CTRL_NUSERS_OFDMA;
++ else if (os_strncmp(config, "add_ba_req_bufsize", 18) == 0)
++ sub_cmd = MTK_VENDOR_ATTR_WIRELESS_CTRL_BA_BUFFER_SIZE;
++ else if (os_strncmp(config, "mimo", 4) == 0)
++ sub_cmd = MTK_VENDOR_ATTR_WIRELESS_CTRL_MIMO;
++ else if (os_strncmp(config, "cert", 4) == 0)
++ sub_cmd = MTK_VENDOR_ATTR_WIRELESS_CTRL_CERT ;
++ else {
++ wpa_printf(MSG_ERROR,
++ "Unsupported parameter %s for ap_wireless", config);
++ return -1;
++ }
++
++ if (hostapd_drv_ap_wireless(hapd, (u8) sub_cmd, atoi(value)) != 0)
++ return -1;
++
++ return os_snprintf(buf, buflen, "OK\n");
++}
++
++static int
++hostapd_ctrl_iface_ap_rfeatures(struct hostapd_data *hapd, char *cmd,
++ char *buf, size_t buflen)
++{
++ char *pos, *value, *type, *config = cmd;
++ enum mtk_vendor_attr_rfeature_ctrl sub_cmd;
++
++ pos = os_strchr(config, '=');
++ if (pos == NULL)
++ return -1;
++ *pos++ = '\0';
++
++ if(pos == NULL)
++ return -1;
++ value = pos;
++
++ if (os_strncmp(config, "he_gi", 5) == 0)
++ sub_cmd = MTK_VENDOR_ATTR_RFEATURE_CTRL_HE_GI;
++ else if (os_strncmp(config, "he_ltf", 6) == 0)
++ sub_cmd = MTK_VENDOR_ATTR_RFEATURE_CTRL_HE_LTF;
++ else if (os_strncmp(config, "trig_type", 9) == 0) {
++ pos = os_strchr(value, ',');
++ if (pos == NULL)
++ return -1;
++ *pos++ = '\0';
++ if(pos == NULL)
++ return -1;
++ type = pos;
++ goto trigtype;
++ } else if (os_strcmp(config, "ack_policy") == 0)
++ sub_cmd = MTK_VENDOR_ATTR_RFEATURE_CTRL_ACK_PLCY;
++ else {
++ wpa_printf(MSG_ERROR,
++ "Unsupported parameter %s for ap_rfeatures", config);
++ return -1;
++ }
++
++ if (hostapd_drv_ap_rfeatures(hapd, (u8) sub_cmd, atoi(value)) != 0)
++ return -1;
++ goto exit;
++
++trigtype:
++ if (hostapd_drv_ap_trig_type(hapd, atoi(value), atoi(type)) != 0)
++ return -1;
++
++exit:
++ return os_snprintf(buf, buflen, "OK\n");
++}
+
+ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
+ char *buf, char *reply,
+@@ -4381,6 +4472,10 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
+ reply_len = hostapd_ctrl_iface_get_bss_color(hapd, reply, reply_size);
+ } else if (os_strncmp(buf, "AVAL_COLOR_BMP", 14) == 0) {
+ reply_len = hostapd_ctrl_iface_get_aval_color_bmp(hapd, reply, reply_size);
++ } else if (os_strncmp(buf, "ap_wireless ", 12) == 0) {
++ reply_len = hostapd_ctrl_iface_ap_wireless(hapd, buf + 12, reply, reply_size);
++ } else if (os_strncmp(buf, "ap_rfeatures ", 13) == 0) {
++ reply_len = hostapd_ctrl_iface_ap_rfeatures(hapd, buf + 13, reply, reply_size);
+ } else {
+ os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
+ reply_len = 16;
+diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c
+index 7b686e5..78b52c8 100644
+--- a/src/ap/ap_drv_ops.c
++++ b/src/ap/ap_drv_ops.c
+@@ -1139,3 +1139,24 @@ int hostapd_drv_get_aval_bss_color_bmp(struct hostapd_data *hapd, u64 *aval_colo
+ return 0;
+ return hapd->driver->get_aval_color_bmp(hapd->drv_priv, aval_color_bmp);
+ }
++
++int hostapd_drv_ap_wireless(struct hostapd_data *hapd, u8 sub_vendor_id, int value)
++{
++ if (!hapd->driver || !hapd->driver->ap_wireless)
++ return 0;
++ return hapd->driver->ap_wireless(hapd->drv_priv, sub_vendor_id, value);
++}
++
++int hostapd_drv_ap_rfeatures(struct hostapd_data *hapd, u8 sub_vendor_id, int value)
++{
++ if (!hapd->driver || !hapd->driver->ap_rfeatures)
++ return 0;
++ return hapd->driver->ap_rfeatures(hapd->drv_priv, sub_vendor_id, value);
++}
++
++int hostapd_drv_ap_trig_type(struct hostapd_data *hapd, u8 enable, u8 type)
++{
++ if (!hapd->driver || !hapd->driver->ap_trigtype)
++ return 0;
++ return hapd->driver->ap_trigtype(hapd->drv_priv, enable, type);
++}
+diff --git a/src/ap/ap_drv_ops.h b/src/ap/ap_drv_ops.h
+index 47356ab..bb9fdf7 100644
+--- a/src/ap/ap_drv_ops.h
++++ b/src/ap/ap_drv_ops.h
+@@ -157,6 +157,9 @@ int hostapd_drv_amsdu_ctrl(struct hostapd_data *hapd);
+ int hostapd_drv_amsdu_dump(struct hostapd_data *hapd, u8 *amsdu);
+ int hostapd_drv_get_aval_bss_color_bmp(struct hostapd_data *hapd,
+ u64 *aval_color_bmp);
++int hostapd_drv_ap_wireless(struct hostapd_data *hapd, u8 sub_vendor_id, int value);
++int hostapd_drv_ap_rfeatures(struct hostapd_data *hapd, u8 sub_vendor_id, int value);
++int hostapd_drv_ap_trig_type(struct hostapd_data *hapd, u8 enable, u8 type);
+
+ #include "drivers/driver.h"
+
+diff --git a/src/common/mtk_vendor.h b/src/common/mtk_vendor.h
+index a99e6f2..32438af 100644
+--- a/src/common/mtk_vendor.h
++++ b/src/common/mtk_vendor.h
+@@ -48,16 +48,6 @@ enum mtk_vendor_attr_edcca_dump {
+ NUM_MTK_VENDOR_ATTRS_EDCCA_DUMP - 1
+ };
+
+-
+-static struct nla_policy edcca_ctrl_policy[NUM_MTK_VENDOR_ATTRS_EDCCA_CTRL] = {
+- [MTK_VENDOR_ATTR_EDCCA_CTRL_MODE] = { .type = NLA_U8 },
+- [MTK_VENDOR_ATTR_EDCCA_CTRL_PRI20_VAL] = { .type = NLA_U8 },
+- [MTK_VENDOR_ATTR_EDCCA_CTRL_SEC20_VAL] = { .type = NLA_U8 },
+- [MTK_VENDOR_ATTR_EDCCA_CTRL_SEC40_VAL] = { .type = NLA_U8 },
+- [MTK_VENDOR_ATTR_EDCCA_CTRL_SEC80_VAL] = { .type = NLA_U8 },
+- [MTK_VENDOR_ATTR_EDCCA_CTRL_COMPENSATE] = { .type = NLA_U8 },
+-};
+-
+ enum mtk_vendor_attr_3wire_ctrl {
+ MTK_VENDOR_ATTR_3WIRE_CTRL_UNSPEC,
+
+@@ -69,10 +59,6 @@ enum mtk_vendor_attr_3wire_ctrl {
+ NUM_MTK_VENDOR_ATTRS_3WIRE_CTRL - 1
+ };
+
+-static struct nla_policy three_wire_ctrl_policy[NUM_MTK_VENDOR_ATTRS_3WIRE_CTRL] = {
+- [MTK_VENDOR_ATTR_3WIRE_CTRL_MODE] = {.type = NLA_U8 },
+-};
+-
+ enum mtk_vendor_attr_csi_ctrl {
+ MTK_VENDOR_ATTR_CSI_CTRL_UNSPEC,
+
+@@ -169,7 +155,7 @@ enum mtk_vendor_attr_wireless_ctrl {
+ MTK_VENDOR_ATTR_WIRELESS_CTRL_BA_BUFFER_SIZE,
+ MTK_VENDOR_ATTR_WIRELESS_CTRL_MIMO,
+ MTK_VENDOR_ATTR_WIRELESS_CTRL_AMSDU,
+- MTK_VENDOR_ATTR_WIRELESS_CTRL_CERT,
++ MTK_VENDOR_ATTR_WIRELESS_CTRL_CERT = 9,
+ MTK_VENDOR_ATTR_WIRELESS_CTRL_RTS_SIGTA,
+
+ /* keep last */
+@@ -189,11 +175,6 @@ enum mtk_vendor_attr_wireless_dump {
+ NUM_MTK_VENDOR_ATTRS_WIRELESS_DUMP - 1
+ };
+
+-static const struct nla_policy
+-wireless_dump_policy[NUM_MTK_VENDOR_ATTRS_WIRELESS_DUMP] = {
+- [MTK_VENDOR_ATTR_WIRELESS_DUMP_AMSDU] = { .type = NLA_U8 },
+-};
+-
+ enum mtk_vendor_attr_rfeature_ctrl {
+ MTK_VENDOR_ATTR_RFEATURE_CTRL_UNSPEC,
+
+@@ -203,6 +184,7 @@ enum mtk_vendor_attr_rfeature_ctrl {
+ MTK_VENDOR_ATTR_RFEATURE_CTRL_TRIG_TYPE_EN,
+ MTK_VENDOR_ATTR_RFEATURE_CTRL_TRIG_TYPE,
+ MTK_VENDOR_ATTR_RFEATURE_CTRL_ACK_PLCY,
++ MTK_VENDOR_ATTR_RFEATURE_CTRL_TRIG_TXBF,
+
+ /* keep last */
+ NUM_MTK_VENDOR_ATTRS_RFEATURE_CTRL,
+@@ -244,16 +226,6 @@ enum mtk_vendor_attr_ibf_dump {
+ NUM_MTK_VENDOR_ATTRS_IBF_DUMP - 1
+ };
+
+-static struct nla_policy
+-ibf_ctrl_policy[NUM_MTK_VENDOR_ATTRS_IBF_CTRL] = {
+- [MTK_VENDOR_ATTR_IBF_CTRL_ENABLE] = { .type = NLA_U8 },
+-};
+-
+-static struct nla_policy
+-ibf_dump_policy[NUM_MTK_VENDOR_ATTRS_IBF_DUMP] = {
+- [MTK_VENDOR_ATTR_IBF_DUMP_ENABLE] = { .type = NLA_U8 },
+-};
+-
+ enum mtk_vendor_attr_bss_color_ctrl {
+ MTK_VENDOR_ATTR_BSS_COLOR_CTRL_UNSPEC,
+
+diff --git a/src/drivers/driver.h b/src/drivers/driver.h
+index f9f9fb5..ae692c2 100644
+--- a/src/drivers/driver.h
++++ b/src/drivers/driver.h
+@@ -5062,6 +5062,28 @@ struct wpa_driver_ops {
+ *
+ */
+ int (*get_aval_color_bmp)(void *priv, u64 *aval_color_bmp);
++
++ /**
++ * ap_wireless - set wireless command
++ * @priv: Private driver interface data
++ * @value: value
++ */
++ int (*ap_wireless)(void *priv, u8 mode, int value);
++
++ /**
++ * ap_rfeatures - set ap rf features command
++ * @priv: Private driver interface data
++ * @value: value
++ */
++ int (*ap_rfeatures)(void *priv, u8 mode, int value);
++
++ /**
++ * ap_trigtype - set trigger type
++ * @priv: Private driver interface data
++ * @enable: enable or disable
++ * @type: trigger type
++ */
++ int (*ap_trigtype)(void *priv, u8 enable, u8 type);
+ };
+
+ /**
+diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
+index 18a5647..730a696 100644
+--- a/src/drivers/driver_nl80211.c
++++ b/src/drivers/driver_nl80211.c
+@@ -76,6 +76,57 @@ enum nlmsgerr_attrs {
+ #endif /* ANDROID */
+
+
++static struct nla_policy
++ibf_ctrl_policy[NUM_MTK_VENDOR_ATTRS_IBF_CTRL] = {
++ [MTK_VENDOR_ATTR_IBF_CTRL_ENABLE] = { .type = NLA_U8 },
++};
++
++static struct nla_policy
++ibf_dump_policy[NUM_MTK_VENDOR_ATTRS_IBF_DUMP] = {
++ [MTK_VENDOR_ATTR_IBF_DUMP_ENABLE] = { .type = NLA_U8 },
++};
++
++static struct nla_policy three_wire_ctrl_policy[NUM_MTK_VENDOR_ATTRS_3WIRE_CTRL] = {
++ [MTK_VENDOR_ATTR_3WIRE_CTRL_MODE] = {.type = NLA_U8 },
++};
++
++static struct nla_policy edcca_ctrl_policy[NUM_MTK_VENDOR_ATTRS_EDCCA_CTRL] = {
++ [MTK_VENDOR_ATTR_EDCCA_CTRL_MODE] = { .type = NLA_U8 },
++ [MTK_VENDOR_ATTR_EDCCA_CTRL_PRI20_VAL] = { .type = NLA_U8 },
++ [MTK_VENDOR_ATTR_EDCCA_CTRL_SEC20_VAL] = { .type = NLA_U8 },
++ [MTK_VENDOR_ATTR_EDCCA_CTRL_SEC40_VAL] = { .type = NLA_U8 },
++ [MTK_VENDOR_ATTR_EDCCA_CTRL_SEC80_VAL] = { .type = NLA_U8 },
++ [MTK_VENDOR_ATTR_EDCCA_CTRL_COMPENSATE] = { .type = NLA_U8 },
++};
++
++static const struct nla_policy
++wireless_dump_policy[NUM_MTK_VENDOR_ATTRS_WIRELESS_DUMP] = {
++ [MTK_VENDOR_ATTR_WIRELESS_DUMP_AMSDU] = { .type = NLA_U8 },
++};
++
++static const struct nla_policy
++rfeature_ctrl_policy[NUM_MTK_VENDOR_ATTRS_RFEATURE_CTRL] = {
++ [MTK_VENDOR_ATTR_RFEATURE_CTRL_HE_GI] = {.type = NLA_U8 },
++ [MTK_VENDOR_ATTR_RFEATURE_CTRL_HE_LTF] = { .type = NLA_U8 },
++ [MTK_VENDOR_ATTR_RFEATURE_CTRL_TRIG_TYPE_CFG] = { .type = NLA_NESTED },
++ [MTK_VENDOR_ATTR_RFEATURE_CTRL_TRIG_TYPE_EN] = { .type = NLA_U8 },
++ [MTK_VENDOR_ATTR_RFEATURE_CTRL_TRIG_TYPE] = { .type = NLA_U8 },
++ [MTK_VENDOR_ATTR_RFEATURE_CTRL_ACK_PLCY] = { .type = NLA_U8 },
++ [MTK_VENDOR_ATTR_RFEATURE_CTRL_TRIG_TXBF] = { .type = NLA_U8 },
++};
++
++static const struct nla_policy
++wireless_ctrl_policy[NUM_MTK_VENDOR_ATTRS_WIRELESS_CTRL] = {
++ [MTK_VENDOR_ATTR_WIRELESS_CTRL_FIXED_MCS] = {.type = NLA_U8 },
++ [MTK_VENDOR_ATTR_WIRELESS_CTRL_FIXED_OFDMA] = {.type = NLA_U8 },
++ [MTK_VENDOR_ATTR_WIRELESS_CTRL_PPDU_TX_TYPE] = {.type = NLA_U8 },
++ [MTK_VENDOR_ATTR_WIRELESS_CTRL_NUSERS_OFDMA] = {.type = NLA_U8 },
++ [MTK_VENDOR_ATTR_WIRELESS_CTRL_MIMO] = {.type = NLA_U8 },
++ [MTK_VENDOR_ATTR_WIRELESS_CTRL_BA_BUFFER_SIZE] = {.type = NLA_U16 },
++ [MTK_VENDOR_ATTR_WIRELESS_CTRL_AMSDU] = {.type = NLA_U8 },
++ [MTK_VENDOR_ATTR_WIRELESS_CTRL_CERT] = {.type = NLA_U8 },
++};
++
+ static struct nl_sock * nl_create_handle(struct nl_cb *cb, const char *dbg)
+ {
+ struct nl_sock *handle;
+@@ -14246,4 +14297,7 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
+ .amsdu_ctrl = nl80211_enable_amsdu,
+ .amsdu_dump = nl80211_dump_amsdu,
+ .get_aval_color_bmp = nl80211_get_aval_color_bmp,
++ .ap_wireless = nl80211_ap_wireless,
++ .ap_rfeatures = nl80211_ap_rfeatures,
++ .ap_trigtype = nl80211_ap_trigtype,
+ };
+diff --git a/src/drivers/driver_nl80211.h b/src/drivers/driver_nl80211.h
+index 190e7a5..49588e6 100644
+--- a/src/drivers/driver_nl80211.h
++++ b/src/drivers/driver_nl80211.h
+@@ -205,6 +205,7 @@ struct wpa_driver_nl80211_data {
+ unsigned int mtk_ibf_vendor_cmd_avail:1;
+ unsigned int mtk_wireless_vendor_cmd_avail:1;
+ unsigned int mtk_bss_color_vendor_cmd_avail:1;
++ unsigned int mtk_rfeatures_vendor_cmd_avail:1;
+
+ u64 vendor_scan_cookie;
+ u64 remain_on_chan_cookie;
+diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c
+index a266926..0674b66 100644
+--- a/src/drivers/driver_nl80211_capa.c
++++ b/src/drivers/driver_nl80211_capa.c
+@@ -1120,6 +1120,9 @@ static int wiphy_info_handler(struct nl_msg *msg, void *arg)
+ case MTK_NL80211_VENDOR_SUBCMD_BSS_COLOR_CTRL :
+ drv->mtk_bss_color_vendor_cmd_avail = 1;
+ break;
++ case MTK_NL80211_VENDOR_SUBCMD_RFEATURE_CTRL:
++ drv->mtk_rfeatures_vendor_cmd_avail = 1;
++ break;
+ }
+ }
+
+--
+2.18.0
+
diff --git a/autobuild_mac80211_release/package/network/services/hostapd_new/patches/mtk-0024-hostapd-mtk-Air-Monitor-support-in-hostapd-by-vendor.patch b/autobuild_mac80211_release/package/network/services/hostapd_new/patches/mtk-0024-hostapd-mtk-Air-Monitor-support-in-hostapd-by-vendor.patch
new file mode 100644
index 0000000..72c6355
--- /dev/null
+++ b/autobuild_mac80211_release/package/network/services/hostapd_new/patches/mtk-0024-hostapd-mtk-Air-Monitor-support-in-hostapd-by-vendor.patch
@@ -0,0 +1,506 @@
+From c8a55373f42c6149df669ba74ffbff70ec74d8db Mon Sep 17 00:00:00 2001
+From: Evelyn Tsai <evelyn.tsai@mediatek.com>
+Date: Fri, 12 May 2023 05:18:48 +0800
+Subject: [PATCH 24/28] hostapd: mtk: Air Monitor support in hostapd by vendor
+
+Signed-off-by: mtk23888 <dipanshu.mittal@mediatek.com>
+---
+ hostapd/ctrl_iface.c | 113 +++++++++++++++++++
+ hostapd/hostapd_cli.c | 15 +++
+ src/ap/ap_drv_ops.c | 14 +++
+ src/ap/ap_drv_ops.h | 3 +
+ src/common/mtk_vendor.h | 8 ++
+ src/drivers/driver.h | 16 +++
+ src/drivers/driver_nl80211.c | 180 ++++++++++++++++++++++++++++++
+ src/drivers/driver_nl80211.h | 1 +
+ src/drivers/driver_nl80211_capa.c | 2 +
+ 9 files changed, 352 insertions(+)
+
+diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
+index 79457d7..234b800 100644
+--- a/hostapd/ctrl_iface.c
++++ b/hostapd/ctrl_iface.c
+@@ -3840,6 +3840,44 @@ hostapd_ctrl_iface_ap_wireless(struct hostapd_data *hapd, char *cmd,
+
+ if (hostapd_drv_ap_wireless(hapd, (u8) sub_cmd, atoi(value)) != 0)
+ return -1;
++ return os_snprintf(buf, buflen, "OK\n");
++}
++
++static int
++hostapd_ctrl_iface_set_amnt(struct hostapd_data *hapd, char *cmd,
++ char *buf, size_t buflen)
++{
++ char *tmp, sta_mac[ETH_ALEN] = {0};
++ int amnt_idx = 0;
++
++ tmp = strtok_r(cmd, " ", &cmd);
++
++ if (!tmp) {
++ wpa_printf(MSG_ERROR, "Error in command format\n");
++ return -1;
++ }
++
++ amnt_idx = strtol(tmp, &tmp, 10);
++
++ if (amnt_idx < 0 || amnt_idx > 15) {
++ wpa_printf(MSG_ERROR, "Wrong AMNT index %d\n", amnt_idx);
++ return -1;
++ }
++
++ if (!cmd) {
++ wpa_printf(MSG_ERROR, "Error in command format\n");
++ return -1;
++ }
++
++ if (hwaddr_aton(cmd, sta_mac) < 0) {
++ wpa_printf(MSG_ERROR, "station mac is not right.\n");
++ return -1;
++ }
++
++ if (hostapd_drv_amnt_set(hapd, amnt_idx, sta_mac)) {
++ wpa_printf(MSG_ERROR, "Not able to set amnt index\n");
++ return -1;
++ }
+
+ return os_snprintf(buf, buflen, "OK\n");
+ }
+@@ -3893,6 +3931,75 @@ exit:
+ return os_snprintf(buf, buflen, "OK\n");
+ }
+
++static int
++hostapd_ctrl_iface_dump_amnt(struct hostapd_data *hapd, char *cmd,
++ char *buf, size_t buflen)
++{
++ char *tmp;
++ int amnt_idx = 0, ret = 0;
++ struct amnt_resp_data *resp_buf;
++ char *pos, *end;
++ struct amnt_data *res;
++
++ pos = buf;
++ end = buf + buflen;
++
++ tmp = strtok_r(cmd, " ", &cmd);
++
++ if (!tmp) {
++ wpa_printf(MSG_ERROR, "Error in command format\n");
++ return -1;
++ }
++
++ amnt_idx = strtoul(tmp, &tmp, 0);
++
++ if ((amnt_idx < 0 || amnt_idx > 15) && amnt_idx != 0xff) {
++ wpa_printf(MSG_ERROR, "Wrong AMNT index\n");
++ return -1;
++ }
++
++ if (amnt_idx == 0xff)
++ resp_buf = (struct amnt_resp_data *) os_zalloc(AIR_MONITOR_MAX_ENTRY
++ * sizeof(struct amnt_data) + 1);
++ else
++ resp_buf = (struct amnt_resp_data *) os_zalloc(sizeof(struct amnt_data) + 1);
++
++ if (resp_buf == NULL) {
++ wpa_printf(MSG_ERROR, "Error in memory allocation\n");
++ return -1;
++ }
++
++ if (hostapd_drv_amnt_dump(hapd, amnt_idx, (u8 *)resp_buf)) {
++ wpa_printf(MSG_ERROR, "Not able to set amnt index\n");
++ os_free(resp_buf);
++ return -1;
++ }
++
++ for (int i = 0; i < resp_buf->sta_num && i < AIR_MONITOR_MAX_ENTRY; i++) {
++ res = &resp_buf->resp_data[i];
++ ret = os_snprintf(pos, end - pos,
++ "[hostapd_cli] amnt_idx: %d, addr="MACSTR
++ ", rssi=%d/%d/%d/%d, last_seen=%u\n",
++ res->idx,
++ MAC2STR(res->addr), res->rssi[0],
++ res->rssi[1], res->rssi[2],
++ res->rssi[3], res->last_seen);
++ if (os_snprintf_error(end - pos, ret)) {
++ os_free(resp_buf);
++ return 0;
++ }
++ pos = pos + ret;
++ }
++
++ os_free(resp_buf);
++
++ if (pos == buf)
++ return os_snprintf(buf, buflen, "Index %d is not monitored\n",
++ amnt_idx);
++ else
++ return pos - buf;
++}
++
+ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
+ char *buf, char *reply,
+ int reply_size,
+@@ -4476,6 +4583,12 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
+ reply_len = hostapd_ctrl_iface_ap_wireless(hapd, buf + 12, reply, reply_size);
+ } else if (os_strncmp(buf, "ap_rfeatures ", 13) == 0) {
+ reply_len = hostapd_ctrl_iface_ap_rfeatures(hapd, buf + 13, reply, reply_size);
++ } else if (os_strncmp(buf, "SET_AMNT", 8) == 0) {
++ reply_len = hostapd_ctrl_iface_set_amnt(hapd, buf+9,
++ reply, reply_size);
++ } else if (os_strncmp(buf, "DUMP_AMNT", 9) == 0) {
++ reply_len = hostapd_ctrl_iface_dump_amnt(hapd, buf+10,
++ reply, reply_size);
+ } else {
+ os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
+ reply_len = 16;
+diff --git a/hostapd/hostapd_cli.c b/hostapd/hostapd_cli.c
+index dc01ad9..02f8546 100644
+--- a/hostapd/hostapd_cli.c
++++ b/hostapd/hostapd_cli.c
+@@ -1633,6 +1633,17 @@ static int hostapd_cli_cmd_get_amsdu(struct wpa_ctrl *ctrl, int argc,
+ return hostapd_cli_cmd(ctrl, "GET_AMSDU", 0, NULL, NULL);
+ }
+
++static int hostapd_cli_cmd_set_amnt(struct wpa_ctrl *ctrl, int argc,
++ char *argv[])
++{
++ return hostapd_cli_cmd(ctrl, "SET_AMNT", 2, argc, argv);
++}
++
++static int hostapd_cli_cmd_dump_amnt(struct wpa_ctrl *ctrl, int argc,
++ char *argv[])
++{
++ return hostapd_cli_cmd(ctrl, "DUMP_AMNT", 1, argc, argv);
++}
+
+ struct hostapd_cli_cmd {
+ const char *cmd;
+@@ -1847,6 +1858,10 @@ static const struct hostapd_cli_cmd hostapd_cli_commands[] = {
+ " = show iBF state (enabled/disabled)"},
+ { "get_amsdu", hostapd_cli_cmd_get_amsdu, NULL,
+ " = show AMSDU state"},
++ { "set_amnt", hostapd_cli_cmd_set_amnt, NULL,
++ " = Set Station index and mac to monitor"},
++ { "dump_amnt", hostapd_cli_cmd_dump_amnt, NULL,
++ " = Dump RSSI of monitoring Station"},
+ { NULL, NULL, NULL, NULL }
+ };
+
+diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c
+index 78b52c8..0052a6d 100644
+--- a/src/ap/ap_drv_ops.c
++++ b/src/ap/ap_drv_ops.c
+@@ -1160,3 +1160,17 @@ int hostapd_drv_ap_trig_type(struct hostapd_data *hapd, u8 enable, u8 type)
+ return 0;
+ return hapd->driver->ap_trigtype(hapd->drv_priv, enable, type);
+ }
++
++int hostapd_drv_amnt_set(struct hostapd_data *hapd, u8 amnt_idx, u8 *amnt_sta_mac)
++{
++ if (!hapd->driver || !hapd->driver->amnt_set)
++ return 0;
++ return hapd->driver->amnt_set(hapd->drv_priv, amnt_idx, amnt_sta_mac);
++}
++
++int hostapd_drv_amnt_dump(struct hostapd_data *hapd, u8 amnt_idx, u8 *amnt_dump_buf)
++{
++ if (!hapd->driver || !hapd->driver->amnt_dump)
++ return 0;
++ return hapd->driver->amnt_dump(hapd->drv_priv, amnt_idx, amnt_dump_buf);
++}
+diff --git a/src/ap/ap_drv_ops.h b/src/ap/ap_drv_ops.h
+index bb9fdf7..9d5a23b 100644
+--- a/src/ap/ap_drv_ops.h
++++ b/src/ap/ap_drv_ops.h
+@@ -161,6 +161,9 @@ int hostapd_drv_ap_wireless(struct hostapd_data *hapd, u8 sub_vendor_id, int val
+ int hostapd_drv_ap_rfeatures(struct hostapd_data *hapd, u8 sub_vendor_id, int value);
+ int hostapd_drv_ap_trig_type(struct hostapd_data *hapd, u8 enable, u8 type);
+
++int hostapd_drv_amnt_set(struct hostapd_data *hapd, u8 amnt_idx, u8 *amnt_sta_mac);
++int hostapd_drv_amnt_dump(struct hostapd_data *hapd, u8 amnt_idx, u8 *amnt_dump_buf);
++
+ #include "drivers/driver.h"
+
+ int hostapd_drv_wnm_oper(struct hostapd_data *hapd,
+diff --git a/src/common/mtk_vendor.h b/src/common/mtk_vendor.h
+index 32438af..74f467c 100644
+--- a/src/common/mtk_vendor.h
++++ b/src/common/mtk_vendor.h
+@@ -256,10 +256,18 @@ struct csi_data {
+ u16 rx_idx;
+ };
+
++#define AIR_MONITOR_MAX_ENTRY 16
++
+ struct amnt_data {
+ u8 idx;
+ u8 addr[ETH_ALEN];
+ s8 rssi[4];
+ u32 last_seen;
+ };
++
++struct amnt_resp_data {
++ u8 sta_num;
++ struct amnt_data resp_data[0];
++};
++
+ #endif /* MTK_VENDOR_H */
+diff --git a/src/drivers/driver.h b/src/drivers/driver.h
+index ae692c2..cb885f9 100644
+--- a/src/drivers/driver.h
++++ b/src/drivers/driver.h
+@@ -5084,6 +5084,22 @@ struct wpa_driver_ops {
+ * @type: trigger type
+ */
+ int (*ap_trigtype)(void *priv, u8 enable, u8 type);
++
++ /**
++ * amnt_set - add/delete station from monitoring
++ * @priv: Private driver interface data
++ * @amnt_idx: Monitor Index
++ * @amnt_sta_mac: station mac address
++ */
++ int (*amnt_set)(void *priv, u8 amnt_idx, u8 *amnt_sta_mac);
++
++ /**
++ * amnt_dump - Dump particular/ all station
++ * @priv: Private driver interface data
++ * @amnt_idx: Monitor Index
++ * @amnt_dump_buf: Buffer to print
++ */
++ int (*amnt_dump)(void *priv, u8 amnt_idx, u8 *amnt_dump_buf);
+ };
+
+ /**
+diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
+index 730a696..088f625 100644
+--- a/src/drivers/driver_nl80211.c
++++ b/src/drivers/driver_nl80211.c
+@@ -127,6 +127,19 @@ wireless_ctrl_policy[NUM_MTK_VENDOR_ATTRS_WIRELESS_CTRL] = {
+ [MTK_VENDOR_ATTR_WIRELESS_CTRL_CERT] = {.type = NLA_U8 },
+ };
+
++static struct nla_policy
++amnt_ctrl_policy[NUM_MTK_VENDOR_ATTRS_AMNT_CTRL] = {
++ [MTK_VENDOR_ATTR_AMNT_CTRL_SET] = {.type = NLA_NESTED },
++ [MTK_VENDOR_ATTR_AMNT_CTRL_DUMP] = { .type = NLA_NESTED },
++};
++
++static struct nla_policy
++amnt_dump_policy[NUM_MTK_VENDOR_ATTRS_AMNT_DUMP] = {
++ [MTK_VENDOR_ATTR_AMNT_DUMP_INDEX] = {.type = NLA_U8 },
++ [MTK_VENDOR_ATTR_AMNT_DUMP_LEN] = { .type = NLA_U8 },
++ [MTK_VENDOR_ATTR_AMNT_DUMP_RESULT] = { .type = NLA_NESTED },
++};
++
+ static struct nl_sock * nl_create_handle(struct nl_cb *cb, const char *dbg)
+ {
+ struct nl_sock *handle;
+@@ -14133,6 +14146,171 @@ fail:
+ return -ENOBUFS;
+ }
+
++static int
++nl80211_amnt_set(void *priv, u8 amnt_idx, u8 *amnt_sta_mac)
++{
++ struct i802_bss *bss = priv;
++ struct wpa_driver_nl80211_data *drv = bss->drv;
++ struct nl_msg *msg;
++ struct nlattr *data;
++ void *tb1;
++ int ret;
++
++ if (!drv->mtk_amnt_vendor_cmd_avail) {
++ wpa_printf(MSG_ERROR,
++ "nl80211: Driver does not support air monitor");
++ return 0;
++ }
++
++ msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR);
++ if (!msg)
++ goto fail;
++
++ if (nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_MTK) ||
++ nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
++ MTK_NL80211_VENDOR_SUBCMD_AMNT_CTRL))
++ goto fail;
++
++ data = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA | NLA_F_NESTED);
++ if (!data)
++ goto fail;
++
++ tb1 = nla_nest_start(msg, MTK_VENDOR_ATTR_AMNT_CTRL_SET);
++ if (!tb1)
++ goto fail;
++
++ nla_put_u8(msg, MTK_VENDOR_ATTR_AMNT_SET_INDEX, amnt_idx);
++
++ nla_put(msg, MTK_VENDOR_ATTR_AMNT_SET_MACADDR, ETH_ALEN, amnt_sta_mac);
++
++ nla_nest_end(msg, tb1);
++ nla_nest_end(msg, data);
++
++ ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
++
++ if (ret)
++ wpa_printf(MSG_ERROR, "Failed to set air monitor. ret=%d (%s)",
++ ret, strerror(-ret));
++
++ return ret;
++
++fail:
++ nlmsg_free(msg);
++ return -ENOBUFS;
++
++}
++
++static int
++mt76_amnt_dump_cb(struct nl_msg *msg, void *arg)
++{
++ struct nlattr *tb[NL80211_ATTR_MAX + 1];
++ struct nlattr *tb1[NUM_MTK_VENDOR_ATTRS_AMNT_CTRL];
++ struct nlattr *tb2[NUM_MTK_VENDOR_ATTRS_AMNT_DUMP];
++ struct nlattr *attr, *cur, *data;
++ struct amnt_data *res;
++ int len = 0, rem;
++ struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
++ struct amnt_resp_data *amnt_dump = (struct amnt_resp_data *)arg;
++
++ nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
++ genlmsg_attrlen(gnlh, 0), NULL);
++
++ attr = tb[NL80211_ATTR_VENDOR_DATA];
++ if (!attr)
++ return NL_SKIP;
++
++ nla_parse_nested(tb1, MTK_VENDOR_ATTR_AMNT_CTRL_MAX,
++ attr, amnt_ctrl_policy);
++
++ if (!tb1[MTK_VENDOR_ATTR_AMNT_CTRL_DUMP])
++ return NL_SKIP;
++
++ nla_parse_nested(tb2, NUM_MTK_VENDOR_ATTRS_AMNT_DUMP,
++ tb1[MTK_VENDOR_ATTR_AMNT_CTRL_DUMP], amnt_dump_policy);
++
++ if (!tb2[MTK_VENDOR_ATTR_AMNT_DUMP_LEN])
++ return NL_SKIP;
++
++ len = nla_get_u8(tb2[MTK_VENDOR_ATTR_AMNT_DUMP_LEN]);
++ if (!len)
++ return 0;
++
++ if (!tb2[MTK_VENDOR_ATTR_AMNT_DUMP_RESULT])
++ return NL_SKIP;
++
++ data = tb2[MTK_VENDOR_ATTR_AMNT_DUMP_RESULT];
++
++ nla_for_each_nested(cur, data, rem) {
++ if (amnt_dump->sta_num >= AIR_MONITOR_MAX_ENTRY)
++ return NL_SKIP;
++ res = (struct amnt_data *) nla_data(cur);
++ wpa_printf(MSG_ERROR, "[vendor] amnt_idx: %d, "
++ "addr="MACSTR", "
++ "rssi=%d/%d/%d/%d, last_seen=%u\n",
++ res->idx,
++ MAC2STR(res->addr),
++ res->rssi[0], res->rssi[1], res->rssi[2],
++ res->rssi[3], res->last_seen);
++ os_memcpy(&amnt_dump->resp_data[amnt_dump->sta_num], res,
++ sizeof(struct amnt_data));
++ amnt_dump->sta_num++;
++ }
++ return 0;
++}
++
++static int
++nl80211_amnt_dump(void *priv, u8 amnt_idx, u8 *dump_buf)
++{
++ struct i802_bss *bss = priv;
++ struct wpa_driver_nl80211_data *drv = bss->drv;
++ struct nl_msg *msg;
++ struct nlattr *data;
++ void *tb1;
++ int ret;
++
++ if (!drv->mtk_amnt_vendor_cmd_avail) {
++ wpa_printf(MSG_INFO,
++ "nl80211: Driver does not support air monitor");
++ return 0;
++ }
++
++ msg = nl80211_drv_msg(drv, NLM_F_DUMP, NL80211_CMD_VENDOR);
++ if (!msg)
++ goto fail;
++
++ if (nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_MTK) ||
++ nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
++ MTK_NL80211_VENDOR_SUBCMD_AMNT_CTRL))
++ goto fail;
++
++ data = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA | NLA_F_NESTED);
++ if (!data)
++ goto fail;
++
++ tb1 = nla_nest_start(msg, MTK_VENDOR_ATTR_AMNT_CTRL_DUMP
++ | NLA_F_NESTED);
++ if (!tb1)
++ goto fail;
++
++ nla_put_u8(msg, MTK_VENDOR_ATTR_AMNT_DUMP_INDEX, amnt_idx);
++
++ nla_nest_end(msg, tb1);
++ nla_nest_end(msg, data);
++
++ ret = send_and_recv_msgs(drv, msg, mt76_amnt_dump_cb,
++ dump_buf, NULL, NULL);
++
++ if (ret)
++ wpa_printf(MSG_ERROR, "Failed to Dump air monitor. ret=%d (%s)"
++ , ret, strerror(-ret));
++
++ return ret;
++
++fail:
++ nlmsg_free(msg);
++ return -ENOBUFS;
++}
++
+ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
+ .name = "nl80211",
+ .desc = "Linux nl80211/cfg80211",
+@@ -14300,4 +14478,6 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
+ .ap_wireless = nl80211_ap_wireless,
+ .ap_rfeatures = nl80211_ap_rfeatures,
+ .ap_trigtype = nl80211_ap_trigtype,
++ .amnt_set = nl80211_amnt_set,
++ .amnt_dump = nl80211_amnt_dump,
+ };
+diff --git a/src/drivers/driver_nl80211.h b/src/drivers/driver_nl80211.h
+index 49588e6..e64a12e 100644
+--- a/src/drivers/driver_nl80211.h
++++ b/src/drivers/driver_nl80211.h
+@@ -206,6 +206,7 @@ struct wpa_driver_nl80211_data {
+ unsigned int mtk_wireless_vendor_cmd_avail:1;
+ unsigned int mtk_bss_color_vendor_cmd_avail:1;
+ unsigned int mtk_rfeatures_vendor_cmd_avail:1;
++ unsigned int mtk_amnt_vendor_cmd_avail:1;
+
+ u64 vendor_scan_cookie;
+ u64 remain_on_chan_cookie;
+diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c
+index 0674b66..7b5079b 100644
+--- a/src/drivers/driver_nl80211_capa.c
++++ b/src/drivers/driver_nl80211_capa.c
+@@ -1119,6 +1119,8 @@ static int wiphy_info_handler(struct nl_msg *msg, void *arg)
+ break;
+ case MTK_NL80211_VENDOR_SUBCMD_BSS_COLOR_CTRL :
+ drv->mtk_bss_color_vendor_cmd_avail = 1;
++ case MTK_NL80211_VENDOR_SUBCMD_AMNT_CTRL:
++ drv->mtk_amnt_vendor_cmd_avail = 1;
+ break;
+ case MTK_NL80211_VENDOR_SUBCMD_RFEATURE_CTRL:
+ drv->mtk_rfeatures_vendor_cmd_avail = 1;
+--
+2.18.0
+
diff --git a/autobuild_mac80211_release/package/network/services/hostapd_new/patches/mtk-0025-hostapd-mtk-Fix-scan-result-updating-issue.patch b/autobuild_mac80211_release/package/network/services/hostapd_new/patches/mtk-0025-hostapd-mtk-Fix-scan-result-updating-issue.patch
new file mode 100644
index 0000000..e00c83b
--- /dev/null
+++ b/autobuild_mac80211_release/package/network/services/hostapd_new/patches/mtk-0025-hostapd-mtk-Fix-scan-result-updating-issue.patch
@@ -0,0 +1,33 @@
+From b86163db7e137c7a91f77f35bc2d5001177c371e Mon Sep 17 00:00:00 2001
+From: Michael Lee <michael-cy.lee@mediatek.com>
+Date: Wed, 19 Apr 2023 17:18:33 +0800
+Subject: [PATCH 25/28] hostapd: mtk: Fix scan result updating issue
+
+There are no HT capability and operation in beacon of AP operating in
+NOHT.
+Therefore, when updating scan results, HT capability and operation
+should be assigned the default value for this kind of AP.
+---
+ wpa_supplicant/bss.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/wpa_supplicant/bss.c b/wpa_supplicant/bss.c
+index 3bfcf7e..004d4a6 100644
+--- a/wpa_supplicant/bss.c
++++ b/wpa_supplicant/bss.c
+@@ -307,8 +307,12 @@ static void wpa_bss_copy_res(struct wpa_bss *dst, struct wpa_scan_res *src,
+ oper = (struct ieee80211_ht_operation *) elems.ht_operation;
+ if (capab)
+ dst->ht_capab = le_to_host16(capab->ht_capabilities_info);
++ else
++ dst->ht_capab = 0;
+ if (oper)
+ dst->ht_param = oper->ht_param;
++ else
++ dst->ht_param = 0;
+
+ calculate_update_time(fetch_time, src->age, &dst->last_update);
+ }
+--
+2.18.0
+
diff --git a/autobuild_mac80211_release/package/network/services/hostapd_new/patches/mtk-0026-hostapd-mtk-avoid-setting-beacon-after-wpa_supplican.patch b/autobuild_mac80211_release/package/network/services/hostapd_new/patches/mtk-0026-hostapd-mtk-avoid-setting-beacon-after-wpa_supplican.patch
new file mode 100644
index 0000000..87e286e
--- /dev/null
+++ b/autobuild_mac80211_release/package/network/services/hostapd_new/patches/mtk-0026-hostapd-mtk-avoid-setting-beacon-after-wpa_supplican.patch
@@ -0,0 +1,135 @@
+From 1d5dfbffb750a0de15622265dc709524a330f059 Mon Sep 17 00:00:00 2001
+From: Evelyn Tsai <evelyn.tsai@mediatek.com>
+Date: Fri, 12 May 2023 05:21:28 +0800
+Subject: [PATCH 26/28] hostapd: mtk: avoid setting beacon after wpa_supplicant
+ stop the AP
+
+Add a new variable 'stopped_by_supplicant' to indicate the AP
+interface is currently stopped by co-locating STA interface.
+After the STA interface finishes association with some other APs, it
+will reload the co-locating AP interfaces and marks the
+'stopped_by_supplicant' as 0.
+---
+ hostapd/ctrl_iface.c | 4 ++++
+ src/ap/beacon.c | 5 ++++-
+ src/ap/bss_load.c | 3 ++-
+ src/ap/ctrl_iface_ap.c | 4 +++-
+ src/ap/hostapd.c | 2 ++
+ src/ap/hostapd.h | 1 +
+ 6 files changed, 16 insertions(+), 3 deletions(-)
+
+diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
+index 234b800..06d8345 100644
+--- a/hostapd/ctrl_iface.c
++++ b/hostapd/ctrl_iface.c
+@@ -194,11 +194,15 @@ static int hostapd_ctrl_iface_update(struct hostapd_data *hapd, char *txt)
+ {
+ struct hostapd_config * (*config_read_cb)(const char *config_fname);
+ struct hostapd_iface *iface = hapd->iface;
++ size_t j;
+
+ config_read_cb = iface->interfaces->config_read_cb;
+ iface->interfaces->config_read_cb = hostapd_ctrl_iface_config_read;
+ reload_opts = txt;
+
++ for (j = 0; j < iface->num_bss; j++)
++ iface->bss[j]->stopped_by_supplicant = 0;
++
+ hostapd_reload_config(iface, 0);
+
+ iface->interfaces->config_read_cb = config_read_cb;
+diff --git a/src/ap/beacon.c b/src/ap/beacon.c
+index ddb5d03..ffa27f3 100644
+--- a/src/ap/beacon.c
++++ b/src/ap/beacon.c
+@@ -2169,7 +2169,8 @@ int ieee802_11_set_beacon(struct hostapd_data *hapd)
+ continue;
+
+ for (i = 0; i < colocated->num_bss; i++) {
+- if (colocated->bss[i] && colocated->bss[i]->started)
++ if (colocated->bss[i] && colocated->bss[i]->started &&
++ !colocated->bss[i]->stopped_by_supplicant)
+ __ieee802_11_set_beacon(colocated->bss[i]);
+ }
+ }
+@@ -2185,6 +2186,7 @@ int ieee802_11_set_beacons(struct hostapd_iface *iface)
+
+ for (i = 0; i < iface->num_bss; i++) {
+ if (iface->bss[i]->started &&
++ !iface->bss[i]->stopped_by_supplicant &&
+ ieee802_11_set_beacon(iface->bss[i]) < 0)
+ ret = -1;
+ }
+@@ -2201,6 +2203,7 @@ int ieee802_11_update_beacons(struct hostapd_iface *iface)
+
+ for (i = 0; i < iface->num_bss; i++) {
+ if (iface->bss[i]->beacon_set_done && iface->bss[i]->started &&
++ !iface->bss[i]->stopped_by_supplicant &&
+ ieee802_11_set_beacon(iface->bss[i]) < 0)
+ ret = -1;
+ }
+diff --git a/src/ap/bss_load.c b/src/ap/bss_load.c
+index 725d3cd..ae55521 100644
+--- a/src/ap/bss_load.c
++++ b/src/ap/bss_load.c
+@@ -46,7 +46,8 @@ static void update_channel_utilization(void *eloop_data, void *user_data)
+ int err;
+ struct hostapd_iface *iface = hapd->iface;
+
+- if (!(hapd->beacon_set_done && hapd->started))
++ if (!(hapd->beacon_set_done && hapd->started &&
++ !hapd->stopped_by_supplicant))
+ return;
+
+ err = hostapd_drv_get_survey(hapd, hapd->iface->freq);
+diff --git a/src/ap/ctrl_iface_ap.c b/src/ap/ctrl_iface_ap.c
+index fed5473..2a8ac9d 100644
+--- a/src/ap/ctrl_iface_ap.c
++++ b/src/ap/ctrl_iface_ap.c
+@@ -1013,8 +1013,10 @@ int hostapd_ctrl_iface_stop_ap(struct hostapd_data *hapd)
+ struct hostapd_iface *iface = hapd->iface;
+ int i;
+
+- for (i = 0; i < iface->num_bss; i++)
++ for (i = 0; i < iface->num_bss; i++){
++ iface->bss[i]->stopped_by_supplicant = 1;
+ hostapd_drv_stop_ap(iface->bss[i]);
++ }
+
+ return 0;
+ }
+diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
+index 88eb984..05ddb6f 100644
+--- a/src/ap/hostapd.c
++++ b/src/ap/hostapd.c
+@@ -488,6 +488,7 @@ void hostapd_free_hapd_data(struct hostapd_data *hapd)
+ }
+ hapd->started = 0;
+ hapd->beacon_set_done = 0;
++ hapd->stopped_by_supplicant = 0;
+
+ wpa_printf(MSG_DEBUG, "%s(%s)", __func__, hapd->conf->iface);
+ hostapd_ubus_free_bss(hapd);
+@@ -1290,6 +1291,7 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first,
+ return -1;
+ }
+ hapd->started = 1;
++ hapd->stopped_by_supplicant = 0;
+
+ if (!first || first == -1) {
+ u8 *addr = hapd->own_addr;
+diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h
+index c0b3a08..fb8566a 100644
+--- a/src/ap/hostapd.h
++++ b/src/ap/hostapd.h
+@@ -190,6 +190,7 @@ struct hostapd_data {
+ unsigned int started:1;
+ unsigned int disabled:1;
+ unsigned int reenable_beacon:1;
++ unsigned int stopped_by_supplicant:1;
+
+ u8 own_addr[ETH_ALEN];
+
+--
+2.18.0
+
diff --git a/autobuild_mac80211_release/package/network/services/hostapd_new/patches/mtk-0027-hostapd-mtk-Fix-setting-wrong-seg0-index-for-5G-cent.patch b/autobuild_mac80211_release/package/network/services/hostapd_new/patches/mtk-0027-hostapd-mtk-Fix-setting-wrong-seg0-index-for-5G-cent.patch
new file mode 100644
index 0000000..462989c
--- /dev/null
+++ b/autobuild_mac80211_release/package/network/services/hostapd_new/patches/mtk-0027-hostapd-mtk-Fix-setting-wrong-seg0-index-for-5G-cent.patch
@@ -0,0 +1,28 @@
+From f229416c4283da4a2f3b264285a5d97fdc8dcc96 Mon Sep 17 00:00:00 2001
+From: Evelyn Tsai <evelyn.tsai@mediatek.com>
+Date: Fri, 12 May 2023 05:23:00 +0800
+Subject: [PATCH 27/28] hostapd: mtk: Fix setting wrong seg0 index for 5G
+ center chan 159 BW40
+
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+---
+ src/ap/ap_config.h | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
+index b9aaa85..9df0b2c 100644
+--- a/src/ap/ap_config.h
++++ b/src/ap/ap_config.h
+@@ -1294,7 +1294,8 @@ hostapd_set_oper_centr_freq_seg0_idx(struct hostapd_config *conf,
+ #ifdef CONFIG_IEEE80211BE
+ if (conf->ieee80211be)
+ conf->eht_oper_centr_freq_seg0_idx = oper_centr_freq_seg0_idx;
+- if (center_idx_to_bw_6ghz(oper_centr_freq_seg0_idx) == 4)
++ if (is_6ghz_op_class(conf->op_class) &&
++ center_idx_to_bw_6ghz(oper_centr_freq_seg0_idx) == 4)
+ oper_centr_freq_seg0_idx +=
+ conf->channel > oper_centr_freq_seg0_idx ? 16 : -16;
+ #endif /* CONFIG_IEEE80211BE */
+--
+2.18.0
+
diff --git a/autobuild_mac80211_release/package/network/services/hostapd_new/patches/mtk-0028-hostapd-mtk-Add-muru-user-number-debug-command.patch b/autobuild_mac80211_release/package/network/services/hostapd_new/patches/mtk-0028-hostapd-mtk-Add-muru-user-number-debug-command.patch
new file mode 100644
index 0000000..26ea489
--- /dev/null
+++ b/autobuild_mac80211_release/package/network/services/hostapd_new/patches/mtk-0028-hostapd-mtk-Add-muru-user-number-debug-command.patch
@@ -0,0 +1,229 @@
+From a90c24ae2b7558eac18cf92fee6cfaf480233ec2 Mon Sep 17 00:00:00 2001
+From: Evelyn Tsai <evelyn.tsai@mediatek.com>
+Date: Fri, 12 May 2023 05:24:19 +0800
+Subject: [PATCH 28/28] hostapd: mtk: Add muru user number debug command
+
+---
+ hostapd/ctrl_iface.c | 13 ++++++++++++-
+ src/ap/ap_drv_ops.c | 4 ++--
+ src/ap/ap_drv_ops.h | 2 +-
+ src/ap/hostapd.c | 4 ++--
+ src/common/mtk_vendor.h | 7 +++++++
+ src/drivers/driver.h | 4 ++--
+ src/drivers/driver_nl80211.c | 37 ++++++++++++++++++++++++++++--------
+ 7 files changed, 55 insertions(+), 16 deletions(-)
+
+diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
+index 06d8345..2d99647 100644
+--- a/hostapd/ctrl_iface.c
++++ b/hostapd/ctrl_iface.c
+@@ -3441,6 +3441,8 @@ hostapd_ctrl_iface_set_edcca(struct hostapd_data *hapd, char *cmd,
+ char *buf, size_t buflen)
+ {
+ char *pos, *config, *value;
++ u8 mode;
++
+ config = cmd;
+ pos = os_strchr(config, ' ');
+ if (pos == NULL)
+@@ -3547,6 +3549,8 @@ hostapd_ctrl_iface_set_mu(struct hostapd_data *hapd, char *cmd,
+ char *buf, size_t buflen)
+ {
+ char *pos, *config, *value;
++ u8 mode;
++
+ config = cmd;
+ pos = os_strchr(config, ' ');
+ if (pos == NULL)
+@@ -3564,13 +3568,20 @@ hostapd_ctrl_iface_set_mu(struct hostapd_data *hapd, char *cmd,
+ return -1;
+ }
+ hapd->iconf->mu_onoff = (u8) mu;
++ mode = MU_CTRL_ONOFF;
++ } else if (os_strcmp(config, "ul_user_cnt") == 0) {
++ mode = MU_CTRL_UL_USER_CNT;
++ wpa_printf(MSG_ERROR, "ul_user_cnt:%d\n", (u8)atoi(value));
++ } else if (os_strcmp(config, "dl_user_cnt") == 0) {
++ mode = MU_CTRL_DL_USER_CNT;
++ wpa_printf(MSG_ERROR, "dl_user_cnt:%d\n", (u8)atoi(value));
+ } else {
+ wpa_printf(MSG_ERROR,
+ "Unsupported parameter %s for SET_MU", config);
+ return -1;
+ }
+
+- if(hostapd_drv_mu_ctrl(hapd) == 0) {
++ if(hostapd_drv_mu_ctrl(hapd, mode, (u8)atoi(value)) == 0) {
+ return os_snprintf(buf, buflen, "OK\n");
+ } else {
+ return -1;
+diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c
+index 0052a6d..d5c7b15 100644
+--- a/src/ap/ap_drv_ops.c
++++ b/src/ap/ap_drv_ops.c
+@@ -1079,11 +1079,11 @@ int hostapd_drv_get_edcca(struct hostapd_data *hapd, const u8 mode, u8 *value)
+ return hapd->driver->get_edcca(hapd->drv_priv, mode, value);
+ }
+
+-int hostapd_drv_mu_ctrl(struct hostapd_data *hapd)
++int hostapd_drv_mu_ctrl(struct hostapd_data *hapd, u8 mode, u8 val)
+ {
+ if (!hapd->driver || !hapd->driver->mu_ctrl)
+ return 0;
+- return hapd->driver->mu_ctrl(hapd->drv_priv, hapd->iconf->mu_onoff);
++ return hapd->driver->mu_ctrl(hapd->drv_priv, mode, val);
+ }
+
+ int hostapd_drv_mu_dump(struct hostapd_data *hapd, u8 *mu_onoff)
+diff --git a/src/ap/ap_drv_ops.h b/src/ap/ap_drv_ops.h
+index 9d5a23b..82283e6 100644
+--- a/src/ap/ap_drv_ops.h
++++ b/src/ap/ap_drv_ops.h
+@@ -148,7 +148,7 @@ int hostapd_drv_configure_edcca_enable(struct hostapd_data *hapd);
+ int hostapd_drv_configure_edcca_threshold(struct hostapd_data *hapd,
+ const int *threshold);
+ int hostapd_drv_get_edcca(struct hostapd_data *hapd, const u8 mode, u8 *value);
+-int hostapd_drv_mu_ctrl(struct hostapd_data *hapd);
++int hostapd_drv_mu_ctrl(struct hostapd_data *hapd, u8 mode, u8 val);
+ int hostapd_drv_mu_dump(struct hostapd_data *hapd, u8 *mu_onoff);
+ int hostapd_drv_three_wire_ctrl(struct hostapd_data *hapd);
+ int hostapd_drv_ibf_ctrl(struct hostapd_data *hapd);
+diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
+index 05ddb6f..9bd81d3 100644
+--- a/src/ap/hostapd.c
++++ b/src/ap/hostapd.c
+@@ -55,7 +55,7 @@
+ #include "hs20.h"
+ #include "airtime_policy.h"
+ #include "wpa_auth_kay.h"
+-
++#include "common/mtk_vendor.h"
+
+ static int hostapd_flush_old_stations(struct hostapd_data *hapd, u16 reason);
+ #ifdef CONFIG_WEP
+@@ -2398,7 +2398,7 @@ dfs_offload:
+ if (hostapd_drv_configure_edcca_threshold(hapd,
+ hapd->iconf->edcca_threshold) < 0)
+ goto fail;
+- if (hostapd_drv_mu_ctrl(hapd) < 0)
++ if (hostapd_drv_mu_ctrl(hapd, MU_CTRL_ONOFF, hapd->iconf->mu_onoff) < 0)
+ goto fail;
+ if (hostapd_drv_three_wire_ctrl(hapd) < 0)
+ goto fail;
+diff --git a/src/common/mtk_vendor.h b/src/common/mtk_vendor.h
+index 74f467c..7dd2fc4 100644
+--- a/src/common/mtk_vendor.h
++++ b/src/common/mtk_vendor.h
+@@ -197,6 +197,8 @@ enum mtk_vendor_attr_mu_ctrl {
+
+ MTK_VENDOR_ATTR_MU_CTRL_ONOFF,
+ MTK_VENDOR_ATTR_MU_CTRL_DUMP,
++ MTK_VENDOR_ATTR_MU_CTRL_OFDMA_MODE,
++ MTK_VENDOR_ATTR_MU_CTRL_OFDMA_VAL,
+
+ /* keep last */
+ NUM_MTK_VENDOR_ATTRS_MU_CTRL,
+@@ -270,4 +272,9 @@ struct amnt_resp_data {
+ struct amnt_data resp_data[0];
+ };
+
++enum {
++ MU_CTRL_ONOFF,
++ MU_CTRL_DL_USER_CNT,
++ MU_CTRL_UL_USER_CNT,
++};
+ #endif /* MTK_VENDOR_H */
+diff --git a/src/drivers/driver.h b/src/drivers/driver.h
+index cb885f9..6cd4dc9 100644
+--- a/src/drivers/driver.h
++++ b/src/drivers/driver.h
+@@ -5017,11 +5017,11 @@ struct wpa_driver_ops {
+ int (*get_edcca)(void *priv, const u8 mode, u8 *value);
+
+ /**
+- * mu_ctrl - ctrl on off for UL/DL MURU
++ * mu_ctrl - ctrl for UL/DL MURU
+ * @priv: Private driver interface data
+ *
+ */
+- int (*mu_ctrl)(void *priv, u8 mu_onoff);
++ int (*mu_ctrl)(void *priv, u8 mode, u8 val);
+ int (*mu_dump)(void *priv, u8 *mu_onoff);
+
+ /**
+diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
+index 088f625..8400e57 100644
+--- a/src/drivers/driver_nl80211.c
++++ b/src/drivers/driver_nl80211.c
+@@ -13295,13 +13295,13 @@ fail:
+
+
+ #ifdef CONFIG_IEEE80211AX
+-static int nl80211_mu_onoff(void *priv, u8 mu_onoff)
++static int nl80211_mu_ctrl(void *priv, u8 mode, u8 val)
+ {
+ struct i802_bss *bss = priv;
+ struct wpa_driver_nl80211_data *drv = bss->drv;
+ struct nl_msg *msg;
+ struct nlattr *data;
+- int ret;
++ int ret = -ENOBUFS;
+
+ if (!drv->mtk_mu_vendor_cmd_avail) {
+ wpa_printf(MSG_INFO,
+@@ -13312,17 +13312,38 @@ static int nl80211_mu_onoff(void *priv, u8 mu_onoff)
+ if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR)) ||
+ nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_MTK) ||
+ nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD, MTK_NL80211_VENDOR_SUBCMD_MU_CTRL) ||
+- !(data = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA)) ||
+- nla_put_u8(msg, MTK_VENDOR_ATTR_MU_CTRL_ONOFF, mu_onoff)) {
+- nlmsg_free(msg);
+- return -ENOBUFS;
++ !(data = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA)))
++ goto fail;
++
++ switch (mode) {
++ case MU_CTRL_ONOFF:
++ if (nla_put_u8(msg, MTK_VENDOR_ATTR_MU_CTRL_ONOFF, val))
++ goto fail;
++ break;
++ case MU_CTRL_UL_USER_CNT:
++ case MU_CTRL_DL_USER_CNT:
++ if (nla_put_u8(msg, MTK_VENDOR_ATTR_MU_CTRL_OFDMA_MODE, mode) ||
++ nla_put_u8(msg, MTK_VENDOR_ATTR_MU_CTRL_OFDMA_VAL, val))
++ goto fail;
++ break;
++ default:
++ wpa_printf(MSG_ERROR, "nl80211: Wrong mu mode !");
++ ret = -EINVAL;
++ goto fail;
+ }
++
+ nla_nest_end(msg, data);
++
+ ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
+ if(ret){
+- wpa_printf(MSG_ERROR, "Failed to set mu_onoff. ret=%d (%s)", ret, strerror(-ret));
++ wpa_printf(MSG_ERROR, "Failed to set mu_ctrl. ret=%d (%s)", ret, strerror(-ret));
+ }
+ return ret;
++
++fail:
++ nl80211_nlmsg_clear(msg);
++ nlmsg_free(msg);
++ return ret;
+ }
+
+
+@@ -14454,7 +14475,7 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
+ .update_connect_params = nl80211_update_connection_params,
+ .send_external_auth_status = nl80211_send_external_auth_status,
+ .set_4addr_mode = nl80211_set_4addr_mode,
+- .mu_ctrl = nl80211_mu_onoff,
++ .mu_ctrl = nl80211_mu_ctrl,
+ .mu_dump = nl80211_mu_dump,
+ #ifdef CONFIG_DPP
+ .dpp_listen = nl80211_dpp_listen,
+--
+2.18.0
+