[rdkb][common][bsp][Refactor and sync wifi from openwrt]

[Description]
a0c7684 [MAC80211][mt76][update mt76 patches]
a2e0f7c [MAC80211][core][Remove start disabled patch in eagle]
4562ef0 [MAC80211][hostapd][Refactor hostapd patch for git am]
22614f8 [mt76][Add vendor cmd to get available color bitmap]
b7b4fef [mac80211][Track obss color bitmap]
3f4ab41 [hostapd][Add hostapd_cli cmd to get available color bitmap]
cb120e7 [MAC80211][core][remove ba timer disabled patches]
24f983f [MAC80211][misc][sync iproute2 package]
3e866ee [MAC80211][core][Mark DFS channel available for CSA]
bdc6428 [MAC80211][hostapd][Mark DFS channel available for CSA]
9113e92 [MAC80211][app][Add eagle testmode iwpriv wrapper support]
d6bd8f4 [mac80211][mt76][Refactor mt76 patches]
7829a83 [MAC80211][mt76][Add monitor vif check in testmode]
19ead62 [mt76][eagle][hostapd mbssid and ema support]

[Release-log]

Change-Id: I75bf6ff01bc50054404bca23fd31cff9d1bc8d86
diff --git a/recipes-wifi/atenl/files/iwpriv.sh b/recipes-wifi/atenl/files/iwpriv.sh
index 3690c2d..de74190 100644
--- a/recipes-wifi/atenl/files/iwpriv.sh
+++ b/recipes-wifi/atenl/files/iwpriv.sh
@@ -269,6 +269,12 @@
         echo "he_tb"
     elif [ "$tx_mode" = "11" ]; then
         echo "he_mu"
+    elif [ "$tx_mode" = "13" ]; then
+        echo "eht_su"
+    elif [ "$tx_mode" = "14" ]; then
+        echo "eht_tb"
+    elif [ "$tx_mode" = "15" ]; then
+        echo "eht_mu"
     else
         echo "undefined"
     fi
@@ -496,7 +502,27 @@
         local base_freq=5180
         local base_chan=36
     else
+        local base_freq=5955
         case ${bw} in
+            "12")
+                local bw_str="320"
+                if [ ${ch} == "31" ]; then
+                    local control_freq="5955"
+                elif [ ${ch} == "63" ]; then
+                    local control_freq="6115"
+                elif [ ${ch} == "95" ]; then
+                    local control_freq="6275"
+                elif [ ${ch} == "127" ]; then
+                    local control_freq="6435"
+                elif [ ${ch} == "159" ]; then
+                    local control_freq="6595"
+                elif [ ${ch} == "191" ]; then
+                    local control_freq="6755"
+                fi
+                local center_freq=$(((ch - base_chan) * 5 + base_freq))
+                do_cmd "iw dev mon${phy_idx} set freq ${control_freq} ${bw_str} ${center_freq}"
+                return
+                ;;
             "5")
                 bw_str="160MHz"
                 if [ ${ch} -lt "33" ]; then
@@ -644,7 +670,6 @@
                 local bw_str="HT20"
                 ;;
         esac
-        local base_freq=5955
     fi
 
     local control_freq=$(((ch - base_chan) * 5 + base_freq))
@@ -826,15 +851,22 @@
     if [ "${cmd}" = "ATETxPacketWithBf" ]; then
         do_cmd "mt76-test phy${phy_idx} set state=tx_frames"
     elif [ "${cmd}" = "ATEConTxETxBfInitProc" ]; then
+        local wlan_idx="1"
+        if [ ${is_eagle} == "1" ]; then
+            local wlan_idx=$((phy_idx+1))
+        fi
         do_cmd "mt76-test phy${phy_idx} set aid=1"
         do_cmd "mt76-test phy${phy_idx} set txbf_act=stop_sounding txbf_param=1"
         do_cmd "mt76-test phy${phy_idx} set txbf_act=update_ch txbf_param=1"
         do_cmd "mt76-test phy${phy_idx} set txbf_act=ebf_prof_update txbf_param=0,0,0"
-        do_cmd "mt76-test phy${phy_idx} set txbf_act=apply_tx txbf_param=1,1,0,0,0"
+        do_cmd "mt76-test phy${phy_idx} set txbf_act=apply_tx txbf_param=${wlan_idx},1,0,0,0"
+        if [ ${is_eagle} == "1" ]; then
+            do_cmd "mt76-test phy${phy_idx} set txbf_act=txcmd txbf_param=1,1,1"
+        fi
         do_cmd "mt76-test phy${phy_idx} set txbf_act=pfmu_tag_read txbf_param=0,1"
-        do_cmd "mt76-test phy${phy_idx} set txbf_act=sta_rec_read txbf_param=1"
-        do_cmd "mt76-test phy${phy_idx} set txbf_act=trigger_sounding txbf_param=0,1,0,1,0,0,0"
-        do_cmd "mt76-test phy${phy_idx} set txbf_act=trigger_sounding txbf_param=2,1,ff,1,0,0,0"
+        do_cmd "mt76-test phy${phy_idx} set txbf_act=sta_rec_read txbf_param=${wlan_idx}"
+        do_cmd "mt76-test phy${phy_idx} set txbf_act=trigger_sounding txbf_param=0,1,0,${wlan_idx},0,0,0"
+        do_cmd "mt76-test phy${phy_idx} set txbf_act=trigger_sounding txbf_param=2,1,ff,${wlan_idx},0,0,0"
         do_cmd "mt76-test phy${phy_idx} set state=rx_frames"
     elif [ "${cmd}" = "ATEConTxETxBfGdProc" ]; then
         do_cmd "mt76-test phy${phy_idx} set aid=1"
@@ -1104,6 +1136,11 @@
     exit
 elif [[ ${interface} == "ra"* ]]; then
     convert_interface $interface
+elif [[ ${interface} == "phy" ]]; then
+    # handle mwctl phy phy0 e2p ... case
+    interface=$2
+    cmd_type=$3
+    full_cmd=$4
 fi
 
 tmp_work_mode=$(get_config "WORKMODE" ${iwpriv_file})
@@ -1122,13 +1159,12 @@
         ## Therefore this wrapper would translate it to either mt76-test or mt76-vendor based on the attribute of the command
         ## Translate to mt76-vendor command
         "csi"|"amnt"|"ap_rfeatures"|"ap_wireless"|"mu")
-	    if [ ${is_eagle} == "1" ]; then
+            if [ ${is_eagle} == "1" ]; then
                 do_cmd "hostapd_cli -i $*"
-                skip=1
-	    else
+            else
                 do_cmd "mt76-vendor $*"
-                skip=1
-	    fi        
+            fi
+            skip=1
             ;;
         "ATE")
             do_ate_work ${param}
@@ -1152,9 +1188,14 @@
             param_new=${param}
             ;;
         "ATETXGI")
-            tx_mode=$(convert_tx_mode $(get_config "ATETXMODE" ${iwpriv_file}))
-            convert_gi ${tx_mode} ${param}
-            skip=1
+            if [ ${is_eagle} == "0" ]; then
+                tx_mode=$(convert_tx_mode $(get_config "ATETXMODE" ${iwpriv_file}))
+                convert_gi ${tx_mode} ${param}
+                skip=1
+            else
+                cmd_new="tx_rate_sgi"
+                param_new=${param}
+            fi
             ;;
         "ATETXMODE")
             cmd_new="tx_rate_mode"
@@ -1167,10 +1208,18 @@
                 record_config ${cmd} ${param} ${iwpriv_file}
             fi
             ;;
-        "ATETXPOW0"|"ATETXPOW1"|"ATETXPOW2"|"ATETXPOW3")
+        "ATETXPOW0"|"ATETXPOW1"|"ATETXPOW2"|"ATETXPOW3"|"ATETXPOW")
             cmd_new="tx_power"
+            if [ "${param}" == "127" ]; then
+                # for iTest verification
+                exit
+            fi
             param_new="${param},0,0,0"
             ;;
+        "ATEMUAID")
+            cmd_new="aid"
+            param_new=${param}
+            ;;
         "ATETXBW")
             record_config ${cmd} ${param} ${iwpriv_file}
             skip=1
@@ -1233,6 +1282,8 @@
 
         do_cmd "echo ${param} > ${wlan_idx}"
         do_cmd "cat ${wtbl_info}"
+    elif [ "${cmd}" = "ATERXSTAT" ]; then
+        convert_rxstat
     else
         do_cmd "mt76-test ${interface} dump"
         do_cmd "mt76-test ${interface} dump stats"
diff --git a/recipes-wifi/hostapd/files/hostapd-full.config b/recipes-wifi/hostapd/files/hostapd-full.config
index b92f9a2..9076ebc 100644
--- a/recipes-wifi/hostapd/files/hostapd-full.config
+++ b/recipes-wifi/hostapd/files/hostapd-full.config
@@ -142,7 +142,7 @@
 
 # RADIUS authentication server. This provides access to the integrated EAP
 # server from external hosts using RADIUS.
-#CONFIG_RADIUS_SERVER=y
+CONFIG_RADIUS_SERVER=y
 
 # Build IPv6 support for RADIUS operations
 CONFIG_IPV6=y
diff --git a/recipes-wifi/hostapd/files/openwrt_script/hostapd.sh b/recipes-wifi/hostapd/files/openwrt_script/hostapd.sh
index 8c233a4..28bd210 100644
--- a/recipes-wifi/hostapd/files/openwrt_script/hostapd.sh
+++ b/recipes-wifi/hostapd/files/openwrt_script/hostapd.sh
@@ -265,11 +265,11 @@
 	config_add_int ieee80211w
 	config_add_int eapol_version
 
-	config_add_string 'auth_server:host' 'server:host'
+	config_add_array auth_server acct_server
+	config_add_string 'server:host'
 	config_add_string auth_secret key
 	config_add_int 'auth_port:port' 'port:port'
 
-	config_add_string acct_server
 	config_add_string acct_secret
 	config_add_int acct_port
 	config_add_int acct_interval
@@ -524,6 +524,20 @@
 	[ -n "$1" ] && append bss_conf "airtime_sta_weight=$1" "$N"
 }
 
+append_auth_server() {
+	[ -n "$1" ] || return
+	append bss_conf "auth_server_addr=$1" "$N"
+	append bss_conf "auth_server_port=$auth_port" "$N"
+	[ -n "$auth_secret" ] && append bss_conf "auth_server_shared_secret=$auth_secret" "$N"
+}
+
+append_acct_server() {
+	[ -n "$1" ] || return
+	append bss_conf "acct_server_addr=$1" "$N"
+	append bss_conf "acct_server_port=$acct_port" "$N"
+	[ -n "$acct_secret" ] && append bss_conf "acct_server_shared_secret=$acct_secret" "$N"
+}
+
 hostapd_set_bss_options() {
 	local var="$1"
 	local phy="$2"
@@ -542,7 +556,7 @@
 		wps_independent wps_device_type wps_device_name wps_manufacturer wps_pin \
 		macfilter ssid utf8_ssid wmm uapsd hidden short_preamble rsn_preauth \
 		iapp_interface eapol_version dynamic_vlan ieee80211w nasid \
-		acct_server acct_secret acct_port acct_interval \
+		acct_secret acct_port acct_interval \
 		bss_load_update_period chan_util_avg_period sae_require_mfp sae_pwe \
 		multi_ap multi_ap_backhaul_ssid multi_ap_backhaul_key skip_inactivity_poll \
 		ppsk airtime_bss_weight airtime_bss_limit airtime_sta_weight \
@@ -614,15 +628,10 @@
 	set_default nasid "${macaddr//\:}"
 	append bss_conf "nas_identifier=$nasid" "$N"
 
-	[ -n "$acct_server" ] && {
-		append bss_conf "acct_server_addr=$acct_server" "$N"
-		append bss_conf "acct_server_port=$acct_port" "$N"
-		[ -n "$acct_secret" ] && \
-			append bss_conf "acct_server_shared_secret=$acct_secret" "$N"
-		[ -n "$acct_interval" ] && \
-			append bss_conf "radius_acct_interim_interval=$acct_interval" "$N"
-		json_for_each_item append_radius_acct_req_attr radius_acct_req_attr
-	}
+	[ -n "$acct_interval" ] && \
+		append bss_conf "radius_acct_interim_interval=$acct_interval" "$N"
+	json_for_each_item append_acct_server acct_server
+	json_for_each_item append_radius_acct_req_attr radius_acct_req_attr
 
 	[ -n "$ocv" ] && append bss_conf "ocv=$ocv" "$N"
 
@@ -659,11 +668,9 @@
 		psk|sae|psk-sae)
 			json_get_vars key wpa_psk_file
 			if [ "$auth_type" = "psk" ] && [ "$ppsk" -ne 0 ] ; then
-				json_get_vars auth_server auth_secret auth_port
+				json_get_vars auth_secret auth_port
 				set_default auth_port 1812
-				append bss_conf "auth_server_addr=$auth_server" "$N"
-				append bss_conf "auth_server_port=$auth_port" "$N"
-				append bss_conf "auth_server_shared_secret=$auth_secret" "$N"
+				json_for_each_item append_auth_server auth_server
 				append bss_conf "macaddr_acl=2" "$N"
 				append bss_conf "wpa_psk_radius=2" "$N"
 			elif [ ${#key} -eq 64 ]; then
@@ -732,12 +739,7 @@
 			set_default dae_port 3799
 			set_default request_cui 0
 
-			[ "$eap_server" -eq 0 ] && {
-				append bss_conf "auth_server_addr=$auth_server" "$N"
-				append bss_conf "auth_server_port=$auth_port" "$N"
-				append bss_conf "auth_server_shared_secret=$auth_secret" "$N"
-			}
-
+			[ "$eap_server" -eq 0 ] && json_for_each_item append_auth_server auth_server
 			[ "$request_cui" -gt 0 ] && append bss_conf "radius_request_cui=$request_cui" "$N"
 			[ -n "$eap_reauth_period" ] && append bss_conf "eap_reauth_period=$eap_reauth_period" "$N"
 
@@ -777,9 +779,7 @@
 			[ -n "$auth_server" ] &&  {
 				set_default auth_port 1812
 
-				append bss_conf "auth_server_addr=$auth_server" "$N"
-				append bss_conf "auth_server_port=$auth_port" "$N"
-				[ -n "$auth_secret" ] && append bss_conf "auth_server_shared_secret=$auth_secret" "$N"
+				json_for_each_item append_auth_server auth_server
 				[ -n "$ownip" ] && append bss_conf "own_ip_addr=$ownip" "$N"
 				[ -n "$radius_client_addr" ] && append bss_conf "radius_client_addr=$radius_client_addr" "$N"
 				append bss_conf "macaddr_acl=2" "$N"
diff --git a/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0010-hostapd-mtk-Add-DFS-detection-mode.patch b/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0010-hostapd-mtk-Add-DFS-detection-mode.patch
index 2ceb639..7ec986a 100644
--- a/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0010-hostapd-mtk-Add-DFS-detection-mode.patch
+++ b/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0010-hostapd-mtk-Add-DFS-detection-mode.patch
@@ -63,7 +63,7 @@
  					      char *buf, char *reply,
  					      int reply_size,
 @@ -4081,6 +4101,9 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
- 		reply_len = hostapd_ctrl_iface_get_hemu(hapd, reply, reply_size);
+ 		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) {
diff --git a/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0016-hostapd-mtk-Add-available-color-bitmap.patch b/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0016-hostapd-mtk-Add-available-color-bitmap.patch
new file mode 100644
index 0000000..9bbbf87
--- /dev/null
+++ b/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0016-hostapd-mtk-Add-available-color-bitmap.patch
@@ -0,0 +1,337 @@
+From e7790a1bceca6b7612f29b00c429cf23f5dd9e3a 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] 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      | 66 +++++++++++++++++++++++++++
+ src/drivers/driver_nl80211.h      |  1 +
+ src/drivers/driver_nl80211_capa.c |  3 ++
+ 9 files changed, 192 insertions(+), 1 deletion(-)
+
+diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
+index 0ad8451..b0d5ded 100644
+--- a/hostapd/ctrl_iface.c
++++ b/hostapd/ctrl_iface.c
+@@ -3635,6 +3635,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,
+@@ -4202,6 +4272,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 30b3392..b6cf52e 100644
+--- a/hostapd/hostapd_cli.c
++++ b/hostapd/hostapd_cli.c
+@@ -1578,6 +1578,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[])
+ {
+@@ -1795,6 +1809,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 1a82f23..decffdd 100644
+--- a/src/ap/ap_drv_ops.c
++++ b/src/ap/ap_drv_ops.c
+@@ -1091,4 +1091,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 4406666..61c1360 100644
+--- a/src/ap/ap_drv_ops.h
++++ b/src/ap/ap_drv_ops.h
+@@ -149,6 +149,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 0999ea9..f2afb2e 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 {
+@@ -252,6 +253,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 b07aaf3..266c630 100644
+--- a/src/drivers/driver.h
++++ b/src/drivers/driver.h
+@@ -4736,6 +4736,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 6702384..c8771f7 100644
+--- a/src/drivers/driver_nl80211.c
++++ b/src/drivers/driver_nl80211.c
+@@ -12433,6 +12433,71 @@ static int nl80211_dpp_listen(void *priv, bool enable)
+ }
+ #endif /* CONFIG_DPP */
+ 
++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;
++}
+ 
+ #ifdef CONFIG_TESTING_OPTIONS
+ 
+@@ -13073,4 +13138,5 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
+ 	.start_disabled = nl80211_start_disabled,
+ 	.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 e570224..b90c8fa 100644
+--- a/src/drivers/driver_nl80211.h
++++ b/src/drivers/driver_nl80211.h
+@@ -186,6 +186,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 fcfa68b..c3c7b41 100644
+--- a/src/drivers/driver_nl80211_capa.c
++++ b/src/drivers/driver_nl80211_capa.c
+@@ -1068,6 +1068,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.39.0
+
diff --git a/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0020-hostapd-mtk-Mark-DFS-channel-as-available-for-CSA.patch b/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0020-hostapd-mtk-Mark-DFS-channel-as-available-for-CSA.patch
new file mode 100644
index 0000000..1fe5c88
--- /dev/null
+++ b/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0020-hostapd-mtk-Mark-DFS-channel-as-available-for-CSA.patch
@@ -0,0 +1,60 @@
+From 3e9500a42a41e8cd7c2d7bc20aba96e1e17161fb 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] 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 c33b7a4..9ba6992 100644
+--- a/hostapd/ctrl_iface.c
++++ b/hostapd/ctrl_iface.c
+@@ -2704,6 +2704,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 0da18e2..6231e51 100644
+--- a/hostapd/hostapd_cli.c
++++ b/hostapd/hostapd_cli.c
+@@ -1693,7 +1693,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 18bae5c..2fae590 100644
+--- a/src/ap/ctrl_iface_ap.c
++++ b/src/ap/ctrl_iface_ap.c
+@@ -938,6 +938,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
+ 
+-- 
+2.18.0
+
diff --git a/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0020-hostapd-mtk-add-11v_mbss-and-ema-support.patch b/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0020-hostapd-mtk-add-11v_mbss-and-ema-support.patch
new file mode 100644
index 0000000..8d59a0f
--- /dev/null
+++ b/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0020-hostapd-mtk-add-11v_mbss-and-ema-support.patch
@@ -0,0 +1,1175 @@
+From 8cbdb9a59e3bbe8804f909b13ce6df6e2777c3da Mon Sep 17 00:00:00 2001
+From: mtk20656 <chank.chen@mediatek.com>
+Date: Thu, 2 Mar 2023 10:51:43 +0800
+Subject: [PATCH] hostapd: mtk: add 11v_mbss and ema support for hostapd
+
+Signed-off-by: mtk20656 <chank.chen@mediatek.com>
+---
+ hostapd/config_file.c             |   9 +
+ hostapd/hostapd.conf              |  58 +++++++
+ hostapd/main.c                    |   3 +
+ src/ap/ap_config.c                |  12 ++
+ src/ap/ap_config.h                |   6 +
+ src/ap/beacon.c                   | 124 ++++++++++++--
+ src/ap/hostapd.c                  |  72 +++++++-
+ src/ap/hostapd.h                  |   7 +
+ src/ap/ieee802_11.c               | 276 +++++++++++++++++++++++++++++-
+ src/ap/ieee802_11.h               |   7 +-
+ src/ap/ieee802_11_shared.c        |  11 ++
+ src/common/ieee802_11_common.c    |   4 +
+ src/common/ieee802_11_common.h    |   3 +
+ src/common/ieee802_11_defs.h      |   5 +
+ src/drivers/driver.h              |  42 +++++
+ src/drivers/driver_nl80211.c      |  52 ++++++
+ src/drivers/driver_nl80211_capa.c |  27 +++
+ 17 files changed, 698 insertions(+), 20 deletions(-)
+
+diff --git a/hostapd/config_file.c b/hostapd/config_file.c
+index 649618b..3f26191 100644
+--- a/hostapd/config_file.c
++++ b/hostapd/config_file.c
+@@ -3663,6 +3663,15 @@ static int hostapd_config_fill(struct hostapd_config *conf,
+ 			return 1;
+ 		}
+ 		bss->unsol_bcast_probe_resp_interval = val;
++	} else if (os_strcmp(buf, "mbssid") == 0) {
++		int mbssid = atoi(pos);
++		if (mbssid < 0 || mbssid > ENHANCED_MBSSID_ENABLED) {
++			wpa_printf(MSG_ERROR,
++				   "Line %d: invalid mbssid (%d): '%s'.",
++				   line, mbssid, pos);
++			return 1;
++		}
++		conf->mbssid = mbssid;
+ 	} else if (os_strcmp(buf, "mu_onoff") == 0) {
+ 		int val = atoi(pos);
+ 		if (val < 0 || val > 15) {
+diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf
+index e3a5eb3..f926029 100644
+--- a/hostapd/hostapd.conf
++++ b/hostapd/hostapd.conf
+@@ -3123,3 +3123,61 @@ own_ip_addr=127.0.0.1
+ #bss=wlan0_1
+ #bssid=00:13:10:95:fe:0b
+ # ...
++#
++# Multiple BSSID Advertisement in 802.11ax
++# IEEE Std 802.11ax-2021 added a feature where instead of multiple interfaces
++# on a common radio transmitting individual beacons, those can form a set with
++# a common beacon is transmitted for all. The interface which is brought up
++# first is called as the transmitting profile of the MBSSID set which transmits
++# the beacons. The remaining interfaces are called as the non-transmitting
++# profiles and these are advertised inside the multiple BSSID element in the
++# beacons and probe response frames.
++# The transmitting interface is visible to all clients in the vicinity, however
++# the clients which do not support parsing of the multiple BSSID element will
++# not be able to connect to the non-transmitting interfaces.
++#
++# Enhanced Multiple BSSID Advertisements (EMA)
++# When enabled, the non-transmitting interfaces are split into multiple
++# beacons. The number of beacons required to cover all the non-transmitting
++# profiles is called as the profile periodicity.
++#
++# Refer to IEEE Std 802.11-2020 for details regarding the procedure and
++# required MAC address assignment.
++#
++# Following configuration is per radio.
++# 0 = Disabled (Default)
++# 1 = Multiple BSSID advertisements enabled.
++# 2 = Enhanced multiple BSSID advertisements enabled.
++#mbssid=0
++#
++# The transmitting interface should be added with 'interface' option while
++# the non-transmitting interfaces should be added using 'bss' option.
++# Security configuration should be added separately per interface, if required.
++#
++# Example:
++#mbssid=2
++#interface=wlan2
++#ctrl_interface=/var/run/hostapd
++#wpa_passphrase=0123456789
++#ieee80211w=2
++#sae_pwe=1
++#auth_algs=1
++#wpa=2
++#wpa_pairwise=CCMP
++#ssid=<SSID-0>
++#bridge=br-lan
++#wpa_key_mgmt=SAE
++#bssid=00:03:7f:12:84:84
++#
++#bss=wlan2-1
++#ctrl_interface=/var/run/hostapd
++#wpa_passphrase=0123456789
++#ieee80211w=2
++#sae_pwe=1
++#auth_algs=1
++#wpa=2
++#wpa_pairwise=CCMP
++#ssid=<SSID-1>
++#bridge=br-lan
++#wpa_key_mgmt=SAE
++#bssid=00:03:7f:12:84:85
+diff --git a/hostapd/main.c b/hostapd/main.c
+index 70a4b32..1b6474a 100644
+--- a/hostapd/main.c
++++ b/hostapd/main.c
+@@ -253,6 +253,9 @@ static int hostapd_driver_init(struct hostapd_iface *iface)
+ 				wpa_printf(MSG_ERROR, "set_wowlan failed");
+ 		}
+ 		os_free(triggs);
++
++		iface->mbssid_max_interfaces = capa.mbssid_max_interfaces;
++		iface->ema_max_periodicity = capa.ema_max_periodicity;
+ 	}
+ 
+ 	return 0;
+diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
+index 4e46a62..7d9d5cb 100644
+--- a/src/ap/ap_config.c
++++ b/src/ap/ap_config.c
+@@ -1462,6 +1462,12 @@ static int hostapd_config_check_bss(struct hostapd_bss_config *bss,
+ 	}
+ #endif /* CONFIG_IEEE80211BE */
+ 
++	if (full_config && bss->ignore_broadcast_ssid && conf->mbssid) {
++		wpa_printf(MSG_ERROR,
++			   "Hidden SSID is not suppored when MBSSID is enabled");
++		return -1;
++	}
++
+ 	return 0;
+ }
+ 
+@@ -1545,6 +1551,12 @@ int hostapd_config_check(struct hostapd_config *conf, int full_config)
+ 	}
+ #endif /* CONFIG_IEEE80211BE */
+ 
++	if (full_config && conf->mbssid && !conf->ieee80211ax) {
++		wpa_printf(MSG_ERROR,
++			   "Cannot enable multiple BSSID support without ieee80211ax");
++		return -1;
++	}
++
+ 	for (i = 0; i < conf->num_bss; i++) {
+ 		if (hostapd_config_check_bss(conf->bss[i], conf, full_config))
+ 			return -1;
+diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
+index 7aeb176..51476b8 100644
+--- a/src/ap/ap_config.h
++++ b/src/ap/ap_config.h
+@@ -923,6 +923,8 @@ struct hostapd_bss_config {
+ 	u8 ext_capa[EXT_CAPA_MAX_LEN];
+ 
+ 	u8 rnr;
++
++	bool xrates_supported;
+ };
+ 
+ /**
+@@ -1163,6 +1165,10 @@ struct hostapd_config {
+ 	u8 ibf_enable;
+ 	u8 dfs_detect_mode;
+ 	u8 amsdu;
++
++#define MBSSID_ENABLED          1
++#define ENHANCED_MBSSID_ENABLED 2
++	u8 mbssid;
+ };
+ 
+ enum three_wire_mode {
+diff --git a/src/ap/beacon.c b/src/ap/beacon.c
+index f3ea5c2..51db23a 100644
+--- a/src/ap/beacon.c
++++ b/src/ap/beacon.c
+@@ -462,15 +462,77 @@ static u8 * hostapd_eid_supported_op_classes(struct hostapd_data *hapd, u8 *eid)
+ }
+ 
+ 
++static int ieee802_11_build_ap_params_mbssid(struct hostapd_data *hapd,
++					     struct wpa_driver_ap_params *params,
++					     u8 **eid)
++{
++	struct hostapd_iface *iface = hapd->iface;
++	struct hostapd_data *tx_bss;
++	size_t len;
++	u8 elem_count = 0, *elem = NULL, **elem_offset = NULL, *end;
++	u8 *tailpos = *eid;
++
++	if (!iface->mbssid_max_interfaces ||
++	    iface->num_bss > iface->mbssid_max_interfaces ||
++	    (iface->conf->mbssid == ENHANCED_MBSSID_ENABLED &&
++	     !iface->ema_max_periodicity))
++		goto fail;
++
++	tx_bss = hostapd_mbssid_get_tx_bss(hapd);
++	len = hostapd_eid_mbssid_len(tx_bss, WLAN_FC_STYPE_BEACON, &elem_count,
++				     NULL, 0);
++	if (!len || (iface->conf->mbssid == ENHANCED_MBSSID_ENABLED &&
++		     elem_count > iface->ema_max_periodicity))
++		goto fail;
++
++	elem = os_zalloc(len);
++	if (!elem)
++		goto fail;
++
++	elem_offset = os_zalloc(elem_count * sizeof(u8 *));
++	if (!elem_offset)
++		goto fail;
++
++	end = hostapd_eid_mbssid(tx_bss, elem, elem + len, WLAN_FC_STYPE_BEACON,
++				 elem_count, elem_offset, NULL, 0);
++
++	params->mbssid_tx_iface = tx_bss->conf->iface;
++	params->mbssid_index = hostapd_mbssid_get_bss_index(hapd);
++	params->mbssid_elem = elem;
++	params->mbssid_elem_len = end - elem;
++	params->mbssid_elem_count = elem_count;
++	params->mbssid_elem_offset = elem_offset;
++	if (iface->conf->mbssid == ENHANCED_MBSSID_ENABLED) {
++		params->ema = true;
++		*tailpos++ = WLAN_EID_EXTENSION;
++		*tailpos++ = 3;
++		*tailpos++ = WLAN_EID_EXT_MULTIPLE_BSSID_CONFIGURATION;
++		*tailpos++ = iface->num_bss;
++		*tailpos++ = params->mbssid_elem_count;
++		*eid = tailpos;
++	}
++
++	return 0;
++
++fail:
++	os_free(elem);
++	wpa_printf(MSG_ERROR, "MBSSID: Configuration failed");
++	return -1;
++}
++
++
+ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
+ 				   const struct ieee80211_mgmt *req,
+ 				   int is_p2p, size_t *resp_len,
+-				   bool bcast_probe_resp)
++				   bool bcast_probe_resp, const u8 *known_bss,
++				   u8 known_bss_len)
+ {
+ 	struct ieee80211_mgmt *resp;
+-	u8 *pos, *epos, *csa_pos;
++	u8 *pos, *epos, *csa_pos, *ext_cap_pos;
+ 	size_t buflen;
+ 
++	hapd = hostapd_mbssid_get_tx_bss(hapd);
++
+ #define MAX_PROBERESP_LEN 768
+ 	buflen = MAX_PROBERESP_LEN;
+ #ifdef CONFIG_WPS
+@@ -517,6 +579,8 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
+ 	}
+ #endif /* CONFIG_IEEE80211BE */
+ 
++	buflen += hostapd_eid_mbssid_len(hapd, WLAN_FC_STYPE_PROBE_RESP, NULL,
++					 known_bss, known_bss_len);
+ 	buflen += hostapd_eid_rnr_len(hapd, WLAN_FC_STYPE_PROBE_RESP);
+ 	buflen += hostapd_mbo_ie_len(hapd);
+ 	buflen += hostapd_eid_owe_trans_len(hapd);
+@@ -588,8 +652,16 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
+ 	pos = hostapd_eid_supported_op_classes(hapd, pos);
+ 	pos = hostapd_eid_ht_capabilities(hapd, pos);
+ 	pos = hostapd_eid_ht_operation(hapd, pos);
++	pos = hostapd_eid_mbssid(hapd, pos, epos, WLAN_FC_STYPE_PROBE_RESP, 0,
++				 NULL, known_bss, known_bss_len);
+ 
++	ext_cap_pos = pos;
+ 	pos = hostapd_eid_ext_capab(hapd, pos);
++	if (hapd->iconf->mbssid >= MBSSID_ENABLED && !known_bss_len)
++		ext_cap_pos[12] |= 0x01; /* Probe responses always include all
++					  * non-tx profiles except when a list
++					  * of known BSSes is included in the
++					  * probe request. */
+ 
+ 	pos = hostapd_eid_time_adv(hapd, pos);
+ 	pos = hostapd_eid_time_zone(hapd, pos);
+@@ -1153,16 +1225,23 @@ void handle_probe_req(struct hostapd_data *hapd,
+ 	}
+ #endif /* CONFIG_TESTING_OPTIONS */
+ 
++	/* Do not send probe response from a non-transmitting multiple BSSID
++	 * profile unless the probe request is directed at that paticular BSS */
++	if (hapd != hostapd_mbssid_get_tx_bss(hapd) && res != EXACT_SSID_MATCH)
++		return;
++
+ 	wpa_msg_ctrl(hapd->msg_ctx, MSG_INFO, RX_PROBE_REQUEST "sa=" MACSTR
+ 		     " signal=%d", MAC2STR(mgmt->sa), ssi_signal);
+ 
+ 	if (is_6ghz_op_class(hapd->iconf->op_class) &&
+ 	    is_broadcast_ether_addr(mgmt->da))
+ 		resp = hostapd_gen_probe_resp(hapd, NULL, elems.p2p != NULL,
+-					      &resp_len, true);
++					      &resp_len, false, elems.mbssid_known_bss,
++					      elems.mbssid_known_bss_len);
+ 	else
+ 		resp = hostapd_gen_probe_resp(hapd, mgmt, elems.p2p != NULL,
+-					      &resp_len, false);
++					      &resp_len, false, elems.mbssid_known_bss,
++					      elems.mbssid_known_bss_len);
+ 	if (resp == NULL)
+ 		return;
+ 
+@@ -1184,7 +1263,8 @@ void handle_probe_req(struct hostapd_data *hapd,
+ 				hapd->cs_c_off_ecsa_proberesp;
+ 	}
+ 
+-	ret = hostapd_drv_send_mlme(hapd, resp, resp_len, noack,
++	ret = hostapd_drv_send_mlme(hostapd_mbssid_get_tx_bss(hapd), resp,
++				    resp_len, noack,
+ 				    csa_offs_len ? csa_offs : NULL,
+ 				    csa_offs_len, 0);
+ 
+@@ -1231,7 +1311,7 @@ static u8 * hostapd_probe_resp_offloads(struct hostapd_data *hapd,
+ 			   "this");
+ 
+ 	/* Generate a Probe Response template for the non-P2P case */
+-	return hostapd_gen_probe_resp(hapd, NULL, 0, resp_len, false);
++	return hostapd_gen_probe_resp(hapd, NULL, 0, resp_len, false, NULL, 0);
+ }
+ 
+ #endif /* NEED_AP_MLME */
+@@ -1250,7 +1330,7 @@ static u8 * hostapd_unsol_bcast_probe_resp(struct hostapd_data *hapd,
+ 
+ 	return hostapd_gen_probe_resp(hapd, NULL, 0,
+ 				      &params->unsol_bcast_probe_resp_tmpl_len,
+-				      true);
++				      true, NULL, 0);
+ }
+ #endif /* CONFIG_IEEE80211AX */
+ 
+@@ -1533,8 +1613,12 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
+ 	size_t resp_len = 0;
+ #ifdef NEED_AP_MLME
+ 	u16 capab_info;
+-	u8 *pos, *tailpos, *tailend, *csa_pos;
++	u8 *pos, *tailpos, *tailend, *csa_pos, *ext_cap_pos;
++#endif /* NEED_AP_MLME */
+ 
++	os_memset(params, 0, sizeof(*params));
++
++#ifdef NEED_AP_MLME
+ #define BEACON_HEAD_BUF_SIZE 256
+ #define BEACON_TAIL_BUF_SIZE 512
+ 	head = os_zalloc(BEACON_HEAD_BUF_SIZE);
+@@ -1586,6 +1670,9 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
+ 	}
+ #endif /* CONFIG_IEEE80211BE */
+ 
++	if (hapd->iconf->mbssid == ENHANCED_MBSSID_ENABLED &&
++	    hapd == hostapd_mbssid_get_tx_bss(hapd))
++		tail_len += 5; /* Multiple BSSID Configuration element */
+ 	tail_len += hostapd_eid_rnr_len(hapd, WLAN_FC_STYPE_BEACON);
+ 	tail_len += hostapd_mbo_ie_len(hapd);
+ 	tail_len += hostapd_eid_owe_trans_len(hapd);
+@@ -1671,9 +1758,23 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
+ 	tailpos = hostapd_eid_supported_op_classes(hapd, tailpos);
+ 	tailpos = hostapd_eid_ht_capabilities(hapd, tailpos);
+ 	tailpos = hostapd_eid_ht_operation(hapd, tailpos);
+-
++	ext_cap_pos = tailpos;
+ 	tailpos = hostapd_eid_ext_capab(hapd, tailpos);
+ 
++	if (hapd->iconf->mbssid && hapd->iconf->num_bss > 1) {
++		if (ieee802_11_build_ap_params_mbssid(hapd, params, &tailpos)) {
++			os_free(head);
++			os_free(tail);
++			wpa_printf(MSG_ERROR, "Failed to set beacon data");
++			return -1;
++		} else if (hapd->iconf->mbssid == MBSSID_ENABLED ||
++			   (hapd->iconf->mbssid == ENHANCED_MBSSID_ENABLED &&
++			   params->mbssid_elem_count == 1)) {
++			/* Set the extended capability bit for "complete list
++			 * of non-tx profiles" */
++			ext_cap_pos[12] |= 0x01;
++		}
++	}
+ 	/*
+ 	 * TODO: Time Advertisement element should only be included in some
+ 	 * DTIM Beacon frames.
+@@ -1794,7 +1895,6 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
+ 	resp = hostapd_probe_resp_offloads(hapd, &resp_len);
+ #endif /* NEED_AP_MLME */
+ 
+-	os_memset(params, 0, sizeof(*params));
+ 	params->head = (u8 *) head;
+ 	params->head_len = head_len;
+ 	params->tail = tail;
+@@ -1897,6 +1997,10 @@ void ieee802_11_free_ap_params(struct wpa_driver_ap_params *params)
+ 	params->head = NULL;
+ 	os_free(params->proberesp);
+ 	params->proberesp = NULL;
++	os_free(params->mbssid_elem);
++	params->mbssid_elem = NULL;
++	os_free(params->mbssid_elem_offset);
++	params->mbssid_elem_offset = NULL;
+ #ifdef CONFIG_FILS
+ 	os_free(params->fd_frame_tmpl);
+ 	params->fd_frame_tmpl = NULL;
+diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
+index 42e8ed7..82cc155 100644
+--- a/src/ap/hostapd.c
++++ b/src/ap/hostapd.c
+@@ -91,6 +91,29 @@ int hostapd_for_each_interface(struct hapd_interfaces *interfaces,
+ }
+ 
+ 
++struct hostapd_data * hostapd_mbssid_get_tx_bss(struct hostapd_data *hapd)
++{
++	if (hapd->iconf->mbssid)
++		return hapd->iface->bss[0];
++
++	return hapd;
++}
++
++
++int hostapd_mbssid_get_bss_index(struct hostapd_data *hapd)
++{
++	if (hapd->iconf->mbssid) {
++		size_t i;
++
++		for (i = 1; i < hapd->iface->num_bss; i++)
++			if (hapd->iface->bss[i] == hapd)
++				return i;
++	}
++
++	return 0;
++}
++
++
+ void hostapd_reconfig_encryption(struct hostapd_data *hapd)
+ {
+ 	if (hapd->wpa_auth)
+@@ -1179,19 +1202,37 @@ static int db_table_create_radius_attributes(sqlite3 *db)
+ 
+ #endif /* CONFIG_NO_RADIUS */
+ 
++static int hostapd_start_beacon(struct hostapd_data *hapd)
++{
++	struct hostapd_bss_config *conf = hapd->conf;
++
++	if (!conf->start_disabled && ieee802_11_set_beacon(hapd) < 0)
++		return -1;
++
++	if (hapd->driver && hapd->driver->set_operstate)
++		hapd->driver->set_operstate(hapd->drv_priv, 1);
++
++	return 0;
++}
+ 
+ /**
+  * hostapd_setup_bss - Per-BSS setup (initialization)
+  * @hapd: Pointer to BSS data
+  * @first: Whether this BSS is the first BSS of an interface; -1 = not first,
+  *	but interface may exist
++ * @start_beacon: Whether beacons should be configured and transmission started
++ *	at this time. This is used when MBSSID IE is enabled where the
++ *	information regarding all BSSes should be retrieved before configuring
++ *	the beacons. The calling functions are responsible to configure the
++ *	beacon explicitly if this is set to 'false'.
+  *
+  * This function is used to initialize all per-BSS data structures and
+  * resources. This gets called in a loop for each BSS when an interface is
+  * initialized. Most of the modules that are initialized here will be
+  * deinitialized in hostapd_cleanup().
+  */
+-static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
++static int hostapd_setup_bss(struct hostapd_data *hapd, int first,
++			     bool start_beacon)
+ {
+ 	struct hostapd_bss_config *conf = hapd->conf;
+ 	u8 ssid[SSID_MAX_LEN + 1];
+@@ -1464,9 +1505,6 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
+ 		return -1;
+ 	}
+ 
+-	if (!conf->start_disabled && ieee802_11_set_beacon(hapd) < 0)
+-		return -1;
+-
+ 	if (flush_old_stations && !conf->start_disabled &&
+ 	    conf->broadcast_deauth) {
+ 		u8 addr[ETH_ALEN];
+@@ -1485,8 +1523,8 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
+ 	if (hapd->wpa_auth && wpa_init_keys(hapd->wpa_auth) < 0)
+ 		return -1;
+ 
+-	if (hapd->driver && hapd->driver->set_operstate)
+-		hapd->driver->set_operstate(hapd->drv_priv, 1);
++	if (start_beacon)
++		return hostapd_start_beacon(hapd);
+ 
+ 	hostapd_ubus_add_bss(hapd);
+ 
+@@ -2214,7 +2252,7 @@ static int hostapd_setup_interface_complete_sync(struct hostapd_iface *iface,
+ 		hapd = iface->bss[j];
+ 		if (j)
+ 			os_memcpy(hapd->own_addr, prev_addr, ETH_ALEN);
+-		if (hostapd_setup_bss(hapd, j == 0)) {
++		if (hostapd_setup_bss(hapd, j == 0, !iface->conf->mbssid)) {
+ 			for (;;) {
+ 				hapd = iface->bss[j];
+ 				hostapd_bss_deinit_no_free(hapd);
+@@ -2228,6 +2266,24 @@ static int hostapd_setup_interface_complete_sync(struct hostapd_iface *iface,
+ 		if (is_zero_ether_addr(hapd->conf->bssid))
+ 			prev_addr = hapd->own_addr;
+ 	}
++
++	if (hapd->iconf->mbssid) {
++		for (j = 0; j < iface->num_bss; j++) {
++			hapd = iface->bss[j];
++			if (hostapd_start_beacon(hapd)) {
++				for (;;) {
++					hapd = iface->bss[j];
++					hostapd_bss_deinit_no_free(hapd);
++					hostapd_free_hapd_data(hapd);
++					if (j == 0)
++						break;
++					j--;
++				}
++				goto fail;
++			}
++		}
++	}
++
+ 	hapd = iface->bss[0];
+ 
+ 	hostapd_tx_queue_params(iface);
+@@ -3130,7 +3186,7 @@ int hostapd_add_iface(struct hapd_interfaces *interfaces, char *buf)
+ 
+ 			if (start_ctrl_iface_bss(hapd) < 0 ||
+ 			    (hapd_iface->state == HAPD_IFACE_ENABLED &&
+-			     hostapd_setup_bss(hapd, -1))) {
++			     hostapd_setup_bss(hapd, -1, true))) {
+ 				hostapd_cleanup(hapd);
+ 				hapd_iface->bss[hapd_iface->num_bss - 1] = NULL;
+ 				hapd_iface->conf->num_bss--;
+diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h
+index 56d96a5..093c28a 100644
+--- a/src/ap/hostapd.h
++++ b/src/ap/hostapd.h
+@@ -660,6 +660,11 @@ struct hostapd_iface {
+ 	/* Previous WMM element information */
+ 	struct hostapd_wmm_ac_params prev_wmm[WMM_AC_NUM];
+ 
++	/* Maximum number of interfaces supported for MBSSID advertisements */
++	u8 mbssid_max_interfaces;
++	/* Maximum profile periodicity for enhanced MBSSID advertisements */
++	u8 ema_max_periodicity;
++
+ 	int (*enable_iface_cb)(struct hostapd_iface *iface);
+ 	int (*disable_iface_cb)(struct hostapd_iface *iface);
+ };
+@@ -762,5 +767,7 @@ void fst_hostapd_fill_iface_obj(struct hostapd_data *hapd,
+ #endif /* CONFIG_FST */
+ 
+ int hostapd_set_acl(struct hostapd_data *hapd);
++struct hostapd_data * hostapd_mbssid_get_tx_bss(struct hostapd_data *hapd);
++int hostapd_mbssid_get_bss_index(struct hostapd_data *hapd);
+ 
+ #endif /* HOSTAPD_H */
+diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
+index 098793e..30bfa30 100644
+--- a/src/ap/ieee802_11.c
++++ b/src/ap/ieee802_11.c
+@@ -165,6 +165,7 @@ u8 * hostapd_eid_ext_supp_rates(struct hostapd_data *hapd, u8 *eid)
+ 	int i, num, count;
+ 	int h2e_required;
+ 
++	hapd->conf->xrates_supported = 0;
+ 	if (hapd->iface->current_rates == NULL)
+ 		return eid;
+ 
+@@ -214,6 +215,7 @@ u8 * hostapd_eid_ext_supp_rates(struct hostapd_data *hapd, u8 *eid)
+ 			*pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_SAE_H2E_ONLY;
+ 	}
+ 
++	hapd->conf->xrates_supported = 1;
+ 	return pos;
+ }
+ 
+@@ -3979,6 +3981,23 @@ static void handle_auth(struct hostapd_data *hapd,
+ }
+ 
+ 
++static u8 hostapd_max_bssid_indicator(struct hostapd_data *hapd)
++{
++	size_t num_bss_nontx;
++	u8 max_bssid_ind = 0;
++
++	if (!hapd->iconf->mbssid || hapd->iface->num_bss <= 1)
++		return 0;
++
++	num_bss_nontx = hapd->iface->num_bss - 1;
++	while (num_bss_nontx > 0) {
++		max_bssid_ind++;
++		num_bss_nontx >>= 1;
++	}
++	return max_bssid_ind;
++}
++
++
+ int hostapd_get_aid(struct hostapd_data *hapd, struct sta_info *sta)
+ {
+ 	int i, j = 32, aid;
+@@ -4004,7 +4023,10 @@ int hostapd_get_aid(struct hostapd_data *hapd, struct sta_info *sta)
+ 	}
+ 	if (j == 32)
+ 		return -1;
+-	aid = i * 32 + j + 1;
++	aid = i * 32 + j;
++
++	aid += (1 << hostapd_max_bssid_indicator(hapd));
++
+ 	if (aid > 2007)
+ 		return -1;
+ 
+@@ -7579,4 +7601,256 @@ u8 * hostapd_eid_rnr(struct hostapd_data *hapd, u8 *eid, u32 type)
+ 	return eid;
+ }
+ 
++
++static size_t hostapd_eid_mbssid_elem_len(struct hostapd_data *hapd,
++					  u32 frame_type, size_t *bss_index,
++					  const u8 *known_bss,
++					  size_t known_bss_len)
++{
++	struct hostapd_data *tx_bss = hostapd_mbssid_get_tx_bss(hapd);
++	size_t len = 3, i;
++
++	for (i = *bss_index; i < hapd->iface->num_bss; i++) {
++		struct hostapd_data *bss = hapd->iface->bss[i];
++		const u8 *auth, *rsn = NULL, *rsnx = NULL;
++		size_t nontx_profile_len, auth_len;
++		u8 ie_count = 0;
++
++		if (known_bss && (known_bss_len > (i / 8))) {
++			known_bss = &known_bss[i / 8];
++			if (*known_bss & (u8)(BIT(i % 8)))
++				continue;
++		}
++
++		if (!bss || !bss->conf || !bss->started)
++			continue;
++
++		/*
++		 * Sublement ID: 1 byte
++		 * Length: 1 byte
++		 * Nontransmitted capabilities: 4 bytes
++		 * SSID element: 2 + variable
++		 * Multiple BSSID Index Element: 3 bytes (+2 bytes in beacons)
++		 * Fixed length = 1 + 1 + 4 + 2 + 3 = 11
++		 */
++		nontx_profile_len = 11 + bss->conf->ssid.ssid_len;
++
++		if (frame_type == WLAN_FC_STYPE_BEACON)
++			nontx_profile_len += 2;
++
++		auth = wpa_auth_get_wpa_ie(bss->wpa_auth, &auth_len);
++		if (auth) {
++			rsn = get_ie(auth, auth_len, WLAN_EID_RSN);
++			if (rsn)
++				nontx_profile_len += (2 + rsn[1]);
++
++			rsnx = get_ie(auth, auth_len, WLAN_EID_RSNX);
++			if (rsnx)
++				nontx_profile_len += (2 + rsnx[1]);
++		}
++		if (!rsn && hostapd_wpa_ie(tx_bss, WLAN_EID_RSN))
++			ie_count++;
++		if (!rsnx && hostapd_wpa_ie(tx_bss, WLAN_EID_RSNX))
++			ie_count++;
++		if (bss->conf->xrates_supported)
++			nontx_profile_len += 8;
++		else if (hapd->conf->xrates_supported)
++			ie_count++;
++		if (ie_count)
++			nontx_profile_len += (4 + ie_count);
++
++		if ((len + nontx_profile_len) > 255)
++			goto mbssid_too_big;
++
++		len += nontx_profile_len;
++	}
++
++mbssid_too_big:
++	*bss_index = i;
++	return len;
++}
++
++
++size_t hostapd_eid_mbssid_len(struct hostapd_data *hapd, u32 frame_type,
++			      u8 *elem_count, const u8 *known_bss,
++			      size_t known_bss_len)
++{
++	size_t len = 0, bss_index = 1;
++
++	if (!hapd->iconf->mbssid || hapd->iface->num_bss <= 1 ||
++	    (frame_type != WLAN_FC_STYPE_BEACON &&
++	     frame_type != WLAN_FC_STYPE_PROBE_RESP))
++		return 0;
++
++	if (frame_type == WLAN_FC_STYPE_BEACON) {
++		if (!elem_count) {
++			wpa_printf(MSG_ERROR,
++				   "MBSSID: Insufficient data for beacons");
++			return 0;
++		}
++		*elem_count = 0;
++	}
++
++	while (bss_index < hapd->iface->num_bss) {
++		len += hostapd_eid_mbssid_elem_len(hapd, frame_type,
++						   &bss_index, known_bss,
++						   known_bss_len);
++
++		if (frame_type == WLAN_FC_STYPE_BEACON)
++			*elem_count += 1;
++	}
++	return len;
++}
++
++
++static u8 * hostapd_eid_mbssid_elem(struct hostapd_data *hapd, u8 *eid, u8 *end,
++				    u32 frame_type, u8 max_bssid_indicator,
++				    size_t *bss_index, u8 elem_count,
++				    const u8 *known_bss, size_t known_bss_len)
++{
++	struct hostapd_data *tx_bss = hostapd_mbssid_get_tx_bss(hapd);
++	size_t i;
++	u8 *eid_len_offset, *max_bssid_indicator_offset;
++
++	*eid++ = WLAN_EID_MULTIPLE_BSSID;
++	eid_len_offset = eid++;
++	max_bssid_indicator_offset = eid++;
++
++	for (i = *bss_index; i < hapd->iface->num_bss; i++) {
++		struct hostapd_data *bss = hapd->iface->bss[i];
++		struct hostapd_bss_config *conf;
++		u8 *eid_len_pos, *nontx_bss_start = eid;
++		const u8 *auth, *rsn = NULL, *rsnx = NULL;
++		u8 ie_count = 0, non_inherit_ie[3];
++		size_t auth_len = 0;
++		u16 capab_info;
++
++		if (known_bss && (known_bss_len > (i / 8))) {
++			known_bss = &known_bss[i / 8];
++			if (*known_bss & (u8)(BIT(i % 8)))
++				continue;
++		}
++
++		if (!bss || !bss->conf || !bss->started)
++			continue;
++		conf = bss->conf;
++
++		*eid++ = WLAN_EID_SUBELEMENT_NONTRANSMITTED_BSSID_PROFILE;
++		eid_len_pos = eid++;
++
++		*eid++ = WLAN_EID_NONTRANSMITTED_BSSID_CAPA;
++		*eid++ = sizeof(capab_info);
++		capab_info = host_to_le16(hostapd_own_capab_info(bss));
++		os_memcpy(eid, (const void *)&capab_info, sizeof(capab_info));
++		eid += sizeof(capab_info);
++
++		*eid++ = WLAN_EID_SSID;
++		*eid++ = conf->ssid.ssid_len;
++		os_memcpy(eid, conf->ssid.ssid, conf->ssid.ssid_len);
++		eid += conf->ssid.ssid_len;
++
++		*eid++ = WLAN_EID_MULTIPLE_BSSID_INDEX;
++		if (frame_type == WLAN_FC_STYPE_BEACON) {
++			*eid++ = 3;
++			*eid++ = i;
++			if (hapd->iconf->mbssid == ENHANCED_MBSSID_ENABLED &&
++			    (conf->dtim_period % elem_count))
++				conf->dtim_period = elem_count;
++			*eid++ = conf->dtim_period;
++			*eid++ = 0xFF;
++		} else {
++			*eid++ = 1;
++			*eid++ = i;
++		}
++
++		auth = wpa_auth_get_wpa_ie(bss->wpa_auth, &auth_len);
++		if (auth) {
++			rsn = get_ie(auth, auth_len, WLAN_EID_RSN);
++			if (rsn) {
++				os_memcpy(eid, rsn, 2 + rsn[1]);
++				eid += (2 + rsn[1]);
++			}
++
++			rsnx = get_ie(auth, auth_len, WLAN_EID_RSNX);
++			if (rsnx) {
++				os_memcpy(eid, rsnx, 2 + rsnx[1]);
++				eid += (2 + rsnx[1]);
++			}
++		}
++		if (!rsn && hostapd_wpa_ie(tx_bss, WLAN_EID_RSN)) {
++			non_inherit_ie[ie_count] = WLAN_EID_RSN;
++			ie_count++;
++		}
++		if (!rsnx && hostapd_wpa_ie(tx_bss, WLAN_EID_RSNX)) {
++			non_inherit_ie[ie_count] = WLAN_EID_RSNX;
++			ie_count++;
++		}
++		if (hapd->conf->xrates_supported &&
++		    !bss->conf->xrates_supported) {
++			non_inherit_ie[ie_count] = WLAN_EID_EXT_SUPP_RATES;
++			ie_count++;
++		}
++		if (ie_count) {
++			*eid++ = WLAN_EID_EXTENSION;
++			*eid++ = 2 + ie_count;
++			*eid++ = WLAN_EID_EXT_NON_INHERITANCE;
++			*eid++ = ie_count;
++			os_memcpy(eid, non_inherit_ie, ie_count);
++			eid += ie_count;
++		}
++
++		*eid_len_pos = (eid - eid_len_pos) - 1;
++
++		if (((eid - eid_len_offset) - 1) > 255) {
++			eid = nontx_bss_start;
++			goto mbssid_too_big;
++		}
++	}
++
++mbssid_too_big:
++	*bss_index = i;
++	*max_bssid_indicator_offset = max_bssid_indicator;
++	if (*max_bssid_indicator_offset < 1)
++		*max_bssid_indicator_offset = 1;
++	*eid_len_offset = (eid - eid_len_offset) - 1;
++	return eid;
++}
++
++
++u8 * hostapd_eid_mbssid(struct hostapd_data *hapd, u8 *eid, u8 *end,
++			u32 frame_type, u8 elem_count, u8 **elem_offset,
++			const u8 *known_bss, size_t known_bss_len)
++{
++	size_t bss_index = 1;
++	u8 elem_index = 0;
++
++	if (!hapd->iconf->mbssid || hapd->iface->num_bss <= 1 ||
++	    (frame_type != WLAN_FC_STYPE_BEACON &&
++	     frame_type != WLAN_FC_STYPE_PROBE_RESP))
++		return eid;
++
++	if (frame_type == WLAN_FC_STYPE_BEACON && !elem_offset) {
++		wpa_printf(MSG_ERROR, "MBSSID: Insufficient data for beacons");
++		return eid;
++	}
++
++	while (bss_index < hapd->iface->num_bss) {
++		if (frame_type == WLAN_FC_STYPE_BEACON) {
++			if (elem_index == elem_count) {
++				wpa_printf(MSG_WARNING,
++					   "MBSSID: More number of elements than provided array");
++				break;
++			}
++
++			elem_offset[elem_index] = eid;
++			elem_index = elem_index + 1;
++		}
++		eid = hostapd_eid_mbssid_elem(hapd, eid, end, frame_type,
++					      hostapd_max_bssid_indicator(hapd),
++					      &bss_index, elem_count,
++					      known_bss, known_bss_len);
++	}
++	return eid;
++}
++
+ #endif /* CONFIG_NATIVE_WINDOWS */
+diff --git a/src/ap/ieee802_11.h b/src/ap/ieee802_11.h
+index fa1f47b..bb454bb 100644
+--- a/src/ap/ieee802_11.h
++++ b/src/ap/ieee802_11.h
+@@ -214,5 +214,10 @@ u16 copy_sta_eht_capab(struct hostapd_data *hapd, struct sta_info *sta,
+ 		       enum ieee80211_op_mode opmode,
+ 		       const u8 *he_capab, size_t he_capab_len,
+ 		       const u8 *eht_capab, size_t eht_capab_len);
+-
++size_t hostapd_eid_mbssid_len(struct hostapd_data *hapd, u32 frame_type,
++			      u8 *elem_count, const u8 *known_bss,
++			      size_t known_bss_len);
++u8 * hostapd_eid_mbssid(struct hostapd_data *hapd, u8 *eid, u8 *end,
++			u32 frame_type, u8 elem_count, u8 **elem_offset,
++			const u8 *known_bss, size_t known_bss_len);
+ #endif /* IEEE802_11_H */
+diff --git a/src/ap/ieee802_11_shared.c b/src/ap/ieee802_11_shared.c
+index 4f85d78..7f5b475 100644
+--- a/src/ap/ieee802_11_shared.c
++++ b/src/ap/ieee802_11_shared.c
+@@ -364,6 +364,8 @@ static void hostapd_ext_capab_byte(struct hostapd_data *hapd, u8 *pos, int idx)
+ 			*pos |= 0x02; /* Bit 17 - WNM-Sleep Mode */
+ 		if (hapd->conf->bss_transition)
+ 			*pos |= 0x08; /* Bit 19 - BSS Transition */
++		if (hapd->iconf->mbssid)
++			*pos |= 0x40; /* Bit 22 - Multiple BSSID */
+ 		break;
+ 	case 3: /* Bits 24-31 */
+ #ifdef CONFIG_WNM_AP
+@@ -436,6 +438,8 @@ static void hostapd_ext_capab_byte(struct hostapd_data *hapd, u8 *pos, int idx)
+ 		    (hapd->iface->drv_flags &
+ 		     WPA_DRIVER_FLAGS_BEACON_PROTECTION))
+ 			*pos |= 0x10; /* Bit 84 - Beacon Protection Enabled */
++		if (hapd->iconf->mbssid == ENHANCED_MBSSID_ENABLED)
++			*pos |= 0x08; /* Bit 83 - Enhanced multiple BSSID */
+ 		break;
+ 	case 11: /* Bits 88-95 */
+ #ifdef CONFIG_SAE_PK
+@@ -471,6 +475,13 @@ u8 * hostapd_eid_ext_capab(struct hostapd_data *hapd, u8 *eid)
+ 			*pos &= ~hapd->conf->ext_capa_mask[i];
+ 			*pos |= hapd->conf->ext_capa[i];
+ 		}
++
++		/* Clear bits 83 and 22 if EMA and MBSSID are not enabled
++		 * otherwise association fails with some clients */
++		if (i == 10 && hapd->iconf->mbssid < ENHANCED_MBSSID_ENABLED)
++			*pos &= ~0x08;
++		if (i == 2 && !hapd->iconf->mbssid)
++			*pos &= ~0x40;
+ 	}
+ 
+ 	while (len > 0 && eid[1 + len] == 0) {
+diff --git a/src/common/ieee802_11_common.c b/src/common/ieee802_11_common.c
+index c8ee90c..2fab7c3 100644
+--- a/src/common/ieee802_11_common.c
++++ b/src/common/ieee802_11_common.c
+@@ -315,6 +315,10 @@ static int ieee802_11_parse_extension(const u8 *pos, size_t elen,
+ 		elems->eht_operation = pos;
+ 		elems->eht_operation_len = elen;
+ 		break;
++	case WLAN_EID_EXT_KNOWN_BSSID:
++		elems->mbssid_known_bss = pos;
++		elems->mbssid_known_bss_len = elen;
++		break;
+ 	default:
+ 		if (show_errors) {
+ 			wpa_printf(MSG_MSGDUMP,
+diff --git a/src/common/ieee802_11_common.h b/src/common/ieee802_11_common.h
+index 94e1d7b..1e4e27d 100644
+--- a/src/common/ieee802_11_common.h
++++ b/src/common/ieee802_11_common.h
+@@ -119,6 +119,7 @@ struct ieee802_11_elems {
+ 	const u8 *pasn_params;
+ 	const u8 *eht_capabilities;
+ 	const u8 *eht_operation;
++	const u8 *mbssid_known_bss;
+ 
+ 	u8 ssid_len;
+ 	u8 supp_rates_len;
+@@ -176,6 +177,8 @@ struct ieee802_11_elems {
+ 	u8 eht_capabilities_len;
+ 	u8 eht_operation_len;
+ 
++	u8 mbssid_known_bss_len;
++
+ 	struct mb_ies_info mb_ies;
+ 	struct frag_ies_info frag_ies;
+ };
+diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h
+index 62088bd..0bbbca9 100644
+--- a/src/common/ieee802_11_defs.h
++++ b/src/common/ieee802_11_defs.h
+@@ -481,6 +481,9 @@
+ #define WLAN_EID_EXT_SPATIAL_REUSE 39
+ #define WLAN_EID_EXT_COLOR_CHANGE_ANNOUNCEMENT 42
+ #define WLAN_EID_EXT_OCV_OCI 54
++#define WLAN_EID_EXT_MULTIPLE_BSSID_CONFIGURATION 55
++#define WLAN_EID_EXT_NON_INHERITANCE 56
++#define WLAN_EID_EXT_KNOWN_BSSID 57
+ #define WLAN_EID_EXT_SHORT_SSID_LIST 58
+ #define WLAN_EID_EXT_HE_6GHZ_BAND_CAP 59
+ #define WLAN_EID_EXT_EDMG_CAPABILITIES 61
+@@ -497,6 +500,8 @@
+ #define WLAN_EID_EXT_MULTI_LINK_TRAFFIC_INDICATION 110
+ #define WLAN_EID_EXT_AKM_SUITE_SELECTOR 114
+ 
++#define WLAN_EID_SUBELEMENT_NONTRANSMITTED_BSSID_PROFILE 0
++
+ /* Extended Capabilities field */
+ #define WLAN_EXT_CAPAB_20_40_COEX 0
+ #define WLAN_EXT_CAPAB_GLK 1
+diff --git a/src/drivers/driver.h b/src/drivers/driver.h
+index 82daef0..36f465c 100644
+--- a/src/drivers/driver.h
++++ b/src/drivers/driver.h
+@@ -1633,6 +1633,43 @@ struct wpa_driver_ap_params {
+ 	 * ibf_enable=<val>
+ 	 */
+ 	u8 ibf_enable;
++
++	/**
++	 * mbssid_tx_iface - Transmitting interface of the MBSSID set
++	 */
++	const char *mbssid_tx_iface;
++
++	/**
++	 * mbssid_index - The index of this BSS in the MBSSID set
++	 */
++	unsigned int mbssid_index;
++
++	/**
++	 * mbssid_elem - Buffer containing all MBSSID elements
++	 */
++	u8 *mbssid_elem;
++
++	/**
++	 * mbssid_elem_len - Total length of all MBSSID elements
++	 */
++	size_t mbssid_elem_len;
++
++	/**
++	 * mbssid_elem_count - The number of MBSSID elements
++	 */
++	u8 mbssid_elem_count;
++
++	/**
++	 * mbssid_elem_offset - Offsets to elements in mbssid_elem.
++	 * Kernel will use these offsets to generate multiple BSSID beacons.
++	 */
++	u8 **mbssid_elem_offset;
++
++	/**
++	 * ema - Enhanced MBSSID advertisements support.
++	 */
++	bool ema;
++
+ };
+ 
+ struct wpa_driver_mesh_bss_params {
+@@ -2197,6 +2234,11 @@ struct wpa_driver_capa {
+ 
+ 	/* Maximum number of supported CSA counters */
+ 	u16 max_csa_counters;
++
++	/* Maximum number of interfaces supported for MBSSID advertisements */
++	u8 mbssid_max_interfaces;
++	/* Maximum profile periodicity for enhanced MBSSID advertisements */
++	u8 ema_max_periodicity;
+ };
+ 
+ 
+diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
+index 6c65901..3753409 100644
+--- a/src/drivers/driver_nl80211.c
++++ b/src/drivers/driver_nl80211.c
+@@ -4540,6 +4540,55 @@ static int nl80211_unsol_bcast_probe_resp(struct i802_bss *bss,
+ 	nla_nest_end(msg, attr);
+ 	return 0;
+ }
++
++
++static int nl80211_mbssid(struct nl_msg *msg,
++			 struct wpa_driver_ap_params *params)
++{
++	struct nlattr *config, *elems;
++	int ifidx;
++
++	if (!params->mbssid_tx_iface)
++		return 0;
++
++	config = nla_nest_start(msg, NL80211_ATTR_MBSSID_CONFIG);
++	if (!config)
++		return -1;
++
++	nla_put_u8(msg, NL80211_MBSSID_CONFIG_ATTR_INDEX, params->mbssid_index);
++	if (params->mbssid_tx_iface) {
++		ifidx = if_nametoindex(params->mbssid_tx_iface);
++		if (ifidx <= 0)
++			return -1;
++		nla_put_u32(msg,
++			    NL80211_MBSSID_CONFIG_ATTR_TX_IFINDEX,
++			    ifidx);
++	}
++
++	if (params->ema)
++		nla_put_flag(msg, NL80211_MBSSID_CONFIG_ATTR_EMA);
++
++	nla_nest_end(msg, config);
++
++	if (params->mbssid_elem_count && params->mbssid_elem_len &&
++	    params->mbssid_elem_offset && *params->mbssid_elem_offset) {
++		u8 i, **offs = params->mbssid_elem_offset;
++
++		elems = nla_nest_start(msg, NL80211_ATTR_MBSSID_ELEMS);
++		if (!elems)
++			return -1;
++
++		for (i = 0; i < params->mbssid_elem_count - 1; i++)
++			nla_put(msg, i + 1, offs[i + 1] - offs[i], offs[i]);
++
++		nla_put(msg, i + 1,
++			*offs + params->mbssid_elem_len - offs[i],
++			offs[i]);
++
++		nla_nest_end(msg, elems);
++	}
++	return 0;
++}
+ #endif /* CONFIG_IEEE80211AX */
+ 
+ 
+@@ -4838,6 +4887,9 @@ static int wpa_driver_nl80211_set_ap(void *priv,
+ 	if (params->unsol_bcast_probe_resp_interval &&
+ 	    nl80211_unsol_bcast_probe_resp(bss, msg, params) < 0)
+ 		goto fail;
++
++	if (nl80211_mbssid(msg, params) < 0)
++		goto fail;
+ #endif /* CONFIG_IEEE80211AX */
+ 
+ #ifdef CONFIG_SAE
+diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c
+index 06a52db..d8078bc 100644
+--- a/src/drivers/driver_nl80211_capa.c
++++ b/src/drivers/driver_nl80211_capa.c
+@@ -857,6 +857,30 @@ err:
+ }
+ 
+ 
++static void wiphy_info_mbssid(struct wpa_driver_capa *cap, struct nlattr *attr)
++{
++	struct nlattr *config[NL80211_MBSSID_CONFIG_ATTR_MAX + 1];
++
++	if (nla_parse_nested(config, NL80211_MBSSID_CONFIG_ATTR_MAX, attr,
++			     NULL))
++		return;
++
++	if (!config[NL80211_MBSSID_CONFIG_ATTR_MAX_INTERFACES])
++		return;
++
++	cap->mbssid_max_interfaces =
++		nla_get_u8(config[NL80211_MBSSID_CONFIG_ATTR_MAX_INTERFACES]);
++
++	if (config[NL80211_MBSSID_CONFIG_ATTR_MAX_EMA_PROFILE_PERIODICITY])
++		cap->ema_max_periodicity =
++		nla_get_u8(config[NL80211_MBSSID_CONFIG_ATTR_MAX_EMA_PROFILE_PERIODICITY]);
++
++	wpa_printf(MSG_DEBUG,
++		   "multiple_bssid: max interfaces %u, max profile periodicity %u\n",
++		   cap->mbssid_max_interfaces, cap->ema_max_periodicity);
++}
++
++
+ static int wiphy_info_handler(struct nl_msg *msg, void *arg)
+ {
+ 	struct nlattr *tb[NL80211_ATTR_MAX + 1];
+@@ -1106,6 +1130,9 @@ static int wiphy_info_handler(struct nl_msg *msg, void *arg)
+ 	if (tb[NL80211_ATTR_WIPHY_SELF_MANAGED_REG])
+ 		capa->flags |= WPA_DRIVER_FLAGS_SELF_MANAGED_REGULATORY;
+ 
++	if (tb[NL80211_ATTR_MBSSID_CONFIG])
++		wiphy_info_mbssid(capa, tb[NL80211_ATTR_MBSSID_CONFIG]);
++
+ 	return NL_SKIP;
+ }
+ 
+-- 
+2.18.0
+
diff --git a/recipes-wifi/hostapd/files/patches-2.10.3/patches.inc b/recipes-wifi/hostapd/files/patches-2.10.3/patches.inc
index 78d5240..5e6bf88 100644
--- a/recipes-wifi/hostapd/files/patches-2.10.3/patches.inc
+++ b/recipes-wifi/hostapd/files/patches-2.10.3/patches.inc
@@ -78,8 +78,11 @@
     file://mtk-0014-hostapd-mtk-Add-the-broadcast-destination-address-of.patch \
     file://mtk-0015-hostapd-mtk-Add-vendor-command-attribute-for-RTS-BW-.patch \
     file://mtk-0016-hostapd-mtk-6G-band-does-not-require-DFS.patch \
+    file://mtk-0016-hostapd-mtk-Add-available-color-bitmap.patch \
     file://mtk-0017-hostapd-mtk-Fix-sending-wrong-VHT-operation-IE-in-CS.patch \
     file://mtk-0018-hostapd-mtk-Add-sta-assisted-DFS-state-update-mechan.patch \
     file://mtk-0019-hostapd-mtk-Fix-auto-ht-issue-when-switching-to-DFS-.patch \
+    file://mtk-0020-hostapd-mtk-Mark-DFS-channel-as-available-for-CSA.patch \
+    file://mtk-0020-hostapd-mtk-add-11v_mbss-and-ema-support.patch \
     file://mtk-0100-hostapd-mtk-update-eht-operation-elem.patch \
     "
diff --git a/recipes-wifi/hostapd/files/patches/mtk-0010-hostapd-mtk-Add-DFS-detection-mode.patch b/recipes-wifi/hostapd/files/patches/mtk-0010-hostapd-mtk-Add-DFS-detection-mode.patch
index 2ceb639..7ec986a 100644
--- a/recipes-wifi/hostapd/files/patches/mtk-0010-hostapd-mtk-Add-DFS-detection-mode.patch
+++ b/recipes-wifi/hostapd/files/patches/mtk-0010-hostapd-mtk-Add-DFS-detection-mode.patch
@@ -63,7 +63,7 @@
  					      char *buf, char *reply,
  					      int reply_size,
 @@ -4081,6 +4101,9 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
- 		reply_len = hostapd_ctrl_iface_get_hemu(hapd, reply, reply_size);
+ 		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) {
diff --git a/recipes-wifi/hostapd/files/patches/mtk-0016-hostapd-mtk-Add-available-color-bitmap.patch b/recipes-wifi/hostapd/files/patches/mtk-0016-hostapd-mtk-Add-available-color-bitmap.patch
new file mode 100644
index 0000000..9bbbf87
--- /dev/null
+++ b/recipes-wifi/hostapd/files/patches/mtk-0016-hostapd-mtk-Add-available-color-bitmap.patch
@@ -0,0 +1,337 @@
+From e7790a1bceca6b7612f29b00c429cf23f5dd9e3a 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] 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      | 66 +++++++++++++++++++++++++++
+ src/drivers/driver_nl80211.h      |  1 +
+ src/drivers/driver_nl80211_capa.c |  3 ++
+ 9 files changed, 192 insertions(+), 1 deletion(-)
+
+diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
+index 0ad8451..b0d5ded 100644
+--- a/hostapd/ctrl_iface.c
++++ b/hostapd/ctrl_iface.c
+@@ -3635,6 +3635,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,
+@@ -4202,6 +4272,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 30b3392..b6cf52e 100644
+--- a/hostapd/hostapd_cli.c
++++ b/hostapd/hostapd_cli.c
+@@ -1578,6 +1578,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[])
+ {
+@@ -1795,6 +1809,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 1a82f23..decffdd 100644
+--- a/src/ap/ap_drv_ops.c
++++ b/src/ap/ap_drv_ops.c
+@@ -1091,4 +1091,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 4406666..61c1360 100644
+--- a/src/ap/ap_drv_ops.h
++++ b/src/ap/ap_drv_ops.h
+@@ -149,6 +149,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 0999ea9..f2afb2e 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 {
+@@ -252,6 +253,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 b07aaf3..266c630 100644
+--- a/src/drivers/driver.h
++++ b/src/drivers/driver.h
+@@ -4736,6 +4736,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 6702384..c8771f7 100644
+--- a/src/drivers/driver_nl80211.c
++++ b/src/drivers/driver_nl80211.c
+@@ -12433,6 +12433,71 @@ static int nl80211_dpp_listen(void *priv, bool enable)
+ }
+ #endif /* CONFIG_DPP */
+ 
++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;
++}
+ 
+ #ifdef CONFIG_TESTING_OPTIONS
+ 
+@@ -13073,4 +13138,5 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
+ 	.start_disabled = nl80211_start_disabled,
+ 	.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 e570224..b90c8fa 100644
+--- a/src/drivers/driver_nl80211.h
++++ b/src/drivers/driver_nl80211.h
+@@ -186,6 +186,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 fcfa68b..c3c7b41 100644
+--- a/src/drivers/driver_nl80211_capa.c
++++ b/src/drivers/driver_nl80211_capa.c
+@@ -1068,6 +1068,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.39.0
+
diff --git a/recipes-wifi/hostapd/files/patches/mtk-0020-hostapd-mtk-Mark-DFS-channel-as-available-for-CSA.patch b/recipes-wifi/hostapd/files/patches/mtk-0020-hostapd-mtk-Mark-DFS-channel-as-available-for-CSA.patch
new file mode 100644
index 0000000..1fe5c88
--- /dev/null
+++ b/recipes-wifi/hostapd/files/patches/mtk-0020-hostapd-mtk-Mark-DFS-channel-as-available-for-CSA.patch
@@ -0,0 +1,60 @@
+From 3e9500a42a41e8cd7c2d7bc20aba96e1e17161fb 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] 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 c33b7a4..9ba6992 100644
+--- a/hostapd/ctrl_iface.c
++++ b/hostapd/ctrl_iface.c
+@@ -2704,6 +2704,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 0da18e2..6231e51 100644
+--- a/hostapd/hostapd_cli.c
++++ b/hostapd/hostapd_cli.c
+@@ -1693,7 +1693,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 18bae5c..2fae590 100644
+--- a/src/ap/ctrl_iface_ap.c
++++ b/src/ap/ctrl_iface_ap.c
+@@ -938,6 +938,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
+ 
+-- 
+2.18.0
+
diff --git a/recipes-wifi/hostapd/files/patches/mtk-0020-hostapd-mtk-add-11v_mbss-and-ema-support.patch b/recipes-wifi/hostapd/files/patches/mtk-0020-hostapd-mtk-add-11v_mbss-and-ema-support.patch
new file mode 100644
index 0000000..8d59a0f
--- /dev/null
+++ b/recipes-wifi/hostapd/files/patches/mtk-0020-hostapd-mtk-add-11v_mbss-and-ema-support.patch
@@ -0,0 +1,1175 @@
+From 8cbdb9a59e3bbe8804f909b13ce6df6e2777c3da Mon Sep 17 00:00:00 2001
+From: mtk20656 <chank.chen@mediatek.com>
+Date: Thu, 2 Mar 2023 10:51:43 +0800
+Subject: [PATCH] hostapd: mtk: add 11v_mbss and ema support for hostapd
+
+Signed-off-by: mtk20656 <chank.chen@mediatek.com>
+---
+ hostapd/config_file.c             |   9 +
+ hostapd/hostapd.conf              |  58 +++++++
+ hostapd/main.c                    |   3 +
+ src/ap/ap_config.c                |  12 ++
+ src/ap/ap_config.h                |   6 +
+ src/ap/beacon.c                   | 124 ++++++++++++--
+ src/ap/hostapd.c                  |  72 +++++++-
+ src/ap/hostapd.h                  |   7 +
+ src/ap/ieee802_11.c               | 276 +++++++++++++++++++++++++++++-
+ src/ap/ieee802_11.h               |   7 +-
+ src/ap/ieee802_11_shared.c        |  11 ++
+ src/common/ieee802_11_common.c    |   4 +
+ src/common/ieee802_11_common.h    |   3 +
+ src/common/ieee802_11_defs.h      |   5 +
+ src/drivers/driver.h              |  42 +++++
+ src/drivers/driver_nl80211.c      |  52 ++++++
+ src/drivers/driver_nl80211_capa.c |  27 +++
+ 17 files changed, 698 insertions(+), 20 deletions(-)
+
+diff --git a/hostapd/config_file.c b/hostapd/config_file.c
+index 649618b..3f26191 100644
+--- a/hostapd/config_file.c
++++ b/hostapd/config_file.c
+@@ -3663,6 +3663,15 @@ static int hostapd_config_fill(struct hostapd_config *conf,
+ 			return 1;
+ 		}
+ 		bss->unsol_bcast_probe_resp_interval = val;
++	} else if (os_strcmp(buf, "mbssid") == 0) {
++		int mbssid = atoi(pos);
++		if (mbssid < 0 || mbssid > ENHANCED_MBSSID_ENABLED) {
++			wpa_printf(MSG_ERROR,
++				   "Line %d: invalid mbssid (%d): '%s'.",
++				   line, mbssid, pos);
++			return 1;
++		}
++		conf->mbssid = mbssid;
+ 	} else if (os_strcmp(buf, "mu_onoff") == 0) {
+ 		int val = atoi(pos);
+ 		if (val < 0 || val > 15) {
+diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf
+index e3a5eb3..f926029 100644
+--- a/hostapd/hostapd.conf
++++ b/hostapd/hostapd.conf
+@@ -3123,3 +3123,61 @@ own_ip_addr=127.0.0.1
+ #bss=wlan0_1
+ #bssid=00:13:10:95:fe:0b
+ # ...
++#
++# Multiple BSSID Advertisement in 802.11ax
++# IEEE Std 802.11ax-2021 added a feature where instead of multiple interfaces
++# on a common radio transmitting individual beacons, those can form a set with
++# a common beacon is transmitted for all. The interface which is brought up
++# first is called as the transmitting profile of the MBSSID set which transmits
++# the beacons. The remaining interfaces are called as the non-transmitting
++# profiles and these are advertised inside the multiple BSSID element in the
++# beacons and probe response frames.
++# The transmitting interface is visible to all clients in the vicinity, however
++# the clients which do not support parsing of the multiple BSSID element will
++# not be able to connect to the non-transmitting interfaces.
++#
++# Enhanced Multiple BSSID Advertisements (EMA)
++# When enabled, the non-transmitting interfaces are split into multiple
++# beacons. The number of beacons required to cover all the non-transmitting
++# profiles is called as the profile periodicity.
++#
++# Refer to IEEE Std 802.11-2020 for details regarding the procedure and
++# required MAC address assignment.
++#
++# Following configuration is per radio.
++# 0 = Disabled (Default)
++# 1 = Multiple BSSID advertisements enabled.
++# 2 = Enhanced multiple BSSID advertisements enabled.
++#mbssid=0
++#
++# The transmitting interface should be added with 'interface' option while
++# the non-transmitting interfaces should be added using 'bss' option.
++# Security configuration should be added separately per interface, if required.
++#
++# Example:
++#mbssid=2
++#interface=wlan2
++#ctrl_interface=/var/run/hostapd
++#wpa_passphrase=0123456789
++#ieee80211w=2
++#sae_pwe=1
++#auth_algs=1
++#wpa=2
++#wpa_pairwise=CCMP
++#ssid=<SSID-0>
++#bridge=br-lan
++#wpa_key_mgmt=SAE
++#bssid=00:03:7f:12:84:84
++#
++#bss=wlan2-1
++#ctrl_interface=/var/run/hostapd
++#wpa_passphrase=0123456789
++#ieee80211w=2
++#sae_pwe=1
++#auth_algs=1
++#wpa=2
++#wpa_pairwise=CCMP
++#ssid=<SSID-1>
++#bridge=br-lan
++#wpa_key_mgmt=SAE
++#bssid=00:03:7f:12:84:85
+diff --git a/hostapd/main.c b/hostapd/main.c
+index 70a4b32..1b6474a 100644
+--- a/hostapd/main.c
++++ b/hostapd/main.c
+@@ -253,6 +253,9 @@ static int hostapd_driver_init(struct hostapd_iface *iface)
+ 				wpa_printf(MSG_ERROR, "set_wowlan failed");
+ 		}
+ 		os_free(triggs);
++
++		iface->mbssid_max_interfaces = capa.mbssid_max_interfaces;
++		iface->ema_max_periodicity = capa.ema_max_periodicity;
+ 	}
+ 
+ 	return 0;
+diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
+index 4e46a62..7d9d5cb 100644
+--- a/src/ap/ap_config.c
++++ b/src/ap/ap_config.c
+@@ -1462,6 +1462,12 @@ static int hostapd_config_check_bss(struct hostapd_bss_config *bss,
+ 	}
+ #endif /* CONFIG_IEEE80211BE */
+ 
++	if (full_config && bss->ignore_broadcast_ssid && conf->mbssid) {
++		wpa_printf(MSG_ERROR,
++			   "Hidden SSID is not suppored when MBSSID is enabled");
++		return -1;
++	}
++
+ 	return 0;
+ }
+ 
+@@ -1545,6 +1551,12 @@ int hostapd_config_check(struct hostapd_config *conf, int full_config)
+ 	}
+ #endif /* CONFIG_IEEE80211BE */
+ 
++	if (full_config && conf->mbssid && !conf->ieee80211ax) {
++		wpa_printf(MSG_ERROR,
++			   "Cannot enable multiple BSSID support without ieee80211ax");
++		return -1;
++	}
++
+ 	for (i = 0; i < conf->num_bss; i++) {
+ 		if (hostapd_config_check_bss(conf->bss[i], conf, full_config))
+ 			return -1;
+diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
+index 7aeb176..51476b8 100644
+--- a/src/ap/ap_config.h
++++ b/src/ap/ap_config.h
+@@ -923,6 +923,8 @@ struct hostapd_bss_config {
+ 	u8 ext_capa[EXT_CAPA_MAX_LEN];
+ 
+ 	u8 rnr;
++
++	bool xrates_supported;
+ };
+ 
+ /**
+@@ -1163,6 +1165,10 @@ struct hostapd_config {
+ 	u8 ibf_enable;
+ 	u8 dfs_detect_mode;
+ 	u8 amsdu;
++
++#define MBSSID_ENABLED          1
++#define ENHANCED_MBSSID_ENABLED 2
++	u8 mbssid;
+ };
+ 
+ enum three_wire_mode {
+diff --git a/src/ap/beacon.c b/src/ap/beacon.c
+index f3ea5c2..51db23a 100644
+--- a/src/ap/beacon.c
++++ b/src/ap/beacon.c
+@@ -462,15 +462,77 @@ static u8 * hostapd_eid_supported_op_classes(struct hostapd_data *hapd, u8 *eid)
+ }
+ 
+ 
++static int ieee802_11_build_ap_params_mbssid(struct hostapd_data *hapd,
++					     struct wpa_driver_ap_params *params,
++					     u8 **eid)
++{
++	struct hostapd_iface *iface = hapd->iface;
++	struct hostapd_data *tx_bss;
++	size_t len;
++	u8 elem_count = 0, *elem = NULL, **elem_offset = NULL, *end;
++	u8 *tailpos = *eid;
++
++	if (!iface->mbssid_max_interfaces ||
++	    iface->num_bss > iface->mbssid_max_interfaces ||
++	    (iface->conf->mbssid == ENHANCED_MBSSID_ENABLED &&
++	     !iface->ema_max_periodicity))
++		goto fail;
++
++	tx_bss = hostapd_mbssid_get_tx_bss(hapd);
++	len = hostapd_eid_mbssid_len(tx_bss, WLAN_FC_STYPE_BEACON, &elem_count,
++				     NULL, 0);
++	if (!len || (iface->conf->mbssid == ENHANCED_MBSSID_ENABLED &&
++		     elem_count > iface->ema_max_periodicity))
++		goto fail;
++
++	elem = os_zalloc(len);
++	if (!elem)
++		goto fail;
++
++	elem_offset = os_zalloc(elem_count * sizeof(u8 *));
++	if (!elem_offset)
++		goto fail;
++
++	end = hostapd_eid_mbssid(tx_bss, elem, elem + len, WLAN_FC_STYPE_BEACON,
++				 elem_count, elem_offset, NULL, 0);
++
++	params->mbssid_tx_iface = tx_bss->conf->iface;
++	params->mbssid_index = hostapd_mbssid_get_bss_index(hapd);
++	params->mbssid_elem = elem;
++	params->mbssid_elem_len = end - elem;
++	params->mbssid_elem_count = elem_count;
++	params->mbssid_elem_offset = elem_offset;
++	if (iface->conf->mbssid == ENHANCED_MBSSID_ENABLED) {
++		params->ema = true;
++		*tailpos++ = WLAN_EID_EXTENSION;
++		*tailpos++ = 3;
++		*tailpos++ = WLAN_EID_EXT_MULTIPLE_BSSID_CONFIGURATION;
++		*tailpos++ = iface->num_bss;
++		*tailpos++ = params->mbssid_elem_count;
++		*eid = tailpos;
++	}
++
++	return 0;
++
++fail:
++	os_free(elem);
++	wpa_printf(MSG_ERROR, "MBSSID: Configuration failed");
++	return -1;
++}
++
++
+ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
+ 				   const struct ieee80211_mgmt *req,
+ 				   int is_p2p, size_t *resp_len,
+-				   bool bcast_probe_resp)
++				   bool bcast_probe_resp, const u8 *known_bss,
++				   u8 known_bss_len)
+ {
+ 	struct ieee80211_mgmt *resp;
+-	u8 *pos, *epos, *csa_pos;
++	u8 *pos, *epos, *csa_pos, *ext_cap_pos;
+ 	size_t buflen;
+ 
++	hapd = hostapd_mbssid_get_tx_bss(hapd);
++
+ #define MAX_PROBERESP_LEN 768
+ 	buflen = MAX_PROBERESP_LEN;
+ #ifdef CONFIG_WPS
+@@ -517,6 +579,8 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
+ 	}
+ #endif /* CONFIG_IEEE80211BE */
+ 
++	buflen += hostapd_eid_mbssid_len(hapd, WLAN_FC_STYPE_PROBE_RESP, NULL,
++					 known_bss, known_bss_len);
+ 	buflen += hostapd_eid_rnr_len(hapd, WLAN_FC_STYPE_PROBE_RESP);
+ 	buflen += hostapd_mbo_ie_len(hapd);
+ 	buflen += hostapd_eid_owe_trans_len(hapd);
+@@ -588,8 +652,16 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
+ 	pos = hostapd_eid_supported_op_classes(hapd, pos);
+ 	pos = hostapd_eid_ht_capabilities(hapd, pos);
+ 	pos = hostapd_eid_ht_operation(hapd, pos);
++	pos = hostapd_eid_mbssid(hapd, pos, epos, WLAN_FC_STYPE_PROBE_RESP, 0,
++				 NULL, known_bss, known_bss_len);
+ 
++	ext_cap_pos = pos;
+ 	pos = hostapd_eid_ext_capab(hapd, pos);
++	if (hapd->iconf->mbssid >= MBSSID_ENABLED && !known_bss_len)
++		ext_cap_pos[12] |= 0x01; /* Probe responses always include all
++					  * non-tx profiles except when a list
++					  * of known BSSes is included in the
++					  * probe request. */
+ 
+ 	pos = hostapd_eid_time_adv(hapd, pos);
+ 	pos = hostapd_eid_time_zone(hapd, pos);
+@@ -1153,16 +1225,23 @@ void handle_probe_req(struct hostapd_data *hapd,
+ 	}
+ #endif /* CONFIG_TESTING_OPTIONS */
+ 
++	/* Do not send probe response from a non-transmitting multiple BSSID
++	 * profile unless the probe request is directed at that paticular BSS */
++	if (hapd != hostapd_mbssid_get_tx_bss(hapd) && res != EXACT_SSID_MATCH)
++		return;
++
+ 	wpa_msg_ctrl(hapd->msg_ctx, MSG_INFO, RX_PROBE_REQUEST "sa=" MACSTR
+ 		     " signal=%d", MAC2STR(mgmt->sa), ssi_signal);
+ 
+ 	if (is_6ghz_op_class(hapd->iconf->op_class) &&
+ 	    is_broadcast_ether_addr(mgmt->da))
+ 		resp = hostapd_gen_probe_resp(hapd, NULL, elems.p2p != NULL,
+-					      &resp_len, true);
++					      &resp_len, false, elems.mbssid_known_bss,
++					      elems.mbssid_known_bss_len);
+ 	else
+ 		resp = hostapd_gen_probe_resp(hapd, mgmt, elems.p2p != NULL,
+-					      &resp_len, false);
++					      &resp_len, false, elems.mbssid_known_bss,
++					      elems.mbssid_known_bss_len);
+ 	if (resp == NULL)
+ 		return;
+ 
+@@ -1184,7 +1263,8 @@ void handle_probe_req(struct hostapd_data *hapd,
+ 				hapd->cs_c_off_ecsa_proberesp;
+ 	}
+ 
+-	ret = hostapd_drv_send_mlme(hapd, resp, resp_len, noack,
++	ret = hostapd_drv_send_mlme(hostapd_mbssid_get_tx_bss(hapd), resp,
++				    resp_len, noack,
+ 				    csa_offs_len ? csa_offs : NULL,
+ 				    csa_offs_len, 0);
+ 
+@@ -1231,7 +1311,7 @@ static u8 * hostapd_probe_resp_offloads(struct hostapd_data *hapd,
+ 			   "this");
+ 
+ 	/* Generate a Probe Response template for the non-P2P case */
+-	return hostapd_gen_probe_resp(hapd, NULL, 0, resp_len, false);
++	return hostapd_gen_probe_resp(hapd, NULL, 0, resp_len, false, NULL, 0);
+ }
+ 
+ #endif /* NEED_AP_MLME */
+@@ -1250,7 +1330,7 @@ static u8 * hostapd_unsol_bcast_probe_resp(struct hostapd_data *hapd,
+ 
+ 	return hostapd_gen_probe_resp(hapd, NULL, 0,
+ 				      &params->unsol_bcast_probe_resp_tmpl_len,
+-				      true);
++				      true, NULL, 0);
+ }
+ #endif /* CONFIG_IEEE80211AX */
+ 
+@@ -1533,8 +1613,12 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
+ 	size_t resp_len = 0;
+ #ifdef NEED_AP_MLME
+ 	u16 capab_info;
+-	u8 *pos, *tailpos, *tailend, *csa_pos;
++	u8 *pos, *tailpos, *tailend, *csa_pos, *ext_cap_pos;
++#endif /* NEED_AP_MLME */
+ 
++	os_memset(params, 0, sizeof(*params));
++
++#ifdef NEED_AP_MLME
+ #define BEACON_HEAD_BUF_SIZE 256
+ #define BEACON_TAIL_BUF_SIZE 512
+ 	head = os_zalloc(BEACON_HEAD_BUF_SIZE);
+@@ -1586,6 +1670,9 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
+ 	}
+ #endif /* CONFIG_IEEE80211BE */
+ 
++	if (hapd->iconf->mbssid == ENHANCED_MBSSID_ENABLED &&
++	    hapd == hostapd_mbssid_get_tx_bss(hapd))
++		tail_len += 5; /* Multiple BSSID Configuration element */
+ 	tail_len += hostapd_eid_rnr_len(hapd, WLAN_FC_STYPE_BEACON);
+ 	tail_len += hostapd_mbo_ie_len(hapd);
+ 	tail_len += hostapd_eid_owe_trans_len(hapd);
+@@ -1671,9 +1758,23 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
+ 	tailpos = hostapd_eid_supported_op_classes(hapd, tailpos);
+ 	tailpos = hostapd_eid_ht_capabilities(hapd, tailpos);
+ 	tailpos = hostapd_eid_ht_operation(hapd, tailpos);
+-
++	ext_cap_pos = tailpos;
+ 	tailpos = hostapd_eid_ext_capab(hapd, tailpos);
+ 
++	if (hapd->iconf->mbssid && hapd->iconf->num_bss > 1) {
++		if (ieee802_11_build_ap_params_mbssid(hapd, params, &tailpos)) {
++			os_free(head);
++			os_free(tail);
++			wpa_printf(MSG_ERROR, "Failed to set beacon data");
++			return -1;
++		} else if (hapd->iconf->mbssid == MBSSID_ENABLED ||
++			   (hapd->iconf->mbssid == ENHANCED_MBSSID_ENABLED &&
++			   params->mbssid_elem_count == 1)) {
++			/* Set the extended capability bit for "complete list
++			 * of non-tx profiles" */
++			ext_cap_pos[12] |= 0x01;
++		}
++	}
+ 	/*
+ 	 * TODO: Time Advertisement element should only be included in some
+ 	 * DTIM Beacon frames.
+@@ -1794,7 +1895,6 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
+ 	resp = hostapd_probe_resp_offloads(hapd, &resp_len);
+ #endif /* NEED_AP_MLME */
+ 
+-	os_memset(params, 0, sizeof(*params));
+ 	params->head = (u8 *) head;
+ 	params->head_len = head_len;
+ 	params->tail = tail;
+@@ -1897,6 +1997,10 @@ void ieee802_11_free_ap_params(struct wpa_driver_ap_params *params)
+ 	params->head = NULL;
+ 	os_free(params->proberesp);
+ 	params->proberesp = NULL;
++	os_free(params->mbssid_elem);
++	params->mbssid_elem = NULL;
++	os_free(params->mbssid_elem_offset);
++	params->mbssid_elem_offset = NULL;
+ #ifdef CONFIG_FILS
+ 	os_free(params->fd_frame_tmpl);
+ 	params->fd_frame_tmpl = NULL;
+diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
+index 42e8ed7..82cc155 100644
+--- a/src/ap/hostapd.c
++++ b/src/ap/hostapd.c
+@@ -91,6 +91,29 @@ int hostapd_for_each_interface(struct hapd_interfaces *interfaces,
+ }
+ 
+ 
++struct hostapd_data * hostapd_mbssid_get_tx_bss(struct hostapd_data *hapd)
++{
++	if (hapd->iconf->mbssid)
++		return hapd->iface->bss[0];
++
++	return hapd;
++}
++
++
++int hostapd_mbssid_get_bss_index(struct hostapd_data *hapd)
++{
++	if (hapd->iconf->mbssid) {
++		size_t i;
++
++		for (i = 1; i < hapd->iface->num_bss; i++)
++			if (hapd->iface->bss[i] == hapd)
++				return i;
++	}
++
++	return 0;
++}
++
++
+ void hostapd_reconfig_encryption(struct hostapd_data *hapd)
+ {
+ 	if (hapd->wpa_auth)
+@@ -1179,19 +1202,37 @@ static int db_table_create_radius_attributes(sqlite3 *db)
+ 
+ #endif /* CONFIG_NO_RADIUS */
+ 
++static int hostapd_start_beacon(struct hostapd_data *hapd)
++{
++	struct hostapd_bss_config *conf = hapd->conf;
++
++	if (!conf->start_disabled && ieee802_11_set_beacon(hapd) < 0)
++		return -1;
++
++	if (hapd->driver && hapd->driver->set_operstate)
++		hapd->driver->set_operstate(hapd->drv_priv, 1);
++
++	return 0;
++}
+ 
+ /**
+  * hostapd_setup_bss - Per-BSS setup (initialization)
+  * @hapd: Pointer to BSS data
+  * @first: Whether this BSS is the first BSS of an interface; -1 = not first,
+  *	but interface may exist
++ * @start_beacon: Whether beacons should be configured and transmission started
++ *	at this time. This is used when MBSSID IE is enabled where the
++ *	information regarding all BSSes should be retrieved before configuring
++ *	the beacons. The calling functions are responsible to configure the
++ *	beacon explicitly if this is set to 'false'.
+  *
+  * This function is used to initialize all per-BSS data structures and
+  * resources. This gets called in a loop for each BSS when an interface is
+  * initialized. Most of the modules that are initialized here will be
+  * deinitialized in hostapd_cleanup().
+  */
+-static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
++static int hostapd_setup_bss(struct hostapd_data *hapd, int first,
++			     bool start_beacon)
+ {
+ 	struct hostapd_bss_config *conf = hapd->conf;
+ 	u8 ssid[SSID_MAX_LEN + 1];
+@@ -1464,9 +1505,6 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
+ 		return -1;
+ 	}
+ 
+-	if (!conf->start_disabled && ieee802_11_set_beacon(hapd) < 0)
+-		return -1;
+-
+ 	if (flush_old_stations && !conf->start_disabled &&
+ 	    conf->broadcast_deauth) {
+ 		u8 addr[ETH_ALEN];
+@@ -1485,8 +1523,8 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
+ 	if (hapd->wpa_auth && wpa_init_keys(hapd->wpa_auth) < 0)
+ 		return -1;
+ 
+-	if (hapd->driver && hapd->driver->set_operstate)
+-		hapd->driver->set_operstate(hapd->drv_priv, 1);
++	if (start_beacon)
++		return hostapd_start_beacon(hapd);
+ 
+ 	hostapd_ubus_add_bss(hapd);
+ 
+@@ -2214,7 +2252,7 @@ static int hostapd_setup_interface_complete_sync(struct hostapd_iface *iface,
+ 		hapd = iface->bss[j];
+ 		if (j)
+ 			os_memcpy(hapd->own_addr, prev_addr, ETH_ALEN);
+-		if (hostapd_setup_bss(hapd, j == 0)) {
++		if (hostapd_setup_bss(hapd, j == 0, !iface->conf->mbssid)) {
+ 			for (;;) {
+ 				hapd = iface->bss[j];
+ 				hostapd_bss_deinit_no_free(hapd);
+@@ -2228,6 +2266,24 @@ static int hostapd_setup_interface_complete_sync(struct hostapd_iface *iface,
+ 		if (is_zero_ether_addr(hapd->conf->bssid))
+ 			prev_addr = hapd->own_addr;
+ 	}
++
++	if (hapd->iconf->mbssid) {
++		for (j = 0; j < iface->num_bss; j++) {
++			hapd = iface->bss[j];
++			if (hostapd_start_beacon(hapd)) {
++				for (;;) {
++					hapd = iface->bss[j];
++					hostapd_bss_deinit_no_free(hapd);
++					hostapd_free_hapd_data(hapd);
++					if (j == 0)
++						break;
++					j--;
++				}
++				goto fail;
++			}
++		}
++	}
++
+ 	hapd = iface->bss[0];
+ 
+ 	hostapd_tx_queue_params(iface);
+@@ -3130,7 +3186,7 @@ int hostapd_add_iface(struct hapd_interfaces *interfaces, char *buf)
+ 
+ 			if (start_ctrl_iface_bss(hapd) < 0 ||
+ 			    (hapd_iface->state == HAPD_IFACE_ENABLED &&
+-			     hostapd_setup_bss(hapd, -1))) {
++			     hostapd_setup_bss(hapd, -1, true))) {
+ 				hostapd_cleanup(hapd);
+ 				hapd_iface->bss[hapd_iface->num_bss - 1] = NULL;
+ 				hapd_iface->conf->num_bss--;
+diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h
+index 56d96a5..093c28a 100644
+--- a/src/ap/hostapd.h
++++ b/src/ap/hostapd.h
+@@ -660,6 +660,11 @@ struct hostapd_iface {
+ 	/* Previous WMM element information */
+ 	struct hostapd_wmm_ac_params prev_wmm[WMM_AC_NUM];
+ 
++	/* Maximum number of interfaces supported for MBSSID advertisements */
++	u8 mbssid_max_interfaces;
++	/* Maximum profile periodicity for enhanced MBSSID advertisements */
++	u8 ema_max_periodicity;
++
+ 	int (*enable_iface_cb)(struct hostapd_iface *iface);
+ 	int (*disable_iface_cb)(struct hostapd_iface *iface);
+ };
+@@ -762,5 +767,7 @@ void fst_hostapd_fill_iface_obj(struct hostapd_data *hapd,
+ #endif /* CONFIG_FST */
+ 
+ int hostapd_set_acl(struct hostapd_data *hapd);
++struct hostapd_data * hostapd_mbssid_get_tx_bss(struct hostapd_data *hapd);
++int hostapd_mbssid_get_bss_index(struct hostapd_data *hapd);
+ 
+ #endif /* HOSTAPD_H */
+diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
+index 098793e..30bfa30 100644
+--- a/src/ap/ieee802_11.c
++++ b/src/ap/ieee802_11.c
+@@ -165,6 +165,7 @@ u8 * hostapd_eid_ext_supp_rates(struct hostapd_data *hapd, u8 *eid)
+ 	int i, num, count;
+ 	int h2e_required;
+ 
++	hapd->conf->xrates_supported = 0;
+ 	if (hapd->iface->current_rates == NULL)
+ 		return eid;
+ 
+@@ -214,6 +215,7 @@ u8 * hostapd_eid_ext_supp_rates(struct hostapd_data *hapd, u8 *eid)
+ 			*pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_SAE_H2E_ONLY;
+ 	}
+ 
++	hapd->conf->xrates_supported = 1;
+ 	return pos;
+ }
+ 
+@@ -3979,6 +3981,23 @@ static void handle_auth(struct hostapd_data *hapd,
+ }
+ 
+ 
++static u8 hostapd_max_bssid_indicator(struct hostapd_data *hapd)
++{
++	size_t num_bss_nontx;
++	u8 max_bssid_ind = 0;
++
++	if (!hapd->iconf->mbssid || hapd->iface->num_bss <= 1)
++		return 0;
++
++	num_bss_nontx = hapd->iface->num_bss - 1;
++	while (num_bss_nontx > 0) {
++		max_bssid_ind++;
++		num_bss_nontx >>= 1;
++	}
++	return max_bssid_ind;
++}
++
++
+ int hostapd_get_aid(struct hostapd_data *hapd, struct sta_info *sta)
+ {
+ 	int i, j = 32, aid;
+@@ -4004,7 +4023,10 @@ int hostapd_get_aid(struct hostapd_data *hapd, struct sta_info *sta)
+ 	}
+ 	if (j == 32)
+ 		return -1;
+-	aid = i * 32 + j + 1;
++	aid = i * 32 + j;
++
++	aid += (1 << hostapd_max_bssid_indicator(hapd));
++
+ 	if (aid > 2007)
+ 		return -1;
+ 
+@@ -7579,4 +7601,256 @@ u8 * hostapd_eid_rnr(struct hostapd_data *hapd, u8 *eid, u32 type)
+ 	return eid;
+ }
+ 
++
++static size_t hostapd_eid_mbssid_elem_len(struct hostapd_data *hapd,
++					  u32 frame_type, size_t *bss_index,
++					  const u8 *known_bss,
++					  size_t known_bss_len)
++{
++	struct hostapd_data *tx_bss = hostapd_mbssid_get_tx_bss(hapd);
++	size_t len = 3, i;
++
++	for (i = *bss_index; i < hapd->iface->num_bss; i++) {
++		struct hostapd_data *bss = hapd->iface->bss[i];
++		const u8 *auth, *rsn = NULL, *rsnx = NULL;
++		size_t nontx_profile_len, auth_len;
++		u8 ie_count = 0;
++
++		if (known_bss && (known_bss_len > (i / 8))) {
++			known_bss = &known_bss[i / 8];
++			if (*known_bss & (u8)(BIT(i % 8)))
++				continue;
++		}
++
++		if (!bss || !bss->conf || !bss->started)
++			continue;
++
++		/*
++		 * Sublement ID: 1 byte
++		 * Length: 1 byte
++		 * Nontransmitted capabilities: 4 bytes
++		 * SSID element: 2 + variable
++		 * Multiple BSSID Index Element: 3 bytes (+2 bytes in beacons)
++		 * Fixed length = 1 + 1 + 4 + 2 + 3 = 11
++		 */
++		nontx_profile_len = 11 + bss->conf->ssid.ssid_len;
++
++		if (frame_type == WLAN_FC_STYPE_BEACON)
++			nontx_profile_len += 2;
++
++		auth = wpa_auth_get_wpa_ie(bss->wpa_auth, &auth_len);
++		if (auth) {
++			rsn = get_ie(auth, auth_len, WLAN_EID_RSN);
++			if (rsn)
++				nontx_profile_len += (2 + rsn[1]);
++
++			rsnx = get_ie(auth, auth_len, WLAN_EID_RSNX);
++			if (rsnx)
++				nontx_profile_len += (2 + rsnx[1]);
++		}
++		if (!rsn && hostapd_wpa_ie(tx_bss, WLAN_EID_RSN))
++			ie_count++;
++		if (!rsnx && hostapd_wpa_ie(tx_bss, WLAN_EID_RSNX))
++			ie_count++;
++		if (bss->conf->xrates_supported)
++			nontx_profile_len += 8;
++		else if (hapd->conf->xrates_supported)
++			ie_count++;
++		if (ie_count)
++			nontx_profile_len += (4 + ie_count);
++
++		if ((len + nontx_profile_len) > 255)
++			goto mbssid_too_big;
++
++		len += nontx_profile_len;
++	}
++
++mbssid_too_big:
++	*bss_index = i;
++	return len;
++}
++
++
++size_t hostapd_eid_mbssid_len(struct hostapd_data *hapd, u32 frame_type,
++			      u8 *elem_count, const u8 *known_bss,
++			      size_t known_bss_len)
++{
++	size_t len = 0, bss_index = 1;
++
++	if (!hapd->iconf->mbssid || hapd->iface->num_bss <= 1 ||
++	    (frame_type != WLAN_FC_STYPE_BEACON &&
++	     frame_type != WLAN_FC_STYPE_PROBE_RESP))
++		return 0;
++
++	if (frame_type == WLAN_FC_STYPE_BEACON) {
++		if (!elem_count) {
++			wpa_printf(MSG_ERROR,
++				   "MBSSID: Insufficient data for beacons");
++			return 0;
++		}
++		*elem_count = 0;
++	}
++
++	while (bss_index < hapd->iface->num_bss) {
++		len += hostapd_eid_mbssid_elem_len(hapd, frame_type,
++						   &bss_index, known_bss,
++						   known_bss_len);
++
++		if (frame_type == WLAN_FC_STYPE_BEACON)
++			*elem_count += 1;
++	}
++	return len;
++}
++
++
++static u8 * hostapd_eid_mbssid_elem(struct hostapd_data *hapd, u8 *eid, u8 *end,
++				    u32 frame_type, u8 max_bssid_indicator,
++				    size_t *bss_index, u8 elem_count,
++				    const u8 *known_bss, size_t known_bss_len)
++{
++	struct hostapd_data *tx_bss = hostapd_mbssid_get_tx_bss(hapd);
++	size_t i;
++	u8 *eid_len_offset, *max_bssid_indicator_offset;
++
++	*eid++ = WLAN_EID_MULTIPLE_BSSID;
++	eid_len_offset = eid++;
++	max_bssid_indicator_offset = eid++;
++
++	for (i = *bss_index; i < hapd->iface->num_bss; i++) {
++		struct hostapd_data *bss = hapd->iface->bss[i];
++		struct hostapd_bss_config *conf;
++		u8 *eid_len_pos, *nontx_bss_start = eid;
++		const u8 *auth, *rsn = NULL, *rsnx = NULL;
++		u8 ie_count = 0, non_inherit_ie[3];
++		size_t auth_len = 0;
++		u16 capab_info;
++
++		if (known_bss && (known_bss_len > (i / 8))) {
++			known_bss = &known_bss[i / 8];
++			if (*known_bss & (u8)(BIT(i % 8)))
++				continue;
++		}
++
++		if (!bss || !bss->conf || !bss->started)
++			continue;
++		conf = bss->conf;
++
++		*eid++ = WLAN_EID_SUBELEMENT_NONTRANSMITTED_BSSID_PROFILE;
++		eid_len_pos = eid++;
++
++		*eid++ = WLAN_EID_NONTRANSMITTED_BSSID_CAPA;
++		*eid++ = sizeof(capab_info);
++		capab_info = host_to_le16(hostapd_own_capab_info(bss));
++		os_memcpy(eid, (const void *)&capab_info, sizeof(capab_info));
++		eid += sizeof(capab_info);
++
++		*eid++ = WLAN_EID_SSID;
++		*eid++ = conf->ssid.ssid_len;
++		os_memcpy(eid, conf->ssid.ssid, conf->ssid.ssid_len);
++		eid += conf->ssid.ssid_len;
++
++		*eid++ = WLAN_EID_MULTIPLE_BSSID_INDEX;
++		if (frame_type == WLAN_FC_STYPE_BEACON) {
++			*eid++ = 3;
++			*eid++ = i;
++			if (hapd->iconf->mbssid == ENHANCED_MBSSID_ENABLED &&
++			    (conf->dtim_period % elem_count))
++				conf->dtim_period = elem_count;
++			*eid++ = conf->dtim_period;
++			*eid++ = 0xFF;
++		} else {
++			*eid++ = 1;
++			*eid++ = i;
++		}
++
++		auth = wpa_auth_get_wpa_ie(bss->wpa_auth, &auth_len);
++		if (auth) {
++			rsn = get_ie(auth, auth_len, WLAN_EID_RSN);
++			if (rsn) {
++				os_memcpy(eid, rsn, 2 + rsn[1]);
++				eid += (2 + rsn[1]);
++			}
++
++			rsnx = get_ie(auth, auth_len, WLAN_EID_RSNX);
++			if (rsnx) {
++				os_memcpy(eid, rsnx, 2 + rsnx[1]);
++				eid += (2 + rsnx[1]);
++			}
++		}
++		if (!rsn && hostapd_wpa_ie(tx_bss, WLAN_EID_RSN)) {
++			non_inherit_ie[ie_count] = WLAN_EID_RSN;
++			ie_count++;
++		}
++		if (!rsnx && hostapd_wpa_ie(tx_bss, WLAN_EID_RSNX)) {
++			non_inherit_ie[ie_count] = WLAN_EID_RSNX;
++			ie_count++;
++		}
++		if (hapd->conf->xrates_supported &&
++		    !bss->conf->xrates_supported) {
++			non_inherit_ie[ie_count] = WLAN_EID_EXT_SUPP_RATES;
++			ie_count++;
++		}
++		if (ie_count) {
++			*eid++ = WLAN_EID_EXTENSION;
++			*eid++ = 2 + ie_count;
++			*eid++ = WLAN_EID_EXT_NON_INHERITANCE;
++			*eid++ = ie_count;
++			os_memcpy(eid, non_inherit_ie, ie_count);
++			eid += ie_count;
++		}
++
++		*eid_len_pos = (eid - eid_len_pos) - 1;
++
++		if (((eid - eid_len_offset) - 1) > 255) {
++			eid = nontx_bss_start;
++			goto mbssid_too_big;
++		}
++	}
++
++mbssid_too_big:
++	*bss_index = i;
++	*max_bssid_indicator_offset = max_bssid_indicator;
++	if (*max_bssid_indicator_offset < 1)
++		*max_bssid_indicator_offset = 1;
++	*eid_len_offset = (eid - eid_len_offset) - 1;
++	return eid;
++}
++
++
++u8 * hostapd_eid_mbssid(struct hostapd_data *hapd, u8 *eid, u8 *end,
++			u32 frame_type, u8 elem_count, u8 **elem_offset,
++			const u8 *known_bss, size_t known_bss_len)
++{
++	size_t bss_index = 1;
++	u8 elem_index = 0;
++
++	if (!hapd->iconf->mbssid || hapd->iface->num_bss <= 1 ||
++	    (frame_type != WLAN_FC_STYPE_BEACON &&
++	     frame_type != WLAN_FC_STYPE_PROBE_RESP))
++		return eid;
++
++	if (frame_type == WLAN_FC_STYPE_BEACON && !elem_offset) {
++		wpa_printf(MSG_ERROR, "MBSSID: Insufficient data for beacons");
++		return eid;
++	}
++
++	while (bss_index < hapd->iface->num_bss) {
++		if (frame_type == WLAN_FC_STYPE_BEACON) {
++			if (elem_index == elem_count) {
++				wpa_printf(MSG_WARNING,
++					   "MBSSID: More number of elements than provided array");
++				break;
++			}
++
++			elem_offset[elem_index] = eid;
++			elem_index = elem_index + 1;
++		}
++		eid = hostapd_eid_mbssid_elem(hapd, eid, end, frame_type,
++					      hostapd_max_bssid_indicator(hapd),
++					      &bss_index, elem_count,
++					      known_bss, known_bss_len);
++	}
++	return eid;
++}
++
+ #endif /* CONFIG_NATIVE_WINDOWS */
+diff --git a/src/ap/ieee802_11.h b/src/ap/ieee802_11.h
+index fa1f47b..bb454bb 100644
+--- a/src/ap/ieee802_11.h
++++ b/src/ap/ieee802_11.h
+@@ -214,5 +214,10 @@ u16 copy_sta_eht_capab(struct hostapd_data *hapd, struct sta_info *sta,
+ 		       enum ieee80211_op_mode opmode,
+ 		       const u8 *he_capab, size_t he_capab_len,
+ 		       const u8 *eht_capab, size_t eht_capab_len);
+-
++size_t hostapd_eid_mbssid_len(struct hostapd_data *hapd, u32 frame_type,
++			      u8 *elem_count, const u8 *known_bss,
++			      size_t known_bss_len);
++u8 * hostapd_eid_mbssid(struct hostapd_data *hapd, u8 *eid, u8 *end,
++			u32 frame_type, u8 elem_count, u8 **elem_offset,
++			const u8 *known_bss, size_t known_bss_len);
+ #endif /* IEEE802_11_H */
+diff --git a/src/ap/ieee802_11_shared.c b/src/ap/ieee802_11_shared.c
+index 4f85d78..7f5b475 100644
+--- a/src/ap/ieee802_11_shared.c
++++ b/src/ap/ieee802_11_shared.c
+@@ -364,6 +364,8 @@ static void hostapd_ext_capab_byte(struct hostapd_data *hapd, u8 *pos, int idx)
+ 			*pos |= 0x02; /* Bit 17 - WNM-Sleep Mode */
+ 		if (hapd->conf->bss_transition)
+ 			*pos |= 0x08; /* Bit 19 - BSS Transition */
++		if (hapd->iconf->mbssid)
++			*pos |= 0x40; /* Bit 22 - Multiple BSSID */
+ 		break;
+ 	case 3: /* Bits 24-31 */
+ #ifdef CONFIG_WNM_AP
+@@ -436,6 +438,8 @@ static void hostapd_ext_capab_byte(struct hostapd_data *hapd, u8 *pos, int idx)
+ 		    (hapd->iface->drv_flags &
+ 		     WPA_DRIVER_FLAGS_BEACON_PROTECTION))
+ 			*pos |= 0x10; /* Bit 84 - Beacon Protection Enabled */
++		if (hapd->iconf->mbssid == ENHANCED_MBSSID_ENABLED)
++			*pos |= 0x08; /* Bit 83 - Enhanced multiple BSSID */
+ 		break;
+ 	case 11: /* Bits 88-95 */
+ #ifdef CONFIG_SAE_PK
+@@ -471,6 +475,13 @@ u8 * hostapd_eid_ext_capab(struct hostapd_data *hapd, u8 *eid)
+ 			*pos &= ~hapd->conf->ext_capa_mask[i];
+ 			*pos |= hapd->conf->ext_capa[i];
+ 		}
++
++		/* Clear bits 83 and 22 if EMA and MBSSID are not enabled
++		 * otherwise association fails with some clients */
++		if (i == 10 && hapd->iconf->mbssid < ENHANCED_MBSSID_ENABLED)
++			*pos &= ~0x08;
++		if (i == 2 && !hapd->iconf->mbssid)
++			*pos &= ~0x40;
+ 	}
+ 
+ 	while (len > 0 && eid[1 + len] == 0) {
+diff --git a/src/common/ieee802_11_common.c b/src/common/ieee802_11_common.c
+index c8ee90c..2fab7c3 100644
+--- a/src/common/ieee802_11_common.c
++++ b/src/common/ieee802_11_common.c
+@@ -315,6 +315,10 @@ static int ieee802_11_parse_extension(const u8 *pos, size_t elen,
+ 		elems->eht_operation = pos;
+ 		elems->eht_operation_len = elen;
+ 		break;
++	case WLAN_EID_EXT_KNOWN_BSSID:
++		elems->mbssid_known_bss = pos;
++		elems->mbssid_known_bss_len = elen;
++		break;
+ 	default:
+ 		if (show_errors) {
+ 			wpa_printf(MSG_MSGDUMP,
+diff --git a/src/common/ieee802_11_common.h b/src/common/ieee802_11_common.h
+index 94e1d7b..1e4e27d 100644
+--- a/src/common/ieee802_11_common.h
++++ b/src/common/ieee802_11_common.h
+@@ -119,6 +119,7 @@ struct ieee802_11_elems {
+ 	const u8 *pasn_params;
+ 	const u8 *eht_capabilities;
+ 	const u8 *eht_operation;
++	const u8 *mbssid_known_bss;
+ 
+ 	u8 ssid_len;
+ 	u8 supp_rates_len;
+@@ -176,6 +177,8 @@ struct ieee802_11_elems {
+ 	u8 eht_capabilities_len;
+ 	u8 eht_operation_len;
+ 
++	u8 mbssid_known_bss_len;
++
+ 	struct mb_ies_info mb_ies;
+ 	struct frag_ies_info frag_ies;
+ };
+diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h
+index 62088bd..0bbbca9 100644
+--- a/src/common/ieee802_11_defs.h
++++ b/src/common/ieee802_11_defs.h
+@@ -481,6 +481,9 @@
+ #define WLAN_EID_EXT_SPATIAL_REUSE 39
+ #define WLAN_EID_EXT_COLOR_CHANGE_ANNOUNCEMENT 42
+ #define WLAN_EID_EXT_OCV_OCI 54
++#define WLAN_EID_EXT_MULTIPLE_BSSID_CONFIGURATION 55
++#define WLAN_EID_EXT_NON_INHERITANCE 56
++#define WLAN_EID_EXT_KNOWN_BSSID 57
+ #define WLAN_EID_EXT_SHORT_SSID_LIST 58
+ #define WLAN_EID_EXT_HE_6GHZ_BAND_CAP 59
+ #define WLAN_EID_EXT_EDMG_CAPABILITIES 61
+@@ -497,6 +500,8 @@
+ #define WLAN_EID_EXT_MULTI_LINK_TRAFFIC_INDICATION 110
+ #define WLAN_EID_EXT_AKM_SUITE_SELECTOR 114
+ 
++#define WLAN_EID_SUBELEMENT_NONTRANSMITTED_BSSID_PROFILE 0
++
+ /* Extended Capabilities field */
+ #define WLAN_EXT_CAPAB_20_40_COEX 0
+ #define WLAN_EXT_CAPAB_GLK 1
+diff --git a/src/drivers/driver.h b/src/drivers/driver.h
+index 82daef0..36f465c 100644
+--- a/src/drivers/driver.h
++++ b/src/drivers/driver.h
+@@ -1633,6 +1633,43 @@ struct wpa_driver_ap_params {
+ 	 * ibf_enable=<val>
+ 	 */
+ 	u8 ibf_enable;
++
++	/**
++	 * mbssid_tx_iface - Transmitting interface of the MBSSID set
++	 */
++	const char *mbssid_tx_iface;
++
++	/**
++	 * mbssid_index - The index of this BSS in the MBSSID set
++	 */
++	unsigned int mbssid_index;
++
++	/**
++	 * mbssid_elem - Buffer containing all MBSSID elements
++	 */
++	u8 *mbssid_elem;
++
++	/**
++	 * mbssid_elem_len - Total length of all MBSSID elements
++	 */
++	size_t mbssid_elem_len;
++
++	/**
++	 * mbssid_elem_count - The number of MBSSID elements
++	 */
++	u8 mbssid_elem_count;
++
++	/**
++	 * mbssid_elem_offset - Offsets to elements in mbssid_elem.
++	 * Kernel will use these offsets to generate multiple BSSID beacons.
++	 */
++	u8 **mbssid_elem_offset;
++
++	/**
++	 * ema - Enhanced MBSSID advertisements support.
++	 */
++	bool ema;
++
+ };
+ 
+ struct wpa_driver_mesh_bss_params {
+@@ -2197,6 +2234,11 @@ struct wpa_driver_capa {
+ 
+ 	/* Maximum number of supported CSA counters */
+ 	u16 max_csa_counters;
++
++	/* Maximum number of interfaces supported for MBSSID advertisements */
++	u8 mbssid_max_interfaces;
++	/* Maximum profile periodicity for enhanced MBSSID advertisements */
++	u8 ema_max_periodicity;
+ };
+ 
+ 
+diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
+index 6c65901..3753409 100644
+--- a/src/drivers/driver_nl80211.c
++++ b/src/drivers/driver_nl80211.c
+@@ -4540,6 +4540,55 @@ static int nl80211_unsol_bcast_probe_resp(struct i802_bss *bss,
+ 	nla_nest_end(msg, attr);
+ 	return 0;
+ }
++
++
++static int nl80211_mbssid(struct nl_msg *msg,
++			 struct wpa_driver_ap_params *params)
++{
++	struct nlattr *config, *elems;
++	int ifidx;
++
++	if (!params->mbssid_tx_iface)
++		return 0;
++
++	config = nla_nest_start(msg, NL80211_ATTR_MBSSID_CONFIG);
++	if (!config)
++		return -1;
++
++	nla_put_u8(msg, NL80211_MBSSID_CONFIG_ATTR_INDEX, params->mbssid_index);
++	if (params->mbssid_tx_iface) {
++		ifidx = if_nametoindex(params->mbssid_tx_iface);
++		if (ifidx <= 0)
++			return -1;
++		nla_put_u32(msg,
++			    NL80211_MBSSID_CONFIG_ATTR_TX_IFINDEX,
++			    ifidx);
++	}
++
++	if (params->ema)
++		nla_put_flag(msg, NL80211_MBSSID_CONFIG_ATTR_EMA);
++
++	nla_nest_end(msg, config);
++
++	if (params->mbssid_elem_count && params->mbssid_elem_len &&
++	    params->mbssid_elem_offset && *params->mbssid_elem_offset) {
++		u8 i, **offs = params->mbssid_elem_offset;
++
++		elems = nla_nest_start(msg, NL80211_ATTR_MBSSID_ELEMS);
++		if (!elems)
++			return -1;
++
++		for (i = 0; i < params->mbssid_elem_count - 1; i++)
++			nla_put(msg, i + 1, offs[i + 1] - offs[i], offs[i]);
++
++		nla_put(msg, i + 1,
++			*offs + params->mbssid_elem_len - offs[i],
++			offs[i]);
++
++		nla_nest_end(msg, elems);
++	}
++	return 0;
++}
+ #endif /* CONFIG_IEEE80211AX */
+ 
+ 
+@@ -4838,6 +4887,9 @@ static int wpa_driver_nl80211_set_ap(void *priv,
+ 	if (params->unsol_bcast_probe_resp_interval &&
+ 	    nl80211_unsol_bcast_probe_resp(bss, msg, params) < 0)
+ 		goto fail;
++
++	if (nl80211_mbssid(msg, params) < 0)
++		goto fail;
+ #endif /* CONFIG_IEEE80211AX */
+ 
+ #ifdef CONFIG_SAE
+diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c
+index 06a52db..d8078bc 100644
+--- a/src/drivers/driver_nl80211_capa.c
++++ b/src/drivers/driver_nl80211_capa.c
+@@ -857,6 +857,30 @@ err:
+ }
+ 
+ 
++static void wiphy_info_mbssid(struct wpa_driver_capa *cap, struct nlattr *attr)
++{
++	struct nlattr *config[NL80211_MBSSID_CONFIG_ATTR_MAX + 1];
++
++	if (nla_parse_nested(config, NL80211_MBSSID_CONFIG_ATTR_MAX, attr,
++			     NULL))
++		return;
++
++	if (!config[NL80211_MBSSID_CONFIG_ATTR_MAX_INTERFACES])
++		return;
++
++	cap->mbssid_max_interfaces =
++		nla_get_u8(config[NL80211_MBSSID_CONFIG_ATTR_MAX_INTERFACES]);
++
++	if (config[NL80211_MBSSID_CONFIG_ATTR_MAX_EMA_PROFILE_PERIODICITY])
++		cap->ema_max_periodicity =
++		nla_get_u8(config[NL80211_MBSSID_CONFIG_ATTR_MAX_EMA_PROFILE_PERIODICITY]);
++
++	wpa_printf(MSG_DEBUG,
++		   "multiple_bssid: max interfaces %u, max profile periodicity %u\n",
++		   cap->mbssid_max_interfaces, cap->ema_max_periodicity);
++}
++
++
+ static int wiphy_info_handler(struct nl_msg *msg, void *arg)
+ {
+ 	struct nlattr *tb[NL80211_ATTR_MAX + 1];
+@@ -1106,6 +1130,9 @@ static int wiphy_info_handler(struct nl_msg *msg, void *arg)
+ 	if (tb[NL80211_ATTR_WIPHY_SELF_MANAGED_REG])
+ 		capa->flags |= WPA_DRIVER_FLAGS_SELF_MANAGED_REGULATORY;
+ 
++	if (tb[NL80211_ATTR_MBSSID_CONFIG])
++		wiphy_info_mbssid(capa, tb[NL80211_ATTR_MBSSID_CONFIG]);
++
+ 	return NL_SKIP;
+ }
+ 
+-- 
+2.18.0
+
diff --git a/recipes-wifi/hostapd/files/patches/patches.inc b/recipes-wifi/hostapd/files/patches/patches.inc
index 872f470..48bd493 100644
--- a/recipes-wifi/hostapd/files/patches/patches.inc
+++ b/recipes-wifi/hostapd/files/patches/patches.inc
@@ -78,7 +78,10 @@
     file://mtk-0014-hostapd-mtk-Add-the-broadcast-destination-address-of.patch \
     file://mtk-0015-hostapd-mtk-Add-vendor-command-attribute-for-RTS-BW-.patch \
     file://mtk-0016-hostapd-mtk-6G-band-does-not-require-DFS.patch \
+    file://mtk-0016-hostapd-mtk-Add-available-color-bitmap.patch \
     file://mtk-0017-hostapd-mtk-Fix-sending-wrong-VHT-operation-IE-in-CS.patch \
     file://mtk-0018-hostapd-mtk-Add-sta-assisted-DFS-state-update-mechan.patch \
     file://mtk-0019-hostapd-mtk-Fix-auto-ht-issue-when-switching-to-DFS-.patch \
+    file://mtk-0020-hostapd-mtk-Mark-DFS-channel-as-available-for-CSA.patch \
+    file://mtk-0020-hostapd-mtk-add-11v_mbss-and-ema-support.patch \
     "
diff --git a/recipes-wifi/hostapd/files/src/src/ap/ubus.c b/recipes-wifi/hostapd/files/src/src/ap/ubus.c
index 5001225..ddd8644 100644
--- a/recipes-wifi/hostapd/files/src/src/ap/ubus.c
+++ b/recipes-wifi/hostapd/files/src/src/ap/ubus.c
@@ -1084,6 +1084,8 @@
 	}
 
 	__hostapd_bss_mgmt_enable(hapd, flags);
+
+	return 0;
 }
 
 
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/319-wifi-mac80211-mesh-fast-xmit-support.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/319-wifi-mac80211-mesh-fast-xmit-support.patch
index b802960..12e9cf5 100644
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/319-wifi-mac80211-mesh-fast-xmit-support.patch
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/319-wifi-mac80211-mesh-fast-xmit-support.patch
@@ -90,7 +90,7 @@
  #include "driver-ops.h"
  
  static int mesh_allocated;
-@@ -698,6 +699,102 @@ ieee80211_mesh_update_bss_params(struct
+@@ -698,6 +699,95 @@ ieee80211_mesh_update_bss_params(struct
  			__le32_to_cpu(he_oper->he_oper_params);
  }
  
@@ -137,8 +137,7 @@
 +	if (!entry)
 +		return false;
 +
-+	if (skb_headroom(skb) + 2 * ETH_ALEN < entry->hdrlen +
-+					       entry->fast_tx.hdr_len)
++	if (skb_headroom(skb) < entry->hdrlen + entry->fast_tx.hdr_len)
 +		return false;
 +
 +	sta = rcu_dereference(entry->mpath->next_hop);
@@ -154,16 +153,9 @@
 +			tid_tx->last_tx = jiffies;
 +	}
 +
-+	/* If the skb is shared we need to obtain our own copy */
-+	if (skb_shared(skb)) {
-+		struct sk_buff *oskb = skb;
-+
-+		skb = skb_clone(skb, GFP_ATOMIC);
-+		if (!skb)
-+			return false;
-+
-+		kfree_skb(oskb);
-+	}
++	skb = skb_share_check(skb, GFP_ATOMIC);
++	if (!skb)
++		return true;
 +
 +	skb_set_queue_mapping(skb, ieee80211_select_queue(sdata, sta, skb));
 +
@@ -184,6 +176,7 @@
 +	if (copy_sa)
 +	    ether_addr_copy(meshhdr->eaddr2, sa);
 +
++	skb_push(skb, 2 * ETH_ALEN);
 +	__ieee80211_xmit_fast(sdata, sta, &entry->fast_tx, skb, tid_tx,
 +			      entry->mpath->dst, sdata->vif.addr);
 +
@@ -193,7 +186,7 @@
  /**
   * ieee80211_fill_mesh_addresses - fill addresses of a locally originated mesh frame
   * @hdr:	802.11 frame header
-@@ -780,6 +877,8 @@ static void ieee80211_mesh_housekeeping(
+@@ -780,6 +870,8 @@ static void ieee80211_mesh_housekeeping(
  	changed = mesh_accept_plinks_update(sdata);
  	ieee80211_mbss_info_change_notify(sdata, changed);
  
@@ -566,7 +559,7 @@
 +	if (!entry)
 +		goto unlock_sta;
 +
-+	spin_lock_bh(&cache->walk_lock);
++	spin_lock(&cache->walk_lock);
 +	prev = rhashtable_lookup_get_insert_fast(&cache->rht,
 +						 &entry->rhash,
 +						 fast_tx_rht_params);
@@ -589,7 +582,7 @@
 +	hlist_add_head(&entry->walk_list, &cache->walk_head);
 +
 +unlock_cache:
-+	spin_unlock_bh(&cache->walk_lock);
++	spin_unlock(&cache->walk_lock);
 +unlock_sta:
 +	spin_unlock_bh(&sta->lock);
 +}
@@ -771,28 +764,20 @@
  {
  	struct ieee80211_local *local = sdata->local;
  	struct ieee80211_hdr *hdr = (void *)fast_tx->hdr;
-@@ -3645,8 +3652,6 @@ static void __ieee80211_xmit_fast(struct
- 	struct ieee80211_tx_data tx;
+@@ -3646,7 +3653,6 @@ static void __ieee80211_xmit_fast(struct
  	ieee80211_tx_result r;
  	int hw_headroom = sdata->local->hw.extra_tx_headroom;
--	int extra_head = fast_tx->hdr_len - (ETH_HLEN - 2);
+ 	int extra_head = fast_tx->hdr_len - (ETH_HLEN - 2);
 -	struct ethhdr eth;
  
  	skb = skb_share_check(skb, GFP_ATOMIC);
  	if (unlikely(!skb))
-@@ -3661,16 +3666,15 @@ static void __ieee80211_xmit_fast(struct
- 	 * more room than we already have in 'extra_head'
- 	 */
- 	if (unlikely(ieee80211_skb_resize(sdata, skb,
--					  max_t(int, extra_head + hw_headroom -
-+					  max_t(int, fast_tx->hdr_len + hw_headroom -
- 						     skb_headroom(skb), 0),
+@@ -3666,11 +3672,10 @@ static void __ieee80211_xmit_fast(struct
  					  ENCRYPT_NO)))
  		goto free;
  
 -	memcpy(&eth, skb->data, ETH_HLEN - 2);
--	hdr = skb_push(skb, extra_head);
-+	hdr = skb_push(skb, fast_tx->hdr_len);
+ 	hdr = skb_push(skb, extra_head);
  	memcpy(skb->data, fast_tx->hdr, fast_tx->hdr_len);
 -	memcpy(skb->data + fast_tx->da_offs, eth.h_dest, ETH_ALEN);
 -	memcpy(skb->data + fast_tx->sa_offs, eth.h_source, ETH_ALEN);
@@ -801,16 +786,17 @@
  
  	info = IEEE80211_SKB_CB(skb);
  	memset(info, 0, sizeof(*info));
-@@ -3689,7 +3693,7 @@ static void __ieee80211_xmit_fast(struct
+@@ -3689,7 +3694,8 @@ static void __ieee80211_xmit_fast(struct
  #endif
  
  	if (hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_QOS_DATA)) {
 -		tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
 +		u8 tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
++
  		*ieee80211_get_qos_ctl(hdr) = tid;
  	}
  
-@@ -3732,6 +3736,7 @@ static bool ieee80211_xmit_fast(struct i
+@@ -3732,6 +3738,7 @@ static bool ieee80211_xmit_fast(struct i
  	struct ieee80211_hdr *hdr = (void *)fast_tx->hdr;
  	struct tid_ampdu_tx *tid_tx = NULL;
  	struct sk_buff *next;
@@ -818,17 +804,16 @@
  	u8 tid = IEEE80211_NUM_TIDS;
  
  	/* control port protocol needs a lot of special handling */
-@@ -3757,14 +3762,18 @@ static bool ieee80211_xmit_fast(struct i
+@@ -3757,6 +3764,8 @@ static bool ieee80211_xmit_fast(struct i
  		}
  	}
  
 +	memcpy(&eth, skb->data, ETH_HLEN - 2);
 +
  	/* after this point (skb is modified) we cannot return false */
-+	skb_pull(skb, ETH_HLEN - 2);
  	skb = ieee80211_tx_skb_fixup(skb, ieee80211_sdata_netdev_features(sdata));
  	if (!skb)
- 		return true;
+@@ -3764,7 +3773,8 @@ static bool ieee80211_xmit_fast(struct i
  
  	skb_list_walk_safe(skb, skb, next) {
  		skb_mark_not_on_list(skb);
@@ -838,7 +823,7 @@
  	}
  
  	return true;
-@@ -4244,8 +4253,15 @@ void __ieee80211_subif_start_xmit(struct
+@@ -4244,8 +4254,15 @@ void __ieee80211_subif_start_xmit(struct
  		return;
  	}
  
@@ -854,7 +839,7 @@
  	if (ieee80211_lookup_ra_sta(sdata, skb, &sta))
  		goto out_free;
  
-@@ -4255,8 +4271,6 @@ void __ieee80211_subif_start_xmit(struct
+@@ -4255,8 +4272,6 @@ void __ieee80211_subif_start_xmit(struct
  	skb_set_queue_mapping(skb, ieee80211_select_queue(sdata, sta, skb));
  	ieee80211_aggr_check(sdata, sta, skb);
  
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/320-wifi-mac80211-use-mesh-header-cache-to-speed-up-mesh.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/320-wifi-mac80211-use-mesh-header-cache-to-speed-up-mesh.patch
index 3b0bae6..7ec8f3d 100644
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/320-wifi-mac80211-use-mesh-header-cache-to-speed-up-mesh.patch
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/320-wifi-mac80211-use-mesh-header-cache-to-speed-up-mesh.patch
@@ -64,7 +64,7 @@
 +
 +	skb->dev = sdata->dev;
 +	memcpy(&eth, skb->data, ETH_HLEN - 2);
-+	skb_pull(skb, sizeof(eth));
++	skb_pull(skb, 2);
 +	__ieee80211_xmit_fast(sdata, sta, &entry->fast_tx, skb, tid_tx,
 +			      eth.h_dest, eth.h_source);
 +	IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, fwded_unicast);
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/323-wifi-mac80211-Add-VHT-MU-MIMO-related-flags-in-ieee8.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/323-wifi-mac80211-Add-VHT-MU-MIMO-related-flags-in-ieee8.patch
new file mode 100644
index 0000000..2310593
--- /dev/null
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/323-wifi-mac80211-Add-VHT-MU-MIMO-related-flags-in-ieee8.patch
@@ -0,0 +1,68 @@
+From: Muna Sinada <quic_msinada@quicinc.com>
+Date: Wed, 5 Oct 2022 14:54:45 -0700
+Subject: [PATCH] wifi: mac80211: Add VHT MU-MIMO related flags in
+ ieee80211_bss_conf
+
+Adding flags for SU Beamformer, SU Beamformee, MU Beamformer and
+MU Beamformee for VHT. This is utilized to pass MU-MIMO
+configurations from user space to driver in AP mode.
+
+Signed-off-by: Muna Sinada <quic_msinada@quicinc.com>
+Link: https://lore.kernel.org/r/1665006886-23874-1-git-send-email-quic_msinada@quicinc.com
+[fixed indentation, removed redundant !!]
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+---
+
+--- a/include/net/mac80211.h
++++ b/include/net/mac80211.h
+@@ -653,6 +653,14 @@ struct ieee80211_fils_discovery {
+  *	write-protected by sdata_lock and local->mtx so holding either is fine
+  *	for read access.
+  * @color_change_color: the bss color that will be used after the change.
++ * @vht_su_beamformer: in AP mode, does this BSS support operation as an VHT SU
++ *	beamformer
++ * @vht_su_beamformee: in AP mode, does this BSS support operation as an VHT SU
++ *	beamformee
++ * @vht_mu_beamformer: in AP mode, does this BSS support operation as an VHT MU
++ *	beamformer
++ * @vht_mu_beamformee: in AP mode, does this BSS support operation as an VHT MU
++ *	beamformee
+  */
+ struct ieee80211_bss_conf {
+ 	const u8 *bssid;
+@@ -726,6 +734,11 @@ struct ieee80211_bss_conf {
+ 
+ 	bool color_change_active;
+ 	u8 color_change_color;
++
++	bool vht_su_beamformer;
++	bool vht_su_beamformee;
++	bool vht_mu_beamformer;
++	bool vht_mu_beamformee;
+ };
+ 
+ /**
+--- a/net/mac80211/cfg.c
++++ b/net/mac80211/cfg.c
+@@ -1251,6 +1251,21 @@ static int ieee80211_start_ap(struct wip
+ 	prev_beacon_int = link_conf->beacon_int;
+ 	link_conf->beacon_int = params->beacon_interval;
+ 
++	if (params->vht_cap) {
++		link_conf->vht_su_beamformer =
++			params->vht_cap->vht_cap_info &
++				cpu_to_le32(IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE);
++		link_conf->vht_su_beamformee =
++			params->vht_cap->vht_cap_info &
++				cpu_to_le32(IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE);
++		link_conf->vht_mu_beamformer =
++			params->vht_cap->vht_cap_info &
++				cpu_to_le32(IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE);
++		link_conf->vht_mu_beamformee =
++			params->vht_cap->vht_cap_info &
++				cpu_to_le32(IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE);
++	}
++
+ 	if (params->he_cap && params->he_oper) {
+ 		link_conf->he_support = true;
+ 		link_conf->htc_trig_based_pkt_ext =
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/324-wifi-mac80211-Add-HE-MU-MIMO-related-flags-in-ieee80.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/324-wifi-mac80211-Add-HE-MU-MIMO-related-flags-in-ieee80.patch
new file mode 100644
index 0000000..a3c4453
--- /dev/null
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/324-wifi-mac80211-Add-HE-MU-MIMO-related-flags-in-ieee80.patch
@@ -0,0 +1,68 @@
+From: Muna Sinada <quic_msinada@quicinc.com>
+Date: Wed, 5 Oct 2022 14:54:46 -0700
+Subject: [PATCH] wifi: mac80211: Add HE MU-MIMO related flags in
+ ieee80211_bss_conf
+
+Adding flags for SU Beamformer, SU Beamformee, MU Beamformer and Full
+Bandwidth UL MU-MIMO for HE. This is utilized to pass MU-MIMO
+configurations from user space to driver in AP mode.
+
+Signed-off-by: Muna Sinada <quic_msinada@quicinc.com>
+Link: https://lore.kernel.org/r/1665006886-23874-2-git-send-email-quic_msinada@quicinc.com
+[fixed indentation, removed redundant !!]
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+---
+
+--- a/include/net/mac80211.h
++++ b/include/net/mac80211.h
+@@ -661,6 +661,15 @@ struct ieee80211_fils_discovery {
+  *	beamformer
+  * @vht_mu_beamformee: in AP mode, does this BSS support operation as an VHT MU
+  *	beamformee
++ * @he_su_beamformer: in AP-mode, does this BSS support operation as an HE SU
++ *	beamformer
++ * @he_su_beamformee: in AP-mode, does this BSS support operation as an HE SU
++ *	beamformee
++ * @he_mu_beamformer: in AP-mode, does this BSS support operation as an HE MU
++ *	beamformer
++ * @he_full_ul_mumimo: does this BSS support the reception (AP) or transmission
++ *	(non-AP STA) of an HE TB PPDU on an RU that spans the entire PPDU
++ *	bandwidth
+  */
+ struct ieee80211_bss_conf {
+ 	const u8 *bssid;
+@@ -739,6 +748,10 @@ struct ieee80211_bss_conf {
+ 	bool vht_su_beamformee;
+ 	bool vht_mu_beamformer;
+ 	bool vht_mu_beamformee;
++	bool he_su_beamformer;
++	bool he_su_beamformee;
++	bool he_mu_beamformer;
++	bool he_full_ul_mumimo;
+ };
+ 
+ /**
+--- a/net/mac80211/cfg.c
++++ b/net/mac80211/cfg.c
+@@ -1280,6 +1280,21 @@ static int ieee80211_start_ap(struct wip
+ 			changed |= BSS_CHANGED_HE_BSS_COLOR;
+ 	}
+ 
++	if (params->he_cap) {
++		link_conf->he_su_beamformer =
++			params->he_cap->phy_cap_info[3] &
++				IEEE80211_HE_PHY_CAP3_SU_BEAMFORMER;
++		link_conf->he_su_beamformee =
++			params->he_cap->phy_cap_info[4] &
++				IEEE80211_HE_PHY_CAP4_SU_BEAMFORMEE;
++		link_conf->he_mu_beamformer =
++			params->he_cap->phy_cap_info[4] &
++				IEEE80211_HE_PHY_CAP4_MU_BEAMFORMER;
++		link_conf->he_full_ul_mumimo =
++			params->he_cap->phy_cap_info[2] &
++				IEEE80211_HE_PHY_CAP2_UL_MU_FULL_MU_MIMO;
++	}
++
+ 	if (sdata->vif.type == NL80211_IFTYPE_AP &&
+ 	    params->mbssid_config.tx_wdev) {
+ 		err = ieee80211_set_ap_mbssid_options(sdata,
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/325-wifi-mac80211-introduce-ieee80211_refresh_tx_agg_ses.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/325-wifi-mac80211-introduce-ieee80211_refresh_tx_agg_ses.patch
new file mode 100644
index 0000000..f6d3d78
--- /dev/null
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/325-wifi-mac80211-introduce-ieee80211_refresh_tx_agg_ses.patch
@@ -0,0 +1,60 @@
+From: Ryder Lee <ryder.lee@mediatek.com>
+Date: Sat, 18 Feb 2023 01:50:05 +0800
+Subject: [PATCH] wifi: mac80211: introduce
+ ieee80211_refresh_tx_agg_session_timer()
+
+This allows low level drivers to refresh the tx agg session timer, based on
+querying stats from the firmware usually. Especially for some mt76 devices
+support .net_fill_forward_path would bypass mac80211, which leads to tx BA
+session timeout for certain clients.
+
+Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
+---
+
+--- a/include/net/mac80211.h
++++ b/include/net/mac80211.h
+@@ -5968,6 +5968,18 @@ void ieee80211_queue_delayed_work(struct
+ 				  unsigned long delay);
+ 
+ /**
++ * ieee80211_refresh_tx_agg_session_timer - Refresh a tx agg session timer.
++ * @sta: the station for which to start a BA session
++ * @tid: the TID to BA on.
++ *
++ * This function allows low level driver to refresh tx agg session timer
++ * to maintain BA session, the session level will still be managed by the
++ * mac80211.
++ */
++void ieee80211_refresh_tx_agg_session_timer(struct ieee80211_sta *sta,
++					    u16 tid);
++
++/**
+  * ieee80211_start_tx_ba_session - Start a tx Block Ack session.
+  * @sta: the station for which to start a BA session
+  * @tid: the TID to BA on.
+--- a/net/mac80211/agg-tx.c
++++ b/net/mac80211/agg-tx.c
+@@ -552,6 +552,23 @@ void ieee80211_tx_ba_session_handle_star
+ 	ieee80211_send_addba_with_timeout(sta, tid_tx);
+ }
+ 
++void ieee80211_refresh_tx_agg_session_timer(struct ieee80211_sta *pubsta,
++					    u16 tid)
++{
++	struct sta_info *sta = container_of(pubsta, struct sta_info, sta);
++	struct tid_ampdu_tx *tid_tx;
++
++	if (WARN_ON_ONCE(tid >= IEEE80211_NUM_TIDS))
++		return;
++
++	tid_tx = rcu_dereference(sta->ampdu_mlme.tid_tx[tid]);
++	if (!tid_tx)
++		return;
++
++	tid_tx->last_tx = jiffies;
++}
++EXPORT_SYMBOL(ieee80211_refresh_tx_agg_session_timer);
++
+ /*
+  * After accepting the AddBA Response we activated a timer,
+  * resetting it after each frame that we send.
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/326-wifi-mac80211-add-mesh-fast-rx-support.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/326-wifi-mac80211-add-mesh-fast-rx-support.patch
new file mode 100644
index 0000000..b2b94d0
--- /dev/null
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/326-wifi-mac80211-add-mesh-fast-rx-support.patch
@@ -0,0 +1,77 @@
+From: Felix Fietkau <nbd@nbd.name>
+Date: Thu, 2 Mar 2023 13:52:29 +0100
+Subject: [PATCH] wifi: mac80211: add mesh fast-rx support
+
+This helps bring down rx CPU usage by avoiding calls to the rx handlers in
+the slow path. Supports forwarding and local rx, including A-MSDU.
+
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+---
+
+--- a/net/mac80211/rx.c
++++ b/net/mac80211/rx.c
+@@ -4572,6 +4572,12 @@ void ieee80211_check_fast_rx(struct sta_
+ 		}
+ 
+ 		break;
++	case NL80211_IFTYPE_MESH_POINT:
++		fastrx.expected_ds_bits = cpu_to_le16(IEEE80211_FCTL_FROMDS |
++						      IEEE80211_FCTL_TODS);
++		fastrx.da_offs = offsetof(struct ieee80211_hdr, addr3);
++		fastrx.sa_offs = offsetof(struct ieee80211_hdr, addr4);
++		break;
+ 	default:
+ 		goto clear;
+ 	}
+@@ -4780,6 +4786,7 @@ static bool ieee80211_invoke_fast_rx(str
+ 	struct sk_buff *skb = rx->skb;
+ 	struct ieee80211_hdr *hdr = (void *)skb->data;
+ 	struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
++	static ieee80211_rx_result res;
+ 	int orig_len = skb->len;
+ 	int hdrlen = ieee80211_hdrlen(hdr->frame_control);
+ 	int snap_offs = hdrlen;
+@@ -4841,7 +4848,8 @@ static bool ieee80211_invoke_fast_rx(str
+ 		snap_offs += IEEE80211_CCMP_HDR_LEN;
+ 	}
+ 
+-	if (!(status->rx_flags & IEEE80211_RX_AMSDU)) {
++	if (!ieee80211_vif_is_mesh(&rx->sdata->vif) &&
++	    !(status->rx_flags & IEEE80211_RX_AMSDU)) {
+ 		if (!pskb_may_pull(skb, snap_offs + sizeof(*payload)))
+ 			return false;
+ 
+@@ -4880,13 +4888,29 @@ static bool ieee80211_invoke_fast_rx(str
+ 	/* do the header conversion - first grab the addresses */
+ 	ether_addr_copy(addrs.da, skb->data + fast_rx->da_offs);
+ 	ether_addr_copy(addrs.sa, skb->data + fast_rx->sa_offs);
+-	skb_postpull_rcsum(skb, skb->data + snap_offs,
+-			   sizeof(rfc1042_header) + 2);
+-	/* remove the SNAP but leave the ethertype */
+-	skb_pull(skb, snap_offs + sizeof(rfc1042_header));
++	if (ieee80211_vif_is_mesh(&rx->sdata->vif)) {
++	    skb_pull(skb, snap_offs - 2);
++	    put_unaligned_be16(skb->len - 2, skb->data);
++	} else {
++	    skb_postpull_rcsum(skb, skb->data + snap_offs,
++			       sizeof(rfc1042_header) + 2);
++
++	    /* remove the SNAP but leave the ethertype */
++	    skb_pull(skb, snap_offs + sizeof(rfc1042_header));
++	}
+ 	/* push the addresses in front */
+ 	memcpy(skb_push(skb, sizeof(addrs)), &addrs, sizeof(addrs));
+ 
++	res = ieee80211_rx_mesh_data(rx->sdata, rx->sta, rx->skb);
++	switch (res) {
++	case RX_QUEUED:
++		return true;
++	case RX_CONTINUE:
++		break;
++	default:
++		goto drop;
++	}
++
+ 	ieee80211_rx_8023(rx, fast_rx, orig_len);
+ 
+ 	return true;
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0008-mac80211-mtk-remove-timerout-handle-for-ax210-iot-is.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0008-mac80211-mtk-remove-timerout-handle-for-ax210-iot-is.patch
deleted file mode 100644
index bf8111a..0000000
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0008-mac80211-mtk-remove-timerout-handle-for-ax210-iot-is.patch
+++ /dev/null
@@ -1,35 +0,0 @@
-From 41ef202d35486326d8fc52466ef4ad6f7aa98e34 Mon Sep 17 00:00:00 2001
-From: Evelyn Tsai <evelyn.tsai@mediatek.com>
-Date: Wed, 19 Oct 2022 13:49:21 +0800
-Subject: [PATCH 08/16] mac80211: mtk: remove timerout handle for ax210 iot
- issue
-
-Signed-off-by: Evelyn Tsai <evelyn.tsai@mediatek.com>
----
- net/mac80211/agg-tx.c | 7 +++----
- 1 file changed, 3 insertions(+), 4 deletions(-)
- mode change 100644 => 100755 net/mac80211/agg-tx.c
-
-diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c
-old mode 100644
-new mode 100755
-index 07c892a..1f46561
---- a/net/mac80211/agg-tx.c
-+++ b/net/mac80211/agg-tx.c
-@@ -568,10 +568,9 @@ static void sta_tx_agg_session_timer_expired(struct timer_list *t)
- 	}
- 
- 	timeout = tid_tx->last_tx + TU_TO_JIFFIES(tid_tx->timeout);
--	if (time_is_after_jiffies(timeout)) {
--		mod_timer(&tid_tx->session_timer, timeout);
--		return;
--	}
-+	/* remove timerout handle for ax210 iot issue */
-+	mod_timer(&tid_tx->session_timer, timeout);
-+	return;
- 
- 	ht_dbg(sta->sdata, "tx session timer expired on %pM tid %d\n",
- 	       sta->sta.addr, tid);
--- 
-2.25.1
-
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0012-mac80211-mtk-check-the-control-channel-before-downgr.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0011-mac80211-mtk-check-the-control-channel-before-downgr.patch
similarity index 92%
rename from recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0012-mac80211-mtk-check-the-control-channel-before-downgr.patch
rename to recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0011-mac80211-mtk-check-the-control-channel-before-downgr.patch
index 23b9ccb..18f434f 100644
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0012-mac80211-mtk-check-the-control-channel-before-downgr.patch
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0011-mac80211-mtk-check-the-control-channel-before-downgr.patch
@@ -1,7 +1,7 @@
-From cc6f40e49bfdee7c824d4b158a060c2dc42ded4c Mon Sep 17 00:00:00 2001
+From 0ed0a8f524a3288603f9eb298dcdeff7ae745e39 Mon Sep 17 00:00:00 2001
 From: Evelyn Tsai <evelyn.tsai@mediatek.com>
 Date: Fri, 16 Dec 2022 03:31:06 +0800
-Subject: [PATCH 12/16] mac80211: mtk: check the control channel before
+Subject: [PATCH 11/19] mac80211: mtk: check the control channel before
  downgrading the bandwidth
 
 ---
@@ -50,5 +50,5 @@
  		*conn_flags |=
  			ieee80211_chandef_downgrade(&chandef);
 -- 
-2.25.1
+2.18.0
 
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0011-mac80211-mtk-fix-the-issue-of-AP-and-STA-starting-on.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0011-mac80211-mtk-fix-the-issue-of-AP-and-STA-starting-on.patch
deleted file mode 100644
index c42a00f..0000000
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0011-mac80211-mtk-fix-the-issue-of-AP-and-STA-starting-on.patch
+++ /dev/null
@@ -1,261 +0,0 @@
-From 7dd3aacd15e5678a617001dc329cf942ed7f4298 Mon Sep 17 00:00:00 2001
-From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
-Date: Wed, 5 Oct 2022 19:13:43 +0800
-Subject: [PATCH 11/16] mac80211: mtk: fix the issue of AP and STA starting on
- DFS channel concurrently
-
-Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
----
- include/net/cfg80211.h       | 22 ++++++++++++++++++
- include/uapi/linux/nl80211.h |  2 +-
- net/mac80211/cfg.c           | 44 ++++++++++++++++++++++++++++++++++++
- net/mac80211/chan.c          |  2 +-
- net/wireless/chan.c          |  6 ++---
- net/wireless/nl80211.c       |  7 ++++++
- net/wireless/rdev-ops.h      | 16 +++++++++++++
- net/wireless/trace.h         | 15 ++++++++++++
- 8 files changed, 109 insertions(+), 5 deletions(-)
-
-diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
-index f9c2cc3..84e769b 100644
---- a/include/net/cfg80211.h
-+++ b/include/net/cfg80211.h
-@@ -888,6 +888,24 @@ cfg80211_chandef_identical(const struct cfg80211_chan_def *chandef1,
- 		chandef1->center_freq2 == chandef2->center_freq2);
- }
- 
-+/**
-+ * cfg80211_chan_fully_overlap - check if two channel are fully overlapped
-+ * @chandef1: first channel definition
-+ * @chandef2: second channel definition
-+ *
-+ * Return: %true if the channels are valid and fully overlapped, %false otherwise.
-+ */
-+static inline bool
-+cfg80211_chan_fully_overlap(const struct cfg80211_chan_def *chandef1,
-+			    const struct cfg80211_chan_def *chandef2)
-+{
-+	return (chandef1->center_freq1 != 0 &&
-+		chandef1->center_freq1 == chandef2->center_freq1 &&
-+		chandef1->width == chandef2->width &&
-+		chandef1->freq1_offset == chandef2->freq1_offset &&
-+		chandef1->center_freq2 == chandef2->center_freq2);
-+}
-+
- /**
-  * cfg80211_chandef_is_edmg - check if chandef represents an EDMG channel
-  *
-@@ -4642,6 +4660,8 @@ struct cfg80211_ops {
- 	int	(*del_link_station)(struct wiphy *wiphy, struct net_device *dev,
- 				    struct link_station_del_parameters *params);
- 	void	(*skip_cac)(struct wireless_dev *wdev);
-+	void	(*check_cac_skip)(struct wiphy *wiphy,
-+				  struct cfg80211_chan_def *chandef);
- };
- 
- /*
-@@ -5847,6 +5867,8 @@ struct wireless_dev {
- 		};
- 	} links[IEEE80211_MLD_MAX_NUM_LINKS];
- 	u16 valid_links;
-+
-+	bool start_disabled;
- };
- 
- static inline const u8 *wdev_address(struct wireless_dev *wdev)
-diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
-index 1293d30..db9d0a8 100644
---- a/include/uapi/linux/nl80211.h
-+++ b/include/uapi/linux/nl80211.h
-@@ -3283,7 +3283,7 @@ enum nl80211_attrs {
- 	NL80211_ATTR_WIPHY_ANTENNA_GAIN,
- 
- 	/* add attributes here, update the policy in nl80211.c */
--
-+	NL80211_ATTR_START_DISABLED = 999,
- 	__NL80211_ATTR_AFTER_LAST,
- 	NUM_NL80211_ATTR = __NL80211_ATTR_AFTER_LAST,
- 	NL80211_ATTR_MAX = __NL80211_ATTR_AFTER_LAST - 1
-diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
-index 5718c56..9da02d9 100644
---- a/net/mac80211/cfg.c
-+++ b/net/mac80211/cfg.c
-@@ -4889,6 +4889,49 @@ ieee80211_skip_cac(struct wireless_dev *wdev)
- 	}
- }
- 
-+static void
-+ieee80211_check_cac_skip(struct wiphy *wiphy,
-+			 struct cfg80211_chan_def *chandef)
-+{
-+	struct ieee80211_local *local = wiphy_priv(wiphy);
-+	struct ieee80211_sub_if_data *s1;
-+	struct ieee80211_sub_if_data *s2;
-+	struct ieee80211_sub_if_data *sdata_sta;
-+	struct ieee80211_if_managed *ifmgd;
-+	struct ieee80211_channel *chan;
-+	struct wireless_dev *wdev;
-+	unsigned int cac_time_ms;
-+
-+	mutex_lock(&local->mtx);
-+	/* Bypass AP's cac if there is a STA associated to the same DFS channel */
-+	list_for_each_entry(s1, &local->interfaces, list) {
-+		ifmgd = &s1->u.mgd;
-+
-+		if (s1->vif.type == NL80211_IFTYPE_STATION && ifmgd->associated)
-+			sdata_sta = s1;
-+		else
-+			continue;
-+
-+		list_for_each_entry(s2, &local->interfaces, list) {
-+			wdev = &s2->wdev;
-+			chan = wdev->links[0].ap.chandef.chan;
-+			if (chan) {
-+				if (!(chan->flags & IEEE80211_CHAN_RADAR))
-+					continue;
-+
-+				if (wdev->identifier != sdata_sta->wdev.identifier &&
-+				    chan->dfs_state == NL80211_DFS_USABLE && wdev->cac_started &&
-+				    cfg80211_chan_fully_overlap(&sdata_sta->vif.bss_conf.chandef,
-+								&s2->vif.bss_conf.chandef)) {
-+					ieee80211_skip_cac(wdev);
-+					sdata_info(s2, "Skip CAC on the associated STA's chan\n");
-+				}
-+			}
-+		}
-+	}
-+	mutex_unlock(&local->mtx);
-+}
-+
- const struct cfg80211_ops mac80211_config_ops = {
- 	.add_virtual_intf = ieee80211_add_iface,
- 	.del_virtual_intf = ieee80211_del_iface,
-@@ -5001,4 +5044,5 @@ const struct cfg80211_ops mac80211_config_ops = {
- 	.mod_link_station = ieee80211_mod_link_station,
- 	.del_link_station = ieee80211_del_link_station,
- 	.skip_cac = ieee80211_skip_cac,
-+	.check_cac_skip = ieee80211_check_cac_skip,
- };
-diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c
-index e72cf07..94496d7 100644
---- a/net/mac80211/chan.c
-+++ b/net/mac80211/chan.c
-@@ -567,7 +567,7 @@ bool ieee80211_is_radar_required(struct ieee80211_local *local)
- 
- 			link = rcu_dereference(sdata->link[link_id]);
- 
--			if (link && link->radar_required) {
-+			if (link && link->radar_required && sdata->wdev.cac_started) {
- 				rcu_read_unlock();
- 				return true;
- 			}
-diff --git a/net/wireless/chan.c b/net/wireless/chan.c
-index 29b5c2f..bf21f99 100644
---- a/net/wireless/chan.c
-+++ b/net/wireless/chan.c
-@@ -719,16 +719,16 @@ bool cfg80211_beaconing_iface_active(struct wireless_dev *wdev)
- 	case NL80211_IFTYPE_AP:
- 	case NL80211_IFTYPE_P2P_GO:
- 		for_each_valid_link(wdev, link) {
--			if (wdev->links[link].ap.beacon_interval)
-+			if (wdev->links[link].ap.beacon_interval || wdev->start_disabled)
- 				return true;
- 		}
- 		break;
- 	case NL80211_IFTYPE_ADHOC:
--		if (wdev->u.ibss.ssid_len)
-+		if (wdev->u.ibss.ssid_len || wdev->start_disabled)
- 			return true;
- 		break;
- 	case NL80211_IFTYPE_MESH_POINT:
--		if (wdev->u.mesh.id_len)
-+		if (wdev->u.mesh.id_len || wdev->start_disabled)
- 			return true;
- 		break;
- 	case NL80211_IFTYPE_STATION:
-diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
-index 202f802..cc8d4b2 100644
---- a/net/wireless/nl80211.c
-+++ b/net/wireless/nl80211.c
-@@ -789,6 +789,7 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
- 			NLA_POLICY_NESTED(nl80211_mbssid_config_policy),
- 	[NL80211_ATTR_MBSSID_ELEMS] = { .type = NLA_NESTED },
- 	[NL80211_ATTR_RADAR_BACKGROUND] = { .type = NLA_FLAG },
-+	[NL80211_ATTR_START_DISABLED] = { .type = NLA_FLAG },
- 	[NL80211_ATTR_AP_SETTINGS_FLAGS] = { .type = NLA_U32 },
- 	[NL80211_ATTR_EHT_CAPABILITY] =
- 		NLA_POLICY_BINARY_RANGE(NL80211_EHT_MIN_CAPABILITY_LEN, NL80211_EHT_MAX_CAPABILITY_LEN),
-@@ -5803,6 +5804,11 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
- 	if (wdev->links[link_id].ap.beacon_interval)
- 		return -EALREADY;
- 
-+	if (info->attrs[NL80211_ATTR_START_DISABLED]) {
-+		wdev->start_disabled = nla_get_flag(info->attrs[NL80211_ATTR_START_DISABLED]);
-+		return 0;
-+	}
-+
- 	/* these are required for START_AP */
- 	if (!info->attrs[NL80211_ATTR_BEACON_INTERVAL] ||
- 	    !info->attrs[NL80211_ATTR_DTIM_PERIOD] ||
-@@ -9846,6 +9852,7 @@ static int nl80211_start_radar_detection(struct sk_buff *skb,
- 		wdev->cac_started = true;
- 		wdev->cac_start_time = jiffies;
- 		wdev->cac_time_ms = cac_time_ms;
-+		err = rdev_check_cac_skip(rdev, &wdev->links[0].ap.chandef);
- 	}
- unlock:
- 	wiphy_unlock(wiphy);
-diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h
-index ce83152..ffa504a 100644
---- a/net/wireless/rdev-ops.h
-+++ b/net/wireless/rdev-ops.h
-@@ -1508,4 +1508,20 @@ rdev_skip_cac(struct cfg80211_registered_device *rdev,
- 	return 0;
- }
- 
-+static inline int
-+rdev_check_cac_skip(struct cfg80211_registered_device *rdev,
-+		    struct cfg80211_chan_def *chandef)
-+{
-+	struct wiphy *wiphy = &rdev->wiphy;
-+
-+	if (!rdev->ops->check_cac_skip)
-+		return -EOPNOTSUPP;
-+
-+	trace_rdev_check_cac_skip(wiphy, chandef);
-+	rdev->ops->check_cac_skip(wiphy, chandef);
-+	trace_rdev_return_void(wiphy);
-+
-+	return 0;
-+}
-+
- #endif /* __CFG80211_RDEV_OPS */
-diff --git a/net/wireless/trace.h b/net/wireless/trace.h
-index d3a98e8..72c8f0e 100644
---- a/net/wireless/trace.h
-+++ b/net/wireless/trace.h
-@@ -3913,6 +3913,21 @@ TRACE_EVENT(rdev_skip_cac,
- 	    TP_printk(WDEV_PR_FMT, WDEV_PR_ARG)
- );
- 
-+TRACE_EVENT(rdev_check_cac_skip,
-+	    TP_PROTO(struct wiphy *wiphy, struct cfg80211_chan_def *chandef),
-+
-+	    TP_ARGS(wiphy, chandef),
-+
-+	    TP_STRUCT__entry(WIPHY_ENTRY
-+			     CHAN_DEF_ENTRY),
-+
-+	    TP_fast_assign(WIPHY_ASSIGN;
-+			   CHAN_DEF_ASSIGN(chandef)),
-+
-+	    TP_printk(WIPHY_PR_FMT ", " CHAN_DEF_PR_FMT,
-+		      WIPHY_PR_ARG, CHAN_DEF_PR_ARG)
-+);
-+
- #endif /* !__RDEV_OPS_TRACE || TRACE_HEADER_MULTI_READ */
- 
- #undef TRACE_INCLUDE_PATH
--- 
-2.25.1
-
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0013-mac80211-mtk-fix-tx-amsdu-aggregation.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0012-mac80211-mtk-fix-tx-amsdu-aggregation.patch
similarity index 87%
rename from recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0013-mac80211-mtk-fix-tx-amsdu-aggregation.patch
rename to recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0012-mac80211-mtk-fix-tx-amsdu-aggregation.patch
index da3eede..6b5dab9 100644
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0013-mac80211-mtk-fix-tx-amsdu-aggregation.patch
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0012-mac80211-mtk-fix-tx-amsdu-aggregation.patch
@@ -1,7 +1,7 @@
-From e07d5401accc96f8380bf42ec454c9ea42255196 Mon Sep 17 00:00:00 2001
+From bb385f098e5f12c7ec0cc5032ac32a27f6713af6 Mon Sep 17 00:00:00 2001
 From: TomLiu <tomml.liu@mediatek.com>
 Date: Wed, 14 Dec 2022 00:26:50 -0800
-Subject: [PATCH 13/16] mac80211: mtk: fix tx amsdu aggregation
+Subject: [PATCH 12/19] mac80211: mtk: fix tx amsdu aggregation
 
 ---
  include/net/mac80211.h | 7 +++++++
@@ -9,10 +9,10 @@
  2 files changed, 11 insertions(+), 2 deletions(-)
 
 diff --git a/include/net/mac80211.h b/include/net/mac80211.h
-index dc4faea..286810b 100644
+index 5908ba3..ad5f217 100644
 --- a/include/net/mac80211.h
 +++ b/include/net/mac80211.h
-@@ -2864,6 +2864,13 @@ static inline void _ieee80211_hw_set(struct ieee80211_hw *hw,
+@@ -2890,6 +2890,13 @@ static inline void _ieee80211_hw_set(struct ieee80211_hw *hw,
  }
  #define ieee80211_hw_set(hw, flg)	_ieee80211_hw_set(hw, IEEE80211_HW_##flg)
  
@@ -27,7 +27,7 @@
   * struct ieee80211_scan_request - hw scan request
   *
 diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c
-index 1f46561..318c71e 100755
+index 65c35e4..6b7ec6e 100755
 --- a/net/mac80211/agg-tx.c
 +++ b/net/mac80211/agg-tx.c
 @@ -66,7 +66,8 @@ static void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata,
@@ -51,5 +51,5 @@
  	capab |= u16_encode_bits(tid, IEEE80211_ADDBA_PARAM_TID_MASK);
  	capab |= u16_encode_bits(agg_size, IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK);
 -- 
-2.25.1
+2.18.0
 
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0014-mac80211-mtk-add-fill-receive-path-ops-to-get-wed-id.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0013-mac80211-mtk-add-fill-receive-path-ops-to-get-wed-id.patch
similarity index 91%
rename from recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0014-mac80211-mtk-add-fill-receive-path-ops-to-get-wed-id.patch
rename to recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0013-mac80211-mtk-add-fill-receive-path-ops-to-get-wed-id.patch
index 277e231..8d2067f 100644
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0014-mac80211-mtk-add-fill-receive-path-ops-to-get-wed-id.patch
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0013-mac80211-mtk-add-fill-receive-path-ops-to-get-wed-id.patch
@@ -1,7 +1,7 @@
-From b36c1fd5e967880b025a8301aadbeb832a364639 Mon Sep 17 00:00:00 2001
+From 2a801c07d58b8c9b9d5e9049856c7ef7b504d841 Mon Sep 17 00:00:00 2001
 From: Sujuan Chen <sujuan.chen@mediatek.com>
 Date: Wed, 18 May 2022 15:10:22 +0800
-Subject: [PATCH 14/16] mac80211: mtk: add fill receive path ops to get wed idx
+Subject: [PATCH 13/19] mac80211: mtk: add fill receive path ops to get wed idx
 
 Signed-off-by: Sujuan Chen <sujuan.chen@mediatek.com>
 ---
@@ -13,10 +13,10 @@
  mode change 100644 => 100755 net/mac80211/util.c
 
 diff --git a/include/net/mac80211.h b/include/net/mac80211.h
-index 286810b..f68eb7d 100644
+index ad5f217..d1d7fc3 100644
 --- a/include/net/mac80211.h
 +++ b/include/net/mac80211.h
-@@ -1354,7 +1354,7 @@ ieee80211_tx_info_clear_status(struct ieee80211_tx_info *info)
+@@ -1380,7 +1380,7 @@ ieee80211_tx_info_clear_status(struct ieee80211_tx_info *info)
   * @RX_FLAG_AMPDU_EOF_BIT_KNOWN: The EOF value is known
   * @RX_FLAG_RADIOTAP_HE: HE radiotap data is present
   *	(&struct ieee80211_radiotap_he, mac80211 will fill in
@@ -25,7 +25,7 @@
   *	 - DATA3_DATA_MCS
   *	 - DATA3_DATA_DCM
   *	 - DATA3_CODING
-@@ -1362,7 +1362,7 @@ ieee80211_tx_info_clear_status(struct ieee80211_tx_info *info)
+@@ -1388,7 +1388,7 @@ ieee80211_tx_info_clear_status(struct ieee80211_tx_info *info)
   *	 - DATA5_DATA_BW_RU_ALLOC
   *	 - DATA6_NSTS
   *	 - DATA3_STBC
@@ -34,7 +34,7 @@
   *	from the RX info data, so leave those zeroed when building this data)
   * @RX_FLAG_RADIOTAP_HE_MU: HE MU radiotap data is present
   *	(&struct ieee80211_radiotap_he_mu)
-@@ -1924,6 +1924,12 @@ struct ieee80211_vif *wdev_to_ieee80211_vif(struct wireless_dev *wdev);
+@@ -1950,6 +1950,12 @@ struct ieee80211_vif *wdev_to_ieee80211_vif(struct wireless_dev *wdev);
   */
  struct wireless_dev *ieee80211_vif_to_wdev(struct ieee80211_vif *vif);
  
@@ -47,7 +47,7 @@
  /**
   * lockdep_vif_mutex_held - for lockdep checks on link poiners
   * @vif: the interface to check
-@@ -4193,6 +4199,8 @@ struct ieee80211_prep_tx_info {
+@@ -4219,6 +4225,8 @@ struct ieee80211_prep_tx_info {
   *	Note that a sta can also be inserted or removed with valid links,
   *	i.e. passed to @sta_add/@sta_state with sta->valid_links not zero.
   *	In fact, cannot change from having valid_links and not having them.
@@ -56,7 +56,7 @@
   */
  struct ieee80211_ops {
  	void (*tx)(struct ieee80211_hw *hw,
-@@ -4548,6 +4556,9 @@ struct ieee80211_ops {
+@@ -4574,6 +4582,9 @@ struct ieee80211_ops {
  				struct ieee80211_vif *vif,
  				struct ieee80211_sta *sta,
  				u16 old_links, u16 new_links);
@@ -153,5 +153,5 @@
   * Nothing should have been stuffed into the workqueue during
   * the suspend->resume cycle. Since we can't check each caller
 -- 
-2.25.1
+2.18.0
 
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0015-mac80211-mtk-register-.ndo_setup_tc-to-support-wifi2.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0014-mac80211-mtk-register-.ndo_setup_tc-to-support-wifi2.patch
similarity index 90%
rename from recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0015-mac80211-mtk-register-.ndo_setup_tc-to-support-wifi2.patch
rename to recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0014-mac80211-mtk-register-.ndo_setup_tc-to-support-wifi2.patch
index 60ab368..c32e2a0 100644
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0015-mac80211-mtk-register-.ndo_setup_tc-to-support-wifi2.patch
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0014-mac80211-mtk-register-.ndo_setup_tc-to-support-wifi2.patch
@@ -1,7 +1,7 @@
-From d0bf320b53011bf418e32991f899683280da184f Mon Sep 17 00:00:00 2001
+From a4cd8f81a63827647e88021cbcfc479f024221cb Mon Sep 17 00:00:00 2001
 From: Sujuan Chen <sujuan.chen@mediatek.com>
 Date: Fri, 23 Dec 2022 18:12:41 +0800
-Subject: [PATCH 15/16] mac80211: mtk: register .ndo_setup_tc to support
+Subject: [PATCH 14/19] mac80211: mtk: register .ndo_setup_tc to support
  wifi2wifi offload
 
 Signed-off-by: Sujuan Chen <sujuan.chen@mediatek.com>
@@ -11,10 +11,10 @@
  2 files changed, 31 insertions(+)
 
 diff --git a/include/net/mac80211.h b/include/net/mac80211.h
-index f68eb7d..c453b19 100644
+index d1d7fc3..1de9fad 100644
 --- a/include/net/mac80211.h
 +++ b/include/net/mac80211.h
-@@ -4201,6 +4201,8 @@ struct ieee80211_prep_tx_info {
+@@ -4227,6 +4227,8 @@ struct ieee80211_prep_tx_info {
   *	In fact, cannot change from having valid_links and not having them.
   * @net_fill_receive_path: Called from .ndo_fill_receive_path in order to
   *	get a path for hardware flow offloading
@@ -23,7 +23,7 @@
   */
  struct ieee80211_ops {
  	void (*tx)(struct ieee80211_hw *hw,
-@@ -4559,6 +4561,9 @@ struct ieee80211_ops {
+@@ -4585,6 +4587,9 @@ struct ieee80211_ops {
  	int (*net_fill_receive_path)(struct ieee80211_hw *hw,
  				     struct net_device_path_ctx *ctx,
  				     struct net_device_path *path);
@@ -85,5 +85,5 @@
  	dev->needs_free_netdev = true;
  	dev->priv_destructor = ieee80211_if_free;
 -- 
-2.25.1
+2.18.0
 
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0016-mac80211-mtk-fix-build-error-on-Linux-Kernel-5.4.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0015-mac80211-mtk-fix-build-error-on-Linux-Kernel-5.4.patch
similarity index 90%
rename from recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0016-mac80211-mtk-fix-build-error-on-Linux-Kernel-5.4.patch
rename to recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0015-mac80211-mtk-fix-build-error-on-Linux-Kernel-5.4.patch
index bb53403..3b2b718 100644
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0016-mac80211-mtk-fix-build-error-on-Linux-Kernel-5.4.patch
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0015-mac80211-mtk-fix-build-error-on-Linux-Kernel-5.4.patch
@@ -1,7 +1,7 @@
-From 12d2196bb600818a9fc9081037c509f2624b2d25 Mon Sep 17 00:00:00 2001
+From 83f826c468a145fb205cffe0f5fcc8d69143bb78 Mon Sep 17 00:00:00 2001
 From: Evelyn Tsai <evelyn.tsai@mediatek.com>
 Date: Tue, 13 Dec 2022 09:04:49 +0800
-Subject: [PATCH 16/16] mac80211: mtk: fix build error on Linux Kernel 5.4
+Subject: [PATCH 15/19] mac80211: mtk: fix build error on Linux Kernel 5.4
 
 ---
  include/linux/ieee80211.h          | 8 +++-----
@@ -66,10 +66,10 @@
  
  
 diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
-index cc8d4b2..8928a26 100644
+index 202f802..1035f74 100644
 --- a/net/wireless/nl80211.c
 +++ b/net/wireless/nl80211.c
-@@ -16448,9 +16448,11 @@ static const struct genl_ops nl80211_ops[] = {
+@@ -16441,9 +16441,11 @@ static const struct genl_ops nl80211_ops[] = {
  		/* can be retrieved by unprivileged users */
  		.internal_flags = IFLAGS(NL80211_FLAG_NEED_WIPHY),
  	},
@@ -81,7 +81,7 @@
  	{
  		.cmd = NL80211_CMD_SET_WIPHY,
  		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
-@@ -17287,8 +17289,10 @@ static struct genl_family nl80211_fam __genl_ro_after_init = {
+@@ -17280,8 +17282,10 @@ static struct genl_family nl80211_fam __genl_ro_after_init = {
  	.module = THIS_MODULE,
  	.ops = nl80211_ops,
  	.n_ops = ARRAY_SIZE(nl80211_ops),
@@ -93,5 +93,5 @@
  	.resv_start_op = NL80211_CMD_REMOVE_LINK_STA + 1,
  #endif
 -- 
-2.25.1
+2.18.0
 
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/subsys.inc b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/subsys.inc
index db2b20a..a2d8984 100644
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/subsys.inc
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/subsys.inc
@@ -27,6 +27,10 @@
     file://320-wifi-mac80211-use-mesh-header-cache-to-speed-up-mesh.patch \
     file://321-mac80211-fix-mesh-forwarding.patch \
     file://322-wifi-mac80211-fix-mesh-path-discovery-based-on-unica.patch \
+    file://323-wifi-mac80211-Add-VHT-MU-MIMO-related-flags-in-ieee8.patch \
+    file://324-wifi-mac80211-Add-HE-MU-MIMO-related-flags-in-ieee80.patch \
+    file://325-wifi-mac80211-introduce-ieee80211_refresh_tx_agg_ses.patch \
+    file://326-wifi-mac80211-add-mesh-fast-rx-support.patch \
     file://400-allow-ibss-mixed.patch \
     file://500-mac80211_configure_antenna_gain.patch \
     file://782-net-next-1-of-net-pass-the-dst-buffer-to-of_get_mac_address.patch \
@@ -37,15 +41,13 @@
     file://mtk-0005-mac80211-mtk-it-s-invalid-case-when-frag_threshold-i.patch \
     file://mtk-0006-mac80211-mtk-airtime_flags-depends-on-NL80211_EXT_FE.patch \
     file://mtk-0007-mac80211-mtk-add-support-for-runtime-set-inband-disc.patch \
-    file://mtk-0008-mac80211-mtk-remove-timerout-handle-for-ax210-iot-is.patch \
     file://mtk-0009-cfg80211-mtk-implement-DFS-status-show-cac-and-nop-s.patch \
     file://mtk-0010-mac80211-mtk-Set-TWT-Information-Frame-Disabled-bit-.patch \
-    file://mtk-0011-mac80211-mtk-fix-the-issue-of-AP-and-STA-starting-on.patch \
-    file://mtk-0012-mac80211-mtk-check-the-control-channel-before-downgr.patch \
-    file://mtk-0013-mac80211-mtk-fix-tx-amsdu-aggregation.patch \
-    file://mtk-0014-mac80211-mtk-add-fill-receive-path-ops-to-get-wed-id.patch \
-    file://mtk-0015-mac80211-mtk-register-.ndo_setup_tc-to-support-wifi2.patch \
-    file://mtk-0016-mac80211-mtk-fix-build-error-on-Linux-Kernel-5.4.patch \
+    file://mtk-0011-mac80211-mtk-check-the-control-channel-before-downgr.patch \
+    file://mtk-0012-mac80211-mtk-fix-tx-amsdu-aggregation.patch \
+    file://mtk-0013-mac80211-mtk-add-fill-receive-path-ops-to-get-wed-id.patch \
+    file://mtk-0014-mac80211-mtk-register-.ndo_setup_tc-to-support-wifi2.patch \
+    file://mtk-0015-mac80211-mtk-fix-build-error-on-Linux-Kernel-5.4.patch \
     file://mtk-0100-mac80211-mtk-add-EHT-BA1024-support.patch \
     file://mtk-0101-mac80211-mtk-add-rate-duration-for-EHT-rate.patch \
     "
diff --git a/recipes-wifi/linux-mac80211/files/patches/subsys/347-wifi-mac80211-introduce-ieee80211_refresh_tx_agg_ses.patch b/recipes-wifi/linux-mac80211/files/patches/subsys/347-wifi-mac80211-introduce-ieee80211_refresh_tx_agg_ses.patch
new file mode 100644
index 0000000..acd6c12
--- /dev/null
+++ b/recipes-wifi/linux-mac80211/files/patches/subsys/347-wifi-mac80211-introduce-ieee80211_refresh_tx_agg_ses.patch
@@ -0,0 +1,60 @@
+From: Ryder Lee <ryder.lee@mediatek.com>
+Date: Sat, 18 Feb 2023 01:50:05 +0800
+Subject: [PATCH] wifi: mac80211: introduce
+ ieee80211_refresh_tx_agg_session_timer()
+
+This allows low level drivers to refresh the tx agg session timer, based on
+querying stats from the firmware usually. Especially for some mt76 devices
+support .net_fill_forward_path would bypass mac80211, which leads to tx BA
+session timeout for certain clients.
+
+Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
+---
+
+--- a/include/net/mac80211.h
++++ b/include/net/mac80211.h
+@@ -5970,6 +5970,18 @@ void ieee80211_queue_delayed_work(struct
+ 				  unsigned long delay);
+ 
+ /**
++ * ieee80211_refresh_tx_agg_session_timer - Refresh a tx agg session timer.
++ * @sta: the station for which to start a BA session
++ * @tid: the TID to BA on.
++ *
++ * This function allows low level driver to refresh tx agg session timer
++ * to maintain BA session, the session level will still be managed by the
++ * mac80211.
++ */
++void ieee80211_refresh_tx_agg_session_timer(struct ieee80211_sta *sta,
++					    u16 tid);
++
++/**
+  * ieee80211_start_tx_ba_session - Start a tx Block Ack session.
+  * @sta: the station for which to start a BA session
+  * @tid: the TID to BA on.
+--- a/net/mac80211/agg-tx.c
++++ b/net/mac80211/agg-tx.c
+@@ -552,6 +552,23 @@ void ieee80211_tx_ba_session_handle_star
+ 	ieee80211_send_addba_with_timeout(sta, tid_tx);
+ }
+ 
++void ieee80211_refresh_tx_agg_session_timer(struct ieee80211_sta *pubsta,
++					    u16 tid)
++{
++	struct sta_info *sta = container_of(pubsta, struct sta_info, sta);
++	struct tid_ampdu_tx *tid_tx;
++
++	if (WARN_ON_ONCE(tid >= IEEE80211_NUM_TIDS))
++		return;
++
++	tid_tx = rcu_dereference(sta->ampdu_mlme.tid_tx[tid]);
++	if (!tid_tx)
++		return;
++
++	tid_tx->last_tx = jiffies;
++}
++EXPORT_SYMBOL(ieee80211_refresh_tx_agg_session_timer);
++
+ /*
+  * After accepting the AddBA Response we activated a timer,
+  * resetting it after each frame that we send.
diff --git a/recipes-wifi/linux-mac80211/files/patches/subsys/mtk-0009-mac80211-mtk-remove-timerout-handle-for-ax210-iot-is.patch b/recipes-wifi/linux-mac80211/files/patches/subsys/mtk-0009-mac80211-mtk-remove-timerout-handle-for-ax210-iot-is.patch
deleted file mode 100644
index 50f2684..0000000
--- a/recipes-wifi/linux-mac80211/files/patches/subsys/mtk-0009-mac80211-mtk-remove-timerout-handle-for-ax210-iot-is.patch
+++ /dev/null
@@ -1,35 +0,0 @@
-From 733277b58ef0b13581c4c22231003f1910d60a5b Mon Sep 17 00:00:00 2001
-From: Evelyn Tsai <evelyn.tsai@mediatek.com>
-Date: Wed, 19 Oct 2022 13:49:21 +0800
-Subject: [PATCH 908/915] mac80211: mtk: remove timerout handle for ax210 iot
- issue
-
-Signed-off-by: Evelyn Tsai <evelyn.tsai@mediatek.com>
----
- net/mac80211/agg-tx.c | 7 +++----
- 1 file changed, 3 insertions(+), 4 deletions(-)
- mode change 100644 => 100755 net/mac80211/agg-tx.c
-
-diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c
-old mode 100644
-new mode 100755
-index 1deb3d8..c30f02d
---- a/net/mac80211/agg-tx.c
-+++ b/net/mac80211/agg-tx.c
-@@ -568,10 +568,9 @@ static void sta_tx_agg_session_timer_expired(struct timer_list *t)
- 	}
- 
- 	timeout = tid_tx->last_tx + TU_TO_JIFFIES(tid_tx->timeout);
--	if (time_is_after_jiffies(timeout)) {
--		mod_timer(&tid_tx->session_timer, timeout);
--		return;
--	}
-+	/* remove timerout handle for ax210 iot issue */
-+	mod_timer(&tid_tx->session_timer, timeout);
-+	return;
- 
- 	ht_dbg(sta->sdata, "tx session timer expired on %pM tid %d\n",
- 	       sta->sta.addr, tid);
--- 
-2.36.1
-
diff --git a/recipes-wifi/linux-mac80211/files/patches/subsys/mtk-0014--mac80211-mtk-track-obss-color-bitmap.patch b/recipes-wifi/linux-mac80211/files/patches/subsys/mtk-0014--mac80211-mtk-track-obss-color-bitmap.patch
new file mode 100644
index 0000000..18d8aab
--- /dev/null
+++ b/recipes-wifi/linux-mac80211/files/patches/subsys/mtk-0014--mac80211-mtk-track-obss-color-bitmap.patch
@@ -0,0 +1,102 @@
+From 40ceb2dcc486ddefb5e4cb69e4cd86906242872c Mon Sep 17 00:00:00 2001
+From: Yi-Chia Hsieh <yi-chia.hsieh@mediatek.com>
+Date: Tue, 15 Nov 2022 06:35:48 +0800
+Subject: [PATCH] mac80211: mtk: track obss color bitmap
+
+Track OBSS BSS color when receive their beacon.
+
+Adding 2 tracepoint for debug, usage:
+echo 1 > /sys/kernel/debug/tracing/events/mac80211/bss_color_bitmap/enable
+echo 1 > /sys/kernel/debug/tracing/events/mac80211/bss_color_collision/enable
+---
+ include/net/cfg80211.h |  1 +
+ net/mac80211/rx.c      | 14 ++++++++++++--
+ net/mac80211/trace.h   | 35 +++++++++++++++++++++++++++++++++++
+ 3 files changed, 48 insertions(+), 2 deletions(-)
+
+diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
+index c4c0926..e5175c2 100644
+--- a/include/net/cfg80211.h
++++ b/include/net/cfg80211.h
+@@ -307,6 +307,7 @@ struct cfg80211_he_bss_color {
+ 	u8 color;
+ 	bool enabled;
+ 	bool partial;
++	u64 used_color_bitmap;
+ };
+ 
+ /**
+diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
+index eb16838..4a6491c 100644
+--- a/net/mac80211/rx.c
++++ b/net/mac80211/rx.c
+@@ -3219,9 +3219,18 @@ ieee80211_rx_check_bss_color_collision(struct ieee80211_rx_data *rx)
+ 
+ 		color = le32_get_bits(he_oper->he_oper_params,
+ 				      IEEE80211_HE_OPERATION_BSS_COLOR_MASK);
+-		if (color == bss_conf->he_bss_color.color)
++
++		bss_conf->he_bss_color.used_color_bitmap |= BIT_ULL(color);
++
++		trace_bss_color_bitmap(color,
++				       bss_conf->he_bss_color.used_color_bitmap);
++
++		if (color == bss_conf->he_bss_color.color) {
++			trace_bss_color_collision(color);
++
+ 			ieeee80211_obss_color_collision_notify(&rx->sdata->vif,
+-							       BIT_ULL(color));
++				bss_conf->he_bss_color.used_color_bitmap);
++		}
+ 	}
+ }
+ 
+diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h
+index d91498f..013f5e4 100644
+--- a/net/mac80211/trace.h
++++ b/net/mac80211/trace.h
+@@ -2899,6 +2899,41 @@ DEFINE_EVENT(sta_event, drv_net_fill_forward_path,
+ 	TP_ARGS(local, sdata, sta)
+ );
+ 
++TRACE_EVENT(bss_color_bitmap,
++	TP_PROTO(u8 color,
++		 u64 color_bitmap),
++
++	TP_ARGS(color, color_bitmap),
++
++	TP_STRUCT__entry(
++		__field(u8, color)
++		__field(u64, color_bitmap)
++	),
++
++	TP_fast_assign(
++		__entry->color = color;
++		__entry->color_bitmap = color_bitmap;
++	),
++
++	TP_printk(
++		"color=%u color_bitmap=0x%llx", __entry->color, __entry->color_bitmap
++	)
++);
++
++TRACE_EVENT(bss_color_collision,
++	TP_PROTO(u8 color),
++
++	TP_ARGS(color),
++
++	TP_STRUCT__entry(__field(u8, color)),
++
++	TP_fast_assign(
++		__entry->color = color;
++	),
++
++	TP_printk("collision detected on color %u", __entry->color)
++);
++
+ #endif /* !__MAC80211_DRIVER_TRACE || TRACE_HEADER_MULTI_READ */
+ 
+ #undef TRACE_INCLUDE_PATH
+-- 
+2.36.1
+
diff --git a/recipes-wifi/linux-mac80211/files/patches/subsys/mtk-0015-mac80211-mtk-aging-color-bitmap.patch b/recipes-wifi/linux-mac80211/files/patches/subsys/mtk-0015-mac80211-mtk-aging-color-bitmap.patch
new file mode 100644
index 0000000..4ed9142
--- /dev/null
+++ b/recipes-wifi/linux-mac80211/files/patches/subsys/mtk-0015-mac80211-mtk-aging-color-bitmap.patch
@@ -0,0 +1,126 @@
+From f6cd955e1c042a00691fa80d231495024cfcf7a5 Mon Sep 17 00:00:00 2001
+From: Yi-Chia Hsieh <yi-chia.hsieh@mediatek.com>
+Date: Tue, 15 Nov 2022 11:03:22 +0800
+Subject: [PATCH] mac80211: mtk: ageout color bitmap
+
+Adding a periodic work which runs once per second to check BSS color.
+OBSS BSS Color will be ageout if not seen for 10 seconds.
+---
+ include/net/cfg80211.h     |  1 +
+ net/mac80211/cfg.c         | 25 +++++++++++++++++++++++++
+ net/mac80211/ieee80211_i.h |  4 ++++
+ net/mac80211/iface.c       |  5 +++++
+ net/mac80211/rx.c          |  1 +
+ 5 files changed, 36 insertions(+)
+
+diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
+index e5175c2..3e826f0 100644
+--- a/include/net/cfg80211.h
++++ b/include/net/cfg80211.h
+@@ -308,6 +308,7 @@ struct cfg80211_he_bss_color {
+ 	bool enabled;
+ 	bool partial;
+ 	u64 used_color_bitmap;
++	u64 color_last_seen[64];
+ };
+ 
+ /**
+diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
+index a7b6284..f084912 100644
+--- a/net/mac80211/cfg.c
++++ b/net/mac80211/cfg.c
+@@ -4425,6 +4425,31 @@ unlock:
+ 	sdata_unlock(sdata);
+ }
+ 
++void ieee80211_color_aging_work(struct work_struct *work)
++{
++	struct ieee80211_sub_if_data *sdata =
++		container_of(work, struct ieee80211_sub_if_data,
++			     color_aging_work.work);
++	struct cfg80211_he_bss_color *he_bss_color = &sdata->vif.bss_conf.he_bss_color;
++	int i = 0;
++
++	sdata_lock(sdata);
++
++	for (i = 0; i < IEEE80211_BSS_COLOR_MAX; i++) {
++		/* ageout if not seen for a period */
++		if ((he_bss_color->used_color_bitmap & BIT_ULL(i)) &&
++		    time_before(he_bss_color->color_last_seen[i],
++			jiffies - IEEE80211_BSS_COLOR_AGEOUT_TIME * HZ)) {
++			he_bss_color->used_color_bitmap &= ~BIT_ULL(i);
++		}
++	}
++
++	ieee80211_queue_delayed_work(&sdata->local->hw,
++				     &sdata->color_aging_work, HZ);
++
++	sdata_unlock(sdata);
++}
++
+ void ieee80211_color_change_finish(struct ieee80211_vif *vif)
+ {
+ 	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
+diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
+index 6edabd8..415f202 100644
+--- a/net/mac80211/ieee80211_i.h
++++ b/net/mac80211/ieee80211_i.h
+@@ -1033,6 +1033,8 @@ struct ieee80211_sub_if_data {
+ 	} debugfs;
+ #endif
+ 
++	struct delayed_work color_aging_work;
++
+ 	/* must be last, dynamically sized area in this! */
+ 	struct ieee80211_vif vif;
+ };
+@@ -1811,8 +1813,11 @@ void ieee80211_csa_finalize_work(struct work_struct *work);
+ int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
+ 			     struct cfg80211_csa_settings *params);
+ 
++#define IEEE80211_BSS_COLOR_AGEOUT_TIME	10
++#define IEEE80211_BSS_COLOR_MAX		64
+ /* color change handling */
+ void ieee80211_color_change_finalize_work(struct work_struct *work);
++void ieee80211_color_aging_work(struct work_struct *work);
+ 
+ /* interface handling */
+ #define MAC80211_SUPPORTED_FEATURES_TX	(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | \
+diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
+index 43f6cb0..7f26828 100644
+--- a/net/mac80211/iface.c
++++ b/net/mac80211/iface.c
+@@ -466,6 +466,8 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, bool going_do
+ 	cancel_work_sync(&sdata->color_change_finalize_work);
+ 
+ 	cancel_delayed_work_sync(&sdata->dfs_cac_timer_work);
++	if (sdata->vif.type == NL80211_IFTYPE_AP)
++		cancel_delayed_work_sync(&sdata->color_aging_work);
+ 
+ 	if (sdata->wdev.cac_started) {
+ 		chandef = sdata->vif.bss_conf.chandef;
+@@ -1804,6 +1806,9 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata,
+ 		skb_queue_head_init(&sdata->u.ap.ps.bc_buf);
+ 		INIT_LIST_HEAD(&sdata->u.ap.vlans);
+ 		sdata->vif.bss_conf.bssid = sdata->vif.addr;
++		INIT_DELAYED_WORK(&sdata->color_aging_work, ieee80211_color_aging_work);
++		ieee80211_queue_delayed_work(&sdata->local->hw,
++					     &sdata->color_aging_work, 0);
+ 		break;
+ 	case NL80211_IFTYPE_P2P_CLIENT:
+ 		type = NL80211_IFTYPE_STATION;
+diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
+index 789a41b..4a6491c 100644
+--- a/net/mac80211/rx.c
++++ b/net/mac80211/rx.c
+@@ -3221,6 +3221,7 @@ ieee80211_rx_check_bss_color_collision(struct ieee80211_rx_data *rx)
+ 				      IEEE80211_HE_OPERATION_BSS_COLOR_MASK);
+ 
+ 		bss_conf->he_bss_color.used_color_bitmap |= BIT_ULL(color);
++		bss_conf->he_bss_color.color_last_seen[color] = jiffies;
+ 
+ 		trace_bss_color_bitmap(color,
+ 				       bss_conf->he_bss_color.used_color_bitmap);
+-- 
+2.39.0
+
diff --git a/recipes-wifi/linux-mac80211/files/patches/subsys/mtk-0015-nl80211-mtk-Mark-DFS-channel-as-available-for-CSA.patch b/recipes-wifi/linux-mac80211/files/patches/subsys/mtk-0015-nl80211-mtk-Mark-DFS-channel-as-available-for-CSA.patch
new file mode 100644
index 0000000..eff574e
--- /dev/null
+++ b/recipes-wifi/linux-mac80211/files/patches/subsys/mtk-0015-nl80211-mtk-Mark-DFS-channel-as-available-for-CSA.patch
@@ -0,0 +1,28 @@
+From 20d6ed31c0e6c15cfbc120bea6a8729121560371 Mon Sep 17 00:00:00 2001
+From: "himanshu.goyal" <himanshu.goyal@mediatek.com>
+Date: Tue, 21 Feb 2023 15:24:09 +0800
+Subject: [PATCH] nl80211: mtk: Mark DFS channel as available for CSA.
+
+---
+ net/wireless/nl80211.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
+index 8dc928d..a02aacb 100644
+--- a/net/wireless/nl80211.c
++++ b/net/wireless/nl80211.c
+@@ -3193,6 +3193,11 @@ int nl80211_parse_chandef(struct cfg80211_registered_device *rdev,
+ 		return -EINVAL;
+ 	}
+ 
++	/* Use RADAR_BACKGROUND attribute here for skipping CAC */
++	if (info->attrs[NL80211_ATTR_RADAR_BACKGROUND]) {
++		cfg80211_set_dfs_state(&rdev->wiphy, chandef, NL80211_DFS_AVAILABLE);
++	}
++
+ 	if (!cfg80211_chandef_usable(&rdev->wiphy, chandef,
+ 				     IEEE80211_CHAN_DISABLED)) {
+ 		NL_SET_ERR_MSG(extack, "(extension) channel is disabled");
+-- 
+2.18.0
+
diff --git a/recipes-wifi/linux-mac80211/files/patches/subsys/subsys.inc b/recipes-wifi/linux-mac80211/files/patches/subsys/subsys.inc
index ae088f6..dcebb38 100644
--- a/recipes-wifi/linux-mac80211/files/patches/subsys/subsys.inc
+++ b/recipes-wifi/linux-mac80211/files/patches/subsys/subsys.inc
@@ -42,6 +42,7 @@
     file://344-v6.1-wifi-cfg80211-fix-ieee80211_data_to_8023_exthdr-hand.patch \
     file://345-v6.1-wifi-mac80211-do-not-drop-packets-smaller-than-the-L.patch \
     file://346-v6.0-wifi-mac80211-fix-mesh-airtime-link-metric-estimatin.patch \
+    file://347-wifi-mac80211-introduce-ieee80211_refresh_tx_agg_ses.patch \
     file://363-v5.19-bss-color-collision.patch \
     file://364-mac80211-add-support-for-restricting-netdev-features.patch \
     file://400-allow-ibss-mixed.patch \
@@ -57,12 +58,14 @@
     file://mtk-0006-mac80211-mtk-add-support-for-runtime-set-inband-disc.patch \
     file://mtk-0007-mac80211-mtk-add-s1g-category-to-_ieee80211_is_robus.patch \
     file://mtk-0008-mac80211-mtk-make-4addr-null-frames-using-min_rate-f.patch \
-    file://mtk-0009-mac80211-mtk-remove-timerout-handle-for-ax210-iot-is.patch \
     file://mtk-0010-cfg80211-mtk-implement-DFS-status-show-cac-and-nop-s.patch \
     file://mtk-0011-mac80211-mtk-Set-TWT-Information-Frame-Disabled-bit-.patch \
     file://mtk-0012-mac80211-mtk-check-the-control-channel-before-downgr.patch \
     file://mtk-0013-mac80211-mtk-fix-tx-amsdu-aggregation.patch \
+    file://mtk-0014--mac80211-mtk-track-obss-color-bitmap.patch \
     file://mtk-0014-mac80211-mtk-add-sta-assisted-DFS-state-update-mecha.patch \
+    file://mtk-0015-mac80211-mtk-aging-color-bitmap.patch \
+    file://mtk-0015-nl80211-mtk-Mark-DFS-channel-as-available-for-CSA.patch \
     file://mtk-9900-mac80211-mtk-mask-kernel-version-limitation-and-fil.patch \
     file://mtk-9901-mac80211-mtk-add-fill-receive-path-ops-to-get-wed-i.patch \
     file://mtk-9902-mac80211-mtk-register-.ndo_setup_tc-to-support-wifi2.patch \
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0000-sync-to-master.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0000-sync-to-master.patch
deleted file mode 100644
index 44a01ec..0000000
--- a/recipes-wifi/linux-mt76/files/patches-3.x/0000-sync-to-master.patch
+++ /dev/null
@@ -1,249 +0,0 @@
-diff --git a/eeprom.c b/eeprom.c
-index 0a88048b..ea54b7af 100644
---- a/eeprom.c
-+++ b/eeprom.c
-@@ -138,6 +138,7 @@ mt76_find_power_limits_node(struct mt76_dev *dev)
- {
- 	struct device_node *np = dev->dev->of_node;
- 	const char *const region_names[] = {
-+		[NL80211_DFS_UNSET] = "ww",
- 		[NL80211_DFS_ETSI] = "etsi",
- 		[NL80211_DFS_FCC] = "fcc",
- 		[NL80211_DFS_JP] = "jp",
-diff --git a/mt76_connac_mac.c b/mt76_connac_mac.c
-index 614df85e..aed4ee95 100644
---- a/mt76_connac_mac.c
-+++ b/mt76_connac_mac.c
-@@ -823,7 +823,6 @@ void mt76_connac2_mac_decode_he_radiotap(struct mt76_dev *dev,
- 			 HE_BITS(DATA2_TXOP_KNOWN),
- 	};
- 	u32 ltf_size = le32_get_bits(rxv[2], MT_CRXV_HE_LTF_SIZE) + 1;
--	u32 txbf_mask = is_mt7996(dev) ? BIT(11) : BIT(10);
- 	struct ieee80211_radiotap_he *he;
- 
- 	status->flag |= RX_FLAG_RADIOTAP_HE;
-@@ -837,7 +836,7 @@ void mt76_connac2_mac_decode_he_radiotap(struct mt76_dev *dev,
- 	he->data5 = HE_PREP(DATA5_PE_DISAMBIG, PE_DISAMBIG, rxv[2]) |
- 		    le16_encode_bits(ltf_size,
- 				     IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE);
--	if (le32_to_cpu(rxv[0]) & txbf_mask)
-+	if (le32_to_cpu(rxv[0]) & MT_PRXV_TXBF)
- 		he->data5 |= HE_BITS(DATA5_TXBF);
- 	he->data6 = HE_PREP(DATA6_TXOP, TXOP_DUR, rxv[14]) |
- 		    HE_PREP(DATA6_DOPPLER, DOPPLER, rxv[14]);
-diff --git a/mt76x0/usb_mcu.c b/mt76x0/usb_mcu.c
-index 45502fd4..6dc1f51f 100644
---- a/mt76x0/usb_mcu.c
-+++ b/mt76x0/usb_mcu.c
-@@ -148,6 +148,7 @@ static int mt76x0u_load_firmware(struct mt76x02_dev *dev)
- 	mt76_wr(dev, MT_USB_DMA_CFG, val);
- 
- 	ret = mt76x0u_upload_firmware(dev, hdr);
-+	mt76x02_set_ethtool_fwver(dev, hdr);
- 	release_firmware(fw);
- 
- 	mt76_wr(dev, MT_FCE_PSE_CTRL, 1);
-diff --git a/mt7996/mac.c b/mt7996/mac.c
-index 674cea1a..c9a9f0e3 100644
---- a/mt7996/mac.c
-+++ b/mt7996/mac.c
-@@ -12,6 +12,10 @@
- 
- #define to_rssi(field, rcpi)	((FIELD_GET(field, rcpi) - 220) / 2)
- 
-+#define HE_BITS(f)		cpu_to_le16(IEEE80211_RADIOTAP_HE_##f)
-+#define HE_PREP(f, m, v)	le16_encode_bits(le32_get_bits(v, MT_CRXV_HE_##m),\
-+						 IEEE80211_RADIOTAP_HE_##f)
-+
- static const struct mt7996_dfs_radar_spec etsi_radar_specs = {
- 	.pulse_th = { 110, -10, -80, 40, 5200, 128, 5200 },
- 	.radar_pattern = {
-@@ -251,6 +255,178 @@ void mt7996_mac_enable_rtscts(struct mt7996_dev *dev,
- 		mt76_clear(dev, addr, BIT(5));
- }
- 
-+static void
-+mt7996_mac_decode_he_radiotap_ru(struct mt76_rx_status *status,
-+				 struct ieee80211_radiotap_he *he,
-+				 __le32 *rxv)
-+{
-+	u32 ru_h, ru_l;
-+	u8 ru, offs = 0;
-+
-+	ru_l = le32_get_bits(rxv[0], MT_PRXV_HE_RU_ALLOC_L);
-+	ru_h = le32_get_bits(rxv[1], MT_PRXV_HE_RU_ALLOC_H);
-+	ru = (u8)(ru_l | ru_h << 4);
-+
-+	status->bw = RATE_INFO_BW_HE_RU;
-+
-+	switch (ru) {
-+	case 0 ... 36:
-+		status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_26;
-+		offs = ru;
-+		break;
-+	case 37 ... 52:
-+		status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_52;
-+		offs = ru - 37;
-+		break;
-+	case 53 ... 60:
-+		status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_106;
-+		offs = ru - 53;
-+		break;
-+	case 61 ... 64:
-+		status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_242;
-+		offs = ru - 61;
-+		break;
-+	case 65 ... 66:
-+		status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_484;
-+		offs = ru - 65;
-+		break;
-+	case 67:
-+		status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_996;
-+		break;
-+	case 68:
-+		status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_2x996;
-+		break;
-+	}
-+
-+	he->data1 |= HE_BITS(DATA1_BW_RU_ALLOC_KNOWN);
-+	he->data2 |= HE_BITS(DATA2_RU_OFFSET_KNOWN) |
-+		     le16_encode_bits(offs,
-+				      IEEE80211_RADIOTAP_HE_DATA2_RU_OFFSET);
-+}
-+
-+static void
-+mt7996_mac_decode_he_mu_radiotap(struct sk_buff *skb, __le32 *rxv)
-+{
-+	struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
-+	static const struct ieee80211_radiotap_he_mu mu_known = {
-+		.flags1 = HE_BITS(MU_FLAGS1_SIG_B_MCS_KNOWN) |
-+			  HE_BITS(MU_FLAGS1_SIG_B_DCM_KNOWN) |
-+			  HE_BITS(MU_FLAGS1_CH1_RU_KNOWN) |
-+			  HE_BITS(MU_FLAGS1_SIG_B_SYMS_USERS_KNOWN),
-+		.flags2 = HE_BITS(MU_FLAGS2_BW_FROM_SIG_A_BW_KNOWN),
-+	};
-+	struct ieee80211_radiotap_he_mu *he_mu = NULL;
-+
-+	status->flag |= RX_FLAG_RADIOTAP_HE_MU;
-+
-+	he_mu = skb_push(skb, sizeof(mu_known));
-+	memcpy(he_mu, &mu_known, sizeof(mu_known));
-+
-+#define MU_PREP(f, v)	le16_encode_bits(v, IEEE80211_RADIOTAP_HE_MU_##f)
-+
-+	he_mu->flags1 |= MU_PREP(FLAGS1_SIG_B_MCS, status->rate_idx);
-+	if (status->he_dcm)
-+		he_mu->flags1 |= MU_PREP(FLAGS1_SIG_B_DCM, status->he_dcm);
-+
-+	he_mu->flags2 |= MU_PREP(FLAGS2_BW_FROM_SIG_A_BW, status->bw) |
-+			 MU_PREP(FLAGS2_SIG_B_SYMS_USERS,
-+				 le32_get_bits(rxv[2], MT_CRXV_HE_NUM_USER));
-+
-+	he_mu->ru_ch1[0] = le32_get_bits(rxv[3], MT_CRXV_HE_RU0);
-+
-+	if (status->bw >= RATE_INFO_BW_40) {
-+		he_mu->flags1 |= HE_BITS(MU_FLAGS1_CH2_RU_KNOWN);
-+		he_mu->ru_ch2[0] = le32_get_bits(rxv[3], MT_CRXV_HE_RU1);
-+	}
-+
-+	if (status->bw >= RATE_INFO_BW_80) {
-+		he_mu->ru_ch1[1] = le32_get_bits(rxv[3], MT_CRXV_HE_RU2);
-+		he_mu->ru_ch2[1] = le32_get_bits(rxv[3], MT_CRXV_HE_RU3);
-+	}
-+}
-+
-+static void
-+mt7996_mac_decode_he_radiotap(struct sk_buff *skb, __le32 *rxv, u8 mode)
-+{
-+	struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
-+	static const struct ieee80211_radiotap_he known = {
-+		.data1 = HE_BITS(DATA1_DATA_MCS_KNOWN) |
-+			 HE_BITS(DATA1_DATA_DCM_KNOWN) |
-+			 HE_BITS(DATA1_STBC_KNOWN) |
-+			 HE_BITS(DATA1_CODING_KNOWN) |
-+			 HE_BITS(DATA1_LDPC_XSYMSEG_KNOWN) |
-+			 HE_BITS(DATA1_DOPPLER_KNOWN) |
-+			 HE_BITS(DATA1_SPTL_REUSE_KNOWN) |
-+			 HE_BITS(DATA1_BSS_COLOR_KNOWN),
-+		.data2 = HE_BITS(DATA2_GI_KNOWN) |
-+			 HE_BITS(DATA2_TXBF_KNOWN) |
-+			 HE_BITS(DATA2_PE_DISAMBIG_KNOWN) |
-+			 HE_BITS(DATA2_TXOP_KNOWN),
-+	};
-+	struct ieee80211_radiotap_he *he = NULL;
-+	u32 ltf_size = le32_get_bits(rxv[2], MT_CRXV_HE_LTF_SIZE) + 1;
-+
-+	status->flag |= RX_FLAG_RADIOTAP_HE;
-+
-+	he = skb_push(skb, sizeof(known));
-+	memcpy(he, &known, sizeof(known));
-+
-+	he->data3 = HE_PREP(DATA3_BSS_COLOR, BSS_COLOR, rxv[14]) |
-+		    HE_PREP(DATA3_LDPC_XSYMSEG, LDPC_EXT_SYM, rxv[2]);
-+	he->data4 = HE_PREP(DATA4_SU_MU_SPTL_REUSE, SR_MASK, rxv[11]);
-+	he->data5 = HE_PREP(DATA5_PE_DISAMBIG, PE_DISAMBIG, rxv[2]) |
-+		    le16_encode_bits(ltf_size,
-+				     IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE);
-+	if (le32_to_cpu(rxv[0]) & MT_PRXV_TXBF)
-+		he->data5 |= HE_BITS(DATA5_TXBF);
-+	he->data6 = HE_PREP(DATA6_TXOP, TXOP_DUR, rxv[14]) |
-+		    HE_PREP(DATA6_DOPPLER, DOPPLER, rxv[14]);
-+
-+	switch (mode) {
-+	case MT_PHY_TYPE_HE_SU:
-+		he->data1 |= HE_BITS(DATA1_FORMAT_SU) |
-+			     HE_BITS(DATA1_UL_DL_KNOWN) |
-+			     HE_BITS(DATA1_BEAM_CHANGE_KNOWN) |
-+			     HE_BITS(DATA1_BW_RU_ALLOC_KNOWN);
-+
-+		he->data3 |= HE_PREP(DATA3_BEAM_CHANGE, BEAM_CHNG, rxv[14]) |
-+			     HE_PREP(DATA3_UL_DL, UPLINK, rxv[2]);
-+		break;
-+	case MT_PHY_TYPE_HE_EXT_SU:
-+		he->data1 |= HE_BITS(DATA1_FORMAT_EXT_SU) |
-+			     HE_BITS(DATA1_UL_DL_KNOWN) |
-+			     HE_BITS(DATA1_BW_RU_ALLOC_KNOWN);
-+
-+		he->data3 |= HE_PREP(DATA3_UL_DL, UPLINK, rxv[2]);
-+		break;
-+	case MT_PHY_TYPE_HE_MU:
-+		he->data1 |= HE_BITS(DATA1_FORMAT_MU) |
-+			     HE_BITS(DATA1_UL_DL_KNOWN);
-+
-+		he->data3 |= HE_PREP(DATA3_UL_DL, UPLINK, rxv[2]);
-+		he->data4 |= HE_PREP(DATA4_MU_STA_ID, MU_AID, rxv[7]);
-+
-+		mt7996_mac_decode_he_radiotap_ru(status, he, rxv);
-+		mt7996_mac_decode_he_mu_radiotap(skb, rxv);
-+		break;
-+	case MT_PHY_TYPE_HE_TB:
-+		he->data1 |= HE_BITS(DATA1_FORMAT_TRIG) |
-+			     HE_BITS(DATA1_SPTL_REUSE2_KNOWN) |
-+			     HE_BITS(DATA1_SPTL_REUSE3_KNOWN) |
-+			     HE_BITS(DATA1_SPTL_REUSE4_KNOWN);
-+
-+		he->data4 |= HE_PREP(DATA4_TB_SPTL_REUSE1, SR_MASK, rxv[11]) |
-+			     HE_PREP(DATA4_TB_SPTL_REUSE2, SR1_MASK, rxv[11]) |
-+			     HE_PREP(DATA4_TB_SPTL_REUSE3, SR2_MASK, rxv[11]) |
-+			     HE_PREP(DATA4_TB_SPTL_REUSE4, SR3_MASK, rxv[11]);
-+
-+		mt7996_mac_decode_he_radiotap_ru(status, he, rxv);
-+		break;
-+	default:
-+		break;
-+	}
-+}
-+
- /* The HW does not translate the mac header to 802.3 for mesh point */
- static int mt7996_reverse_frag0_hdr_trans(struct sk_buff *skb, u16 hdr_gap)
- {
-@@ -686,8 +862,7 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, struct sk_buff *skb)
- 	}
- 
- 	if (rxv && mode >= MT_PHY_TYPE_HE_SU && !(status->flag & RX_FLAG_8023))
--		mt76_connac2_mac_decode_he_radiotap(&dev->mt76, skb, rxv,
--						    mode);
-+		mt7996_mac_decode_he_radiotap(skb, rxv, mode);
- 
- 	if (!status->wcid || !ieee80211_is_data_qos(fc))
- 		return 0;
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0001-Revert-wifi-mt76-mt7996-rely-on-mt76_connac_tx_compl.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0001-Revert-wifi-mt76-mt7996-rely-on-mt76_connac_tx_compl.patch
deleted file mode 100644
index 1022535..0000000
--- a/recipes-wifi/linux-mt76/files/patches-3.x/0001-Revert-wifi-mt76-mt7996-rely-on-mt76_connac_tx_compl.patch
+++ /dev/null
@@ -1,96 +0,0 @@
-From 6767bcfec5f48f14fdf63c9699c63e6bc741ad74 Mon Sep 17 00:00:00 2001
-From: Shayne Chen <shayne.chen@mediatek.com>
-Date: Fri, 3 Feb 2023 11:00:59 +0800
-Subject: [PATCH 1/7] Revert "wifi: mt76: mt7996: rely on
- mt76_connac_tx_complete_skb"
-
-This reverts commit 8688756305c643b8a296c16d0626732aaae1d02a.
----
- mt7996/mac.c    | 21 +++++++++++++++++++++
- mt7996/mac.h    | 13 +++++++++++++
- mt7996/mmio.c   |  2 +-
- mt7996/mt7996.h |  1 +
- 4 files changed, 36 insertions(+), 1 deletion(-)
-
-diff --git a/mt7996/mac.c b/mt7996/mac.c
-index c9a9f0e3..0d718598 100644
---- a/mt7996/mac.c
-+++ b/mt7996/mac.c
-@@ -1565,6 +1565,27 @@ void mt7996_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
- 	}
- }
- 
-+void mt7996_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue_entry *e)
-+{
-+	if (!e->txwi) {
-+		dev_kfree_skb_any(e->skb);
-+		return;
-+	}
-+
-+	/* error path */
-+	if (e->skb == DMA_DUMMY_DATA) {
-+		struct mt76_connac_txp_common *txp;
-+		struct mt76_txwi_cache *t;
-+
-+		txp = mt7996_txwi_to_txp(mdev, e->txwi);
-+		t = mt76_token_put(mdev, le16_to_cpu(txp->fw.token));
-+		e->skb = t ? t->skb : NULL;
-+	}
-+
-+	if (e->skb)
-+		mt76_tx_complete_skb(mdev, e->wcid, e->skb);
-+}
-+
- void mt7996_mac_cca_stats_reset(struct mt7996_phy *phy)
- {
- 	struct mt7996_dev *dev = phy->dev;
-diff --git a/mt7996/mac.h b/mt7996/mac.h
-index 27184cba..10e08d66 100644
---- a/mt7996/mac.h
-+++ b/mt7996/mac.h
-@@ -371,4 +371,17 @@ struct mt7996_dfs_radar_spec {
- 	struct mt7996_dfs_pattern radar_pattern[16];
- };
- 
-+static inline struct mt76_connac_txp_common *
-+mt7996_txwi_to_txp(struct mt76_dev *dev, struct mt76_txwi_cache *t)
-+{
-+	u8 *txwi;
-+
-+	if (!t)
-+		return NULL;
-+
-+	txwi = mt76_get_txwi_ptr(dev, t);
-+
-+	return (struct mt76_connac_txp_common *)(txwi + MT_TXD_SIZE);
-+}
-+
- #endif
-diff --git a/mt7996/mmio.c b/mt7996/mmio.c
-index 902370a2..2237f50a 100644
---- a/mt7996/mmio.c
-+++ b/mt7996/mmio.c
-@@ -326,7 +326,7 @@ struct mt7996_dev *mt7996_mmio_probe(struct device *pdev,
- 				SURVEY_INFO_TIME_BSS_RX,
- 		.token_size = MT7996_TOKEN_SIZE,
- 		.tx_prepare_skb = mt7996_tx_prepare_skb,
--		.tx_complete_skb = mt76_connac_tx_complete_skb,
-+		.tx_complete_skb = mt7996_tx_complete_skb,
- 		.rx_skb = mt7996_queue_rx_skb,
- 		.rx_check = mt7996_rx_check,
- 		.rx_poll_complete = mt7996_rx_poll_complete,
-diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
-index 018dfd2b..13f22432 100644
---- a/mt7996/mt7996.h
-+++ b/mt7996/mt7996.h
-@@ -508,6 +508,7 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
- 			  enum mt76_txq_id qid, struct mt76_wcid *wcid,
- 			  struct ieee80211_sta *sta,
- 			  struct mt76_tx_info *tx_info);
-+void mt7996_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue_entry *e);
- void mt7996_tx_token_put(struct mt7996_dev *dev);
- void mt7996_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
- 			 struct sk_buff *skb, u32 *info);
--- 
-2.25.1
-
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0001-wifi-mt76-mt7996-add-eht-rx-rate-support.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0001-wifi-mt76-mt7996-add-eht-rx-rate-support.patch
new file mode 100644
index 0000000..66ab9ce
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0001-wifi-mt76-mt7996-add-eht-rx-rate-support.patch
@@ -0,0 +1,92 @@
+From 995b09b6a62700568b36cc2e4ae6b6063456942b Mon Sep 17 00:00:00 2001
+From: Shayne Chen <shayne.chen@mediatek.com>
+Date: Fri, 10 Feb 2023 17:39:23 +0800
+Subject: [PATCH 01/19] wifi: mt76: mt7996: add eht rx rate support
+
+Add support to report eht rx rate.
+
+Change-Id: Iee067d891bd634a918c942c2ba90ae72cd40c538
+Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
+---
+ mac80211.c   | 11 ++++++++---
+ mt76.h       | 18 ++++++++++++++----
+ mt7996/mac.c |  9 +++++----
+ 3 files changed, 27 insertions(+), 11 deletions(-)
+
+diff --git a/mac80211.c b/mac80211.c
+index 87902f4b..e53166fc 100644
+--- a/mac80211.c
++++ b/mac80211.c
+@@ -1067,9 +1067,14 @@ mt76_rx_convert(struct mt76_dev *dev, struct sk_buff *skb,
+ 	status->enc_flags = mstat.enc_flags;
+ 	status->encoding = mstat.encoding;
+ 	status->bw = mstat.bw;
+-	status->he_ru = mstat.he_ru;
+-	status->he_gi = mstat.he_gi;
+-	status->he_dcm = mstat.he_dcm;
++	if (status->encoding == RX_ENC_EHT) {
++		status->eht.ru = mstat.eht.ru;
++		status->eht.gi = mstat.eht.gi;
++	} else {
++		status->he_ru = mstat.he_ru;
++		status->he_gi = mstat.he_gi;
++		status->he_dcm = mstat.he_dcm;
++	}
+ 	status->rate_idx = mstat.rate_idx;
+ 	status->nss = mstat.nss;
+ 	status->band = mstat.band;
+diff --git a/mt76.h b/mt76.h
+index 183b0fc5..c3d1313e 100644
+--- a/mt76.h
++++ b/mt76.h
+@@ -621,12 +621,22 @@ struct mt76_rx_status {
+ 	u16 freq;
+ 	u32 flag;
+ 	u8 enc_flags;
+-	u8 encoding:2, bw:3, he_ru:3;
+-	u8 he_gi:2, he_dcm:1;
++	u8 encoding:3, bw:4;
++	union {
++		struct {
++			u8 he_ru:3;
++			u8 he_gi:2;
++			u8 he_dcm:1;
++		};
++		struct {
++			u8 ru:4;
++			u8 gi:2;
++		} eht;
++	};
++
+ 	u8 amsdu:1, first_amsdu:1, last_amsdu:1;
+ 	u8 rate_idx;
+-	u8 nss;
+-	u8 band;
++	u8 nss:5, band:3;
+ 	s8 signal;
+ 	u8 chains;
+ 	s8 chain_signal[IEEE80211_MAX_CHAINS];
+diff --git a/mt7996/mac.c b/mt7996/mac.c
+index 3c3506c7..d811b4e0 100644
+--- a/mt7996/mac.c
++++ b/mt7996/mac.c
+@@ -572,11 +572,12 @@ mt7996_mac_fill_rx_rate(struct mt7996_dev *dev,
+ 	case MT_PHY_TYPE_EHT_SU:
+ 	case MT_PHY_TYPE_EHT_TRIG:
+ 	case MT_PHY_TYPE_EHT_MU:
+-		/* TODO: currently report rx rate with HE rate */
+ 		status->nss = nss;
+-		status->encoding = RX_ENC_HE;
+-		bw = min_t(int, bw, IEEE80211_STA_RX_BW_160);
+-		i = min_t(int, i & 0xf, 11);
++		status->encoding = RX_ENC_EHT;
++		i &= GENMASK(3, 0);
++
++		if (gi <= NL80211_RATE_INFO_EHT_GI_3_2)
++			status->eht.gi = gi;
+ 		break;
+ 	default:
+ 		return -EINVAL;
+-- 
+2.39.2
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0002-Revert-wifi-mt76-mt7996-rely-on-mt76_connac_txp_skb_.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0002-Revert-wifi-mt76-mt7996-rely-on-mt76_connac_txp_skb_.patch
deleted file mode 100644
index fb6581a..0000000
--- a/recipes-wifi/linux-mt76/files/patches-3.x/0002-Revert-wifi-mt76-mt7996-rely-on-mt76_connac_txp_skb_.patch
+++ /dev/null
@@ -1,46 +0,0 @@
-From 9c2313ddded0179ae1a9e6112e2762a1a3e958d7 Mon Sep 17 00:00:00 2001
-From: Shayne Chen <shayne.chen@mediatek.com>
-Date: Fri, 3 Feb 2023 11:01:11 +0800
-Subject: [PATCH 2/7] Revert "wifi: mt76: mt7996: rely on
- mt76_connac_txp_skb_unmap"
-
-This reverts commit bdb7dc38a6d150b5aa4b09b82a8954c6bb49ba4a.
----
- mt7996/mac.c | 14 +++++++++++++-
- 1 file changed, 13 insertions(+), 1 deletion(-)
-
-diff --git a/mt7996/mac.c b/mt7996/mac.c
-index 0d718598..df97d7cf 100644
---- a/mt7996/mac.c
-+++ b/mt7996/mac.c
-@@ -1187,6 +1187,18 @@ mt7996_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi)
- 		ieee80211_start_tx_ba_session(sta, tid, 0);
- }
- 
-+static void
-+mt7996_txp_skb_unmap(struct mt76_dev *dev, struct mt76_txwi_cache *t)
-+{
-+	struct mt76_connac_txp_common *txp;
-+	int i;
-+
-+	txp = mt7996_txwi_to_txp(dev, t);
-+	for (i = 0; i < txp->fw.nbuf; i++)
-+		dma_unmap_single(dev->dev, le32_to_cpu(txp->fw.buf[i]),
-+				 le16_to_cpu(txp->fw.len[i]), DMA_TO_DEVICE);
-+}
-+
- static void
- mt7996_txwi_free(struct mt7996_dev *dev, struct mt76_txwi_cache *t,
- 		 struct ieee80211_sta *sta, struct list_head *free_list)
-@@ -1196,7 +1208,7 @@ mt7996_txwi_free(struct mt7996_dev *dev, struct mt76_txwi_cache *t,
- 	__le32 *txwi;
- 	u16 wcid_idx;
- 
--	mt76_connac_txp_skb_unmap(mdev, t);
-+	mt7996_txp_skb_unmap(mdev, t);
- 	if (!t->skb)
- 		goto out;
- 
--- 
-2.25.1
-
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0002-wifi-mt76-mt7996-let-non-bufferable-MMPDUs-use-corre.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0002-wifi-mt76-mt7996-let-non-bufferable-MMPDUs-use-corre.patch
new file mode 100644
index 0000000..872ef03
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0002-wifi-mt76-mt7996-let-non-bufferable-MMPDUs-use-corre.patch
@@ -0,0 +1,92 @@
+From 5b858f7f944144d99fb0ca1ef26d6b8c6719890c Mon Sep 17 00:00:00 2001
+From: Shayne Chen <shayne.chen@mediatek.com>
+Date: Thu, 16 Feb 2023 10:52:22 +0800
+Subject: [PATCH 02/19] wifi: mt76: mt7996: let non-bufferable MMPDUs use
+ correct hw queue
+
+non-bufferable MMPDUs are expected to use ALTX hw queue, but current
+condition in mt7996_mac_write_txwi() won't let their tx descriptor
+be filled with correct q_idx. Fix this by passing qid parameter into
+the funciton.
+
+Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
+Change-Id: I18bd1a5ea698912c7aa8f4d4317d4a428d4ac440
+---
+ mt7996/mac.c    | 9 +++++----
+ mt7996/mcu.c    | 4 ++--
+ mt7996/mt7996.h | 3 ++-
+ 3 files changed, 9 insertions(+), 7 deletions(-)
+
+diff --git a/mt7996/mac.c b/mt7996/mac.c
+index d811b4e0..198eb711 100644
+--- a/mt7996/mac.c
++++ b/mt7996/mac.c
+@@ -982,7 +982,8 @@ mt7996_mac_write_txwi_80211(struct mt7996_dev *dev, __le32 *txwi,
+ }
+ 
+ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
+-			   struct sk_buff *skb, struct mt76_wcid *wcid, int pid,
++			   struct sk_buff *skb, struct mt76_wcid *wcid,
++			   enum mt76_txq_id qid, int pid,
+ 			   struct ieee80211_key_conf *key, u32 changed)
+ {
+ 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+@@ -1014,7 +1015,7 @@ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
+ 	} else if (beacon) {
+ 		p_fmt = MT_TX_TYPE_FW;
+ 		q_idx = MT_LMAC_BCN0;
+-	} else if (skb_get_queue_mapping(skb) >= MT_TXQ_PSD) {
++	} else if (qid >= MT_TXQ_PSD) {
+ 		p_fmt = MT_TX_TYPE_CT;
+ 		q_idx = MT_LMAC_ALTX0;
+ 	} else {
+@@ -1123,8 +1124,8 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
+ 	memset(txwi_ptr, 0, MT_TXD_SIZE);
+ 	/* Transmit non qos data by 802.11 header and need to fill txd by host*/
+ 	if (!is_8023 || pid >= MT_PACKET_ID_FIRST)
+-		mt7996_mac_write_txwi(dev, txwi_ptr, tx_info->skb, wcid, pid,
+-				      key, 0);
++		mt7996_mac_write_txwi(dev, txwi_ptr, tx_info->skb, wcid, qid,
++				      pid, key, 0);
+ 
+ 	txp = (struct mt76_connac_txp_common *)(txwi + MT_TXD_SIZE);
+ 	for (i = 0; i < nbuf; i++) {
+diff --git a/mt7996/mcu.c b/mt7996/mcu.c
+index 8ad51cbf..dbe10576 100644
+--- a/mt7996/mcu.c
++++ b/mt7996/mcu.c
+@@ -1906,7 +1906,7 @@ mt7996_mcu_beacon_cont(struct mt7996_dev *dev, struct ieee80211_vif *vif,
+ 	}
+ 
+ 	buf = (u8 *)bcn + sizeof(*bcn) - MAX_BEACON_SIZE;
+-	mt7996_mac_write_txwi(dev, (__le32 *)buf, skb, wcid, 0, NULL,
++	mt7996_mac_write_txwi(dev, (__le32 *)buf, skb, wcid, 0, 0, NULL,
+ 			      BSS_CHANGED_BEACON);
+ 	memcpy(buf + MT_TXD_SIZE, skb->data, skb->len);
+ }
+@@ -2115,7 +2115,7 @@ int mt7996_mcu_beacon_inband_discov(struct mt7996_dev *dev,
+ 
+ 	buf = (u8 *)tlv + sizeof(*discov) - MAX_INBAND_FRAME_SIZE;
+ 
+-	mt7996_mac_write_txwi(dev, (__le32 *)buf, skb, wcid, 0, NULL,
++	mt7996_mac_write_txwi(dev, (__le32 *)buf, skb, wcid, 0, 0, NULL,
+ 			      changed);
+ 
+ 	memcpy(buf + MT_TXD_SIZE, skb->data, skb->len);
+diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
+index 018dfd2b..d20aa5f2 100644
+--- a/mt7996/mt7996.h
++++ b/mt7996/mt7996.h
+@@ -487,7 +487,8 @@ void mt7996_mac_enable_nf(struct mt7996_dev *dev, u8 band);
+ void mt7996_mac_enable_rtscts(struct mt7996_dev *dev,
+ 			      struct ieee80211_vif *vif, bool enable);
+ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
+-			   struct sk_buff *skb, struct mt76_wcid *wcid, int pid,
++			   struct sk_buff *skb, struct mt76_wcid *wcid,
++			   enum mt76_txq_id qid, int pid,
+ 			   struct ieee80211_key_conf *key, u32 changed);
+ void mt7996_mac_set_timing(struct mt7996_phy *phy);
+ int mt7996_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
+-- 
+2.39.2
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0003-Revert-wifi-mt76-mt7996-rely-on-mt76_connac_txp_comm.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0003-Revert-wifi-mt76-mt7996-rely-on-mt76_connac_txp_comm.patch
deleted file mode 100644
index 43ea6c9..0000000
--- a/recipes-wifi/linux-mt76/files/patches-3.x/0003-Revert-wifi-mt76-mt7996-rely-on-mt76_connac_txp_comm.patch
+++ /dev/null
@@ -1,163 +0,0 @@
-From 8ba17e7cdbb5e921edd03102476cd8fb4f4e1b31 Mon Sep 17 00:00:00 2001
-From: Shayne Chen <shayne.chen@mediatek.com>
-Date: Fri, 3 Feb 2023 11:12:46 +0800
-Subject: [PATCH 3/7] Revert "wifi: mt76: mt7996: rely on
- mt76_connac_txp_common structure"
-
-This reverts commit 321edbb414dcc03d349bddd08916b7cc531802e8.
----
- mt7996/mac.c  | 38 +++++++++++++++++++-------------------
- mt7996/mac.h  | 15 +++++++++++++--
- mt7996/mmio.c |  2 +-
- 3 files changed, 33 insertions(+), 22 deletions(-)
-
-diff --git a/mt7996/mac.c b/mt7996/mac.c
-index df97d7cf..e5b5fed6 100644
---- a/mt7996/mac.c
-+++ b/mt7996/mac.c
-@@ -1088,8 +1088,8 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
- 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx_info->skb);
- 	struct ieee80211_key_conf *key = info->control.hw_key;
- 	struct ieee80211_vif *vif = info->control.vif;
--	struct mt76_connac_txp_common *txp;
- 	struct mt76_txwi_cache *t;
-+	struct mt7996_txp *txp;
- 	int id, i, pid, nbuf = tx_info->nbuf - 1;
- 	bool is_8023 = info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP;
- 	u8 *txwi = (u8 *)txwi_ptr;
-@@ -1123,35 +1123,35 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
- 		mt7996_mac_write_txwi(dev, txwi_ptr, tx_info->skb, wcid, pid,
- 				      key, 0);
- 
--	txp = (struct mt76_connac_txp_common *)(txwi + MT_TXD_SIZE);
-+	txp = (struct mt7996_txp *)(txwi + MT_TXD_SIZE);
- 	for (i = 0; i < nbuf; i++) {
--		txp->fw.buf[i] = cpu_to_le32(tx_info->buf[i + 1].addr);
--		txp->fw.len[i] = cpu_to_le16(tx_info->buf[i + 1].len);
-+		txp->buf[i] = cpu_to_le32(tx_info->buf[i + 1].addr);
-+		txp->len[i] = cpu_to_le16(tx_info->buf[i + 1].len);
- 	}
--	txp->fw.nbuf = nbuf;
-+	txp->nbuf = nbuf;
- 
--	txp->fw.flags = cpu_to_le16(MT_CT_INFO_FROM_HOST);
-+	txp->flags = cpu_to_le16(MT_CT_INFO_FROM_HOST);
- 
- 	if (!is_8023 || pid >= MT_PACKET_ID_FIRST)
--		txp->fw.flags |= cpu_to_le16(MT_CT_INFO_APPLY_TXD);
-+		txp->flags |= cpu_to_le16(MT_CT_INFO_APPLY_TXD);
- 
- 	if (!key)
--		txp->fw.flags |= cpu_to_le16(MT_CT_INFO_NONE_CIPHER_FRAME);
-+		txp->flags |= cpu_to_le16(MT_CT_INFO_NONE_CIPHER_FRAME);
- 
- 	if (!is_8023 && ieee80211_is_mgmt(hdr->frame_control))
--		txp->fw.flags |= cpu_to_le16(MT_CT_INFO_MGMT_FRAME);
-+		txp->flags |= cpu_to_le16(MT_CT_INFO_MGMT_FRAME);
- 
- 	if (vif) {
- 		struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
- 
--		txp->fw.bss_idx = mvif->mt76.idx;
-+		txp->bss_idx = mvif->mt76.idx;
- 	}
- 
--	txp->fw.token = cpu_to_le16(id);
-+	txp->token = cpu_to_le16(id);
- 	if (test_bit(MT_WCID_FLAG_4ADDR, &wcid->flags))
--		txp->fw.rept_wds_wcid = cpu_to_le16(wcid->idx);
-+		txp->rept_wds_wcid = cpu_to_le16(wcid->idx);
- 	else
--		txp->fw.rept_wds_wcid = cpu_to_le16(0xfff);
-+		txp->rept_wds_wcid = cpu_to_le16(0xfff);
- 	tx_info->skb = DMA_DUMMY_DATA;
- 
- 	/* pass partial skb header to fw */
-@@ -1190,13 +1190,13 @@ mt7996_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi)
- static void
- mt7996_txp_skb_unmap(struct mt76_dev *dev, struct mt76_txwi_cache *t)
- {
--	struct mt76_connac_txp_common *txp;
-+	struct mt7996_txp *txp;
- 	int i;
- 
- 	txp = mt7996_txwi_to_txp(dev, t);
--	for (i = 0; i < txp->fw.nbuf; i++)
--		dma_unmap_single(dev->dev, le32_to_cpu(txp->fw.buf[i]),
--				 le16_to_cpu(txp->fw.len[i]), DMA_TO_DEVICE);
-+	for (i = 0; i < txp->nbuf; i++)
-+		dma_unmap_single(dev->dev, le32_to_cpu(txp->buf[i]),
-+				 le16_to_cpu(txp->len[i]), DMA_TO_DEVICE);
- }
- 
- static void
-@@ -1586,11 +1586,11 @@ void mt7996_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue_entry *e)
- 
- 	/* error path */
- 	if (e->skb == DMA_DUMMY_DATA) {
--		struct mt76_connac_txp_common *txp;
- 		struct mt76_txwi_cache *t;
-+		struct mt7996_txp *txp;
- 
- 		txp = mt7996_txwi_to_txp(mdev, e->txwi);
--		t = mt76_token_put(mdev, le16_to_cpu(txp->fw.token));
-+		t = mt76_token_put(mdev, le16_to_cpu(txp->token));
- 		e->skb = t ? t->skb : NULL;
- 	}
- 
-diff --git a/mt7996/mac.h b/mt7996/mac.h
-index 10e08d66..9f688520 100644
---- a/mt7996/mac.h
-+++ b/mt7996/mac.h
-@@ -268,6 +268,17 @@ enum tx_mgnt_type {
- /* VHT/HE only use bits 0-3 */
- #define MT_TX_RATE_IDX			GENMASK(5, 0)
- 
-+struct mt7996_txp {
-+	__le16 flags;
-+	__le16 token;
-+	u8 bss_idx;
-+	__le16 rept_wds_wcid;
-+	u8 nbuf;
-+#define MT_TXP_MAX_BUF_NUM	6
-+	__le32 buf[MT_TXP_MAX_BUF_NUM];
-+	__le16 len[MT_TXP_MAX_BUF_NUM];
-+} __packed __aligned(4);
-+
- #define MT_TXFREE0_PKT_TYPE		GENMASK(31, 27)
- #define MT_TXFREE0_MSDU_CNT		GENMASK(25, 16)
- #define MT_TXFREE0_RX_BYTE		GENMASK(15, 0)
-@@ -371,7 +382,7 @@ struct mt7996_dfs_radar_spec {
- 	struct mt7996_dfs_pattern radar_pattern[16];
- };
- 
--static inline struct mt76_connac_txp_common *
-+static inline struct mt7996_txp *
- mt7996_txwi_to_txp(struct mt76_dev *dev, struct mt76_txwi_cache *t)
- {
- 	u8 *txwi;
-@@ -381,7 +392,7 @@ mt7996_txwi_to_txp(struct mt76_dev *dev, struct mt76_txwi_cache *t)
- 
- 	txwi = mt76_get_txwi_ptr(dev, t);
- 
--	return (struct mt76_connac_txp_common *)(txwi + MT_TXD_SIZE);
-+	return (struct mt7996_txp *)(txwi + MT_TXD_SIZE);
- }
- 
- #endif
-diff --git a/mt7996/mmio.c b/mt7996/mmio.c
-index 2237f50a..d8a2c1a7 100644
---- a/mt7996/mmio.c
-+++ b/mt7996/mmio.c
-@@ -318,7 +318,7 @@ struct mt7996_dev *mt7996_mmio_probe(struct device *pdev,
- {
- 	static const struct mt76_driver_ops drv_ops = {
- 		/* txwi_size = txd size + txp size */
--		.txwi_size = MT_TXD_SIZE + sizeof(struct mt76_connac_fw_txp),
-+		.txwi_size = MT_TXD_SIZE + sizeof(struct mt7996_txp),
- 		.drv_flags = MT_DRV_TXWI_NO_FREE |
- 			     MT_DRV_HW_MGMT_TXQ,
- 		.survey_flags = SURVEY_INFO_TIME_TX |
--- 
-2.25.1
-
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0003-wifi-mt76-mt7996-reduce-repeated-bss_info-and-sta_re.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0003-wifi-mt76-mt7996-reduce-repeated-bss_info-and-sta_re.patch
new file mode 100644
index 0000000..c91eb62
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0003-wifi-mt76-mt7996-reduce-repeated-bss_info-and-sta_re.patch
@@ -0,0 +1,67 @@
+From 09ef1c1248c8b38c5f2c6e624397e64e8938349f Mon Sep 17 00:00:00 2001
+From: Shayne Chen <shayne.chen@mediatek.com>
+Date: Thu, 16 Feb 2023 00:39:01 +0800
+Subject: [PATCH 03/19] wifi: mt76: mt7996: reduce repeated bss_info and
+ sta_rec commands
+
+Refine the flow of setting bss_info and sta_rec commands to prevent from
+sending duplicated commands, especially for station mode.
+
+Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
+Change-Id: Iffd2c81f9ec98284793e75f4b7d39e9618977024
+---
+ mt7996/main.c | 21 ++++++---------------
+ 1 file changed, 6 insertions(+), 15 deletions(-)
+
+diff --git a/mt7996/main.c b/mt7996/main.c
+index 3e4da035..e80ee19e 100644
+--- a/mt7996/main.c
++++ b/mt7996/main.c
+@@ -241,8 +241,8 @@ static void mt7996_remove_interface(struct ieee80211_hw *hw,
+ 	struct mt7996_phy *phy = mt7996_hw_phy(hw);
+ 	int idx = msta->wcid.idx;
+ 
+-	mt7996_mcu_add_bss_info(phy, vif, false);
+ 	mt7996_mcu_add_sta(dev, vif, NULL, false);
++	mt7996_mcu_add_bss_info(phy, vif, false);
+ 
+ 	if (vif == phy->monitor_vif)
+ 		phy->monitor_vif = NULL;
+@@ -510,17 +510,13 @@ static void mt7996_bss_info_changed(struct ieee80211_hw *hw,
+ 	/* station mode uses BSSID to map the wlan entry to a peer,
+ 	 * and then peer references bss_info_rfch to set bandwidth cap.
+ 	 */
+-	if (changed & BSS_CHANGED_BSSID &&
+-	    vif->type == NL80211_IFTYPE_STATION) {
+-		bool join = !is_zero_ether_addr(info->bssid);
+-
+-		mt7996_mcu_add_bss_info(phy, vif, join);
+-		mt7996_mcu_add_sta(dev, vif, NULL, join);
++	if ((changed & BSS_CHANGED_BSSID && !is_zero_ether_addr(info->bssid)) ||
++	    (changed & BSS_CHANGED_ASSOC && vif->cfg.assoc) ||
++	    (changed & BSS_CHANGED_BEACON_ENABLED && info->enable_beacon)) {
++		mt7996_mcu_add_bss_info(phy, vif, true);
++		mt7996_mcu_add_sta(dev, vif, NULL, true);
+ 	}
+ 
+-	if (changed & BSS_CHANGED_ASSOC)
+-		mt7996_mcu_add_bss_info(phy, vif, vif->cfg.assoc);
+-
+ 	if (changed & BSS_CHANGED_ERP_CTS_PROT)
+ 		mt7996_mac_enable_rtscts(dev, vif, info->use_cts_prot);
+ 
+@@ -533,11 +529,6 @@ static void mt7996_bss_info_changed(struct ieee80211_hw *hw,
+ 		}
+ 	}
+ 
+-	if (changed & BSS_CHANGED_BEACON_ENABLED && info->enable_beacon) {
+-		mt7996_mcu_add_bss_info(phy, vif, true);
+-		mt7996_mcu_add_sta(dev, vif, NULL, true);
+-	}
+-
+ 	/* ensure that enable txcmd_mode after bss_info */
+ 	if (changed & (BSS_CHANGED_QOS | BSS_CHANGED_BEACON_ENABLED))
+ 		mt7996_mcu_set_tx(dev, vif);
+-- 
+2.39.2
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0004-wifi-mt76-mt7996-move-radio-enable-command-to-mt7996.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0004-wifi-mt76-mt7996-move-radio-enable-command-to-mt7996.patch
new file mode 100644
index 0000000..cc366e3
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0004-wifi-mt76-mt7996-move-radio-enable-command-to-mt7996.patch
@@ -0,0 +1,61 @@
+From c86f2243472f00fd2011cc44b89a87f7f6e2066a Mon Sep 17 00:00:00 2001
+From: Shayne Chen <shayne.chen@mediatek.com>
+Date: Wed, 15 Feb 2023 18:38:04 +0800
+Subject: [PATCH 04/19] wifi: mt76: mt7996: move radio enable command to
+ mt7996_start()
+
+The radio enable and disable commands are used for per-phy radio, so
+move them into mt7996_start() and mt7996_stop(), respectively.
+
+Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
+Change-Id: I610b170f5198e085eb86dbd371ee0745ac6ff50f
+---
+ mt7996/main.c | 11 ++++++-----
+ 1 file changed, 6 insertions(+), 5 deletions(-)
+
+diff --git a/mt7996/main.c b/mt7996/main.c
+index e80ee19e..a4fd9e24 100644
+--- a/mt7996/main.c
++++ b/mt7996/main.c
+@@ -46,6 +46,10 @@ static int mt7996_start(struct ieee80211_hw *hw)
+ 	if (ret)
+ 		goto out;
+ 
++	ret = mt7996_mcu_set_radio_en(phy, true);
++	if (ret)
++		goto out;
++
+ 	ret = mt7996_mcu_set_chan_info(phy, UNI_CHANNEL_RX_PATH);
+ 	if (ret)
+ 		goto out;
+@@ -77,6 +81,8 @@ static void mt7996_stop(struct ieee80211_hw *hw)
+ 
+ 	mutex_lock(&dev->mt76.mutex);
+ 
++	mt7996_mcu_set_radio_en(phy, false);
++
+ 	clear_bit(MT76_STATE_RUNNING, &phy->mt76->state);
+ 
+ 	ieee80211_iterate_interfaces(dev->mt76.hw,
+@@ -189,10 +195,6 @@ static int mt7996_add_interface(struct ieee80211_hw *hw,
+ 	if (ret)
+ 		goto out;
+ 
+-	ret = mt7996_mcu_set_radio_en(phy, true);
+-	if (ret)
+-		goto out;
+-
+ 	dev->mt76.vif_mask |= BIT_ULL(mvif->mt76.idx);
+ 	phy->omac_mask |= BIT_ULL(mvif->mt76.omac_idx);
+ 
+@@ -248,7 +250,6 @@ static void mt7996_remove_interface(struct ieee80211_hw *hw,
+ 		phy->monitor_vif = NULL;
+ 
+ 	mt7996_mcu_add_dev_info(phy, vif, false);
+-	mt7996_mcu_set_radio_en(phy, false);
+ 
+ 	rcu_assign_pointer(dev->mt76.wcid[idx], NULL);
+ 
+-- 
+2.39.2
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0005-wifi-mt76-connac-set-correct-muar_idx-for-connac3-ch.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0005-wifi-mt76-connac-set-correct-muar_idx-for-connac3-ch.patch
new file mode 100644
index 0000000..07dffec
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0005-wifi-mt76-connac-set-correct-muar_idx-for-connac3-ch.patch
@@ -0,0 +1,49 @@
+From 5d4c7f88b2066f4a8ec1769cf6c067d0e88abfa3 Mon Sep 17 00:00:00 2001
+From: Shayne Chen <shayne.chen@mediatek.com>
+Date: Thu, 16 Feb 2023 13:53:14 +0800
+Subject: [PATCH 05/19] wifi: mt76: connac: set correct muar_idx for connac3
+ chipset
+
+Set the muar_idx to 0xe for the hw bcast/mcast station entry of connac3
+chipset.
+
+Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
+Change-Id: I7054c3b3c64ec447cc280ea810f4958afdfa9e02
+---
+ mt76_connac.h     | 5 +++++
+ mt76_connac_mcu.c | 3 +++
+ 2 files changed, 8 insertions(+)
+
+diff --git a/mt76_connac.h b/mt76_connac.h
+index b339c50b..c8b91e86 100644
+--- a/mt76_connac.h
++++ b/mt76_connac.h
+@@ -216,6 +216,11 @@ static inline bool is_connac_v1(struct mt76_dev *dev)
+ 	return is_mt7615(dev) || is_mt7663(dev) || is_mt7622(dev);
+ }
+ 
++static inline bool is_connac_v3(struct mt76_dev *dev)
++{
++	return is_mt7996(dev);
++}
++
+ static inline bool is_mt76_fw_txp(struct mt76_dev *dev)
+ {
+ 	switch (mt76_chip(dev)) {
+diff --git a/mt76_connac_mcu.c b/mt76_connac_mcu.c
+index efb9bfaa..4e4f6b35 100644
+--- a/mt76_connac_mcu.c
++++ b/mt76_connac_mcu.c
+@@ -281,6 +281,9 @@ __mt76_connac_mcu_alloc_sta_req(struct mt76_dev *dev, struct mt76_vif *mvif,
+ 	};
+ 	struct sk_buff *skb;
+ 
++	if (is_connac_v3(dev) && !wcid->sta)
++		hdr.muar_idx = 0xe;
++
+ 	mt76_connac_mcu_get_wlan_idx(dev, wcid, &hdr.wlan_idx_lo,
+ 				     &hdr.wlan_idx_hi);
+ 	skb = mt76_mcu_msg_alloc(dev, NULL, len);
+-- 
+2.39.2
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0005-wifi-mt76-mt7996-set-txd-v1.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0005-wifi-mt76-mt7996-set-txd-v1.patch
deleted file mode 100644
index 8fddb93..0000000
--- a/recipes-wifi/linux-mt76/files/patches-3.x/0005-wifi-mt76-mt7996-set-txd-v1.patch
+++ /dev/null
@@ -1,48 +0,0 @@
-From d8bef73f22f88bf857698f4018db3aed6a2fca2d Mon Sep 17 00:00:00 2001
-From: Peter Chiu <chui-hao.chiu@mediatek.com>
-Date: Tue, 29 Nov 2022 09:13:32 +0800
-Subject: [PATCH 5/7] wifi: mt76: mt7996: set txd v1
-
----
- mt7996/mac.c | 3 +++
- mt7996/mac.h | 3 ++-
- 2 files changed, 5 insertions(+), 1 deletion(-)
-
-diff --git a/mt7996/mac.c b/mt7996/mac.c
-index e5b5fed6..51337dde 100644
---- a/mt7996/mac.c
-+++ b/mt7996/mac.c
-@@ -1092,6 +1092,7 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
- 	struct mt7996_txp *txp;
- 	int id, i, pid, nbuf = tx_info->nbuf - 1;
- 	bool is_8023 = info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP;
-+	__le32 *txd = (__le32 *)txwi_ptr;
- 	u8 *txwi = (u8 *)txwi_ptr;
- 
- 	if (unlikely(tx_info->skb->len <= ETH_HLEN))
-@@ -1123,6 +1124,8 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
- 		mt7996_mac_write_txwi(dev, txwi_ptr, tx_info->skb, wcid, pid,
- 				      key, 0);
- 
-+	txd[0] |= le32_encode_bits(1, MT_TXD0_VER);
-+
- 	txp = (struct mt7996_txp *)(txwi + MT_TXD_SIZE);
- 	for (i = 0; i < nbuf; i++) {
- 		txp->buf[i] = cpu_to_le32(tx_info->buf[i + 1].addr);
-diff --git a/mt7996/mac.h b/mt7996/mac.h
-index 9f688520..470b701a 100644
---- a/mt7996/mac.h
-+++ b/mt7996/mac.h
-@@ -186,7 +186,8 @@ enum tx_mgnt_type {
- 
- #define MT_TXD0_Q_IDX			GENMASK(31, 25)
- #define MT_TXD0_PKT_FMT			GENMASK(24, 23)
--#define MT_TXD0_ETH_TYPE_OFFSET		GENMASK(22, 16)
-+#define MT_TXD0_VER			GENMASK(22, 19)
-+#define MT_TXD0_ETH_TYPE_OFFSET		GENMASK(18, 16)
- #define MT_TXD0_TX_BYTES		GENMASK(15, 0)
- 
- #define MT_TXD1_FIXED_RATE		BIT(31)
--- 
-2.25.1
-
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0006-wifi-mt76-mt7996-fix-pointer-calculation-in-ie-count.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0006-wifi-mt76-mt7996-fix-pointer-calculation-in-ie-count.patch
new file mode 100644
index 0000000..65596f4
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0006-wifi-mt76-mt7996-fix-pointer-calculation-in-ie-count.patch
@@ -0,0 +1,34 @@
+From 00d76d4dc3cdb719b5fc234d9cf3bbef39f448ce Mon Sep 17 00:00:00 2001
+From: Peter Chiu <chui-hao.chiu@mediatek.com>
+Date: Mon, 13 Feb 2023 14:48:10 +0800
+Subject: [PATCH 06/19] wifi: mt76: mt7996: fix pointer calculation in ie
+ countdown event
+
+Fix the tail and data pointers. The rxd->len in mt7996_mcu_rxd does not
+include the length of general rxd. It only includes the length of
+firmware event rxd. Use the skb->length to get the correct length.
+
+Signed-off-by: Peter Chiu <chui-hao.chiu@mediatek.com>
+Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
+Change-Id: I832194559e63e6b49b7ee00dc9c606b6106d8669
+---
+ mt7996/mcu.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/mt7996/mcu.c b/mt7996/mcu.c
+index dbe10576..2e25572a 100644
+--- a/mt7996/mcu.c
++++ b/mt7996/mcu.c
+@@ -422,7 +422,8 @@ mt7996_mcu_ie_countdown(struct mt7996_dev *dev, struct sk_buff *skb)
+ 	if (hdr->band && dev->mt76.phys[hdr->band])
+ 		mphy = dev->mt76.phys[hdr->band];
+ 
+-	tail = skb->data + le16_to_cpu(rxd->len);
++	tail = skb->data + skb->len;
++	data += sizeof(struct header);
+ 	while (data + sizeof(struct tlv) < tail && le16_to_cpu(tlv->len)) {
+ 		switch (le16_to_cpu(tlv->tag)) {
+ 		case UNI_EVENT_IE_COUNTDOWN_CSA:
+-- 
+2.39.2
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0007-wifi-mt76-mt7996-remove-mt7996_mcu_set_pm.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0007-wifi-mt76-mt7996-remove-mt7996_mcu_set_pm.patch
new file mode 100644
index 0000000..7988196
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0007-wifi-mt76-mt7996-remove-mt7996_mcu_set_pm.patch
@@ -0,0 +1,96 @@
+From c2dafe57df1726acb80e30987bc8d678b86af14a Mon Sep 17 00:00:00 2001
+From: Peter Chiu <chui-hao.chiu@mediatek.com>
+Date: Tue, 14 Feb 2023 18:35:43 +0800
+Subject: [PATCH 07/19] wifi: mt76: mt7996: remove mt7996_mcu_set_pm()
+
+Currently using BSS_INFO_PS command will sometimes cause packet drop in
+hw rx queue.
+Temporarily remove this function until finding the cause.
+
+Signed-off-by: Peter Chiu <chui-hao.chiu@mediatek.com>
+Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
+Change-Id: I863fc1edb18e4d7b5dac20140dd0904875e1323c
+---
+ mt7996/main.c   |  8 --------
+ mt7996/mcu.c    | 26 --------------------------
+ mt7996/mt7996.h |  1 -
+ 3 files changed, 35 deletions(-)
+
+diff --git a/mt7996/main.c b/mt7996/main.c
+index a4fd9e24..44d23e1d 100644
+--- a/mt7996/main.c
++++ b/mt7996/main.c
+@@ -56,10 +56,6 @@ static int mt7996_start(struct ieee80211_hw *hw)
+ 
+ 	set_bit(MT76_STATE_RUNNING, &phy->mt76->state);
+ 
+-	ieee80211_iterate_interfaces(dev->mt76.hw,
+-				     IEEE80211_IFACE_ITER_RESUME_ALL,
+-				     mt7996_mcu_set_pm, dev->mt76.hw);
+-
+ 	ieee80211_queue_delayed_work(hw, &phy->mt76->mac_work,
+ 				     MT7996_WATCHDOG_TIME);
+ 
+@@ -85,10 +81,6 @@ static void mt7996_stop(struct ieee80211_hw *hw)
+ 
+ 	clear_bit(MT76_STATE_RUNNING, &phy->mt76->state);
+ 
+-	ieee80211_iterate_interfaces(dev->mt76.hw,
+-				     IEEE80211_IFACE_ITER_RESUME_ALL,
+-				     mt7996_mcu_set_pm, dev->mt76.hw);
+-
+ 	mutex_unlock(&dev->mt76.mutex);
+ }
+ 
+diff --git a/mt7996/mcu.c b/mt7996/mcu.c
+index 2e25572a..f6947438 100644
+--- a/mt7996/mcu.c
++++ b/mt7996/mcu.c
+@@ -3577,32 +3577,6 @@ int mt7996_mcu_twt_agrt_update(struct mt7996_dev *dev,
+ 				 &req, sizeof(req), true);
+ }
+ 
+-void mt7996_mcu_set_pm(void *priv, u8 *mac, struct ieee80211_vif *vif)
+-{
+-#define EXIT_PM_STATE	0
+-#define ENTER_PM_STATE	1
+-	struct ieee80211_hw *hw = priv;
+-	struct mt7996_dev *dev = mt7996_hw_dev(hw);
+-	struct mt7996_phy *phy = mt7996_hw_phy(hw);
+-	struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
+-	struct bss_power_save *ps;
+-	struct sk_buff *skb;
+-	struct tlv *tlv;
+-	bool running = test_bit(MT76_STATE_RUNNING, &phy->mt76->state);
+-
+-	skb = __mt7996_mcu_alloc_bss_req(&dev->mt76, &mvif->mt76,
+-					 MT7996_BSS_UPDATE_MAX_SIZE);
+-	if (IS_ERR(skb))
+-		return;
+-
+-	tlv = mt7996_mcu_add_uni_tlv(skb, UNI_BSS_INFO_PS, sizeof(*ps));
+-	ps = (struct bss_power_save *)tlv;
+-	ps->profile = running ? EXIT_PM_STATE : ENTER_PM_STATE;
+-
+-	mt76_mcu_skb_send_msg(&dev->mt76, skb,
+-			      MCU_WMWA_UNI_CMD(BSS_INFO_UPDATE), true);
+-}
+-
+ int mt7996_mcu_set_rts_thresh(struct mt7996_phy *phy, u32 val)
+ {
+ 	struct {
+diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
+index d20aa5f2..f9d8fbfd 100644
+--- a/mt7996/mt7996.h
++++ b/mt7996/mt7996.h
+@@ -432,7 +432,6 @@ int mt7996_mcu_set_pulse_th(struct mt7996_dev *dev,
+ int mt7996_mcu_set_radar_th(struct mt7996_dev *dev, int index,
+ 			    const struct mt7996_dfs_pattern *pattern);
+ int mt7996_mcu_set_radio_en(struct mt7996_phy *phy, bool enable);
+-void mt7996_mcu_set_pm(void *priv, u8 *mac, struct ieee80211_vif *vif);
+ int mt7996_mcu_set_rts_thresh(struct mt7996_phy *phy, u32 val);
+ int mt7996_mcu_get_chan_mib_info(struct mt7996_phy *phy, bool chan_switch);
+ int mt7996_mcu_rdd_cmd(struct mt7996_dev *dev, int cmd, u8 index,
+-- 
+2.39.2
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0004-wifi-mt76-mt7996-add-muru-support.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0008-wifi-mt76-mt7996-add-muru-support.patch
similarity index 91%
rename from recipes-wifi/linux-mt76/files/patches-3.x/0004-wifi-mt76-mt7996-add-muru-support.patch
rename to recipes-wifi/linux-mt76/files/patches-3.x/0008-wifi-mt76-mt7996-add-muru-support.patch
index dab5182..20d7f48 100644
--- a/recipes-wifi/linux-mt76/files/patches-3.x/0004-wifi-mt76-mt7996-add-muru-support.patch
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0008-wifi-mt76-mt7996-add-muru-support.patch
@@ -1,7 +1,7 @@
-From 7c8b8c77489ef907f2122c5d0edb7ff5e0fed177 Mon Sep 17 00:00:00 2001
+From b587a9f1615585f8db0fa98cc46791a3253ddac7 Mon Sep 17 00:00:00 2001
 From: MeiChia Chiu <MeiChia.Chiu@mediatek.com>
 Date: Mon, 28 Nov 2022 14:36:09 +0800
-Subject: [PATCH 4/7] wifi: mt76: mt7996: add muru support
+Subject: [PATCH 08/19] wifi: mt76: mt7996: add muru support
 
 Add sta_rec_muru() and related phy cap for MU and RU support.
 
@@ -15,7 +15,7 @@
  3 files changed, 73 insertions(+), 2 deletions(-)
 
 diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
-index a5e6ee4d..39667840 100644
+index 40a99e0c..6f30a0fb 100644
 --- a/mt76_connac_mcu.h
 +++ b/mt76_connac_mcu.h
 @@ -518,7 +518,8 @@ struct sta_rec_muru {
@@ -29,10 +29,10 @@
  
  	struct {
 diff --git a/mt7996/mcu.c b/mt7996/mcu.c
-index dbe30832..394dd15c 100644
+index f6947438..b6bd36c2 100644
 --- a/mt7996/mcu.c
 +++ b/mt7996/mcu.c
-@@ -1049,6 +1049,63 @@ mt7996_mcu_sta_amsdu_tlv(struct mt7996_dev *dev, struct sk_buff *skb,
+@@ -1050,6 +1050,63 @@ mt7996_mcu_sta_amsdu_tlv(struct mt7996_dev *dev, struct sk_buff *skb,
  	}
  }
  
@@ -96,7 +96,7 @@
  static inline bool
  mt7996_is_ebf_supported(struct mt7996_phy *phy, struct ieee80211_vif *vif,
  			struct ieee80211_sta *sta, bool bfee)
-@@ -1721,7 +1778,8 @@ int mt7996_mcu_add_sta(struct mt7996_dev *dev, struct ieee80211_vif *vif,
+@@ -1722,7 +1779,8 @@ int mt7996_mcu_add_sta(struct mt7996_dev *dev, struct ieee80211_vif *vif,
  		mt7996_mcu_sta_he_6g_tlv(skb, sta);
  		/* starec eht */
  		mt7996_mcu_sta_eht_tlv(skb, sta);
@@ -106,7 +106,7 @@
  		/* starec bfee */
  		mt7996_mcu_sta_bfee_tlv(dev, skb, vif, sta);
  		/* starec hdr trans */
-@@ -2004,6 +2062,15 @@ mt7996_mcu_beacon_check_caps(struct mt7996_phy *phy, struct ieee80211_vif *vif,
+@@ -2005,6 +2063,15 @@ mt7996_mcu_beacon_check_caps(struct mt7996_phy *phy, struct ieee80211_vif *vif,
  		vc->eht_su_ebfee =
  			EHT_PHY(CAP0_SU_BEAMFORMEE, eht->phy_cap_info[0]) &&
  			EHT_PHY(CAP0_SU_BEAMFORMEE, pe->phy_cap_info[0]);
@@ -123,7 +123,7 @@
  }
  
 diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
-index 13f22432..64a804a4 100644
+index f9d8fbfd..997a0bf0 100644
 --- a/mt7996/mt7996.h
 +++ b/mt7996/mt7996.h
 @@ -125,6 +125,9 @@ struct mt7996_vif_cap {
@@ -137,5 +137,5 @@
  
  struct mt7996_vif {
 -- 
-2.25.1
+2.39.2
 
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0009-wifi-mt76-mt7996-set-txd-v1.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0009-wifi-mt76-mt7996-set-txd-v1.patch
new file mode 100644
index 0000000..cc7548a
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0009-wifi-mt76-mt7996-set-txd-v1.patch
@@ -0,0 +1,48 @@
+From 9a1a54c7df9babadd8f6ae066deb2b5e49715cb0 Mon Sep 17 00:00:00 2001
+From: Bo Jiao <Bo.Jiao@mediatek.com>
+Date: Mon, 6 Feb 2023 10:40:33 +0800
+Subject: [PATCH 09/19] wifi: mt76: mt7996: set txd v1
+
+---
+ mt7996/mac.c | 3 +++
+ mt7996/mac.h | 3 ++-
+ 2 files changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/mt7996/mac.c b/mt7996/mac.c
+index 198eb711..40ef5e4b 100644
+--- a/mt7996/mac.c
++++ b/mt7996/mac.c
+@@ -1096,6 +1096,7 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
+ 	struct mt76_txwi_cache *t;
+ 	int id, i, pid, nbuf = tx_info->nbuf - 1;
+ 	bool is_8023 = info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP;
++	__le32 *txd = (__le32 *)txwi_ptr;
+ 	u8 *txwi = (u8 *)txwi_ptr;
+ 
+ 	if (unlikely(tx_info->skb->len <= ETH_HLEN))
+@@ -1127,6 +1128,8 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
+ 		mt7996_mac_write_txwi(dev, txwi_ptr, tx_info->skb, wcid, qid,
+ 				      pid, key, 0);
+ 
++	txd[0] |= le32_encode_bits(1, MT_TXD0_VER);
++
+ 	txp = (struct mt76_connac_txp_common *)(txwi + MT_TXD_SIZE);
+ 	for (i = 0; i < nbuf; i++) {
+ 		txp->fw.buf[i] = cpu_to_le32(tx_info->buf[i + 1].addr);
+diff --git a/mt7996/mac.h b/mt7996/mac.h
+index 2cc218f7..4914d3e5 100644
+--- a/mt7996/mac.h
++++ b/mt7996/mac.h
+@@ -183,7 +183,8 @@ enum tx_mgnt_type {
+ 
+ #define MT_TXD0_Q_IDX			GENMASK(31, 25)
+ #define MT_TXD0_PKT_FMT			GENMASK(24, 23)
+-#define MT_TXD0_ETH_TYPE_OFFSET		GENMASK(22, 16)
++#define MT_TXD0_VER			GENMASK(22, 19)
++#define MT_TXD0_ETH_TYPE_OFFSET		GENMASK(18, 16)
+ #define MT_TXD0_TX_BYTES		GENMASK(15, 0)
+ 
+ #define MT_TXD1_FIXED_RATE		BIT(31)
+-- 
+2.39.2
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0010-wifi-mt76-mt7996-add-thermal-protection-support.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0010-wifi-mt76-mt7996-add-thermal-protection-support.patch
new file mode 100644
index 0000000..319eb1f
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0010-wifi-mt76-mt7996-add-thermal-protection-support.patch
@@ -0,0 +1,437 @@
+From 1744b5397ad4240ce41bf88bfff2eef34d76d587 Mon Sep 17 00:00:00 2001
+From: Howard Hsu <howard-yh.hsu@mediatek.com>
+Date: Thu, 2 Feb 2023 21:20:31 +0800
+Subject: [PATCH 10/19] wifi: mt76: mt7996: add thermal protection support
+
+This commit includes the following changes:
+1. implement MTK thermal protection driver API
+2. support Linux cooling device control
+
+Change-Id: I8fecc28f5b17ee50ae4644d1dd17d188dd694731
+---
+ mt76_connac_mcu.h |   1 +
+ mt7996/init.c     | 105 +++++++++++++++++++++++++++++++++++++++++++++
+ mt7996/main.c     |   8 ++++
+ mt7996/mcu.c      | 106 ++++++++++++++++++++++++++++++++++++++++++++++
+ mt7996/mcu.h      |  44 +++++++++++++++++++
+ mt7996/mt7996.h   |  15 +++++++
+ 6 files changed, 279 insertions(+)
+
+diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
+index 6f30a0fb..fa10d823 100644
+--- a/mt76_connac_mcu.h
++++ b/mt76_connac_mcu.h
+@@ -1009,6 +1009,7 @@ enum {
+ 	MCU_UNI_EVENT_FW_LOG_2_HOST = 0x04,
+ 	MCU_UNI_EVENT_IE_COUNTDOWN = 0x09,
+ 	MCU_UNI_EVENT_RDD_REPORT = 0x11,
++	MCU_UNI_EVENT_THERMAL = 0x35,
+ };
+ 
+ #define MCU_UNI_CMD_EVENT			BIT(1)
+diff --git a/mt7996/init.c b/mt7996/init.c
+index 946da93e..5a22cd81 100644
+--- a/mt7996/init.c
++++ b/mt7996/init.c
+@@ -41,6 +41,98 @@ static const struct ieee80211_iface_combination if_comb[] = {
+ 	}
+ };
+ 
++static int
++mt7996_thermal_get_max_throttle_state(struct thermal_cooling_device *cdev,
++				      unsigned long *state)
++{
++	*state = MT7996_CDEV_THROTTLE_MAX;
++
++	return 0;
++}
++
++static int
++mt7996_thermal_get_cur_throttle_state(struct thermal_cooling_device *cdev,
++				      unsigned long *state)
++{
++	struct mt7996_phy *phy = cdev->devdata;
++
++	*state = phy->cdev_state;
++
++	return 0;
++}
++
++static int
++mt7996_thermal_set_cur_throttle_state(struct thermal_cooling_device *cdev,
++				      unsigned long state)
++{
++	struct mt7996_phy *phy = cdev->devdata;
++	u8 throttling = MT7996_THERMAL_THROTTLE_MAX - state;
++	int ret;
++
++	if (state > MT7996_CDEV_THROTTLE_MAX) {
++		dev_err(phy->dev->mt76.dev,
++			"please specify a valid throttling state\n");
++		return -EINVAL;
++	}
++
++	if (state == phy->cdev_state)
++		return 0;
++
++	/*
++	 * cooling_device convention: 0 = no cooling, more = more cooling
++	 * mcu convention: 1 = max cooling, more = less cooling
++	 */
++	ret = mt7996_mcu_set_thermal_throttling(phy, throttling);
++	if (ret)
++		return ret;
++
++	phy->cdev_state = state;
++
++	return 0;
++}
++
++static const struct thermal_cooling_device_ops mt7996_thermal_ops = {
++	.get_max_state = mt7996_thermal_get_max_throttle_state,
++	.get_cur_state = mt7996_thermal_get_cur_throttle_state,
++	.set_cur_state = mt7996_thermal_set_cur_throttle_state,
++};
++
++static void mt7996_unregister_thermal(struct mt7996_phy *phy)
++{
++	struct wiphy *wiphy = phy->mt76->hw->wiphy;
++
++	if (!phy->cdev)
++	    return;
++
++	sysfs_remove_link(&wiphy->dev.kobj, "cooling_device");
++	thermal_cooling_device_unregister(phy->cdev);
++}
++
++static int mt7996_thermal_init(struct mt7996_phy *phy)
++{
++	struct wiphy *wiphy = phy->mt76->hw->wiphy;
++	struct thermal_cooling_device *cdev;
++	const char *name;
++
++	name = devm_kasprintf(&wiphy->dev, GFP_KERNEL, "mt7996_%s",
++			      wiphy_name(wiphy));
++
++	cdev = thermal_cooling_device_register(name, phy, &mt7996_thermal_ops);
++	if (!IS_ERR(cdev)) {
++		if (sysfs_create_link(&wiphy->dev.kobj, &cdev->device.kobj,
++				      "cooling_device") < 0)
++			thermal_cooling_device_unregister(cdev);
++		else
++			phy->cdev = cdev;
++	}
++
++	/* initialize critical/maximum high temperature */
++	phy->throttle_temp[MT7996_CRIT_TEMP_IDX] = MT7996_CRIT_TEMP;
++	phy->throttle_temp[MT7996_MAX_TEMP_IDX] = MT7996_MAX_TEMP;
++
++	return 0;
++}
++
+ static void mt7996_led_set_config(struct led_classdev *led_cdev,
+ 				  u8 delay_on, u8 delay_off)
+ {
+@@ -367,6 +459,10 @@ static int mt7996_register_phy(struct mt7996_dev *dev, struct mt7996_phy *phy,
+ 	if (ret)
+ 		goto error;
+ 
++	ret = mt7996_thermal_init(phy);
++	if (ret)
++		goto error;
++
+ 	ret = mt7996_init_debugfs(phy);
+ 	if (ret)
+ 		goto error;
+@@ -387,6 +483,8 @@ mt7996_unregister_phy(struct mt7996_phy *phy, enum mt76_band_id band)
+ 	if (!phy)
+ 		return;
+ 
++	mt7996_unregister_thermal(phy);
++
+ 	mphy = phy->dev->mt76.phys[band];
+ 	mt76_unregister_phy(mphy);
+ 	ieee80211_free_hw(mphy->hw);
+@@ -876,6 +974,10 @@ int mt7996_register_device(struct mt7996_dev *dev)
+ 	if (ret)
+ 		return ret;
+ 
++	ret = mt7996_thermal_init(&dev->phy);
++	if (ret)
++		return ret;
++
+ 	ieee80211_queue_work(mt76_hw(dev), &dev->init_work);
+ 
+ 	ret = mt7996_register_phy(dev, mt7996_phy2(dev), MT_BAND1);
+@@ -893,6 +995,9 @@ void mt7996_unregister_device(struct mt7996_dev *dev)
+ {
+ 	mt7996_unregister_phy(mt7996_phy3(dev), MT_BAND2);
+ 	mt7996_unregister_phy(mt7996_phy2(dev), MT_BAND1);
++
++	mt7996_unregister_thermal(&dev->phy);
++
+ 	mt76_unregister_device(&dev->mt76);
+ 	mt7996_mcu_exit(dev);
+ 	mt7996_tx_token_put(dev);
+diff --git a/mt7996/main.c b/mt7996/main.c
+index 44d23e1d..d8d578c0 100644
+--- a/mt7996/main.c
++++ b/mt7996/main.c
+@@ -54,6 +54,14 @@ static int mt7996_start(struct ieee80211_hw *hw)
+ 	if (ret)
+ 		goto out;
+ 
++	ret = mt7996_mcu_set_thermal_throttling(phy, MT7996_THERMAL_THROTTLE_MAX);
++	if (ret)
++		goto out;
++
++	ret = mt7996_mcu_set_thermal_protect(phy);
++	if (ret)
++		goto out;
++
+ 	set_bit(MT76_STATE_RUNNING, &phy->mt76->state);
+ 
+ 	ieee80211_queue_delayed_work(hw, &phy->mt76->mac_work,
+diff --git a/mt7996/mcu.c b/mt7996/mcu.c
+index b6bd36c2..3820a63e 100644
+--- a/mt7996/mcu.c
++++ b/mt7996/mcu.c
+@@ -443,6 +443,34 @@ mt7996_mcu_ie_countdown(struct mt7996_dev *dev, struct sk_buff *skb)
+ 	}
+ }
+ 
++static void
++mt7996_mcu_rx_thermal_notify(struct mt7996_dev *dev, struct sk_buff *skb)
++{
++#define THERMAL_NOTIFY_TAG 0x4
++#define THERMAL_NOTIFY 0x2
++	struct mt76_phy *mphy = &dev->mt76.phy;
++	struct mt7996_mcu_thermal_notify *n;
++	struct mt7996_phy *phy;
++
++	n = (struct mt7996_mcu_thermal_notify *)skb->data;
++
++	if (n->tag != THERMAL_NOTIFY_TAG)
++		return;
++
++	if (n->event_id != THERMAL_NOTIFY)
++		return;
++
++	if (n->band_idx > MT_BAND2)
++		return;
++
++	mphy = dev->mt76.phys[n->band_idx];
++	if (!mphy)
++		return;
++
++	phy = (struct mt7996_phy *)mphy->priv;
++	phy->throttle_state = n->duty_percent;
++}
++
+ static void
+ mt7996_mcu_rx_ext_event(struct mt7996_dev *dev, struct sk_buff *skb)
+ {
+@@ -487,6 +515,9 @@ mt7996_mcu_uni_rx_unsolicited_event(struct mt7996_dev *dev, struct sk_buff *skb)
+ 	case MCU_UNI_EVENT_RDD_REPORT:
+ 		mt7996_mcu_rx_radar_detected(dev, skb);
+ 		break;
++	case MCU_UNI_EVENT_THERMAL:
++		mt7996_mcu_rx_thermal_notify(dev, skb);
++		break;
+ 	default:
+ 		break;
+ 	}
+@@ -3277,6 +3308,81 @@ out:
+ 	return 0;
+ }
+ 
++
++int mt7996_mcu_set_thermal_throttling(struct mt7996_phy *phy, u8 state)
++{
++	struct {
++		u8 _rsv[4];
++
++		__le16 tag;
++		__le16 len;
++
++		struct mt7996_mcu_thermal_ctrl ctrl;
++	} __packed req = {
++		.tag = cpu_to_le16(UNI_CMD_THERMAL_PROTECT_DUTY_CONFIG),
++		.len = cpu_to_le16(sizeof(req) - 4),
++		.ctrl = {
++			.band_idx = phy->mt76->band_idx,
++		},
++	};
++	int level, ret;
++
++	/* set duty cycle and level */
++	for (level = 0; level < 4; level++) {
++		req.ctrl.duty.duty_level = level;
++		req.ctrl.duty.duty_cycle = state;
++		state /= 2;
++
++		ret = mt76_mcu_send_msg(&phy->dev->mt76, MCU_WM_UNI_CMD(THERMAL),
++					&req, sizeof(req), false);
++		if (ret)
++			return ret;
++	}
++
++	return 0;
++}
++
++int mt7996_mcu_set_thermal_protect(struct mt7996_phy *phy)
++{
++#define SUSTAIN_PERIOD		10
++	struct {
++		u8 _rsv[4];
++
++		__le16 tag;
++		__le16 len;
++
++		struct mt7996_mcu_thermal_ctrl ctrl;
++		struct mt7996_mcu_thermal_enable enable;
++	} __packed req = {
++		.len = cpu_to_le16(sizeof(req) - 4 - sizeof(req.enable)),
++		.ctrl = {
++			.band_idx = phy->mt76->band_idx,
++			.type.protect_type = 1,
++			.type.trigger_type = 1,
++		},
++	};
++	int ret;
++
++	req.tag = cpu_to_le16(UNI_CMD_THERMAL_PROTECT_DISABLE);
++
++	ret = mt76_mcu_send_msg(&phy->dev->mt76, MCU_WM_UNI_CMD(THERMAL),
++				&req, sizeof(req) - sizeof(req.enable), false);
++	if (ret)
++		return ret;
++
++	/* set high-temperature trigger threshold */
++	req.tag = cpu_to_le16(UNI_CMD_THERMAL_PROTECT_ENABLE);
++	/* add a safety margin ~10 */
++	req.enable.restore_temp = cpu_to_le32(phy->throttle_temp[0] - 10);
++	req.enable.trigger_temp = cpu_to_le32(phy->throttle_temp[1]);
++	req.enable.sustain_time = cpu_to_le16(SUSTAIN_PERIOD);
++
++	req.len = cpu_to_le16(sizeof(req) - 4);
++
++	return mt76_mcu_send_msg(&phy->dev->mt76, MCU_WM_UNI_CMD(THERMAL),
++				 &req, sizeof(req), false);
++}
++
+ int mt7996_mcu_set_ser(struct mt7996_dev *dev, u8 action, u8 val, u8 band)
+ {
+ 	struct {
+diff --git a/mt7996/mcu.h b/mt7996/mcu.h
+index dd0c5ac5..7fefc28f 100644
+--- a/mt7996/mcu.h
++++ b/mt7996/mcu.h
+@@ -30,6 +30,28 @@ struct mt7996_mcu_uni_event {
+ 	__le32 status; /* 0: success, others: fail */
+ } __packed;
+ 
++struct mt7996_mcu_thermal_ctrl {
++	u8 ctrl_id;
++	u8 band_idx;
++	union {
++		struct {
++			u8 protect_type; /* 1: duty admit, 2: radio off */
++			u8 trigger_type; /* 0: low, 1: high */
++		} __packed type;
++		struct {
++			u8 duty_level;	/* level 0~3 */
++			u8 duty_cycle;
++		} __packed duty;
++	};
++} __packed;
++
++struct mt7996_mcu_thermal_enable {
++	__le32 trigger_temp;
++	__le32 restore_temp;
++	__le16 sustain_time;
++	u8 rsv[2];
++} __packed;
++
+ struct mt7996_mcu_csa_notify {
+ 	struct mt7996_mcu_rxd rxd;
+ 
+@@ -153,6 +175,22 @@ struct mt7996_mcu_mib {
+ 	__le64 data;
+ } __packed;
+ 
++struct mt7996_mcu_thermal_notify {
++	struct mt7996_mcu_rxd rxd;
++
++	u8 __rsv1[4];
++
++	__le16 tag;
++	__le16 len;
++
++	u8 event_id;
++	u8 band_idx;
++	u8 level_idx;
++	u8 duty_percent;
++	__le32 restore_temp;
++	u8 __rsv2[4];
++} __packed;
++
+ enum mt7996_chan_mib_offs {
+ 	UNI_MIB_OBSS_AIRTIME = 26,
+ 	UNI_MIB_NON_WIFI_TIME = 27,
+@@ -642,6 +680,12 @@ enum{
+ 	UNI_CMD_SR_SET_SIGA = 0xd0,
+ };
+ 
++enum {
++	UNI_CMD_THERMAL_PROTECT_ENABLE = 0x6,
++	UNI_CMD_THERMAL_PROTECT_DISABLE,
++	UNI_CMD_THERMAL_PROTECT_DUTY_CONFIG,
++};
++
+ enum {
+ 	UNI_CMD_ACCESS_REG_BASIC = 0x0,
+ 	UNI_CMD_ACCESS_RF_REG_BASIC,
+diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
+index 997a0bf0..25b20fa6 100644
+--- a/mt7996/mt7996.h
++++ b/mt7996/mt7996.h
+@@ -43,6 +43,13 @@
+ #define MT7996_MAX_STA_TWT_AGRT		8
+ #define MT7996_MAX_QUEUE		(__MT_RXQ_MAX +	__MT_MCUQ_MAX + 3)
+ 
++#define MT7996_THERMAL_THROTTLE_MAX	100
++#define MT7996_CDEV_THROTTLE_MAX	99
++#define MT7996_CRIT_TEMP_IDX		0
++#define MT7996_MAX_TEMP_IDX		1
++#define MT7996_CRIT_TEMP		110
++#define MT7996_MAX_TEMP			120
++
+ struct mt7996_vif;
+ struct mt7996_sta;
+ struct mt7996_dfs_pulse;
+@@ -211,6 +218,11 @@ struct mt7996_phy {
+ 
+ 	struct ieee80211_vif *monitor_vif;
+ 
++	struct thermal_cooling_device *cdev;
++	u8 cdev_state;
++	u8 throttle_state;
++	u32 throttle_temp[2]; /* 0: critical high, 1: maximum */
++
+ 	u32 rxfilter;
+ 	u64 omac_mask;
+ 
+@@ -437,6 +449,9 @@ int mt7996_mcu_set_radar_th(struct mt7996_dev *dev, int index,
+ int mt7996_mcu_set_radio_en(struct mt7996_phy *phy, bool enable);
+ int mt7996_mcu_set_rts_thresh(struct mt7996_phy *phy, u32 val);
+ int mt7996_mcu_get_chan_mib_info(struct mt7996_phy *phy, bool chan_switch);
++int mt7996_mcu_get_temperature(struct mt7996_phy *phy);
++int mt7996_mcu_set_thermal_throttling(struct mt7996_phy *phy, u8 state);
++int mt7996_mcu_set_thermal_protect(struct mt7996_phy *phy);
+ int mt7996_mcu_rdd_cmd(struct mt7996_dev *dev, int cmd, u8 index,
+ 		       u8 rx_sel, u8 val);
+ int mt7996_mcu_rdd_background_enable(struct mt7996_phy *phy,
+-- 
+2.39.2
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0011-wifi-mt76-mt7996-add-thermal-sensor-device-support.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0011-wifi-mt76-mt7996-add-thermal-sensor-device-support.patch
new file mode 100644
index 0000000..3de5b90
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0011-wifi-mt76-mt7996-add-thermal-sensor-device-support.patch
@@ -0,0 +1,184 @@
+From afdb511f0febad0e0cc5572461ab04794cf86852 Mon Sep 17 00:00:00 2001
+From: Howard Hsu <howard-yh.hsu@mediatek.com>
+Date: Thu, 2 Feb 2023 20:53:42 +0800
+Subject: [PATCH 11/19] wifi: mt76: mt7996: add thermal sensor device support
+
+---
+ mt7996/init.c | 87 +++++++++++++++++++++++++++++++++++++++++++++++++++
+ mt7996/mcu.c  | 41 ++++++++++++++++++++++++
+ 2 files changed, 128 insertions(+)
+
+diff --git a/mt7996/init.c b/mt7996/init.c
+index 5a22cd81..631ada15 100644
+--- a/mt7996/init.c
++++ b/mt7996/init.c
+@@ -4,6 +4,8 @@
+  */
+ 
+ #include <linux/etherdevice.h>
++#include <linux/hwmon.h>
++#include <linux/hwmon-sysfs.h>
+ #include <linux/thermal.h>
+ #include "mt7996.h"
+ #include "mac.h"
+@@ -41,6 +43,81 @@ static const struct ieee80211_iface_combination if_comb[] = {
+ 	}
+ };
+ 
++static ssize_t mt7996_thermal_temp_show(struct device *dev,
++					struct device_attribute *attr,
++					char *buf)
++{
++	struct mt7996_phy *phy = dev_get_drvdata(dev);
++	int i = to_sensor_dev_attr(attr)->index;
++	int temperature;
++
++	switch (i) {
++	case 0:
++		temperature = mt7996_mcu_get_temperature(phy);
++		if (temperature < 0)
++			return temperature;
++		/* display in millidegree celcius */
++		return sprintf(buf, "%u\n", temperature * 1000);
++	case 1:
++	case 2:
++		return sprintf(buf, "%u\n",
++			       phy->throttle_temp[i - 1] * 1000);
++	case 3:
++		return sprintf(buf, "%hhu\n", phy->throttle_state);
++	default:
++		return -EINVAL;
++	}
++}
++
++static ssize_t mt7996_thermal_temp_store(struct device *dev,
++					 struct device_attribute *attr,
++					 const char *buf, size_t count)
++{
++	struct mt7996_phy *phy = dev_get_drvdata(dev);
++	int ret, i = to_sensor_dev_attr(attr)->index;
++	long val;
++
++	ret = kstrtol(buf, 10, &val);
++	if (ret < 0)
++		return ret;
++
++	mutex_lock(&phy->dev->mt76.mutex);
++	val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), 40, 130);
++
++	if ((i - 1 == MT7996_CRIT_TEMP_IDX &&
++	     val > phy->throttle_temp[MT7996_MAX_TEMP_IDX]) ||
++	    (i - 1 == MT7996_MAX_TEMP_IDX &&
++	     val < phy->throttle_temp[MT7996_CRIT_TEMP_IDX])) {
++		dev_err(phy->dev->mt76.dev,
++			"temp1_max shall be greater than temp1_crit.");
++		mutex_unlock(&phy->dev->mt76.mutex);
++		return -EINVAL;
++	}
++
++	phy->throttle_temp[i - 1] = val;
++	mutex_unlock(&phy->dev->mt76.mutex);
++
++	ret = mt7996_mcu_set_thermal_protect(phy);
++	if (ret)
++		return ret;
++
++	return count;
++}
++
++static SENSOR_DEVICE_ATTR_RO(temp1_input, mt7996_thermal_temp, 0);
++static SENSOR_DEVICE_ATTR_RW(temp1_crit, mt7996_thermal_temp, 1);
++static SENSOR_DEVICE_ATTR_RW(temp1_max, mt7996_thermal_temp, 2);
++static SENSOR_DEVICE_ATTR_RO(throttle1, mt7996_thermal_temp, 3);
++
++static struct attribute *mt7996_hwmon_attrs[] = {
++	&sensor_dev_attr_temp1_input.dev_attr.attr,
++	&sensor_dev_attr_temp1_crit.dev_attr.attr,
++	&sensor_dev_attr_temp1_max.dev_attr.attr,
++	&sensor_dev_attr_throttle1.dev_attr.attr,
++	NULL,
++};
++ATTRIBUTE_GROUPS(mt7996_hwmon);
++
+ static int
+ mt7996_thermal_get_max_throttle_state(struct thermal_cooling_device *cdev,
+ 				      unsigned long *state)
+@@ -112,6 +189,7 @@ static int mt7996_thermal_init(struct mt7996_phy *phy)
+ {
+ 	struct wiphy *wiphy = phy->mt76->hw->wiphy;
+ 	struct thermal_cooling_device *cdev;
++	struct device *hwmon;
+ 	const char *name;
+ 
+ 	name = devm_kasprintf(&wiphy->dev, GFP_KERNEL, "mt7996_%s",
+@@ -130,6 +208,15 @@ static int mt7996_thermal_init(struct mt7996_phy *phy)
+ 	phy->throttle_temp[MT7996_CRIT_TEMP_IDX] = MT7996_CRIT_TEMP;
+ 	phy->throttle_temp[MT7996_MAX_TEMP_IDX] = MT7996_MAX_TEMP;
+ 
++	if (!IS_REACHABLE(CONFIG_HWMON))
++		return 0;
++
++	hwmon = devm_hwmon_device_register_with_groups(&wiphy->dev, name, phy,
++						       mt7996_hwmon_groups);
++
++	if (IS_ERR(hwmon))
++		return PTR_ERR(hwmon);
++
+ 	return 0;
+ }
+ 
+diff --git a/mt7996/mcu.c b/mt7996/mcu.c
+index 3820a63e..b3326586 100644
+--- a/mt7996/mcu.c
++++ b/mt7996/mcu.c
+@@ -3308,6 +3308,47 @@ out:
+ 	return 0;
+ }
+ 
++int mt7996_mcu_get_temperature(struct mt7996_phy *phy)
++{
++#define TEMPERATURE_QUERY 0
++#define GET_TEMPERATURE 0
++	struct {
++		u8 _rsv[4];
++
++		__le16 tag;
++		__le16 len;
++
++		u8 rsv1;
++		u8 action;
++		u8 band_idx;
++		u8 rsv2;
++	} req = {
++		.tag = cpu_to_le16(TEMPERATURE_QUERY),
++		.len = cpu_to_le16(sizeof(req) - 4),
++		.action = GET_TEMPERATURE,
++		.band_idx = phy->mt76->band_idx,
++	};
++	struct mt7996_mcu_thermal {
++		u8 _rsv[4];
++
++		__le16 tag;
++		__le16 len;
++
++		__le32 rsv;
++		__le32 temperature;
++	} __packed *res;
++	struct sk_buff *skb;
++	int ret;
++
++	ret = mt76_mcu_send_and_get_msg(&phy->dev->mt76, MCU_WM_UNI_CMD(THERMAL),
++					&req, sizeof(req), true, &skb);
++	if (ret)
++		return ret;
++
++	res = (void *)skb->data;
++
++	return le32_to_cpu(res->temperature);
++}
+ 
+ int mt7996_mcu_set_thermal_throttling(struct mt7996_phy *phy, u8 state)
+ {
+-- 
+2.39.2
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0006-wifi-mt76-mt7996-add-802.11s-mesh-amsdu-de-amsdu-sup.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0012-wifi-mt76-mt7996-add-802.11s-mesh-amsdu-de-amsdu-sup.patch
similarity index 78%
rename from recipes-wifi/linux-mt76/files/patches-3.x/0006-wifi-mt76-mt7996-add-802.11s-mesh-amsdu-de-amsdu-sup.patch
rename to recipes-wifi/linux-mt76/files/patches-3.x/0012-wifi-mt76-mt7996-add-802.11s-mesh-amsdu-de-amsdu-sup.patch
index 70867df..728b4e0 100644
--- a/recipes-wifi/linux-mt76/files/patches-3.x/0006-wifi-mt76-mt7996-add-802.11s-mesh-amsdu-de-amsdu-sup.patch
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0012-wifi-mt76-mt7996-add-802.11s-mesh-amsdu-de-amsdu-sup.patch
@@ -1,7 +1,7 @@
-From 6298046de15b190139552d74aeb668e8cb873b1d Mon Sep 17 00:00:00 2001
+From f78111386b1ac57a459687b9d58e1804a80d4970 Mon Sep 17 00:00:00 2001
 From: Bo Jiao <Bo.Jiao@mediatek.com>
-Date: Thu, 15 Dec 2022 18:22:37 +0800
-Subject: [PATCH 6/7] wifi: mt76: mt7996: add 802.11s mesh amsdu/de-amsdu
+Date: Mon, 6 Feb 2023 11:34:51 +0800
+Subject: [PATCH 12/19] wifi: mt76: mt7996: add 802.11s mesh amsdu/de-amsdu
  support
 
 Signed-off-by: Bo Jiao <Bo.Jiao@mediatek.com>
@@ -12,16 +12,12 @@
  mt7996/mcu.h  |  2 +-
  mt7996/mmio.c |  3 ++-
  5 files changed, 27 insertions(+), 4 deletions(-)
- mode change 100644 => 100755 mt7996/mac.c
- mode change 100644 => 100755 mt7996/mmio.c
 
 diff --git a/mt7996/mac.c b/mt7996/mac.c
-old mode 100644
-new mode 100755
-index 51337dde..d17b5478
+index 40ef5e4b..8dc3a621 100644
 --- a/mt7996/mac.c
 +++ b/mt7996/mac.c
-@@ -630,6 +630,7 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, struct sk_buff *skb)
+@@ -633,6 +633,7 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, struct sk_buff *skb)
  	u32 rxd4 = le32_to_cpu(rxd[4]);
  	u32 csum_mask = MT_RXD0_NORMAL_IP_SUM | MT_RXD0_NORMAL_UDP_TCP_SUM;
  	u32 csum_status = *(u32 *)skb->cb;
@@ -29,7 +25,7 @@
  	bool unicast, insert_ccmp_hdr = false;
  	u8 remove_pad, amsdu_info, band_idx;
  	u8 mode = 0, qos_ctl = 0;
-@@ -822,6 +823,9 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, struct sk_buff *skb)
+@@ -825,6 +826,9 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, struct sk_buff *skb)
  
  		skb_pull(skb, hdr_gap);
  		if (!hdr_trans && status->amsdu) {
@@ -39,7 +35,7 @@
  			pad_start = ieee80211_get_hdrlen_from_skb(skb);
  		} else if (hdr_trans && (rxd2 & MT_RXD2_NORMAL_HDR_TRANS_ERROR)) {
  			/* When header translation failure is indicated,
-@@ -854,8 +858,17 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, struct sk_buff *skb)
+@@ -857,8 +861,17 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, struct sk_buff *skb)
  		hdr = mt76_skb_get_hdr(skb);
  		fc = hdr->frame_control;
  		if (ieee80211_is_data_qos(fc)) {
@@ -59,7 +55,7 @@
  	} else {
  		status->flag |= RX_FLAG_8023;
 diff --git a/mt7996/mac.h b/mt7996/mac.h
-index 470b701a..fd0e5d1c 100644
+index 4914d3e5..e48cc68b 100644
 --- a/mt7996/mac.h
 +++ b/mt7996/mac.h
 @@ -12,6 +12,8 @@
@@ -72,10 +68,10 @@
  #define MT_RXD0_NORMAL_IP_SUM		BIT(23)
  #define MT_RXD0_NORMAL_UDP_TCP_SUM	BIT(24)
 diff --git a/mt7996/mcu.c b/mt7996/mcu.c
-index 394dd15c..1e47b0ae 100644
+index b3326586..0dbe2e01 100644
 --- a/mt7996/mcu.c
 +++ b/mt7996/mcu.c
-@@ -1022,7 +1022,8 @@ mt7996_mcu_sta_amsdu_tlv(struct mt7996_dev *dev, struct sk_buff *skb,
+@@ -1054,7 +1054,8 @@ mt7996_mcu_sta_amsdu_tlv(struct mt7996_dev *dev, struct sk_buff *skb,
  	struct tlv *tlv;
  
  	if (vif->type != NL80211_IFTYPE_STATION &&
@@ -85,7 +81,7 @@
  		return;
  
  	if (!sta->deflink.agg.max_amsdu_len)
-@@ -1528,6 +1529,12 @@ mt7996_mcu_sta_hdr_trans_tlv(struct mt7996_dev *dev, struct sk_buff *skb,
+@@ -1560,6 +1561,12 @@ mt7996_mcu_sta_hdr_trans_tlv(struct mt7996_dev *dev, struct sk_buff *skb,
  		hdr_trans->to_ds = true;
  		hdr_trans->from_ds = true;
  	}
@@ -99,10 +95,10 @@
  
  static enum mcu_mmps_mode
 diff --git a/mt7996/mcu.h b/mt7996/mcu.h
-index dd0c5ac5..009f5f06 100644
+index 7fefc28f..ad66a1f8 100644
 --- a/mt7996/mcu.h
 +++ b/mt7996/mcu.h
-@@ -396,7 +396,7 @@ struct sta_rec_hdr_trans {
+@@ -434,7 +434,7 @@ struct sta_rec_hdr_trans {
  	u8 from_ds;
  	u8 to_ds;
  	u8 dis_rx_hdr_tran;
@@ -112,14 +108,12 @@
  
  struct hdr_trans_en {
 diff --git a/mt7996/mmio.c b/mt7996/mmio.c
-old mode 100644
-new mode 100755
-index d8a2c1a7..08164b1a
+index 902370a2..6610cc45 100644
 --- a/mt7996/mmio.c
 +++ b/mt7996/mmio.c
 @@ -320,7 +320,8 @@ struct mt7996_dev *mt7996_mmio_probe(struct device *pdev,
  		/* txwi_size = txd size + txp size */
- 		.txwi_size = MT_TXD_SIZE + sizeof(struct mt7996_txp),
+ 		.txwi_size = MT_TXD_SIZE + sizeof(struct mt76_connac_fw_txp),
  		.drv_flags = MT_DRV_TXWI_NO_FREE |
 -			     MT_DRV_HW_MGMT_TXQ,
 +			     MT_DRV_HW_MGMT_TXQ |
@@ -128,5 +122,5 @@
  				SURVEY_INFO_TIME_RX |
  				SURVEY_INFO_TIME_BSS_RX,
 -- 
-2.25.1
+2.39.2
 
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0013-wifi-mt76-mt7996-add-L0.5-system-error-recovery-supp.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0013-wifi-mt76-mt7996-add-L0.5-system-error-recovery-supp.patch
new file mode 100644
index 0000000..93ec12d
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0013-wifi-mt76-mt7996-add-L0.5-system-error-recovery-supp.patch
@@ -0,0 +1,948 @@
+From 6b8dfe2580a782be754be7bcd44da6ad79dc4231 Mon Sep 17 00:00:00 2001
+From: Bo Jiao <Bo.Jiao@mediatek.com>
+Date: Mon, 13 Feb 2023 18:00:25 +0800
+Subject: [PATCH 13/19] wifi: mt76: mt7996: add L0.5 system error recovery
+ support
+
+Signed-off-by: Bo Jiao <Bo.Jiao@mediatek.com>
+---
+ mt7996/debugfs.c | 155 +++++++++++++++++++++++---
+ mt7996/dma.c     |  65 +++++++++++
+ mt7996/init.c    |   9 +-
+ mt7996/mac.c     | 285 +++++++++++++++++++++++++++++++++++++++--------
+ mt7996/main.c    |  18 ++-
+ mt7996/mcu.c     |  22 ++--
+ mt7996/mcu.h     |  28 +++--
+ mt7996/mmio.c    |   7 +-
+ mt7996/mt7996.h  |  17 ++-
+ mt7996/regs.h    |  36 +++++-
+ 10 files changed, 542 insertions(+), 100 deletions(-)
+
+diff --git a/mt7996/debugfs.c b/mt7996/debugfs.c
+index 9c5e9ac1..f2c46a50 100644
+--- a/mt7996/debugfs.c
++++ b/mt7996/debugfs.c
+@@ -48,12 +48,12 @@ DEFINE_DEBUGFS_ATTRIBUTE(fops_implicit_txbf, mt7996_implicit_txbf_get,
+ 
+ /* test knob of system error recovery */
+ static ssize_t
+-mt7996_fw_ser_set(struct file *file, const char __user *user_buf,
+-		  size_t count, loff_t *ppos)
++mt7996_sys_recovery_set(struct file *file, const char __user *user_buf,
++			size_t count, loff_t *ppos)
+ {
+ 	struct mt7996_phy *phy = file->private_data;
+ 	struct mt7996_dev *dev = phy->dev;
+-	u8 band_idx = phy->mt76->band_idx;
++	bool band = phy->mt76->band_idx;
+ 	char buf[16];
+ 	int ret = 0;
+ 	u16 val;
+@@ -73,17 +73,49 @@ mt7996_fw_ser_set(struct file *file, const char __user *user_buf,
+ 		return -EINVAL;
+ 
+ 	switch (val) {
+-	case SER_SET_RECOVER_L1:
+-	case SER_SET_RECOVER_L2:
+-	case SER_SET_RECOVER_L3_RX_ABORT:
+-	case SER_SET_RECOVER_L3_TX_ABORT:
+-	case SER_SET_RECOVER_L3_TX_DISABLE:
+-	case SER_SET_RECOVER_L3_BF:
+-		ret = mt7996_mcu_set_ser(dev, SER_ENABLE, BIT(val), band_idx);
++	/*
++	 * 0: grab firmware current SER state.
++	 * 1: trigger & enable system error L1 recovery.
++	 * 2: trigger & enable system error L2 recovery.
++	 * 3: trigger & enable system error L3 rx abort.
++	 * 4: trigger & enable system error L3 tx abort.
++	 * 5: trigger & enable system error L3 tx disable.
++	 * 6: trigger & enable system error L3 bf recovery.
++	 * 7: trigger & enable system error L4 MDP recovery.
++	 * 8: trigger & enable system error full recovery.
++	 * 9: trigger firmware crash.
++	 */
++	case UNI_CMD_SER_QUERY:
++		ret = mt7996_mcu_set_ser(dev, UNI_CMD_SER_QUERY, 0, band);
++		break;
++	case UNI_CMD_SER_SET_RECOVER_L1:
++	case UNI_CMD_SER_SET_RECOVER_L2:
++	case UNI_CMD_SER_SET_RECOVER_L3_RX_ABORT:
++	case UNI_CMD_SER_SET_RECOVER_L3_TX_ABORT:
++	case UNI_CMD_SER_SET_RECOVER_L3_TX_DISABLE:
++	case UNI_CMD_SER_SET_RECOVER_L3_BF:
++	case UNI_CMD_SER_SET_RECOVER_L4_MDP:
++		ret = mt7996_mcu_set_ser(dev, UNI_CMD_SER_SET, BIT(val), band);
++		if (ret)
++			return ret;
++
++		ret = mt7996_mcu_set_ser(dev, UNI_CMD_SER_TRIGGER, val, band);
++		break;
++
++	/* enable full chip reset */
++	case UNI_CMD_SER_SET_RECOVER_FULL:
++		mt76_set(dev, MT_WFDMA0_MCU_HOST_INT_ENA, MT_MCU_CMD_WDT_MASK);
+ 		if (ret)
+ 			return ret;
+ 
+-		ret = mt7996_mcu_set_ser(dev, SER_RECOVER, val, band_idx);
++		dev->recovery.state |= MT_MCU_CMD_WDT_MASK;
++		mt7996_reset(dev);
++		break;
++
++	/* WARNING: trigger firmware crash */
++	case UNI_CMD_SER_SET_SYSTEM_ASSERT:
++		mt76_wr(dev, MT_MCU_WM_CIRQ_EINT_MASK_CLR_ADDR, BIT(18));
++		mt76_wr(dev, MT_MCU_WM_CIRQ_EINT_SOFT_ADDR, BIT(18));
+ 		break;
+ 	default:
+ 		break;
+@@ -92,9 +124,101 @@ mt7996_fw_ser_set(struct file *file, const char __user *user_buf,
+ 	return ret ? ret : count;
+ }
+ 
+-static const struct file_operations mt7996_fw_ser_ops = {
+-	.write = mt7996_fw_ser_set,
+-	/* TODO: ser read */
++static ssize_t
++mt7996_sys_recovery_get(struct file *file, char __user *user_buf,
++			size_t count, loff_t *ppos)
++{
++	struct mt7996_phy *phy = file->private_data;
++	struct mt7996_dev *dev = phy->dev;
++	char *buff;
++	int desc = 0;
++	ssize_t ret;
++	static const size_t bufsz = 1024;
++
++	buff = kmalloc(bufsz, GFP_KERNEL);
++	if (!buff)
++		return -ENOMEM;
++
++	/* HELP */
++	desc += scnprintf(buff + desc, bufsz - desc,
++			  "Please echo the correct value ...\n");
++	desc += scnprintf(buff + desc, bufsz - desc,
++			  "0: grab firmware transient SER state\n");
++	desc += scnprintf(buff + desc, bufsz - desc,
++			  "1: trigger system error L1 recovery\n");
++	desc += scnprintf(buff + desc, bufsz - desc,
++			  "2: trigger system error L2 recovery\n");
++	desc += scnprintf(buff + desc, bufsz - desc,
++			  "3: trigger system error L3 rx abort\n");
++	desc += scnprintf(buff + desc, bufsz - desc,
++			  "4: trigger system error L3 tx abort\n");
++	desc += scnprintf(buff + desc, bufsz - desc,
++			  "5: trigger system error L3 tx disable\n");
++	desc += scnprintf(buff + desc, bufsz - desc,
++			  "6: trigger system error L3 bf recovery\n");
++	desc += scnprintf(buff + desc, bufsz - desc,
++			  "7: trigger system error L4 MDP recovery\n");
++	desc += scnprintf(buff + desc, bufsz - desc,
++			  "8: trigger system error full recovery\n");
++	desc += scnprintf(buff + desc, bufsz - desc,
++			  "9: trigger firmware crash\n");
++
++	/* SER statistics */
++	desc += scnprintf(buff + desc, bufsz - desc,
++			  "\nlet's dump firmware SER statistics...\n");
++	desc += scnprintf(buff + desc, bufsz - desc,
++			  "::E  R , SER_STATUS        = 0x%08x\n",
++			  mt76_rr(dev, MT_SWDEF_SER_STATS));
++	desc += scnprintf(buff + desc, bufsz - desc,
++			  "::E  R , SER_PLE_ERR       = 0x%08x\n",
++			  mt76_rr(dev, MT_SWDEF_PLE_STATS));
++	desc += scnprintf(buff + desc, bufsz - desc,
++			  "::E  R , SER_PLE_ERR_1     = 0x%08x\n",
++			  mt76_rr(dev, MT_SWDEF_PLE1_STATS));
++	desc += scnprintf(buff + desc, bufsz - desc,
++			  "::E  R , SER_PLE_ERR_AMSDU = 0x%08x\n",
++			  mt76_rr(dev, MT_SWDEF_PLE_AMSDU_STATS));
++	desc += scnprintf(buff + desc, bufsz - desc,
++			  "::E  R , SER_PSE_ERR       = 0x%08x\n",
++			  mt76_rr(dev, MT_SWDEF_PSE_STATS));
++	desc += scnprintf(buff + desc, bufsz - desc,
++			  "::E  R , SER_PSE_ERR_1     = 0x%08x\n",
++			  mt76_rr(dev, MT_SWDEF_PSE1_STATS));
++	desc += scnprintf(buff + desc, bufsz - desc,
++			  "::E  R , SER_LMAC_WISR6_B0 = 0x%08x\n",
++			  mt76_rr(dev, MT_SWDEF_LAMC_WISR6_BN0_STATS));
++	desc += scnprintf(buff + desc, bufsz - desc,
++			  "::E  R , SER_LMAC_WISR6_B1 = 0x%08x\n",
++			  mt76_rr(dev, MT_SWDEF_LAMC_WISR6_BN1_STATS));
++	desc += scnprintf(buff + desc, bufsz - desc,
++			  "::E  R , SER_LMAC_WISR6_B2 = 0x%08x\n",
++			  mt76_rr(dev, MT_SWDEF_LAMC_WISR6_BN2_STATS));
++	desc += scnprintf(buff + desc, bufsz - desc,
++			  "::E  R , SER_LMAC_WISR7_B0 = 0x%08x\n",
++			  mt76_rr(dev, MT_SWDEF_LAMC_WISR7_BN0_STATS));
++	desc += scnprintf(buff + desc, bufsz - desc,
++			  "::E  R , SER_LMAC_WISR7_B1 = 0x%08x\n",
++			  mt76_rr(dev, MT_SWDEF_LAMC_WISR7_BN1_STATS));
++	desc += scnprintf(buff + desc, bufsz - desc,
++			  "::E  R , SER_LMAC_WISR7_B2 = 0x%08x\n",
++			  mt76_rr(dev, MT_SWDEF_LAMC_WISR7_BN2_STATS));
++	desc += scnprintf(buff + desc, bufsz - desc,
++			  "::E  R , SER_WFDMA_ERR = 0x%08x\n",
++			  mt76_rr(dev, WF_SWDEF_WFDMA_STATUS_ADDR));
++
++	desc += scnprintf(buff + desc, bufsz - desc,
++			  "\nSYS_RESET_COUNT: WM %d, WA %d\n",
++			  dev->recovery.wm_reset_count,
++			  dev->recovery.wa_reset_count);
++
++	ret = simple_read_from_buffer(user_buf, count, ppos, buff, desc);
++	kfree(buff);
++	return ret;
++}
++
++static const struct file_operations mt7996_sys_recovery_ops = {
++	.write = mt7996_sys_recovery_set,
++	.read = mt7996_sys_recovery_get,
+ 	.open = simple_open,
+ 	.llseek = default_llseek,
+ };
+@@ -674,6 +798,8 @@ int mt7996_init_debugfs(struct mt7996_phy *phy)
+ 	debugfs_create_file("xmit-queues", 0400, dir, phy,
+ 			    &mt7996_xmit_queues_fops);
+ 	debugfs_create_file("tx_stats", 0400, dir, phy, &mt7996_tx_stats_fops);
++	debugfs_create_file("sys_recovery", 0600, dir, phy,
++			    &mt7996_sys_recovery_ops);
+ 	debugfs_create_file("fw_debug_wm", 0600, dir, dev, &fops_fw_debug_wm);
+ 	debugfs_create_file("fw_debug_wa", 0600, dir, dev, &fops_fw_debug_wa);
+ 	debugfs_create_file("fw_debug_bin", 0600, dir, dev, &fops_fw_debug_bin);
+@@ -684,7 +810,6 @@ int mt7996_init_debugfs(struct mt7996_phy *phy)
+ 			    &fops_implicit_txbf);
+ 	debugfs_create_devm_seqfile(dev->mt76.dev, "twt_stats", dir,
+ 				    mt7996_twt_stats);
+-	debugfs_create_file("fw_ser", 0600, dir, phy, &mt7996_fw_ser_ops);
+ 	debugfs_create_file("rf_regval", 0600, dir, dev, &fops_rf_regval);
+ 
+ 	if (phy->mt76->cap.has_5ghz) {
+diff --git a/mt7996/dma.c b/mt7996/dma.c
+index c09fe427..18ea758c 100644
+--- a/mt7996/dma.c
++++ b/mt7996/dma.c
+@@ -352,6 +352,71 @@ int mt7996_dma_init(struct mt7996_dev *dev)
+ 	return 0;
+ }
+ 
++void mt7996_dma_reset(struct mt7996_dev *dev, bool force)
++{
++	struct mt76_phy *phy2 = dev->mt76.phys[MT_BAND1];
++	struct mt76_phy *phy3 = dev->mt76.phys[MT_BAND2];
++	u32 hif1_ofs = MT_WFDMA0_PCIE1(0) - MT_WFDMA0(0);
++	int i;
++
++	mt76_clear(dev, MT_WFDMA0_GLO_CFG,
++		   MT_WFDMA0_GLO_CFG_TX_DMA_EN |
++		   MT_WFDMA0_GLO_CFG_RX_DMA_EN);
++
++	if (dev->hif2)
++		mt76_clear(dev, MT_WFDMA0_GLO_CFG + hif1_ofs,
++			   MT_WFDMA0_GLO_CFG_TX_DMA_EN |
++			   MT_WFDMA0_GLO_CFG_RX_DMA_EN);
++
++	usleep_range(1000, 2000);
++
++	for (i = 0; i < __MT_TXQ_MAX; i++) {
++		mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[i], true);
++		if (phy2)
++			mt76_queue_tx_cleanup(dev, phy2->q_tx[i], true);
++		if (phy3)
++			mt76_queue_tx_cleanup(dev, phy3->q_tx[i], true);
++	}
++
++	for (i = 0; i < __MT_MCUQ_MAX; i++)
++		mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[i], true);
++
++	mt76_for_each_q_rx(&dev->mt76, i)
++		//mt76_queue_rx_reset(dev, i);
++		mt76_queue_rx_cleanup(dev, &dev->mt76.q_rx[i]);
++
++	mt76_tx_status_check(&dev->mt76, true);
++
++	/* reset wfsys */
++	if (force)
++		mt7996_wfsys_reset(dev);
++
++	mt7996_dma_disable(dev, force);
++
++	/* reset hw queues */
++	for (i = 0; i < __MT_TXQ_MAX; i++) {
++		mt76_queue_reset(dev, dev->mphy.q_tx[i]);
++		if (phy2)
++			mt76_queue_reset(dev, phy2->q_tx[i]);
++		if (phy3)
++			mt76_queue_reset(dev, phy3->q_tx[i]);
++	}
++
++	for (i = 0; i < __MT_MCUQ_MAX; i++)
++		mt76_queue_reset(dev, dev->mt76.q_mcu[i]);
++
++	mt76_for_each_q_rx(&dev->mt76, i) {
++		mt76_queue_reset(dev, &dev->mt76.q_rx[i]);
++	}
++
++	mt76_tx_status_check(&dev->mt76, true);
++
++	mt76_for_each_q_rx(&dev->mt76, i)
++		mt76_queue_rx_reset(dev, i);
++
++	mt7996_dma_enable(dev);
++}
++
+ void mt7996_dma_cleanup(struct mt7996_dev *dev)
+ {
+ 	mt7996_dma_disable(dev, true);
+diff --git a/mt7996/init.c b/mt7996/init.c
+index 631ada15..ced38ac8 100644
+--- a/mt7996/init.c
++++ b/mt7996/init.c
+@@ -278,8 +278,7 @@ static void mt7996_led_set_brightness(struct led_classdev *led_cdev,
+ 		mt7996_led_set_config(led_cdev, 0xff, 0);
+ }
+ 
+-static void
+-mt7996_init_txpower(struct mt7996_dev *dev,
++void mt7996_init_txpower(struct mt7996_dev *dev,
+ 		    struct ieee80211_supported_band *sband)
+ {
+ 	int i, nss = hweight8(dev->mphy.antenna_mask);
+@@ -429,7 +428,7 @@ mt7996_mac_init_band(struct mt7996_dev *dev, u8 band)
+ 	mt76_rmw(dev, MT_WTBLOFF_RSCR(band), mask, set);
+ }
+ 
+-static void mt7996_mac_init(struct mt7996_dev *dev)
++void mt7996_mac_init(struct mt7996_dev *dev)
+ {
+ #define HIF_TXD_V2_1	4
+ 	int i;
+@@ -463,7 +462,7 @@ static void mt7996_mac_init(struct mt7996_dev *dev)
+ 		mt7996_mac_init_band(dev, i);
+ }
+ 
+-static int mt7996_txbf_init(struct mt7996_dev *dev)
++int mt7996_txbf_init(struct mt7996_dev *dev)
+ {
+ 	int ret;
+ 
+@@ -1075,6 +1074,8 @@ int mt7996_register_device(struct mt7996_dev *dev)
+ 	if (ret)
+ 		return ret;
+ 
++	dev->recovery.hw_init_done = true;
++
+ 	return mt7996_init_debugfs(&dev->phy);
+ }
+ 
+diff --git a/mt7996/mac.c b/mt7996/mac.c
+index 8dc3a621..4c0c8f1e 100644
+--- a/mt7996/mac.c
++++ b/mt7996/mac.c
+@@ -1724,7 +1724,7 @@ mt7996_wait_reset_state(struct mt7996_dev *dev, u32 state)
+ 	bool ret;
+ 
+ 	ret = wait_event_timeout(dev->reset_wait,
+-				 (READ_ONCE(dev->reset_state) & state),
++				 (READ_ONCE(dev->recovery.state) & state),
+ 				 MT7996_RESET_TIMEOUT);
+ 
+ 	WARN(!ret, "Timeout waiting for MCU reset state %x\n", state);
+@@ -1773,68 +1773,208 @@ mt7996_update_beacons(struct mt7996_dev *dev)
+ 					    mt7996_update_vif_beacon, phy3->hw);
+ }
+ 
+-static void
+-mt7996_dma_reset(struct mt7996_dev *dev)
++void mt7996_tx_token_put(struct mt7996_dev *dev)
+ {
+-	struct mt76_phy *phy2 = dev->mt76.phys[MT_BAND1];
+-	struct mt76_phy *phy3 = dev->mt76.phys[MT_BAND2];
+-	u32 hif1_ofs = MT_WFDMA0_PCIE1(0) - MT_WFDMA0(0);
+-	int i;
++	struct mt76_txwi_cache *txwi;
++	int id;
+ 
+-	mt76_clear(dev, MT_WFDMA0_GLO_CFG,
+-		   MT_WFDMA0_GLO_CFG_TX_DMA_EN |
+-		   MT_WFDMA0_GLO_CFG_RX_DMA_EN);
++	spin_lock_bh(&dev->mt76.token_lock);
++	idr_for_each_entry(&dev->mt76.token, txwi, id) {
++		mt7996_txwi_free(dev, txwi, NULL, NULL);
++		dev->mt76.token_count--;
++	}
++	spin_unlock_bh(&dev->mt76.token_lock);
++	idr_destroy(&dev->mt76.token);
++}
+ 
+-	if (dev->hif2)
+-		mt76_clear(dev, MT_WFDMA0_GLO_CFG + hif1_ofs,
+-			   MT_WFDMA0_GLO_CFG_TX_DMA_EN |
+-			   MT_WFDMA0_GLO_CFG_RX_DMA_EN);
+ 
+-	usleep_range(1000, 2000);
++static int
++mt7996_mac_restart(struct mt7996_dev *dev)
++{
++	struct mt7996_phy *phy2, *phy3;
++	struct mt76_dev *mdev = &dev->mt76;
++	int i, ret;
+ 
+-	for (i = 0; i < __MT_TXQ_MAX; i++) {
+-		mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[i], true);
+-		if (phy2)
+-			mt76_queue_tx_cleanup(dev, phy2->q_tx[i], true);
+-		if (phy3)
+-			mt76_queue_tx_cleanup(dev, phy3->q_tx[i], true);
++	phy2 = mt7996_phy2(dev);
++	phy3 = mt7996_phy3(dev);
++
++	if (dev->hif2) {
++		mt76_wr(dev, MT_INT1_MASK_CSR, 0x0);
++		mt76_wr(dev, MT_INT1_SOURCE_CSR, ~0);
+ 	}
+ 
+-	for (i = 0; i < __MT_MCUQ_MAX; i++)
+-		mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[i], true);
++	if (dev_is_pci(mdev->dev)) {
++		mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0x0);
++		if (dev->hif2)
++			mt76_wr(dev, MT_PCIE1_MAC_INT_ENABLE, 0x0);
++	}
+ 
+-	mt76_for_each_q_rx(&dev->mt76, i)
+-		mt76_queue_rx_reset(dev, i);
++	set_bit(MT76_RESET, &dev->mphy.state);
++	set_bit(MT76_MCU_RESET, &dev->mphy.state);
++	wake_up(&dev->mt76.mcu.wait);
++	if (phy2) {
++		set_bit(MT76_RESET, &phy2->mt76->state);
++		set_bit(MT76_MCU_RESET, &phy2->mt76->state);
++	}
++	if (phy3) {
++		set_bit(MT76_RESET, &phy3->mt76->state);
++		set_bit(MT76_MCU_RESET, &phy3->mt76->state);
++	}
+ 
+-	mt76_tx_status_check(&dev->mt76, true);
++	/* lock/unlock all queues to ensure that no tx is pending */
++	mt76_txq_schedule_all(&dev->mphy);
++	if (phy2)
++		mt76_txq_schedule_all(phy2->mt76);
++	if (phy3)
++		mt76_txq_schedule_all(phy3->mt76);
++
++	/* disable all tx/rx napi */
++	mt76_worker_disable(&dev->mt76.tx_worker);
++	mt76_for_each_q_rx(mdev, i) {
++		if (mdev->q_rx[i].ndesc)
++			napi_disable(&dev->mt76.napi[i]);
++	}
++	napi_disable(&dev->mt76.tx_napi);
+ 
+-	/* re-init prefetch settings after reset */
+-	mt7996_dma_prefetch(dev);
++	/* token reinit */
++	mt7996_tx_token_put(dev);
++	idr_init(&dev->mt76.token);
+ 
+-	mt76_set(dev, MT_WFDMA0_GLO_CFG,
+-		 MT_WFDMA0_GLO_CFG_TX_DMA_EN | MT_WFDMA0_GLO_CFG_RX_DMA_EN);
++	mt7996_dma_reset(dev, true);
+ 
+-	if (dev->hif2)
+-		mt76_set(dev, MT_WFDMA0_GLO_CFG + hif1_ofs,
+-			 MT_WFDMA0_GLO_CFG_TX_DMA_EN |
+-			 MT_WFDMA0_GLO_CFG_RX_DMA_EN);
++	local_bh_disable();
++	mt76_for_each_q_rx(mdev, i) {
++		if (mdev->q_rx[i].ndesc) {
++			napi_enable(&dev->mt76.napi[i]);
++			napi_schedule(&dev->mt76.napi[i]);
++		}
++	}
++	local_bh_enable();
++	clear_bit(MT76_MCU_RESET, &dev->mphy.state);
++	clear_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state);
++
++	mt76_wr(dev, MT_INT_MASK_CSR, dev->mt76.mmio.irqmask);
++	mt76_wr(dev, MT_INT_SOURCE_CSR, ~0);
++	if (dev->hif2) {
++		mt76_wr(dev, MT_INT1_MASK_CSR, dev->mt76.mmio.irqmask);
++		mt76_wr(dev, MT_INT1_SOURCE_CSR, ~0);
++	}
++	if (dev_is_pci(mdev->dev)) {
++		mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff);
++		if (dev->hif2)
++			mt76_wr(dev, MT_PCIE1_MAC_INT_ENABLE, 0xff);
++	}
++
++	/* load firmware */
++	ret = mt7996_mcu_init_firmware(dev);
++	if (ret)
++		goto out;
++
++	/* set the necessary init items */
++	ret = mt7996_mcu_set_eeprom(dev);
++	if (ret)
++		goto out;
++
++	mt7996_mac_init(dev);
++	mt7996_init_txpower(dev, &dev->mphy.sband_2g.sband);
++	mt7996_init_txpower(dev, &dev->mphy.sband_5g.sband);
++	mt7996_init_txpower(dev, &dev->mphy.sband_6g.sband);
++	ret = mt7996_txbf_init(dev);
++
++	if (test_bit(MT76_STATE_RUNNING, &dev->mphy.state)) {
++		ret = mt7996_run(dev->mphy.hw);
++		if (ret)
++			goto out;
++	}
++
++	if (phy2 && test_bit(MT76_STATE_RUNNING, &phy2->mt76->state)) {
++		ret = mt7996_run(phy2->mt76->hw);
++		if (ret)
++			goto out;
++	}
++
++	if (phy3 && test_bit(MT76_STATE_RUNNING, &phy3->mt76->state)) {
++		ret = mt7996_run(phy3->mt76->hw);
++		if (ret)
++			goto out;
++	}
++
++out:
++	/* reset done */
++	clear_bit(MT76_RESET, &dev->mphy.state);
++	if (phy2)
++		clear_bit(MT76_RESET, &phy2->mt76->state);
++	if (phy3)
++		clear_bit(MT76_RESET, &phy3->mt76->state);
++
++	local_bh_disable();
++	napi_enable(&dev->mt76.tx_napi);
++	napi_schedule(&dev->mt76.tx_napi);
++	local_bh_enable();
++
++	mt76_worker_enable(&dev->mt76.tx_worker);
++	return ret;
+ }
+ 
+-void mt7996_tx_token_put(struct mt7996_dev *dev)
++static void
++mt7996_mac_full_reset(struct mt7996_dev *dev)
+ {
+-	struct mt76_txwi_cache *txwi;
+-	int id;
++	struct mt7996_phy *phy2, *phy3;
++	int i;
+ 
+-	spin_lock_bh(&dev->mt76.token_lock);
+-	idr_for_each_entry(&dev->mt76.token, txwi, id) {
+-		mt7996_txwi_free(dev, txwi, NULL, NULL);
+-		dev->mt76.token_count--;
++	phy2 = mt7996_phy2(dev);
++	phy3 = mt7996_phy3(dev);
++	dev->recovery.hw_full_reset = true;
++
++	wake_up(&dev->mt76.mcu.wait);
++	ieee80211_stop_queues(mt76_hw(dev));
++	if (phy2)
++		ieee80211_stop_queues(phy2->mt76->hw);
++	if (phy3)
++		ieee80211_stop_queues(phy3->mt76->hw);
++
++	cancel_delayed_work_sync(&dev->mphy.mac_work);
++	if (phy2)
++		cancel_delayed_work_sync(&phy2->mt76->mac_work);
++	if (phy3)
++		cancel_delayed_work_sync(&phy3->mt76->mac_work);
++
++	mutex_lock(&dev->mt76.mutex);
++	for (i = 0; i < 10; i++) {
++		if (!mt7996_mac_restart(dev))
++			break;
+ 	}
+-	spin_unlock_bh(&dev->mt76.token_lock);
+-	idr_destroy(&dev->mt76.token);
++	mutex_unlock(&dev->mt76.mutex);
++
++	if (i == 10)
++		dev_err(dev->mt76.dev, "chip full reset failed\n");
++
++	ieee80211_restart_hw(mt76_hw(dev));
++	if (phy2)
++		ieee80211_restart_hw(phy2->mt76->hw);
++	if (phy3)
++		ieee80211_restart_hw(phy3->mt76->hw);
++
++	ieee80211_wake_queues(mt76_hw(dev));
++	if (phy2)
++		ieee80211_wake_queues(phy2->mt76->hw);
++	if (phy3)
++		ieee80211_wake_queues(phy3->mt76->hw);
++
++	dev->recovery.hw_full_reset = false;
++	ieee80211_queue_delayed_work(mt76_hw(dev),
++				     &dev->mphy.mac_work,
++				     MT7996_WATCHDOG_TIME);
++	if (phy2)
++		ieee80211_queue_delayed_work(phy2->mt76->hw,
++					     &phy2->mt76->mac_work,
++					     MT7996_WATCHDOG_TIME);
++	if (phy3)
++		ieee80211_queue_delayed_work(phy3->mt76->hw,
++					     &phy3->mt76->mac_work,
++					     MT7996_WATCHDOG_TIME);
+ }
+ 
+-/* system error recovery */
+ void mt7996_mac_reset_work(struct work_struct *work)
+ {
+ 	struct mt7996_phy *phy2, *phy3;
+@@ -1845,9 +1985,36 @@ void mt7996_mac_reset_work(struct work_struct *work)
+ 	phy2 = mt7996_phy2(dev);
+ 	phy3 = mt7996_phy3(dev);
+ 
+-	if (!(READ_ONCE(dev->reset_state) & MT_MCU_CMD_STOP_DMA))
++	/* chip full reset */
++	if (dev->recovery.restart) {
++		/* disable WA/WM WDT */
++		mt76_clear(dev, MT_WFDMA0_MCU_HOST_INT_ENA,
++			   MT_MCU_CMD_WDT_MASK);
++
++		if (READ_ONCE(dev->recovery.state) & MT_MCU_CMD_WA_WDT)
++			dev->recovery.wa_reset_count++;
++		else
++			dev->recovery.wm_reset_count++;
++
++		mt7996_mac_full_reset(dev);
++
++		/* enable mcu irq */
++		mt7996_irq_enable(dev, MT_INT_MCU_CMD);
++		mt7996_irq_disable(dev, 0);
++
++		/* enable WA/WM WDT */
++		mt76_set(dev, MT_WFDMA0_MCU_HOST_INT_ENA, MT_MCU_CMD_WDT_MASK);
++
++		dev->recovery.state = MT_MCU_CMD_NORMAL_STATE;
++		dev->recovery.restart = false;
+ 		return;
++	}
+ 
++	if (!(READ_ONCE(dev->recovery.state) & MT_MCU_CMD_STOP_DMA))
++		return;
++
++	dev_info(dev->mt76.dev,"\n%s L1 SER recovery start.",
++		 wiphy_name(dev->mt76.hw->wiphy));
+ 	ieee80211_stop_queues(mt76_hw(dev));
+ 	if (phy2)
+ 		ieee80211_stop_queues(phy2->mt76->hw);
+@@ -1876,7 +2043,7 @@ void mt7996_mac_reset_work(struct work_struct *work)
+ 	mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_DMA_STOPPED);
+ 
+ 	if (mt7996_wait_reset_state(dev, MT_MCU_CMD_RESET_DONE)) {
+-		mt7996_dma_reset(dev);
++		mt7996_dma_reset(dev, false);
+ 
+ 		mt7996_tx_token_put(dev);
+ 		idr_init(&dev->mt76.token);
+@@ -1931,6 +2098,32 @@ void mt7996_mac_reset_work(struct work_struct *work)
+ 		ieee80211_queue_delayed_work(phy3->mt76->hw,
+ 					     &phy3->mt76->mac_work,
+ 					     MT7996_WATCHDOG_TIME);
++	dev_info(dev->mt76.dev,"\n%s L1 SER recovery completed.",
++		 wiphy_name(dev->mt76.hw->wiphy));
++}
++
++void mt7996_reset(struct mt7996_dev *dev)
++{
++	if (!dev->recovery.hw_init_done)
++		return;
++
++	if (dev->recovery.hw_full_reset)
++		return;
++
++	/* wm/wa exception: do full recovery */
++	if (READ_ONCE(dev->recovery.state) & MT_MCU_CMD_WDT_MASK) {
++		dev->recovery.restart = true;
++		dev_info(dev->mt76.dev,
++			 "%s indicated firmware crash, attempting recovery\n",
++			 wiphy_name(dev->mt76.hw->wiphy));
++
++		mt7996_irq_disable(dev, MT_INT_MCU_CMD);
++		queue_work(dev->mt76.wq, &dev->reset_work);
++		return;
++	}
++
++	queue_work(dev->mt76.wq, &dev->reset_work);
++	wake_up(&dev->reset_wait);
+ }
+ 
+ void mt7996_mac_update_stats(struct mt7996_phy *phy)
+diff --git a/mt7996/main.c b/mt7996/main.c
+index d8d578c0..cb0e0d31 100644
+--- a/mt7996/main.c
++++ b/mt7996/main.c
+@@ -22,17 +22,13 @@ static bool mt7996_dev_running(struct mt7996_dev *dev)
+ 	return phy && test_bit(MT76_STATE_RUNNING, &phy->mt76->state);
+ }
+ 
+-static int mt7996_start(struct ieee80211_hw *hw)
++int mt7996_run(struct ieee80211_hw *hw)
+ {
+ 	struct mt7996_dev *dev = mt7996_hw_dev(hw);
+ 	struct mt7996_phy *phy = mt7996_hw_phy(hw);
+ 	bool running;
+ 	int ret;
+ 
+-	flush_work(&dev->init_work);
+-
+-	mutex_lock(&dev->mt76.mutex);
+-
+ 	running = mt7996_dev_running(dev);
+ 	if (!running) {
+ 		ret = mt7996_mcu_set_hdr_trans(dev, true);
+@@ -71,6 +67,18 @@ static int mt7996_start(struct ieee80211_hw *hw)
+ 		mt7996_mac_reset_counters(phy);
+ 
+ out:
++	return ret;
++}
++
++static int mt7996_start(struct ieee80211_hw *hw)
++{
++	struct mt7996_dev *dev = mt7996_hw_dev(hw);
++	int ret;
++
++	flush_work(&dev->init_work);
++
++	mutex_lock(&dev->mt76.mutex);
++	ret = mt7996_run(hw);
+ 	mutex_unlock(&dev->mt76.mutex);
+ 
+ 	return ret;
+diff --git a/mt7996/mcu.c b/mt7996/mcu.c
+index 0dbe2e01..a949ff76 100644
+--- a/mt7996/mcu.c
++++ b/mt7996/mcu.c
+@@ -2629,17 +2629,10 @@ mt7996_mcu_init_rx_airtime(struct mt7996_dev *dev)
+ 				     MCU_WM_UNI_CMD(VOW), true);
+ }
+ 
+-int mt7996_mcu_init(struct mt7996_dev *dev)
++int mt7996_mcu_init_firmware(struct mt7996_dev *dev)
+ {
+-	static const struct mt76_mcu_ops mt7996_mcu_ops = {
+-		.headroom = sizeof(struct mt76_connac2_mcu_txd), /* reuse */
+-		.mcu_skb_send_msg = mt7996_mcu_send_message,
+-		.mcu_parse_response = mt7996_mcu_parse_response,
+-	};
+ 	int ret;
+ 
+-	dev->mt76.mcu_ops = &mt7996_mcu_ops;
+-
+ 	/* force firmware operation mode into normal state,
+ 	 * which should be set before firmware download stage.
+ 	 */
+@@ -2680,6 +2673,19 @@ int mt7996_mcu_init(struct mt7996_dev *dev)
+ 				 MCU_WA_PARAM_RED, 0, 0);
+ }
+ 
++int mt7996_mcu_init(struct mt7996_dev *dev)
++{
++	static const struct mt76_mcu_ops mt7996_mcu_ops = {
++		.headroom = sizeof(struct mt76_connac2_mcu_txd), /* reuse */
++		.mcu_skb_send_msg = mt7996_mcu_send_message,
++		.mcu_parse_response = mt7996_mcu_parse_response,
++	};
++
++	dev->mt76.mcu_ops = &mt7996_mcu_ops;
++
++	return mt7996_mcu_init_firmware(dev);
++}
++
+ void mt7996_mcu_exit(struct mt7996_dev *dev)
+ {
+ 	mt7996_mcu_restart(&dev->mt76);
+diff --git a/mt7996/mcu.h b/mt7996/mcu.h
+index ad66a1f8..778deedf 100644
+--- a/mt7996/mcu.h
++++ b/mt7996/mcu.h
+@@ -692,23 +692,21 @@ enum {
+ };
+ 
+ enum {
+-	UNI_CMD_SER_QUERY = 0x0,
+-	UNI_CMD_SER_SET = 0x2,
+-	UNI_CMD_SER_TRIGGER = 0x3,
+-};
+-
+-enum {
+-	SER_QUERY,
++	UNI_CMD_SER_QUERY,
+ 	/* recovery */
+-	SER_SET_RECOVER_L1,
+-	SER_SET_RECOVER_L2,
+-	SER_SET_RECOVER_L3_RX_ABORT,
+-	SER_SET_RECOVER_L3_TX_ABORT,
+-	SER_SET_RECOVER_L3_TX_DISABLE,
+-	SER_SET_RECOVER_L3_BF,
++	UNI_CMD_SER_SET_RECOVER_L1,
++	UNI_CMD_SER_SET_RECOVER_L2,
++	UNI_CMD_SER_SET_RECOVER_L3_RX_ABORT,
++	UNI_CMD_SER_SET_RECOVER_L3_TX_ABORT,
++	UNI_CMD_SER_SET_RECOVER_L3_TX_DISABLE,
++	UNI_CMD_SER_SET_RECOVER_L3_BF,
++	UNI_CMD_SER_SET_RECOVER_L4_MDP,
++	UNI_CMD_SER_SET_RECOVER_FULL,
++	UNI_CMD_SER_SET_SYSTEM_ASSERT,
+ 	/* action */
+-	SER_ENABLE = 2,
+-	SER_RECOVER
++	UNI_CMD_SER_ENABLE = 1,
++	UNI_CMD_SER_SET,
++	UNI_CMD_SER_TRIGGER
+ };
+ 
+ enum {
+diff --git a/mt7996/mmio.c b/mt7996/mmio.c
+index 6610cc45..0e11f398 100644
+--- a/mt7996/mmio.c
++++ b/mt7996/mmio.c
+@@ -289,10 +289,9 @@ static void mt7996_irq_tasklet(struct tasklet_struct *t)
+ 		u32 val = mt76_rr(dev, MT_MCU_CMD);
+ 
+ 		mt76_wr(dev, MT_MCU_CMD, val);
+-		if (val & MT_MCU_CMD_ERROR_MASK) {
+-			dev->reset_state = val;
+-			ieee80211_queue_work(mt76_hw(dev), &dev->reset_work);
+-			wake_up(&dev->reset_wait);
++		if (val & (MT_MCU_CMD_ERROR_MASK | MT_MCU_CMD_WDT_MASK)) {
++			dev->recovery.state = val;
++			mt7996_reset(dev);
+ 		}
+ 	}
+ }
+diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
+index 25b20fa6..923e6fc9 100644
+--- a/mt7996/mt7996.h
++++ b/mt7996/mt7996.h
+@@ -268,7 +268,14 @@ struct mt7996_dev {
+ 	struct work_struct rc_work;
+ 	struct work_struct reset_work;
+ 	wait_queue_head_t reset_wait;
+-	u32 reset_state;
++	struct {
++		u32 state;
++		u32 wa_reset_count;
++		u32 wm_reset_count;
++		bool hw_full_reset:1;
++		bool hw_init_done:1;
++		bool restart:1;
++	} recovery;
+ 
+ 	struct list_head sta_rc_list;
+ 	struct list_head sta_poll_list;
+@@ -401,9 +408,16 @@ int mt7996_eeprom_get_target_power(struct mt7996_dev *dev,
+ 				   struct ieee80211_channel *chan);
+ s8 mt7996_eeprom_get_power_delta(struct mt7996_dev *dev, int band);
+ int mt7996_dma_init(struct mt7996_dev *dev);
++void mt7996_dma_reset(struct mt7996_dev *dev, bool force);
+ void mt7996_dma_prefetch(struct mt7996_dev *dev);
+ void mt7996_dma_cleanup(struct mt7996_dev *dev);
++void mt7996_init_txpower(struct mt7996_dev *dev,
++		    struct ieee80211_supported_band *sband);
++int mt7996_txbf_init(struct mt7996_dev *dev);
++void mt7996_reset(struct mt7996_dev *dev);
++int mt7996_run(struct ieee80211_hw *hw);
+ int mt7996_mcu_init(struct mt7996_dev *dev);
++int mt7996_mcu_init_firmware(struct mt7996_dev *dev);
+ int mt7996_mcu_twt_agrt_update(struct mt7996_dev *dev,
+ 			       struct mt7996_vif *mvif,
+ 			       struct mt7996_twt_flow *flow,
+@@ -496,6 +510,7 @@ static inline void mt7996_irq_disable(struct mt7996_dev *dev, u32 mask)
+ 		mt76_set_irq_mask(&dev->mt76, MT_INT_MASK_CSR, mask, 0);
+ }
+ 
++void mt7996_mac_init(struct mt7996_dev *dev);
+ u32 mt7996_mac_wtbl_lmac_addr(struct mt7996_dev *dev, u16 wcid, u8 dw);
+ bool mt7996_mac_wtbl_update(struct mt7996_dev *dev, int idx, u32 mask);
+ void mt7996_mac_reset_counters(struct mt7996_phy *phy);
+diff --git a/mt7996/regs.h b/mt7996/regs.h
+index 7a28cae3..0775ca58 100644
+--- a/mt7996/regs.h
++++ b/mt7996/regs.h
+@@ -317,6 +317,8 @@ enum base_rev {
+ #define MT_WFDMA0_RX_INT_PCIE_SEL		MT_WFDMA0(0x154)
+ #define MT_WFDMA0_RX_INT_SEL_RING3		BIT(3)
+ 
++#define MT_WFDMA0_MCU_HOST_INT_ENA		MT_WFDMA0(0x1f4)
++
+ #define MT_WFDMA0_GLO_CFG			MT_WFDMA0(0x208)
+ #define MT_WFDMA0_GLO_CFG_TX_DMA_EN		BIT(0)
+ #define MT_WFDMA0_GLO_CFG_RX_DMA_EN		BIT(2)
+@@ -444,6 +446,10 @@ enum base_rev {
+ #define MT_MCU_CMD_NORMAL_STATE			BIT(5)
+ #define MT_MCU_CMD_ERROR_MASK			GENMASK(5, 1)
+ 
++#define MT_MCU_CMD_WA_WDT			BIT(31)
++#define MT_MCU_CMD_WM_WDT			BIT(30)
++#define MT_MCU_CMD_WDT_MASK			GENMASK(31, 30)
++
+ /* l1/l2 remap */
+ #define MT_HIF_REMAP_L1				0x155024
+ #define MT_HIF_REMAP_L1_MASK			GENMASK(31, 16)
+@@ -468,8 +474,27 @@ enum base_rev {
+ #define MT_INFRA_MCU_END			0x7c3fffff
+ 
+ /* FW MODE SYNC */
+-#define MT_SWDEF_MODE				0x9143c
++#define MT_SWDEF_BASE				0x00401400
++
++#define MT_SWDEF(ofs)				(MT_SWDEF_BASE + (ofs))
++#define MT_SWDEF_MODE				MT_SWDEF(0x3c)
+ #define MT_SWDEF_NORMAL_MODE			0
++#define MT_SWDEF_ICAP_MODE			1
++#define MT_SWDEF_SPECTRUM_MODE			2
++
++#define MT_SWDEF_SER_STATS			MT_SWDEF(0x040)
++#define MT_SWDEF_PLE_STATS			MT_SWDEF(0x044)
++#define MT_SWDEF_PLE1_STATS			MT_SWDEF(0x048)
++#define MT_SWDEF_PLE_AMSDU_STATS		MT_SWDEF(0x04C)
++#define MT_SWDEF_PSE_STATS			MT_SWDEF(0x050)
++#define MT_SWDEF_PSE1_STATS			MT_SWDEF(0x054)
++#define MT_SWDEF_LAMC_WISR6_BN0_STATS		MT_SWDEF(0x058)
++#define MT_SWDEF_LAMC_WISR6_BN1_STATS		MT_SWDEF(0x05C)
++#define MT_SWDEF_LAMC_WISR6_BN2_STATS		MT_SWDEF(0x060)
++#define MT_SWDEF_LAMC_WISR7_BN0_STATS		MT_SWDEF(0x064)
++#define MT_SWDEF_LAMC_WISR7_BN1_STATS		MT_SWDEF(0x068)
++#define MT_SWDEF_LAMC_WISR7_BN2_STATS		MT_SWDEF(0x06C)
++#define WF_SWDEF_WFDMA_STATUS_ADDR		MT_SWDEF(0x090)
+ 
+ /* LED */
+ #define MT_LED_TOP_BASE				0x18013000
+@@ -506,7 +531,7 @@ enum base_rev {
+ #define MT_TOP_MISC_FW_STATE			GENMASK(2, 0)
+ 
+ #define MT_HW_REV				0x70010204
+-#define MT_WF_SUBSYS_RST			0x70002600
++#define MT_WF_SUBSYS_RST			0x70028600
+ 
+ /* PCIE MAC */
+ #define MT_PCIE_MAC_BASE			0x74030000
+@@ -539,4 +564,11 @@ enum base_rev {
+ #define MT_WF_PHYRX_CSD_BAND_RXTD12_IRPI_SW_CLR_ONLY	BIT(18)
+ #define MT_WF_PHYRX_CSD_BAND_RXTD12_IRPI_SW_CLR		BIT(29)
+ 
++#define MT_MCU_WM_CIRQ_BASE			0x89010000
++#define MT_MCU_WM_CIRQ(ofs)			(MT_MCU_WM_CIRQ_BASE + (ofs))
++#define MT_MCU_WM_CIRQ_IRQ_MASK_CLR_ADDR	MT_MCU_WM_CIRQ(0x80)
++#define MT_MCU_WM_CIRQ_IRQ_SOFT_ADDR		MT_MCU_WM_CIRQ(0xc0)
++#define MT_MCU_WM_CIRQ_EINT_MASK_CLR_ADDR	MT_MCU_WM_CIRQ(0x108)
++#define MT_MCU_WM_CIRQ_EINT_SOFT_ADDR		MT_MCU_WM_CIRQ(0x118)
++
+ #endif
+-- 
+2.39.2
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0014-wifi-mt76-mt7996-add-dsp-firmware-download.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0014-wifi-mt76-mt7996-add-dsp-firmware-download.patch
new file mode 100644
index 0000000..8193a5a
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0014-wifi-mt76-mt7996-add-dsp-firmware-download.patch
@@ -0,0 +1,194 @@
+From 2d6ca0f6974ad4f6dcf110ccbbcbbc7185aa7655 Mon Sep 17 00:00:00 2001
+From: Peter Chiu <chui-hao.chiu@mediatek.com>
+Date: Fri, 17 Feb 2023 14:13:38 +0800
+Subject: [PATCH 14/19] wifi: mt76: mt7996: add dsp firmware download
+
+Add DSP firmware for phy related control. Without this patch,the
+firmware state would not be ready.
+
+Signed-off-by: Peter Chiu <chui-hao.chiu@mediatek.com>
+---
+ mt76_connac_mcu.h |  1 +
+ mt7996/mcu.c      | 94 +++++++++++++++++++++--------------------------
+ mt7996/mt7996.h   |  7 ++++
+ mt7996/pci.c      |  1 +
+ 4 files changed, 50 insertions(+), 53 deletions(-)
+
+diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
+index fa10d823..79dde31a 100644
+--- a/mt76_connac_mcu.h
++++ b/mt76_connac_mcu.h
+@@ -22,6 +22,7 @@
+ 
+ #define FW_START_OVERRIDE		BIT(0)
+ #define FW_START_WORKING_PDA_CR4	BIT(2)
++#define FW_START_WORKING_PDA_DSP	BIT(3)
+ 
+ #define PATCH_SEC_NOT_SUPPORT		GENMASK(31, 0)
+ #define PATCH_SEC_TYPE_MASK		GENMASK(15, 0)
+diff --git a/mt7996/mcu.c b/mt7996/mcu.c
+index a949ff76..09800ff2 100644
+--- a/mt7996/mcu.c
++++ b/mt7996/mcu.c
+@@ -2353,7 +2353,7 @@ out:
+ static int
+ mt7996_mcu_send_ram_firmware(struct mt7996_dev *dev,
+ 			     const struct mt7996_fw_trailer *hdr,
+-			     const u8 *data, bool is_wa)
++			     const u8 *data, enum mt7996_ram_type type)
+ {
+ 	int i, offset = 0;
+ 	u32 override = 0, option = 0;
+@@ -2365,8 +2365,10 @@ mt7996_mcu_send_ram_firmware(struct mt7996_dev *dev,
+ 
+ 		region = (const struct mt7996_fw_region *)((const u8 *)hdr -
+ 			 (hdr->n_region - i) * sizeof(*region));
++		/* DSP and WA use same mode */
+ 		mode = mt76_connac_mcu_gen_dl_mode(&dev->mt76,
+-						   region->feature_set, is_wa);
++						   region->feature_set,
++						   type != MT7996_RAM_TYPE_WM);
+ 		len = le32_to_cpu(region->len);
+ 		addr = le32_to_cpu(region->addr);
+ 
+@@ -2393,8 +2395,10 @@ mt7996_mcu_send_ram_firmware(struct mt7996_dev *dev,
+ 	if (override)
+ 		option |= FW_START_OVERRIDE;
+ 
+-	if (is_wa)
++	if (type == MT7996_RAM_TYPE_WA)
+ 		option |= FW_START_WORKING_PDA_CR4;
++	else if (type == MT7996_RAM_TYPE_DSP)
++		option |= FW_START_WORKING_PDA_DSP;
+ 
+ 	return mt76_connac_mcu_start_firmware(&dev->mt76, override, option);
+ }
+@@ -2405,56 +2409,40 @@ static int mt7996_load_ram(struct mt7996_dev *dev)
+ 	const struct firmware *fw;
+ 	int ret;
+ 
+-	ret = request_firmware(&fw, MT7996_FIRMWARE_WM, dev->mt76.dev);
+-	if (ret)
+-		return ret;
+-
+-	if (!fw || !fw->data || fw->size < sizeof(*hdr)) {
+-		dev_err(dev->mt76.dev, "Invalid firmware\n");
+-		ret = -EINVAL;
+-		goto out;
+-	}
+-
+-	hdr = (const struct mt7996_fw_trailer *)(fw->data + fw->size - sizeof(*hdr));
+-
+-	dev_info(dev->mt76.dev, "WM Firmware Version: %.10s, Build Time: %.15s\n",
+-		 hdr->fw_ver, hdr->build_date);
+-
+-	ret = mt7996_mcu_send_ram_firmware(dev, hdr, fw->data, false);
+-	if (ret) {
+-		dev_err(dev->mt76.dev, "Failed to start WM firmware\n");
+-		goto out;
+-	}
+-
+-	release_firmware(fw);
+-
+-	ret = request_firmware(&fw, MT7996_FIRMWARE_WA, dev->mt76.dev);
+-	if (ret)
+-		return ret;
+-
+-	if (!fw || !fw->data || fw->size < sizeof(*hdr)) {
+-		dev_err(dev->mt76.dev, "Invalid firmware\n");
+-		ret = -EINVAL;
+-		goto out;
+-	}
+-
+-	hdr = (const struct mt7996_fw_trailer *)(fw->data + fw->size - sizeof(*hdr));
+-
+-	dev_info(dev->mt76.dev, "WA Firmware Version: %.10s, Build Time: %.15s\n",
+-		 hdr->fw_ver, hdr->build_date);
+-
+-	ret = mt7996_mcu_send_ram_firmware(dev, hdr, fw->data, true);
+-	if (ret) {
+-		dev_err(dev->mt76.dev, "Failed to start WA firmware\n");
+-		goto out;
+-	}
+-
+-	snprintf(dev->mt76.hw->wiphy->fw_version,
+-		 sizeof(dev->mt76.hw->wiphy->fw_version),
+-		 "%.10s-%.15s", hdr->fw_ver, hdr->build_date);
+-
+-out:
+-	release_firmware(fw);
++#define LOAD_RAM(_type) \
++	do {									\
++		ret = request_firmware(&fw, MT7996_FIRMWARE_##_type, dev->mt76.dev);	\
++		if (ret)							\
++			return ret;						\
++										\
++		if (!fw || !fw->data || fw->size < sizeof(*hdr)) {		\
++			dev_err(dev->mt76.dev, "Invalid firmware\n");		\
++			release_firmware(fw);					\
++			return -EINVAL;						\
++		}								\
++										\
++		hdr = (const struct mt7996_fw_trailer *)			\
++				(fw->data + fw->size - sizeof(*hdr));		\
++										\
++		dev_info(dev->mt76.dev,						\
++			 "%s Firmware Version: %.10s, Build Time: %.15s\n",	\
++			 #_type, hdr->fw_ver, hdr->build_date);			\
++										\
++		ret = mt7996_mcu_send_ram_firmware(dev, hdr, fw->data,		\
++						   MT7996_RAM_TYPE_##_type);    \
++		if (ret) {							\
++			dev_err(dev->mt76.dev, "Failed to start %s firmware\n", #_type);\
++			release_firmware(fw);					\
++			return ret;						\
++		}								\
++										\
++		release_firmware(fw);						\
++	} while (0)
++
++	LOAD_RAM(WM);
++	LOAD_RAM(DSP);
++	LOAD_RAM(WA);
++#undef LOAD_RAM
+ 
+ 	return ret;
+ }
+diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
+index 923e6fc9..c2f8900c 100644
+--- a/mt7996/mt7996.h
++++ b/mt7996/mt7996.h
+@@ -29,6 +29,7 @@
+ 
+ #define MT7996_FIRMWARE_WA		"mediatek/mt7996/mt7996_wa.bin"
+ #define MT7996_FIRMWARE_WM		"mediatek/mt7996/mt7996_wm.bin"
++#define MT7996_FIRMWARE_DSP		"mediatek/mt7996/mt7996_dsp.bin"
+ #define MT7996_ROM_PATCH		"mediatek/mt7996/mt7996_rom_patch.bin"
+ 
+ #define MT7996_EEPROM_DEFAULT		"mediatek/mt7996/mt7996_eeprom.bin"
+@@ -55,6 +56,12 @@ struct mt7996_sta;
+ struct mt7996_dfs_pulse;
+ struct mt7996_dfs_pattern;
+ 
++enum mt7996_ram_type {
++	MT7996_RAM_TYPE_WM = 0,
++	MT7996_RAM_TYPE_WA,
++	MT7996_RAM_TYPE_DSP,
++};
++
+ enum mt7996_txq_id {
+ 	MT7996_TXQ_FWDL = 16,
+ 	MT7996_TXQ_MCU_WM,
+diff --git a/mt7996/pci.c b/mt7996/pci.c
+index 64aee3fb..c5301050 100644
+--- a/mt7996/pci.c
++++ b/mt7996/pci.c
+@@ -219,4 +219,5 @@ MODULE_DEVICE_TABLE(pci, mt7996_pci_device_table);
+ MODULE_DEVICE_TABLE(pci, mt7996_hif_device_table);
+ MODULE_FIRMWARE(MT7996_FIRMWARE_WA);
+ MODULE_FIRMWARE(MT7996_FIRMWARE_WM);
++MODULE_FIRMWARE(MT7996_FIRMWARE_DSP);
+ MODULE_FIRMWARE(MT7996_ROM_PATCH);
+-- 
+2.39.2
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0015-wifi-mt76-mt7996-fix-eeprom-antenna-bitfield-mask.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0015-wifi-mt76-mt7996-fix-eeprom-antenna-bitfield-mask.patch
new file mode 100644
index 0000000..236cada
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0015-wifi-mt76-mt7996-fix-eeprom-antenna-bitfield-mask.patch
@@ -0,0 +1,33 @@
+From 763303e5fb846c92c22dd19ffec95d844103e425 Mon Sep 17 00:00:00 2001
+From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+Date: Thu, 23 Feb 2023 19:18:45 +0800
+Subject: [PATCH 15/19] wifi: mt76: mt7996: fix eeprom antenna bitfield mask
+
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+---
+ mt7996/eeprom.h | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/mt7996/eeprom.h b/mt7996/eeprom.h
+index 8da599e0..cfc48698 100644
+--- a/mt7996/eeprom.h
++++ b/mt7996/eeprom.h
+@@ -31,11 +31,11 @@ enum mt7996_eeprom_field {
+ #define MT_EE_WIFI_CONF2_BAND_SEL		GENMASK(2, 0)
+ 
+ #define MT_EE_WIFI_CONF1_TX_PATH_BAND0		GENMASK(5, 3)
+-#define MT_EE_WIFI_CONF2_TX_PATH_BAND1		GENMASK(5, 3)
+-#define MT_EE_WIFI_CONF2_TX_PATH_BAND2		GENMASK(2, 0)
++#define MT_EE_WIFI_CONF2_TX_PATH_BAND1		GENMASK(2, 0)
++#define MT_EE_WIFI_CONF2_TX_PATH_BAND2		GENMASK(5, 3)
+ #define MT_EE_WIFI_CONF4_STREAM_NUM_BAND0	GENMASK(5, 3)
+-#define MT_EE_WIFI_CONF5_STREAM_NUM_BAND1	GENMASK(5, 3)
+-#define MT_EE_WIFI_CONF5_STREAM_NUM_BAND2	GENMASK(2, 0)
++#define MT_EE_WIFI_CONF5_STREAM_NUM_BAND1	GENMASK(2, 0)
++#define MT_EE_WIFI_CONF5_STREAM_NUM_BAND2	GENMASK(5, 3)
+ 
+ #define MT_EE_RATE_DELTA_MASK			GENMASK(5, 0)
+ #define MT_EE_RATE_DELTA_SIGN			BIT(6)
+-- 
+2.39.2
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0016-wifi-mt76-mt7996-init-mpdu-density.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0016-wifi-mt76-mt7996-init-mpdu-density.patch
new file mode 100644
index 0000000..74992ab
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0016-wifi-mt76-mt7996-init-mpdu-density.patch
@@ -0,0 +1,53 @@
+From 322307272a4c4ccb627d6596220b0ab5bd4aed45 Mon Sep 17 00:00:00 2001
+From: Peter Chiu <chui-hao.chiu@mediatek.com>
+Date: Mon, 13 Feb 2023 09:46:40 +0800
+Subject: [PATCH 16/19] wifi: mt76: mt7996: init mpdu density
+
+Init mpdu density based on the hardware capability to
+prevent hardware drop.
+
+Signed-off-by: Peter Chiu <chui-hao.chiu@mediatek.com>
+---
+ mt7996/init.c | 9 +++++++--
+ 1 file changed, 7 insertions(+), 2 deletions(-)
+
+diff --git a/mt7996/init.c b/mt7996/init.c
+index ced38ac8..479b2cee 100644
+--- a/mt7996/init.c
++++ b/mt7996/init.c
+@@ -374,10 +374,13 @@ mt7996_init_wiphy(struct ieee80211_hw *hw)
+ 
+ 	hw->max_tx_fragments = 4;
+ 
+-	if (phy->mt76->cap.has_2ghz)
++	if (phy->mt76->cap.has_2ghz) {
+ 		phy->mt76->sband_2g.sband.ht_cap.cap |=
+ 			IEEE80211_HT_CAP_LDPC_CODING |
+ 			IEEE80211_HT_CAP_MAX_AMSDU;
++		phy->mt76->sband_2g.sband.ht_cap.ampdu_density =
++			IEEE80211_HT_MPDU_DENSITY_2;
++	}
+ 
+ 	if (phy->mt76->cap.has_5ghz) {
+ 		phy->mt76->sband_5g.sband.ht_cap.cap |=
+@@ -389,6 +392,8 @@ mt7996_init_wiphy(struct ieee80211_hw *hw)
+ 			IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK |
+ 			IEEE80211_VHT_CAP_SHORT_GI_160 |
+ 			IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
++		phy->mt76->sband_5g.sband.ht_cap.ampdu_density =
++			IEEE80211_HT_MPDU_DENSITY_1;
+ 	}
+ 
+ 	mt76_set_stream_caps(phy->mt76, true);
+@@ -873,7 +878,7 @@ mt7996_init_he_caps(struct mt7996_phy *phy, enum nl80211_band band,
+ 		u16 cap = IEEE80211_HE_6GHZ_CAP_TX_ANTPAT_CONS |
+ 			  IEEE80211_HE_6GHZ_CAP_RX_ANTPAT_CONS;
+ 
+-		cap |= u16_encode_bits(IEEE80211_HT_MPDU_DENSITY_2,
++		cap |= u16_encode_bits(IEEE80211_HT_MPDU_DENSITY_0_5,
+ 				       IEEE80211_HE_6GHZ_CAP_MIN_MPDU_START) |
+ 		       u16_encode_bits(IEEE80211_VHT_MAX_AMPDU_1024K,
+ 				       IEEE80211_HE_6GHZ_CAP_MAX_AMPDU_LEN_EXP) |
+-- 
+2.39.2
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0017-wifi-mt76-mt7996-fix-icv-error-when-enable-AP-and-ST.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0017-wifi-mt76-mt7996-fix-icv-error-when-enable-AP-and-ST.patch
new file mode 100644
index 0000000..0b179f4
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0017-wifi-mt76-mt7996-fix-icv-error-when-enable-AP-and-ST.patch
@@ -0,0 +1,71 @@
+From b4af2c843368e7a787fc02ebde5a8ff41edf0a76 Mon Sep 17 00:00:00 2001
+From: Peter Chiu <chui-hao.chiu@mediatek.com>
+Date: Thu, 2 Mar 2023 15:44:52 +0800
+Subject: [PATCH 17/19] wifi: mt76: mt7996: fix icv error when enable AP and
+ STA simultaneously
+
+Fix mcu command content to prevent ICV error
+1. The legacy mld index needs to start from 16.
+2. The bmc_tx_wlan_idx needs to be the vif index rather
+than peer AP's index.
+
+Signed-off-by: Peter Chiu <chui-hao.chiu@mediatek.com>
+---
+ mt7996/mcu.c | 12 +++++++++---
+ 1 file changed, 9 insertions(+), 3 deletions(-)
+
+diff --git a/mt7996/mcu.c b/mt7996/mcu.c
+index 09800ff2..829f7be6 100644
+--- a/mt7996/mcu.c
++++ b/mt7996/mcu.c
+@@ -664,6 +664,7 @@ mt7996_mcu_bss_txcmd_tlv(struct sk_buff *skb, bool en)
+ static void
+ mt7996_mcu_bss_mld_tlv(struct sk_buff *skb, struct ieee80211_vif *vif)
+ {
++#define MT7996_LEGACY_MLD_IDX_START 16
+ 	struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
+ 	struct bss_mld_tlv *mld;
+ 	struct tlv *tlv;
+@@ -672,8 +673,12 @@ mt7996_mcu_bss_mld_tlv(struct sk_buff *skb, struct ieee80211_vif *vif)
+ 
+ 	mld = (struct bss_mld_tlv *)tlv;
+ 	mld->group_mld_id = 0xff;
+-	mld->own_mld_id = mvif->mt76.idx;
++	mld->own_mld_id = MT7996_LEGACY_MLD_IDX_START + mvif->mt76.idx;
+ 	mld->remap_idx = 0xff;
++	if (vif->type == NL80211_IFTYPE_AP) {
++		mld->group_mld_id = MT7996_LEGACY_MLD_IDX_START + mvif->mt76.idx;
++		memcpy(mld->mac_addr, vif->bss_conf.bssid, ETH_ALEN);
++	}
+ }
+ 
+ static void
+@@ -744,6 +749,7 @@ mt7996_mcu_bss_basic_tlv(struct sk_buff *skb,
+ 	struct cfg80211_chan_def *chandef = &phy->chandef;
+ 	struct mt76_connac_bss_basic_tlv *bss;
+ 	u32 type = CONNECTION_INFRA_AP;
++	u16 sta_wlan_idx = wlan_idx;
+ 	struct tlv *tlv;
+ 	int idx;
+ 
+@@ -763,7 +769,7 @@ mt7996_mcu_bss_basic_tlv(struct sk_buff *skb,
+ 				struct mt76_wcid *wcid;
+ 
+ 				wcid = (struct mt76_wcid *)sta->drv_priv;
+-				wlan_idx = wcid->idx;
++				sta_wlan_idx = wcid->idx;
+ 			}
+ 			rcu_read_unlock();
+ 		}
+@@ -783,7 +789,7 @@ mt7996_mcu_bss_basic_tlv(struct sk_buff *skb,
+ 	bss->bcn_interval = cpu_to_le16(vif->bss_conf.beacon_int);
+ 	bss->dtim_period = vif->bss_conf.dtim_period;
+ 	bss->bmc_tx_wlan_idx = cpu_to_le16(wlan_idx);
+-	bss->sta_idx = cpu_to_le16(wlan_idx);
++	bss->sta_idx = cpu_to_le16(sta_wlan_idx);
+ 	bss->conn_type = cpu_to_le32(type);
+ 	bss->omac_idx = mvif->omac_idx;
+ 	bss->band_idx = mvif->band_idx;
+-- 
+2.39.2
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0018-wifi-mt76-mt7996-set-wcid-in-txp.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0018-wifi-mt76-mt7996-set-wcid-in-txp.patch
new file mode 100644
index 0000000..74f4e9e
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0018-wifi-mt76-mt7996-set-wcid-in-txp.patch
@@ -0,0 +1,35 @@
+From 68649746f1862d6c9b3e06492789aadde8c4d2e5 Mon Sep 17 00:00:00 2001
+From: Peter Chiu <chui-hao.chiu@mediatek.com>
+Date: Mon, 6 Mar 2023 15:52:26 +0800
+Subject: [PATCH 18/19] wifi: mt76: mt7996: set wcid in txp
+
+Set correct wcid in txp for SDO to get wtbl.
+
+Signed-off-by: Peter Chiu <chui-hao.chiu@mediatek.com>
+---
+ mt7996/mac.c | 8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+diff --git a/mt7996/mac.c b/mt7996/mac.c
+index 4c0c8f1e..bb23f531 100644
+--- a/mt7996/mac.c
++++ b/mt7996/mac.c
+@@ -1168,10 +1168,12 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
+ 	}
+ 
+ 	txp->fw.token = cpu_to_le16(id);
+-	if (test_bit(MT_WCID_FLAG_4ADDR, &wcid->flags))
+-		txp->fw.rept_wds_wcid = cpu_to_le16(wcid->idx);
+-	else
++	if ((is_8023 && is_multicast_ether_addr(tx_info->skb->data)) ||
++	     is_multicast_ether_addr(hdr->addr1))
+ 		txp->fw.rept_wds_wcid = cpu_to_le16(0xfff);
++	else
++		txp->fw.rept_wds_wcid = cpu_to_le16(wcid->idx);
++
+ 	tx_info->skb = DMA_DUMMY_DATA;
+ 
+ 	/* pass partial skb header to fw */
+-- 
+2.39.2
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0007-mt76-revert-page-pool-changes.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0019-mt76-revert-page-pool-changes.patch
similarity index 92%
rename from recipes-wifi/linux-mt76/files/patches-3.x/0007-mt76-revert-page-pool-changes.patch
rename to recipes-wifi/linux-mt76/files/patches-3.x/0019-mt76-revert-page-pool-changes.patch
index ab1161f..20feead 100644
--- a/recipes-wifi/linux-mt76/files/patches-3.x/0007-mt76-revert-page-pool-changes.patch
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0019-mt76-revert-page-pool-changes.patch
@@ -1,7 +1,7 @@
-From 60c4e64c0198c828fafd5e7b96027ad5fd633213 Mon Sep 17 00:00:00 2001
+From 175bf122ac5790e7e28dadecd9410370364bc16a Mon Sep 17 00:00:00 2001
 From: Shayne Chen <shayne.chen@mediatek.com>
 Date: Mon, 6 Feb 2023 15:34:43 +0800
-Subject: [PATCH 7/7] mt76: revert page pool changes
+Subject: [PATCH 19/19] mt76: revert page pool changes
 
 ---
  dma.c         | 72 ++++++++++++++++++++++++++-------------------------
@@ -10,11 +10,11 @@
  mt7915/main.c | 26 +++++++------------
  mt7915/mmio.c | 55 ++++++++++++++++++++++++---------------
  mt7921/main.c | 31 +++-------------------
- usb.c         | 42 ++++++++++++++++--------------
- 7 files changed, 108 insertions(+), 197 deletions(-)
+ usb.c         | 43 +++++++++++++++---------------
+ 7 files changed, 108 insertions(+), 198 deletions(-)
 
 diff --git a/dma.c b/dma.c
-index e3fa4f39..50a7a689 100644
+index df2ca73f..7357b398 100644
 --- a/dma.c
 +++ b/dma.c
 @@ -173,7 +173,7 @@ mt76_free_pending_rxwi(struct mt76_dev *dev)
@@ -39,7 +39,7 @@
  
  		buf = t->ptr;
  		t->dma_addr = 0;
-@@ -428,9 +428,9 @@ mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx,
+@@ -430,9 +430,9 @@ mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx,
  	} else {
  		buf = e->buf;
  		e->buf = NULL;
@@ -52,7 +52,7 @@
  	}
  
  	return buf;
-@@ -582,11 +582,11 @@ free_skb:
+@@ -584,11 +584,11 @@ free_skb:
  }
  
  static int
@@ -67,7 +67,7 @@
  
  	if (!q->ndesc)
  		return 0;
-@@ -594,25 +594,26 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q,
+@@ -596,25 +596,26 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q,
  	spin_lock_bh(&q->lock);
  
  	while (q->queued < q->ndesc - 1) {
@@ -105,7 +105,7 @@
  			break;
  		}
  		frames++;
-@@ -656,7 +657,7 @@ int mt76_dma_wed_setup(struct mt76_dev *dev, struct mt76_queue *q, bool reset)
+@@ -658,7 +659,7 @@ int mt76_dma_wed_setup(struct mt76_dev *dev, struct mt76_queue *q, bool reset)
  		/* WED txfree queue needs ring to be initialized before setup */
  		q->flags = 0;
  		mt76_dma_queue_reset(dev, q);
@@ -114,7 +114,7 @@
  		q->flags = flags;
  
  		ret = mtk_wed_device_txfree_ring_setup(wed, q->regs);
-@@ -704,10 +705,6 @@ mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q,
+@@ -706,10 +707,6 @@ mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q,
  	if (!q->entry)
  		return -ENOMEM;
  
@@ -125,7 +125,7 @@
  	ret = mt76_dma_wed_setup(dev, q, false);
  	if (ret)
  		return ret;
-@@ -721,6 +718,7 @@ mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q,
+@@ -723,6 +720,7 @@ mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q,
  static void
  mt76_dma_rx_cleanup(struct mt76_dev *dev, struct mt76_queue *q)
  {
@@ -133,7 +133,7 @@
  	void *buf;
  	bool more;
  
-@@ -734,7 +732,7 @@ mt76_dma_rx_cleanup(struct mt76_dev *dev, struct mt76_queue *q)
+@@ -736,7 +734,7 @@ mt76_dma_rx_cleanup(struct mt76_dev *dev, struct mt76_queue *q)
  		if (!buf)
  			break;
  
@@ -142,7 +142,7 @@
  	} while (1);
  
  	if (q->rx_head) {
-@@ -743,6 +741,13 @@ mt76_dma_rx_cleanup(struct mt76_dev *dev, struct mt76_queue *q)
+@@ -745,6 +743,13 @@ mt76_dma_rx_cleanup(struct mt76_dev *dev, struct mt76_queue *q)
  	}
  
  	spin_unlock_bh(&q->lock);
@@ -156,7 +156,7 @@
  }
  
  static void
-@@ -763,7 +768,7 @@ mt76_dma_rx_reset(struct mt76_dev *dev, enum mt76_rxq_id qid)
+@@ -765,7 +770,7 @@ mt76_dma_rx_reset(struct mt76_dev *dev, enum mt76_rxq_id qid)
  	mt76_dma_wed_setup(dev, q, true);
  	if (q->flags != MT_WED_Q_TXFREE) {
  		mt76_dma_sync_idx(dev, q);
@@ -165,7 +165,7 @@
  	}
  }
  
-@@ -781,7 +786,7 @@ mt76_add_fragment(struct mt76_dev *dev, struct mt76_queue *q, void *data,
+@@ -783,7 +788,7 @@ mt76_add_fragment(struct mt76_dev *dev, struct mt76_queue *q, void *data,
  
  		skb_add_rx_frag(skb, nr_frags, page, offset, len, q->buf_size);
  	} else {
@@ -174,7 +174,7 @@
  	}
  
  	if (more)
-@@ -854,7 +859,6 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)
+@@ -856,7 +861,6 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)
  			goto free_frag;
  
  		skb_reserve(skb, q->buf_offset);
@@ -182,7 +182,7 @@
  
  		*(u32 *)skb->cb = info;
  
-@@ -870,10 +874,10 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)
+@@ -872,10 +876,10 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)
  		continue;
  
  free_frag:
@@ -195,7 +195,7 @@
  	return done;
  }
  
-@@ -918,7 +922,7 @@ mt76_dma_init(struct mt76_dev *dev,
+@@ -920,7 +924,7 @@ mt76_dma_init(struct mt76_dev *dev,
  
  	mt76_for_each_q_rx(dev, i) {
  		netif_napi_add(&dev->napi_dev, &dev->napi[i], poll);
@@ -204,7 +204,7 @@
  		napi_enable(&dev->napi[i]);
  	}
  
-@@ -969,8 +973,6 @@ void mt76_dma_cleanup(struct mt76_dev *dev)
+@@ -971,8 +975,6 @@ void mt76_dma_cleanup(struct mt76_dev *dev)
  
  		netif_napi_del(&dev->napi[i]);
  		mt76_dma_rx_cleanup(dev, q);
@@ -214,7 +214,7 @@
  
  	mt76_free_pending_txwi(dev);
 diff --git a/mac80211.c b/mac80211.c
-index b117e446..8a5f21e8 100644
+index e53166fc..d69e7214 100644
 --- a/mac80211.c
 +++ b/mac80211.c
 @@ -4,7 +4,6 @@
@@ -225,7 +225,7 @@
  #include "mt76.h"
  
  #define CHAN2G(_idx, _freq) {			\
-@@ -557,47 +556,6 @@ void mt76_unregister_phy(struct mt76_phy *phy)
+@@ -562,47 +561,6 @@ void mt76_unregister_phy(struct mt76_phy *phy)
  }
  EXPORT_SYMBOL_GPL(mt76_unregister_phy);
  
@@ -273,7 +273,7 @@
  struct mt76_dev *
  mt76_alloc_device(struct device *pdev, unsigned int size,
  		  const struct ieee80211_ops *ops,
-@@ -1732,21 +1690,6 @@ void mt76_ethtool_worker(struct mt76_ethtool_worker_info *wi,
+@@ -1746,21 +1704,6 @@ void mt76_ethtool_worker(struct mt76_ethtool_worker_info *wi,
  }
  EXPORT_SYMBOL_GPL(mt76_ethtool_worker);
  
@@ -296,7 +296,7 @@
  {
  	struct ieee80211_hw *hw = phy->hw;
 diff --git a/mt76.h b/mt76.h
-index ccca0162..f6a32fe3 100644
+index c3d1313e..49da2caa 100644
 --- a/mt76.h
 +++ b/mt76.h
 @@ -202,7 +202,7 @@ struct mt76_queue {
@@ -308,7 +308,7 @@
  };
  
  struct mt76_mcu_ops {
-@@ -1318,7 +1318,6 @@ mt76u_bulk_msg(struct mt76_dev *dev, void *data, int len, int *actual_len,
+@@ -1329,7 +1329,6 @@ mt76u_bulk_msg(struct mt76_dev *dev, void *data, int len, int *actual_len,
  	return usb_bulk_msg(udev, pipe, data, len, actual_len, timeout);
  }
  
@@ -316,7 +316,7 @@
  void mt76_ethtool_worker(struct mt76_ethtool_worker_info *wi,
  			 struct mt76_sta_stats *stats, bool eht);
  int mt76_skb_adjust_pad(struct sk_buff *skb, int pad);
-@@ -1430,25 +1429,6 @@ void __mt76_set_tx_blocked(struct mt76_dev *dev, bool blocked);
+@@ -1441,25 +1440,6 @@ void __mt76_set_tx_blocked(struct mt76_dev *dev, bool blocked);
  struct mt76_txwi_cache *mt76_rx_token_release(struct mt76_dev *dev, int token);
  int mt76_rx_token_consume(struct mt76_dev *dev, void *ptr,
  			  struct mt76_txwi_cache *r, dma_addr_t phys);
@@ -401,7 +401,7 @@
  
  static void
 diff --git a/mt7915/mmio.c b/mt7915/mmio.c
-index 225a1960..cbe6e2cd 100644
+index 6f0c0e2a..5ef43c44 100644
 --- a/mt7915/mmio.c
 +++ b/mt7915/mmio.c
 @@ -596,9 +596,13 @@ static void mt7915_mmio_wed_offload_disable(struct mtk_wed_device *wed)
@@ -505,7 +505,7 @@
  	return -ENOMEM;
  }
 diff --git a/mt7921/main.c b/mt7921/main.c
-index 75eaf86c..1434ca79 100644
+index a72964e7..4c400223 100644
 --- a/mt7921/main.c
 +++ b/mt7921/main.c
 @@ -1090,34 +1090,17 @@ static void
@@ -571,7 +571,7 @@
  
  static u64
 diff --git a/usb.c b/usb.c
-index b88959ef..3e281715 100644
+index 5e5c7bf5..3e281715 100644
 --- a/usb.c
 +++ b/usb.c
 @@ -319,27 +319,29 @@ mt76u_set_endpoints(struct usb_interface *intf,
@@ -688,11 +688,12 @@
  	int i;
  
  	for (i = 0; i < q->ndesc; i++) {
-@@ -705,7 +701,13 @@ mt76u_free_rx_queue(struct mt76_dev *dev, struct mt76_queue *q)
+@@ -705,8 +701,13 @@ mt76u_free_rx_queue(struct mt76_dev *dev, struct mt76_queue *q)
  		mt76u_urb_free(q->entry[i].urb);
  		q->entry[i].urb = NULL;
  	}
 -	page_pool_destroy(q->page_pool);
+-	q->page_pool = NULL;
 +
 +	if (!q->rx_page.va)
 +		return;
@@ -704,5 +705,5 @@
  
  static void mt76u_free_rx(struct mt76_dev *dev)
 -- 
-2.25.1
+2.39.2
 
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0999-mt76-mt7996-for-build-pass.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0999-mt76-mt7996-for-build-pass.patch
index dd28dc9..2f9a0c3 100644
--- a/recipes-wifi/linux-mt76/files/patches-3.x/0999-mt76-mt7996-for-build-pass.patch
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0999-mt76-mt7996-for-build-pass.patch
@@ -1,4 +1,4 @@
-From e66fbcb72e09e9e6a88fcedc84f4eda0d53ef65d Mon Sep 17 00:00:00 2001
+From a126ad08af718c71b4b05261caefb68996044330 Mon Sep 17 00:00:00 2001
 From: Shayne Chen <shayne.chen@mediatek.com>
 Date: Thu, 3 Nov 2022 00:27:17 +0800
 Subject: [PATCH] mt76: mt7996: for build pass
@@ -6,16 +6,15 @@
 Change-Id: Ieb44c33ee6e6a2e6058c1ef528404c1a1cbcfdaf
 ---
  debugfs.c         | 3 +++
- dma.c             | 2 +-
  eeprom.c          | 8 +++++++-
  mcu.c             | 1 +
  mt7615/mcu.c      | 1 +
  mt76_connac_mcu.c | 1 +
  mt7915/mcu.c      | 1 +
  mt7996/dma.c      | 4 ++--
- mt7996/eeprom.c   | 1 +
+ mt7996/eeprom.c   | 2 ++
  mt7996/mcu.c      | 1 +
- 10 files changed, 19 insertions(+), 4 deletions(-)
+ 9 files changed, 19 insertions(+), 3 deletions(-)
 
 diff --git a/debugfs.c b/debugfs.c
 index 79064a4d..e10d4cbc 100644
@@ -33,19 +32,6 @@
  
  	return 0;
  }
-diff --git a/dma.c b/dma.c
-index 50a7a689..beb9f4a4 100644
---- a/dma.c
-+++ b/dma.c
-@@ -854,7 +854,7 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)
- 		    !(dev->drv->rx_check(dev, data, len)))
- 			goto free_frag;
- 
--		skb = napi_build_skb(data, q->buf_size);
-+		skb = build_skb(data, q->buf_size);
- 		if (!skb)
- 			goto free_frag;
- 
 diff --git a/eeprom.c b/eeprom.c
 index ea54b7af..90d36c8d 100644
 --- a/eeprom.c
@@ -92,7 +78,7 @@
  static bool prefer_offload_fw = true;
  module_param(prefer_offload_fw, bool, 0644);
 diff --git a/mt76_connac_mcu.c b/mt76_connac_mcu.c
-index efb9bfaa..4a650721 100644
+index 4e4f6b35..e5815227 100644
 --- a/mt76_connac_mcu.c
 +++ b/mt76_connac_mcu.c
 @@ -4,6 +4,7 @@
@@ -104,7 +90,7 @@
  int mt76_connac_mcu_start_firmware(struct mt76_dev *dev, u32 addr, u32 option)
  {
 diff --git a/mt7915/mcu.c b/mt7915/mcu.c
-index f151ce86..20d81f05 100644
+index d08907f5..99ef8c9c 100644
 --- a/mt7915/mcu.c
 +++ b/mt7915/mcu.c
 @@ -6,6 +6,7 @@
@@ -116,7 +102,7 @@
  #define fw_name(_dev, name, ...)	({			\
  	char *_fw;						\
 diff --git a/mt7996/dma.c b/mt7996/dma.c
-index c09fe427..8c2e060d 100644
+index 18ea758c..3e2967f7 100644
 --- a/mt7996/dma.c
 +++ b/mt7996/dma.c
 @@ -343,8 +343,8 @@ int mt7996_dma_init(struct mt7996_dev *dev)
@@ -131,19 +117,20 @@
  
  	mt7996_dma_enable(dev);
 diff --git a/mt7996/eeprom.c b/mt7996/eeprom.c
-index 2e48c5a4..dd322f62 100644
+index 2e48c5a4..e747cb9f 100644
 --- a/mt7996/eeprom.c
 +++ b/mt7996/eeprom.c
-@@ -98,6 +98,7 @@ static int mt7996_eeprom_parse_efuse_hw_cap(struct mt7996_dev *dev)
+@@ -98,6 +98,8 @@ static int mt7996_eeprom_parse_efuse_hw_cap(struct mt7996_dev *dev)
  	if (ret)
  		return ret;
  
-+	cap = 0x4b249248;	/* internal hardcode */
++	/* for internal testing */
++	cap = 0x4b249248;
  	if (cap) {
  		dev->has_eht = !(cap & MODE_HE_ONLY);
  		dev->wtbl_size_group = u32_get_bits(cap, WTBL_SIZE_GROUP);
 diff --git a/mt7996/mcu.c b/mt7996/mcu.c
-index 1e47b0ae..db715195 100644
+index 829f7be6..0d9d309f 100644
 --- a/mt7996/mcu.c
 +++ b/mt7996/mcu.c
 @@ -5,6 +5,7 @@
@@ -155,5 +142,5 @@
  #include "mcu.h"
  #include "mac.h"
 -- 
-2.25.1
+2.39.2
 
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/patches.inc b/recipes-wifi/linux-mt76/files/patches-3.x/patches.inc
index cf59945..51df096 100644
--- a/recipes-wifi/linux-mt76/files/patches-3.x/patches.inc
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/patches.inc
@@ -1,12 +1,23 @@
 #patch patches (come from openwrt/lede/target/linux/mediatek)
 SRC_URI_append = " \
-    file://0000-sync-to-master.patch \
-    file://0001-Revert-wifi-mt76-mt7996-rely-on-mt76_connac_tx_compl.patch \
-    file://0002-Revert-wifi-mt76-mt7996-rely-on-mt76_connac_txp_skb_.patch \
-    file://0003-Revert-wifi-mt76-mt7996-rely-on-mt76_connac_txp_comm.patch \
-    file://0004-wifi-mt76-mt7996-add-muru-support.patch \
-    file://0005-wifi-mt76-mt7996-set-txd-v1.patch \
-    file://0006-wifi-mt76-mt7996-add-802.11s-mesh-amsdu-de-amsdu-sup.patch \
-    file://0007-mt76-revert-page-pool-changes.patch \
+    file://0001-wifi-mt76-mt7996-add-eht-rx-rate-support.patch \
+    file://0002-wifi-mt76-mt7996-let-non-bufferable-MMPDUs-use-corre.patch \
+    file://0003-wifi-mt76-mt7996-reduce-repeated-bss_info-and-sta_re.patch \
+    file://0004-wifi-mt76-mt7996-move-radio-enable-command-to-mt7996.patch \
+    file://0005-wifi-mt76-connac-set-correct-muar_idx-for-connac3-ch.patch \
+    file://0006-wifi-mt76-mt7996-fix-pointer-calculation-in-ie-count.patch \
+    file://0007-wifi-mt76-mt7996-remove-mt7996_mcu_set_pm.patch \
+    file://0008-wifi-mt76-mt7996-add-muru-support.patch \
+    file://0009-wifi-mt76-mt7996-set-txd-v1.patch \
+    file://0010-wifi-mt76-mt7996-add-thermal-protection-support.patch \
+    file://0011-wifi-mt76-mt7996-add-thermal-sensor-device-support.patch \
+    file://0012-wifi-mt76-mt7996-add-802.11s-mesh-amsdu-de-amsdu-sup.patch \
+    file://0013-wifi-mt76-mt7996-add-L0.5-system-error-recovery-supp.patch \
+    file://0014-wifi-mt76-mt7996-add-dsp-firmware-download.patch \
+    file://0015-wifi-mt76-mt7996-fix-eeprom-antenna-bitfield-mask.patch \
+    file://0016-wifi-mt76-mt7996-init-mpdu-density.patch \
+    file://0017-wifi-mt76-mt7996-fix-icv-error-when-enable-AP-and-ST.patch \
+    file://0018-wifi-mt76-mt7996-set-wcid-in-txp.patch \
+    file://0019-mt76-revert-page-pool-changes.patch \
     file://0999-mt76-mt7996-for-build-pass.patch \
     "
diff --git a/recipes-wifi/linux-mt76/files/patches/0001-wifi-mt76-mt7915-rework-mt7915_thermal_init.patch b/recipes-wifi/linux-mt76/files/patches/0001-wifi-mt76-mt7915-rework-mt7915_thermal_init.patch
deleted file mode 100644
index 0494b40..0000000
--- a/recipes-wifi/linux-mt76/files/patches/0001-wifi-mt76-mt7915-rework-mt7915_thermal_init.patch
+++ /dev/null
@@ -1,41 +0,0 @@
-From e4a095d551a5d2252887b88d064dee43fcb4149d Mon Sep 17 00:00:00 2001
-From: Howard Hsu <howard-yh.hsu@mediatek.com>
-Date: Thu, 19 Jan 2023 11:03:44 +0800
-Subject: [PATCH] wifi: mt76: mt7915: rework mt7915_thermal_init()
-
-If the kernel configuration "CONFIG_HWMON" is not set to Y, the
-critial/maximum high temperature will not be initialised to the correct
-setting. Rework mt7915_thermal_init to fix this.
----
- mt7915/init.c | 8 ++++----
- 1 file changed, 4 insertions(+), 4 deletions(-)
-
-diff --git a/mt7915/init.c b/mt7915/init.c
-index ec297e04..8485a154 100644
---- a/mt7915/init.c
-+++ b/mt7915/init.c
-@@ -202,6 +202,10 @@ static int mt7915_thermal_init(struct mt7915_phy *phy)
- 			phy->cdev = cdev;
- 	}
- 
-+	/* initialize critical/maximum high temperature */
-+	phy->throttle_temp[MT7915_CRIT_TEMP_IDX] = MT7915_CRIT_TEMP;
-+	phy->throttle_temp[MT7915_MAX_TEMP_IDX] = MT7915_MAX_TEMP;
-+
- 	if (!IS_REACHABLE(CONFIG_HWMON))
- 		return 0;
- 
-@@ -210,10 +214,6 @@ static int mt7915_thermal_init(struct mt7915_phy *phy)
- 	if (IS_ERR(hwmon))
- 		return PTR_ERR(hwmon);
- 
--	/* initialize critical/maximum high temperature */
--	phy->throttle_temp[MT7915_CRIT_TEMP_IDX] = MT7915_CRIT_TEMP;
--	phy->throttle_temp[MT7915_MAX_TEMP_IDX] = MT7915_MAX_TEMP;
--
- 	return 0;
- }
- 
--- 
-2.18.0
-
diff --git a/recipes-wifi/linux-mt76/files/patches/1001-mt76-mt7915-add-mtk-internal-debug-tools-for-mt76.patch b/recipes-wifi/linux-mt76/files/patches/1001-mt76-mt7915-add-mtk-internal-debug-tools-for-mt76.patch
index 492a5de..ef37684 100644
--- a/recipes-wifi/linux-mt76/files/patches/1001-mt76-mt7915-add-mtk-internal-debug-tools-for-mt76.patch
+++ b/recipes-wifi/linux-mt76/files/patches/1001-mt76-mt7915-add-mtk-internal-debug-tools-for-mt76.patch
@@ -1,7 +1,7 @@
-From 0585e668ca5e848c1b30f6f492ba0897ddb4071b Mon Sep 17 00:00:00 2001
+From 764731bb9676e58e8819bdbe48719b1076625032 Mon Sep 17 00:00:00 2001
 From: Shayne Chen <shayne.chen@mediatek.com>
 Date: Wed, 22 Jun 2022 10:39:47 +0800
-Subject: [PATCH] mt76: mt7915: add mtk internal debug tools for mt76
+Subject: [PATCH 1001/1009] mt76: mt7915: add mtk internal debug tools for mt76
 
 ---
  mt76_connac_mcu.h     |    6 +
@@ -22,10 +22,10 @@
  create mode 100644 mt7915/mtk_mcu.c
 
 diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
-index a5e6ee4d..cbe0c52a 100644
+index 40a99e0c..312e7b3c 100644
 --- a/mt76_connac_mcu.h
 +++ b/mt76_connac_mcu.h
-@@ -1151,6 +1151,7 @@ enum {
+@@ -1148,6 +1148,7 @@ enum {
  	MCU_EXT_CMD_SET_TX_POWER_CTRL = 0x11,
  	MCU_EXT_CMD_FW_LOG_2_HOST = 0x13,
  	MCU_EXT_CMD_TXBF_ACTION = 0x1e,
@@ -33,7 +33,7 @@
  	MCU_EXT_CMD_EFUSE_BUFFER_MODE = 0x21,
  	MCU_EXT_CMD_THERMAL_PROT = 0x23,
  	MCU_EXT_CMD_STA_REC_UPDATE = 0x25,
-@@ -1174,6 +1175,11 @@ enum {
+@@ -1171,6 +1172,11 @@ enum {
  	MCU_EXT_CMD_TX_POWER_FEATURE_CTRL = 0x58,
  	MCU_EXT_CMD_RXDCOC_CAL = 0x59,
  	MCU_EXT_CMD_GET_MIB_INFO = 0x5a,
@@ -258,7 +258,7 @@
  		goto out;
  
 diff --git a/mt7915/mcu.c b/mt7915/mcu.c
-index f151ce86..ff718f78 100644
+index d08907f5..1fecd4b1 100644
 --- a/mt7915/mcu.c
 +++ b/mt7915/mcu.c
 @@ -199,6 +199,11 @@ mt7915_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb,
@@ -285,7 +285,7 @@
  {
  #define RED_DISABLE		0
  #define RED_BY_WA_ENABLE	2
-@@ -3377,6 +3385,8 @@ int mt7915_mcu_set_sku_en(struct mt7915_phy *phy, bool enable)
+@@ -3379,6 +3387,8 @@ int mt7915_mcu_set_sku_en(struct mt7915_phy *phy, bool enable)
  		.sku_enable = enable,
  	};
  
@@ -294,7 +294,7 @@
  	return mt76_mcu_send_msg(&dev->mt76,
  				 MCU_EXT_CMD(TX_POWER_FEATURE_CTRL), &req,
  				 sizeof(req), true);
-@@ -3814,6 +3824,23 @@ int mt7915_mcu_twt_agrt_update(struct mt7915_dev *dev,
+@@ -3816,6 +3826,23 @@ int mt7915_mcu_twt_agrt_update(struct mt7915_dev *dev,
  				 &req, sizeof(req), true);
  }
  
@@ -318,7 +318,7 @@
  int mt7915_mcu_rf_regval(struct mt7915_dev *dev, u32 regidx, u32 *val, bool set)
  {
  	struct {
-@@ -3842,3 +3869,22 @@ int mt7915_mcu_rf_regval(struct mt7915_dev *dev, u32 regidx, u32 *val, bool set)
+@@ -3844,3 +3871,22 @@ int mt7915_mcu_rf_regval(struct mt7915_dev *dev, u32 regidx, u32 *val, bool set)
  
  	return 0;
  }
diff --git a/recipes-wifi/linux-mt76/files/patches/1002-mt76-mt7915-csi-implement-csi-support.patch b/recipes-wifi/linux-mt76/files/patches/1002-mt76-mt7915-csi-implement-csi-support.patch
index bde66c3..125a023 100644
--- a/recipes-wifi/linux-mt76/files/patches/1002-mt76-mt7915-csi-implement-csi-support.patch
+++ b/recipes-wifi/linux-mt76/files/patches/1002-mt76-mt7915-csi-implement-csi-support.patch
@@ -1,4 +1,4 @@
-From f7a36f2ff5ca5cdf4a5fca215b14622da6257016 Mon Sep 17 00:00:00 2001
+From 41752b5e4ac73781e070aabff226904ab9efb5e4 Mon Sep 17 00:00:00 2001
 From: Bo Jiao <Bo.Jiao@mediatek.com>
 Date: Mon, 6 Jun 2022 20:13:02 +0800
 Subject: [PATCH 1002/1009] mt76: mt7915: csi: implement csi support
@@ -17,10 +17,10 @@
  create mode 100644 mt7915/vendor.h
 
 diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
-index cbe0c52a..32156d35 100644
+index 312e7b3c..39a7f691 100644
 --- a/mt76_connac_mcu.h
 +++ b/mt76_connac_mcu.h
-@@ -1003,6 +1003,7 @@ enum {
+@@ -1000,6 +1000,7 @@ enum {
  	MCU_EXT_EVENT_CSA_NOTIFY = 0x4f,
  	MCU_EXT_EVENT_BCC_NOTIFY = 0x75,
  	MCU_EXT_EVENT_MURU_CTRL = 0x9f,
@@ -28,7 +28,7 @@
  };
  
  /* unified event table */
-@@ -1196,6 +1197,7 @@ enum {
+@@ -1193,6 +1194,7 @@ enum {
  	MCU_EXT_CMD_GROUP_PRE_CAL_INFO = 0xab,
  	MCU_EXT_CMD_DPD_PRE_CAL_INFO = 0xac,
  	MCU_EXT_CMD_PHY_STAT_INFO = 0xad,
@@ -54,10 +54,10 @@
  mt7915e-$(CONFIG_NL80211_TESTMODE) += testmode.o
  mt7915e-$(CONFIG_MT7986_WMAC) += soc.o
 diff --git a/mt7915/init.c b/mt7915/init.c
-index 8485a154..06ac261f 100644
+index b88c3827..c27469e4 100644
 --- a/mt7915/init.c
 +++ b/mt7915/init.c
-@@ -652,6 +652,12 @@ mt7915_register_ext_phy(struct mt7915_dev *dev, struct mt7915_phy *phy)
+@@ -664,6 +664,12 @@ mt7915_register_ext_phy(struct mt7915_dev *dev, struct mt7915_phy *phy)
  	/* init wiphy according to mphy and phy */
  	mt7915_init_wiphy(phy);
  
@@ -70,7 +70,7 @@
  	ret = mt76_register_phy(mphy, true, mt76_rates,
  				ARRAY_SIZE(mt76_rates));
  	if (ret)
-@@ -1144,6 +1150,25 @@ void mt7915_set_stream_he_caps(struct mt7915_phy *phy)
+@@ -1165,6 +1171,25 @@ void mt7915_set_stream_he_caps(struct mt7915_phy *phy)
  	}
  }
  
@@ -96,7 +96,7 @@
  static void mt7915_unregister_ext_phy(struct mt7915_dev *dev)
  {
  	struct mt7915_phy *phy = mt7915_ext_phy(dev);
-@@ -1152,6 +1177,10 @@ static void mt7915_unregister_ext_phy(struct mt7915_dev *dev)
+@@ -1173,6 +1198,10 @@ static void mt7915_unregister_ext_phy(struct mt7915_dev *dev)
  	if (!phy)
  		return;
  
@@ -107,7 +107,7 @@
  	mt7915_unregister_thermal(phy);
  	mt76_unregister_phy(mphy);
  	ieee80211_free_hw(mphy->hw);
-@@ -1164,6 +1193,10 @@ static void mt7915_stop_hardware(struct mt7915_dev *dev)
+@@ -1185,6 +1214,10 @@ static void mt7915_stop_hardware(struct mt7915_dev *dev)
  	mt7915_dma_cleanup(dev);
  	tasklet_disable(&dev->irq_tasklet);
  
@@ -118,7 +118,7 @@
  	if (is_mt7986(&dev->mt76))
  		mt7986_wmac_disable(dev);
  }
-@@ -1204,6 +1237,12 @@ int mt7915_register_device(struct mt7915_dev *dev)
+@@ -1225,6 +1258,12 @@ int mt7915_register_device(struct mt7915_dev *dev)
  	dev->mt76.test_ops = &mt7915_testmode_ops;
  #endif
  
@@ -132,7 +132,7 @@
  				   ARRAY_SIZE(mt76_rates));
  	if (ret)
 diff --git a/mt7915/mcu.c b/mt7915/mcu.c
-index ff718f78..59cce553 100644
+index 1fecd4b1..40f77428 100644
 --- a/mt7915/mcu.c
 +++ b/mt7915/mcu.c
 @@ -36,6 +36,10 @@ static bool sr_scene_detect = true;
@@ -158,7 +158,7 @@
  	case MCU_EXT_EVENT_BCC_NOTIFY:
  		mt7915_mcu_rx_bcc_notify(dev, skb);
  		break;
-@@ -3824,6 +3833,108 @@ int mt7915_mcu_twt_agrt_update(struct mt7915_dev *dev,
+@@ -3826,6 +3835,108 @@ int mt7915_mcu_twt_agrt_update(struct mt7915_dev *dev,
  				 &req, sizeof(req), true);
  }
  
@@ -353,7 +353,7 @@
 +
  #endif
 diff --git a/mt7915/mt7915.h b/mt7915/mt7915.h
-index 19880099..bd2ca6cc 100644
+index 5fcc8ace..e0133b13 100644
 --- a/mt7915/mt7915.h
 +++ b/mt7915/mt7915.h
 @@ -294,6 +294,20 @@ struct mt7915_phy {
@@ -377,7 +377,7 @@
  };
  
  struct mt7915_dev {
-@@ -675,6 +689,12 @@ void mt7915_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+@@ -674,6 +688,12 @@ void mt7915_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
  int mt7915_mmio_wed_init(struct mt7915_dev *dev, void *pdev_ptr,
  			 bool pci, int *irq);
  
diff --git a/recipes-wifi/linux-mt76/files/patches/1003-mt76-mt7915-air-monitor-support.patch b/recipes-wifi/linux-mt76/files/patches/1003-mt76-mt7915-air-monitor-support.patch
index c59c63d..b3388ce 100644
--- a/recipes-wifi/linux-mt76/files/patches/1003-mt76-mt7915-air-monitor-support.patch
+++ b/recipes-wifi/linux-mt76/files/patches/1003-mt76-mt7915-air-monitor-support.patch
@@ -1,4 +1,4 @@
-From a97766c58f1dc2a25421f1bc527a06b59cd5f0dc Mon Sep 17 00:00:00 2001
+From f6b5a16ecd5e9cc986a3dde75a84a447aa729449 Mon Sep 17 00:00:00 2001
 From: Bo Jiao <Bo.Jiao@mediatek.com>
 Date: Tue, 11 Jan 2022 12:03:23 +0800
 Subject: [PATCH 1003/1009] mt76: mt7915: air monitor support
@@ -13,10 +13,10 @@
  6 files changed, 440 insertions(+)
 
 diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
-index 32156d35..60161c9e 100644
+index 39a7f691..d35f9e92 100644
 --- a/mt76_connac_mcu.h
 +++ b/mt76_connac_mcu.h
-@@ -1197,6 +1197,8 @@ enum {
+@@ -1194,6 +1194,8 @@ enum {
  	MCU_EXT_CMD_GROUP_PRE_CAL_INFO = 0xab,
  	MCU_EXT_CMD_DPD_PRE_CAL_INFO = 0xac,
  	MCU_EXT_CMD_PHY_STAT_INFO = 0xad,
@@ -55,7 +55,7 @@
  }
  
 diff --git a/mt7915/mt7915.h b/mt7915/mt7915.h
-index bd2ca6cc..9a9d7f55 100644
+index e0133b13..df0d7a1e 100644
 --- a/mt7915/mt7915.h
 +++ b/mt7915/mt7915.h
 @@ -250,6 +250,35 @@ struct mt7915_hif {
@@ -103,7 +103,7 @@
  #endif
  };
  
-@@ -693,6 +724,9 @@ int mt7915_mmio_wed_init(struct mt7915_dev *dev, void *pdev_ptr,
+@@ -692,6 +723,9 @@ int mt7915_mmio_wed_init(struct mt7915_dev *dev, void *pdev_ptr,
  void mt7915_vendor_register(struct mt7915_phy *phy);
  int mt7915_mcu_set_csi(struct mt7915_phy *phy, u8 mode,
  			u8 cfg, u8 v1, u32 v2, u8 *mac_addr);
diff --git a/recipes-wifi/linux-mt76/files/patches/1004-mt76-mt7915-add-support-for-muru_onoff-via-debugfs.patch b/recipes-wifi/linux-mt76/files/patches/1004-mt76-mt7915-add-support-for-muru_onoff-via-debugfs.patch
index 30c30f1..b2739d3 100644
--- a/recipes-wifi/linux-mt76/files/patches/1004-mt76-mt7915-add-support-for-muru_onoff-via-debugfs.patch
+++ b/recipes-wifi/linux-mt76/files/patches/1004-mt76-mt7915-add-support-for-muru_onoff-via-debugfs.patch
@@ -1,4 +1,4 @@
-From f45e6908cbe43d1dd02f92569ed2549e021822e1 Mon Sep 17 00:00:00 2001
+From 7a1f0d570d96e8e23b771976da052e94def589b9 Mon Sep 17 00:00:00 2001
 From: MeiChia Chiu <meichia.chiu@mediatek.com>
 Date: Wed, 22 Jun 2022 10:45:53 +0800
 Subject: [PATCH 1004/1009] mt76: mt7915: add support for muru_onoff via
@@ -13,10 +13,10 @@
  5 files changed, 52 insertions(+), 3 deletions(-)
 
 diff --git a/mt7915/init.c b/mt7915/init.c
-index 06ac261..3897ac4 100644
+index c27469e4..1177e4e7 100644
 --- a/mt7915/init.c
 +++ b/mt7915/init.c
-@@ -433,6 +433,8 @@ mt7915_init_wiphy(struct mt7915_phy *phy)
+@@ -445,6 +445,8 @@ mt7915_init_wiphy(struct mt7915_phy *phy)
  		mphy->leds.cdev.brightness_set = mt7915_led_set_brightness;
  		mphy->leds.cdev.blink_set = mt7915_led_set_blink;
  	}
@@ -26,7 +26,7 @@
  
  static void
 diff --git a/mt7915/mcu.c b/mt7915/mcu.c
-index 59cce55..cf9a3e2 100644
+index 40f77428..b507f14f 100644
 --- a/mt7915/mcu.c
 +++ b/mt7915/mcu.c
 @@ -864,6 +864,7 @@ mt7915_mcu_sta_muru_tlv(struct mt7915_dev *dev, struct sk_buff *skb,
@@ -60,7 +60,7 @@
  		muru->mimo_dl.vht_mu_bfee =
  			!!(sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE);
 diff --git a/mt7915/mcu.h b/mt7915/mcu.h
-index c776417..275a0ec 100644
+index c776417b..275a0ece 100644
 --- a/mt7915/mcu.h
 +++ b/mt7915/mcu.h
 @@ -609,4 +609,10 @@ struct csi_data {
@@ -75,7 +75,7 @@
 +
  #endif
 diff --git a/mt7915/mt7915.h b/mt7915/mt7915.h
-index df0d7a1..e94970b 100644
+index df0d7a1e..e94970ba 100644
 --- a/mt7915/mt7915.h
 +++ b/mt7915/mt7915.h
 @@ -307,6 +307,8 @@ struct mt7915_phy {
@@ -88,7 +88,7 @@
  	struct mt76_channel_state state_ts;
  
 diff --git a/mt7915/mtk_debugfs.c b/mt7915/mtk_debugfs.c
-index 4fb845b..1aafe04 100644
+index 530bde1a..824ddeda 100644
 --- a/mt7915/mtk_debugfs.c
 +++ b/mt7915/mtk_debugfs.c
 @@ -2558,6 +2558,38 @@ static int mt7915_token_txd_read(struct seq_file *s, void *data)
@@ -139,5 +139,5 @@
  			    &fops_fw_debug_module);
  	debugfs_create_file("fw_debug_level", 0600, dir, dev,
 -- 
-2.39.0
+2.18.0
 
diff --git a/recipes-wifi/linux-mt76/files/patches/1005-mt76-mt7915-certification-patches.patch b/recipes-wifi/linux-mt76/files/patches/1005-mt76-mt7915-certification-patches.patch
index 1c216ec..8bb1195 100644
--- a/recipes-wifi/linux-mt76/files/patches/1005-mt76-mt7915-certification-patches.patch
+++ b/recipes-wifi/linux-mt76/files/patches/1005-mt76-mt7915-certification-patches.patch
@@ -1,4 +1,4 @@
-From a3246b4d0ebb9b123c552f05226b0dc612c70788 Mon Sep 17 00:00:00 2001
+From a3b277ab5965fc3ea056d9d4f2f9a9dedd4fef51 Mon Sep 17 00:00:00 2001
 From: MeiChia Chiu <meichia.chiu@mediatek.com>
 Date: Mon, 6 Jun 2022 20:15:51 +0800
 Subject: [PATCH 1005/1009] mt76: mt7915: certification patches
@@ -6,20 +6,20 @@
 ---
  mt76_connac_mcu.h    |   1 +
  mt7915/mac.c         |  23 +++
- mt7915/main.c        |  15 +-
+ mt7915/main.c        |  13 +-
  mt7915/mcu.c         | 466 +++++++++++++++++++++++++++++++++++++++++++
  mt7915/mcu.h         | 207 ++++++++++++++++++-
  mt7915/mt7915.h      |  13 ++
- mt7915/mtk_debugfs.c |  25 +--
+ mt7915/mtk_debugfs.c |   7 +-
  mt7915/vendor.c      | 187 +++++++++++++++++
  mt7915/vendor.h      |  42 ++++
- 9 files changed, 965 insertions(+), 14 deletions(-)
+ 9 files changed, 954 insertions(+), 5 deletions(-)
 
 diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
-index 60161c9..ff114cb 100644
+index d35f9e92..68e9c7e1 100644
 --- a/mt76_connac_mcu.h
 +++ b/mt76_connac_mcu.h
-@@ -1199,6 +1199,7 @@ enum {
+@@ -1196,6 +1196,7 @@ enum {
  	MCU_EXT_CMD_PHY_STAT_INFO = 0xad,
  	/* for vendor csi and air monitor */
  	MCU_EXT_CMD_SMESH_CTRL = 0xae,
@@ -28,7 +28,7 @@
  };
  
 diff --git a/mt7915/mac.c b/mt7915/mac.c
-index 547519c..599d328 100644
+index 547519cc..599d328d 100644
 --- a/mt7915/mac.c
 +++ b/mt7915/mac.c
 @@ -8,6 +8,7 @@
@@ -76,7 +76,7 @@
  			       IEEE80211_RC_NSS_CHANGED |
  			       IEEE80211_RC_BW_CHANGED))
 diff --git a/mt7915/main.c b/mt7915/main.c
-index 3ded65d..05a5fbc 100644
+index 3ded65de..f0cbfbef 100644
 --- a/mt7915/main.c
 +++ b/mt7915/main.c
 @@ -678,6 +678,9 @@ int mt7915_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
@@ -107,10 +107,10 @@
  
  void mt7915_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
 diff --git a/mt7915/mcu.c b/mt7915/mcu.c
-index cf9a3e2..c15dce3 100644
+index b507f14f..057ea6ee 100644
 --- a/mt7915/mcu.c
 +++ b/mt7915/mcu.c
-@@ -3939,6 +3939,472 @@ mt7915_mcu_report_csi(struct mt7915_dev *dev, struct sk_buff *skb)
+@@ -3941,6 +3941,472 @@ mt7915_mcu_report_csi(struct mt7915_dev *dev, struct sk_buff *skb)
  
  	return 0;
  }
@@ -584,7 +584,7 @@
  
  #ifdef MTK_DEBUG
 diff --git a/mt7915/mcu.h b/mt7915/mcu.h
-index 275a0ec..714bc44 100644
+index 275a0ece..714bc44d 100644
 --- a/mt7915/mcu.h
 +++ b/mt7915/mcu.h
 @@ -416,10 +416,14 @@ enum {
@@ -818,7 +818,7 @@
  
  #endif
 diff --git a/mt7915/mt7915.h b/mt7915/mt7915.h
-index e94970b..8b292c3 100644
+index e94970ba..8b292c3c 100644
 --- a/mt7915/mt7915.h
 +++ b/mt7915/mt7915.h
 @@ -722,6 +722,19 @@ int mt7915_mmio_wed_init(struct mt7915_dev *dev, void *pdev_ptr,
@@ -842,10 +842,10 @@
  int mt7915_mcu_set_csi(struct mt7915_phy *phy, u8 mode,
  			u8 cfg, u8 v1, u32 v2, u8 *mac_addr);
 diff --git a/mt7915/mtk_debugfs.c b/mt7915/mtk_debugfs.c
-index 1aafe04..e0af645 100644
+index 824ddeda..4662f46f 100644
 --- a/mt7915/mtk_debugfs.c
 +++ b/mt7915/mtk_debugfs.c
-@@ -2564,7 +2564,8 @@ static int mt7915_muru_onoff_get(void *d
+@@ -2564,7 +2564,8 @@ static int mt7915_muru_onoff_get(void *data, u64 *val)
  
  	*val = phy->muru_onoff;
  
@@ -855,7 +855,7 @@
  		    !!(phy->muru_onoff & MUMIMO_UL),
  		    !!(phy->muru_onoff & MUMIMO_DL),
  		    !!(phy->muru_onoff & OFDMA_UL),
-@@ -2577,8 +2578,8 @@ static int mt7915_muru_onoff_set(void *d
+@@ -2577,8 +2578,8 @@ static int mt7915_muru_onoff_set(void *data, u64 val)
  {
  	struct mt7915_phy *phy = data;
  
@@ -867,7 +867,7 @@
  	}
  
 diff --git a/mt7915/vendor.c b/mt7915/vendor.c
-index b94d787..beb0583 100644
+index b94d787e..beb0583a 100644
 --- a/mt7915/vendor.c
 +++ b/mt7915/vendor.c
 @@ -22,6 +22,29 @@ csi_ctrl_policy[NUM_MTK_VENDOR_ATTRS_CSI_CTRL] = {
@@ -1079,7 +1079,7 @@
  };
  
 diff --git a/mt7915/vendor.h b/mt7915/vendor.h
-index 976817f..1b08321 100644
+index 976817f3..1b08321c 100644
 --- a/mt7915/vendor.h
 +++ b/mt7915/vendor.h
 @@ -6,6 +6,48 @@
@@ -1132,5 +1132,5 @@
  
  enum mtk_vendor_attr_csi_ctrl {
 -- 
-2.39.0
+2.18.0
 
diff --git a/recipes-wifi/linux-mt76/files/patches/1006-mt76-mt7915-add-support-for-runtime-set-in-band-disc.patch b/recipes-wifi/linux-mt76/files/patches/1006-mt76-mt7915-add-support-for-runtime-set-in-band-disc.patch
index 8ed42b3..b1db4b7 100644
--- a/recipes-wifi/linux-mt76/files/patches/1006-mt76-mt7915-add-support-for-runtime-set-in-band-disc.patch
+++ b/recipes-wifi/linux-mt76/files/patches/1006-mt76-mt7915-add-support-for-runtime-set-in-band-disc.patch
@@ -1,4 +1,4 @@
-From 1a60e2ba1ae97e6109e1e27dc48ae074b46043ff Mon Sep 17 00:00:00 2001
+From 8999d582213c666073a3bf3c855b66b16be16a52 Mon Sep 17 00:00:00 2001
 From: MeiChia Chiu <meichia.chiu@mediatek.com>
 Date: Fri, 27 May 2022 15:51:48 +0800
 Subject: [PATCH 1006/1009] mt76: mt7915: add support for runtime set in-band
@@ -10,10 +10,10 @@
  1 file changed, 2 insertions(+), 3 deletions(-)
 
 diff --git a/mt7915/mcu.c b/mt7915/mcu.c
-index 40b17b5f..f7ed1049 100644
+index 057ea6ee..03c94349 100644
 --- a/mt7915/mcu.c
 +++ b/mt7915/mcu.c
-@@ -1993,8 +1993,7 @@ mt7915_mcu_beacon_inband_discov(struct mt7915_dev *dev, struct ieee80211_vif *vi
+@@ -1994,8 +1994,7 @@ mt7915_mcu_beacon_inband_discov(struct mt7915_dev *dev, struct ieee80211_vif *vi
  	u8 *buf, interval;
  	int len;
  
@@ -23,7 +23,7 @@
  		interval = vif->bss_conf.fils_discovery.max_interval;
  		skb = ieee80211_get_fils_discovery_tmpl(hw, vif);
  	} else if (changed & BSS_CHANGED_UNSOL_BCAST_PROBE_RESP &&
-@@ -2029,7 +2028,7 @@ mt7915_mcu_beacon_inband_discov(struct mt7915_dev *dev, struct ieee80211_vif *vi
+@@ -2030,7 +2029,7 @@ mt7915_mcu_beacon_inband_discov(struct mt7915_dev *dev, struct ieee80211_vif *vi
  	discov->tx_type = !!(changed & BSS_CHANGED_FILS_DISCOVERY);
  	discov->tx_interval = interval;
  	discov->prob_rsp_len = cpu_to_le16(MT_TXD_SIZE + skb->len);
diff --git a/recipes-wifi/linux-mt76/files/patches/1007-mt76-mt7915-add-mt76-vendor-muru-onoff-command.patch b/recipes-wifi/linux-mt76/files/patches/1007-mt76-mt7915-add-mt76-vendor-muru-onoff-command.patch
index 050a40b..39d4df8 100644
--- a/recipes-wifi/linux-mt76/files/patches/1007-mt76-mt7915-add-mt76-vendor-muru-onoff-command.patch
+++ b/recipes-wifi/linux-mt76/files/patches/1007-mt76-mt7915-add-mt76-vendor-muru-onoff-command.patch
@@ -1,4 +1,4 @@
-From 7197b9ba537a486c3ba398d2e0a806f093b682a3 Mon Sep 17 00:00:00 2001
+From b789f416faea7dc90e4c83119274c773d417069c Mon Sep 17 00:00:00 2001
 From: MeiChia Chiu <meichia.chiu@mediatek.com>
 Date: Wed, 22 Jun 2022 10:53:43 +0800
 Subject: [PATCH 1007/1009] mt76: mt7915: add mt76 vendor muru onoff command
@@ -11,10 +11,10 @@
  4 files changed, 63 insertions(+)
 
 diff --git a/mt7915/mcu.c b/mt7915/mcu.c
-index 3a0e87a..62d83bf 100644
+index 03c94349..70349a75 100644
 --- a/mt7915/mcu.c
 +++ b/mt7915/mcu.c
-@@ -3958,6 +3958,13 @@ void mt7915_set_wireless_vif(void *data, u8 *mac, struct ieee80211_vif *vif)
+@@ -3960,6 +3960,13 @@ void mt7915_set_wireless_vif(void *data, u8 *mac, struct ieee80211_vif *vif)
  		if (val == 0)
  			phy->muru_onoff = MUMIMO_DL_CERT | MUMIMO_DL;
  		break;
@@ -29,7 +29,7 @@
  }
  
 diff --git a/mt7915/mcu.h b/mt7915/mcu.h
-index 714bc44..aaea323 100644
+index 714bc44d..ac4e6c8b 100644
 --- a/mt7915/mcu.h
 +++ b/mt7915/mcu.h
 @@ -423,6 +423,7 @@ enum {
@@ -41,7 +41,7 @@
  };
  
 diff --git a/mt7915/vendor.c b/mt7915/vendor.c
-index beb0583..5acbd2d 100644
+index beb0583a..8d864c86 100644
 --- a/mt7915/vendor.c
 +++ b/mt7915/vendor.c
 @@ -34,6 +34,11 @@ wireless_ctrl_policy[NUM_MTK_VENDOR_ATTRS_WIRELESS_CTRL] = {
@@ -109,7 +109,7 @@
  };
  
 diff --git a/mt7915/vendor.h b/mt7915/vendor.h
-index 1b08321..a8e4ebf 100644
+index 1b08321c..2be5fc89 100644
 --- a/mt7915/vendor.h
 +++ b/mt7915/vendor.h
 @@ -8,6 +8,7 @@ enum mtk_nl80211_vendor_subcmds {
@@ -139,5 +139,5 @@
  	MTK_VENDOR_ATTR_RFEATURE_CTRL_UNSPEC,
  
 -- 
-2.39.0
+2.18.0
 
diff --git a/recipes-wifi/linux-mt76/files/patches/1008-mt76-mt7915-drop-undefined-action-frame.patch b/recipes-wifi/linux-mt76/files/patches/1008-mt76-mt7915-drop-undefined-action-frame.patch
index eea5003..a48e596 100644
--- a/recipes-wifi/linux-mt76/files/patches/1008-mt76-mt7915-drop-undefined-action-frame.patch
+++ b/recipes-wifi/linux-mt76/files/patches/1008-mt76-mt7915-drop-undefined-action-frame.patch
@@ -1,4 +1,4 @@
-From d23718033b7a128a1bcffc203b38609116428374 Mon Sep 17 00:00:00 2001
+From d88b52321783cfb7cb51bc383d13ed270ccced43 Mon Sep 17 00:00:00 2001
 From: Peter Chiu <chui-hao.chiu@mediatek.com>
 Date: Thu, 14 Apr 2022 15:18:02 +0800
 Subject: [PATCH 1008/1009] mt76: mt7915: drop undefined action frame
diff --git a/recipes-wifi/linux-mt76/files/patches/1009-mt76-mt7915-add-fw_version-dump.patch b/recipes-wifi/linux-mt76/files/patches/1009-mt76-mt7915-add-fw_version-dump.patch
index 89c073a..f405a43 100644
--- a/recipes-wifi/linux-mt76/files/patches/1009-mt76-mt7915-add-fw_version-dump.patch
+++ b/recipes-wifi/linux-mt76/files/patches/1009-mt76-mt7915-add-fw_version-dump.patch
@@ -1,4 +1,4 @@
-From e64af60e5c5642dec30e8605967b74dff53ada80 Mon Sep 17 00:00:00 2001
+From 5034a64c8d1905c639f2bb26f538f4d2d7703a21 Mon Sep 17 00:00:00 2001
 From: Evelyn Tsai <evelyn.tsai@mediatek.com>
 Date: Wed, 17 Aug 2022 13:40:24 +0800
 Subject: [PATCH 1009/1009] mt76: mt7915: add fw_version dump
@@ -10,10 +10,10 @@
  3 files changed, 32 insertions(+)
 
 diff --git a/mt76.h b/mt76.h
-index ccca0162..00f1cd0d 100644
+index 183b0fc5..55751e8f 100644
 --- a/mt76.h
 +++ b/mt76.h
-@@ -843,6 +843,10 @@ struct mt76_dev {
+@@ -844,6 +844,10 @@ struct mt76_dev {
  		struct mt76_usb usb;
  		struct mt76_sdio sdio;
  	};
@@ -59,7 +59,7 @@
  		struct mt76_connac2_patch_sec *sec;
  		u32 len, addr, mode;
 diff --git a/mt7915/mtk_debugfs.c b/mt7915/mtk_debugfs.c
-index f8d2cbbb..cba38513 100644
+index 4662f46f..05dc7d5a 100644
 --- a/mt7915/mtk_debugfs.c
 +++ b/mt7915/mtk_debugfs.c
 @@ -2799,6 +2799,22 @@ static int mt7915_agginfo_read_band1(struct seq_file *s, void *data)
diff --git a/recipes-wifi/linux-mt76/files/patches/1111-mt76-testmode-rework-testmode-init-registers.patch b/recipes-wifi/linux-mt76/files/patches/1111-mt76-testmode-rework-testmode-init-registers.patch
index 54c27fb..d8bcf4c 100644
--- a/recipes-wifi/linux-mt76/files/patches/1111-mt76-testmode-rework-testmode-init-registers.patch
+++ b/recipes-wifi/linux-mt76/files/patches/1111-mt76-testmode-rework-testmode-init-registers.patch
@@ -1,7 +1,7 @@
-From 6517389a3eb0ee290151240c1639a94405fdfbd8 Mon Sep 17 00:00:00 2001
+From 67a19923b1e9f0491531d7f641725310b5152f87 Mon Sep 17 00:00:00 2001
 From: Shayne Chen <shayne.chen@mediatek.com>
 Date: Mon, 6 Jun 2022 19:46:26 +0800
-Subject: [PATCH 1111/1133] mt76: testmode: rework testmode init registers
+Subject: [PATCH 1111/1132] mt76: testmode: rework testmode init registers
 
 ---
  mac80211.c        |   3 +-
@@ -17,10 +17,10 @@
  10 files changed, 164 insertions(+), 35 deletions(-)
 
 diff --git a/mac80211.c b/mac80211.c
-index b117e446..00e7b4f3 100644
+index 87902f4b..ad5d6f8b 100644
 --- a/mac80211.c
 +++ b/mac80211.c
-@@ -817,7 +817,8 @@ void mt76_rx(struct mt76_dev *dev, enum mt76_rxq_id q, struct sk_buff *skb)
+@@ -826,7 +826,8 @@ void mt76_rx(struct mt76_dev *dev, enum mt76_rxq_id q, struct sk_buff *skb)
  	}
  
  #ifdef CONFIG_NL80211_TESTMODE
@@ -31,10 +31,10 @@
  		if (status->flag & RX_FLAG_FAILED_FCS_CRC)
  			phy->test.rx_stats.fcs_error[q]++;
 diff --git a/mt76.h b/mt76.h
-index 00f1cd0d..25ad0f6b 100644
+index 55751e8f..ca664489 100644
 --- a/mt76.h
 +++ b/mt76.h
-@@ -643,6 +643,8 @@ struct mt76_testmode_ops {
+@@ -644,6 +644,8 @@ struct mt76_testmode_ops {
  	int (*dump_stats)(struct mt76_phy *phy, struct sk_buff *msg);
  };
  
@@ -43,7 +43,7 @@
  struct mt76_testmode_data {
  	enum mt76_testmode_state state;
  
-@@ -674,6 +676,8 @@ struct mt76_testmode_data {
+@@ -675,6 +677,8 @@ struct mt76_testmode_data {
  
  	u8 addr[3][ETH_ALEN];
  
@@ -52,7 +52,7 @@
  	u32 tx_pending;
  	u32 tx_queued;
  	u16 tx_queued_limit;
-@@ -681,6 +685,7 @@ struct mt76_testmode_data {
+@@ -682,6 +686,7 @@ struct mt76_testmode_data {
  	struct {
  		u64 packets[__MT_RXQ_MAX];
  		u64 fcs_error[__MT_RXQ_MAX];
@@ -61,10 +61,10 @@
  };
  
 diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
-index ff114cb9..1a146563 100644
+index 68e9c7e1..8ba8ebfe 100644
 --- a/mt76_connac_mcu.h
 +++ b/mt76_connac_mcu.h
-@@ -1193,6 +1193,7 @@ enum {
+@@ -1190,6 +1190,7 @@ enum {
  	MCU_EXT_CMD_OFFCH_SCAN_CTRL = 0x9a,
  	MCU_EXT_CMD_SET_RDD_TH = 0x9d,
  	MCU_EXT_CMD_MURU_CTRL = 0x9f,
@@ -73,7 +73,7 @@
  	MCU_EXT_CMD_GROUP_PRE_CAL_INFO = 0xab,
  	MCU_EXT_CMD_DPD_PRE_CAL_INFO = 0xac,
 diff --git a/mt7915/mcu.h b/mt7915/mcu.h
-index aaea3230..a4b7ef82 100644
+index ac4e6c8b..3c16d214 100644
 --- a/mt7915/mcu.h
 +++ b/mt7915/mcu.h
 @@ -9,6 +9,7 @@
@@ -85,7 +85,7 @@
  	MCU_ATE_CLEAN_TXQUEUE = 0x1c,
  };
 diff --git a/mt7915/mmio.c b/mt7915/mmio.c
-index 225a1960..6d8455d5 100644
+index 6f0c0e2a..dbafb5ff 100644
 --- a/mt7915/mmio.c
 +++ b/mt7915/mmio.c
 @@ -120,6 +120,7 @@ static const u32 mt7986_reg[] = {
diff --git a/recipes-wifi/linux-mt76/files/patches/1112-mt76-testmode-additional-supports.patch b/recipes-wifi/linux-mt76/files/patches/1112-mt76-testmode-additional-supports.patch
index 1430ef9..e5beb49 100644
--- a/recipes-wifi/linux-mt76/files/patches/1112-mt76-testmode-additional-supports.patch
+++ b/recipes-wifi/linux-mt76/files/patches/1112-mt76-testmode-additional-supports.patch
@@ -1,9 +1,10 @@
-From 947b0a84d32ca9fbdfc5befc133da50c1349694e Mon Sep 17 00:00:00 2001
+From ec2f469639d9c5119fb6f1592df8407f3f45a8fe Mon Sep 17 00:00:00 2001
 From: Shayne Chen <shayne.chen@mediatek.com>
 Date: Thu, 21 Apr 2022 15:43:19 +0800
-Subject: [PATCH 1112/1133] mt76: testmode: additional supports
+Subject: [PATCH 1112/1116] mt76: testmode: additional supports
 
 Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
 ---
  dma.c             |    3 +-
  mac80211.c        |   12 +
@@ -18,16 +19,16 @@
  mt7915/mmio.c     |    2 +
  mt7915/mt7915.h   |   14 +-
  mt7915/regs.h     |    3 +
- mt7915/testmode.c | 1172 ++++++++++++++++++++++++++++++++++++++++++---
+ mt7915/testmode.c | 1177 ++++++++++++++++++++++++++++++++++++++++++---
  mt7915/testmode.h |  278 +++++++++++
  testmode.c        |  275 +++++++++--
  testmode.h        |   75 +++
- tools/fields.c    |   80 ++++
+ tools/fields.c    |   80 +++
  tx.c              |    3 +-
- 19 files changed, 1964 insertions(+), 148 deletions(-)
+ 19 files changed, 1969 insertions(+), 148 deletions(-)
 
 diff --git a/dma.c b/dma.c
-index e3fa4f39..a6bb3730 100644
+index e3fa4f3..a6bb373 100644
 --- a/dma.c
 +++ b/dma.c
 @@ -566,8 +566,7 @@ free:
@@ -41,7 +42,7 @@
  #endif
  
 diff --git a/mac80211.c b/mac80211.c
-index 00e7b4f3..2a66b1dd 100644
+index 00e7b4f..2a66b1d 100644
 --- a/mac80211.c
 +++ b/mac80211.c
 @@ -56,6 +56,13 @@ static const struct ieee80211_channel mt76_channels_5ghz[] = {
@@ -71,7 +72,7 @@
  
  static const struct ieee80211_channel mt76_channels_6ghz[] = {
 diff --git a/mt76.h b/mt76.h
-index 25ad0f6b..cde52268 100644
+index 25ad0f6..cde5226 100644
 --- a/mt76.h
 +++ b/mt76.h
 @@ -641,6 +641,21 @@ struct mt76_testmode_ops {
@@ -233,7 +234,7 @@
  static inline void mt76_testmode_reset(struct mt76_phy *phy, bool disable)
  {
 diff --git a/mt76_connac_mcu.c b/mt76_connac_mcu.c
-index 2fefac68..b6c2ccf0 100644
+index 2fefac6..b6c2ccf 100644
 --- a/mt76_connac_mcu.c
 +++ b/mt76_connac_mcu.c
 @@ -394,6 +394,7 @@ void mt76_connac_mcu_sta_basic_tlv(struct sk_buff *skb,
@@ -255,7 +256,7 @@
  		return;
  
 diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
-index 1a146563..f616bcea 100644
+index 1a14656..f616bce 100644
 --- a/mt76_connac_mcu.h
 +++ b/mt76_connac_mcu.h
 @@ -999,6 +999,7 @@ enum {
@@ -275,10 +276,10 @@
  	MCU_EXT_CMD_CSI_CTRL = 0xc2,
  };
 diff --git a/mt7915/init.c b/mt7915/init.c
-index f73d34a9..19447ad1 100644
+index 3897ac4..0a13a83 100644
 --- a/mt7915/init.c
 +++ b/mt7915/init.c
-@@ -681,7 +681,7 @@ static void mt7915_init_work(struct work_struct *work)
+@@ -683,7 +683,7 @@ static void mt7915_init_work(struct work_struct *work)
  	struct mt7915_dev *dev = container_of(work, struct mt7915_dev,
  				 init_work);
  
@@ -288,7 +289,7 @@
  	mt7915_init_txpower(dev, &dev->mphy.sband_2g.sband);
  	mt7915_init_txpower(dev, &dev->mphy.sband_5g.sband);
 diff --git a/mt7915/mac.c b/mt7915/mac.c
-index de2bdba5..1460a32b 100644
+index de2bdba..1460a32 100644
 --- a/mt7915/mac.c
 +++ b/mt7915/mac.c
 @@ -627,16 +627,38 @@ mt7915_mac_write_txwi_tm(struct mt7915_phy *phy, __le32 *txwi,
@@ -370,7 +371,7 @@
  		goto out;
  
 diff --git a/mt7915/main.c b/mt7915/main.c
-index e4d1c27b..ea0d22fe 100644
+index f0cbfbe..651887c 100644
 --- a/mt7915/main.c
 +++ b/mt7915/main.c
 @@ -238,7 +238,7 @@ static int mt7915_add_interface(struct ieee80211_hw *hw,
@@ -383,7 +384,7 @@
  		mvif->mt76.wmm_idx += 2;
  
 diff --git a/mt7915/mcu.c b/mt7915/mcu.c
-index 6ec12fd2..4d878665 100644
+index 62d83bf..0e5ed14 100644
 --- a/mt7915/mcu.c
 +++ b/mt7915/mcu.c
 @@ -383,6 +383,11 @@ mt7915_mcu_rx_ext_event(struct mt7915_dev *dev, struct sk_buff *skb)
@@ -406,7 +407,7 @@
  	    !rxd->seq)
  		mt7915_mcu_rx_unsolicited_event(dev, skb);
  	else
-@@ -2847,14 +2853,14 @@ static int mt7915_mcu_set_eeprom_flash(struct mt7915_dev *dev)
+@@ -2848,14 +2854,14 @@ static int mt7915_mcu_set_eeprom_flash(struct mt7915_dev *dev)
  	return 0;
  }
  
@@ -424,7 +425,7 @@
  
  	return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(EFUSE_BUFFER_MODE),
 diff --git a/mt7915/mcu.h b/mt7915/mcu.h
-index a4b7ef82..1671d563 100644
+index a4b7ef8..1671d56 100644
 --- a/mt7915/mcu.h
 +++ b/mt7915/mcu.h
 @@ -8,10 +8,15 @@
@@ -481,7 +482,7 @@
  
  enum {
 diff --git a/mt7915/mmio.c b/mt7915/mmio.c
-index 6d8455d5..9a666d0f 100644
+index 6d8455d..9a666d0 100644
 --- a/mt7915/mmio.c
 +++ b/mt7915/mmio.c
 @@ -134,6 +134,7 @@ static const u32 mt7915_offs[] = {
@@ -501,10 +502,10 @@
  	[AGG_PCR0]		= 0x040,
  	[AGG_ACR0]		= 0x054,
 diff --git a/mt7915/mt7915.h b/mt7915/mt7915.h
-index 018fd23e..c45e42c5 100644
+index 8b292c3..9d9c5fc 100644
 --- a/mt7915/mt7915.h
 +++ b/mt7915/mt7915.h
-@@ -321,6 +321,9 @@ struct mt7915_phy {
+@@ -323,6 +323,9 @@ struct mt7915_phy {
  		u8 last_snr;
  
  		u8 spe_idx;
@@ -514,7 +515,7 @@
  	} test;
  #endif
  
-@@ -420,6 +423,14 @@ struct mt7915_dev {
+@@ -422,6 +425,14 @@ struct mt7915_dev {
  	void __iomem *dcm;
  	void __iomem *sku;
  
@@ -529,7 +530,7 @@
  #ifdef MTK_DEBUG
  	u16 wlan_idx;
  	struct {
-@@ -591,7 +602,7 @@ int mt7915_mcu_set_fixed_rate_ctrl(struct mt7915_dev *dev,
+@@ -592,7 +603,7 @@ int mt7915_mcu_set_fixed_rate_ctrl(struct mt7915_dev *dev,
  				   struct ieee80211_vif *vif,
  				   struct ieee80211_sta *sta,
  				   void *data, u32 field);
@@ -538,7 +539,7 @@
  int mt7915_mcu_get_eeprom(struct mt7915_dev *dev, u32 offset);
  int mt7915_mcu_get_eeprom_free_block(struct mt7915_dev *dev, u8 *block_num);
  int mt7915_mcu_set_mac(struct mt7915_dev *dev, int band, bool enable,
-@@ -629,6 +640,7 @@ int mt7915_mcu_fw_log_2_host(struct mt7915_dev *dev, u8 type, u8 ctrl);
+@@ -630,6 +641,7 @@ int mt7915_mcu_fw_log_2_host(struct mt7915_dev *dev, u8 type, u8 ctrl);
  int mt7915_mcu_fw_dbg_ctrl(struct mt7915_dev *dev, u32 module, u8 level);
  void mt7915_mcu_rx_event(struct mt7915_dev *dev, struct sk_buff *skb);
  void mt7915_mcu_exit(struct mt7915_dev *dev);
@@ -547,7 +548,7 @@
  static inline u16 mt7915_wtbl_size(struct mt7915_dev *dev)
  {
 diff --git a/mt7915/regs.h b/mt7915/regs.h
-index d6a05f13..e8768488 100644
+index d6a05f1..e876848 100644
 --- a/mt7915/regs.h
 +++ b/mt7915/regs.h
 @@ -62,6 +62,7 @@ enum offs_rev {
@@ -568,7 +569,7 @@
  							  (_n) * 4))
  #define MT_AGG_PCR0(_band, _n)		MT_WF_AGG(_band, (__OFFS(AGG_PCR0) +	\
 diff --git a/mt7915/testmode.c b/mt7915/testmode.c
-index 46939191..e0ba088f 100644
+index 4693919..9317a8e 100644
 --- a/mt7915/testmode.c
 +++ b/mt7915/testmode.c
 @@ -9,6 +9,9 @@
@@ -1829,7 +1830,19 @@
  }
  
  static int
-@@ -807,6 +1771,7 @@ static int
+@@ -737,6 +1701,11 @@ mt7915_tm_set_state(struct mt76_phy *mphy, enum mt76_testmode_state state)
+ 	struct mt7915_phy *phy = mphy->priv;
+ 	enum mt76_testmode_state prev_state = td->state;
+ 
++	if (!phy->monitor_vif) {
++		dev_err(phy->dev->mt76.dev, "Please make sure monitor interface is up\n");
++		return -ENOTCONN;
++	}
++
+ 	mphy->test.state = state;
+ 
+ 	if (prev_state == MT76_TM_STATE_TX_FRAMES ||
+@@ -807,6 +1776,7 @@ static int
  mt7915_tm_dump_stats(struct mt76_phy *mphy, struct sk_buff *msg)
  {
  	struct mt7915_phy *phy = mphy->priv;
@@ -1837,7 +1850,7 @@
  	void *rx, *rssi;
  	int i;
  
-@@ -852,11 +1817,68 @@ mt7915_tm_dump_stats(struct mt76_phy *mphy, struct sk_buff *msg)
+@@ -852,11 +1822,68 @@ mt7915_tm_dump_stats(struct mt76_phy *mphy, struct sk_buff *msg)
  
  	nla_nest_end(msg, rx);
  
@@ -1907,7 +1920,7 @@
 +	.set_eeprom = mt7915_tm_set_eeprom,
  };
 diff --git a/mt7915/testmode.h b/mt7915/testmode.h
-index a1c54c89..01b08e9e 100644
+index a1c54c8..01b08e9 100644
 --- a/mt7915/testmode.h
 +++ b/mt7915/testmode.h
 @@ -4,6 +4,8 @@
@@ -2222,7 +2235,7 @@
 +
  #endif
 diff --git a/testmode.c b/testmode.c
-index 1d0d5d30..7a9ed543 100644
+index 1d0d5d3..7a9ed54 100644
 --- a/testmode.c
 +++ b/testmode.c
 @@ -27,28 +27,16 @@ const struct nla_policy mt76_tm_policy[NUM_MT76_TM_ATTRS] = {
@@ -2689,7 +2702,7 @@
  		a = nla_nest_start(msg, MT76_TM_ATTR_TX_POWER);
  		if (!a)
 diff --git a/testmode.h b/testmode.h
-index 89613266..57949f2b 100644
+index 8961326..57949f2 100644
 --- a/testmode.h
 +++ b/testmode.h
 @@ -6,6 +6,8 @@
@@ -2794,7 +2807,7 @@
 +
  #endif
 diff --git a/tools/fields.c b/tools/fields.c
-index e3f69089..6e36ab27 100644
+index e3f6908..6e36ab2 100644
 --- a/tools/fields.c
 +++ b/tools/fields.c
 @@ -10,6 +10,7 @@ static const char * const testmode_state[] = {
@@ -2920,7 +2933,7 @@
  };
  
 diff --git a/tx.c b/tx.c
-index 1f309d05..6d55566f 100644
+index 1f309d0..6d55566 100644
 --- a/tx.c
 +++ b/tx.c
 @@ -250,8 +250,7 @@ void __mt76_tx_complete_skb(struct mt76_dev *dev, u16 wcid_idx, struct sk_buff *
diff --git a/recipes-wifi/linux-mt76/files/patches/1113-mt76-testmode-add-pre-cal-support.patch b/recipes-wifi/linux-mt76/files/patches/1113-mt76-testmode-add-pre-cal-support.patch
index 496d3a6..137b15a 100644
--- a/recipes-wifi/linux-mt76/files/patches/1113-mt76-testmode-add-pre-cal-support.patch
+++ b/recipes-wifi/linux-mt76/files/patches/1113-mt76-testmode-add-pre-cal-support.patch
@@ -1,7 +1,7 @@
-From 7e220c97e2010f5a36f5d86928bb0bb7f3f5aa16 Mon Sep 17 00:00:00 2001
+From 52d97d39f652d9b7441bbbe52de72b25796df4a0 Mon Sep 17 00:00:00 2001
 From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
 Date: Wed, 31 Aug 2022 20:06:52 +0800
-Subject: [PATCH 1113/1133] mt76: testmode: add pre-cal support
+Subject: [PATCH 1113/1116] mt76: testmode: add pre-cal support
 
 Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
 Change-Id: Ibfbbc3443de994eeb4daa5e364b0a90f5d7d3bcd
@@ -20,7 +20,7 @@
  11 files changed, 562 insertions(+), 13 deletions(-)
 
 diff --git a/eeprom.c b/eeprom.c
-index 0a88048b..cb6ff17a 100644
+index 0a88048..cb6ff17 100644
 --- a/eeprom.c
 +++ b/eeprom.c
 @@ -89,8 +89,10 @@ int mt76_get_of_eeprom(struct mt76_dev *dev, void *eep, int offset, int len)
@@ -37,7 +37,7 @@
  
  out_put_node:
 diff --git a/mt76.h b/mt76.h
-index cde52268..e22f82c7 100644
+index cde5226..e22f82c 100644
 --- a/mt76.h
 +++ b/mt76.h
 @@ -642,6 +642,7 @@ struct mt76_testmode_ops {
@@ -49,7 +49,7 @@
  
  struct mt76_testmode_entry_data {
 diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
-index f616bcea..89411ba6 100644
+index f616bce..89411ba 100644
 --- a/mt76_connac_mcu.h
 +++ b/mt76_connac_mcu.h
 @@ -995,6 +995,7 @@ enum {
@@ -61,7 +61,7 @@
  	MCU_EXT_EVENT_FW_LOG_2_HOST = 0x13,
  	MCU_EXT_EVENT_THERMAL_PROTECT = 0x22,
 diff --git a/mt7915/eeprom.h b/mt7915/eeprom.h
-index f3e56817..88aaa16a 100644
+index f3e5681..88aaa16 100644
 --- a/mt7915/eeprom.h
 +++ b/mt7915/eeprom.h
 @@ -39,10 +39,18 @@ enum mt7915_eeprom_field {
@@ -114,7 +114,7 @@
  
  #endif
 diff --git a/mt7915/mcu.c b/mt7915/mcu.c
-index 4d878665..fb89686b 100644
+index 0e5ed14..4922e73 100644
 --- a/mt7915/mcu.c
 +++ b/mt7915/mcu.c
 @@ -387,6 +387,9 @@ mt7915_mcu_rx_ext_event(struct mt7915_dev *dev, struct sk_buff *skb)
@@ -127,7 +127,7 @@
  #endif
  	default:
  		break;
-@@ -2950,7 +2953,7 @@ int mt7915_mcu_apply_group_cal(struct mt7915_dev *dev)
+@@ -2951,7 +2954,7 @@ int mt7915_mcu_apply_group_cal(struct mt7915_dev *dev)
  	u8 idx = 0, *cal = dev->cal, *eep = dev->mt76.eeprom.data;
  	u32 total = MT_EE_CAL_GROUP_SIZE;
  
@@ -136,7 +136,7 @@
  		return 0;
  
  	/*
-@@ -3030,11 +3033,29 @@ int mt7915_mcu_apply_tx_dpd(struct mt7915_phy *phy)
+@@ -3031,11 +3034,29 @@ int mt7915_mcu_apply_tx_dpd(struct mt7915_phy *phy)
  {
  	struct mt7915_dev *dev = phy->dev;
  	struct cfg80211_chan_def *chandef = &phy->mt76->chandef;
@@ -169,10 +169,10 @@
  
  	idx = mt7915_dpd_freq_idx(center_freq, chandef->width);
 diff --git a/mt7915/mt7915.h b/mt7915/mt7915.h
-index c45e42c5..5d12cbbc 100644
+index 9d9c5fc..d6fe9e7 100644
 --- a/mt7915/mt7915.h
 +++ b/mt7915/mt7915.h
-@@ -407,6 +407,10 @@ struct mt7915_dev {
+@@ -409,6 +409,10 @@ struct mt7915_dev {
  	struct rchan *relay_fwlog;
  
  	void *cal;
@@ -183,7 +183,7 @@
  
  	struct {
  		u8 debug_wm;
-@@ -641,6 +645,7 @@ int mt7915_mcu_fw_dbg_ctrl(struct mt7915_dev *dev, u32 module, u8 level);
+@@ -642,6 +646,7 @@ int mt7915_mcu_fw_dbg_ctrl(struct mt7915_dev *dev, u32 module, u8 level);
  void mt7915_mcu_rx_event(struct mt7915_dev *dev, struct sk_buff *skb);
  void mt7915_mcu_exit(struct mt7915_dev *dev);
  int mt7915_tm_txbf_status_read(struct mt7915_dev *dev, struct sk_buff *skb);
@@ -192,7 +192,7 @@
  static inline u16 mt7915_wtbl_size(struct mt7915_dev *dev)
  {
 diff --git a/mt7915/testmode.c b/mt7915/testmode.c
-index e0ba088f..a9e57e4b 100644
+index 9317a8e..a7c185f 100644
 --- a/mt7915/testmode.c
 +++ b/mt7915/testmode.c
 @@ -5,6 +5,7 @@
@@ -541,7 +541,7 @@
  static void
  mt7915_tm_update_params(struct mt7915_phy *phy, u32 changed)
  {
-@@ -1715,6 +2024,10 @@ mt7915_tm_set_state(struct mt76_phy *mphy, enum mt76_testmode_state state)
+@@ -1720,6 +2029,10 @@ mt7915_tm_set_state(struct mt76_phy *mphy, enum mt76_testmode_state state)
  	else if (prev_state == MT76_TM_STATE_OFF ||
  		 state == MT76_TM_STATE_OFF)
  		mt7915_tm_init(phy, !(state == MT76_TM_STATE_OFF));
@@ -552,7 +552,7 @@
  
  	if ((state == MT76_TM_STATE_IDLE &&
  	     prev_state == MT76_TM_STATE_OFF) ||
-@@ -1876,9 +2189,113 @@ mt7915_tm_set_eeprom(struct mt76_phy *mphy, u32 offset, u8 *val, u8 action)
+@@ -1881,9 +2194,113 @@ mt7915_tm_set_eeprom(struct mt76_phy *mphy, u32 offset, u8 *val, u8 action)
  	return ret;
  }
  
@@ -667,7 +667,7 @@
 +	.dump_precal = mt7915_tm_dump_precal,
  };
 diff --git a/mt7915/testmode.h b/mt7915/testmode.h
-index 01b08e9e..d500987d 100644
+index 01b08e9..d500987 100644
 --- a/mt7915/testmode.h
 +++ b/mt7915/testmode.h
 @@ -81,6 +81,11 @@ struct tm_tx_cont {
@@ -735,7 +735,7 @@
  	TAM_ARB_OP_MODE_NORMAL = 1,
  	TAM_ARB_OP_MODE_TEST,
 diff --git a/testmode.c b/testmode.c
-index 7a9ed543..42da6f08 100644
+index 7a9ed54..42da6f0 100644
 --- a/testmode.c
 +++ b/testmode.c
 @@ -763,6 +763,18 @@ int mt76_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *msg,
@@ -768,7 +768,7 @@
  
  	if (nla_put_u32(msg, MT76_TM_ATTR_TX_COUNT, td->tx_count) ||
 diff --git a/testmode.h b/testmode.h
-index 57949f2b..34936e5f 100644
+index 57949f2..34936e5 100644
 --- a/testmode.h
 +++ b/testmode.h
 @@ -19,6 +19,7 @@
@@ -824,7 +824,7 @@
  
  	/* keep last */
 diff --git a/tools/fields.c b/tools/fields.c
-index 6e36ab27..1be1ffd6 100644
+index 6e36ab2..1be1ffd 100644
 --- a/tools/fields.c
 +++ b/tools/fields.c
 @@ -11,6 +11,14 @@ static const char * const testmode_state[] = {
diff --git a/recipes-wifi/linux-mt76/files/patches/1114-mt76-testmode-add-iBF-command-mode-support.patch b/recipes-wifi/linux-mt76/files/patches/1114-mt76-testmode-add-iBF-command-mode-support.patch
index 8f8b4dc..ff74c33 100644
--- a/recipes-wifi/linux-mt76/files/patches/1114-mt76-testmode-add-iBF-command-mode-support.patch
+++ b/recipes-wifi/linux-mt76/files/patches/1114-mt76-testmode-add-iBF-command-mode-support.patch
@@ -1,7 +1,7 @@
-From 0f8a11a93fd25593e5e778e0d0abda8d61127117 Mon Sep 17 00:00:00 2001
+From 074ca69eba297963caa63b79a20d2cdf962045d2 Mon Sep 17 00:00:00 2001
 From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
 Date: Mon, 12 Sep 2022 18:16:54 +0800
-Subject: [PATCH 1114/1133] mt76: testmode: add iBF command mode support
+Subject: [PATCH 1114/1116] mt76: testmode: add iBF command mode support
 
 Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
 Change-Id: I7eea1d6412563f889e5774e787e58ce9eba001bd
@@ -13,7 +13,7 @@
  4 files changed, 85 insertions(+), 7 deletions(-)
 
 diff --git a/mt7915/testmode.c b/mt7915/testmode.c
-index a9e57e4b..99582d9c 100644
+index a7c185f..668f483 100644
 --- a/mt7915/testmode.c
 +++ b/mt7915/testmode.c
 @@ -701,6 +701,7 @@ mt7915_tm_txbf_profile_update(struct mt7915_phy *phy, u16 *val, bool ebf)
@@ -105,7 +105,7 @@
  		mt7915_tm_set_tx_len(phy, tx_time);
  
 diff --git a/testmode.c b/testmode.c
-index 42da6f08..b605a4bc 100644
+index 42da6f0..b605a4b 100644
 --- a/testmode.c
 +++ b/testmode.c
 @@ -530,6 +530,42 @@ out:
@@ -164,7 +164,7 @@
  		nla_for_each_nested(cur, tb[MT76_TM_ATTR_TXBF_PARAM], rem) {
  			if (nla_len(cur) != 2 ||
 diff --git a/testmode.h b/testmode.h
-index 34936e5f..bbfb313f 100644
+index 34936e5..bbfb313 100644
 --- a/testmode.h
 +++ b/testmode.h
 @@ -281,8 +281,10 @@ enum mt76_testmode_txbf_act {
@@ -179,7 +179,7 @@
  
  	/* keep last */
 diff --git a/tools/fields.c b/tools/fields.c
-index 1be1ffd6..47fc69f9 100644
+index 1be1ffd..47fc69f 100644
 --- a/tools/fields.c
 +++ b/tools/fields.c
 @@ -32,6 +32,20 @@ static const char * const testmode_tx_mode[] = {
diff --git a/recipes-wifi/linux-mt76/files/patches/1115-mt76-testmode-add-ZWDFS-test-mode-support.patch b/recipes-wifi/linux-mt76/files/patches/1115-mt76-testmode-add-ZWDFS-test-mode-support.patch
index 10a8119..1128a92 100644
--- a/recipes-wifi/linux-mt76/files/patches/1115-mt76-testmode-add-ZWDFS-test-mode-support.patch
+++ b/recipes-wifi/linux-mt76/files/patches/1115-mt76-testmode-add-ZWDFS-test-mode-support.patch
@@ -1,7 +1,7 @@
-From b269297b9cb95ea651d363ba49fff3d25d06f99b Mon Sep 17 00:00:00 2001
+From 34ccd9ebdfd36f8e6e7b554446eaeb022141307d Mon Sep 17 00:00:00 2001
 From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
 Date: Thu, 27 Oct 2022 17:42:07 +0800
-Subject: [PATCH 1115/1133] mt76: testmode: add ZWDFS test mode support
+Subject: [PATCH 1115/1116] mt76: testmode: add ZWDFS test mode support
 
 Change-Id: I14d104b7158a35acf6b0595357d07fb87f5a9d94
 Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
@@ -19,7 +19,7 @@
  10 files changed, 452 insertions(+), 1 deletion(-)
 
 diff --git a/mt76.h b/mt76.h
-index e22f82c7..d5f5054f 100644
+index e22f82c..d5f5054 100644
 --- a/mt76.h
 +++ b/mt76.h
 @@ -725,6 +725,15 @@ struct mt76_testmode_data {
@@ -39,7 +39,7 @@
  
  struct mt76_vif {
 diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
-index 89411ba6..5cef308a 100644
+index 89411ba..5cef308 100644
 --- a/mt76_connac_mcu.h
 +++ b/mt76_connac_mcu.h
 @@ -1195,6 +1195,7 @@ enum {
@@ -59,10 +59,10 @@
  
  enum {
 diff --git a/mt7915/mcu.c b/mt7915/mcu.c
-index fb89686b..988c55c6 100644
+index 4922e73..cce622d 100644
 --- a/mt7915/mcu.c
 +++ b/mt7915/mcu.c
-@@ -2685,6 +2685,7 @@ mt7915_mcu_background_chain_ctrl(struct mt7915_phy *phy,
+@@ -2686,6 +2686,7 @@ mt7915_mcu_background_chain_ctrl(struct mt7915_phy *phy,
  		req.monitor_chan = chandef->chan->hw_value;
  		req.monitor_central_chan =
  			ieee80211_frequency_to_channel(chandef->center_freq1);
@@ -70,7 +70,7 @@
  		req.band_idx = phy->mt76->band_idx;
  		req.scan_mode = 2;
  		break;
-@@ -4503,3 +4504,68 @@ int mt7915_mcu_set_amsdu_algo(struct mt7915_dev *dev, u16 wcid, u8 enable)
+@@ -4504,3 +4505,68 @@ int mt7915_mcu_set_amsdu_algo(struct mt7915_dev *dev, u16 wcid, u8 enable)
  	return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(MEC_CTRL), &req, sizeof(req), true);
  }
  #endif
@@ -140,7 +140,7 @@
 +	return 0;
 +}
 diff --git a/mt7915/mcu.h b/mt7915/mcu.h
-index 1671d563..d780415c 100644
+index 1671d56..d780415 100644
 --- a/mt7915/mcu.h
 +++ b/mt7915/mcu.h
 @@ -629,6 +629,52 @@ struct csi_data {
@@ -197,10 +197,10 @@
  #define OFDMA_DL                       BIT(0)
  #define OFDMA_UL                       BIT(1)
 diff --git a/mt7915/mt7915.h b/mt7915/mt7915.h
-index 5d12cbbc..2b42fb11 100644
+index d6fe9e7..e99b586 100644
 --- a/mt7915/mt7915.h
 +++ b/mt7915/mt7915.h
-@@ -309,6 +309,7 @@ struct mt7915_phy {
+@@ -311,6 +311,7 @@ struct mt7915_phy {
  
  	struct mib_stats mib;
  	struct mt76_channel_state state_ts;
@@ -208,7 +208,7 @@
  
  #ifdef CONFIG_NL80211_TESTMODE
  	struct {
-@@ -759,6 +760,9 @@ int mt7915_vendor_amnt_sta_remove(struct mt7915_phy *phy,
+@@ -760,6 +761,9 @@ int mt7915_vendor_amnt_sta_remove(struct mt7915_phy *phy,
  				  struct ieee80211_sta *sta);
  #endif
  
@@ -219,7 +219,7 @@
  int mt7915_mtk_init_debugfs(struct mt7915_phy *phy, struct dentry *dir);
  int mt7915_dbg_mcu_wa_cmd(struct mt7915_dev *dev, int cmd, u32 a1, u32 a2, u32 a3, bool wait_resp);
 diff --git a/mt7915/regs.h b/mt7915/regs.h
-index e8768488..f4b57099 100644
+index e876848..f4b5709 100644
 --- a/mt7915/regs.h
 +++ b/mt7915/regs.h
 @@ -1194,6 +1194,8 @@ enum offs_rev {
@@ -232,7 +232,7 @@
  #define MT_WF_PHY_BASE			0x83080000
  #define MT_WF_PHY(ofs)			(MT_WF_PHY_BASE + (ofs))
 diff --git a/mt7915/testmode.c b/mt7915/testmode.c
-index 99582d9c..2ae6c07f 100644
+index 668f483..23dcabd 100644
 --- a/mt7915/testmode.c
 +++ b/mt7915/testmode.c
 @@ -13,6 +13,12 @@ enum {
@@ -503,7 +503,7 @@
  
  static int
 diff --git a/testmode.c b/testmode.c
-index b605a4bc..58280a40 100644
+index b605a4b..58280a4 100644
 --- a/testmode.c
 +++ b/testmode.c
 @@ -24,6 +24,13 @@ const struct nla_policy mt76_tm_policy[NUM_MT76_TM_ATTRS] = {
@@ -567,7 +567,7 @@
  	     nla_put_u8(msg, MT76_TM_ATTR_TX_LTF, td->tx_ltf)) ||
  	    (mt76_testmode_param_present(td, MT76_TM_ATTR_TX_ANTENNA) &&
 diff --git a/testmode.h b/testmode.h
-index bbfb313f..e03fa6df 100644
+index bbfb313..e03fa6d 100644
 --- a/testmode.h
 +++ b/testmode.h
 @@ -63,6 +63,20 @@
@@ -635,7 +635,7 @@
 +
  #endif
 diff --git a/tools/fields.c b/tools/fields.c
-index 47fc69f9..6f07eed0 100644
+index 47fc69f..6f07eed 100644
 --- a/tools/fields.c
 +++ b/tools/fields.c
 @@ -46,6 +46,14 @@ static const char * const testmode_txbf_act[] = {
diff --git a/recipes-wifi/linux-mt76/files/patches/1116-mt76-testmode-add-iBF-eBF-cal-and-cert-commands-with.patch b/recipes-wifi/linux-mt76/files/patches/1116-mt76-testmode-add-iBF-eBF-cal-and-cert-commands-with.patch
index 8e9b2aa..fb5bb23 100644
--- a/recipes-wifi/linux-mt76/files/patches/1116-mt76-testmode-add-iBF-eBF-cal-and-cert-commands-with.patch
+++ b/recipes-wifi/linux-mt76/files/patches/1116-mt76-testmode-add-iBF-eBF-cal-and-cert-commands-with.patch
@@ -1,7 +1,7 @@
-From e6da252b1895b1aebdfe737dcd57572d877cd1f1 Mon Sep 17 00:00:00 2001
+From a00620522ddc62d8070077e4d4a1ec18a8402bf9 Mon Sep 17 00:00:00 2001
 From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
 Date: Thu, 15 Dec 2022 19:45:18 +0800
-Subject: [PATCH 1116/1133] mt76: testmode: add iBF/eBF cal and cert commands
+Subject: [PATCH 1116/1116] mt76: testmode: add iBF/eBF cal and cert commands
  with golden
 
 Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
@@ -25,7 +25,7 @@
  16 files changed, 856 insertions(+), 324 deletions(-)
 
 diff --git a/mt76.h b/mt76.h
-index d5f5054f..6ab689af 100644
+index d5f5054..6ab689a 100644
 --- a/mt76.h
 +++ b/mt76.h
 @@ -687,6 +687,7 @@ struct mt76_testmode_data {
@@ -47,7 +47,7 @@
  	u32 tx_pending;
  	u32 tx_queued;
 diff --git a/mt76_connac_mcu.c b/mt76_connac_mcu.c
-index b6c2ccf0..6f5c81ce 100644
+index b6c2ccf..6f5c81c 100644
 --- a/mt76_connac_mcu.c
 +++ b/mt76_connac_mcu.c
 @@ -2802,6 +2802,7 @@ int mt76_connac_mcu_bss_basic_tlv(struct sk_buff *skb,
@@ -68,7 +68,7 @@
  		memcpy(bss->bssid, phy->macaddr, ETH_ALEN);
  	}
 diff --git a/mt7915/mac.c b/mt7915/mac.c
-index 1460a32b..35b85843 100644
+index 1460a32..35b8584 100644
 --- a/mt7915/mac.c
 +++ b/mt7915/mac.c
 @@ -752,8 +752,10 @@ mt7915_mac_write_txwi_tm(struct mt7915_phy *phy, __le32 *txwi,
@@ -84,7 +84,7 @@
  	txwi[6] |= cpu_to_le32(val);
  #endif
 diff --git a/mt7915/main.c b/mt7915/main.c
-index ea0d22fe..ecd023f6 100644
+index 651887c..21ad3b0 100644
 --- a/mt7915/main.c
 +++ b/mt7915/main.c
 @@ -205,46 +205,37 @@ static void mt7915_init_bitrate_mask(struct ieee80211_vif *vif)
@@ -175,7 +175,7 @@
  
  	return ret;
 diff --git a/mt7915/mcu.c b/mt7915/mcu.c
-index 988c55c6..e82b7e14 100644
+index cce622d..d8a1b00 100644
 --- a/mt7915/mcu.c
 +++ b/mt7915/mcu.c
 @@ -193,6 +193,7 @@ mt7915_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb,
@@ -227,7 +227,7 @@
  
  	if (enable) {
  		mt7915_mcu_bss_rfch_tlv(skb, vif, phy);
-@@ -3452,6 +3466,7 @@ int mt7915_mcu_set_ser(struct mt7915_dev *dev, u8 action, u8 set, u8 band)
+@@ -3453,6 +3467,7 @@ int mt7915_mcu_set_ser(struct mt7915_dev *dev, u8 action, u8 set, u8 band)
  
  int mt7915_mcu_set_txbf(struct mt7915_dev *dev, u8 action)
  {
@@ -235,7 +235,7 @@
  	struct {
  		u8 action;
  		union {
-@@ -3478,7 +3493,6 @@ int mt7915_mcu_set_txbf(struct mt7915_dev *dev, u8 action)
+@@ -3479,7 +3494,6 @@ int mt7915_mcu_set_txbf(struct mt7915_dev *dev, u8 action)
  		.action = action,
  	};
  
@@ -243,7 +243,7 @@
  	switch (action) {
  	case MT_BF_SOUNDING_ON:
  		req.snd.snd_mode = MT_BF_PROCESSING;
-@@ -4396,6 +4410,9 @@ int mt7915_mcu_set_txbf_sound_info(struct mt7915_phy *phy, u8 action,
+@@ -4397,6 +4411,9 @@ int mt7915_mcu_set_txbf_sound_info(struct mt7915_phy *phy, u8 action,
  		req.he_opt = v2;
  		req.glo_opt = v3;
  		break;
@@ -254,7 +254,7 @@
  		return -EINVAL;
  	}
 diff --git a/mt7915/mcu.h b/mt7915/mcu.h
-index d780415c..5c5c92fc 100644
+index d780415..5c5c92f 100644
 --- a/mt7915/mcu.h
 +++ b/mt7915/mcu.h
 @@ -476,10 +476,12 @@ enum {
@@ -448,7 +448,7 @@
  	MURU_SET_ARB_OP_MODE = 14,
  	MURU_SET_PLATFORM_TYPE = 25,
 diff --git a/mt7915/mmio.c b/mt7915/mmio.c
-index 9a666d0f..95ded131 100644
+index 9a666d0..95ded13 100644
 --- a/mt7915/mmio.c
 +++ b/mt7915/mmio.c
 @@ -133,6 +133,7 @@ static const u32 mt7915_offs[] = {
@@ -468,10 +468,10 @@
  	[AGG_AALCR0]		= 0x028,
  	[AGG_AWSCR0]		= 0x030,
 diff --git a/mt7915/mt7915.h b/mt7915/mt7915.h
-index 2b42fb11..ae06a7c6 100644
+index e99b586..bb9c374 100644
 --- a/mt7915/mt7915.h
 +++ b/mt7915/mt7915.h
-@@ -323,7 +323,6 @@ struct mt7915_phy {
+@@ -325,7 +325,6 @@ struct mt7915_phy {
  
  		u8 spe_idx;
  
@@ -479,7 +479,7 @@
  		bool bf_ever_en;
  	} test;
  #endif
-@@ -428,7 +427,7 @@ struct mt7915_dev {
+@@ -430,7 +429,7 @@ struct mt7915_dev {
  	void __iomem *dcm;
  	void __iomem *sku;
  
@@ -488,7 +488,7 @@
  	struct {
  		void *txbf_phase_cal;
  		void *txbf_pfmu_data;
-@@ -567,6 +566,7 @@ void mt7915_dma_prefetch(struct mt7915_dev *dev);
+@@ -568,6 +567,7 @@ void mt7915_dma_prefetch(struct mt7915_dev *dev);
  void mt7915_dma_cleanup(struct mt7915_dev *dev);
  int mt7915_dma_reset(struct mt7915_dev *dev, bool force);
  int mt7915_txbf_init(struct mt7915_dev *dev);
@@ -496,7 +496,7 @@
  void mt7915_init_txpower(struct mt7915_dev *dev,
  			 struct ieee80211_supported_band *sband);
  void mt7915_reset(struct mt7915_dev *dev);
-@@ -645,8 +645,10 @@ int mt7915_mcu_fw_log_2_host(struct mt7915_dev *dev, u8 type, u8 ctrl);
+@@ -646,8 +646,10 @@ int mt7915_mcu_fw_log_2_host(struct mt7915_dev *dev, u8 type, u8 ctrl);
  int mt7915_mcu_fw_dbg_ctrl(struct mt7915_dev *dev, u32 module, u8 level);
  void mt7915_mcu_rx_event(struct mt7915_dev *dev, struct sk_buff *skb);
  void mt7915_mcu_exit(struct mt7915_dev *dev);
@@ -508,7 +508,7 @@
  
  static inline u16 mt7915_wtbl_size(struct mt7915_dev *dev)
  {
-@@ -783,4 +785,10 @@ enum {
+@@ -784,4 +786,10 @@ enum {
  
  #endif
  
@@ -520,7 +520,7 @@
 +
  #endif
 diff --git a/mt7915/mtk_debugfs.c b/mt7915/mtk_debugfs.c
-index cba38513..867d52d1 100644
+index 05dc7d5..a130f56 100644
 --- a/mt7915/mtk_debugfs.c
 +++ b/mt7915/mtk_debugfs.c
 @@ -2908,6 +2908,36 @@ mt7915_txpower_level_set(void *data, u64 val)
@@ -573,7 +573,7 @@
  
  	debugfs_create_devm_seqfile(dev->mt76.dev, "fw_version", dir,
 diff --git a/mt7915/mtk_mcu.c b/mt7915/mtk_mcu.c
-index 143dae26..906c8725 100644
+index 143dae2..906c872 100644
 --- a/mt7915/mtk_mcu.c
 +++ b/mt7915/mtk_mcu.c
 @@ -1,9 +1,10 @@
@@ -836,7 +836,7 @@
 +}
 +#endif
 diff --git a/mt7915/regs.h b/mt7915/regs.h
-index f4b57099..007fd4d2 100644
+index f4b5709..007fd4d 100644
 --- a/mt7915/regs.h
 +++ b/mt7915/regs.h
 @@ -61,6 +61,7 @@ enum offs_rev {
@@ -858,7 +858,7 @@
  #define MT_WF_RMAC_BASE(_band)		((_band) ? 0x820f5000 : 0x820e5000)
  #define MT_WF_RMAC(_band, ofs)		(MT_WF_RMAC_BASE(_band) + (ofs))
 diff --git a/mt7915/testmode.c b/mt7915/testmode.c
-index 2ae6c07f..e4af5e1c 100644
+index 23dcabd..ad1865e 100644
 --- a/mt7915/testmode.c
 +++ b/mt7915/testmode.c
 @@ -53,6 +53,8 @@ struct reg_band {
@@ -1701,7 +1701,7 @@
  	rateval =  mode << 6 | rate_idx;
  	tx_cont->rateval = cpu_to_le16(rateval);
 diff --git a/mt7915/testmode.h b/mt7915/testmode.h
-index d500987d..19823694 100644
+index d500987..1982369 100644
 --- a/mt7915/testmode.h
 +++ b/mt7915/testmode.h
 @@ -311,137 +311,7 @@ struct mt7915_tm_muru {
@@ -1845,7 +1845,7 @@
  
  #endif
 diff --git a/testmode.c b/testmode.c
-index 58280a40..a6b0c160 100644
+index 58280a4..a6b0c16 100644
 --- a/testmode.c
 +++ b/testmode.c
 @@ -191,6 +191,7 @@ mt76_testmode_alloc_skb(struct mt76_phy *phy, u32 len,
@@ -1857,7 +1857,7 @@
  	memcpy(hdr->addr2, addr[1], ETH_ALEN);
  	memcpy(hdr->addr3, addr[2], ETH_ALEN);
 diff --git a/testmode.h b/testmode.h
-index e03fa6df..0e96173b 100644
+index e03fa6d..0e96173 100644
 --- a/testmode.h
 +++ b/testmode.h
 @@ -299,7 +299,10 @@ enum mt76_testmode_cfg {
@@ -1885,7 +1885,7 @@
  	/* keep last */
  	NUM_MT76_TM_TXBF_ACT,
 diff --git a/tools/fields.c b/tools/fields.c
-index 6f07eed0..7211ec52 100644
+index 6f07eed..7211ec5 100644
 --- a/tools/fields.c
 +++ b/tools/fields.c
 @@ -33,7 +33,10 @@ static const char * const testmode_tx_mode[] = {
diff --git a/recipes-wifi/linux-mt76/files/patches/1117-mt76-mt7915-init-rssi-in-WTBL-when-add-station.patch b/recipes-wifi/linux-mt76/files/patches/1117-mt76-mt7915-init-rssi-in-WTBL-when-add-station.patch
index 04e2217..43a0ae7 100644
--- a/recipes-wifi/linux-mt76/files/patches/1117-mt76-mt7915-init-rssi-in-WTBL-when-add-station.patch
+++ b/recipes-wifi/linux-mt76/files/patches/1117-mt76-mt7915-init-rssi-in-WTBL-when-add-station.patch
@@ -1,14 +1,14 @@
-From 57e604539560994584444115d893df77a24fafe0 Mon Sep 17 00:00:00 2001
+From 55254f381217a874a2bb20c288107bb3d2f3811d Mon Sep 17 00:00:00 2001
 From: Peter Chiu <chui-hao.chiu@mediatek.com>
 Date: Sun, 24 Apr 2022 10:07:00 +0800
-Subject: [PATCH 1117/1133] mt76: mt7915: init rssi in WTBL when add station
+Subject: [PATCH 1117/1132] mt76: mt7915: init rssi in WTBL when add station
 
 ---
  mt7915/main.c | 4 ++++
  1 file changed, 4 insertions(+)
 
 diff --git a/mt7915/main.c b/mt7915/main.c
-index ecd023f6..c32df9b1 100644
+index 21ad3b07..d1135d9f 100644
 --- a/mt7915/main.c
 +++ b/mt7915/main.c
 @@ -692,6 +692,7 @@ int mt7915_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
diff --git a/recipes-wifi/linux-mt76/files/patches/1118-mt76-connac-airtime-fairness-feature-off-in-mac80211.patch b/recipes-wifi/linux-mt76/files/patches/1118-mt76-connac-airtime-fairness-feature-off-in-mac80211.patch
index 27f8787..df0677d 100644
--- a/recipes-wifi/linux-mt76/files/patches/1118-mt76-connac-airtime-fairness-feature-off-in-mac80211.patch
+++ b/recipes-wifi/linux-mt76/files/patches/1118-mt76-connac-airtime-fairness-feature-off-in-mac80211.patch
@@ -1,7 +1,7 @@
-From d0a0b51c3aea4e3a948e70aef7d137a5c4b235f3 Mon Sep 17 00:00:00 2001
+From 8ede062234d043820c188e0d25e68a9f71cb0e28 Mon Sep 17 00:00:00 2001
 From: Evelyn Tsai <evelyn.tsai@mediatek.com>
 Date: Fri, 6 May 2022 15:58:42 +0800
-Subject: [PATCH 1118/1133] mt76: connac: airtime fairness feature off in
+Subject: [PATCH 1118/1132] mt76: connac: airtime fairness feature off in
  mac80211
 
 ---
@@ -9,10 +9,10 @@
  1 file changed, 1 deletion(-)
 
 diff --git a/mac80211.c b/mac80211.c
-index 2a66b1dd..e79568d1 100644
+index 9107c0c1..e2122c78 100644
 --- a/mac80211.c
 +++ b/mac80211.c
-@@ -436,7 +436,6 @@ mt76_phy_init(struct mt76_phy *phy, struct ieee80211_hw *hw)
+@@ -437,7 +437,6 @@ mt76_phy_init(struct mt76_phy *phy, struct ieee80211_hw *hw)
  			WIPHY_FLAG_AP_UAPSD;
  
  	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST);
diff --git a/recipes-wifi/linux-mt76/files/patches/1119-mt76-mt7915-add-mt7986-and-mt7916-pre-calibration.patch b/recipes-wifi/linux-mt76/files/patches/1119-mt76-mt7915-add-mt7986-and-mt7916-pre-calibration.patch
index c754c64..026f079 100644
--- a/recipes-wifi/linux-mt76/files/patches/1119-mt76-mt7915-add-mt7986-and-mt7916-pre-calibration.patch
+++ b/recipes-wifi/linux-mt76/files/patches/1119-mt76-mt7915-add-mt7986-and-mt7916-pre-calibration.patch
@@ -1,7 +1,7 @@
-From 1d8b96957fe7ad695caf20a1525118bd48cf34f3 Mon Sep 17 00:00:00 2001
+From 166c44f4a9dfde91ac01c1cd04f79a3b9c8fe23e Mon Sep 17 00:00:00 2001
 From: Peter Chiu <chui-hao.chiu@mediatek.com>
 Date: Fri, 20 May 2022 19:19:25 +0800
-Subject: [PATCH 1119/1133] mt76: mt7915: add mt7986 and mt7916 pre-calibration
+Subject: [PATCH 1119/1132] mt76: mt7915: add mt7986 and mt7916 pre-calibration
 
 Add pre-calibration for mt7986 and mt7916. It has different data size
 with mt7915. Group cal needs 54k and 94k for 2G + 5G and 2G + 6G,
@@ -62,10 +62,10 @@
  	MT_EE_RATE_DELTA_5G =	0x29d,
  	MT_EE_TX0_POWER_2G =	0x2fc,
 diff --git a/mt7915/mcu.c b/mt7915/mcu.c
-index d8a1b00e..185b6495 100644
+index e5cb9317..7da5bdfb 100644
 --- a/mt7915/mcu.c
 +++ b/mt7915/mcu.c
-@@ -2967,7 +2967,8 @@ static int mt7915_mcu_set_pre_cal(struct mt7915_dev *dev, u8 idx,
+@@ -2969,7 +2969,8 @@ static int mt7915_mcu_set_pre_cal(struct mt7915_dev *dev, u8 idx,
  int mt7915_mcu_apply_group_cal(struct mt7915_dev *dev)
  {
  	u8 idx = 0, *cal = dev->cal, *eep = dev->mt76.eeprom.data;
@@ -75,7 +75,7 @@
  
  	if (!(eep[offs] & MT_EE_WIFI_CAL_GROUP))
  		return 0;
-@@ -3005,9 +3006,9 @@ static int mt7915_find_freq_idx(const u16 *freqs, int n_freqs, u16 cur)
+@@ -3007,9 +3008,9 @@ static int mt7915_find_freq_idx(const u16 *freqs, int n_freqs, u16 cur)
  	return -1;
  }
  
@@ -87,7 +87,7 @@
  		5180, 5200, 5220, 5240,
  		5260, 5280, 5300, 5320,
  		5500, 5520, 5540, 5560,
-@@ -3015,34 +3016,69 @@ static int mt7915_dpd_freq_idx(u16 freq, u8 bw)
+@@ -3017,34 +3018,69 @@ static int mt7915_dpd_freq_idx(u16 freq, u8 bw)
  		5660, 5680, 5700, 5745,
  		5765, 5785, 5805, 5825
  	};
@@ -167,7 +167,7 @@
  }
  
  int mt7915_mcu_apply_tx_dpd(struct mt7915_phy *phy)
-@@ -3074,24 +3110,24 @@ int mt7915_mcu_apply_tx_dpd(struct mt7915_phy *phy)
+@@ -3076,24 +3112,24 @@ int mt7915_mcu_apply_tx_dpd(struct mt7915_phy *phy)
  	if (!(eep[offs] & dpd_mask))
  		return 0;
  
diff --git a/recipes-wifi/linux-mt76/files/patches/1120-mt76-mt7915-add-phy-capability-vendor-command.patch b/recipes-wifi/linux-mt76/files/patches/1120-mt76-mt7915-add-phy-capability-vendor-command.patch
index 302d0ab..de77b3a 100644
--- a/recipes-wifi/linux-mt76/files/patches/1120-mt76-mt7915-add-phy-capability-vendor-command.patch
+++ b/recipes-wifi/linux-mt76/files/patches/1120-mt76-mt7915-add-phy-capability-vendor-command.patch
@@ -1,7 +1,7 @@
-From 99d36c925c886a383d62fb3e9d009265161cf62a Mon Sep 17 00:00:00 2001
+From d181881aaeb24db4a51c75ac607eaeacc252e050 Mon Sep 17 00:00:00 2001
 From: Yi-Chia Hsieh <Yi-Chia.Hsieh@mediatek.com>
 Date: Tue, 12 Jul 2022 10:04:35 -0700
-Subject: [PATCH 1120/1133] mt76: mt7915: add phy capability vendor command
+Subject: [PATCH 1120/1132] mt76: mt7915: add phy capability vendor command
 
 ---
  mt7915/mt7915.h |  1 +
@@ -22,7 +22,7 @@
  #define MT7916_WTBL_SIZE		544
  #define MT7915_WTBL_RESERVED		(mt7915_wtbl_size(dev) - 1)
 diff --git a/mt7915/vendor.c b/mt7915/vendor.c
-index 5acbd2d7..526eb6b2 100644
+index 8d864c86..607e66bb 100644
 --- a/mt7915/vendor.c
 +++ b/mt7915/vendor.c
 @@ -50,6 +50,18 @@ rfeature_ctrl_policy[NUM_MTK_VENDOR_ATTRS_RFEATURE_CTRL] = {
@@ -99,7 +99,7 @@
  };
  
 diff --git a/mt7915/vendor.h b/mt7915/vendor.h
-index a8e4ebf9..719b851f 100644
+index 2be5fc89..ffdb466b 100644
 --- a/mt7915/vendor.h
 +++ b/mt7915/vendor.h
 @@ -9,6 +9,7 @@ enum mtk_nl80211_vendor_subcmds {
diff --git a/recipes-wifi/linux-mt76/files/patches/1121-mt76-mt7915-add-vendor-subcmd-EDCCA-ctrl-enable-thre.patch b/recipes-wifi/linux-mt76/files/patches/1121-mt76-mt7915-add-vendor-subcmd-EDCCA-ctrl-enable-thre.patch
index ca559be..fc68b4d 100644
--- a/recipes-wifi/linux-mt76/files/patches/1121-mt76-mt7915-add-vendor-subcmd-EDCCA-ctrl-enable-thre.patch
+++ b/recipes-wifi/linux-mt76/files/patches/1121-mt76-mt7915-add-vendor-subcmd-EDCCA-ctrl-enable-thre.patch
@@ -1,7 +1,7 @@
-From 9f4ef5f8637f597acf5fc876d40f9159e051e512 Mon Sep 17 00:00:00 2001
+From 0519381004e17ba76e11bda6d806bc5a4aedd013 Mon Sep 17 00:00:00 2001
 From: Howard Hsu <howard-yh.hsu@mediatek.com>
 Date: Fri, 24 Jun 2022 11:15:45 +0800
-Subject: [PATCH] mt76: mt7915: add vendor subcmd EDCCA ctrl
+Subject: [PATCH 1121/1132] mt76: mt7915: add vendor subcmd EDCCA ctrl
  enable/threshold/compensation
 
 Change-Id: I06a3f94d5e444be894200e2b6588d76ed38d09d0
@@ -16,10 +16,10 @@
  7 files changed, 265 insertions(+), 1 deletion(-)
 
 diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
-index 5cef308a..65863a0d 100644
+index f4a329e8..e04500f5 100644
 --- a/mt76_connac_mcu.h
 +++ b/mt76_connac_mcu.h
-@@ -1205,6 +1205,7 @@ enum {
+@@ -1202,6 +1202,7 @@ enum {
  	MCU_EXT_CMD_SMESH_CTRL = 0xae,
  	MCU_EXT_CMD_RX_STAT_USER_CTRL = 0xb3,
  	MCU_EXT_CMD_CERT_CFG = 0xb7,
@@ -42,10 +42,10 @@
  		ret = mt7915_set_channel(phy);
  		if (ret)
 diff --git a/mt7915/mcu.c b/mt7915/mcu.c
-index 185b6495..85bb60c9 100644
+index 7da5bdfb..28b2a624 100644
 --- a/mt7915/mcu.c
 +++ b/mt7915/mcu.c
-@@ -4623,3 +4623,76 @@ int mt7915_mcu_ipi_hist_scan(struct mt7915_phy *phy, void *data, u8 mode, bool w
+@@ -4625,3 +4625,76 @@ int mt7915_mcu_ipi_hist_scan(struct mt7915_phy *phy, void *data, u8 mode, bool w
  
  	return 0;
  }
@@ -123,7 +123,7 @@
 +	return 0;
 +}
 diff --git a/mt7915/mcu.h b/mt7915/mcu.h
-index 5c5c92fc..c87fe8e8 100644
+index 7d1dc500..7558726c 100644
 --- a/mt7915/mcu.h
 +++ b/mt7915/mcu.h
 @@ -1058,6 +1058,27 @@ enum {
@@ -169,7 +169,7 @@
  int mt7915_mcu_ipi_hist_scan(struct mt7915_phy *phy, void *data, u8 mode, bool wait_resp);
  
 diff --git a/mt7915/vendor.c b/mt7915/vendor.c
-index 526eb6b2..f712d67c 100644
+index 607e66bb..e748ab16 100644
 --- a/mt7915/vendor.c
 +++ b/mt7915/vendor.c
 @@ -62,6 +62,24 @@ phy_capa_dump_policy[NUM_MTK_VENDOR_ATTRS_PHY_CAPA_DUMP] = {
@@ -326,7 +326,7 @@
  };
  
 diff --git a/mt7915/vendor.h b/mt7915/vendor.h
-index 719b851f..72319717 100644
+index ffdb466b..0c96377f 100644
 --- a/mt7915/vendor.h
 +++ b/mt7915/vendor.h
 @@ -2,6 +2,7 @@
diff --git a/recipes-wifi/linux-mt76/files/patches/1122-mt76-mt7915-implement-bin-file-mode.patch b/recipes-wifi/linux-mt76/files/patches/1122-mt76-mt7915-implement-bin-file-mode.patch
index fdd6c4d..c9c4ad9 100644
--- a/recipes-wifi/linux-mt76/files/patches/1122-mt76-mt7915-implement-bin-file-mode.patch
+++ b/recipes-wifi/linux-mt76/files/patches/1122-mt76-mt7915-implement-bin-file-mode.patch
@@ -1,7 +1,7 @@
-From 8a6c47c698f273485f749c8aa2c3fd2b6a946c86 Mon Sep 17 00:00:00 2001
+From 5650267fdb5d7e237e58908b5f11c9bd12170c3a Mon Sep 17 00:00:00 2001
 From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
 Date: Thu, 7 Jul 2022 11:09:59 +0800
-Subject: [PATCH 1122/1133] mt76: mt7915: implement bin file mode
+Subject: [PATCH 1122/1132] mt76: mt7915: implement bin file mode
 
 Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
 Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
@@ -46,10 +46,10 @@
  mt76_eeprom_override(struct mt76_phy *phy)
  {
 diff --git a/mt76.h b/mt76.h
-index 6ab689af..1638ef63 100644
+index 4cbe3670..675c12a4 100644
 --- a/mt76.h
 +++ b/mt76.h
-@@ -900,9 +900,11 @@ struct mt76_dev {
+@@ -901,9 +901,11 @@ struct mt76_dev {
  		struct mt76_sdio sdio;
  	};
  
@@ -61,7 +61,7 @@
  };
  
  struct mt76_power_limits {
-@@ -1039,6 +1041,7 @@ void mt76_seq_puts_array(struct seq_file *file, const char *str,
+@@ -1040,6 +1042,7 @@ void mt76_seq_puts_array(struct seq_file *file, const char *str,
  int mt76_eeprom_init(struct mt76_dev *dev, int len);
  void mt76_eeprom_override(struct mt76_phy *phy);
  int mt76_get_of_eeprom(struct mt76_dev *dev, void *data, int offset, int len);
@@ -203,7 +203,7 @@
  #define PKT_BIN_DEBUG_MAGIC	0xc8763123
  enum {
 diff --git a/mt7915/mtk_debugfs.c b/mt7915/mtk_debugfs.c
-index da444f38..5f34afc7 100644
+index a130f564..1f347efe 100644
 --- a/mt7915/mtk_debugfs.c
 +++ b/mt7915/mtk_debugfs.c
 @@ -3,6 +3,7 @@
diff --git a/recipes-wifi/linux-mt76/files/patches/1123-mt76-mt7915-initialize-wcid.patch b/recipes-wifi/linux-mt76/files/patches/1123-mt76-mt7915-initialize-wcid.patch
index 066630e..8c0393c 100644
--- a/recipes-wifi/linux-mt76/files/patches/1123-mt76-mt7915-initialize-wcid.patch
+++ b/recipes-wifi/linux-mt76/files/patches/1123-mt76-mt7915-initialize-wcid.patch
@@ -1,7 +1,7 @@
-From 9758ae301b7a08ace837a88d9534c7f22e4fef7f Mon Sep 17 00:00:00 2001
+From 76dcae6805d85864d5ebea700fcc488f80fbd75d Mon Sep 17 00:00:00 2001
 From: Sujuan Chen <sujuan.chen@mediatek.com>
 Date: Tue, 12 Jul 2022 13:56:07 +0800
-Subject: [PATCH 1123/1133] mt76: mt7915: initialize wcid
+Subject: [PATCH 1123/1132] mt76: mt7915: initialize wcid
 
 Signed-off-by: Sujuan Chen <sujuan.chen@mediatek.com>
 ---
diff --git a/recipes-wifi/linux-mt76/files/patches/1124-mt76-mt7915-Add-mu-dump-support.patch b/recipes-wifi/linux-mt76/files/patches/1124-mt76-mt7915-Add-mu-dump-support.patch
index b3789c3..bac5e25 100644
--- a/recipes-wifi/linux-mt76/files/patches/1124-mt76-mt7915-Add-mu-dump-support.patch
+++ b/recipes-wifi/linux-mt76/files/patches/1124-mt76-mt7915-Add-mu-dump-support.patch
@@ -1,7 +1,7 @@
-From dc1ea53db698073c61765925cdb17d28043c6f2d Mon Sep 17 00:00:00 2001
+From 0dbdca6f8f719929258c851bccd3dacbe78c4ad5 Mon Sep 17 00:00:00 2001
 From: TomLiu <tomml.liu@mediatek.com>
 Date: Thu, 11 Aug 2022 18:09:45 -0700
-Subject: [PATCH 1124/1133] mt76: mt7915: Add mu dump support
+Subject: [PATCH 1124/1132] mt76: mt7915: Add mu dump support
 
 Change-Id: I521214f3feb6f0d528a9f550255050ffd1ec96d2
 ---
@@ -10,7 +10,7 @@
  2 files changed, 25 insertions(+)
 
 diff --git a/mt7915/vendor.c b/mt7915/vendor.c
-index f712d67c..83f38e07 100644
+index e748ab16..6915ac8d 100644
 --- a/mt7915/vendor.c
 +++ b/mt7915/vendor.c
 @@ -37,6 +37,7 @@ wireless_ctrl_policy[NUM_MTK_VENDOR_ATTRS_WIRELESS_CTRL] = {
@@ -59,7 +59,7 @@
  		.maxattr = MTK_VENDOR_ATTR_MU_CTRL_MAX,
  	},
 diff --git a/mt7915/vendor.h b/mt7915/vendor.h
-index 72319717..c19ffe72 100644
+index 0c96377f..d8e23d34 100644
 --- a/mt7915/vendor.h
 +++ b/mt7915/vendor.h
 @@ -72,6 +72,7 @@ enum mtk_vendor_attr_mu_ctrl {
diff --git a/recipes-wifi/linux-mt76/files/patches/1125-mt76-mt7915-add-vendor-subcmd-three-wire-PTA-ctrl.patch b/recipes-wifi/linux-mt76/files/patches/1125-mt76-mt7915-add-vendor-subcmd-three-wire-PTA-ctrl.patch
index cd5fd8f..066ae83 100644
--- a/recipes-wifi/linux-mt76/files/patches/1125-mt76-mt7915-add-vendor-subcmd-three-wire-PTA-ctrl.patch
+++ b/recipes-wifi/linux-mt76/files/patches/1125-mt76-mt7915-add-vendor-subcmd-three-wire-PTA-ctrl.patch
@@ -1,7 +1,7 @@
-From 6d68ed1f6ead694289dc9d2a98ef3d49dcb778dd Mon Sep 17 00:00:00 2001
+From 305cf303e1ab242784019ff78a2b534f7c9df707 Mon Sep 17 00:00:00 2001
 From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
 Date: Fri, 28 Oct 2022 10:15:56 +0800
-Subject: [PATCH 1125/1133] mt76: mt7915: add vendor subcmd three wire (PTA)
+Subject: [PATCH 1125/1132] mt76: mt7915: add vendor subcmd three wire (PTA)
  ctrl
 
 Change-Id: Ic1044698f294455594a0c6254f55326fdab90580
@@ -16,10 +16,10 @@
  6 files changed, 111 insertions(+), 29 deletions(-)
 
 diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
-index 65863a0d..41859dc3 100644
+index e04500f5..1ff517f0 100644
 --- a/mt76_connac_mcu.h
 +++ b/mt76_connac_mcu.h
-@@ -1204,7 +1204,7 @@ enum {
+@@ -1201,7 +1201,7 @@ enum {
  	/* for vendor csi and air monitor */
  	MCU_EXT_CMD_SMESH_CTRL = 0xae,
  	MCU_EXT_CMD_RX_STAT_USER_CTRL = 0xb3,
@@ -29,10 +29,10 @@
  	MCU_EXT_CMD_CSI_CTRL = 0xc2,
  	MCU_EXT_CMD_IPI_HIST_SCAN = 0xc5,
 diff --git a/mt7915/mcu.c b/mt7915/mcu.c
-index 3408555e..ebe00300 100644
+index 28b2a624..baf74440 100644
 --- a/mt7915/mcu.c
 +++ b/mt7915/mcu.c
-@@ -4322,37 +4322,33 @@ void mt7915_mcu_set_dynalgo(struct mt7915_phy *phy, u8 enable)
+@@ -4324,37 +4324,33 @@ void mt7915_mcu_set_dynalgo(struct mt7915_phy *phy, u8 enable)
  			&req, sizeof(req), false);
  }
  
@@ -94,7 +94,7 @@
  
  void mt7915_mcu_set_bypass_smthint(struct mt7915_phy *phy, u8 val)
 diff --git a/mt7915/mcu.h b/mt7915/mcu.h
-index c87fe8e8..16517099 100644
+index 7558726c..0aee6948 100644
 --- a/mt7915/mcu.h
 +++ b/mt7915/mcu.h
 @@ -847,6 +847,35 @@ struct mt7915_mcu_rdd_ipi_scan {
@@ -146,7 +146,7 @@
  void mt7915_vendor_register(struct mt7915_phy *phy);
  int mt7915_mcu_set_csi(struct mt7915_phy *phy, u8 mode,
 diff --git a/mt7915/vendor.c b/mt7915/vendor.c
-index 83f38e07..48d124e0 100644
+index 6915ac8d..b26b1cc6 100644
 --- a/mt7915/vendor.c
 +++ b/mt7915/vendor.c
 @@ -40,6 +40,11 @@ mu_ctrl_policy[NUM_MTK_VENDOR_ATTRS_MU_CTRL] = {
@@ -229,7 +229,7 @@
  };
  
 diff --git a/mt7915/vendor.h b/mt7915/vendor.h
-index c19ffe72..d96e5c23 100644
+index d8e23d34..de3cbe2c 100644
 --- a/mt7915/vendor.h
 +++ b/mt7915/vendor.h
 @@ -12,6 +12,7 @@ enum mtk_nl80211_vendor_subcmds {
diff --git a/recipes-wifi/linux-mt76/files/patches/1126-mt76-mt7915-add-ibf-control-vendor-cmd.patch b/recipes-wifi/linux-mt76/files/patches/1126-mt76-mt7915-add-ibf-control-vendor-cmd.patch
index 1fa6a9a..72672ac 100644
--- a/recipes-wifi/linux-mt76/files/patches/1126-mt76-mt7915-add-ibf-control-vendor-cmd.patch
+++ b/recipes-wifi/linux-mt76/files/patches/1126-mt76-mt7915-add-ibf-control-vendor-cmd.patch
@@ -1,7 +1,7 @@
-From 169a6fe9914e6480b9981f5cd6a3911e8700e46c Mon Sep 17 00:00:00 2001
+From 2557e2878455ac38e0458a34d8e9fa4c0fcabe7e Mon Sep 17 00:00:00 2001
 From: mtk27835 <shurong.wen@mediatek.com>
 Date: Wed, 7 Sep 2022 14:01:29 -0700
-Subject: [PATCH 1126/1133] mt76: mt7915: add ibf control vendor cmd
+Subject: [PATCH 1126/1132] mt76: mt7915: add ibf control vendor cmd
 
 Signed-off-by: mtk27835 <shurong.wen@mediatek.com>
 ---
@@ -10,7 +10,7 @@
  2 files changed, 89 insertions(+), 1 deletion(-)
 
 diff --git a/mt7915/vendor.c b/mt7915/vendor.c
-index 48d124e0..9cd6e811 100644
+index b26b1cc6..3e5c479e 100644
 --- a/mt7915/vendor.c
 +++ b/mt7915/vendor.c
 @@ -86,6 +86,11 @@ edcca_dump_policy[NUM_MTK_VENDOR_ATTRS_EDCCA_DUMP] = {
@@ -100,7 +100,7 @@
  };
  
 diff --git a/mt7915/vendor.h b/mt7915/vendor.h
-index d96e5c23..949c8853 100644
+index de3cbe2c..a6309a32 100644
 --- a/mt7915/vendor.h
 +++ b/mt7915/vendor.h
 @@ -12,7 +12,8 @@ enum mtk_nl80211_vendor_subcmds {
diff --git a/recipes-wifi/linux-mt76/files/patches/1127-mt76-mt7915-add-E3-re-bonding-for-low-yield-rate-iss.patch b/recipes-wifi/linux-mt76/files/patches/1127-mt76-mt7915-add-E3-re-bonding-for-low-yield-rate-iss.patch
index b06c540..1669e0c 100644
--- a/recipes-wifi/linux-mt76/files/patches/1127-mt76-mt7915-add-E3-re-bonding-for-low-yield-rate-iss.patch
+++ b/recipes-wifi/linux-mt76/files/patches/1127-mt76-mt7915-add-E3-re-bonding-for-low-yield-rate-iss.patch
@@ -1,7 +1,7 @@
-From 2cd8e8385970f43311305c6849b31cd86cc40f5a Mon Sep 17 00:00:00 2001
+From 8f2a166a0af3f1c6b1f77335685beb56b9d908f3 Mon Sep 17 00:00:00 2001
 From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
 Date: Thu, 13 Oct 2022 13:22:05 +0800
-Subject: [PATCH 1127/1133] mt76: mt7915: add E3 re-bonding for low yield rate
+Subject: [PATCH 1127/1132] mt76: mt7915: add E3 re-bonding for low yield rate
  issue
 
 Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
@@ -64,10 +64,10 @@
  	if (ret)
  		return ret;
 diff --git a/mt7915/mcu.c b/mt7915/mcu.c
-index ebe00300..292351fb 100644
+index baf74440..9d934748 100644
 --- a/mt7915/mcu.c
 +++ b/mt7915/mcu.c
-@@ -2886,7 +2886,7 @@ int mt7915_mcu_set_eeprom(struct mt7915_dev *dev, bool flash_mode)
+@@ -2888,7 +2888,7 @@ int mt7915_mcu_set_eeprom(struct mt7915_dev *dev, bool flash_mode)
  				 &req, sizeof(req), true);
  }
  
@@ -76,7 +76,7 @@
  {
  	struct mt7915_mcu_eeprom_info req = {
  		.addr = cpu_to_le32(round_down(offset,
-@@ -2904,8 +2904,15 @@ int mt7915_mcu_get_eeprom(struct mt7915_dev *dev, u32 offset)
+@@ -2906,8 +2906,15 @@ int mt7915_mcu_get_eeprom(struct mt7915_dev *dev, u32 offset)
  		return ret;
  
  	res = (struct mt7915_mcu_eeprom_info *)skb->data;
diff --git a/recipes-wifi/linux-mt76/files/patches/1128-mt76-mt7915-support-on-off-SW-ACI-through-debugfs.patch b/recipes-wifi/linux-mt76/files/patches/1128-mt76-mt7915-support-on-off-SW-ACI-through-debugfs.patch
index 3fc342b..998228b 100644
--- a/recipes-wifi/linux-mt76/files/patches/1128-mt76-mt7915-support-on-off-SW-ACI-through-debugfs.patch
+++ b/recipes-wifi/linux-mt76/files/patches/1128-mt76-mt7915-support-on-off-SW-ACI-through-debugfs.patch
@@ -1,7 +1,7 @@
-From 7cc147efe8e493d163b9670b8b737fd3bf8d59e0 Mon Sep 17 00:00:00 2001
+From 19ed70a278de504a58054906f9b25b4f5c3cf3d0 Mon Sep 17 00:00:00 2001
 From: Evelyn Tsai <evelyn.tsai@mediatek.com>
 Date: Fri, 14 Oct 2022 11:15:13 +0800
-Subject: [PATCH 1128/1133] mt76: mt7915: support on off SW ACI through debugfs
+Subject: [PATCH 1128/1132] mt76: mt7915: support on off SW ACI through debugfs
 
 Signed-off-by: Evelyn Tsai <evelyn.tsai@mediatek.com>
 Change-Id: I8a9c277c41d1ba76f9737d8af6f42e5e8f00ba64
@@ -11,10 +11,10 @@
  2 files changed, 22 insertions(+)
 
 diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
-index 41859dc3..73a5509a 100644
+index 1ff517f0..1a13cee0 100644
 --- a/mt76_connac_mcu.h
 +++ b/mt76_connac_mcu.h
-@@ -1206,6 +1206,7 @@ enum {
+@@ -1203,6 +1203,7 @@ enum {
  	MCU_EXT_CMD_RX_STAT_USER_CTRL = 0xb3,
  	MCU_EXT_CMD_SET_CFG = 0xb7,
  	MCU_EXT_CMD_EDCCA = 0xba,
@@ -23,7 +23,7 @@
  	MCU_EXT_CMD_IPI_HIST_SCAN = 0xc5,
  };
 diff --git a/mt7915/mtk_debugfs.c b/mt7915/mtk_debugfs.c
-index 5f34afc7..b99519dd 100644
+index 1f347efe..224d9960 100644
 --- a/mt7915/mtk_debugfs.c
 +++ b/mt7915/mtk_debugfs.c
 @@ -3040,6 +3040,25 @@ static int mt7915_show_eeprom_mode(struct seq_file *s, void *data)
diff --git a/recipes-wifi/linux-mt76/files/patches/1129-mt76-mt7915-add-bf-backoff-limit-table-support.patch b/recipes-wifi/linux-mt76/files/patches/1129-mt76-mt7915-add-bf-backoff-limit-table-support.patch
index c916131..213e390 100644
--- a/recipes-wifi/linux-mt76/files/patches/1129-mt76-mt7915-add-bf-backoff-limit-table-support.patch
+++ b/recipes-wifi/linux-mt76/files/patches/1129-mt76-mt7915-add-bf-backoff-limit-table-support.patch
@@ -1,7 +1,7 @@
-From cd6e64e5bdea2ee410c1cc8e83f78322bf9f3982 Mon Sep 17 00:00:00 2001
+From 82351f298ec49641998232fb648606996b3c5a37 Mon Sep 17 00:00:00 2001
 From: Shayne Chen <shayne.chen@mediatek.com>
 Date: Mon, 5 Dec 2022 18:21:51 +0800
-Subject: [PATCH 1129/1133] mt76: mt7915: add bf backoff limit table support
+Subject: [PATCH 1129/1132] mt76: mt7915: add bf backoff limit table support
 
 Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
 ---
@@ -57,10 +57,10 @@
  }
  EXPORT_SYMBOL_GPL(mt76_get_rate_power_limits);
 diff --git a/mt76.h b/mt76.h
-index 1638ef63..5e24d03c 100644
+index 675c12a4..dbb120cc 100644
 --- a/mt76.h
 +++ b/mt76.h
-@@ -912,6 +912,14 @@ struct mt76_power_limits {
+@@ -913,6 +913,14 @@ struct mt76_power_limits {
  	s8 ofdm[8];
  	s8 mcs[4][10];
  	s8 ru[7][12];
@@ -188,10 +188,10 @@
  				    mt7915_twt_stats);
  	debugfs_create_file("rf_regval", 0600, dir, dev, &fops_rf_regval);
 diff --git a/mt7915/mcu.c b/mt7915/mcu.c
-index 292351fb..ff309294 100644
+index 9d934748..5e74ed6e 100644
 --- a/mt7915/mcu.c
 +++ b/mt7915/mcu.c
-@@ -3331,7 +3331,8 @@ int mt7915_mcu_set_txpower_frame(struct mt7915_phy *phy,
+@@ -3333,7 +3333,8 @@ int mt7915_mcu_set_txpower_frame(struct mt7915_phy *phy,
  	int ret;
  	s8 txpower_sku[MT7915_SKU_RATE_NUM];
  
@@ -201,7 +201,7 @@
  	if (ret)
  		return ret;
  
-@@ -3373,51 +3374,98 @@ int mt7915_mcu_set_txpower_frame(struct mt7915_phy *phy,
+@@ -3375,51 +3376,98 @@ int mt7915_mcu_set_txpower_frame(struct mt7915_phy *phy,
  
  int mt7915_mcu_set_txpower_sku(struct mt7915_phy *phy)
  {
@@ -325,7 +325,7 @@
  	struct mt7915_dev *dev = phy->dev;
  	struct {
  		u8 format_id;
-@@ -3426,10 +3474,9 @@ int mt7915_mcu_get_txpower_sku(struct mt7915_phy *phy, s8 *txpower, int len)
+@@ -3428,10 +3476,9 @@ int mt7915_mcu_get_txpower_sku(struct mt7915_phy *phy, s8 *txpower, int len)
  		u8 _rsv;
  	} __packed req = {
  		.format_id = TX_POWER_LIMIT_INFO,
@@ -337,7 +337,7 @@
  	struct sk_buff *skb;
  	int ret, i;
  
-@@ -3439,9 +3486,15 @@ int mt7915_mcu_get_txpower_sku(struct mt7915_phy *phy, s8 *txpower, int len)
+@@ -3441,9 +3488,15 @@ int mt7915_mcu_get_txpower_sku(struct mt7915_phy *phy, s8 *txpower, int len)
  	if (ret)
  		return ret;
  
@@ -356,7 +356,7 @@
  
  	dev_kfree_skb(skb);
  
-@@ -3483,9 +3536,18 @@ int mt7915_mcu_set_sku_en(struct mt7915_phy *phy, bool enable)
+@@ -3485,9 +3538,18 @@ int mt7915_mcu_set_sku_en(struct mt7915_phy *phy, bool enable)
  		.band_idx = phy->mt76->band_idx,
  		.sku_enable = enable,
  	};
@@ -376,7 +376,7 @@
  				 MCU_EXT_CMD(TX_POWER_FEATURE_CTRL), &req,
  				 sizeof(req), true);
 diff --git a/mt7915/mcu.h b/mt7915/mcu.h
-index 16517099..e869a9f5 100644
+index 0aee6948..a07bb9ac 100644
 --- a/mt7915/mcu.h
 +++ b/mt7915/mcu.h
 @@ -447,12 +447,18 @@ enum {
diff --git a/recipes-wifi/linux-mt76/files/patches/1130-mt76-mt7915-amsdu-set-and-get-control.patch b/recipes-wifi/linux-mt76/files/patches/1130-mt76-mt7915-amsdu-set-and-get-control.patch
index 54ca9d2..be8c506 100644
--- a/recipes-wifi/linux-mt76/files/patches/1130-mt76-mt7915-amsdu-set-and-get-control.patch
+++ b/recipes-wifi/linux-mt76/files/patches/1130-mt76-mt7915-amsdu-set-and-get-control.patch
@@ -1,7 +1,7 @@
-From 3991eb6b59ffaf4f30815206fb451bc32e2e2af6 Mon Sep 17 00:00:00 2001
+From dc16e6198fe467ca6db8701ba98f5dbdfecc1211 Mon Sep 17 00:00:00 2001
 From: TomLiu <tomml.liu@mediatek.com>
 Date: Wed, 14 Dec 2022 00:44:07 -0800
-Subject: [PATCH 1130/1133] mt76: mt7915: amsdu set and get control
+Subject: [PATCH 1130/1132] mt76: mt7915: amsdu set and get control
 
 ---
  mt7915/mac.c    | 10 ++++++++++
@@ -44,7 +44,7 @@
  void mt7915_set_wireless_vif(void *data, u8 *mac, struct ieee80211_vif *vif);
  void mt7915_mcu_set_rfeature_starec(void *data, struct mt7915_dev *dev,
 diff --git a/mt7915/vendor.c b/mt7915/vendor.c
-index 9cd6e811..766fa595 100644
+index 3e5c479e..2e5f07c3 100644
 --- a/mt7915/vendor.c
 +++ b/mt7915/vendor.c
 @@ -30,10 +30,16 @@ wireless_ctrl_policy[NUM_MTK_VENDOR_ATTRS_WIRELESS_CTRL] = {
@@ -109,7 +109,7 @@
  		.maxattr = MTK_VENDOR_ATTR_WIRELESS_CTRL_MAX,
  	},
 diff --git a/mt7915/vendor.h b/mt7915/vendor.h
-index 949c8853..cbff910b 100644
+index a6309a32..33c75dc9 100644
 --- a/mt7915/vendor.h
 +++ b/mt7915/vendor.h
 @@ -74,6 +74,7 @@ enum mtk_vendor_attr_wireless_ctrl {
diff --git a/recipes-wifi/linux-mt76/files/patches/1131-wifi-mt76-mt7915-add-support-for-he-ldpc-control-fro.patch b/recipes-wifi/linux-mt76/files/patches/1131-wifi-mt76-mt7915-add-support-for-he-ldpc-control-fro.patch
index ef0375b..6da2c9f 100644
--- a/recipes-wifi/linux-mt76/files/patches/1131-wifi-mt76-mt7915-add-support-for-he-ldpc-control-fro.patch
+++ b/recipes-wifi/linux-mt76/files/patches/1131-wifi-mt76-mt7915-add-support-for-he-ldpc-control-fro.patch
@@ -1,7 +1,7 @@
-From 1fb0932ca2be712c94a8f57be5a7069541266201 Mon Sep 17 00:00:00 2001
+From 60271e19265ab37376b428decece440458156aa2 Mon Sep 17 00:00:00 2001
 From: MeiChia Chiu <meichia.chiu@mediatek.com>
 Date: Thu, 12 Jan 2023 15:15:42 +0800
-Subject: [PATCH 1131/1133] wifi: mt76: mt7915: add support for he ldpc control
+Subject: [PATCH 1131/1132] wifi: mt76: mt7915: add support for he ldpc control
  from hostapd
 
 ---
@@ -9,7 +9,7 @@
  1 file changed, 1 insertion(+)
 
 diff --git a/mt7915/mcu.c b/mt7915/mcu.c
-index ff309294..2cfad0a3 100644
+index 5e74ed6e..dffd1761 100644
 --- a/mt7915/mcu.c
 +++ b/mt7915/mcu.c
 @@ -1983,6 +1983,7 @@ mt7915_mcu_beacon_check_caps(struct mt7915_phy *phy, struct ieee80211_vif *vif,
diff --git a/recipes-wifi/linux-mt76/files/patches/1132-mt76-mt7915-Add-vendor-command-attribute-for-RTS-BW-.patch b/recipes-wifi/linux-mt76/files/patches/1132-mt76-mt7915-Add-vendor-command-attribute-for-RTS-BW-.patch
index 6a891bf..dea4ae5 100644
--- a/recipes-wifi/linux-mt76/files/patches/1132-mt76-mt7915-Add-vendor-command-attribute-for-RTS-BW-.patch
+++ b/recipes-wifi/linux-mt76/files/patches/1132-mt76-mt7915-Add-vendor-command-attribute-for-RTS-BW-.patch
@@ -1,7 +1,7 @@
-From 610518420411975d6d4cb88c722a8abf645c88f2 Mon Sep 17 00:00:00 2001
+From 81f9124f106441a6ac2f9c43efb9de9f5cc60cb4 Mon Sep 17 00:00:00 2001
 From: "himanshu.goyal" <himanshu.goyal@mediatek.com>
 Date: Tue, 24 Jan 2023 14:32:08 +0800
-Subject: [PATCH 1132/1133] mt76: mt7915: Add vendor command attribute for RTS
+Subject: [PATCH 1132/1132] mt76: mt7915: Add vendor command attribute for RTS
  BW signaling.
 
 Signed-off-by: himanshu.goyal <himanshu.goyal@mediatek.com>
@@ -13,10 +13,10 @@
  4 files changed, 20 insertions(+)
 
 diff --git a/mt7915/mcu.c b/mt7915/mcu.c
-index 2cfad0a3..4f1d2fe6 100644
+index dffd1761..e07197d0 100644
 --- a/mt7915/mcu.c
 +++ b/mt7915/mcu.c
-@@ -4408,6 +4408,12 @@ int mt7915_mcu_set_cfg(struct mt7915_phy *phy, u8 cfg_info, u8 type)
+@@ -4410,6 +4410,12 @@ int mt7915_mcu_set_cfg(struct mt7915_phy *phy, u8 cfg_info, u8 type)
  		req.cert.length = cpu_to_le16(tlv_len);
  		req.cert.cert_program = type;
  		break;
@@ -30,7 +30,7 @@
  		tlv_len = sizeof(struct three_wire_cfg);
  		req.three_wire.tag = cpu_to_le16(cfg_info);
 diff --git a/mt7915/mcu.h b/mt7915/mcu.h
-index e869a9f5..03ee600a 100644
+index a07bb9ac..8cbd37ca 100644
 --- a/mt7915/mcu.h
 +++ b/mt7915/mcu.h
 @@ -867,6 +867,13 @@ struct three_wire_cfg {
@@ -62,7 +62,7 @@
  };
  
 diff --git a/mt7915/vendor.c b/mt7915/vendor.c
-index 766fa595..7fbf67d6 100644
+index 2e5f07c3..3b7ac098 100644
 --- a/mt7915/vendor.c
 +++ b/mt7915/vendor.c
 @@ -33,6 +33,7 @@ wireless_ctrl_policy[NUM_MTK_VENDOR_ATTRS_WIRELESS_CTRL] = {
@@ -84,7 +84,7 @@
  
  	return 0;
 diff --git a/mt7915/vendor.h b/mt7915/vendor.h
-index cbff910b..41d6ff26 100644
+index 33c75dc9..6001ce4a 100644
 --- a/mt7915/vendor.h
 +++ b/mt7915/vendor.h
 @@ -76,6 +76,7 @@ enum mtk_vendor_attr_wireless_ctrl {
diff --git a/recipes-wifi/linux-mt76/files/patches/1133-mt76-mt7915-Allow-AP-to-change-channel-width-for-40M.patch b/recipes-wifi/linux-mt76/files/patches/1133-mt76-mt7915-Allow-AP-to-change-channel-width-for-40M.patch
deleted file mode 100644
index 5f558ea..0000000
--- a/recipes-wifi/linux-mt76/files/patches/1133-mt76-mt7915-Allow-AP-to-change-channel-width-for-40M.patch
+++ /dev/null
@@ -1,30 +0,0 @@
-From 48e04e1209ec16bdb258c13a2939ad48f29deec1 Mon Sep 17 00:00:00 2001
-From: "himanshu.goyal" <himanshu.goyal@mediatek.com>
-Date: Mon, 30 Jan 2023 17:47:06 +0800
-Subject: [PATCH 1133/1133] mt76: mt7915: Allow AP to change channel width for
- 40Mhz Intolerant STA
-
-Ref: WFA 11n Test Case: 4.2.41 AP 20/40 MHz Coexistence
-
-Signed-off-by: himanshu.goyal <himanshu.goyal@mediatek.com>
----
- mac80211.c | 3 ++-
- 1 file changed, 2 insertions(+), 1 deletion(-)
-
-diff --git a/mac80211.c b/mac80211.c
-index e79568d1..35fd0347 100644
---- a/mac80211.c
-+++ b/mac80211.c
-@@ -430,7 +430,8 @@ mt76_phy_init(struct mt76_phy *phy, struct ieee80211_hw *hw)
- 	SET_IEEE80211_DEV(hw, dev->dev);
- 	SET_IEEE80211_PERM_ADDR(hw, phy->macaddr);
- 
--	wiphy->features |= NL80211_FEATURE_ACTIVE_MONITOR;
-+	wiphy->features |= NL80211_FEATURE_ACTIVE_MONITOR |
-+			   NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE;
- 	wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH |
- 			WIPHY_FLAG_SUPPORTS_TDLS |
- 			WIPHY_FLAG_AP_UAPSD;
--- 
-2.18.0
-
diff --git a/recipes-wifi/linux-mt76/files/patches/1134-mt76-mt7915-add-vendor-cmd-to-get-available-color-bi.patch b/recipes-wifi/linux-mt76/files/patches/1134-mt76-mt7915-add-vendor-cmd-to-get-available-color-bi.patch
new file mode 100644
index 0000000..ec25241
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches/1134-mt76-mt7915-add-vendor-cmd-to-get-available-color-bi.patch
@@ -0,0 +1,106 @@
+From 1ecc90eee785504c9671985cabd6631ff1640f64 Mon Sep 17 00:00:00 2001
+From: Yi-Chia Hsieh <yi-chia.hsieh@mediatek.com>
+Date: Thu, 26 Jan 2023 08:50:47 +0800
+Subject: [PATCH] mt76: mt7915: add vendor cmd to get available color bitmap
+
+Add a vendor cmd to notify user space available color bitmap.
+The OBSS BSS color bitmap is maintained in mac80211, so mt76 will make use of that.
+
+Signed-off-by: Yi-Chia Hsieh <yi-chia.hsieh@mediatek.com>
+---
+ mt7915/vendor.c | 37 +++++++++++++++++++++++++++++++++++++
+ mt7915/vendor.h | 11 +++++++++++
+ 2 files changed, 48 insertions(+)
+
+diff --git a/mt7915/vendor.c b/mt7915/vendor.c
+index a1f526c..5cbe856 100644
+--- a/mt7915/vendor.c
++++ b/mt7915/vendor.c
+@@ -97,6 +97,11 @@ ibf_ctrl_policy[NUM_MTK_VENDOR_ATTRS_IBF_CTRL] = {
+ 	[MTK_VENDOR_ATTR_IBF_CTRL_ENABLE] = { .type = NLA_U8 },
+ };
+ 
++static struct nla_policy
++bss_color_ctrl_policy[NUM_MTK_VENDOR_ATTRS_BSS_COLOR_CTRL] = {
++	[MTK_VENDOR_ATTR_AVAL_BSS_COLOR_BMP] = { .type = NLA_U64 },
++};
++
+ struct csi_null_tone {
+ 	u8 start;
+ 	u8 end;
+@@ -1272,6 +1277,27 @@ mt7915_vendor_ibf_ctrl_dump(struct wiphy *wiphy, struct wireless_dev *wdev,
+ 	return 1;
+ }
+ 
++static int
++mt7915_vendor_bss_color_ctrl_dump(struct wiphy *wiphy, struct wireless_dev *wdev,
++			     struct sk_buff *skb, const void *data, int data_len,
++			     unsigned long *storage)
++{
++	struct ieee80211_vif *vif = wdev_to_ieee80211_vif(wdev);
++	struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
++	int len = 0;
++
++	if (*storage == 1)
++		return -ENOENT;
++	*storage = 1;
++
++	if (nla_put_u64_64bit(skb,
++	    MTK_VENDOR_ATTR_AVAL_BSS_COLOR_BMP,
++	    ~bss_conf->he_bss_color.used_color_bitmap, NL80211_ATTR_PAD))
++		return -ENOMEM;
++	len += 1;
++
++	return len;
++}
+ 
+ static const struct wiphy_vendor_command mt7915_vendor_commands[] = {
+ 	{
+@@ -1378,6 +1404,17 @@ static const struct wiphy_vendor_command mt7915_vendor_commands[] = {
+ 		.dumpit = mt7915_vendor_ibf_ctrl_dump,
+ 		.policy = ibf_ctrl_policy,
+ 		.maxattr = MTK_VENDOR_ATTR_IBF_CTRL_MAX,
++	},
++	{
++		.info = {
++			.vendor_id = MTK_NL80211_VENDOR_ID,
++			.subcmd = MTK_NL80211_VENDOR_SUBCMD_BSS_COLOR_CTRL,
++		},
++		.flags = WIPHY_VENDOR_CMD_NEED_NETDEV |
++			 WIPHY_VENDOR_CMD_NEED_RUNNING,
++		.dumpit = mt7915_vendor_bss_color_ctrl_dump,
++		.policy = bss_color_ctrl_policy,
++		.maxattr = MTK_VENDOR_ATTR_BSS_COLOR_CTRL_MAX,
+ 	}
+ };
+ 
+diff --git a/mt7915/vendor.h b/mt7915/vendor.h
+index cbff910..dda1447 100644
+--- a/mt7915/vendor.h
++++ b/mt7915/vendor.h
+@@ -14,6 +14,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,
+ };
+ 
+ 
+@@ -257,4 +258,14 @@ enum mtk_vendor_attr_ibf_dump {
+ 		NUM_MTK_VENDOR_ATTRS_IBF_DUMP - 1
+ };
+ 
++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
++};
+ #endif
+-- 
+2.39.0
+
diff --git a/recipes-wifi/linux-mt76/files/patches/3001-mt76-mt7915-wed-add-wed-tx-support.patch b/recipes-wifi/linux-mt76/files/patches/3001-mt76-mt7915-wed-add-wed-tx-support.patch
index 500ec0f..deab403 100644
--- a/recipes-wifi/linux-mt76/files/patches/3001-mt76-mt7915-wed-add-wed-tx-support.patch
+++ b/recipes-wifi/linux-mt76/files/patches/3001-mt76-mt7915-wed-add-wed-tx-support.patch
@@ -1,7 +1,7 @@
-From 783c715b2271209d23b965517d97e5a834fcfa76 Mon Sep 17 00:00:00 2001
+From af605bd8d821cc9cd9dd4f3928c4632113574dc4 Mon Sep 17 00:00:00 2001
 From: Sujuan Chen <sujuan.chen@mediatek.com>
 Date: Fri, 25 Nov 2022 10:38:53 +0800
-Subject: [PATCH 3001/3015] mt76: mt7915: wed: add wed tx support
+Subject: [PATCH 3001/3013] mt76: mt7915: wed: add wed tx support
 
 Signed-off-by: Sujuan Chen <sujuan.chen@mediatek.com>
 ---
@@ -86,7 +86,7 @@
  
  	ctx->dev = NULL;
 diff --git a/mt7915/mmio.c b/mt7915/mmio.c
-index 95ded131..6ebb969f 100644
+index 568b5feb..890af388 100644
 --- a/mt7915/mmio.c
 +++ b/mt7915/mmio.c
 @@ -13,7 +13,7 @@
diff --git a/recipes-wifi/linux-mt76/files/patches/3002-mt76-mt7915-wed-add-wds-support-when-wed-is-enabled.patch b/recipes-wifi/linux-mt76/files/patches/3002-mt76-mt7915-wed-add-wds-support-when-wed-is-enabled.patch
index 46fbf0c..46a68b5 100644
--- a/recipes-wifi/linux-mt76/files/patches/3002-mt76-mt7915-wed-add-wds-support-when-wed-is-enabled.patch
+++ b/recipes-wifi/linux-mt76/files/patches/3002-mt76-mt7915-wed-add-wds-support-when-wed-is-enabled.patch
@@ -1,21 +1,21 @@
-From 443b9ce1fa3d69fbfdbb6051c4ed46029556083d Mon Sep 17 00:00:00 2001
+From e7caf441138764cd701c00bf8c3bd6b7747ed323 Mon Sep 17 00:00:00 2001
 From: Sujuan Chen <sujuan.chen@mediatek.com>
 Date: Tue, 13 Dec 2022 17:51:26 +0800
-Subject: [PATCH 3002/3015] mt76: mt7915: wed: add wds support when wed is
+Subject: [PATCH 3002/3013] mt76: mt7915: wed: add wds support when wed is
  enabled
 
 Signed-off-by: Sujuan Chen <sujuan.chen@mediatek.com>
 ---
  mt76.h        |  6 ++++++
  mt7915/main.c | 22 ++++++++++++++++++++--
- mt7915/mcu.c  | 13 +++++++++++--
+ mt7915/mcu.c  | 16 ++++++++++++----
  mt7915/mcu.h  |  1 +
  util.c        | 40 +++++++++++++++++++++++++++++++++++++---
  util.h        |  7 ++++++-
- 6 files changed, 81 insertions(+), 8 deletions(-)
+ 6 files changed, 82 insertions(+), 10 deletions(-)
 
 diff --git a/mt76.h b/mt76.h
-index 5e24d03c..cb34391a 100644
+index dbb120cc..d8438953 100644
 --- a/mt76.h
 +++ b/mt76.h
 @@ -60,6 +60,12 @@ enum mt76_wed_type {
@@ -81,17 +81,20 @@
  	ctx->dev = NULL;
  
 diff --git a/mt7915/mcu.c b/mt7915/mcu.c
-index 4f1d2fe6..d046ce0f 100644
+index e07197d0..6b90f338 100644
 --- a/mt7915/mcu.c
 +++ b/mt7915/mcu.c
-@@ -2416,8 +2416,17 @@ int mt7915_mcu_init_firmware(struct mt7915_dev *dev)
+@@ -2416,10 +2416,18 @@ int mt7915_mcu_init_firmware(struct mt7915_dev *dev)
  	if (ret)
  		return ret;
  
--	if (mtk_wed_device_active(&dev->mt76.mmio.wed) && is_mt7915(&dev->mt76))
+-	if ((mtk_wed_device_active(&dev->mt76.mmio.wed) &&
+-	     is_mt7915(&dev->mt76)) ||
+-	    !mtk_wed_get_rx_capa(&dev->mt76.mmio.wed))
 -		mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(CAPABILITY), 0, 0, 0);
 +	if (mtk_wed_device_active(&dev->mt76.mmio.wed)) {
-+		if (is_mt7915(&dev->mt76))
++		if (is_mt7915(&dev->mt76) ||
++		    !mtk_wed_get_rx_capa(&dev->mt76.mmio.wed))
 +			ret = mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(CAPABILITY),
 +						0, 0, 0);
 +		else
@@ -105,7 +108,7 @@
  	ret = mt7915_mcu_set_mwds(dev, 1);
  	if (ret)
 diff --git a/mt7915/mcu.h b/mt7915/mcu.h
-index 03ee600a..24d0efd3 100644
+index 8cbd37ca..0f845075 100644
 --- a/mt7915/mcu.h
 +++ b/mt7915/mcu.h
 @@ -284,6 +284,7 @@ enum {
diff --git a/recipes-wifi/linux-mt76/files/patches/3003-mt76-mt7915-wed-add-fill-receive-path-to-report-wed-.patch b/recipes-wifi/linux-mt76/files/patches/3003-mt76-mt7915-wed-add-fill-receive-path-to-report-wed-.patch
index 528c44c..5d3affc 100644
--- a/recipes-wifi/linux-mt76/files/patches/3003-mt76-mt7915-wed-add-fill-receive-path-to-report-wed-.patch
+++ b/recipes-wifi/linux-mt76/files/patches/3003-mt76-mt7915-wed-add-fill-receive-path-to-report-wed-.patch
@@ -1,7 +1,7 @@
-From b52fb2adf7b44ed323983b10721612347b86b569 Mon Sep 17 00:00:00 2001
+From 3cdc91efeb0dcb344b79c832373a62c09c4ceee9 Mon Sep 17 00:00:00 2001
 From: Sujuan Chen <sujuan.chen@mediatek.com>
 Date: Thu, 19 May 2022 13:44:42 +0800
-Subject: [PATCH 3003/3015] mt76: mt7915: wed: add fill receive path to report
+Subject: [PATCH 3003/3013] mt76: mt7915: wed: add fill receive path to report
  wed idx
 
 Signed-off-by: Sujuan Chen <sujuan.chen@mediatek.com>
diff --git a/recipes-wifi/linux-mt76/files/patches/3004-mt76-mt7915-wed-find-rx-token-by-physical-address.patch b/recipes-wifi/linux-mt76/files/patches/3004-mt76-mt7915-wed-find-rx-token-by-physical-address.patch
index 21367e9..a958a8f 100644
--- a/recipes-wifi/linux-mt76/files/patches/3004-mt76-mt7915-wed-find-rx-token-by-physical-address.patch
+++ b/recipes-wifi/linux-mt76/files/patches/3004-mt76-mt7915-wed-find-rx-token-by-physical-address.patch
@@ -1,7 +1,7 @@
-From fc10309ea47b4d34ace30e6f4e7ff0c0ffa71db2 Mon Sep 17 00:00:00 2001
+From b454d9a320895e76b3211a3c176dbf3ab24c1a8a Mon Sep 17 00:00:00 2001
 From: Sujuan Chen <sujuan.chen@mediatek.com>
 Date: Fri, 25 Nov 2022 14:32:35 +0800
-Subject: [PATCH 3004/3015] mt76: mt7915: wed: find rx token by physical
+Subject: [PATCH 3004/3013] mt76: mt7915: wed: find rx token by physical
  address
 
 The token id in RxDMAD may be incorrect when it is not the last frame due to
@@ -9,21 +9,19 @@
 
 Signed-off-by: Peter Chiu <chui-hao.chiu@mediatek.com>
 ---
- dma.c | 27 ++++++++++++++++++++++++++-
- 1 file changed, 26 insertions(+), 1 deletion(-)
+ dma.c | 25 ++++++++++++++++++++++++-
+ 1 file changed, 24 insertions(+), 1 deletion(-)
 
 diff --git a/dma.c b/dma.c
-index a6bb3730..b58579c5 100644
+index fe65e0f3..14553b24 100644
 --- a/dma.c
 +++ b/dma.c
-@@ -402,10 +402,35 @@ mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx,
- 		*info = le32_to_cpu(desc->info);
+@@ -403,9 +403,32 @@ mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx,
  
  	if (mt76_queue_is_wed_rx(q)) {
-+		__le32 buf1;
+ 		u32 buf1 = le32_to_cpu(desc->buf1);
 +		u32 id, find = 0;
- 		u32 token = FIELD_GET(MT_DMA_CTL_TOKEN,
- 				      le32_to_cpu(desc->buf1));
+ 		u32 token = FIELD_GET(MT_DMA_CTL_TOKEN, buf1);
 -		struct mt76_txwi_cache *t = mt76_rx_token_release(dev, token);
 +		struct mt76_txwi_cache *t;
 +
@@ -36,10 +34,9 @@
 +					token = id;
 +
 +					/* Write correct id back to DMA*/
-+					buf1 = desc->buf1;
-+					buf1 = le32_replace_bits(buf1, id,
-+							MT_DMA_CTL_TOKEN);
-+					WRITE_ONCE(desc->buf1, buf1);
++					u32p_replace_bits(&buf1, id,
++							  MT_DMA_CTL_TOKEN);
++					WRITE_ONCE(desc->buf1, cpu_to_le32(buf1));
 +					break;
 +				}
 +			}
diff --git a/recipes-wifi/linux-mt76/files/patches/3006-mt76-mt7915-wed-HW-ATF-support-for-mt7986.patch b/recipes-wifi/linux-mt76/files/patches/3005-mt76-mt7915-wed-HW-ATF-support-for-mt7986.patch
similarity index 98%
rename from recipes-wifi/linux-mt76/files/patches/3006-mt76-mt7915-wed-HW-ATF-support-for-mt7986.patch
rename to recipes-wifi/linux-mt76/files/patches/3005-mt76-mt7915-wed-HW-ATF-support-for-mt7986.patch
index c22106c..c163906 100644
--- a/recipes-wifi/linux-mt76/files/patches/3006-mt76-mt7915-wed-HW-ATF-support-for-mt7986.patch
+++ b/recipes-wifi/linux-mt76/files/patches/3005-mt76-mt7915-wed-HW-ATF-support-for-mt7986.patch
@@ -1,7 +1,7 @@
-From b2b4b6a891b1c9e4232addc929a0dac8cd548a06 Mon Sep 17 00:00:00 2001
+From c040b9a6ac177c22283388bff0b7a8c72271b45c Mon Sep 17 00:00:00 2001
 From: Lian Chen <lian.chen@mediatek.com>
 Date: Mon, 7 Nov 2022 14:47:44 +0800
-Subject: [PATCH 3006/3010] mt76: mt7915: wed: HW ATF support for mt7986
+Subject: [PATCH 3005/3013] mt76: mt7915: wed: HW ATF support for mt7986
 
 Signed-off-by: Lian Chen <lian.chen@mediatek.com>
 ---
@@ -15,10 +15,10 @@
  7 files changed, 826 insertions(+), 1 deletion(-)
 
 diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
-index 73a5509a..130a8d25 100644
+index 1a13cee0..ad6f845b 100644
 --- a/mt76_connac_mcu.h
 +++ b/mt76_connac_mcu.h
-@@ -1164,6 +1164,7 @@ enum {
+@@ -1161,6 +1161,7 @@ enum {
  	MCU_EXT_CMD_THERMAL_CTRL = 0x2c,
  	MCU_EXT_CMD_WTBL_UPDATE = 0x32,
  	MCU_EXT_CMD_SET_DRR_CTRL = 0x36,
@@ -26,7 +26,7 @@
  	MCU_EXT_CMD_SET_RDD_CTRL = 0x3a,
  	MCU_EXT_CMD_ATE_CTRL = 0x3d,
  	MCU_EXT_CMD_PROTECT_CTRL = 0x3e,
-@@ -1173,6 +1174,7 @@ enum {
+@@ -1170,6 +1171,7 @@ enum {
  	MCU_EXT_CMD_MUAR_UPDATE = 0x48,
  	MCU_EXT_CMD_BCN_OFFLOAD = 0x49,
  	MCU_EXT_CMD_RX_AIRTIME_CTRL = 0x4a,
@@ -465,10 +465,10 @@
  	if (!dev->dbdc_support || phy->mt76->band_idx) {
  		debugfs_create_u32("dfs_hw_pattern", 0400, dir,
 diff --git a/mt7915/init.c b/mt7915/init.c
-index 19447ad1..92977b98 100644
+index f40d09c3..27395316 100644
 --- a/mt7915/init.c
 +++ b/mt7915/init.c
-@@ -559,10 +559,46 @@ mt7915_init_led_mux(struct mt7915_dev *dev)
+@@ -571,10 +571,46 @@ mt7915_init_led_mux(struct mt7915_dev *dev)
  	}
  }
  
@@ -515,7 +515,7 @@
  
  	/* config pse qid6 wfdma port selection */
  	if (!is_mt7915(&dev->mt76) && dev->hif2)
-@@ -584,6 +620,9 @@ void mt7915_mac_init(struct mt7915_dev *dev)
+@@ -596,6 +632,9 @@ void mt7915_mac_init(struct mt7915_dev *dev)
  		mt7915_mac_init_band(dev, i);
  
  	mt7915_init_led_mux(dev);
@@ -526,7 +526,7 @@
  
  int mt7915_txbf_init(struct mt7915_dev *dev)
 diff --git a/mt7915/main.c b/mt7915/main.c
-index 9a5dac91..a9980e70 100644
+index 7d25a93f..c549a183 100644
 --- a/mt7915/main.c
 +++ b/mt7915/main.c
 @@ -209,6 +209,7 @@ int mt7915_init_vif(struct mt7915_phy *phy, struct ieee80211_vif *vif, bool bf_e
@@ -573,10 +573,10 @@
  }
  
 diff --git a/mt7915/mcu.c b/mt7915/mcu.c
-index 64789b80..e3b7d824 100644
+index 6b90f338..da10895c 100644
 --- a/mt7915/mcu.c
 +++ b/mt7915/mcu.c
-@@ -3580,6 +3580,171 @@ int mt7915_mcu_set_ser(struct mt7915_dev *dev, u8 action, u8 set, u8 band)
+@@ -3581,6 +3581,171 @@ int mt7915_mcu_set_ser(struct mt7915_dev *dev, u8 action, u8 set, u8 band)
  				 &req, sizeof(req), false);
  }
  
@@ -749,7 +749,7 @@
  {
  #define MT_BF_PROCESSING	4
 diff --git a/mt7915/mt7915.h b/mt7915/mt7915.h
-index eb24b45f..a1ef8359 100644
+index c14d13ae..0fbc1047 100644
 --- a/mt7915/mt7915.h
 +++ b/mt7915/mt7915.h
 @@ -127,6 +127,58 @@ struct mt7915_twt_flow {
@@ -856,7 +856,7 @@
  int mt7915_mcu_set_txpower_sku(struct mt7915_phy *phy);
  int mt7915_mcu_get_txpower_sku(struct mt7915_phy *phy, s8 *txpower, int len,
 diff --git a/mt7915/mtk_debugfs.c b/mt7915/mtk_debugfs.c
-index 576995dc..5e64fe91 100644
+index 224d9960..2dc4cb87 100644
 --- a/mt7915/mtk_debugfs.c
 +++ b/mt7915/mtk_debugfs.c
 @@ -1368,7 +1368,6 @@ static EMPTY_QUEUE_INFO_T ple_txcmd_queue_empty_info[] = {
diff --git a/recipes-wifi/linux-mt76/files/patches/3005-mt76-mt7915-wed-drop-scatter-and-gather-frame.patch b/recipes-wifi/linux-mt76/files/patches/3005-mt76-mt7915-wed-drop-scatter-and-gather-frame.patch
deleted file mode 100644
index 4f5d2c6..0000000
--- a/recipes-wifi/linux-mt76/files/patches/3005-mt76-mt7915-wed-drop-scatter-and-gather-frame.patch
+++ /dev/null
@@ -1,62 +0,0 @@
-From d99756a5e6b4b3d1d520aba763fddeadff53a529 Mon Sep 17 00:00:00 2001
-From: Peter Chiu <chui-hao.chiu@mediatek.com>
-Date: Fri, 25 Nov 2022 14:37:58 +0800
-Subject: [PATCH 3005/3015] mt76: mt7915: wed: drop scatter and gather frame
-
-The scatter and gather frame may be incorrect because WED and WO may
-send frames to host driver interleaved.
-
-Signed-off-by: Peter Chiu <chui-hao.chiu@mediatek.com>
----
- dma.c  | 9 +++++++++
- dma.h  | 1 +
- mt76.h | 1 +
- 3 files changed, 11 insertions(+)
-
-diff --git a/dma.c b/dma.c
-index b58579c5..86b0bf84 100644
---- a/dma.c
-+++ b/dma.c
-@@ -449,6 +449,15 @@ mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx,
- 
- 			*drop = !!(ctrl & (MT_DMA_CTL_TO_HOST_A |
- 					   MT_DMA_CTL_DROP));
-+
-+			if (*more || (q->flags & MT_QFLAG_WED_FRAG)) {
-+				*drop = true;
-+
-+				if (!(*more) && FIELD_GET(MT_DMA_CTL_WO, desc->buf1))
-+					q->flags &= ~MT_QFLAG_WED_FRAG;
-+				else
-+					q->flags |= MT_QFLAG_WED_FRAG;
-+			}
- 		}
- 	} else {
- 		buf = e->buf;
-diff --git a/dma.h b/dma.h
-index 4b9bc7f4..ce8ac426 100644
---- a/dma.h
-+++ b/dma.h
-@@ -19,6 +19,7 @@
- #define MT_DMA_CTL_TO_HOST_A		BIT(12)
- #define MT_DMA_CTL_DROP			BIT(14)
- #define MT_DMA_CTL_TOKEN		GENMASK(31, 16)
-+#define MT_DMA_CTL_WO			BIT(8)
- 
- #define MT_DMA_PPE_CPU_REASON		GENMASK(15, 11)
- #define MT_DMA_PPE_ENTRY		GENMASK(30, 16)
-diff --git a/mt76.h b/mt76.h
-index cb34391a..982d0bbf 100644
---- a/mt76.h
-+++ b/mt76.h
-@@ -30,6 +30,7 @@
- #define MT_QFLAG_WED_RING	GENMASK(1, 0)
- #define MT_QFLAG_WED_TYPE	GENMASK(3, 2)
- #define MT_QFLAG_WED		BIT(4)
-+#define MT_QFLAG_WED_FRAG	BIT(5)
- 
- #define __MT_WED_Q(_type, _n)	(MT_QFLAG_WED | \
- 				 FIELD_PREP(MT_QFLAG_WED_TYPE, _type) | \
--- 
-2.18.0
-
diff --git a/recipes-wifi/linux-mt76/files/patches/3008-mt76-mt7915-wed-add-rxwi-for-further-in-chip-rro.patch b/recipes-wifi/linux-mt76/files/patches/3006-mt76-mt7915-wed-add-rxwi-for-further-in-chip-rro.patch
similarity index 93%
rename from recipes-wifi/linux-mt76/files/patches/3008-mt76-mt7915-wed-add-rxwi-for-further-in-chip-rro.patch
rename to recipes-wifi/linux-mt76/files/patches/3006-mt76-mt7915-wed-add-rxwi-for-further-in-chip-rro.patch
index 78e257d..4e22353 100644
--- a/recipes-wifi/linux-mt76/files/patches/3008-mt76-mt7915-wed-add-rxwi-for-further-in-chip-rro.patch
+++ b/recipes-wifi/linux-mt76/files/patches/3006-mt76-mt7915-wed-add-rxwi-for-further-in-chip-rro.patch
@@ -1,7 +1,7 @@
-From 8d7faa4d207c13487196d09de0c1c452703f1b84 Mon Sep 17 00:00:00 2001
+From 72dda83ffb5d48393da817757f537770aeca4e40 Mon Sep 17 00:00:00 2001
 From: Sujuan Chen <sujuan.chen@mediatek.com>
 Date: Fri, 6 Jan 2023 18:18:50 +0800
-Subject: [PATCH 3008/3015] mt76: mt7915: wed: add rxwi for further in chip rro
+Subject: [PATCH 3006/3013] mt76: mt7915: wed: add rxwi for further in chip rro
 
 Signed-off-by: Sujuan Chen <sujuan.chen@mediatek.com>
 ---
@@ -15,7 +15,7 @@
  7 files changed, 86 insertions(+), 79 deletions(-)
 
 diff --git a/dma.c b/dma.c
-index 86b0bf84..76af6506 100644
+index 14553b24..d1a1dae4 100644
 --- a/dma.c
 +++ b/dma.c
 @@ -59,17 +59,17 @@ mt76_alloc_txwi(struct mt76_dev *dev)
@@ -180,10 +180,10 @@
  	q->entry[idx].skb = skb;
  	q->entry[idx].wcid = 0xffff;
  
-@@ -406,13 +407,13 @@ mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx,
+@@ -405,13 +406,13 @@ mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx,
+ 		u32 buf1 = le32_to_cpu(desc->buf1);
  		u32 id, find = 0;
- 		u32 token = FIELD_GET(MT_DMA_CTL_TOKEN,
- 				      le32_to_cpu(desc->buf1));
+ 		u32 token = FIELD_GET(MT_DMA_CTL_TOKEN, buf1);
 -		struct mt76_txwi_cache *t;
 +		struct mt76_rxwi_cache *r;
  
@@ -197,7 +197,7 @@
  					find = 1;
  					token = id;
  
-@@ -430,19 +431,19 @@ mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx,
+@@ -428,19 +429,19 @@ mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx,
  				return NULL;
  		}
  
@@ -224,7 +224,7 @@
  
  		if (drop) {
  			u32 ctrl = le32_to_cpu(READ_ONCE(desc->ctrl));
-@@ -510,7 +511,7 @@ mt76_dma_tx_queue_skb_raw(struct mt76_dev *dev, struct mt76_queue *q,
+@@ -501,7 +502,7 @@ mt76_dma_tx_queue_skb_raw(struct mt76_dev *dev, struct mt76_queue *q,
  	buf.len = skb->len;
  
  	spin_lock_bh(&q->lock);
@@ -233,7 +233,7 @@
  	mt76_dma_kick_queue(dev, q);
  	spin_unlock_bh(&q->lock);
  
-@@ -587,7 +588,7 @@ mt76_dma_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q,
+@@ -578,7 +579,7 @@ mt76_dma_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q,
  		goto unmap;
  
  	return mt76_dma_add_buf(dev, q, tx_info.buf, tx_info.nbuf,
@@ -243,10 +243,10 @@
  unmap:
  	for (n--; n > 0; n--)
 diff --git a/mac80211.c b/mac80211.c
-index 35fd0347..95861d47 100644
+index e2122c78..4655f814 100644
 --- a/mac80211.c
 +++ b/mac80211.c
-@@ -640,7 +640,6 @@ mt76_alloc_device(struct device *pdev, unsigned int size,
+@@ -644,7 +644,6 @@ mt76_alloc_device(struct device *pdev, unsigned int size,
  	spin_lock_init(&dev->lock);
  	spin_lock_init(&dev->cc_lock);
  	spin_lock_init(&dev->status_lock);
@@ -254,7 +254,7 @@
  	mutex_init(&dev->mutex);
  	init_waitqueue_head(&dev->tx_wait);
  
-@@ -671,6 +670,7 @@ mt76_alloc_device(struct device *pdev, unsigned int size,
+@@ -675,6 +674,7 @@ mt76_alloc_device(struct device *pdev, unsigned int size,
  	INIT_LIST_HEAD(&dev->txwi_cache);
  	INIT_LIST_HEAD(&dev->rxwi_cache);
  	dev->token_size = dev->drv->token_size;
@@ -263,10 +263,10 @@
  	for (i = 0; i < ARRAY_SIZE(dev->q_rx); i++)
  		skb_queue_head_init(&dev->rx_skb[i]);
 diff --git a/mt76.h b/mt76.h
-index 982d0bbf..a36a978b 100644
+index d8438953..7919cda8 100644
 --- a/mt76.h
 +++ b/mt76.h
-@@ -166,6 +166,7 @@ struct mt76_queue_entry {
+@@ -165,6 +165,7 @@ struct mt76_queue_entry {
  	};
  	union {
  		struct mt76_txwi_cache *txwi;
@@ -274,7 +274,7 @@
  		struct urb *urb;
  		int buf_sz;
  	};
-@@ -357,10 +358,15 @@ struct mt76_txwi_cache {
+@@ -356,10 +357,15 @@ struct mt76_txwi_cache {
  	struct list_head list;
  	dma_addr_t dma_addr;
  
@@ -334,10 +334,10 @@
  static inline void mt76_put_page_pool_buf(void *buf, bool allow_direct)
  {
 diff --git a/mt7915/dma.c b/mt7915/dma.c
-index 52fabde0..4dd321ee 100644
+index 43a5456d..6d9b2d15 100644
 --- a/mt7915/dma.c
 +++ b/mt7915/dma.c
-@@ -491,7 +491,6 @@ int mt7915_dma_init(struct mt7915_dev *dev, struct mt7915_phy *phy2)
+@@ -493,7 +493,6 @@ int mt7915_dma_init(struct mt7915_dev *dev, struct mt7915_phy *phy2)
  		    mtk_wed_get_rx_capa(&mdev->mmio.wed)) {
  			dev->mt76.q_rx[MT_RXQ_MAIN].flags =
  				MT_WED_Q_RX(MT7915_RXQ_BAND0);
@@ -345,7 +345,7 @@
  		}
  
  		ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MAIN],
-@@ -528,7 +527,6 @@ int mt7915_dma_init(struct mt7915_dev *dev, struct mt7915_phy *phy2)
+@@ -530,7 +529,6 @@ int mt7915_dma_init(struct mt7915_dev *dev, struct mt7915_phy *phy2)
  		    mtk_wed_get_rx_capa(&mdev->mmio.wed)) {
  			dev->mt76.q_rx[MT_RXQ_BAND1].flags =
  				MT_WED_Q_RX(MT7915_RXQ_BAND1);
diff --git a/recipes-wifi/linux-mt76/files/patches/3009-mt76-mt7915-add-mt7915_net_setup_tc-to-support-wifi2.patch b/recipes-wifi/linux-mt76/files/patches/3007-mt76-mt7915-add-mt7915_net_setup_tc-to-support-wifi2.patch
similarity index 90%
rename from recipes-wifi/linux-mt76/files/patches/3009-mt76-mt7915-add-mt7915_net_setup_tc-to-support-wifi2.patch
rename to recipes-wifi/linux-mt76/files/patches/3007-mt76-mt7915-add-mt7915_net_setup_tc-to-support-wifi2.patch
index d5bbee7..bce65e6 100644
--- a/recipes-wifi/linux-mt76/files/patches/3009-mt76-mt7915-add-mt7915_net_setup_tc-to-support-wifi2.patch
+++ b/recipes-wifi/linux-mt76/files/patches/3007-mt76-mt7915-add-mt7915_net_setup_tc-to-support-wifi2.patch
@@ -1,7 +1,7 @@
-From b3a12a2a257355951c1f1a5902eb793a982bc23c Mon Sep 17 00:00:00 2001
+From 38e99f5b8641c3b1c054244d3c74229a9c0a470e Mon Sep 17 00:00:00 2001
 From: Sujuan Chen <sujuan.chen@mediatek.com>
 Date: Tue, 27 Dec 2022 09:45:14 +0800
-Subject: [PATCH 3009/3015] mt76: mt7915: add mt7915_net_setup_tc to support
+Subject: [PATCH 3007/3013] mt76: mt7915: add mt7915_net_setup_tc to support
  wifi2wifi offload
 
 Signed-off-by: Sujuan Chen <sujuan.chen@mediatek.com>
diff --git a/recipes-wifi/linux-mt76/files/patches/3007-mt76-mt7915-wed-add-mt7916-2-pcie-support-when-wed-o.patch b/recipes-wifi/linux-mt76/files/patches/3007-mt76-mt7915-wed-add-mt7916-2-pcie-support-when-wed-o.patch
deleted file mode 100644
index 4917bae..0000000
--- a/recipes-wifi/linux-mt76/files/patches/3007-mt76-mt7915-wed-add-mt7916-2-pcie-support-when-wed-o.patch
+++ /dev/null
@@ -1,75 +0,0 @@
-From 76a6c0fd812fa4682abca05d94594f063808d815 Mon Sep 17 00:00:00 2001
-From: Sujuan Chen <sujuan.chen@mediatek.com>
-Date: Fri, 2 Dec 2022 17:17:06 +0800
-Subject: [PATCH 3007/3015] mt76: mt7915: wed: add mt7916 2 pcie support when
- wed on
-
-It should use bit 23 in interrupt mask for wfdma band1 data
-for 2 pcie mt7916, and use bit 19 for  band1 data for 1 pcie.
-
-Signed-off-by: Sujuan Chen <sujuan.chen@mediatek.com>
----
- mt7915/dma.c  |  8 ++++++--
- mt7915/mcu.c  |  3 ++-
- mt7915/mmio.c | 10 +++++-----
- 3 files changed, 13 insertions(+), 8 deletions(-)
-
-diff --git a/mt7915/dma.c b/mt7915/dma.c
-index abe17dac..52fabde0 100644
---- a/mt7915/dma.c
-+++ b/mt7915/dma.c
-@@ -87,8 +87,12 @@ static void mt7915_dma_config(struct mt7915_dev *dev)
- 				   MT7916_RXQ_BAND0);
- 			RXQ_CONFIG(MT_RXQ_MCU_WA, WFDMA0, MT_INT_WED_RX_DONE_WA_MT7916,
- 				   MT7916_RXQ_MCU_WA);
--			RXQ_CONFIG(MT_RXQ_BAND1, WFDMA0, MT_INT_WED_RX_DONE_BAND1_MT7916,
--				   MT7916_RXQ_BAND1);
-+			if (dev->hif2)
-+				RXQ_CONFIG(MT_RXQ_BAND1, WFDMA0, MT_INT_RX_DONE_BAND1_MT7916,
-+					   MT7916_RXQ_BAND1);
-+			else
-+				RXQ_CONFIG(MT_RXQ_BAND1, WFDMA0, MT_INT_WED_RX_DONE_BAND1_MT7916,
-+					   MT7916_RXQ_BAND1);
- 			RXQ_CONFIG(MT_RXQ_MAIN_WA, WFDMA0, MT_INT_WED_RX_DONE_WA_MAIN_MT7916,
- 				   MT7916_RXQ_MCU_WA_MAIN);
- 			TXQ_CONFIG(0, WFDMA0, MT_INT_WED_TX_DONE_BAND0,
-diff --git a/mt7915/mcu.c b/mt7915/mcu.c
-index 134dc5cb..7301ec1d 100644
---- a/mt7915/mcu.c
-+++ b/mt7915/mcu.c
-@@ -2417,7 +2417,8 @@ int mt7915_mcu_init_firmware(struct mt7915_dev *dev)
- 		return ret;
- 
- 	if (mtk_wed_device_active(&dev->mt76.mmio.wed)) {
--		if (is_mt7915(&dev->mt76))
-+		if (is_mt7915(&dev->mt76) ||
-+		    !mtk_wed_get_rx_capa(&dev->mt76.mmio.wed))
- 			ret = mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(CAPABILITY),
- 						0, 0, 0);
- 		else
-diff --git a/mt7915/mmio.c b/mt7915/mmio.c
-index 6ebb969f..890af388 100644
---- a/mt7915/mmio.c
-+++ b/mt7915/mmio.c
-@@ -996,13 +996,13 @@ irqreturn_t mt7915_irq_handler(int irq, void *dev_instance)
- 	struct mt7915_dev *dev = dev_instance;
- 	struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
- 
--	if (mtk_wed_device_active(wed)) {
-+	if (mtk_wed_device_active(wed))
- 		mtk_wed_device_irq_set_mask(wed, 0);
--	} else {
-+	else
- 		mt76_wr(dev, MT_INT_MASK_CSR, 0);
--		if (dev->hif2)
--			mt76_wr(dev, MT_INT1_MASK_CSR, 0);
--	}
-+
-+	if (dev->hif2)
-+		mt76_wr(dev, MT_INT1_MASK_CSR, 0);
- 
- 	if (!test_bit(MT76_STATE_INITIALIZED, &dev->mphy.state))
- 		return IRQ_NONE;
--- 
-2.18.0
-
diff --git a/recipes-wifi/linux-mt76/files/patches/3010-wifi-mt76-mt7915-add-wa-command-to-get-tx-msdu-count.patch b/recipes-wifi/linux-mt76/files/patches/3008-wifi-mt76-mt7915-add-wa-command-to-get-tx-msdu-count.patch
similarity index 94%
rename from recipes-wifi/linux-mt76/files/patches/3010-wifi-mt76-mt7915-add-wa-command-to-get-tx-msdu-count.patch
rename to recipes-wifi/linux-mt76/files/patches/3008-wifi-mt76-mt7915-add-wa-command-to-get-tx-msdu-count.patch
index 85d97b1..9f30456 100644
--- a/recipes-wifi/linux-mt76/files/patches/3010-wifi-mt76-mt7915-add-wa-command-to-get-tx-msdu-count.patch
+++ b/recipes-wifi/linux-mt76/files/patches/3008-wifi-mt76-mt7915-add-wa-command-to-get-tx-msdu-count.patch
@@ -1,7 +1,7 @@
-From dbd25fa4a361f77c713e2f95e11c3806c490877e Mon Sep 17 00:00:00 2001
+From 101ab7022c500ad4adacb5faf90bef25d897c70a Mon Sep 17 00:00:00 2001
 From: Peter Chiu <chui-hao.chiu@mediatek.com>
 Date: Wed, 18 Jan 2023 16:37:22 +0800
-Subject: [PATCH 3010/3015] wifi: mt76: mt7915: add wa command to get tx msdu
+Subject: [PATCH 3008/3013] wifi: mt76: mt7915: add wa command to get tx msdu
  count
 
 ---
@@ -16,10 +16,10 @@
  8 files changed, 78 insertions(+), 11 deletions(-)
 
 diff --git a/mt76.h b/mt76.h
-index a36a978b..0d1f3cbf 100644
+index 7919cda8..08945d66 100644
 --- a/mt76.h
 +++ b/mt76.h
-@@ -285,7 +285,7 @@ struct mt76_sta_stats {
+@@ -284,7 +284,7 @@ struct mt76_sta_stats {
  	u64 tx_mcs[16];		/* mcs idx */
  	u64 tx_bytes;
  	/* WED TX */
@@ -41,7 +41,7 @@
  
  /* RXD DW1 */
 diff --git a/mt76_connac_mac.c b/mt76_connac_mac.c
-index aed4ee95..2643f5aa 100644
+index 8d316d3a..1816bcbc 100644
 --- a/mt76_connac_mac.c
 +++ b/mt76_connac_mac.c
 @@ -491,7 +491,9 @@ void mt76_connac2_mac_write_txwi(struct mt76_dev *dev, __le32 *txwi,
@@ -68,10 +68,10 @@
  			le32_get_bits(txs_data[6], MT_TXS6_MPDU_FAIL_CNT);
  		stats->tx_retries +=
 diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
-index 130a8d25..34df625a 100644
+index ad6f845b..7afd9d09 100644
 --- a/mt76_connac_mcu.h
 +++ b/mt76_connac_mcu.h
-@@ -1003,6 +1003,7 @@ enum {
+@@ -1000,6 +1000,7 @@ enum {
  	MCU_EXT_EVENT_BF_STATUS_READ = 0x35,
  	MCU_EXT_EVENT_RDD_REPORT = 0x3a,
  	MCU_EXT_EVENT_CSA_NOTIFY = 0x4f,
@@ -106,7 +106,7 @@
  	sinfo->filled |= BIT_ULL(NL80211_STA_INFO_ACK_SIGNAL);
  
 diff --git a/mt7915/mcu.c b/mt7915/mcu.c
-index 7301ec1d..3e0c3ab1 100644
+index da10895c..076480ba 100644
 --- a/mt7915/mcu.c
 +++ b/mt7915/mcu.c
 @@ -168,7 +168,9 @@ mt7915_mcu_parse_response(struct mt76_dev *mdev, int cmd,
@@ -192,7 +192,7 @@
  				struct cfg80211_he_bss_color *he_bss_color)
  {
 diff --git a/mt7915/mcu.h b/mt7915/mcu.h
-index 24d0efd3..5f6c7c80 100644
+index 0f845075..d761fa59 100644
 --- a/mt7915/mcu.h
 +++ b/mt7915/mcu.h
 @@ -292,6 +292,17 @@ enum {
diff --git a/recipes-wifi/linux-mt76/files/patches/3011-wifi-mt76-get-tx-count-and-tx-failed-from-mcu-comman.patch b/recipes-wifi/linux-mt76/files/patches/3009-wifi-mt76-get-tx-count-and-tx-failed-from-mcu-comman.patch
similarity index 94%
rename from recipes-wifi/linux-mt76/files/patches/3011-wifi-mt76-get-tx-count-and-tx-failed-from-mcu-comman.patch
rename to recipes-wifi/linux-mt76/files/patches/3009-wifi-mt76-get-tx-count-and-tx-failed-from-mcu-comman.patch
index 617ee6c..f1d5c88 100644
--- a/recipes-wifi/linux-mt76/files/patches/3011-wifi-mt76-get-tx-count-and-tx-failed-from-mcu-comman.patch
+++ b/recipes-wifi/linux-mt76/files/patches/3009-wifi-mt76-get-tx-count-and-tx-failed-from-mcu-comman.patch
@@ -1,7 +1,7 @@
-From 2a8cadb17c7c31806a41c5af0e97d76aed47fd94 Mon Sep 17 00:00:00 2001
+From 8fa8a22a16c04d8f18e27af2c02b960f0c02c91b Mon Sep 17 00:00:00 2001
 From: Peter Chiu <chui-hao.chiu@mediatek.com>
 Date: Wed, 11 Jan 2023 10:56:27 +0800
-Subject: [PATCH 3011/3015] wifi: mt76: get tx count and tx failed from mcu
+Subject: [PATCH 3009/3013] wifi: mt76: get tx count and tx failed from mcu
  command
 
 ---
@@ -15,10 +15,10 @@
  7 files changed, 138 insertions(+), 5 deletions(-)
 
 diff --git a/mt76.h b/mt76.h
-index 0d1f3cbf..22c6531a 100644
+index 08945d66..bc0c9ae7 100644
 --- a/mt76.h
 +++ b/mt76.h
-@@ -286,6 +286,7 @@ struct mt76_sta_stats {
+@@ -285,6 +285,7 @@ struct mt76_sta_stats {
  	u64 tx_bytes;
  	/* WED TX */
  	u32 tx_packets;		/* unit: MSDU */
@@ -27,7 +27,7 @@
  	u32 tx_failed;
  	/* WED RX */
 diff --git a/mt76_connac_mac.c b/mt76_connac_mac.c
-index 2643f5aa..05ba5f26 100644
+index 1816bcbc..abcb9a27 100644
 --- a/mt76_connac_mac.c
 +++ b/mt76_connac_mac.c
 @@ -579,8 +579,6 @@ bool mt76_connac2_mac_fill_txs(struct mt76_dev *dev, struct mt76_wcid *wcid,
@@ -38,12 +38,12 @@
 -			le32_get_bits(txs_data[6], MT_TXS6_MPDU_FAIL_CNT);
  		stats->tx_retries +=
  			le32_get_bits(txs_data[7], MT_TXS7_MPDU_RETRY_CNT);
- 	}
+ 
 diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
-index 34df625a..747ae7e9 100644
+index 7afd9d09..287cffcc 100644
 --- a/mt76_connac_mcu.h
 +++ b/mt76_connac_mcu.h
-@@ -1163,6 +1163,7 @@ enum {
+@@ -1160,6 +1160,7 @@ enum {
  	MCU_EXT_CMD_EDCA_UPDATE = 0x27,
  	MCU_EXT_CMD_DEV_INFO_UPDATE = 0x2A,
  	MCU_EXT_CMD_THERMAL_CTRL = 0x2c,
@@ -78,7 +78,7 @@
  	sinfo->filled |= BIT_ULL(NL80211_STA_INFO_ACK_SIGNAL);
  
 diff --git a/mt7915/mcu.c b/mt7915/mcu.c
-index 3e0c3ab1..16a82e92 100644
+index 076480ba..e1c08178 100644
 --- a/mt7915/mcu.c
 +++ b/mt7915/mcu.c
 @@ -4137,6 +4137,114 @@ out:
@@ -197,7 +197,7 @@
  				struct cfg80211_he_bss_color *he_bss_color)
  {
 diff --git a/mt7915/mcu.h b/mt7915/mcu.h
-index 5f6c7c80..7b611fb7 100644
+index d761fa59..41d5ea19 100644
 --- a/mt7915/mcu.h
 +++ b/mt7915/mcu.h
 @@ -1018,6 +1018,28 @@ struct mt7915_muru {
diff --git a/recipes-wifi/linux-mt76/files/patches/3012-wifi-mt76-mt7915-enable-PPDU-TxS-to-host-when-wed-en.patch b/recipes-wifi/linux-mt76/files/patches/3010-wifi-mt76-mt7915-enable-PPDU-TxS-to-host-when-wed-en.patch
similarity index 93%
rename from recipes-wifi/linux-mt76/files/patches/3012-wifi-mt76-mt7915-enable-PPDU-TxS-to-host-when-wed-en.patch
rename to recipes-wifi/linux-mt76/files/patches/3010-wifi-mt76-mt7915-enable-PPDU-TxS-to-host-when-wed-en.patch
index 4dcba32..d7af854 100644
--- a/recipes-wifi/linux-mt76/files/patches/3012-wifi-mt76-mt7915-enable-PPDU-TxS-to-host-when-wed-en.patch
+++ b/recipes-wifi/linux-mt76/files/patches/3010-wifi-mt76-mt7915-enable-PPDU-TxS-to-host-when-wed-en.patch
@@ -1,7 +1,7 @@
-From 3c70695fbf551ae8eaf90fa92f08ab45199f69e4 Mon Sep 17 00:00:00 2001
+From 5c346af2c8a9352b9303d1e7f9e6f424417dfc98 Mon Sep 17 00:00:00 2001
 From: Peter Chiu <chui-hao.chiu@mediatek.com>
 Date: Wed, 18 Jan 2023 11:50:38 +0800
-Subject: [PATCH 3012/3015] wifi: mt76: mt7915: enable PPDU-TxS to host when
+Subject: [PATCH 3010/3013] wifi: mt76: mt7915: enable PPDU-TxS to host when
  wed enable
 
 Calculate tx bytes and tx retries from PPDU-TxS
@@ -13,7 +13,7 @@
  4 files changed, 12 insertions(+), 23 deletions(-)
 
 diff --git a/mt76_connac_mac.c b/mt76_connac_mac.c
-index 05ba5f26..4e24c492 100644
+index abcb9a27..5a5861a8 100644
 --- a/mt76_connac_mac.c
 +++ b/mt76_connac_mac.c
 @@ -490,8 +490,6 @@ void mt76_connac2_mac_write_txwi(struct mt76_dev *dev, __le32 *txwi,
@@ -26,10 +26,10 @@
  			wcid->stats.tx_packets++;
  	}
 diff --git a/mt7915/init.c b/mt7915/init.c
-index c3b186c8..a1be5b7d 100644
+index 27395316..70563c9d 100644
 --- a/mt7915/init.c
 +++ b/mt7915/init.c
-@@ -491,6 +491,12 @@ mt7915_mac_init_band(struct mt7915_dev *dev, u8 band)
+@@ -503,6 +503,12 @@ mt7915_mac_init_band(struct mt7915_dev *dev, u8 band)
  	set = FIELD_PREP(MT_WTBLOFF_TOP_RSCR_RCPI_MODE, 0) |
  	      FIELD_PREP(MT_WTBLOFF_TOP_RSCR_RCPI_PARAM, 0x3);
  	mt76_rmw(dev, MT_WTBLOFF_TOP_RSCR(band), mask, set);
diff --git a/recipes-wifi/linux-mt76/files/patches/3013-wifi-mt76-mt7915-get-tx-retries-from-tx-free-done-ev.patch b/recipes-wifi/linux-mt76/files/patches/3011-wifi-mt76-mt7915-get-tx-retries-from-tx-free-done-ev.patch
similarity index 95%
rename from recipes-wifi/linux-mt76/files/patches/3013-wifi-mt76-mt7915-get-tx-retries-from-tx-free-done-ev.patch
rename to recipes-wifi/linux-mt76/files/patches/3011-wifi-mt76-mt7915-get-tx-retries-from-tx-free-done-ev.patch
index e596240..6904bea 100644
--- a/recipes-wifi/linux-mt76/files/patches/3013-wifi-mt76-mt7915-get-tx-retries-from-tx-free-done-ev.patch
+++ b/recipes-wifi/linux-mt76/files/patches/3011-wifi-mt76-mt7915-get-tx-retries-from-tx-free-done-ev.patch
@@ -1,8 +1,8 @@
-From be812eb6a9ceafc732c518070458fed74a09cd2e Mon Sep 17 00:00:00 2001
+From 47c0c3360a84cb4f8d5500ef1190a1eea394e2e8 Mon Sep 17 00:00:00 2001
 From: Peter Chiu <chui-hao.chiu@mediatek.com>
 Date: Tue, 17 Jan 2023 21:15:00 +0800
-Subject: [PATCH] wifi: mt76: mt7915: get tx retries from tx free done event
- for sw path
+Subject: [PATCH 3011/3013] wifi: mt76: mt7915: get tx retries from tx free
+ done event for sw path
 
 ---
  mt7915/mac.c  | 14 +++++++++++---
diff --git a/recipes-wifi/linux-mt76/files/patches/3014-wifi-mt76-update-debugfs-knob-for-reset-counter-and-.patch b/recipes-wifi/linux-mt76/files/patches/3012-wifi-mt76-update-debugfs-knob-for-reset-counter-and-.patch
similarity index 93%
rename from recipes-wifi/linux-mt76/files/patches/3014-wifi-mt76-update-debugfs-knob-for-reset-counter-and-.patch
rename to recipes-wifi/linux-mt76/files/patches/3012-wifi-mt76-update-debugfs-knob-for-reset-counter-and-.patch
index 96c308b..c852b73 100644
--- a/recipes-wifi/linux-mt76/files/patches/3014-wifi-mt76-update-debugfs-knob-for-reset-counter-and-.patch
+++ b/recipes-wifi/linux-mt76/files/patches/3012-wifi-mt76-update-debugfs-knob-for-reset-counter-and-.patch
@@ -1,7 +1,7 @@
-From 5b02de4f8b414de462c2c2df61aed85e745d5999 Mon Sep 17 00:00:00 2001
+From 655d403531165600ea621dc7889165a091971331 Mon Sep 17 00:00:00 2001
 From: Peter Chiu <chui-hao.chiu@mediatek.com>
 Date: Mon, 30 Jan 2023 11:36:32 +0800
-Subject: [PATCH 3014/3015] wifi: mt76: update debugfs knob for reset counter
+Subject: [PATCH 3012/3013] wifi: mt76: update debugfs knob for reset counter
  and get tx packet error rate
 
 ---
@@ -9,7 +9,7 @@
  1 file changed, 62 insertions(+)
 
 diff --git a/mt7915/mtk_debugfs.c b/mt7915/mtk_debugfs.c
-index d203facf..479da4a0 100644
+index 2dc4cb87..87a7ca98 100644
 --- a/mt7915/mtk_debugfs.c
 +++ b/mt7915/mtk_debugfs.c
 @@ -3190,6 +3190,66 @@ mt7915_sw_aci_set(void *data, u64 val)
diff --git a/recipes-wifi/linux-mt76/files/patches/3015-mt76-connac-wed-add-wed-rx-copy-skb-and-revert-page_.patch b/recipes-wifi/linux-mt76/files/patches/3013-mt76-connac-wed-add-wed-rx-copy-skb-and-revert-page_.patch
similarity index 93%
rename from recipes-wifi/linux-mt76/files/patches/3015-mt76-connac-wed-add-wed-rx-copy-skb-and-revert-page_.patch
rename to recipes-wifi/linux-mt76/files/patches/3013-mt76-connac-wed-add-wed-rx-copy-skb-and-revert-page_.patch
index 883312e..89b423c 100644
--- a/recipes-wifi/linux-mt76/files/patches/3015-mt76-connac-wed-add-wed-rx-copy-skb-and-revert-page_.patch
+++ b/recipes-wifi/linux-mt76/files/patches/3013-mt76-connac-wed-add-wed-rx-copy-skb-and-revert-page_.patch
@@ -1,7 +1,7 @@
-From a8e76b8635c6daf65fb029ea4476ef777768c092 Mon Sep 17 00:00:00 2001
+From 40bc4191469a25ab239596071faf7d8ad69e9fb3 Mon Sep 17 00:00:00 2001
 From: Sujuan Chen <sujuan.chen@mediatek.com>
 Date: Thu, 5 Jan 2023 16:43:57 +0800
-Subject: [PATCH 3015/3015] mt76: connac: wed: add wed rx copy skb and revert
+Subject: [PATCH 3013/3013] mt76: connac: wed: add wed rx copy skb and revert
  page_pool
 
 Signed-off-by: Sujuan Chen <sujuan.chen@mediatek.com>
@@ -13,10 +13,10 @@
  mt7915/mmio.c |  74 +++++++++++++++++++--------
  mt7921/main.c |  31 ++----------
  usb.c         |  42 +++++++--------
- 7 files changed, 180 insertions(+), 210 deletions(-)
+ 7 files changed, 179 insertions(+), 211 deletions(-)
 
 diff --git a/dma.c b/dma.c
-index 76af6506..79da538c 100644
+index d1a1dae4..3adb1136 100644
 --- a/dma.c
 +++ b/dma.c
 @@ -173,7 +173,7 @@ mt76_free_pending_rxwi(struct mt76_dev *dev)
@@ -66,7 +66,7 @@
  {
  	struct mt76_queue_entry *e = &q->entry[idx];
  	struct mt76_desc *desc = &q->desc[idx];
-@@ -435,15 +437,47 @@ mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx,
+@@ -433,15 +435,47 @@ mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx,
  		if (!r)
  			return NULL;
  
@@ -121,7 +121,7 @@
  
  		if (drop) {
  			u32 ctrl = le32_to_cpu(READ_ONCE(desc->ctrl));
-@@ -463,9 +497,9 @@ mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx,
+@@ -454,9 +488,9 @@ mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx,
  	} else {
  		buf = e->buf;
  		e->buf = NULL;
@@ -134,7 +134,7 @@
  	}
  
  	return buf;
-@@ -489,7 +523,7 @@ mt76_dma_dequeue(struct mt76_dev *dev, struct mt76_queue *q, bool flush,
+@@ -480,7 +514,7 @@ mt76_dma_dequeue(struct mt76_dev *dev, struct mt76_queue *q, bool flush,
  	q->tail = (q->tail + 1) % q->ndesc;
  	q->queued--;
  
@@ -143,7 +143,7 @@
  }
  
  static int
-@@ -616,11 +650,12 @@ free_skb:
+@@ -607,11 +641,12 @@ free_skb:
  }
  
  static int
@@ -159,7 +159,7 @@
  
  	if (!q->ndesc)
  		return 0;
-@@ -628,31 +663,35 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q,
+@@ -619,31 +654,35 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q,
  	spin_lock_bh(&q->lock);
  
  	while (q->queued < q->ndesc - 1) {
@@ -208,7 +208,7 @@
  		mt76_dma_kick_queue(dev, q);
  
  	spin_unlock_bh(&q->lock);
-@@ -690,7 +729,7 @@ int mt76_dma_wed_setup(struct mt76_dev *dev, struct mt76_queue *q, bool reset)
+@@ -681,7 +720,7 @@ int mt76_dma_wed_setup(struct mt76_dev *dev, struct mt76_queue *q, bool reset)
  		/* WED txfree queue needs ring to be initialized before setup */
  		q->flags = 0;
  		mt76_dma_queue_reset(dev, q);
@@ -217,7 +217,7 @@
  		q->flags = flags;
  
  		ret = mtk_wed_device_txfree_ring_setup(wed, q->regs);
-@@ -738,10 +777,6 @@ mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q,
+@@ -729,10 +768,6 @@ mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q,
  	if (!q->entry)
  		return -ENOMEM;
  
@@ -228,7 +228,7 @@
  	ret = mt76_dma_wed_setup(dev, q, false);
  	if (ret)
  		return ret;
-@@ -755,6 +790,7 @@ mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q,
+@@ -746,6 +781,7 @@ mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q,
  static void
  mt76_dma_rx_cleanup(struct mt76_dev *dev, struct mt76_queue *q)
  {
@@ -236,7 +236,7 @@
  	void *buf;
  	bool more;
  
-@@ -768,7 +804,7 @@ mt76_dma_rx_cleanup(struct mt76_dev *dev, struct mt76_queue *q)
+@@ -759,7 +795,7 @@ mt76_dma_rx_cleanup(struct mt76_dev *dev, struct mt76_queue *q)
  		if (!buf)
  			break;
  
@@ -245,7 +245,7 @@
  	} while (1);
  
  	if (q->rx_head) {
-@@ -777,6 +813,15 @@ mt76_dma_rx_cleanup(struct mt76_dev *dev, struct mt76_queue *q)
+@@ -768,6 +804,15 @@ mt76_dma_rx_cleanup(struct mt76_dev *dev, struct mt76_queue *q)
  	}
  
  	spin_unlock_bh(&q->lock);
@@ -261,7 +261,7 @@
  }
  
  static void
-@@ -797,7 +842,7 @@ mt76_dma_rx_reset(struct mt76_dev *dev, enum mt76_rxq_id qid)
+@@ -788,7 +833,7 @@ mt76_dma_rx_reset(struct mt76_dev *dev, enum mt76_rxq_id qid)
  	mt76_dma_wed_setup(dev, q, true);
  	if (q->flags != MT_WED_Q_TXFREE) {
  		mt76_dma_sync_idx(dev, q);
@@ -270,7 +270,7 @@
  	}
  }
  
-@@ -815,7 +860,7 @@ mt76_add_fragment(struct mt76_dev *dev, struct mt76_queue *q, void *data,
+@@ -806,7 +851,7 @@ mt76_add_fragment(struct mt76_dev *dev, struct mt76_queue *q, void *data,
  
  		skb_add_rx_frag(skb, nr_frags, page, offset, len, q->buf_size);
  	} else {
@@ -279,7 +279,7 @@
  	}
  
  	if (more)
-@@ -888,7 +933,6 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)
+@@ -879,7 +924,6 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)
  			goto free_frag;
  
  		skb_reserve(skb, q->buf_offset);
@@ -287,7 +287,7 @@
  
  		*(u32 *)skb->cb = info;
  
-@@ -904,10 +948,10 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)
+@@ -895,10 +939,10 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)
  		continue;
  
  free_frag:
@@ -300,7 +300,7 @@
  	return done;
  }
  
-@@ -952,7 +996,7 @@ mt76_dma_init(struct mt76_dev *dev,
+@@ -943,7 +987,7 @@ mt76_dma_init(struct mt76_dev *dev,
  
  	mt76_for_each_q_rx(dev, i) {
  		netif_napi_add(&dev->napi_dev, &dev->napi[i], poll);
@@ -309,7 +309,7 @@
  		napi_enable(&dev->napi[i]);
  	}
  
-@@ -1003,8 +1047,6 @@ void mt76_dma_cleanup(struct mt76_dev *dev)
+@@ -994,8 +1038,6 @@ void mt76_dma_cleanup(struct mt76_dev *dev)
  
  		netif_napi_del(&dev->napi[i]);
  		mt76_dma_rx_cleanup(dev, q);
@@ -319,7 +319,7 @@
  
  	mt76_free_pending_txwi(dev);
 diff --git a/mac80211.c b/mac80211.c
-index 95861d47..90447472 100644
+index 4655f814..4dc7627e 100644
 --- a/mac80211.c
 +++ b/mac80211.c
 @@ -4,7 +4,6 @@
@@ -330,7 +330,7 @@
  #include "mt76.h"
  
  #define CHAN2G(_idx, _freq) {			\
-@@ -569,47 +568,6 @@ void mt76_unregister_phy(struct mt76_phy *phy)
+@@ -573,47 +572,6 @@ void mt76_unregister_phy(struct mt76_phy *phy)
  }
  EXPORT_SYMBOL_GPL(mt76_unregister_phy);
  
@@ -378,7 +378,7 @@
  struct mt76_dev *
  mt76_alloc_device(struct device *pdev, unsigned int size,
  		  const struct ieee80211_ops *ops,
-@@ -1745,21 +1703,6 @@ void mt76_ethtool_worker(struct mt76_ethtool_worker_info *wi,
+@@ -1753,21 +1711,6 @@ void mt76_ethtool_worker(struct mt76_ethtool_worker_info *wi,
  }
  EXPORT_SYMBOL_GPL(mt76_ethtool_worker);
  
@@ -401,10 +401,10 @@
  {
  	struct ieee80211_hw *hw = phy->hw;
 diff --git a/mt76.h b/mt76.h
-index 22c6531a..19100d62 100644
+index bc0c9ae7..d17650d0 100644
 --- a/mt76.h
 +++ b/mt76.h
-@@ -210,7 +210,7 @@ struct mt76_queue {
+@@ -209,7 +209,7 @@ struct mt76_queue {
  
  	dma_addr_t desc_dma;
  	struct sk_buff *rx_head;
@@ -633,7 +633,7 @@
  	return -ENOMEM;
  }
 diff --git a/mt7921/main.c b/mt7921/main.c
-index 75eaf86c..1434ca79 100644
+index a72964e7..4c400223 100644
 --- a/mt7921/main.c
 +++ b/mt7921/main.c
 @@ -1090,34 +1090,17 @@ static void
@@ -699,7 +699,7 @@
  
  static u64
 diff --git a/usb.c b/usb.c
-index b88959ef..3e281715 100644
+index 5e5c7bf5..f0a50f57 100644
 --- a/usb.c
 +++ b/usb.c
 @@ -319,27 +319,29 @@ mt76u_set_endpoints(struct usb_interface *intf,
@@ -816,12 +816,12 @@
  	int i;
  
  	for (i = 0; i < q->ndesc; i++) {
-@@ -705,7 +701,13 @@ mt76u_free_rx_queue(struct mt76_dev *dev, struct mt76_queue *q)
+@@ -705,8 +701,12 @@ mt76u_free_rx_queue(struct mt76_dev *dev, struct mt76_queue *q)
  		mt76u_urb_free(q->entry[i].urb);
  		q->entry[i].urb = NULL;
  	}
 -	page_pool_destroy(q->page_pool);
-+
+-	q->page_pool = NULL;
 +	if (!q->rx_page.va)
 +		return;
 +
diff --git a/recipes-wifi/linux-mt76/files/patches/4001-mt76-revert-get_of_mac_addr.patch b/recipes-wifi/linux-mt76/files/patches/4001-mt76-revert-get_of_mac_addr.patch
index 143f279..7a0aa12 100644
--- a/recipes-wifi/linux-mt76/files/patches/4001-mt76-revert-get_of_mac_addr.patch
+++ b/recipes-wifi/linux-mt76/files/patches/4001-mt76-revert-get_of_mac_addr.patch
@@ -1,4 +1,4 @@
-From d5719b44dcc2f6ef728a63f523dbbe9f089a2eaf Mon Sep 17 00:00:00 2001
+From 5b3d131191690db907ee5c0ba43a80cb0f23b3bc Mon Sep 17 00:00:00 2001
 From: Shayne Chen <shayne.chen@mediatek.com>
 Date: Tue, 13 Dec 2022 10:51:46 +0800
 Subject: [PATCH 4001/4005] mt76: revert get_of_mac_addr
@@ -8,7 +8,7 @@
  1 file changed, 7 insertions(+), 1 deletion(-)
 
 diff --git a/eeprom.c b/eeprom.c
-index d1612641..1f29cf99 100644
+index 6e6d84e3..b2df0f44 100644
 --- a/eeprom.c
 +++ b/eeprom.c
 @@ -128,9 +128,15 @@ void
diff --git a/recipes-wifi/linux-mt76/files/patches/4002-mt76-include-header-files-for-module-param.patch b/recipes-wifi/linux-mt76/files/patches/4002-mt76-include-header-files-for-module-param.patch
index 509b828..e7661df 100644
--- a/recipes-wifi/linux-mt76/files/patches/4002-mt76-include-header-files-for-module-param.patch
+++ b/recipes-wifi/linux-mt76/files/patches/4002-mt76-include-header-files-for-module-param.patch
@@ -1,4 +1,4 @@
-From 83be679b14eb071b0eb1cedac9d004901322b2f3 Mon Sep 17 00:00:00 2001
+From 227f29f577dda88bda5c6213a655e89ff3b9203c Mon Sep 17 00:00:00 2001
 From: Shayne Chen <shayne.chen@mediatek.com>
 Date: Tue, 13 Dec 2022 10:38:13 +0800
 Subject: [PATCH 4002/4005] mt76: include header files for module param
@@ -47,7 +47,7 @@
  int mt76_connac_mcu_start_firmware(struct mt76_dev *dev, u32 addr, u32 option)
  {
 diff --git a/mt7915/mcu.c b/mt7915/mcu.c
-index b5a0967b..f4867ea7 100644
+index e1c08178..37291865 100644
 --- a/mt7915/mcu.c
 +++ b/mt7915/mcu.c
 @@ -6,6 +6,7 @@
diff --git a/recipes-wifi/linux-mt76/files/patches/4003-mt76-revert-kernel-api-for-kernel-5.4.patch b/recipes-wifi/linux-mt76/files/patches/4003-mt76-revert-kernel-api-for-kernel-5.4.patch
index d7d40c2..a75825e 100644
--- a/recipes-wifi/linux-mt76/files/patches/4003-mt76-revert-kernel-api-for-kernel-5.4.patch
+++ b/recipes-wifi/linux-mt76/files/patches/4003-mt76-revert-kernel-api-for-kernel-5.4.patch
@@ -1,4 +1,4 @@
-From 1796376cd4aedff17a93f6a28c5b321d678ebf95 Mon Sep 17 00:00:00 2001
+From be0397f77f21cfbc5f865d89d9c4dcdc87f06233 Mon Sep 17 00:00:00 2001
 From: Peter Chiu <chui-hao.chiu@mediatek.com>
 Date: Fri, 30 Dec 2022 11:11:59 +0800
 Subject: [PATCH 4003/4005] mt76: revert kernel api for kernel 5.4
@@ -24,10 +24,10 @@
  	return 0;
  }
 diff --git a/dma.c b/dma.c
-index 79da538c..e6021369 100644
+index 3adb1136..1fc4bd2d 100644
 --- a/dma.c
 +++ b/dma.c
-@@ -928,7 +928,7 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)
+@@ -919,7 +919,7 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)
  		    !(dev->drv->rx_check(dev, data, len)))
  			goto free_frag;
  
diff --git a/recipes-wifi/linux-mt76/files/patches/4004-mt76-revert-for-backports-5.15-wireless-stack.patch b/recipes-wifi/linux-mt76/files/patches/4004-mt76-revert-for-backports-5.15-wireless-stack.patch
index 1059763..652fa50 100644
--- a/recipes-wifi/linux-mt76/files/patches/4004-mt76-revert-for-backports-5.15-wireless-stack.patch
+++ b/recipes-wifi/linux-mt76/files/patches/4004-mt76-revert-for-backports-5.15-wireless-stack.patch
@@ -1,4 +1,4 @@
-From fb3205686d76d409b1cdd4a25c2dd526fda4b2e4 Mon Sep 17 00:00:00 2001
+From 1a40927274d316173f1aa460083eea54e2804a0a Mon Sep 17 00:00:00 2001
 From: Shayne Chen <shayne.chen@mediatek.com>
 Date: Fri, 30 Dec 2022 11:12:07 +0800
 Subject: [PATCH 4004/4005] mt76: revert for backports-5.15 wireless stack
@@ -22,10 +22,10 @@
  15 files changed, 168 insertions(+), 178 deletions(-)
 
 diff --git a/dma.c b/dma.c
-index e6021369..c2125106 100644
+index 1fc4bd2d..e7d174b8 100644
 --- a/dma.c
 +++ b/dma.c
-@@ -995,7 +995,7 @@ mt76_dma_init(struct mt76_dev *dev,
+@@ -986,7 +986,7 @@ mt76_dma_init(struct mt76_dev *dev,
  	init_completion(&dev->mmio.wed_reset_complete);
  
  	mt76_for_each_q_rx(dev, i) {
@@ -35,10 +35,10 @@
  		napi_enable(&dev->napi[i]);
  	}
 diff --git a/mac80211.c b/mac80211.c
-index 90447472..14a02c01 100644
+index 4dc7627e..4c88710f 100644
 --- a/mac80211.c
 +++ b/mac80211.c
-@@ -1509,7 +1509,7 @@ EXPORT_SYMBOL_GPL(mt76_get_sar_power);
+@@ -1517,7 +1517,7 @@ EXPORT_SYMBOL_GPL(mt76_get_sar_power);
  static void
  __mt76_csa_finish(void *priv, u8 *mac, struct ieee80211_vif *vif)
  {
@@ -47,7 +47,7 @@
  		ieee80211_csa_finish(vif);
  }
  
-@@ -1531,7 +1531,7 @@ __mt76_csa_check(void *priv, u8 *mac, struct ieee80211_vif *vif)
+@@ -1539,7 +1539,7 @@ __mt76_csa_check(void *priv, u8 *mac, struct ieee80211_vif *vif)
  {
  	struct mt76_dev *dev = priv;
  
@@ -524,10 +524,10 @@
  	field = RATE_PARAM_FIXED;
  
 diff --git a/mt7915/dma.c b/mt7915/dma.c
-index 4dd321ee..354d1e0e 100644
+index 6d9b2d15..08322453 100644
 --- a/mt7915/dma.c
 +++ b/mt7915/dma.c
-@@ -552,8 +552,8 @@ int mt7915_dma_init(struct mt7915_dev *dev, struct mt7915_phy *phy2)
+@@ -554,8 +554,8 @@ int mt7915_dma_init(struct mt7915_dev *dev, struct mt7915_phy *phy2)
  	if (ret < 0)
  		return ret;
  
@@ -539,10 +539,10 @@
  
  	mt7915_dma_enable(dev);
 diff --git a/mt7915/init.c b/mt7915/init.c
-index a1be5b7d..9e8003d7 100644
+index 70563c9d..0b852286 100644
 --- a/mt7915/init.c
 +++ b/mt7915/init.c
-@@ -1139,8 +1139,7 @@ mt7915_init_he_caps(struct mt7915_phy *phy, enum nl80211_band band,
+@@ -1160,8 +1160,7 @@ mt7915_init_he_caps(struct mt7915_phy *phy, enum nl80211_band band,
  			mt7915_gen_ppe_thresh(he_cap->ppe_thres, nss);
  		} else {
  			he_cap_elem->phy_cap_info[9] |=
@@ -553,7 +553,7 @@
  
  		if (band == NL80211_BAND_6GHZ) {
 diff --git a/mt7915/mac.c b/mt7915/mac.c
-index b7559182..26eb211a 100644
+index 180c1ae3..583b71b1 100644
 --- a/mt7915/mac.c
 +++ b/mt7915/mac.c
 @@ -902,7 +902,7 @@ mt7915_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi)
@@ -610,7 +610,7 @@
  
  	mutex_lock(&dev->mt76.mutex);
 diff --git a/mt7915/mcu.c b/mt7915/mcu.c
-index 003e33be..a7d3adc2 100644
+index 37291865..4f1bd1cd 100644
 --- a/mt7915/mcu.c
 +++ b/mt7915/mcu.c
 @@ -64,7 +64,7 @@ mt7915_mcu_set_sta_he_mcs(struct ieee80211_sta *sta, __le16 *he_mcs,
diff --git a/recipes-wifi/linux-mt76/files/patches/4005-wifi-mt76-revert-EHT-definitions.patch b/recipes-wifi/linux-mt76/files/patches/4005-wifi-mt76-revert-EHT-definitions.patch
index 8404f7b..479accf 100644
--- a/recipes-wifi/linux-mt76/files/patches/4005-wifi-mt76-revert-EHT-definitions.patch
+++ b/recipes-wifi/linux-mt76/files/patches/4005-wifi-mt76-revert-EHT-definitions.patch
@@ -1,4 +1,4 @@
-From b655964b1f68678a665f30a68c13a73feeffaa73 Mon Sep 17 00:00:00 2001
+From 21286ba6a27ae54885687c0f82a48e52cef638aa Mon Sep 17 00:00:00 2001
 From: Peter Chiu <chui-hao.chiu@mediatek.com>
 Date: Fri, 3 Feb 2023 17:09:55 +0800
 Subject: [PATCH 4005/4005] wifi: mt76: revert EHT definitions
@@ -99,10 +99,10 @@
  #define DEFAULT_HE_DURATION_RTS_THRES	1023
  static void
 diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
-index 747ae7e9..3d4322d1 100644
+index 287cffcc..b80a1011 100644
 --- a/mt76_connac_mcu.h
 +++ b/mt76_connac_mcu.h
-@@ -1897,12 +1897,8 @@ void mt76_connac_mcu_reg_wr(struct mt76_dev *dev, u32 offset, u32 val);
+@@ -1894,12 +1894,8 @@ void mt76_connac_mcu_reg_wr(struct mt76_dev *dev, u32 offset, u32 val);
  
  const struct ieee80211_sta_he_cap *
  mt76_connac_get_he_phy_cap(struct mt76_phy *phy, struct ieee80211_vif *vif);
diff --git a/recipes-wifi/linux-mt76/files/patches/patches.inc b/recipes-wifi/linux-mt76/files/patches/patches.inc
index c041c72..833a2b0 100644
--- a/recipes-wifi/linux-mt76/files/patches/patches.inc
+++ b/recipes-wifi/linux-mt76/files/patches/patches.inc
@@ -1,6 +1,5 @@
 #patch patches (come from openwrt/lede/target/linux/mediatek)
 SRC_URI_append = " \
-    file://0001-wifi-mt76-mt7915-rework-mt7915_thermal_init.patch \
     file://1001-mt76-mt7915-add-mtk-internal-debug-tools-for-mt76.patch \
     file://1002-mt76-mt7915-csi-implement-csi-support.patch \
     file://1003-mt76-mt7915-air-monitor-support.patch \
@@ -32,22 +31,20 @@
     file://1130-mt76-mt7915-amsdu-set-and-get-control.patch \
     file://1131-wifi-mt76-mt7915-add-support-for-he-ldpc-control-fro.patch \
     file://1132-mt76-mt7915-Add-vendor-command-attribute-for-RTS-BW-.patch \
-    file://1133-mt76-mt7915-Allow-AP-to-change-channel-width-for-40M.patch \
+    file://1134-mt76-mt7915-add-vendor-cmd-to-get-available-color-bi.patch \
     file://3001-mt76-mt7915-wed-add-wed-tx-support.patch \
     file://3002-mt76-mt7915-wed-add-wds-support-when-wed-is-enabled.patch \
     file://3003-mt76-mt7915-wed-add-fill-receive-path-to-report-wed-.patch \
     file://3004-mt76-mt7915-wed-find-rx-token-by-physical-address.patch \
-    file://3005-mt76-mt7915-wed-drop-scatter-and-gather-frame.patch \
-    file://3006-mt76-mt7915-wed-HW-ATF-support-for-mt7986.patch \
-    file://3007-mt76-mt7915-wed-add-mt7916-2-pcie-support-when-wed-o.patch \
-    file://3008-mt76-mt7915-wed-add-rxwi-for-further-in-chip-rro.patch \
-    file://3009-mt76-mt7915-add-mt7915_net_setup_tc-to-support-wifi2.patch \
-    file://3010-wifi-mt76-mt7915-add-wa-command-to-get-tx-msdu-count.patch \
-    file://3011-wifi-mt76-get-tx-count-and-tx-failed-from-mcu-comman.patch \
-    file://3012-wifi-mt76-mt7915-enable-PPDU-TxS-to-host-when-wed-en.patch \
-    file://3013-wifi-mt76-mt7915-get-tx-retries-from-tx-free-done-ev.patch \
-    file://3014-wifi-mt76-update-debugfs-knob-for-reset-counter-and-.patch \
-    file://3015-mt76-connac-wed-add-wed-rx-copy-skb-and-revert-page_.patch \
+    file://3005-mt76-mt7915-wed-HW-ATF-support-for-mt7986.patch \
+    file://3006-mt76-mt7915-wed-add-rxwi-for-further-in-chip-rro.patch \
+    file://3007-mt76-mt7915-add-mt7915_net_setup_tc-to-support-wifi2.patch \
+    file://3008-wifi-mt76-mt7915-add-wa-command-to-get-tx-msdu-count.patch \
+    file://3009-wifi-mt76-get-tx-count-and-tx-failed-from-mcu-comman.patch \
+    file://3010-wifi-mt76-mt7915-enable-PPDU-TxS-to-host-when-wed-en.patch \
+    file://3011-wifi-mt76-mt7915-get-tx-retries-from-tx-free-done-ev.patch \
+    file://3012-wifi-mt76-update-debugfs-knob-for-reset-counter-and-.patch \
+    file://3013-mt76-connac-wed-add-wed-rx-copy-skb-and-revert-page_.patch \
     file://4001-mt76-revert-get_of_mac_addr.patch \
     file://4002-mt76-include-header-files-for-module-param.patch \
     file://4003-mt76-revert-kernel-api-for-kernel-5.4.patch \
diff --git a/recipes-wifi/linux-mt76/files/src/firmware/mt7996/mt7996_eeprom_tm.bin b/recipes-wifi/linux-mt76/files/src/firmware/mt7996/mt7996_eeprom_tm.bin
new file mode 100755
index 0000000..0ff5567
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/src/firmware/mt7996/mt7996_eeprom_tm.bin
Binary files differ
diff --git a/recipes-wifi/linux-mt76/mt76.inc b/recipes-wifi/linux-mt76/mt76.inc
index 4feb511..1739876 100644
--- a/recipes-wifi/linux-mt76/mt76.inc
+++ b/recipes-wifi/linux-mt76/mt76.inc
@@ -1 +1 @@
-SRCREV ?= "b2360d59747c6fed2b65bc1c3563c10593c83f3e"
+SRCREV ?= "c32d6d849c43792abd8007e13e468b12d6d6e0b7"
diff --git a/recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0010-hostapd-mtk-Add-DFS-detection-mode.patch b/recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0010-hostapd-mtk-Add-DFS-detection-mode.patch
index 2ceb639..7ec986a 100644
--- a/recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0010-hostapd-mtk-Add-DFS-detection-mode.patch
+++ b/recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0010-hostapd-mtk-Add-DFS-detection-mode.patch
@@ -63,7 +63,7 @@
  					      char *buf, char *reply,
  					      int reply_size,
 @@ -4081,6 +4101,9 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
- 		reply_len = hostapd_ctrl_iface_get_hemu(hapd, reply, reply_size);
+ 		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) {
diff --git a/recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0016-hostapd-mtk-Add-available-color-bitmap.patch b/recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0016-hostapd-mtk-Add-available-color-bitmap.patch
new file mode 100644
index 0000000..9bbbf87
--- /dev/null
+++ b/recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0016-hostapd-mtk-Add-available-color-bitmap.patch
@@ -0,0 +1,337 @@
+From e7790a1bceca6b7612f29b00c429cf23f5dd9e3a 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] 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      | 66 +++++++++++++++++++++++++++
+ src/drivers/driver_nl80211.h      |  1 +
+ src/drivers/driver_nl80211_capa.c |  3 ++
+ 9 files changed, 192 insertions(+), 1 deletion(-)
+
+diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
+index 0ad8451..b0d5ded 100644
+--- a/hostapd/ctrl_iface.c
++++ b/hostapd/ctrl_iface.c
+@@ -3635,6 +3635,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,
+@@ -4202,6 +4272,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 30b3392..b6cf52e 100644
+--- a/hostapd/hostapd_cli.c
++++ b/hostapd/hostapd_cli.c
+@@ -1578,6 +1578,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[])
+ {
+@@ -1795,6 +1809,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 1a82f23..decffdd 100644
+--- a/src/ap/ap_drv_ops.c
++++ b/src/ap/ap_drv_ops.c
+@@ -1091,4 +1091,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 4406666..61c1360 100644
+--- a/src/ap/ap_drv_ops.h
++++ b/src/ap/ap_drv_ops.h
+@@ -149,6 +149,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 0999ea9..f2afb2e 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 {
+@@ -252,6 +253,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 b07aaf3..266c630 100644
+--- a/src/drivers/driver.h
++++ b/src/drivers/driver.h
+@@ -4736,6 +4736,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 6702384..c8771f7 100644
+--- a/src/drivers/driver_nl80211.c
++++ b/src/drivers/driver_nl80211.c
+@@ -12433,6 +12433,71 @@ static int nl80211_dpp_listen(void *priv, bool enable)
+ }
+ #endif /* CONFIG_DPP */
+ 
++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;
++}
+ 
+ #ifdef CONFIG_TESTING_OPTIONS
+ 
+@@ -13073,4 +13138,5 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
+ 	.start_disabled = nl80211_start_disabled,
+ 	.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 e570224..b90c8fa 100644
+--- a/src/drivers/driver_nl80211.h
++++ b/src/drivers/driver_nl80211.h
+@@ -186,6 +186,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 fcfa68b..c3c7b41 100644
+--- a/src/drivers/driver_nl80211_capa.c
++++ b/src/drivers/driver_nl80211_capa.c
+@@ -1068,6 +1068,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.39.0
+
diff --git a/recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0020-hostapd-mtk-Mark-DFS-channel-as-available-for-CSA.patch b/recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0020-hostapd-mtk-Mark-DFS-channel-as-available-for-CSA.patch
new file mode 100644
index 0000000..1fe5c88
--- /dev/null
+++ b/recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0020-hostapd-mtk-Mark-DFS-channel-as-available-for-CSA.patch
@@ -0,0 +1,60 @@
+From 3e9500a42a41e8cd7c2d7bc20aba96e1e17161fb 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] 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 c33b7a4..9ba6992 100644
+--- a/hostapd/ctrl_iface.c
++++ b/hostapd/ctrl_iface.c
+@@ -2704,6 +2704,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 0da18e2..6231e51 100644
+--- a/hostapd/hostapd_cli.c
++++ b/hostapd/hostapd_cli.c
+@@ -1693,7 +1693,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 18bae5c..2fae590 100644
+--- a/src/ap/ctrl_iface_ap.c
++++ b/src/ap/ctrl_iface_ap.c
+@@ -938,6 +938,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
+ 
+-- 
+2.18.0
+
diff --git a/recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0020-hostapd-mtk-add-11v_mbss-and-ema-support.patch b/recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0020-hostapd-mtk-add-11v_mbss-and-ema-support.patch
new file mode 100644
index 0000000..8d59a0f
--- /dev/null
+++ b/recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0020-hostapd-mtk-add-11v_mbss-and-ema-support.patch
@@ -0,0 +1,1175 @@
+From 8cbdb9a59e3bbe8804f909b13ce6df6e2777c3da Mon Sep 17 00:00:00 2001
+From: mtk20656 <chank.chen@mediatek.com>
+Date: Thu, 2 Mar 2023 10:51:43 +0800
+Subject: [PATCH] hostapd: mtk: add 11v_mbss and ema support for hostapd
+
+Signed-off-by: mtk20656 <chank.chen@mediatek.com>
+---
+ hostapd/config_file.c             |   9 +
+ hostapd/hostapd.conf              |  58 +++++++
+ hostapd/main.c                    |   3 +
+ src/ap/ap_config.c                |  12 ++
+ src/ap/ap_config.h                |   6 +
+ src/ap/beacon.c                   | 124 ++++++++++++--
+ src/ap/hostapd.c                  |  72 +++++++-
+ src/ap/hostapd.h                  |   7 +
+ src/ap/ieee802_11.c               | 276 +++++++++++++++++++++++++++++-
+ src/ap/ieee802_11.h               |   7 +-
+ src/ap/ieee802_11_shared.c        |  11 ++
+ src/common/ieee802_11_common.c    |   4 +
+ src/common/ieee802_11_common.h    |   3 +
+ src/common/ieee802_11_defs.h      |   5 +
+ src/drivers/driver.h              |  42 +++++
+ src/drivers/driver_nl80211.c      |  52 ++++++
+ src/drivers/driver_nl80211_capa.c |  27 +++
+ 17 files changed, 698 insertions(+), 20 deletions(-)
+
+diff --git a/hostapd/config_file.c b/hostapd/config_file.c
+index 649618b..3f26191 100644
+--- a/hostapd/config_file.c
++++ b/hostapd/config_file.c
+@@ -3663,6 +3663,15 @@ static int hostapd_config_fill(struct hostapd_config *conf,
+ 			return 1;
+ 		}
+ 		bss->unsol_bcast_probe_resp_interval = val;
++	} else if (os_strcmp(buf, "mbssid") == 0) {
++		int mbssid = atoi(pos);
++		if (mbssid < 0 || mbssid > ENHANCED_MBSSID_ENABLED) {
++			wpa_printf(MSG_ERROR,
++				   "Line %d: invalid mbssid (%d): '%s'.",
++				   line, mbssid, pos);
++			return 1;
++		}
++		conf->mbssid = mbssid;
+ 	} else if (os_strcmp(buf, "mu_onoff") == 0) {
+ 		int val = atoi(pos);
+ 		if (val < 0 || val > 15) {
+diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf
+index e3a5eb3..f926029 100644
+--- a/hostapd/hostapd.conf
++++ b/hostapd/hostapd.conf
+@@ -3123,3 +3123,61 @@ own_ip_addr=127.0.0.1
+ #bss=wlan0_1
+ #bssid=00:13:10:95:fe:0b
+ # ...
++#
++# Multiple BSSID Advertisement in 802.11ax
++# IEEE Std 802.11ax-2021 added a feature where instead of multiple interfaces
++# on a common radio transmitting individual beacons, those can form a set with
++# a common beacon is transmitted for all. The interface which is brought up
++# first is called as the transmitting profile of the MBSSID set which transmits
++# the beacons. The remaining interfaces are called as the non-transmitting
++# profiles and these are advertised inside the multiple BSSID element in the
++# beacons and probe response frames.
++# The transmitting interface is visible to all clients in the vicinity, however
++# the clients which do not support parsing of the multiple BSSID element will
++# not be able to connect to the non-transmitting interfaces.
++#
++# Enhanced Multiple BSSID Advertisements (EMA)
++# When enabled, the non-transmitting interfaces are split into multiple
++# beacons. The number of beacons required to cover all the non-transmitting
++# profiles is called as the profile periodicity.
++#
++# Refer to IEEE Std 802.11-2020 for details regarding the procedure and
++# required MAC address assignment.
++#
++# Following configuration is per radio.
++# 0 = Disabled (Default)
++# 1 = Multiple BSSID advertisements enabled.
++# 2 = Enhanced multiple BSSID advertisements enabled.
++#mbssid=0
++#
++# The transmitting interface should be added with 'interface' option while
++# the non-transmitting interfaces should be added using 'bss' option.
++# Security configuration should be added separately per interface, if required.
++#
++# Example:
++#mbssid=2
++#interface=wlan2
++#ctrl_interface=/var/run/hostapd
++#wpa_passphrase=0123456789
++#ieee80211w=2
++#sae_pwe=1
++#auth_algs=1
++#wpa=2
++#wpa_pairwise=CCMP
++#ssid=<SSID-0>
++#bridge=br-lan
++#wpa_key_mgmt=SAE
++#bssid=00:03:7f:12:84:84
++#
++#bss=wlan2-1
++#ctrl_interface=/var/run/hostapd
++#wpa_passphrase=0123456789
++#ieee80211w=2
++#sae_pwe=1
++#auth_algs=1
++#wpa=2
++#wpa_pairwise=CCMP
++#ssid=<SSID-1>
++#bridge=br-lan
++#wpa_key_mgmt=SAE
++#bssid=00:03:7f:12:84:85
+diff --git a/hostapd/main.c b/hostapd/main.c
+index 70a4b32..1b6474a 100644
+--- a/hostapd/main.c
++++ b/hostapd/main.c
+@@ -253,6 +253,9 @@ static int hostapd_driver_init(struct hostapd_iface *iface)
+ 				wpa_printf(MSG_ERROR, "set_wowlan failed");
+ 		}
+ 		os_free(triggs);
++
++		iface->mbssid_max_interfaces = capa.mbssid_max_interfaces;
++		iface->ema_max_periodicity = capa.ema_max_periodicity;
+ 	}
+ 
+ 	return 0;
+diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
+index 4e46a62..7d9d5cb 100644
+--- a/src/ap/ap_config.c
++++ b/src/ap/ap_config.c
+@@ -1462,6 +1462,12 @@ static int hostapd_config_check_bss(struct hostapd_bss_config *bss,
+ 	}
+ #endif /* CONFIG_IEEE80211BE */
+ 
++	if (full_config && bss->ignore_broadcast_ssid && conf->mbssid) {
++		wpa_printf(MSG_ERROR,
++			   "Hidden SSID is not suppored when MBSSID is enabled");
++		return -1;
++	}
++
+ 	return 0;
+ }
+ 
+@@ -1545,6 +1551,12 @@ int hostapd_config_check(struct hostapd_config *conf, int full_config)
+ 	}
+ #endif /* CONFIG_IEEE80211BE */
+ 
++	if (full_config && conf->mbssid && !conf->ieee80211ax) {
++		wpa_printf(MSG_ERROR,
++			   "Cannot enable multiple BSSID support without ieee80211ax");
++		return -1;
++	}
++
+ 	for (i = 0; i < conf->num_bss; i++) {
+ 		if (hostapd_config_check_bss(conf->bss[i], conf, full_config))
+ 			return -1;
+diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
+index 7aeb176..51476b8 100644
+--- a/src/ap/ap_config.h
++++ b/src/ap/ap_config.h
+@@ -923,6 +923,8 @@ struct hostapd_bss_config {
+ 	u8 ext_capa[EXT_CAPA_MAX_LEN];
+ 
+ 	u8 rnr;
++
++	bool xrates_supported;
+ };
+ 
+ /**
+@@ -1163,6 +1165,10 @@ struct hostapd_config {
+ 	u8 ibf_enable;
+ 	u8 dfs_detect_mode;
+ 	u8 amsdu;
++
++#define MBSSID_ENABLED          1
++#define ENHANCED_MBSSID_ENABLED 2
++	u8 mbssid;
+ };
+ 
+ enum three_wire_mode {
+diff --git a/src/ap/beacon.c b/src/ap/beacon.c
+index f3ea5c2..51db23a 100644
+--- a/src/ap/beacon.c
++++ b/src/ap/beacon.c
+@@ -462,15 +462,77 @@ static u8 * hostapd_eid_supported_op_classes(struct hostapd_data *hapd, u8 *eid)
+ }
+ 
+ 
++static int ieee802_11_build_ap_params_mbssid(struct hostapd_data *hapd,
++					     struct wpa_driver_ap_params *params,
++					     u8 **eid)
++{
++	struct hostapd_iface *iface = hapd->iface;
++	struct hostapd_data *tx_bss;
++	size_t len;
++	u8 elem_count = 0, *elem = NULL, **elem_offset = NULL, *end;
++	u8 *tailpos = *eid;
++
++	if (!iface->mbssid_max_interfaces ||
++	    iface->num_bss > iface->mbssid_max_interfaces ||
++	    (iface->conf->mbssid == ENHANCED_MBSSID_ENABLED &&
++	     !iface->ema_max_periodicity))
++		goto fail;
++
++	tx_bss = hostapd_mbssid_get_tx_bss(hapd);
++	len = hostapd_eid_mbssid_len(tx_bss, WLAN_FC_STYPE_BEACON, &elem_count,
++				     NULL, 0);
++	if (!len || (iface->conf->mbssid == ENHANCED_MBSSID_ENABLED &&
++		     elem_count > iface->ema_max_periodicity))
++		goto fail;
++
++	elem = os_zalloc(len);
++	if (!elem)
++		goto fail;
++
++	elem_offset = os_zalloc(elem_count * sizeof(u8 *));
++	if (!elem_offset)
++		goto fail;
++
++	end = hostapd_eid_mbssid(tx_bss, elem, elem + len, WLAN_FC_STYPE_BEACON,
++				 elem_count, elem_offset, NULL, 0);
++
++	params->mbssid_tx_iface = tx_bss->conf->iface;
++	params->mbssid_index = hostapd_mbssid_get_bss_index(hapd);
++	params->mbssid_elem = elem;
++	params->mbssid_elem_len = end - elem;
++	params->mbssid_elem_count = elem_count;
++	params->mbssid_elem_offset = elem_offset;
++	if (iface->conf->mbssid == ENHANCED_MBSSID_ENABLED) {
++		params->ema = true;
++		*tailpos++ = WLAN_EID_EXTENSION;
++		*tailpos++ = 3;
++		*tailpos++ = WLAN_EID_EXT_MULTIPLE_BSSID_CONFIGURATION;
++		*tailpos++ = iface->num_bss;
++		*tailpos++ = params->mbssid_elem_count;
++		*eid = tailpos;
++	}
++
++	return 0;
++
++fail:
++	os_free(elem);
++	wpa_printf(MSG_ERROR, "MBSSID: Configuration failed");
++	return -1;
++}
++
++
+ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
+ 				   const struct ieee80211_mgmt *req,
+ 				   int is_p2p, size_t *resp_len,
+-				   bool bcast_probe_resp)
++				   bool bcast_probe_resp, const u8 *known_bss,
++				   u8 known_bss_len)
+ {
+ 	struct ieee80211_mgmt *resp;
+-	u8 *pos, *epos, *csa_pos;
++	u8 *pos, *epos, *csa_pos, *ext_cap_pos;
+ 	size_t buflen;
+ 
++	hapd = hostapd_mbssid_get_tx_bss(hapd);
++
+ #define MAX_PROBERESP_LEN 768
+ 	buflen = MAX_PROBERESP_LEN;
+ #ifdef CONFIG_WPS
+@@ -517,6 +579,8 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
+ 	}
+ #endif /* CONFIG_IEEE80211BE */
+ 
++	buflen += hostapd_eid_mbssid_len(hapd, WLAN_FC_STYPE_PROBE_RESP, NULL,
++					 known_bss, known_bss_len);
+ 	buflen += hostapd_eid_rnr_len(hapd, WLAN_FC_STYPE_PROBE_RESP);
+ 	buflen += hostapd_mbo_ie_len(hapd);
+ 	buflen += hostapd_eid_owe_trans_len(hapd);
+@@ -588,8 +652,16 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
+ 	pos = hostapd_eid_supported_op_classes(hapd, pos);
+ 	pos = hostapd_eid_ht_capabilities(hapd, pos);
+ 	pos = hostapd_eid_ht_operation(hapd, pos);
++	pos = hostapd_eid_mbssid(hapd, pos, epos, WLAN_FC_STYPE_PROBE_RESP, 0,
++				 NULL, known_bss, known_bss_len);
+ 
++	ext_cap_pos = pos;
+ 	pos = hostapd_eid_ext_capab(hapd, pos);
++	if (hapd->iconf->mbssid >= MBSSID_ENABLED && !known_bss_len)
++		ext_cap_pos[12] |= 0x01; /* Probe responses always include all
++					  * non-tx profiles except when a list
++					  * of known BSSes is included in the
++					  * probe request. */
+ 
+ 	pos = hostapd_eid_time_adv(hapd, pos);
+ 	pos = hostapd_eid_time_zone(hapd, pos);
+@@ -1153,16 +1225,23 @@ void handle_probe_req(struct hostapd_data *hapd,
+ 	}
+ #endif /* CONFIG_TESTING_OPTIONS */
+ 
++	/* Do not send probe response from a non-transmitting multiple BSSID
++	 * profile unless the probe request is directed at that paticular BSS */
++	if (hapd != hostapd_mbssid_get_tx_bss(hapd) && res != EXACT_SSID_MATCH)
++		return;
++
+ 	wpa_msg_ctrl(hapd->msg_ctx, MSG_INFO, RX_PROBE_REQUEST "sa=" MACSTR
+ 		     " signal=%d", MAC2STR(mgmt->sa), ssi_signal);
+ 
+ 	if (is_6ghz_op_class(hapd->iconf->op_class) &&
+ 	    is_broadcast_ether_addr(mgmt->da))
+ 		resp = hostapd_gen_probe_resp(hapd, NULL, elems.p2p != NULL,
+-					      &resp_len, true);
++					      &resp_len, false, elems.mbssid_known_bss,
++					      elems.mbssid_known_bss_len);
+ 	else
+ 		resp = hostapd_gen_probe_resp(hapd, mgmt, elems.p2p != NULL,
+-					      &resp_len, false);
++					      &resp_len, false, elems.mbssid_known_bss,
++					      elems.mbssid_known_bss_len);
+ 	if (resp == NULL)
+ 		return;
+ 
+@@ -1184,7 +1263,8 @@ void handle_probe_req(struct hostapd_data *hapd,
+ 				hapd->cs_c_off_ecsa_proberesp;
+ 	}
+ 
+-	ret = hostapd_drv_send_mlme(hapd, resp, resp_len, noack,
++	ret = hostapd_drv_send_mlme(hostapd_mbssid_get_tx_bss(hapd), resp,
++				    resp_len, noack,
+ 				    csa_offs_len ? csa_offs : NULL,
+ 				    csa_offs_len, 0);
+ 
+@@ -1231,7 +1311,7 @@ static u8 * hostapd_probe_resp_offloads(struct hostapd_data *hapd,
+ 			   "this");
+ 
+ 	/* Generate a Probe Response template for the non-P2P case */
+-	return hostapd_gen_probe_resp(hapd, NULL, 0, resp_len, false);
++	return hostapd_gen_probe_resp(hapd, NULL, 0, resp_len, false, NULL, 0);
+ }
+ 
+ #endif /* NEED_AP_MLME */
+@@ -1250,7 +1330,7 @@ static u8 * hostapd_unsol_bcast_probe_resp(struct hostapd_data *hapd,
+ 
+ 	return hostapd_gen_probe_resp(hapd, NULL, 0,
+ 				      &params->unsol_bcast_probe_resp_tmpl_len,
+-				      true);
++				      true, NULL, 0);
+ }
+ #endif /* CONFIG_IEEE80211AX */
+ 
+@@ -1533,8 +1613,12 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
+ 	size_t resp_len = 0;
+ #ifdef NEED_AP_MLME
+ 	u16 capab_info;
+-	u8 *pos, *tailpos, *tailend, *csa_pos;
++	u8 *pos, *tailpos, *tailend, *csa_pos, *ext_cap_pos;
++#endif /* NEED_AP_MLME */
+ 
++	os_memset(params, 0, sizeof(*params));
++
++#ifdef NEED_AP_MLME
+ #define BEACON_HEAD_BUF_SIZE 256
+ #define BEACON_TAIL_BUF_SIZE 512
+ 	head = os_zalloc(BEACON_HEAD_BUF_SIZE);
+@@ -1586,6 +1670,9 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
+ 	}
+ #endif /* CONFIG_IEEE80211BE */
+ 
++	if (hapd->iconf->mbssid == ENHANCED_MBSSID_ENABLED &&
++	    hapd == hostapd_mbssid_get_tx_bss(hapd))
++		tail_len += 5; /* Multiple BSSID Configuration element */
+ 	tail_len += hostapd_eid_rnr_len(hapd, WLAN_FC_STYPE_BEACON);
+ 	tail_len += hostapd_mbo_ie_len(hapd);
+ 	tail_len += hostapd_eid_owe_trans_len(hapd);
+@@ -1671,9 +1758,23 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
+ 	tailpos = hostapd_eid_supported_op_classes(hapd, tailpos);
+ 	tailpos = hostapd_eid_ht_capabilities(hapd, tailpos);
+ 	tailpos = hostapd_eid_ht_operation(hapd, tailpos);
+-
++	ext_cap_pos = tailpos;
+ 	tailpos = hostapd_eid_ext_capab(hapd, tailpos);
+ 
++	if (hapd->iconf->mbssid && hapd->iconf->num_bss > 1) {
++		if (ieee802_11_build_ap_params_mbssid(hapd, params, &tailpos)) {
++			os_free(head);
++			os_free(tail);
++			wpa_printf(MSG_ERROR, "Failed to set beacon data");
++			return -1;
++		} else if (hapd->iconf->mbssid == MBSSID_ENABLED ||
++			   (hapd->iconf->mbssid == ENHANCED_MBSSID_ENABLED &&
++			   params->mbssid_elem_count == 1)) {
++			/* Set the extended capability bit for "complete list
++			 * of non-tx profiles" */
++			ext_cap_pos[12] |= 0x01;
++		}
++	}
+ 	/*
+ 	 * TODO: Time Advertisement element should only be included in some
+ 	 * DTIM Beacon frames.
+@@ -1794,7 +1895,6 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
+ 	resp = hostapd_probe_resp_offloads(hapd, &resp_len);
+ #endif /* NEED_AP_MLME */
+ 
+-	os_memset(params, 0, sizeof(*params));
+ 	params->head = (u8 *) head;
+ 	params->head_len = head_len;
+ 	params->tail = tail;
+@@ -1897,6 +1997,10 @@ void ieee802_11_free_ap_params(struct wpa_driver_ap_params *params)
+ 	params->head = NULL;
+ 	os_free(params->proberesp);
+ 	params->proberesp = NULL;
++	os_free(params->mbssid_elem);
++	params->mbssid_elem = NULL;
++	os_free(params->mbssid_elem_offset);
++	params->mbssid_elem_offset = NULL;
+ #ifdef CONFIG_FILS
+ 	os_free(params->fd_frame_tmpl);
+ 	params->fd_frame_tmpl = NULL;
+diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
+index 42e8ed7..82cc155 100644
+--- a/src/ap/hostapd.c
++++ b/src/ap/hostapd.c
+@@ -91,6 +91,29 @@ int hostapd_for_each_interface(struct hapd_interfaces *interfaces,
+ }
+ 
+ 
++struct hostapd_data * hostapd_mbssid_get_tx_bss(struct hostapd_data *hapd)
++{
++	if (hapd->iconf->mbssid)
++		return hapd->iface->bss[0];
++
++	return hapd;
++}
++
++
++int hostapd_mbssid_get_bss_index(struct hostapd_data *hapd)
++{
++	if (hapd->iconf->mbssid) {
++		size_t i;
++
++		for (i = 1; i < hapd->iface->num_bss; i++)
++			if (hapd->iface->bss[i] == hapd)
++				return i;
++	}
++
++	return 0;
++}
++
++
+ void hostapd_reconfig_encryption(struct hostapd_data *hapd)
+ {
+ 	if (hapd->wpa_auth)
+@@ -1179,19 +1202,37 @@ static int db_table_create_radius_attributes(sqlite3 *db)
+ 
+ #endif /* CONFIG_NO_RADIUS */
+ 
++static int hostapd_start_beacon(struct hostapd_data *hapd)
++{
++	struct hostapd_bss_config *conf = hapd->conf;
++
++	if (!conf->start_disabled && ieee802_11_set_beacon(hapd) < 0)
++		return -1;
++
++	if (hapd->driver && hapd->driver->set_operstate)
++		hapd->driver->set_operstate(hapd->drv_priv, 1);
++
++	return 0;
++}
+ 
+ /**
+  * hostapd_setup_bss - Per-BSS setup (initialization)
+  * @hapd: Pointer to BSS data
+  * @first: Whether this BSS is the first BSS of an interface; -1 = not first,
+  *	but interface may exist
++ * @start_beacon: Whether beacons should be configured and transmission started
++ *	at this time. This is used when MBSSID IE is enabled where the
++ *	information regarding all BSSes should be retrieved before configuring
++ *	the beacons. The calling functions are responsible to configure the
++ *	beacon explicitly if this is set to 'false'.
+  *
+  * This function is used to initialize all per-BSS data structures and
+  * resources. This gets called in a loop for each BSS when an interface is
+  * initialized. Most of the modules that are initialized here will be
+  * deinitialized in hostapd_cleanup().
+  */
+-static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
++static int hostapd_setup_bss(struct hostapd_data *hapd, int first,
++			     bool start_beacon)
+ {
+ 	struct hostapd_bss_config *conf = hapd->conf;
+ 	u8 ssid[SSID_MAX_LEN + 1];
+@@ -1464,9 +1505,6 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
+ 		return -1;
+ 	}
+ 
+-	if (!conf->start_disabled && ieee802_11_set_beacon(hapd) < 0)
+-		return -1;
+-
+ 	if (flush_old_stations && !conf->start_disabled &&
+ 	    conf->broadcast_deauth) {
+ 		u8 addr[ETH_ALEN];
+@@ -1485,8 +1523,8 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
+ 	if (hapd->wpa_auth && wpa_init_keys(hapd->wpa_auth) < 0)
+ 		return -1;
+ 
+-	if (hapd->driver && hapd->driver->set_operstate)
+-		hapd->driver->set_operstate(hapd->drv_priv, 1);
++	if (start_beacon)
++		return hostapd_start_beacon(hapd);
+ 
+ 	hostapd_ubus_add_bss(hapd);
+ 
+@@ -2214,7 +2252,7 @@ static int hostapd_setup_interface_complete_sync(struct hostapd_iface *iface,
+ 		hapd = iface->bss[j];
+ 		if (j)
+ 			os_memcpy(hapd->own_addr, prev_addr, ETH_ALEN);
+-		if (hostapd_setup_bss(hapd, j == 0)) {
++		if (hostapd_setup_bss(hapd, j == 0, !iface->conf->mbssid)) {
+ 			for (;;) {
+ 				hapd = iface->bss[j];
+ 				hostapd_bss_deinit_no_free(hapd);
+@@ -2228,6 +2266,24 @@ static int hostapd_setup_interface_complete_sync(struct hostapd_iface *iface,
+ 		if (is_zero_ether_addr(hapd->conf->bssid))
+ 			prev_addr = hapd->own_addr;
+ 	}
++
++	if (hapd->iconf->mbssid) {
++		for (j = 0; j < iface->num_bss; j++) {
++			hapd = iface->bss[j];
++			if (hostapd_start_beacon(hapd)) {
++				for (;;) {
++					hapd = iface->bss[j];
++					hostapd_bss_deinit_no_free(hapd);
++					hostapd_free_hapd_data(hapd);
++					if (j == 0)
++						break;
++					j--;
++				}
++				goto fail;
++			}
++		}
++	}
++
+ 	hapd = iface->bss[0];
+ 
+ 	hostapd_tx_queue_params(iface);
+@@ -3130,7 +3186,7 @@ int hostapd_add_iface(struct hapd_interfaces *interfaces, char *buf)
+ 
+ 			if (start_ctrl_iface_bss(hapd) < 0 ||
+ 			    (hapd_iface->state == HAPD_IFACE_ENABLED &&
+-			     hostapd_setup_bss(hapd, -1))) {
++			     hostapd_setup_bss(hapd, -1, true))) {
+ 				hostapd_cleanup(hapd);
+ 				hapd_iface->bss[hapd_iface->num_bss - 1] = NULL;
+ 				hapd_iface->conf->num_bss--;
+diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h
+index 56d96a5..093c28a 100644
+--- a/src/ap/hostapd.h
++++ b/src/ap/hostapd.h
+@@ -660,6 +660,11 @@ struct hostapd_iface {
+ 	/* Previous WMM element information */
+ 	struct hostapd_wmm_ac_params prev_wmm[WMM_AC_NUM];
+ 
++	/* Maximum number of interfaces supported for MBSSID advertisements */
++	u8 mbssid_max_interfaces;
++	/* Maximum profile periodicity for enhanced MBSSID advertisements */
++	u8 ema_max_periodicity;
++
+ 	int (*enable_iface_cb)(struct hostapd_iface *iface);
+ 	int (*disable_iface_cb)(struct hostapd_iface *iface);
+ };
+@@ -762,5 +767,7 @@ void fst_hostapd_fill_iface_obj(struct hostapd_data *hapd,
+ #endif /* CONFIG_FST */
+ 
+ int hostapd_set_acl(struct hostapd_data *hapd);
++struct hostapd_data * hostapd_mbssid_get_tx_bss(struct hostapd_data *hapd);
++int hostapd_mbssid_get_bss_index(struct hostapd_data *hapd);
+ 
+ #endif /* HOSTAPD_H */
+diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
+index 098793e..30bfa30 100644
+--- a/src/ap/ieee802_11.c
++++ b/src/ap/ieee802_11.c
+@@ -165,6 +165,7 @@ u8 * hostapd_eid_ext_supp_rates(struct hostapd_data *hapd, u8 *eid)
+ 	int i, num, count;
+ 	int h2e_required;
+ 
++	hapd->conf->xrates_supported = 0;
+ 	if (hapd->iface->current_rates == NULL)
+ 		return eid;
+ 
+@@ -214,6 +215,7 @@ u8 * hostapd_eid_ext_supp_rates(struct hostapd_data *hapd, u8 *eid)
+ 			*pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_SAE_H2E_ONLY;
+ 	}
+ 
++	hapd->conf->xrates_supported = 1;
+ 	return pos;
+ }
+ 
+@@ -3979,6 +3981,23 @@ static void handle_auth(struct hostapd_data *hapd,
+ }
+ 
+ 
++static u8 hostapd_max_bssid_indicator(struct hostapd_data *hapd)
++{
++	size_t num_bss_nontx;
++	u8 max_bssid_ind = 0;
++
++	if (!hapd->iconf->mbssid || hapd->iface->num_bss <= 1)
++		return 0;
++
++	num_bss_nontx = hapd->iface->num_bss - 1;
++	while (num_bss_nontx > 0) {
++		max_bssid_ind++;
++		num_bss_nontx >>= 1;
++	}
++	return max_bssid_ind;
++}
++
++
+ int hostapd_get_aid(struct hostapd_data *hapd, struct sta_info *sta)
+ {
+ 	int i, j = 32, aid;
+@@ -4004,7 +4023,10 @@ int hostapd_get_aid(struct hostapd_data *hapd, struct sta_info *sta)
+ 	}
+ 	if (j == 32)
+ 		return -1;
+-	aid = i * 32 + j + 1;
++	aid = i * 32 + j;
++
++	aid += (1 << hostapd_max_bssid_indicator(hapd));
++
+ 	if (aid > 2007)
+ 		return -1;
+ 
+@@ -7579,4 +7601,256 @@ u8 * hostapd_eid_rnr(struct hostapd_data *hapd, u8 *eid, u32 type)
+ 	return eid;
+ }
+ 
++
++static size_t hostapd_eid_mbssid_elem_len(struct hostapd_data *hapd,
++					  u32 frame_type, size_t *bss_index,
++					  const u8 *known_bss,
++					  size_t known_bss_len)
++{
++	struct hostapd_data *tx_bss = hostapd_mbssid_get_tx_bss(hapd);
++	size_t len = 3, i;
++
++	for (i = *bss_index; i < hapd->iface->num_bss; i++) {
++		struct hostapd_data *bss = hapd->iface->bss[i];
++		const u8 *auth, *rsn = NULL, *rsnx = NULL;
++		size_t nontx_profile_len, auth_len;
++		u8 ie_count = 0;
++
++		if (known_bss && (known_bss_len > (i / 8))) {
++			known_bss = &known_bss[i / 8];
++			if (*known_bss & (u8)(BIT(i % 8)))
++				continue;
++		}
++
++		if (!bss || !bss->conf || !bss->started)
++			continue;
++
++		/*
++		 * Sublement ID: 1 byte
++		 * Length: 1 byte
++		 * Nontransmitted capabilities: 4 bytes
++		 * SSID element: 2 + variable
++		 * Multiple BSSID Index Element: 3 bytes (+2 bytes in beacons)
++		 * Fixed length = 1 + 1 + 4 + 2 + 3 = 11
++		 */
++		nontx_profile_len = 11 + bss->conf->ssid.ssid_len;
++
++		if (frame_type == WLAN_FC_STYPE_BEACON)
++			nontx_profile_len += 2;
++
++		auth = wpa_auth_get_wpa_ie(bss->wpa_auth, &auth_len);
++		if (auth) {
++			rsn = get_ie(auth, auth_len, WLAN_EID_RSN);
++			if (rsn)
++				nontx_profile_len += (2 + rsn[1]);
++
++			rsnx = get_ie(auth, auth_len, WLAN_EID_RSNX);
++			if (rsnx)
++				nontx_profile_len += (2 + rsnx[1]);
++		}
++		if (!rsn && hostapd_wpa_ie(tx_bss, WLAN_EID_RSN))
++			ie_count++;
++		if (!rsnx && hostapd_wpa_ie(tx_bss, WLAN_EID_RSNX))
++			ie_count++;
++		if (bss->conf->xrates_supported)
++			nontx_profile_len += 8;
++		else if (hapd->conf->xrates_supported)
++			ie_count++;
++		if (ie_count)
++			nontx_profile_len += (4 + ie_count);
++
++		if ((len + nontx_profile_len) > 255)
++			goto mbssid_too_big;
++
++		len += nontx_profile_len;
++	}
++
++mbssid_too_big:
++	*bss_index = i;
++	return len;
++}
++
++
++size_t hostapd_eid_mbssid_len(struct hostapd_data *hapd, u32 frame_type,
++			      u8 *elem_count, const u8 *known_bss,
++			      size_t known_bss_len)
++{
++	size_t len = 0, bss_index = 1;
++
++	if (!hapd->iconf->mbssid || hapd->iface->num_bss <= 1 ||
++	    (frame_type != WLAN_FC_STYPE_BEACON &&
++	     frame_type != WLAN_FC_STYPE_PROBE_RESP))
++		return 0;
++
++	if (frame_type == WLAN_FC_STYPE_BEACON) {
++		if (!elem_count) {
++			wpa_printf(MSG_ERROR,
++				   "MBSSID: Insufficient data for beacons");
++			return 0;
++		}
++		*elem_count = 0;
++	}
++
++	while (bss_index < hapd->iface->num_bss) {
++		len += hostapd_eid_mbssid_elem_len(hapd, frame_type,
++						   &bss_index, known_bss,
++						   known_bss_len);
++
++		if (frame_type == WLAN_FC_STYPE_BEACON)
++			*elem_count += 1;
++	}
++	return len;
++}
++
++
++static u8 * hostapd_eid_mbssid_elem(struct hostapd_data *hapd, u8 *eid, u8 *end,
++				    u32 frame_type, u8 max_bssid_indicator,
++				    size_t *bss_index, u8 elem_count,
++				    const u8 *known_bss, size_t known_bss_len)
++{
++	struct hostapd_data *tx_bss = hostapd_mbssid_get_tx_bss(hapd);
++	size_t i;
++	u8 *eid_len_offset, *max_bssid_indicator_offset;
++
++	*eid++ = WLAN_EID_MULTIPLE_BSSID;
++	eid_len_offset = eid++;
++	max_bssid_indicator_offset = eid++;
++
++	for (i = *bss_index; i < hapd->iface->num_bss; i++) {
++		struct hostapd_data *bss = hapd->iface->bss[i];
++		struct hostapd_bss_config *conf;
++		u8 *eid_len_pos, *nontx_bss_start = eid;
++		const u8 *auth, *rsn = NULL, *rsnx = NULL;
++		u8 ie_count = 0, non_inherit_ie[3];
++		size_t auth_len = 0;
++		u16 capab_info;
++
++		if (known_bss && (known_bss_len > (i / 8))) {
++			known_bss = &known_bss[i / 8];
++			if (*known_bss & (u8)(BIT(i % 8)))
++				continue;
++		}
++
++		if (!bss || !bss->conf || !bss->started)
++			continue;
++		conf = bss->conf;
++
++		*eid++ = WLAN_EID_SUBELEMENT_NONTRANSMITTED_BSSID_PROFILE;
++		eid_len_pos = eid++;
++
++		*eid++ = WLAN_EID_NONTRANSMITTED_BSSID_CAPA;
++		*eid++ = sizeof(capab_info);
++		capab_info = host_to_le16(hostapd_own_capab_info(bss));
++		os_memcpy(eid, (const void *)&capab_info, sizeof(capab_info));
++		eid += sizeof(capab_info);
++
++		*eid++ = WLAN_EID_SSID;
++		*eid++ = conf->ssid.ssid_len;
++		os_memcpy(eid, conf->ssid.ssid, conf->ssid.ssid_len);
++		eid += conf->ssid.ssid_len;
++
++		*eid++ = WLAN_EID_MULTIPLE_BSSID_INDEX;
++		if (frame_type == WLAN_FC_STYPE_BEACON) {
++			*eid++ = 3;
++			*eid++ = i;
++			if (hapd->iconf->mbssid == ENHANCED_MBSSID_ENABLED &&
++			    (conf->dtim_period % elem_count))
++				conf->dtim_period = elem_count;
++			*eid++ = conf->dtim_period;
++			*eid++ = 0xFF;
++		} else {
++			*eid++ = 1;
++			*eid++ = i;
++		}
++
++		auth = wpa_auth_get_wpa_ie(bss->wpa_auth, &auth_len);
++		if (auth) {
++			rsn = get_ie(auth, auth_len, WLAN_EID_RSN);
++			if (rsn) {
++				os_memcpy(eid, rsn, 2 + rsn[1]);
++				eid += (2 + rsn[1]);
++			}
++
++			rsnx = get_ie(auth, auth_len, WLAN_EID_RSNX);
++			if (rsnx) {
++				os_memcpy(eid, rsnx, 2 + rsnx[1]);
++				eid += (2 + rsnx[1]);
++			}
++		}
++		if (!rsn && hostapd_wpa_ie(tx_bss, WLAN_EID_RSN)) {
++			non_inherit_ie[ie_count] = WLAN_EID_RSN;
++			ie_count++;
++		}
++		if (!rsnx && hostapd_wpa_ie(tx_bss, WLAN_EID_RSNX)) {
++			non_inherit_ie[ie_count] = WLAN_EID_RSNX;
++			ie_count++;
++		}
++		if (hapd->conf->xrates_supported &&
++		    !bss->conf->xrates_supported) {
++			non_inherit_ie[ie_count] = WLAN_EID_EXT_SUPP_RATES;
++			ie_count++;
++		}
++		if (ie_count) {
++			*eid++ = WLAN_EID_EXTENSION;
++			*eid++ = 2 + ie_count;
++			*eid++ = WLAN_EID_EXT_NON_INHERITANCE;
++			*eid++ = ie_count;
++			os_memcpy(eid, non_inherit_ie, ie_count);
++			eid += ie_count;
++		}
++
++		*eid_len_pos = (eid - eid_len_pos) - 1;
++
++		if (((eid - eid_len_offset) - 1) > 255) {
++			eid = nontx_bss_start;
++			goto mbssid_too_big;
++		}
++	}
++
++mbssid_too_big:
++	*bss_index = i;
++	*max_bssid_indicator_offset = max_bssid_indicator;
++	if (*max_bssid_indicator_offset < 1)
++		*max_bssid_indicator_offset = 1;
++	*eid_len_offset = (eid - eid_len_offset) - 1;
++	return eid;
++}
++
++
++u8 * hostapd_eid_mbssid(struct hostapd_data *hapd, u8 *eid, u8 *end,
++			u32 frame_type, u8 elem_count, u8 **elem_offset,
++			const u8 *known_bss, size_t known_bss_len)
++{
++	size_t bss_index = 1;
++	u8 elem_index = 0;
++
++	if (!hapd->iconf->mbssid || hapd->iface->num_bss <= 1 ||
++	    (frame_type != WLAN_FC_STYPE_BEACON &&
++	     frame_type != WLAN_FC_STYPE_PROBE_RESP))
++		return eid;
++
++	if (frame_type == WLAN_FC_STYPE_BEACON && !elem_offset) {
++		wpa_printf(MSG_ERROR, "MBSSID: Insufficient data for beacons");
++		return eid;
++	}
++
++	while (bss_index < hapd->iface->num_bss) {
++		if (frame_type == WLAN_FC_STYPE_BEACON) {
++			if (elem_index == elem_count) {
++				wpa_printf(MSG_WARNING,
++					   "MBSSID: More number of elements than provided array");
++				break;
++			}
++
++			elem_offset[elem_index] = eid;
++			elem_index = elem_index + 1;
++		}
++		eid = hostapd_eid_mbssid_elem(hapd, eid, end, frame_type,
++					      hostapd_max_bssid_indicator(hapd),
++					      &bss_index, elem_count,
++					      known_bss, known_bss_len);
++	}
++	return eid;
++}
++
+ #endif /* CONFIG_NATIVE_WINDOWS */
+diff --git a/src/ap/ieee802_11.h b/src/ap/ieee802_11.h
+index fa1f47b..bb454bb 100644
+--- a/src/ap/ieee802_11.h
++++ b/src/ap/ieee802_11.h
+@@ -214,5 +214,10 @@ u16 copy_sta_eht_capab(struct hostapd_data *hapd, struct sta_info *sta,
+ 		       enum ieee80211_op_mode opmode,
+ 		       const u8 *he_capab, size_t he_capab_len,
+ 		       const u8 *eht_capab, size_t eht_capab_len);
+-
++size_t hostapd_eid_mbssid_len(struct hostapd_data *hapd, u32 frame_type,
++			      u8 *elem_count, const u8 *known_bss,
++			      size_t known_bss_len);
++u8 * hostapd_eid_mbssid(struct hostapd_data *hapd, u8 *eid, u8 *end,
++			u32 frame_type, u8 elem_count, u8 **elem_offset,
++			const u8 *known_bss, size_t known_bss_len);
+ #endif /* IEEE802_11_H */
+diff --git a/src/ap/ieee802_11_shared.c b/src/ap/ieee802_11_shared.c
+index 4f85d78..7f5b475 100644
+--- a/src/ap/ieee802_11_shared.c
++++ b/src/ap/ieee802_11_shared.c
+@@ -364,6 +364,8 @@ static void hostapd_ext_capab_byte(struct hostapd_data *hapd, u8 *pos, int idx)
+ 			*pos |= 0x02; /* Bit 17 - WNM-Sleep Mode */
+ 		if (hapd->conf->bss_transition)
+ 			*pos |= 0x08; /* Bit 19 - BSS Transition */
++		if (hapd->iconf->mbssid)
++			*pos |= 0x40; /* Bit 22 - Multiple BSSID */
+ 		break;
+ 	case 3: /* Bits 24-31 */
+ #ifdef CONFIG_WNM_AP
+@@ -436,6 +438,8 @@ static void hostapd_ext_capab_byte(struct hostapd_data *hapd, u8 *pos, int idx)
+ 		    (hapd->iface->drv_flags &
+ 		     WPA_DRIVER_FLAGS_BEACON_PROTECTION))
+ 			*pos |= 0x10; /* Bit 84 - Beacon Protection Enabled */
++		if (hapd->iconf->mbssid == ENHANCED_MBSSID_ENABLED)
++			*pos |= 0x08; /* Bit 83 - Enhanced multiple BSSID */
+ 		break;
+ 	case 11: /* Bits 88-95 */
+ #ifdef CONFIG_SAE_PK
+@@ -471,6 +475,13 @@ u8 * hostapd_eid_ext_capab(struct hostapd_data *hapd, u8 *eid)
+ 			*pos &= ~hapd->conf->ext_capa_mask[i];
+ 			*pos |= hapd->conf->ext_capa[i];
+ 		}
++
++		/* Clear bits 83 and 22 if EMA and MBSSID are not enabled
++		 * otherwise association fails with some clients */
++		if (i == 10 && hapd->iconf->mbssid < ENHANCED_MBSSID_ENABLED)
++			*pos &= ~0x08;
++		if (i == 2 && !hapd->iconf->mbssid)
++			*pos &= ~0x40;
+ 	}
+ 
+ 	while (len > 0 && eid[1 + len] == 0) {
+diff --git a/src/common/ieee802_11_common.c b/src/common/ieee802_11_common.c
+index c8ee90c..2fab7c3 100644
+--- a/src/common/ieee802_11_common.c
++++ b/src/common/ieee802_11_common.c
+@@ -315,6 +315,10 @@ static int ieee802_11_parse_extension(const u8 *pos, size_t elen,
+ 		elems->eht_operation = pos;
+ 		elems->eht_operation_len = elen;
+ 		break;
++	case WLAN_EID_EXT_KNOWN_BSSID:
++		elems->mbssid_known_bss = pos;
++		elems->mbssid_known_bss_len = elen;
++		break;
+ 	default:
+ 		if (show_errors) {
+ 			wpa_printf(MSG_MSGDUMP,
+diff --git a/src/common/ieee802_11_common.h b/src/common/ieee802_11_common.h
+index 94e1d7b..1e4e27d 100644
+--- a/src/common/ieee802_11_common.h
++++ b/src/common/ieee802_11_common.h
+@@ -119,6 +119,7 @@ struct ieee802_11_elems {
+ 	const u8 *pasn_params;
+ 	const u8 *eht_capabilities;
+ 	const u8 *eht_operation;
++	const u8 *mbssid_known_bss;
+ 
+ 	u8 ssid_len;
+ 	u8 supp_rates_len;
+@@ -176,6 +177,8 @@ struct ieee802_11_elems {
+ 	u8 eht_capabilities_len;
+ 	u8 eht_operation_len;
+ 
++	u8 mbssid_known_bss_len;
++
+ 	struct mb_ies_info mb_ies;
+ 	struct frag_ies_info frag_ies;
+ };
+diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h
+index 62088bd..0bbbca9 100644
+--- a/src/common/ieee802_11_defs.h
++++ b/src/common/ieee802_11_defs.h
+@@ -481,6 +481,9 @@
+ #define WLAN_EID_EXT_SPATIAL_REUSE 39
+ #define WLAN_EID_EXT_COLOR_CHANGE_ANNOUNCEMENT 42
+ #define WLAN_EID_EXT_OCV_OCI 54
++#define WLAN_EID_EXT_MULTIPLE_BSSID_CONFIGURATION 55
++#define WLAN_EID_EXT_NON_INHERITANCE 56
++#define WLAN_EID_EXT_KNOWN_BSSID 57
+ #define WLAN_EID_EXT_SHORT_SSID_LIST 58
+ #define WLAN_EID_EXT_HE_6GHZ_BAND_CAP 59
+ #define WLAN_EID_EXT_EDMG_CAPABILITIES 61
+@@ -497,6 +500,8 @@
+ #define WLAN_EID_EXT_MULTI_LINK_TRAFFIC_INDICATION 110
+ #define WLAN_EID_EXT_AKM_SUITE_SELECTOR 114
+ 
++#define WLAN_EID_SUBELEMENT_NONTRANSMITTED_BSSID_PROFILE 0
++
+ /* Extended Capabilities field */
+ #define WLAN_EXT_CAPAB_20_40_COEX 0
+ #define WLAN_EXT_CAPAB_GLK 1
+diff --git a/src/drivers/driver.h b/src/drivers/driver.h
+index 82daef0..36f465c 100644
+--- a/src/drivers/driver.h
++++ b/src/drivers/driver.h
+@@ -1633,6 +1633,43 @@ struct wpa_driver_ap_params {
+ 	 * ibf_enable=<val>
+ 	 */
+ 	u8 ibf_enable;
++
++	/**
++	 * mbssid_tx_iface - Transmitting interface of the MBSSID set
++	 */
++	const char *mbssid_tx_iface;
++
++	/**
++	 * mbssid_index - The index of this BSS in the MBSSID set
++	 */
++	unsigned int mbssid_index;
++
++	/**
++	 * mbssid_elem - Buffer containing all MBSSID elements
++	 */
++	u8 *mbssid_elem;
++
++	/**
++	 * mbssid_elem_len - Total length of all MBSSID elements
++	 */
++	size_t mbssid_elem_len;
++
++	/**
++	 * mbssid_elem_count - The number of MBSSID elements
++	 */
++	u8 mbssid_elem_count;
++
++	/**
++	 * mbssid_elem_offset - Offsets to elements in mbssid_elem.
++	 * Kernel will use these offsets to generate multiple BSSID beacons.
++	 */
++	u8 **mbssid_elem_offset;
++
++	/**
++	 * ema - Enhanced MBSSID advertisements support.
++	 */
++	bool ema;
++
+ };
+ 
+ struct wpa_driver_mesh_bss_params {
+@@ -2197,6 +2234,11 @@ struct wpa_driver_capa {
+ 
+ 	/* Maximum number of supported CSA counters */
+ 	u16 max_csa_counters;
++
++	/* Maximum number of interfaces supported for MBSSID advertisements */
++	u8 mbssid_max_interfaces;
++	/* Maximum profile periodicity for enhanced MBSSID advertisements */
++	u8 ema_max_periodicity;
+ };
+ 
+ 
+diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
+index 6c65901..3753409 100644
+--- a/src/drivers/driver_nl80211.c
++++ b/src/drivers/driver_nl80211.c
+@@ -4540,6 +4540,55 @@ static int nl80211_unsol_bcast_probe_resp(struct i802_bss *bss,
+ 	nla_nest_end(msg, attr);
+ 	return 0;
+ }
++
++
++static int nl80211_mbssid(struct nl_msg *msg,
++			 struct wpa_driver_ap_params *params)
++{
++	struct nlattr *config, *elems;
++	int ifidx;
++
++	if (!params->mbssid_tx_iface)
++		return 0;
++
++	config = nla_nest_start(msg, NL80211_ATTR_MBSSID_CONFIG);
++	if (!config)
++		return -1;
++
++	nla_put_u8(msg, NL80211_MBSSID_CONFIG_ATTR_INDEX, params->mbssid_index);
++	if (params->mbssid_tx_iface) {
++		ifidx = if_nametoindex(params->mbssid_tx_iface);
++		if (ifidx <= 0)
++			return -1;
++		nla_put_u32(msg,
++			    NL80211_MBSSID_CONFIG_ATTR_TX_IFINDEX,
++			    ifidx);
++	}
++
++	if (params->ema)
++		nla_put_flag(msg, NL80211_MBSSID_CONFIG_ATTR_EMA);
++
++	nla_nest_end(msg, config);
++
++	if (params->mbssid_elem_count && params->mbssid_elem_len &&
++	    params->mbssid_elem_offset && *params->mbssid_elem_offset) {
++		u8 i, **offs = params->mbssid_elem_offset;
++
++		elems = nla_nest_start(msg, NL80211_ATTR_MBSSID_ELEMS);
++		if (!elems)
++			return -1;
++
++		for (i = 0; i < params->mbssid_elem_count - 1; i++)
++			nla_put(msg, i + 1, offs[i + 1] - offs[i], offs[i]);
++
++		nla_put(msg, i + 1,
++			*offs + params->mbssid_elem_len - offs[i],
++			offs[i]);
++
++		nla_nest_end(msg, elems);
++	}
++	return 0;
++}
+ #endif /* CONFIG_IEEE80211AX */
+ 
+ 
+@@ -4838,6 +4887,9 @@ static int wpa_driver_nl80211_set_ap(void *priv,
+ 	if (params->unsol_bcast_probe_resp_interval &&
+ 	    nl80211_unsol_bcast_probe_resp(bss, msg, params) < 0)
+ 		goto fail;
++
++	if (nl80211_mbssid(msg, params) < 0)
++		goto fail;
+ #endif /* CONFIG_IEEE80211AX */
+ 
+ #ifdef CONFIG_SAE
+diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c
+index 06a52db..d8078bc 100644
+--- a/src/drivers/driver_nl80211_capa.c
++++ b/src/drivers/driver_nl80211_capa.c
+@@ -857,6 +857,30 @@ err:
+ }
+ 
+ 
++static void wiphy_info_mbssid(struct wpa_driver_capa *cap, struct nlattr *attr)
++{
++	struct nlattr *config[NL80211_MBSSID_CONFIG_ATTR_MAX + 1];
++
++	if (nla_parse_nested(config, NL80211_MBSSID_CONFIG_ATTR_MAX, attr,
++			     NULL))
++		return;
++
++	if (!config[NL80211_MBSSID_CONFIG_ATTR_MAX_INTERFACES])
++		return;
++
++	cap->mbssid_max_interfaces =
++		nla_get_u8(config[NL80211_MBSSID_CONFIG_ATTR_MAX_INTERFACES]);
++
++	if (config[NL80211_MBSSID_CONFIG_ATTR_MAX_EMA_PROFILE_PERIODICITY])
++		cap->ema_max_periodicity =
++		nla_get_u8(config[NL80211_MBSSID_CONFIG_ATTR_MAX_EMA_PROFILE_PERIODICITY]);
++
++	wpa_printf(MSG_DEBUG,
++		   "multiple_bssid: max interfaces %u, max profile periodicity %u\n",
++		   cap->mbssid_max_interfaces, cap->ema_max_periodicity);
++}
++
++
+ static int wiphy_info_handler(struct nl_msg *msg, void *arg)
+ {
+ 	struct nlattr *tb[NL80211_ATTR_MAX + 1];
+@@ -1106,6 +1130,9 @@ static int wiphy_info_handler(struct nl_msg *msg, void *arg)
+ 	if (tb[NL80211_ATTR_WIPHY_SELF_MANAGED_REG])
+ 		capa->flags |= WPA_DRIVER_FLAGS_SELF_MANAGED_REGULATORY;
+ 
++	if (tb[NL80211_ATTR_MBSSID_CONFIG])
++		wiphy_info_mbssid(capa, tb[NL80211_ATTR_MBSSID_CONFIG]);
++
+ 	return NL_SKIP;
+ }
+ 
+-- 
+2.18.0
+
diff --git a/recipes-wifi/wpa-supplicant/files/patches-2.10.3/patches.inc b/recipes-wifi/wpa-supplicant/files/patches-2.10.3/patches.inc
index 78d5240..5e6bf88 100644
--- a/recipes-wifi/wpa-supplicant/files/patches-2.10.3/patches.inc
+++ b/recipes-wifi/wpa-supplicant/files/patches-2.10.3/patches.inc
@@ -78,8 +78,11 @@
     file://mtk-0014-hostapd-mtk-Add-the-broadcast-destination-address-of.patch \
     file://mtk-0015-hostapd-mtk-Add-vendor-command-attribute-for-RTS-BW-.patch \
     file://mtk-0016-hostapd-mtk-6G-band-does-not-require-DFS.patch \
+    file://mtk-0016-hostapd-mtk-Add-available-color-bitmap.patch \
     file://mtk-0017-hostapd-mtk-Fix-sending-wrong-VHT-operation-IE-in-CS.patch \
     file://mtk-0018-hostapd-mtk-Add-sta-assisted-DFS-state-update-mechan.patch \
     file://mtk-0019-hostapd-mtk-Fix-auto-ht-issue-when-switching-to-DFS-.patch \
+    file://mtk-0020-hostapd-mtk-Mark-DFS-channel-as-available-for-CSA.patch \
+    file://mtk-0020-hostapd-mtk-add-11v_mbss-and-ema-support.patch \
     file://mtk-0100-hostapd-mtk-update-eht-operation-elem.patch \
     "
diff --git a/recipes-wifi/wpa-supplicant/files/patches/mtk-0010-hostapd-mtk-Add-DFS-detection-mode.patch b/recipes-wifi/wpa-supplicant/files/patches/mtk-0010-hostapd-mtk-Add-DFS-detection-mode.patch
index 2ceb639..7ec986a 100644
--- a/recipes-wifi/wpa-supplicant/files/patches/mtk-0010-hostapd-mtk-Add-DFS-detection-mode.patch
+++ b/recipes-wifi/wpa-supplicant/files/patches/mtk-0010-hostapd-mtk-Add-DFS-detection-mode.patch
@@ -63,7 +63,7 @@
  					      char *buf, char *reply,
  					      int reply_size,
 @@ -4081,6 +4101,9 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
- 		reply_len = hostapd_ctrl_iface_get_hemu(hapd, reply, reply_size);
+ 		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) {
diff --git a/recipes-wifi/wpa-supplicant/files/patches/mtk-0016-hostapd-mtk-Add-available-color-bitmap.patch b/recipes-wifi/wpa-supplicant/files/patches/mtk-0016-hostapd-mtk-Add-available-color-bitmap.patch
new file mode 100644
index 0000000..9bbbf87
--- /dev/null
+++ b/recipes-wifi/wpa-supplicant/files/patches/mtk-0016-hostapd-mtk-Add-available-color-bitmap.patch
@@ -0,0 +1,337 @@
+From e7790a1bceca6b7612f29b00c429cf23f5dd9e3a 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] 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      | 66 +++++++++++++++++++++++++++
+ src/drivers/driver_nl80211.h      |  1 +
+ src/drivers/driver_nl80211_capa.c |  3 ++
+ 9 files changed, 192 insertions(+), 1 deletion(-)
+
+diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
+index 0ad8451..b0d5ded 100644
+--- a/hostapd/ctrl_iface.c
++++ b/hostapd/ctrl_iface.c
+@@ -3635,6 +3635,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,
+@@ -4202,6 +4272,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 30b3392..b6cf52e 100644
+--- a/hostapd/hostapd_cli.c
++++ b/hostapd/hostapd_cli.c
+@@ -1578,6 +1578,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[])
+ {
+@@ -1795,6 +1809,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 1a82f23..decffdd 100644
+--- a/src/ap/ap_drv_ops.c
++++ b/src/ap/ap_drv_ops.c
+@@ -1091,4 +1091,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 4406666..61c1360 100644
+--- a/src/ap/ap_drv_ops.h
++++ b/src/ap/ap_drv_ops.h
+@@ -149,6 +149,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 0999ea9..f2afb2e 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 {
+@@ -252,6 +253,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 b07aaf3..266c630 100644
+--- a/src/drivers/driver.h
++++ b/src/drivers/driver.h
+@@ -4736,6 +4736,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 6702384..c8771f7 100644
+--- a/src/drivers/driver_nl80211.c
++++ b/src/drivers/driver_nl80211.c
+@@ -12433,6 +12433,71 @@ static int nl80211_dpp_listen(void *priv, bool enable)
+ }
+ #endif /* CONFIG_DPP */
+ 
++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;
++}
+ 
+ #ifdef CONFIG_TESTING_OPTIONS
+ 
+@@ -13073,4 +13138,5 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
+ 	.start_disabled = nl80211_start_disabled,
+ 	.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 e570224..b90c8fa 100644
+--- a/src/drivers/driver_nl80211.h
++++ b/src/drivers/driver_nl80211.h
+@@ -186,6 +186,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 fcfa68b..c3c7b41 100644
+--- a/src/drivers/driver_nl80211_capa.c
++++ b/src/drivers/driver_nl80211_capa.c
+@@ -1068,6 +1068,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.39.0
+
diff --git a/recipes-wifi/wpa-supplicant/files/patches/mtk-0020-hostapd-mtk-Mark-DFS-channel-as-available-for-CSA.patch b/recipes-wifi/wpa-supplicant/files/patches/mtk-0020-hostapd-mtk-Mark-DFS-channel-as-available-for-CSA.patch
new file mode 100644
index 0000000..1fe5c88
--- /dev/null
+++ b/recipes-wifi/wpa-supplicant/files/patches/mtk-0020-hostapd-mtk-Mark-DFS-channel-as-available-for-CSA.patch
@@ -0,0 +1,60 @@
+From 3e9500a42a41e8cd7c2d7bc20aba96e1e17161fb 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] 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 c33b7a4..9ba6992 100644
+--- a/hostapd/ctrl_iface.c
++++ b/hostapd/ctrl_iface.c
+@@ -2704,6 +2704,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 0da18e2..6231e51 100644
+--- a/hostapd/hostapd_cli.c
++++ b/hostapd/hostapd_cli.c
+@@ -1693,7 +1693,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 18bae5c..2fae590 100644
+--- a/src/ap/ctrl_iface_ap.c
++++ b/src/ap/ctrl_iface_ap.c
+@@ -938,6 +938,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
+ 
+-- 
+2.18.0
+
diff --git a/recipes-wifi/wpa-supplicant/files/patches/mtk-0020-hostapd-mtk-add-11v_mbss-and-ema-support.patch b/recipes-wifi/wpa-supplicant/files/patches/mtk-0020-hostapd-mtk-add-11v_mbss-and-ema-support.patch
new file mode 100644
index 0000000..8d59a0f
--- /dev/null
+++ b/recipes-wifi/wpa-supplicant/files/patches/mtk-0020-hostapd-mtk-add-11v_mbss-and-ema-support.patch
@@ -0,0 +1,1175 @@
+From 8cbdb9a59e3bbe8804f909b13ce6df6e2777c3da Mon Sep 17 00:00:00 2001
+From: mtk20656 <chank.chen@mediatek.com>
+Date: Thu, 2 Mar 2023 10:51:43 +0800
+Subject: [PATCH] hostapd: mtk: add 11v_mbss and ema support for hostapd
+
+Signed-off-by: mtk20656 <chank.chen@mediatek.com>
+---
+ hostapd/config_file.c             |   9 +
+ hostapd/hostapd.conf              |  58 +++++++
+ hostapd/main.c                    |   3 +
+ src/ap/ap_config.c                |  12 ++
+ src/ap/ap_config.h                |   6 +
+ src/ap/beacon.c                   | 124 ++++++++++++--
+ src/ap/hostapd.c                  |  72 +++++++-
+ src/ap/hostapd.h                  |   7 +
+ src/ap/ieee802_11.c               | 276 +++++++++++++++++++++++++++++-
+ src/ap/ieee802_11.h               |   7 +-
+ src/ap/ieee802_11_shared.c        |  11 ++
+ src/common/ieee802_11_common.c    |   4 +
+ src/common/ieee802_11_common.h    |   3 +
+ src/common/ieee802_11_defs.h      |   5 +
+ src/drivers/driver.h              |  42 +++++
+ src/drivers/driver_nl80211.c      |  52 ++++++
+ src/drivers/driver_nl80211_capa.c |  27 +++
+ 17 files changed, 698 insertions(+), 20 deletions(-)
+
+diff --git a/hostapd/config_file.c b/hostapd/config_file.c
+index 649618b..3f26191 100644
+--- a/hostapd/config_file.c
++++ b/hostapd/config_file.c
+@@ -3663,6 +3663,15 @@ static int hostapd_config_fill(struct hostapd_config *conf,
+ 			return 1;
+ 		}
+ 		bss->unsol_bcast_probe_resp_interval = val;
++	} else if (os_strcmp(buf, "mbssid") == 0) {
++		int mbssid = atoi(pos);
++		if (mbssid < 0 || mbssid > ENHANCED_MBSSID_ENABLED) {
++			wpa_printf(MSG_ERROR,
++				   "Line %d: invalid mbssid (%d): '%s'.",
++				   line, mbssid, pos);
++			return 1;
++		}
++		conf->mbssid = mbssid;
+ 	} else if (os_strcmp(buf, "mu_onoff") == 0) {
+ 		int val = atoi(pos);
+ 		if (val < 0 || val > 15) {
+diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf
+index e3a5eb3..f926029 100644
+--- a/hostapd/hostapd.conf
++++ b/hostapd/hostapd.conf
+@@ -3123,3 +3123,61 @@ own_ip_addr=127.0.0.1
+ #bss=wlan0_1
+ #bssid=00:13:10:95:fe:0b
+ # ...
++#
++# Multiple BSSID Advertisement in 802.11ax
++# IEEE Std 802.11ax-2021 added a feature where instead of multiple interfaces
++# on a common radio transmitting individual beacons, those can form a set with
++# a common beacon is transmitted for all. The interface which is brought up
++# first is called as the transmitting profile of the MBSSID set which transmits
++# the beacons. The remaining interfaces are called as the non-transmitting
++# profiles and these are advertised inside the multiple BSSID element in the
++# beacons and probe response frames.
++# The transmitting interface is visible to all clients in the vicinity, however
++# the clients which do not support parsing of the multiple BSSID element will
++# not be able to connect to the non-transmitting interfaces.
++#
++# Enhanced Multiple BSSID Advertisements (EMA)
++# When enabled, the non-transmitting interfaces are split into multiple
++# beacons. The number of beacons required to cover all the non-transmitting
++# profiles is called as the profile periodicity.
++#
++# Refer to IEEE Std 802.11-2020 for details regarding the procedure and
++# required MAC address assignment.
++#
++# Following configuration is per radio.
++# 0 = Disabled (Default)
++# 1 = Multiple BSSID advertisements enabled.
++# 2 = Enhanced multiple BSSID advertisements enabled.
++#mbssid=0
++#
++# The transmitting interface should be added with 'interface' option while
++# the non-transmitting interfaces should be added using 'bss' option.
++# Security configuration should be added separately per interface, if required.
++#
++# Example:
++#mbssid=2
++#interface=wlan2
++#ctrl_interface=/var/run/hostapd
++#wpa_passphrase=0123456789
++#ieee80211w=2
++#sae_pwe=1
++#auth_algs=1
++#wpa=2
++#wpa_pairwise=CCMP
++#ssid=<SSID-0>
++#bridge=br-lan
++#wpa_key_mgmt=SAE
++#bssid=00:03:7f:12:84:84
++#
++#bss=wlan2-1
++#ctrl_interface=/var/run/hostapd
++#wpa_passphrase=0123456789
++#ieee80211w=2
++#sae_pwe=1
++#auth_algs=1
++#wpa=2
++#wpa_pairwise=CCMP
++#ssid=<SSID-1>
++#bridge=br-lan
++#wpa_key_mgmt=SAE
++#bssid=00:03:7f:12:84:85
+diff --git a/hostapd/main.c b/hostapd/main.c
+index 70a4b32..1b6474a 100644
+--- a/hostapd/main.c
++++ b/hostapd/main.c
+@@ -253,6 +253,9 @@ static int hostapd_driver_init(struct hostapd_iface *iface)
+ 				wpa_printf(MSG_ERROR, "set_wowlan failed");
+ 		}
+ 		os_free(triggs);
++
++		iface->mbssid_max_interfaces = capa.mbssid_max_interfaces;
++		iface->ema_max_periodicity = capa.ema_max_periodicity;
+ 	}
+ 
+ 	return 0;
+diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
+index 4e46a62..7d9d5cb 100644
+--- a/src/ap/ap_config.c
++++ b/src/ap/ap_config.c
+@@ -1462,6 +1462,12 @@ static int hostapd_config_check_bss(struct hostapd_bss_config *bss,
+ 	}
+ #endif /* CONFIG_IEEE80211BE */
+ 
++	if (full_config && bss->ignore_broadcast_ssid && conf->mbssid) {
++		wpa_printf(MSG_ERROR,
++			   "Hidden SSID is not suppored when MBSSID is enabled");
++		return -1;
++	}
++
+ 	return 0;
+ }
+ 
+@@ -1545,6 +1551,12 @@ int hostapd_config_check(struct hostapd_config *conf, int full_config)
+ 	}
+ #endif /* CONFIG_IEEE80211BE */
+ 
++	if (full_config && conf->mbssid && !conf->ieee80211ax) {
++		wpa_printf(MSG_ERROR,
++			   "Cannot enable multiple BSSID support without ieee80211ax");
++		return -1;
++	}
++
+ 	for (i = 0; i < conf->num_bss; i++) {
+ 		if (hostapd_config_check_bss(conf->bss[i], conf, full_config))
+ 			return -1;
+diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
+index 7aeb176..51476b8 100644
+--- a/src/ap/ap_config.h
++++ b/src/ap/ap_config.h
+@@ -923,6 +923,8 @@ struct hostapd_bss_config {
+ 	u8 ext_capa[EXT_CAPA_MAX_LEN];
+ 
+ 	u8 rnr;
++
++	bool xrates_supported;
+ };
+ 
+ /**
+@@ -1163,6 +1165,10 @@ struct hostapd_config {
+ 	u8 ibf_enable;
+ 	u8 dfs_detect_mode;
+ 	u8 amsdu;
++
++#define MBSSID_ENABLED          1
++#define ENHANCED_MBSSID_ENABLED 2
++	u8 mbssid;
+ };
+ 
+ enum three_wire_mode {
+diff --git a/src/ap/beacon.c b/src/ap/beacon.c
+index f3ea5c2..51db23a 100644
+--- a/src/ap/beacon.c
++++ b/src/ap/beacon.c
+@@ -462,15 +462,77 @@ static u8 * hostapd_eid_supported_op_classes(struct hostapd_data *hapd, u8 *eid)
+ }
+ 
+ 
++static int ieee802_11_build_ap_params_mbssid(struct hostapd_data *hapd,
++					     struct wpa_driver_ap_params *params,
++					     u8 **eid)
++{
++	struct hostapd_iface *iface = hapd->iface;
++	struct hostapd_data *tx_bss;
++	size_t len;
++	u8 elem_count = 0, *elem = NULL, **elem_offset = NULL, *end;
++	u8 *tailpos = *eid;
++
++	if (!iface->mbssid_max_interfaces ||
++	    iface->num_bss > iface->mbssid_max_interfaces ||
++	    (iface->conf->mbssid == ENHANCED_MBSSID_ENABLED &&
++	     !iface->ema_max_periodicity))
++		goto fail;
++
++	tx_bss = hostapd_mbssid_get_tx_bss(hapd);
++	len = hostapd_eid_mbssid_len(tx_bss, WLAN_FC_STYPE_BEACON, &elem_count,
++				     NULL, 0);
++	if (!len || (iface->conf->mbssid == ENHANCED_MBSSID_ENABLED &&
++		     elem_count > iface->ema_max_periodicity))
++		goto fail;
++
++	elem = os_zalloc(len);
++	if (!elem)
++		goto fail;
++
++	elem_offset = os_zalloc(elem_count * sizeof(u8 *));
++	if (!elem_offset)
++		goto fail;
++
++	end = hostapd_eid_mbssid(tx_bss, elem, elem + len, WLAN_FC_STYPE_BEACON,
++				 elem_count, elem_offset, NULL, 0);
++
++	params->mbssid_tx_iface = tx_bss->conf->iface;
++	params->mbssid_index = hostapd_mbssid_get_bss_index(hapd);
++	params->mbssid_elem = elem;
++	params->mbssid_elem_len = end - elem;
++	params->mbssid_elem_count = elem_count;
++	params->mbssid_elem_offset = elem_offset;
++	if (iface->conf->mbssid == ENHANCED_MBSSID_ENABLED) {
++		params->ema = true;
++		*tailpos++ = WLAN_EID_EXTENSION;
++		*tailpos++ = 3;
++		*tailpos++ = WLAN_EID_EXT_MULTIPLE_BSSID_CONFIGURATION;
++		*tailpos++ = iface->num_bss;
++		*tailpos++ = params->mbssid_elem_count;
++		*eid = tailpos;
++	}
++
++	return 0;
++
++fail:
++	os_free(elem);
++	wpa_printf(MSG_ERROR, "MBSSID: Configuration failed");
++	return -1;
++}
++
++
+ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
+ 				   const struct ieee80211_mgmt *req,
+ 				   int is_p2p, size_t *resp_len,
+-				   bool bcast_probe_resp)
++				   bool bcast_probe_resp, const u8 *known_bss,
++				   u8 known_bss_len)
+ {
+ 	struct ieee80211_mgmt *resp;
+-	u8 *pos, *epos, *csa_pos;
++	u8 *pos, *epos, *csa_pos, *ext_cap_pos;
+ 	size_t buflen;
+ 
++	hapd = hostapd_mbssid_get_tx_bss(hapd);
++
+ #define MAX_PROBERESP_LEN 768
+ 	buflen = MAX_PROBERESP_LEN;
+ #ifdef CONFIG_WPS
+@@ -517,6 +579,8 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
+ 	}
+ #endif /* CONFIG_IEEE80211BE */
+ 
++	buflen += hostapd_eid_mbssid_len(hapd, WLAN_FC_STYPE_PROBE_RESP, NULL,
++					 known_bss, known_bss_len);
+ 	buflen += hostapd_eid_rnr_len(hapd, WLAN_FC_STYPE_PROBE_RESP);
+ 	buflen += hostapd_mbo_ie_len(hapd);
+ 	buflen += hostapd_eid_owe_trans_len(hapd);
+@@ -588,8 +652,16 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
+ 	pos = hostapd_eid_supported_op_classes(hapd, pos);
+ 	pos = hostapd_eid_ht_capabilities(hapd, pos);
+ 	pos = hostapd_eid_ht_operation(hapd, pos);
++	pos = hostapd_eid_mbssid(hapd, pos, epos, WLAN_FC_STYPE_PROBE_RESP, 0,
++				 NULL, known_bss, known_bss_len);
+ 
++	ext_cap_pos = pos;
+ 	pos = hostapd_eid_ext_capab(hapd, pos);
++	if (hapd->iconf->mbssid >= MBSSID_ENABLED && !known_bss_len)
++		ext_cap_pos[12] |= 0x01; /* Probe responses always include all
++					  * non-tx profiles except when a list
++					  * of known BSSes is included in the
++					  * probe request. */
+ 
+ 	pos = hostapd_eid_time_adv(hapd, pos);
+ 	pos = hostapd_eid_time_zone(hapd, pos);
+@@ -1153,16 +1225,23 @@ void handle_probe_req(struct hostapd_data *hapd,
+ 	}
+ #endif /* CONFIG_TESTING_OPTIONS */
+ 
++	/* Do not send probe response from a non-transmitting multiple BSSID
++	 * profile unless the probe request is directed at that paticular BSS */
++	if (hapd != hostapd_mbssid_get_tx_bss(hapd) && res != EXACT_SSID_MATCH)
++		return;
++
+ 	wpa_msg_ctrl(hapd->msg_ctx, MSG_INFO, RX_PROBE_REQUEST "sa=" MACSTR
+ 		     " signal=%d", MAC2STR(mgmt->sa), ssi_signal);
+ 
+ 	if (is_6ghz_op_class(hapd->iconf->op_class) &&
+ 	    is_broadcast_ether_addr(mgmt->da))
+ 		resp = hostapd_gen_probe_resp(hapd, NULL, elems.p2p != NULL,
+-					      &resp_len, true);
++					      &resp_len, false, elems.mbssid_known_bss,
++					      elems.mbssid_known_bss_len);
+ 	else
+ 		resp = hostapd_gen_probe_resp(hapd, mgmt, elems.p2p != NULL,
+-					      &resp_len, false);
++					      &resp_len, false, elems.mbssid_known_bss,
++					      elems.mbssid_known_bss_len);
+ 	if (resp == NULL)
+ 		return;
+ 
+@@ -1184,7 +1263,8 @@ void handle_probe_req(struct hostapd_data *hapd,
+ 				hapd->cs_c_off_ecsa_proberesp;
+ 	}
+ 
+-	ret = hostapd_drv_send_mlme(hapd, resp, resp_len, noack,
++	ret = hostapd_drv_send_mlme(hostapd_mbssid_get_tx_bss(hapd), resp,
++				    resp_len, noack,
+ 				    csa_offs_len ? csa_offs : NULL,
+ 				    csa_offs_len, 0);
+ 
+@@ -1231,7 +1311,7 @@ static u8 * hostapd_probe_resp_offloads(struct hostapd_data *hapd,
+ 			   "this");
+ 
+ 	/* Generate a Probe Response template for the non-P2P case */
+-	return hostapd_gen_probe_resp(hapd, NULL, 0, resp_len, false);
++	return hostapd_gen_probe_resp(hapd, NULL, 0, resp_len, false, NULL, 0);
+ }
+ 
+ #endif /* NEED_AP_MLME */
+@@ -1250,7 +1330,7 @@ static u8 * hostapd_unsol_bcast_probe_resp(struct hostapd_data *hapd,
+ 
+ 	return hostapd_gen_probe_resp(hapd, NULL, 0,
+ 				      &params->unsol_bcast_probe_resp_tmpl_len,
+-				      true);
++				      true, NULL, 0);
+ }
+ #endif /* CONFIG_IEEE80211AX */
+ 
+@@ -1533,8 +1613,12 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
+ 	size_t resp_len = 0;
+ #ifdef NEED_AP_MLME
+ 	u16 capab_info;
+-	u8 *pos, *tailpos, *tailend, *csa_pos;
++	u8 *pos, *tailpos, *tailend, *csa_pos, *ext_cap_pos;
++#endif /* NEED_AP_MLME */
+ 
++	os_memset(params, 0, sizeof(*params));
++
++#ifdef NEED_AP_MLME
+ #define BEACON_HEAD_BUF_SIZE 256
+ #define BEACON_TAIL_BUF_SIZE 512
+ 	head = os_zalloc(BEACON_HEAD_BUF_SIZE);
+@@ -1586,6 +1670,9 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
+ 	}
+ #endif /* CONFIG_IEEE80211BE */
+ 
++	if (hapd->iconf->mbssid == ENHANCED_MBSSID_ENABLED &&
++	    hapd == hostapd_mbssid_get_tx_bss(hapd))
++		tail_len += 5; /* Multiple BSSID Configuration element */
+ 	tail_len += hostapd_eid_rnr_len(hapd, WLAN_FC_STYPE_BEACON);
+ 	tail_len += hostapd_mbo_ie_len(hapd);
+ 	tail_len += hostapd_eid_owe_trans_len(hapd);
+@@ -1671,9 +1758,23 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
+ 	tailpos = hostapd_eid_supported_op_classes(hapd, tailpos);
+ 	tailpos = hostapd_eid_ht_capabilities(hapd, tailpos);
+ 	tailpos = hostapd_eid_ht_operation(hapd, tailpos);
+-
++	ext_cap_pos = tailpos;
+ 	tailpos = hostapd_eid_ext_capab(hapd, tailpos);
+ 
++	if (hapd->iconf->mbssid && hapd->iconf->num_bss > 1) {
++		if (ieee802_11_build_ap_params_mbssid(hapd, params, &tailpos)) {
++			os_free(head);
++			os_free(tail);
++			wpa_printf(MSG_ERROR, "Failed to set beacon data");
++			return -1;
++		} else if (hapd->iconf->mbssid == MBSSID_ENABLED ||
++			   (hapd->iconf->mbssid == ENHANCED_MBSSID_ENABLED &&
++			   params->mbssid_elem_count == 1)) {
++			/* Set the extended capability bit for "complete list
++			 * of non-tx profiles" */
++			ext_cap_pos[12] |= 0x01;
++		}
++	}
+ 	/*
+ 	 * TODO: Time Advertisement element should only be included in some
+ 	 * DTIM Beacon frames.
+@@ -1794,7 +1895,6 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
+ 	resp = hostapd_probe_resp_offloads(hapd, &resp_len);
+ #endif /* NEED_AP_MLME */
+ 
+-	os_memset(params, 0, sizeof(*params));
+ 	params->head = (u8 *) head;
+ 	params->head_len = head_len;
+ 	params->tail = tail;
+@@ -1897,6 +1997,10 @@ void ieee802_11_free_ap_params(struct wpa_driver_ap_params *params)
+ 	params->head = NULL;
+ 	os_free(params->proberesp);
+ 	params->proberesp = NULL;
++	os_free(params->mbssid_elem);
++	params->mbssid_elem = NULL;
++	os_free(params->mbssid_elem_offset);
++	params->mbssid_elem_offset = NULL;
+ #ifdef CONFIG_FILS
+ 	os_free(params->fd_frame_tmpl);
+ 	params->fd_frame_tmpl = NULL;
+diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
+index 42e8ed7..82cc155 100644
+--- a/src/ap/hostapd.c
++++ b/src/ap/hostapd.c
+@@ -91,6 +91,29 @@ int hostapd_for_each_interface(struct hapd_interfaces *interfaces,
+ }
+ 
+ 
++struct hostapd_data * hostapd_mbssid_get_tx_bss(struct hostapd_data *hapd)
++{
++	if (hapd->iconf->mbssid)
++		return hapd->iface->bss[0];
++
++	return hapd;
++}
++
++
++int hostapd_mbssid_get_bss_index(struct hostapd_data *hapd)
++{
++	if (hapd->iconf->mbssid) {
++		size_t i;
++
++		for (i = 1; i < hapd->iface->num_bss; i++)
++			if (hapd->iface->bss[i] == hapd)
++				return i;
++	}
++
++	return 0;
++}
++
++
+ void hostapd_reconfig_encryption(struct hostapd_data *hapd)
+ {
+ 	if (hapd->wpa_auth)
+@@ -1179,19 +1202,37 @@ static int db_table_create_radius_attributes(sqlite3 *db)
+ 
+ #endif /* CONFIG_NO_RADIUS */
+ 
++static int hostapd_start_beacon(struct hostapd_data *hapd)
++{
++	struct hostapd_bss_config *conf = hapd->conf;
++
++	if (!conf->start_disabled && ieee802_11_set_beacon(hapd) < 0)
++		return -1;
++
++	if (hapd->driver && hapd->driver->set_operstate)
++		hapd->driver->set_operstate(hapd->drv_priv, 1);
++
++	return 0;
++}
+ 
+ /**
+  * hostapd_setup_bss - Per-BSS setup (initialization)
+  * @hapd: Pointer to BSS data
+  * @first: Whether this BSS is the first BSS of an interface; -1 = not first,
+  *	but interface may exist
++ * @start_beacon: Whether beacons should be configured and transmission started
++ *	at this time. This is used when MBSSID IE is enabled where the
++ *	information regarding all BSSes should be retrieved before configuring
++ *	the beacons. The calling functions are responsible to configure the
++ *	beacon explicitly if this is set to 'false'.
+  *
+  * This function is used to initialize all per-BSS data structures and
+  * resources. This gets called in a loop for each BSS when an interface is
+  * initialized. Most of the modules that are initialized here will be
+  * deinitialized in hostapd_cleanup().
+  */
+-static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
++static int hostapd_setup_bss(struct hostapd_data *hapd, int first,
++			     bool start_beacon)
+ {
+ 	struct hostapd_bss_config *conf = hapd->conf;
+ 	u8 ssid[SSID_MAX_LEN + 1];
+@@ -1464,9 +1505,6 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
+ 		return -1;
+ 	}
+ 
+-	if (!conf->start_disabled && ieee802_11_set_beacon(hapd) < 0)
+-		return -1;
+-
+ 	if (flush_old_stations && !conf->start_disabled &&
+ 	    conf->broadcast_deauth) {
+ 		u8 addr[ETH_ALEN];
+@@ -1485,8 +1523,8 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
+ 	if (hapd->wpa_auth && wpa_init_keys(hapd->wpa_auth) < 0)
+ 		return -1;
+ 
+-	if (hapd->driver && hapd->driver->set_operstate)
+-		hapd->driver->set_operstate(hapd->drv_priv, 1);
++	if (start_beacon)
++		return hostapd_start_beacon(hapd);
+ 
+ 	hostapd_ubus_add_bss(hapd);
+ 
+@@ -2214,7 +2252,7 @@ static int hostapd_setup_interface_complete_sync(struct hostapd_iface *iface,
+ 		hapd = iface->bss[j];
+ 		if (j)
+ 			os_memcpy(hapd->own_addr, prev_addr, ETH_ALEN);
+-		if (hostapd_setup_bss(hapd, j == 0)) {
++		if (hostapd_setup_bss(hapd, j == 0, !iface->conf->mbssid)) {
+ 			for (;;) {
+ 				hapd = iface->bss[j];
+ 				hostapd_bss_deinit_no_free(hapd);
+@@ -2228,6 +2266,24 @@ static int hostapd_setup_interface_complete_sync(struct hostapd_iface *iface,
+ 		if (is_zero_ether_addr(hapd->conf->bssid))
+ 			prev_addr = hapd->own_addr;
+ 	}
++
++	if (hapd->iconf->mbssid) {
++		for (j = 0; j < iface->num_bss; j++) {
++			hapd = iface->bss[j];
++			if (hostapd_start_beacon(hapd)) {
++				for (;;) {
++					hapd = iface->bss[j];
++					hostapd_bss_deinit_no_free(hapd);
++					hostapd_free_hapd_data(hapd);
++					if (j == 0)
++						break;
++					j--;
++				}
++				goto fail;
++			}
++		}
++	}
++
+ 	hapd = iface->bss[0];
+ 
+ 	hostapd_tx_queue_params(iface);
+@@ -3130,7 +3186,7 @@ int hostapd_add_iface(struct hapd_interfaces *interfaces, char *buf)
+ 
+ 			if (start_ctrl_iface_bss(hapd) < 0 ||
+ 			    (hapd_iface->state == HAPD_IFACE_ENABLED &&
+-			     hostapd_setup_bss(hapd, -1))) {
++			     hostapd_setup_bss(hapd, -1, true))) {
+ 				hostapd_cleanup(hapd);
+ 				hapd_iface->bss[hapd_iface->num_bss - 1] = NULL;
+ 				hapd_iface->conf->num_bss--;
+diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h
+index 56d96a5..093c28a 100644
+--- a/src/ap/hostapd.h
++++ b/src/ap/hostapd.h
+@@ -660,6 +660,11 @@ struct hostapd_iface {
+ 	/* Previous WMM element information */
+ 	struct hostapd_wmm_ac_params prev_wmm[WMM_AC_NUM];
+ 
++	/* Maximum number of interfaces supported for MBSSID advertisements */
++	u8 mbssid_max_interfaces;
++	/* Maximum profile periodicity for enhanced MBSSID advertisements */
++	u8 ema_max_periodicity;
++
+ 	int (*enable_iface_cb)(struct hostapd_iface *iface);
+ 	int (*disable_iface_cb)(struct hostapd_iface *iface);
+ };
+@@ -762,5 +767,7 @@ void fst_hostapd_fill_iface_obj(struct hostapd_data *hapd,
+ #endif /* CONFIG_FST */
+ 
+ int hostapd_set_acl(struct hostapd_data *hapd);
++struct hostapd_data * hostapd_mbssid_get_tx_bss(struct hostapd_data *hapd);
++int hostapd_mbssid_get_bss_index(struct hostapd_data *hapd);
+ 
+ #endif /* HOSTAPD_H */
+diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
+index 098793e..30bfa30 100644
+--- a/src/ap/ieee802_11.c
++++ b/src/ap/ieee802_11.c
+@@ -165,6 +165,7 @@ u8 * hostapd_eid_ext_supp_rates(struct hostapd_data *hapd, u8 *eid)
+ 	int i, num, count;
+ 	int h2e_required;
+ 
++	hapd->conf->xrates_supported = 0;
+ 	if (hapd->iface->current_rates == NULL)
+ 		return eid;
+ 
+@@ -214,6 +215,7 @@ u8 * hostapd_eid_ext_supp_rates(struct hostapd_data *hapd, u8 *eid)
+ 			*pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_SAE_H2E_ONLY;
+ 	}
+ 
++	hapd->conf->xrates_supported = 1;
+ 	return pos;
+ }
+ 
+@@ -3979,6 +3981,23 @@ static void handle_auth(struct hostapd_data *hapd,
+ }
+ 
+ 
++static u8 hostapd_max_bssid_indicator(struct hostapd_data *hapd)
++{
++	size_t num_bss_nontx;
++	u8 max_bssid_ind = 0;
++
++	if (!hapd->iconf->mbssid || hapd->iface->num_bss <= 1)
++		return 0;
++
++	num_bss_nontx = hapd->iface->num_bss - 1;
++	while (num_bss_nontx > 0) {
++		max_bssid_ind++;
++		num_bss_nontx >>= 1;
++	}
++	return max_bssid_ind;
++}
++
++
+ int hostapd_get_aid(struct hostapd_data *hapd, struct sta_info *sta)
+ {
+ 	int i, j = 32, aid;
+@@ -4004,7 +4023,10 @@ int hostapd_get_aid(struct hostapd_data *hapd, struct sta_info *sta)
+ 	}
+ 	if (j == 32)
+ 		return -1;
+-	aid = i * 32 + j + 1;
++	aid = i * 32 + j;
++
++	aid += (1 << hostapd_max_bssid_indicator(hapd));
++
+ 	if (aid > 2007)
+ 		return -1;
+ 
+@@ -7579,4 +7601,256 @@ u8 * hostapd_eid_rnr(struct hostapd_data *hapd, u8 *eid, u32 type)
+ 	return eid;
+ }
+ 
++
++static size_t hostapd_eid_mbssid_elem_len(struct hostapd_data *hapd,
++					  u32 frame_type, size_t *bss_index,
++					  const u8 *known_bss,
++					  size_t known_bss_len)
++{
++	struct hostapd_data *tx_bss = hostapd_mbssid_get_tx_bss(hapd);
++	size_t len = 3, i;
++
++	for (i = *bss_index; i < hapd->iface->num_bss; i++) {
++		struct hostapd_data *bss = hapd->iface->bss[i];
++		const u8 *auth, *rsn = NULL, *rsnx = NULL;
++		size_t nontx_profile_len, auth_len;
++		u8 ie_count = 0;
++
++		if (known_bss && (known_bss_len > (i / 8))) {
++			known_bss = &known_bss[i / 8];
++			if (*known_bss & (u8)(BIT(i % 8)))
++				continue;
++		}
++
++		if (!bss || !bss->conf || !bss->started)
++			continue;
++
++		/*
++		 * Sublement ID: 1 byte
++		 * Length: 1 byte
++		 * Nontransmitted capabilities: 4 bytes
++		 * SSID element: 2 + variable
++		 * Multiple BSSID Index Element: 3 bytes (+2 bytes in beacons)
++		 * Fixed length = 1 + 1 + 4 + 2 + 3 = 11
++		 */
++		nontx_profile_len = 11 + bss->conf->ssid.ssid_len;
++
++		if (frame_type == WLAN_FC_STYPE_BEACON)
++			nontx_profile_len += 2;
++
++		auth = wpa_auth_get_wpa_ie(bss->wpa_auth, &auth_len);
++		if (auth) {
++			rsn = get_ie(auth, auth_len, WLAN_EID_RSN);
++			if (rsn)
++				nontx_profile_len += (2 + rsn[1]);
++
++			rsnx = get_ie(auth, auth_len, WLAN_EID_RSNX);
++			if (rsnx)
++				nontx_profile_len += (2 + rsnx[1]);
++		}
++		if (!rsn && hostapd_wpa_ie(tx_bss, WLAN_EID_RSN))
++			ie_count++;
++		if (!rsnx && hostapd_wpa_ie(tx_bss, WLAN_EID_RSNX))
++			ie_count++;
++		if (bss->conf->xrates_supported)
++			nontx_profile_len += 8;
++		else if (hapd->conf->xrates_supported)
++			ie_count++;
++		if (ie_count)
++			nontx_profile_len += (4 + ie_count);
++
++		if ((len + nontx_profile_len) > 255)
++			goto mbssid_too_big;
++
++		len += nontx_profile_len;
++	}
++
++mbssid_too_big:
++	*bss_index = i;
++	return len;
++}
++
++
++size_t hostapd_eid_mbssid_len(struct hostapd_data *hapd, u32 frame_type,
++			      u8 *elem_count, const u8 *known_bss,
++			      size_t known_bss_len)
++{
++	size_t len = 0, bss_index = 1;
++
++	if (!hapd->iconf->mbssid || hapd->iface->num_bss <= 1 ||
++	    (frame_type != WLAN_FC_STYPE_BEACON &&
++	     frame_type != WLAN_FC_STYPE_PROBE_RESP))
++		return 0;
++
++	if (frame_type == WLAN_FC_STYPE_BEACON) {
++		if (!elem_count) {
++			wpa_printf(MSG_ERROR,
++				   "MBSSID: Insufficient data for beacons");
++			return 0;
++		}
++		*elem_count = 0;
++	}
++
++	while (bss_index < hapd->iface->num_bss) {
++		len += hostapd_eid_mbssid_elem_len(hapd, frame_type,
++						   &bss_index, known_bss,
++						   known_bss_len);
++
++		if (frame_type == WLAN_FC_STYPE_BEACON)
++			*elem_count += 1;
++	}
++	return len;
++}
++
++
++static u8 * hostapd_eid_mbssid_elem(struct hostapd_data *hapd, u8 *eid, u8 *end,
++				    u32 frame_type, u8 max_bssid_indicator,
++				    size_t *bss_index, u8 elem_count,
++				    const u8 *known_bss, size_t known_bss_len)
++{
++	struct hostapd_data *tx_bss = hostapd_mbssid_get_tx_bss(hapd);
++	size_t i;
++	u8 *eid_len_offset, *max_bssid_indicator_offset;
++
++	*eid++ = WLAN_EID_MULTIPLE_BSSID;
++	eid_len_offset = eid++;
++	max_bssid_indicator_offset = eid++;
++
++	for (i = *bss_index; i < hapd->iface->num_bss; i++) {
++		struct hostapd_data *bss = hapd->iface->bss[i];
++		struct hostapd_bss_config *conf;
++		u8 *eid_len_pos, *nontx_bss_start = eid;
++		const u8 *auth, *rsn = NULL, *rsnx = NULL;
++		u8 ie_count = 0, non_inherit_ie[3];
++		size_t auth_len = 0;
++		u16 capab_info;
++
++		if (known_bss && (known_bss_len > (i / 8))) {
++			known_bss = &known_bss[i / 8];
++			if (*known_bss & (u8)(BIT(i % 8)))
++				continue;
++		}
++
++		if (!bss || !bss->conf || !bss->started)
++			continue;
++		conf = bss->conf;
++
++		*eid++ = WLAN_EID_SUBELEMENT_NONTRANSMITTED_BSSID_PROFILE;
++		eid_len_pos = eid++;
++
++		*eid++ = WLAN_EID_NONTRANSMITTED_BSSID_CAPA;
++		*eid++ = sizeof(capab_info);
++		capab_info = host_to_le16(hostapd_own_capab_info(bss));
++		os_memcpy(eid, (const void *)&capab_info, sizeof(capab_info));
++		eid += sizeof(capab_info);
++
++		*eid++ = WLAN_EID_SSID;
++		*eid++ = conf->ssid.ssid_len;
++		os_memcpy(eid, conf->ssid.ssid, conf->ssid.ssid_len);
++		eid += conf->ssid.ssid_len;
++
++		*eid++ = WLAN_EID_MULTIPLE_BSSID_INDEX;
++		if (frame_type == WLAN_FC_STYPE_BEACON) {
++			*eid++ = 3;
++			*eid++ = i;
++			if (hapd->iconf->mbssid == ENHANCED_MBSSID_ENABLED &&
++			    (conf->dtim_period % elem_count))
++				conf->dtim_period = elem_count;
++			*eid++ = conf->dtim_period;
++			*eid++ = 0xFF;
++		} else {
++			*eid++ = 1;
++			*eid++ = i;
++		}
++
++		auth = wpa_auth_get_wpa_ie(bss->wpa_auth, &auth_len);
++		if (auth) {
++			rsn = get_ie(auth, auth_len, WLAN_EID_RSN);
++			if (rsn) {
++				os_memcpy(eid, rsn, 2 + rsn[1]);
++				eid += (2 + rsn[1]);
++			}
++
++			rsnx = get_ie(auth, auth_len, WLAN_EID_RSNX);
++			if (rsnx) {
++				os_memcpy(eid, rsnx, 2 + rsnx[1]);
++				eid += (2 + rsnx[1]);
++			}
++		}
++		if (!rsn && hostapd_wpa_ie(tx_bss, WLAN_EID_RSN)) {
++			non_inherit_ie[ie_count] = WLAN_EID_RSN;
++			ie_count++;
++		}
++		if (!rsnx && hostapd_wpa_ie(tx_bss, WLAN_EID_RSNX)) {
++			non_inherit_ie[ie_count] = WLAN_EID_RSNX;
++			ie_count++;
++		}
++		if (hapd->conf->xrates_supported &&
++		    !bss->conf->xrates_supported) {
++			non_inherit_ie[ie_count] = WLAN_EID_EXT_SUPP_RATES;
++			ie_count++;
++		}
++		if (ie_count) {
++			*eid++ = WLAN_EID_EXTENSION;
++			*eid++ = 2 + ie_count;
++			*eid++ = WLAN_EID_EXT_NON_INHERITANCE;
++			*eid++ = ie_count;
++			os_memcpy(eid, non_inherit_ie, ie_count);
++			eid += ie_count;
++		}
++
++		*eid_len_pos = (eid - eid_len_pos) - 1;
++
++		if (((eid - eid_len_offset) - 1) > 255) {
++			eid = nontx_bss_start;
++			goto mbssid_too_big;
++		}
++	}
++
++mbssid_too_big:
++	*bss_index = i;
++	*max_bssid_indicator_offset = max_bssid_indicator;
++	if (*max_bssid_indicator_offset < 1)
++		*max_bssid_indicator_offset = 1;
++	*eid_len_offset = (eid - eid_len_offset) - 1;
++	return eid;
++}
++
++
++u8 * hostapd_eid_mbssid(struct hostapd_data *hapd, u8 *eid, u8 *end,
++			u32 frame_type, u8 elem_count, u8 **elem_offset,
++			const u8 *known_bss, size_t known_bss_len)
++{
++	size_t bss_index = 1;
++	u8 elem_index = 0;
++
++	if (!hapd->iconf->mbssid || hapd->iface->num_bss <= 1 ||
++	    (frame_type != WLAN_FC_STYPE_BEACON &&
++	     frame_type != WLAN_FC_STYPE_PROBE_RESP))
++		return eid;
++
++	if (frame_type == WLAN_FC_STYPE_BEACON && !elem_offset) {
++		wpa_printf(MSG_ERROR, "MBSSID: Insufficient data for beacons");
++		return eid;
++	}
++
++	while (bss_index < hapd->iface->num_bss) {
++		if (frame_type == WLAN_FC_STYPE_BEACON) {
++			if (elem_index == elem_count) {
++				wpa_printf(MSG_WARNING,
++					   "MBSSID: More number of elements than provided array");
++				break;
++			}
++
++			elem_offset[elem_index] = eid;
++			elem_index = elem_index + 1;
++		}
++		eid = hostapd_eid_mbssid_elem(hapd, eid, end, frame_type,
++					      hostapd_max_bssid_indicator(hapd),
++					      &bss_index, elem_count,
++					      known_bss, known_bss_len);
++	}
++	return eid;
++}
++
+ #endif /* CONFIG_NATIVE_WINDOWS */
+diff --git a/src/ap/ieee802_11.h b/src/ap/ieee802_11.h
+index fa1f47b..bb454bb 100644
+--- a/src/ap/ieee802_11.h
++++ b/src/ap/ieee802_11.h
+@@ -214,5 +214,10 @@ u16 copy_sta_eht_capab(struct hostapd_data *hapd, struct sta_info *sta,
+ 		       enum ieee80211_op_mode opmode,
+ 		       const u8 *he_capab, size_t he_capab_len,
+ 		       const u8 *eht_capab, size_t eht_capab_len);
+-
++size_t hostapd_eid_mbssid_len(struct hostapd_data *hapd, u32 frame_type,
++			      u8 *elem_count, const u8 *known_bss,
++			      size_t known_bss_len);
++u8 * hostapd_eid_mbssid(struct hostapd_data *hapd, u8 *eid, u8 *end,
++			u32 frame_type, u8 elem_count, u8 **elem_offset,
++			const u8 *known_bss, size_t known_bss_len);
+ #endif /* IEEE802_11_H */
+diff --git a/src/ap/ieee802_11_shared.c b/src/ap/ieee802_11_shared.c
+index 4f85d78..7f5b475 100644
+--- a/src/ap/ieee802_11_shared.c
++++ b/src/ap/ieee802_11_shared.c
+@@ -364,6 +364,8 @@ static void hostapd_ext_capab_byte(struct hostapd_data *hapd, u8 *pos, int idx)
+ 			*pos |= 0x02; /* Bit 17 - WNM-Sleep Mode */
+ 		if (hapd->conf->bss_transition)
+ 			*pos |= 0x08; /* Bit 19 - BSS Transition */
++		if (hapd->iconf->mbssid)
++			*pos |= 0x40; /* Bit 22 - Multiple BSSID */
+ 		break;
+ 	case 3: /* Bits 24-31 */
+ #ifdef CONFIG_WNM_AP
+@@ -436,6 +438,8 @@ static void hostapd_ext_capab_byte(struct hostapd_data *hapd, u8 *pos, int idx)
+ 		    (hapd->iface->drv_flags &
+ 		     WPA_DRIVER_FLAGS_BEACON_PROTECTION))
+ 			*pos |= 0x10; /* Bit 84 - Beacon Protection Enabled */
++		if (hapd->iconf->mbssid == ENHANCED_MBSSID_ENABLED)
++			*pos |= 0x08; /* Bit 83 - Enhanced multiple BSSID */
+ 		break;
+ 	case 11: /* Bits 88-95 */
+ #ifdef CONFIG_SAE_PK
+@@ -471,6 +475,13 @@ u8 * hostapd_eid_ext_capab(struct hostapd_data *hapd, u8 *eid)
+ 			*pos &= ~hapd->conf->ext_capa_mask[i];
+ 			*pos |= hapd->conf->ext_capa[i];
+ 		}
++
++		/* Clear bits 83 and 22 if EMA and MBSSID are not enabled
++		 * otherwise association fails with some clients */
++		if (i == 10 && hapd->iconf->mbssid < ENHANCED_MBSSID_ENABLED)
++			*pos &= ~0x08;
++		if (i == 2 && !hapd->iconf->mbssid)
++			*pos &= ~0x40;
+ 	}
+ 
+ 	while (len > 0 && eid[1 + len] == 0) {
+diff --git a/src/common/ieee802_11_common.c b/src/common/ieee802_11_common.c
+index c8ee90c..2fab7c3 100644
+--- a/src/common/ieee802_11_common.c
++++ b/src/common/ieee802_11_common.c
+@@ -315,6 +315,10 @@ static int ieee802_11_parse_extension(const u8 *pos, size_t elen,
+ 		elems->eht_operation = pos;
+ 		elems->eht_operation_len = elen;
+ 		break;
++	case WLAN_EID_EXT_KNOWN_BSSID:
++		elems->mbssid_known_bss = pos;
++		elems->mbssid_known_bss_len = elen;
++		break;
+ 	default:
+ 		if (show_errors) {
+ 			wpa_printf(MSG_MSGDUMP,
+diff --git a/src/common/ieee802_11_common.h b/src/common/ieee802_11_common.h
+index 94e1d7b..1e4e27d 100644
+--- a/src/common/ieee802_11_common.h
++++ b/src/common/ieee802_11_common.h
+@@ -119,6 +119,7 @@ struct ieee802_11_elems {
+ 	const u8 *pasn_params;
+ 	const u8 *eht_capabilities;
+ 	const u8 *eht_operation;
++	const u8 *mbssid_known_bss;
+ 
+ 	u8 ssid_len;
+ 	u8 supp_rates_len;
+@@ -176,6 +177,8 @@ struct ieee802_11_elems {
+ 	u8 eht_capabilities_len;
+ 	u8 eht_operation_len;
+ 
++	u8 mbssid_known_bss_len;
++
+ 	struct mb_ies_info mb_ies;
+ 	struct frag_ies_info frag_ies;
+ };
+diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h
+index 62088bd..0bbbca9 100644
+--- a/src/common/ieee802_11_defs.h
++++ b/src/common/ieee802_11_defs.h
+@@ -481,6 +481,9 @@
+ #define WLAN_EID_EXT_SPATIAL_REUSE 39
+ #define WLAN_EID_EXT_COLOR_CHANGE_ANNOUNCEMENT 42
+ #define WLAN_EID_EXT_OCV_OCI 54
++#define WLAN_EID_EXT_MULTIPLE_BSSID_CONFIGURATION 55
++#define WLAN_EID_EXT_NON_INHERITANCE 56
++#define WLAN_EID_EXT_KNOWN_BSSID 57
+ #define WLAN_EID_EXT_SHORT_SSID_LIST 58
+ #define WLAN_EID_EXT_HE_6GHZ_BAND_CAP 59
+ #define WLAN_EID_EXT_EDMG_CAPABILITIES 61
+@@ -497,6 +500,8 @@
+ #define WLAN_EID_EXT_MULTI_LINK_TRAFFIC_INDICATION 110
+ #define WLAN_EID_EXT_AKM_SUITE_SELECTOR 114
+ 
++#define WLAN_EID_SUBELEMENT_NONTRANSMITTED_BSSID_PROFILE 0
++
+ /* Extended Capabilities field */
+ #define WLAN_EXT_CAPAB_20_40_COEX 0
+ #define WLAN_EXT_CAPAB_GLK 1
+diff --git a/src/drivers/driver.h b/src/drivers/driver.h
+index 82daef0..36f465c 100644
+--- a/src/drivers/driver.h
++++ b/src/drivers/driver.h
+@@ -1633,6 +1633,43 @@ struct wpa_driver_ap_params {
+ 	 * ibf_enable=<val>
+ 	 */
+ 	u8 ibf_enable;
++
++	/**
++	 * mbssid_tx_iface - Transmitting interface of the MBSSID set
++	 */
++	const char *mbssid_tx_iface;
++
++	/**
++	 * mbssid_index - The index of this BSS in the MBSSID set
++	 */
++	unsigned int mbssid_index;
++
++	/**
++	 * mbssid_elem - Buffer containing all MBSSID elements
++	 */
++	u8 *mbssid_elem;
++
++	/**
++	 * mbssid_elem_len - Total length of all MBSSID elements
++	 */
++	size_t mbssid_elem_len;
++
++	/**
++	 * mbssid_elem_count - The number of MBSSID elements
++	 */
++	u8 mbssid_elem_count;
++
++	/**
++	 * mbssid_elem_offset - Offsets to elements in mbssid_elem.
++	 * Kernel will use these offsets to generate multiple BSSID beacons.
++	 */
++	u8 **mbssid_elem_offset;
++
++	/**
++	 * ema - Enhanced MBSSID advertisements support.
++	 */
++	bool ema;
++
+ };
+ 
+ struct wpa_driver_mesh_bss_params {
+@@ -2197,6 +2234,11 @@ struct wpa_driver_capa {
+ 
+ 	/* Maximum number of supported CSA counters */
+ 	u16 max_csa_counters;
++
++	/* Maximum number of interfaces supported for MBSSID advertisements */
++	u8 mbssid_max_interfaces;
++	/* Maximum profile periodicity for enhanced MBSSID advertisements */
++	u8 ema_max_periodicity;
+ };
+ 
+ 
+diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
+index 6c65901..3753409 100644
+--- a/src/drivers/driver_nl80211.c
++++ b/src/drivers/driver_nl80211.c
+@@ -4540,6 +4540,55 @@ static int nl80211_unsol_bcast_probe_resp(struct i802_bss *bss,
+ 	nla_nest_end(msg, attr);
+ 	return 0;
+ }
++
++
++static int nl80211_mbssid(struct nl_msg *msg,
++			 struct wpa_driver_ap_params *params)
++{
++	struct nlattr *config, *elems;
++	int ifidx;
++
++	if (!params->mbssid_tx_iface)
++		return 0;
++
++	config = nla_nest_start(msg, NL80211_ATTR_MBSSID_CONFIG);
++	if (!config)
++		return -1;
++
++	nla_put_u8(msg, NL80211_MBSSID_CONFIG_ATTR_INDEX, params->mbssid_index);
++	if (params->mbssid_tx_iface) {
++		ifidx = if_nametoindex(params->mbssid_tx_iface);
++		if (ifidx <= 0)
++			return -1;
++		nla_put_u32(msg,
++			    NL80211_MBSSID_CONFIG_ATTR_TX_IFINDEX,
++			    ifidx);
++	}
++
++	if (params->ema)
++		nla_put_flag(msg, NL80211_MBSSID_CONFIG_ATTR_EMA);
++
++	nla_nest_end(msg, config);
++
++	if (params->mbssid_elem_count && params->mbssid_elem_len &&
++	    params->mbssid_elem_offset && *params->mbssid_elem_offset) {
++		u8 i, **offs = params->mbssid_elem_offset;
++
++		elems = nla_nest_start(msg, NL80211_ATTR_MBSSID_ELEMS);
++		if (!elems)
++			return -1;
++
++		for (i = 0; i < params->mbssid_elem_count - 1; i++)
++			nla_put(msg, i + 1, offs[i + 1] - offs[i], offs[i]);
++
++		nla_put(msg, i + 1,
++			*offs + params->mbssid_elem_len - offs[i],
++			offs[i]);
++
++		nla_nest_end(msg, elems);
++	}
++	return 0;
++}
+ #endif /* CONFIG_IEEE80211AX */
+ 
+ 
+@@ -4838,6 +4887,9 @@ static int wpa_driver_nl80211_set_ap(void *priv,
+ 	if (params->unsol_bcast_probe_resp_interval &&
+ 	    nl80211_unsol_bcast_probe_resp(bss, msg, params) < 0)
+ 		goto fail;
++
++	if (nl80211_mbssid(msg, params) < 0)
++		goto fail;
+ #endif /* CONFIG_IEEE80211AX */
+ 
+ #ifdef CONFIG_SAE
+diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c
+index 06a52db..d8078bc 100644
+--- a/src/drivers/driver_nl80211_capa.c
++++ b/src/drivers/driver_nl80211_capa.c
+@@ -857,6 +857,30 @@ err:
+ }
+ 
+ 
++static void wiphy_info_mbssid(struct wpa_driver_capa *cap, struct nlattr *attr)
++{
++	struct nlattr *config[NL80211_MBSSID_CONFIG_ATTR_MAX + 1];
++
++	if (nla_parse_nested(config, NL80211_MBSSID_CONFIG_ATTR_MAX, attr,
++			     NULL))
++		return;
++
++	if (!config[NL80211_MBSSID_CONFIG_ATTR_MAX_INTERFACES])
++		return;
++
++	cap->mbssid_max_interfaces =
++		nla_get_u8(config[NL80211_MBSSID_CONFIG_ATTR_MAX_INTERFACES]);
++
++	if (config[NL80211_MBSSID_CONFIG_ATTR_MAX_EMA_PROFILE_PERIODICITY])
++		cap->ema_max_periodicity =
++		nla_get_u8(config[NL80211_MBSSID_CONFIG_ATTR_MAX_EMA_PROFILE_PERIODICITY]);
++
++	wpa_printf(MSG_DEBUG,
++		   "multiple_bssid: max interfaces %u, max profile periodicity %u\n",
++		   cap->mbssid_max_interfaces, cap->ema_max_periodicity);
++}
++
++
+ static int wiphy_info_handler(struct nl_msg *msg, void *arg)
+ {
+ 	struct nlattr *tb[NL80211_ATTR_MAX + 1];
+@@ -1106,6 +1130,9 @@ static int wiphy_info_handler(struct nl_msg *msg, void *arg)
+ 	if (tb[NL80211_ATTR_WIPHY_SELF_MANAGED_REG])
+ 		capa->flags |= WPA_DRIVER_FLAGS_SELF_MANAGED_REGULATORY;
+ 
++	if (tb[NL80211_ATTR_MBSSID_CONFIG])
++		wiphy_info_mbssid(capa, tb[NL80211_ATTR_MBSSID_CONFIG]);
++
+ 	return NL_SKIP;
+ }
+ 
+-- 
+2.18.0
+
diff --git a/recipes-wifi/wpa-supplicant/files/patches/patches.inc b/recipes-wifi/wpa-supplicant/files/patches/patches.inc
index 872f470..48bd493 100644
--- a/recipes-wifi/wpa-supplicant/files/patches/patches.inc
+++ b/recipes-wifi/wpa-supplicant/files/patches/patches.inc
@@ -78,7 +78,10 @@
     file://mtk-0014-hostapd-mtk-Add-the-broadcast-destination-address-of.patch \
     file://mtk-0015-hostapd-mtk-Add-vendor-command-attribute-for-RTS-BW-.patch \
     file://mtk-0016-hostapd-mtk-6G-band-does-not-require-DFS.patch \
+    file://mtk-0016-hostapd-mtk-Add-available-color-bitmap.patch \
     file://mtk-0017-hostapd-mtk-Fix-sending-wrong-VHT-operation-IE-in-CS.patch \
     file://mtk-0018-hostapd-mtk-Add-sta-assisted-DFS-state-update-mechan.patch \
     file://mtk-0019-hostapd-mtk-Fix-auto-ht-issue-when-switching-to-DFS-.patch \
+    file://mtk-0020-hostapd-mtk-Mark-DFS-channel-as-available-for-CSA.patch \
+    file://mtk-0020-hostapd-mtk-add-11v_mbss-and-ema-support.patch \
     "
diff --git a/recipes-wifi/wpa-supplicant/files/src/src/ap/ubus.c b/recipes-wifi/wpa-supplicant/files/src/src/ap/ubus.c
index 5001225..ddd8644 100644
--- a/recipes-wifi/wpa-supplicant/files/src/src/ap/ubus.c
+++ b/recipes-wifi/wpa-supplicant/files/src/src/ap/ubus.c
@@ -1084,6 +1084,8 @@
 	}
 
 	__hostapd_bss_mgmt_enable(hapd, flags);
+
+	return 0;
 }