[Refactor and sync wifi from Openwrt]
[Description]
Refactor and sync wifi from Openwrt
1.mt76/mac80211/hostapd
[Release-log]
N/A
diff --git a/recipes-connectivity/hostapd/files/patches/912-master-add-destination-address-of-unsolicited-probe.patch b/recipes-connectivity/hostapd/files/patches/912-master-add-destination-address-of-unsolicited-probe.patch
deleted file mode 100644
index ae57f36..0000000
--- a/recipes-connectivity/hostapd/files/patches/912-master-add-destination-address-of-unsolicited-probe.patch
+++ /dev/null
@@ -1,31 +0,0 @@
-From b5928412d6debbaf624f9d91650b3a60443e3099 Mon Sep 17 00:00:00 2001
-From: MeiChia Chiu <meichia.chiu@mediatek.com>
-Date: Tue, 26 Apr 2022 11:21:14 +0800
-Subject: [PATCH] hostapd: add destination address of unsolicited probe
- response
-
-without this patch, hostapd generates probe responses with
-null destination address when ap enables unsolicited probe response.
-
-Signed-off-by: MeiChia Chiu <meichia.chiu@mediatek.com>
----
- src/ap/beacon.c | 3 +++
- 1 file changed, 3 insertions(+)
-
-diff --git a/src/ap/beacon.c b/src/ap/beacon.c
-index 8cd1c4170..3c49653cc 100644
---- a/src/ap/beacon.c
-+++ b/src/ap/beacon.c
-@@ -484,6 +484,9 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
- WLAN_FC_STYPE_PROBE_RESP);
- if (req)
- os_memcpy(resp->da, req->sa, ETH_ALEN);
-+ else if (hapd->conf->unsol_bcast_probe_resp_interval > 0)
-+ os_memset(resp->da, 0xff, ETH_ALEN);
-+
- os_memcpy(resp->sa, hapd->own_addr, ETH_ALEN);
-
- os_memcpy(resp->bssid, hapd->own_addr, ETH_ALEN);
---
-2.29.2
-
diff --git a/recipes-connectivity/hostapd/files/patches/912-master-add-the-destination-address-of-unsolicited-Probe.patch b/recipes-connectivity/hostapd/files/patches/912-master-add-the-destination-address-of-unsolicited-Probe.patch
new file mode 100644
index 0000000..e9b630f
--- /dev/null
+++ b/recipes-connectivity/hostapd/files/patches/912-master-add-the-destination-address-of-unsolicited-Probe.patch
@@ -0,0 +1,71 @@
+From 96a7f383290f78e15f1e7a5bc33099c81f104c5b Mon Sep 17 00:00:00 2001
+From: MeiChia Chiu <meichia.chiu@mediatek.com>
+Date: Fri, 6 May 2022 11:02:36 +0800
+Subject: hostapd: Add the destination address of unsolicited Probe Response
+ frame
+
+Without this, hostapd generates Probe Response frames with the null
+destination address when hostapd enables unsolicited Probe Response
+frame transmission. Fix this to use the broadcast address instead.
+
+Fixes: 024b4b2a298f ("AP: Unsolicited broadcast Probe Response configuration")
+Signed-off-by: MeiChia Chiu <meichia.chiu@mediatek.com>
+---
+ src/ap/beacon.c | 13 +++++++++----
+ 1 file changed, 9 insertions(+), 4 deletions(-)
+
+diff --git a/src/ap/beacon.c b/src/ap/beacon.c
+index eaa403326..58872bfda 100644
+--- a/src/ap/beacon.c
++++ b/src/ap/beacon.c
+@@ -464,7 +464,8 @@ static u8 * hostapd_eid_supported_op_classes(struct hostapd_data *hapd, u8 *eid)
+
+ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
+ const struct ieee80211_mgmt *req,
+- int is_p2p, size_t *resp_len)
++ int is_p2p, size_t *resp_len,
++ bool bcast_probe_resp)
+ {
+ struct ieee80211_mgmt *resp;
+ u8 *pos, *epos, *csa_pos;
+@@ -531,6 +532,9 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
+ WLAN_FC_STYPE_PROBE_RESP);
+ if (req)
+ os_memcpy(resp->da, req->sa, ETH_ALEN);
++ else if (bcast_probe_resp)
++ os_memset(resp->da, 0xff, ETH_ALEN);
++
+ os_memcpy(resp->sa, hapd->own_addr, ETH_ALEN);
+
+ os_memcpy(resp->bssid, hapd->own_addr, ETH_ALEN);
+@@ -1141,7 +1145,7 @@ void handle_probe_req(struct hostapd_data *hapd,
+ " signal=%d", MAC2STR(mgmt->sa), ssi_signal);
+
+ resp = hostapd_gen_probe_resp(hapd, mgmt, elems.p2p != NULL,
+- &resp_len);
++ &resp_len, false);
+ if (resp == NULL)
+ return;
+
+@@ -1210,7 +1214,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);
++ return hostapd_gen_probe_resp(hapd, NULL, 0, resp_len, false);
+ }
+
+ #endif /* NEED_AP_MLME */
+@@ -1228,7 +1232,8 @@ static u8 * hostapd_unsol_bcast_probe_resp(struct hostapd_data *hapd,
+ hapd->conf->unsol_bcast_probe_resp_interval;
+
+ return hostapd_gen_probe_resp(hapd, NULL, 0,
+- ¶ms->unsol_bcast_probe_resp_tmpl_len);
++ ¶ms->unsol_bcast_probe_resp_tmpl_len,
++ true);
+ }
+ #endif /* CONFIG_IEEE80211AX */
+
+--
+cgit v1.2.3-18-g5258
+
diff --git a/recipes-connectivity/hostapd/files/patches/913-master-add-support-for-runtime-set-in-band-discover.patch b/recipes-connectivity/hostapd/files/patches/913-master-add-support-for-runtime-set-in-band-discover.patch
new file mode 100644
index 0000000..306b221
--- /dev/null
+++ b/recipes-connectivity/hostapd/files/patches/913-master-add-support-for-runtime-set-in-band-discover.patch
@@ -0,0 +1,204 @@
+From 8c9d9f2b8da1b0e3e0832e7d7b02d75c4c0a4f3e Mon Sep 17 00:00:00 2001
+From: MeiChia Chiu <meichia.chiu@mediatek.com>
+Date: Thu, 24 May 2022 21:48:21 +0800
+Subject: [PATCH] hostapd:v2 add support for runtime set in-band discovery-v2
+
+Usage:
+hostapd_cli unsolic_probe_resp [tx_type] [interval]
+
+0: disable all in-band discovery
+1: enable unsolicited probe response
+2: enable FILS discovery
+
+Signed-off-by: MeiChia Chiu <MeiChia.Chiu@mediatek.com>
+---
+ hostapd/ctrl_iface.c | 62 ++++++++++++++++++++++++++++++++++++
+ hostapd/hostapd_cli.c | 20 ++++++++++++
+ src/ap/beacon.c | 5 ++-
+ src/drivers/driver_nl80211.c | 8 +++--
+ src/drivers/nl80211_copy.h | 1 +
+ 5 files changed, 92 insertions(+), 4 deletions(-)
+
+diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
+index 86adf18e5..41740cfd5 100644
+--- a/hostapd/ctrl_iface.c
++++ b/hostapd/ctrl_iface.c
+@@ -769,6 +769,65 @@ static int hostapd_ctrl_iface_send_qos_map_conf(struct hostapd_data *hapd,
+
+ #endif /* CONFIG_INTERWORKING */
+
++static int hostapd_ctrl_iface_inband_discovery(struct hostapd_data *hapd,
++ const char *cmd)
++{
++ struct hostapd_bss_config *conf = hapd->conf;
++ const char *pos = cmd;
++ int tx_type, interval, ret;
++
++ tx_type = atoi(pos);
++ if (tx_type < 0 || tx_type > 2) {
++ wpa_printf(MSG_ERROR, "Invalid tx type\n");
++ return -1;
++ }
++
++ pos = os_strchr(pos, ' ');
++ if(!pos)
++ return -1;
++ pos++;
++ interval = atoi(pos);
++ if (interval < 0 || interval > 20) {
++ wpa_printf(MSG_ERROR, "Invalid interval value\n");
++ return -1;
++ }
++
++ wpa_printf(MSG_ERROR, "Set inband discovery type:%d, interval:%d\n",
++ tx_type, interval);
++
++#define DISABLE_INBAND_DISC 0
++#define UNSOL_PROBE_RESP 1
++#define FILS_DISCOVERY 2
++
++ conf->fils_discovery_max_int = 0;
++ conf->fils_discovery_min_int = 0;
++ conf->unsol_bcast_probe_resp_interval = 0;
++
++ switch (tx_type) {
++ case DISABLE_INBAND_DISC:
++ default:
++ /* Disable both Unsolicited probe response and FILS discovery*/
++ break;
++ case UNSOL_PROBE_RESP:
++ /* Enable Unsolicited probe response */
++ conf->unsol_bcast_probe_resp_interval = interval;
++ break;
++ case FILS_DISCOVERY:
++ /* Enable FILS discovery */
++ conf->fils_discovery_min_int = interval;
++ conf->fils_discovery_max_int = interval;
++ break;
++ }
++
++ ret = ieee802_11_update_beacons(hapd->iface);
++ if(ret) {
++ wpa_printf(MSG_DEBUG,
++ "Failed to update with inband discovery parameters\n");
++ return -1;
++ }
++
++ return 0;
++}
+
+ #ifdef CONFIG_WNM_AP
+
+@@ -3673,6 +3732,9 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
+ if (hostapd_ctrl_iface_coloc_intf_req(hapd, buf + 15))
+ reply_len = -1;
+ #endif /* CONFIG_WNM_AP */
++ } else if (os_strncmp(buf, "INBAND_DISCOVERY ", 17) == 0) {
++ if (hostapd_ctrl_iface_inband_discovery(hapd, buf + 17))
++ reply_len = -1;
+ } else if (os_strcmp(buf, "GET_CONFIG") == 0) {
+ reply_len = hostapd_ctrl_iface_get_config(hapd, reply,
+ reply_size);
+diff --git a/hostapd/hostapd_cli.c b/hostapd/hostapd_cli.c
+index 260912111..e30c4e7c1 100644
+--- a/hostapd/hostapd_cli.c
++++ b/hostapd/hostapd_cli.c
+@@ -646,6 +646,24 @@ static int hostapd_cli_cmd_wps_config(struct wpa_ctrl *ctrl, int argc,
+ }
+ #endif /* CONFIG_WPS */
+
++static int hostapd_cli_cmd_inband_discovery(struct wpa_ctrl *ctrl, int argc,
++ char *argv[])
++{
++ char buf[300];
++ int res;
++
++ if (argc < 2) {
++ printf("Invalid 'inband_discovery' command - two arguments"
++ "tx_type interval\n");
++ return -1;
++ }
++
++ res = os_snprintf(buf, sizeof(buf), "INBAND_DISCOVERY %s %s",
++ argv[0], argv[1]);
++ if (os_snprintf_error(sizeof(buf), res))
++ return -1;
++ return wpa_ctrl_command(ctrl, buf);
++}
+
+ static int hostapd_cli_cmd_disassoc_imminent(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+@@ -1744,6 +1762,8 @@ static const struct hostapd_cli_cmd hostapd_cli_commands[] = {
+ { "driver", hostapd_cli_cmd_driver, NULL,
+ "<driver sub command> [<hex formatted data>] = send driver command data" },
+ #endif /* ANDROID */
++ { "inband_discovery", hostapd_cli_cmd_inband_discovery, NULL,
++ "<tx type(0/1/2)> <interval> = runtime set inband discovery" },
+ { NULL, NULL, NULL, NULL }
+ };
+
+diff --git a/src/ap/beacon.c b/src/ap/beacon.c
+index 3c49653cc..367e32611 100644
+--- a/src/ap/beacon.c
++++ b/src/ap/beacon.c
+@@ -1406,6 +1406,8 @@ static u8 * hostapd_fils_discovery(struct hostapd_data *hapd,
+ struct wpa_driver_ap_params *params)
+ {
+ params->fd_max_int = hapd->conf->fils_discovery_max_int;
++ params->unsol_bcast_probe_resp_interval =
++ hapd->conf->unsol_bcast_probe_resp_interval;
+ if (is_6ghz_op_class(hapd->iconf->op_class) &&
+ params->fd_max_int > FD_MAX_INTERVAL_6GHZ)
+ params->fd_max_int = FD_MAX_INTERVAL_6GHZ;
+@@ -1414,7 +1416,8 @@ static u8 * hostapd_fils_discovery(struct hostapd_data *hapd,
+ if (params->fd_min_int > params->fd_max_int)
+ params->fd_min_int = params->fd_max_int;
+
+- if (params->fd_max_int)
++ if (params->fd_max_int ||
++ !params->unsol_bcast_probe_resp_interval)
+ return hostapd_gen_fils_discovery(hapd,
+ ¶ms->fd_frame_tmpl_len);
+
+diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
+index aec179ac3..6113aff0b 100644
+--- a/src/drivers/driver_nl80211.c
++++ b/src/drivers/driver_nl80211.c
+@@ -4491,9 +4491,10 @@ static int nl80211_fils_discovery(struct i802_bss *bss, struct nl_msg *msg,
+ params->fd_max_int) ||
+ (params->fd_frame_tmpl &&
+ nla_put(msg, NL80211_FILS_DISCOVERY_ATTR_TMPL,
+- params->fd_frame_tmpl_len, params->fd_frame_tmpl)))
++ params->fd_frame_tmpl_len, params->fd_frame_tmpl)) ||
++ nla_put_u32(msg, NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_INTE,
++ params->unsol_bcast_probe_resp_interval))
+ return -1;
+-
+ nla_nest_end(msg, attr);
+ return 0;
+ }
+@@ -4823,7 +4824,8 @@ static int wpa_driver_nl80211_set_ap(void *priv,
+ #endif /* CONFIG_SAE */
+
+ #ifdef CONFIG_FILS
+- if (params->fd_max_int && nl80211_fils_discovery(bss, msg, params) < 0)
++ if ((params->fd_max_int || !(params->unsol_bcast_probe_resp_interval)) &&
++ nl80211_fils_discovery(bss, msg, params) < 0)
+ goto fail;
+ #endif /* CONFIG_FILS */
+
+diff --git a/src/drivers/nl80211_copy.h b/src/drivers/nl80211_copy.h
+index f962c06e9..6fb7b7fcf 100644
+--- a/src/drivers/nl80211_copy.h
++++ b/src/drivers/nl80211_copy.h
+@@ -7150,6 +7150,7 @@ enum nl80211_fils_discovery_attributes {
+ NL80211_FILS_DISCOVERY_ATTR_INT_MIN,
+ NL80211_FILS_DISCOVERY_ATTR_INT_MAX,
+ NL80211_FILS_DISCOVERY_ATTR_TMPL,
++ NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_INTE,
+
+ /* keep last */
+ __NL80211_FILS_DISCOVERY_ATTR_LAST,
+--
+2.29.2
+
diff --git a/recipes-connectivity/hostapd/files/patches/patches.inc b/recipes-connectivity/hostapd/files/patches/patches.inc
index 8db63c7..36ec650 100644
--- a/recipes-connectivity/hostapd/files/patches/patches.inc
+++ b/recipes-connectivity/hostapd/files/patches/patches.inc
@@ -61,5 +61,6 @@
file://909-master-Add-hostapd_neighbor_set_own_report_pref.patch \
file://910-master-Add-hostapd_neighbor_set_pref_by_non_pref_chan.patch \
file://911-master-print-sae-groups-by-hostapd-ctrl.patch \
- file://912-master-add-destination-address-of-unsolicited-probe.patch \
+ file://912-master-add-the-destination-address-of-unsolicited-Probe.patch \
+ file://913-master-add-support-for-runtime-set-in-band-discover.patch \
"
diff --git a/recipes-connectivity/hostapd/hostapd_2.10.bb b/recipes-connectivity/hostapd/hostapd_2.10.bb
index 8560d43..0a487db 100644
--- a/recipes-connectivity/hostapd/hostapd_2.10.bb
+++ b/recipes-connectivity/hostapd/hostapd_2.10.bb
@@ -59,6 +59,7 @@
echo "CONFIG_AP=y" >> ${B}/.config
echo "CONFIG_MESH=y" >> ${B}/.config
echo "CONFIG_WEP=y" >> ${B}/.config
+ echo "CONFIG_FILS=y" >> ${B}/.config
}
SRC_URI_append_mt7915 += " \
diff --git a/recipes-connectivity/wpa-supplicant/files/patches/912-master-add-destination-address-of-unsolicited-probe.patch b/recipes-connectivity/wpa-supplicant/files/patches/912-master-add-destination-address-of-unsolicited-probe.patch
deleted file mode 100644
index ae57f36..0000000
--- a/recipes-connectivity/wpa-supplicant/files/patches/912-master-add-destination-address-of-unsolicited-probe.patch
+++ /dev/null
@@ -1,31 +0,0 @@
-From b5928412d6debbaf624f9d91650b3a60443e3099 Mon Sep 17 00:00:00 2001
-From: MeiChia Chiu <meichia.chiu@mediatek.com>
-Date: Tue, 26 Apr 2022 11:21:14 +0800
-Subject: [PATCH] hostapd: add destination address of unsolicited probe
- response
-
-without this patch, hostapd generates probe responses with
-null destination address when ap enables unsolicited probe response.
-
-Signed-off-by: MeiChia Chiu <meichia.chiu@mediatek.com>
----
- src/ap/beacon.c | 3 +++
- 1 file changed, 3 insertions(+)
-
-diff --git a/src/ap/beacon.c b/src/ap/beacon.c
-index 8cd1c4170..3c49653cc 100644
---- a/src/ap/beacon.c
-+++ b/src/ap/beacon.c
-@@ -484,6 +484,9 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
- WLAN_FC_STYPE_PROBE_RESP);
- if (req)
- os_memcpy(resp->da, req->sa, ETH_ALEN);
-+ else if (hapd->conf->unsol_bcast_probe_resp_interval > 0)
-+ os_memset(resp->da, 0xff, ETH_ALEN);
-+
- os_memcpy(resp->sa, hapd->own_addr, ETH_ALEN);
-
- os_memcpy(resp->bssid, hapd->own_addr, ETH_ALEN);
---
-2.29.2
-
diff --git a/recipes-connectivity/wpa-supplicant/files/patches/912-master-add-the-destination-address-of-unsolicited-Probe.patch b/recipes-connectivity/wpa-supplicant/files/patches/912-master-add-the-destination-address-of-unsolicited-Probe.patch
new file mode 100644
index 0000000..e9b630f
--- /dev/null
+++ b/recipes-connectivity/wpa-supplicant/files/patches/912-master-add-the-destination-address-of-unsolicited-Probe.patch
@@ -0,0 +1,71 @@
+From 96a7f383290f78e15f1e7a5bc33099c81f104c5b Mon Sep 17 00:00:00 2001
+From: MeiChia Chiu <meichia.chiu@mediatek.com>
+Date: Fri, 6 May 2022 11:02:36 +0800
+Subject: hostapd: Add the destination address of unsolicited Probe Response
+ frame
+
+Without this, hostapd generates Probe Response frames with the null
+destination address when hostapd enables unsolicited Probe Response
+frame transmission. Fix this to use the broadcast address instead.
+
+Fixes: 024b4b2a298f ("AP: Unsolicited broadcast Probe Response configuration")
+Signed-off-by: MeiChia Chiu <meichia.chiu@mediatek.com>
+---
+ src/ap/beacon.c | 13 +++++++++----
+ 1 file changed, 9 insertions(+), 4 deletions(-)
+
+diff --git a/src/ap/beacon.c b/src/ap/beacon.c
+index eaa403326..58872bfda 100644
+--- a/src/ap/beacon.c
++++ b/src/ap/beacon.c
+@@ -464,7 +464,8 @@ static u8 * hostapd_eid_supported_op_classes(struct hostapd_data *hapd, u8 *eid)
+
+ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
+ const struct ieee80211_mgmt *req,
+- int is_p2p, size_t *resp_len)
++ int is_p2p, size_t *resp_len,
++ bool bcast_probe_resp)
+ {
+ struct ieee80211_mgmt *resp;
+ u8 *pos, *epos, *csa_pos;
+@@ -531,6 +532,9 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
+ WLAN_FC_STYPE_PROBE_RESP);
+ if (req)
+ os_memcpy(resp->da, req->sa, ETH_ALEN);
++ else if (bcast_probe_resp)
++ os_memset(resp->da, 0xff, ETH_ALEN);
++
+ os_memcpy(resp->sa, hapd->own_addr, ETH_ALEN);
+
+ os_memcpy(resp->bssid, hapd->own_addr, ETH_ALEN);
+@@ -1141,7 +1145,7 @@ void handle_probe_req(struct hostapd_data *hapd,
+ " signal=%d", MAC2STR(mgmt->sa), ssi_signal);
+
+ resp = hostapd_gen_probe_resp(hapd, mgmt, elems.p2p != NULL,
+- &resp_len);
++ &resp_len, false);
+ if (resp == NULL)
+ return;
+
+@@ -1210,7 +1214,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);
++ return hostapd_gen_probe_resp(hapd, NULL, 0, resp_len, false);
+ }
+
+ #endif /* NEED_AP_MLME */
+@@ -1228,7 +1232,8 @@ static u8 * hostapd_unsol_bcast_probe_resp(struct hostapd_data *hapd,
+ hapd->conf->unsol_bcast_probe_resp_interval;
+
+ return hostapd_gen_probe_resp(hapd, NULL, 0,
+- ¶ms->unsol_bcast_probe_resp_tmpl_len);
++ ¶ms->unsol_bcast_probe_resp_tmpl_len,
++ true);
+ }
+ #endif /* CONFIG_IEEE80211AX */
+
+--
+cgit v1.2.3-18-g5258
+
diff --git a/recipes-connectivity/wpa-supplicant/files/patches/913-master-add-support-for-runtime-set-in-band-discover.patch b/recipes-connectivity/wpa-supplicant/files/patches/913-master-add-support-for-runtime-set-in-band-discover.patch
new file mode 100644
index 0000000..306b221
--- /dev/null
+++ b/recipes-connectivity/wpa-supplicant/files/patches/913-master-add-support-for-runtime-set-in-band-discover.patch
@@ -0,0 +1,204 @@
+From 8c9d9f2b8da1b0e3e0832e7d7b02d75c4c0a4f3e Mon Sep 17 00:00:00 2001
+From: MeiChia Chiu <meichia.chiu@mediatek.com>
+Date: Thu, 24 May 2022 21:48:21 +0800
+Subject: [PATCH] hostapd:v2 add support for runtime set in-band discovery-v2
+
+Usage:
+hostapd_cli unsolic_probe_resp [tx_type] [interval]
+
+0: disable all in-band discovery
+1: enable unsolicited probe response
+2: enable FILS discovery
+
+Signed-off-by: MeiChia Chiu <MeiChia.Chiu@mediatek.com>
+---
+ hostapd/ctrl_iface.c | 62 ++++++++++++++++++++++++++++++++++++
+ hostapd/hostapd_cli.c | 20 ++++++++++++
+ src/ap/beacon.c | 5 ++-
+ src/drivers/driver_nl80211.c | 8 +++--
+ src/drivers/nl80211_copy.h | 1 +
+ 5 files changed, 92 insertions(+), 4 deletions(-)
+
+diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
+index 86adf18e5..41740cfd5 100644
+--- a/hostapd/ctrl_iface.c
++++ b/hostapd/ctrl_iface.c
+@@ -769,6 +769,65 @@ static int hostapd_ctrl_iface_send_qos_map_conf(struct hostapd_data *hapd,
+
+ #endif /* CONFIG_INTERWORKING */
+
++static int hostapd_ctrl_iface_inband_discovery(struct hostapd_data *hapd,
++ const char *cmd)
++{
++ struct hostapd_bss_config *conf = hapd->conf;
++ const char *pos = cmd;
++ int tx_type, interval, ret;
++
++ tx_type = atoi(pos);
++ if (tx_type < 0 || tx_type > 2) {
++ wpa_printf(MSG_ERROR, "Invalid tx type\n");
++ return -1;
++ }
++
++ pos = os_strchr(pos, ' ');
++ if(!pos)
++ return -1;
++ pos++;
++ interval = atoi(pos);
++ if (interval < 0 || interval > 20) {
++ wpa_printf(MSG_ERROR, "Invalid interval value\n");
++ return -1;
++ }
++
++ wpa_printf(MSG_ERROR, "Set inband discovery type:%d, interval:%d\n",
++ tx_type, interval);
++
++#define DISABLE_INBAND_DISC 0
++#define UNSOL_PROBE_RESP 1
++#define FILS_DISCOVERY 2
++
++ conf->fils_discovery_max_int = 0;
++ conf->fils_discovery_min_int = 0;
++ conf->unsol_bcast_probe_resp_interval = 0;
++
++ switch (tx_type) {
++ case DISABLE_INBAND_DISC:
++ default:
++ /* Disable both Unsolicited probe response and FILS discovery*/
++ break;
++ case UNSOL_PROBE_RESP:
++ /* Enable Unsolicited probe response */
++ conf->unsol_bcast_probe_resp_interval = interval;
++ break;
++ case FILS_DISCOVERY:
++ /* Enable FILS discovery */
++ conf->fils_discovery_min_int = interval;
++ conf->fils_discovery_max_int = interval;
++ break;
++ }
++
++ ret = ieee802_11_update_beacons(hapd->iface);
++ if(ret) {
++ wpa_printf(MSG_DEBUG,
++ "Failed to update with inband discovery parameters\n");
++ return -1;
++ }
++
++ return 0;
++}
+
+ #ifdef CONFIG_WNM_AP
+
+@@ -3673,6 +3732,9 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
+ if (hostapd_ctrl_iface_coloc_intf_req(hapd, buf + 15))
+ reply_len = -1;
+ #endif /* CONFIG_WNM_AP */
++ } else if (os_strncmp(buf, "INBAND_DISCOVERY ", 17) == 0) {
++ if (hostapd_ctrl_iface_inband_discovery(hapd, buf + 17))
++ reply_len = -1;
+ } else if (os_strcmp(buf, "GET_CONFIG") == 0) {
+ reply_len = hostapd_ctrl_iface_get_config(hapd, reply,
+ reply_size);
+diff --git a/hostapd/hostapd_cli.c b/hostapd/hostapd_cli.c
+index 260912111..e30c4e7c1 100644
+--- a/hostapd/hostapd_cli.c
++++ b/hostapd/hostapd_cli.c
+@@ -646,6 +646,24 @@ static int hostapd_cli_cmd_wps_config(struct wpa_ctrl *ctrl, int argc,
+ }
+ #endif /* CONFIG_WPS */
+
++static int hostapd_cli_cmd_inband_discovery(struct wpa_ctrl *ctrl, int argc,
++ char *argv[])
++{
++ char buf[300];
++ int res;
++
++ if (argc < 2) {
++ printf("Invalid 'inband_discovery' command - two arguments"
++ "tx_type interval\n");
++ return -1;
++ }
++
++ res = os_snprintf(buf, sizeof(buf), "INBAND_DISCOVERY %s %s",
++ argv[0], argv[1]);
++ if (os_snprintf_error(sizeof(buf), res))
++ return -1;
++ return wpa_ctrl_command(ctrl, buf);
++}
+
+ static int hostapd_cli_cmd_disassoc_imminent(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+@@ -1744,6 +1762,8 @@ static const struct hostapd_cli_cmd hostapd_cli_commands[] = {
+ { "driver", hostapd_cli_cmd_driver, NULL,
+ "<driver sub command> [<hex formatted data>] = send driver command data" },
+ #endif /* ANDROID */
++ { "inband_discovery", hostapd_cli_cmd_inband_discovery, NULL,
++ "<tx type(0/1/2)> <interval> = runtime set inband discovery" },
+ { NULL, NULL, NULL, NULL }
+ };
+
+diff --git a/src/ap/beacon.c b/src/ap/beacon.c
+index 3c49653cc..367e32611 100644
+--- a/src/ap/beacon.c
++++ b/src/ap/beacon.c
+@@ -1406,6 +1406,8 @@ static u8 * hostapd_fils_discovery(struct hostapd_data *hapd,
+ struct wpa_driver_ap_params *params)
+ {
+ params->fd_max_int = hapd->conf->fils_discovery_max_int;
++ params->unsol_bcast_probe_resp_interval =
++ hapd->conf->unsol_bcast_probe_resp_interval;
+ if (is_6ghz_op_class(hapd->iconf->op_class) &&
+ params->fd_max_int > FD_MAX_INTERVAL_6GHZ)
+ params->fd_max_int = FD_MAX_INTERVAL_6GHZ;
+@@ -1414,7 +1416,8 @@ static u8 * hostapd_fils_discovery(struct hostapd_data *hapd,
+ if (params->fd_min_int > params->fd_max_int)
+ params->fd_min_int = params->fd_max_int;
+
+- if (params->fd_max_int)
++ if (params->fd_max_int ||
++ !params->unsol_bcast_probe_resp_interval)
+ return hostapd_gen_fils_discovery(hapd,
+ ¶ms->fd_frame_tmpl_len);
+
+diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
+index aec179ac3..6113aff0b 100644
+--- a/src/drivers/driver_nl80211.c
++++ b/src/drivers/driver_nl80211.c
+@@ -4491,9 +4491,10 @@ static int nl80211_fils_discovery(struct i802_bss *bss, struct nl_msg *msg,
+ params->fd_max_int) ||
+ (params->fd_frame_tmpl &&
+ nla_put(msg, NL80211_FILS_DISCOVERY_ATTR_TMPL,
+- params->fd_frame_tmpl_len, params->fd_frame_tmpl)))
++ params->fd_frame_tmpl_len, params->fd_frame_tmpl)) ||
++ nla_put_u32(msg, NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_INTE,
++ params->unsol_bcast_probe_resp_interval))
+ return -1;
+-
+ nla_nest_end(msg, attr);
+ return 0;
+ }
+@@ -4823,7 +4824,8 @@ static int wpa_driver_nl80211_set_ap(void *priv,
+ #endif /* CONFIG_SAE */
+
+ #ifdef CONFIG_FILS
+- if (params->fd_max_int && nl80211_fils_discovery(bss, msg, params) < 0)
++ if ((params->fd_max_int || !(params->unsol_bcast_probe_resp_interval)) &&
++ nl80211_fils_discovery(bss, msg, params) < 0)
+ goto fail;
+ #endif /* CONFIG_FILS */
+
+diff --git a/src/drivers/nl80211_copy.h b/src/drivers/nl80211_copy.h
+index f962c06e9..6fb7b7fcf 100644
+--- a/src/drivers/nl80211_copy.h
++++ b/src/drivers/nl80211_copy.h
+@@ -7150,6 +7150,7 @@ enum nl80211_fils_discovery_attributes {
+ NL80211_FILS_DISCOVERY_ATTR_INT_MIN,
+ NL80211_FILS_DISCOVERY_ATTR_INT_MAX,
+ NL80211_FILS_DISCOVERY_ATTR_TMPL,
++ NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_INTE,
+
+ /* keep last */
+ __NL80211_FILS_DISCOVERY_ATTR_LAST,
+--
+2.29.2
+
diff --git a/recipes-connectivity/wpa-supplicant/files/patches/patches.inc b/recipes-connectivity/wpa-supplicant/files/patches/patches.inc
index 8db63c7..36ec650 100644
--- a/recipes-connectivity/wpa-supplicant/files/patches/patches.inc
+++ b/recipes-connectivity/wpa-supplicant/files/patches/patches.inc
@@ -61,5 +61,6 @@
file://909-master-Add-hostapd_neighbor_set_own_report_pref.patch \
file://910-master-Add-hostapd_neighbor_set_pref_by_non_pref_chan.patch \
file://911-master-print-sae-groups-by-hostapd-ctrl.patch \
- file://912-master-add-destination-address-of-unsolicited-probe.patch \
+ file://912-master-add-the-destination-address-of-unsolicited-Probe.patch \
+ file://913-master-add-support-for-runtime-set-in-band-discover.patch \
"
diff --git a/recipes-connectivity/wpa-supplicant/files/wpa_supplicant-full.config b/recipes-connectivity/wpa-supplicant/files/wpa_supplicant-full.config
index 800c18c..1397111 100644
--- a/recipes-connectivity/wpa-supplicant/files/wpa_supplicant-full.config
+++ b/recipes-connectivity/wpa-supplicant/files/wpa_supplicant-full.config
@@ -618,6 +618,7 @@
# Services can connect to the bus and provide methods
# that can be called by other services or clients.
+
# OpenWrt patch 380-disable-ctrl-iface-mib.patch
# leads to the MIB only being compiled in if
# CONFIG_CTRL_IFACE_MIB is enabled.
diff --git a/recipes-kernel/linux-mac80211/files/patches/subsys/350-bss-color-collision.patch b/recipes-kernel/linux-mac80211/files/patches/subsys/350-bss-color-collision.patch
new file mode 100644
index 0000000..5924a05
--- /dev/null
+++ b/recipes-kernel/linux-mac80211/files/patches/subsys/350-bss-color-collision.patch
@@ -0,0 +1,118 @@
+From 6d945a33f2b0aa24fc210dadaa0af3e8218e7002 Mon Sep 17 00:00:00 2001
+From: Lorenzo Bianconi <lorenzo@kernel.org>
+Date: Fri, 25 Mar 2022 11:42:41 +0100
+Subject: [PATCH] mac80211: introduce BSS color collision detection
+
+Add ieee80211_rx_check_bss_color_collision routine in order to introduce
+BSS color collision detection in mac80211 if it is not supported in HW/FW
+(e.g. for mt7915 chipset).
+Add IEEE80211_HW_DETECTS_COLOR_COLLISION flag to let the driver notify
+BSS color collision detection is supported in HW/FW. Set this for ath11k
+which apparently didn't need this code.
+
+Tested-by: Peter Chiu <Chui-Hao.Chiu@mediatek.com>
+Co-developed-by: Ryder Lee <ryder.lee@mediatek.com>
+Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
+Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
+Link: https://lore.kernel.org/r/a05eeeb1841a84560dc5aaec77894fcb69a54f27.1648204871.git.lorenzo@kernel.org
+[clarify commit message a bit, move flag to mac80211]
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+---
+ drivers/net/wireless/ath/ath11k/mac.c | 5 ++-
+ include/net/mac80211.h | 4 +++
+ net/mac80211/debugfs.c | 1 +
+ net/mac80211/rx.c | 46 +++++++++++++++++++++++++++
+ 4 files changed, 55 insertions(+), 1 deletion(-)
+
+--- a/include/net/mac80211.h
++++ b/include/net/mac80211.h
+@@ -2418,6 +2418,9 @@ struct ieee80211_txq {
+ * usage and 802.11 frames with %RX_FLAG_ONLY_MONITOR set for monitor to
+ * the stack.
+ *
++ * @IEEE80211_HW_DETECTS_COLOR_COLLISION: HW/driver has support for BSS color
++ * collision detection and doesn't need it in software.
++ *
+ * @NUM_IEEE80211_HW_FLAGS: number of hardware flags, used for sizing arrays
+ */
+ enum ieee80211_hw_flags {
+@@ -2473,6 +2476,7 @@ enum ieee80211_hw_flags {
+ IEEE80211_HW_SUPPORTS_TX_ENCAP_OFFLOAD,
+ IEEE80211_HW_SUPPORTS_RX_DECAP_OFFLOAD,
+ IEEE80211_HW_SUPPORTS_CONC_MON_RX_DECAP,
++ IEEE80211_HW_DETECTS_COLOR_COLLISION,
+
+ /* keep last, obviously */
+ NUM_IEEE80211_HW_FLAGS
+--- a/net/mac80211/debugfs.c
++++ b/net/mac80211/debugfs.c
+@@ -504,6 +504,7 @@ static const char *hw_flag_names[] = {
+ FLAG(SUPPORTS_TX_ENCAP_OFFLOAD),
+ FLAG(SUPPORTS_RX_DECAP_OFFLOAD),
+ FLAG(SUPPORTS_CONC_MON_RX_DECAP),
++ FLAG(DETECTS_COLOR_COLLISION),
+ #undef FLAG
+ };
+
+--- a/net/mac80211/rx.c
++++ b/net/mac80211/rx.c
+@@ -3177,6 +3177,49 @@ static void ieee80211_process_sa_query_r
+ ieee80211_tx_skb(sdata, skb);
+ }
+
++static void
++ieee80211_rx_check_bss_color_collision(struct ieee80211_rx_data *rx)
++{
++ struct ieee80211_mgmt *mgmt = (void *)rx->skb->data;
++ const struct element *ie;
++ size_t baselen;
++
++ if (!wiphy_ext_feature_isset(rx->local->hw.wiphy,
++ NL80211_EXT_FEATURE_BSS_COLOR))
++ return;
++
++ if (ieee80211_hw_check(&rx->local->hw, DETECTS_COLOR_COLLISION))
++ return;
++
++ if (rx->sdata->vif.csa_active)
++ return;
++
++ baselen = mgmt->u.beacon.variable - rx->skb->data;
++ if (baselen > rx->skb->len)
++ return;
++
++ ie = cfg80211_find_ext_elem(WLAN_EID_EXT_HE_OPERATION,
++ mgmt->u.beacon.variable,
++ rx->skb->len - baselen);
++ if (ie && ie->datalen >= sizeof(struct ieee80211_he_operation) &&
++ ie->datalen >= ieee80211_he_oper_size(ie->data + 1)) {
++ struct ieee80211_bss_conf *bss_conf = &rx->sdata->vif.bss_conf;
++ const struct ieee80211_he_operation *he_oper;
++ u8 color;
++
++ he_oper = (void *)(ie->data + 1);
++ if (le32_get_bits(he_oper->he_oper_params,
++ IEEE80211_HE_OPERATION_BSS_COLOR_DISABLED))
++ return;
++
++ color = le32_get_bits(he_oper->he_oper_params,
++ IEEE80211_HE_OPERATION_BSS_COLOR_MASK);
++ if (color == bss_conf->he_bss_color.color)
++ ieeee80211_obss_color_collision_notify(&rx->sdata->vif,
++ BIT_ULL(color));
++ }
++}
++
+ static ieee80211_rx_result debug_noinline
+ ieee80211_rx_h_mgmt_check(struct ieee80211_rx_data *rx)
+ {
+@@ -3202,6 +3245,9 @@ ieee80211_rx_h_mgmt_check(struct ieee802
+ !(rx->flags & IEEE80211_RX_BEACON_REPORTED)) {
+ int sig = 0;
+
++ /* sw bss color collision detection */
++ ieee80211_rx_check_bss_color_collision(rx);
++
+ if (ieee80211_hw_check(&rx->local->hw, SIGNAL_DBM) &&
+ !(status->flag & RX_FLAG_NO_SIGNAL_VAL))
+ sig = status->signal;
diff --git a/recipes-kernel/linux-mac80211/files/patches/subsys/902-nl80211-internal-extend-CAC-time-for-weather-radar-c.patch b/recipes-kernel/linux-mac80211/files/patches/subsys/902-nl80211-internal-extend-CAC-time-for-weather-radar-c.patch
index 04b3270..b6f6d69 100644
--- a/recipes-kernel/linux-mac80211/files/patches/subsys/902-nl80211-internal-extend-CAC-time-for-weather-radar-c.patch
+++ b/recipes-kernel/linux-mac80211/files/patches/subsys/902-nl80211-internal-extend-CAC-time-for-weather-radar-c.patch
@@ -17,9 +17,9 @@
cac_time_ms = IEEE80211_DFS_MIN_CAC_TIME_MS;
+ if ((dfs_region == NL80211_DFS_ETSI) &&
-+ ((chandef.width == NL80211_CHAN_WIDTH_160) &&
++ (((chandef.width == NL80211_CHAN_WIDTH_160) &&
+ (chandef.center_freq2 >= 5580 && chandef.center_freq2 <= 5640)) ||
-+ (chandef.center_freq1 >= 5580 && chandef.center_freq1 <= 5640))
++ (chandef.center_freq1 >= 5580 && chandef.center_freq1 <= 5640)))
+ cac_time_ms = 600000;
+ pr_info("%s: region = %u, cetner freq1 = %u, center freq2 = %u, cac time ms = %u\n", __func__, dfs_region, chandef.center_freq1, chandef.center_freq2, cac_time_ms);
+
diff --git a/recipes-kernel/linux-mac80211/files/patches/subsys/905-mac80211-airtime_flags-depends-on-NL80211_EXT_FEATUR.patch b/recipes-kernel/linux-mac80211/files/patches/subsys/905-mac80211-airtime_flags-depends-on-NL80211_EXT_FEATUR.patch
new file mode 100644
index 0000000..8325e96
--- /dev/null
+++ b/recipes-kernel/linux-mac80211/files/patches/subsys/905-mac80211-airtime_flags-depends-on-NL80211_EXT_FEATUR.patch
@@ -0,0 +1,19 @@
+diff --git a/net/mac80211/main.c b/net/mac80211/main.c
+index 3a442d8..f355cd3 100644
+--- a/net/mac80211/main.c
++++ b/net/mac80211/main.c
+@@ -723,8 +723,9 @@ struct ieee80211_hw *ieee80211_alloc_hw_nm(size_t priv_data_len,
+ air_sched->aql_txq_limit_high =
+ IEEE80211_DEFAULT_AQL_TXQ_LIMIT_H;
+ }
+-
+- local->airtime_flags = AIRTIME_USE_TX | AIRTIME_USE_RX;
++ if (wiphy_ext_feature_isset(local->hw.wiphy,
++ NL80211_EXT_FEATURE_AIRTIME_FAIRNESS))
++ local->airtime_flags = AIRTIME_USE_TX | AIRTIME_USE_RX;
+ local->aql_threshold = IEEE80211_AQL_THRESHOLD;
+ atomic_set(&local->aql_total_pending_airtime, 0);
+
+--
+2.18.0
+
diff --git a/recipes-kernel/linux-mac80211/files/patches/subsys/906-mac80211-add-support-for-runtime-set-inband-discovery.patch b/recipes-kernel/linux-mac80211/files/patches/subsys/906-mac80211-add-support-for-runtime-set-inband-discovery.patch
new file mode 100644
index 0000000..f6fc98f
--- /dev/null
+++ b/recipes-kernel/linux-mac80211/files/patches/subsys/906-mac80211-add-support-for-runtime-set-inband-discovery.patch
@@ -0,0 +1,150 @@
+diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
+--- a/include/net/cfg80211.h
++++ b/include/net/cfg80211.h
+@@ -1158,6 +1158,7 @@ struct cfg80211_fils_discovery {
+ u32 max_interval;
+ size_t tmpl_len;
+ const u8 *tmpl;
++ u8 disable;
+ };
+
+ /**
+diff --git a/include/net/mac80211.h b/include/net/mac80211.h
+--- a/include/net/mac80211.h
++++ b/include/net/mac80211.h
+@@ -505,6 +505,7 @@ struct ieee80211_ftm_responder_params {
+ struct ieee80211_fils_discovery {
+ u32 min_interval;
+ u32 max_interval;
++ u8 disable;
+ };
+
+ /**
+diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
+--- a/include/uapi/linux/nl80211.h
++++ b/include/uapi/linux/nl80211.h
+@@ -7236,6 +7236,7 @@ enum nl80211_fils_discovery_attributes {
+ NL80211_FILS_DISCOVERY_ATTR_INT_MIN,
+ NL80211_FILS_DISCOVERY_ATTR_INT_MAX,
+ NL80211_FILS_DISCOVERY_ATTR_TMPL,
++ NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_INTE,
+
+ /* keep last */
+ __NL80211_FILS_DISCOVERY_ATTR_LAST,
+diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
+--- a/net/mac80211/cfg.c
++++ b/net/mac80211/cfg.c
+@@ -906,6 +906,7 @@ static int ieee80211_set_fils_discovery(
+ fd = &sdata->vif.bss_conf.fils_discovery;
+ fd->min_interval = params->min_interval;
+ fd->max_interval = params->max_interval;
++ fd->disable = params->disable;
+
+ old = sdata_dereference(sdata->u.ap.fils_discovery, sdata);
+ new = kzalloc(sizeof(*new) + params->tmpl_len, GFP_KERNEL);
+@@ -1316,6 +1317,8 @@ static int ieee80211_change_beacon(struc
+ {
+ struct ieee80211_sub_if_data *sdata;
+ struct beacon_data *old;
++ struct cfg80211_ap_settings *ap_params;
++ u32 changed;
+ int err;
+
+ sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+@@ -1334,7 +1337,26 @@ static int ieee80211_change_beacon(struc
+ err = ieee80211_assign_beacon(sdata, params, NULL, NULL);
+ if (err < 0)
+ return err;
+- ieee80211_bss_info_change_notify(sdata, err);
++
++ changed = err;
++ ap_params = container_of(params, struct cfg80211_ap_settings, beacon);
++
++ if(ap_params->unsol_bcast_probe_resp.interval) {
++ err = ieee80211_set_unsol_bcast_probe_resp(sdata,
++ &ap_params->unsol_bcast_probe_resp);
++ if (err < 0)
++ return err;
++ changed |= BSS_CHANGED_UNSOL_BCAST_PROBE_RESP;
++ } else {
++ err = ieee80211_set_fils_discovery(sdata,
++ &ap_params->fils_discovery);
++ if (err < 0)
++ return err;
++ changed |= BSS_CHANGED_FILS_DISCOVERY;
++
++ }
++
++ ieee80211_bss_info_change_notify(sdata, changed);
+ return 0;
+ }
+
+diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
+--- a/net/wireless/nl80211.c
++++ b/net/wireless/nl80211.c
+@@ -421,6 +421,7 @@ nl80211_fils_discovery_policy[NL80211_FI
+ [NL80211_FILS_DISCOVERY_ATTR_TMPL] = { .type = NLA_BINARY,
+ .len = IEEE80211_MAX_DATA_LEN },
+ #endif
++ [NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_INTE] = NLA_POLICY_MAX(NLA_U32, 20),
+ };
+
+ static const struct nla_policy
+@@ -5349,6 +5350,8 @@ static int nl80211_parse_fils_discovery(
+ fd->tmpl = nla_data(tb[NL80211_FILS_DISCOVERY_ATTR_TMPL]);
+ fd->min_interval = nla_get_u32(tb[NL80211_FILS_DISCOVERY_ATTR_INT_MIN]);
+ fd->max_interval = nla_get_u32(tb[NL80211_FILS_DISCOVERY_ATTR_INT_MAX]);
++ fd->disable = !(fd->max_interval ||
++ nla_get_u32(tb[NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_INTE]));
+
+ return 0;
+ }
+@@ -5754,7 +5757,8 @@ static int nl80211_set_beacon(struct sk_
+ struct cfg80211_registered_device *rdev = info->user_ptr[0];
+ struct net_device *dev = info->user_ptr[1];
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+- struct cfg80211_beacon_data params;
++ struct cfg80211_ap_settings ap_params;
++ struct cfg80211_beacon_data *params;
+ int err;
+
+ if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
+@@ -5767,16 +5771,35 @@ static int nl80211_set_beacon(struct sk_
+ if (!wdev->beacon_interval)
+ return -EINVAL;
+
+- err = nl80211_parse_beacon(rdev, info->attrs, ¶ms);
++ memset(&ap_params, 0, sizeof(ap_params));
++ params = &ap_params.beacon;
++
++ err = nl80211_parse_beacon(rdev, info->attrs, params);
+ if (err)
+ goto out;
+
++ if (info->attrs[NL80211_ATTR_FILS_DISCOVERY]) {
++ err = nl80211_parse_fils_discovery(rdev,
++ info->attrs[NL80211_ATTR_FILS_DISCOVERY],
++ &ap_params);
++ if (err)
++ goto out;
++ }
++
++ if (info->attrs[NL80211_ATTR_UNSOL_BCAST_PROBE_RESP]) {
++ err = nl80211_parse_unsol_bcast_probe_resp(rdev,
++ info->attrs[NL80211_ATTR_UNSOL_BCAST_PROBE_RESP],
++ &ap_params);
++ if (err)
++ goto out;
++ }
++
+ wdev_lock(wdev);
+- err = rdev_change_beacon(rdev, dev, ¶ms);
++ err = rdev_change_beacon(rdev, dev, params);
+ wdev_unlock(wdev);
+
+ out:
+- kfree(params.mbssid_ies);
++ kfree(params->mbssid_ies);
+ return err;
+ }
+
diff --git a/recipes-kernel/linux-mac80211/files/patches/subsys/subsys.inc b/recipes-kernel/linux-mac80211/files/patches/subsys/subsys.inc
index 01fd587..89f1e95 100644
--- a/recipes-kernel/linux-mac80211/files/patches/subsys/subsys.inc
+++ b/recipes-kernel/linux-mac80211/files/patches/subsys/subsys.inc
@@ -26,6 +26,7 @@
file://325-mac80211-MBSSID-channel-switch.patch \
file://326-mac80211-update-bssid_indicator-in-ieee80211_assign_.patch \
file://329-mac80211-minstrel_ht-fix-where-rate-stats-are-stored.patch \
+ file://350-bss-color-collision.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 \
@@ -33,4 +34,6 @@
file://902-nl80211-internal-extend-CAC-time-for-weather-radar-c.patch \
file://903-mac80211-it-s-invalid-case-when-frag_threshold-is-gr.patch \
file://904-mac80211-correct-legacy-rates-check-in-ieee80211_cal.patch \
+ file://905-mac80211-airtime_flags-depends-on-NL80211_EXT_FEATUR.patch \
+ file://906-mac80211-add-support-for-runtime-set-inband-discovery.patch \
"
diff --git a/recipes-kernel/linux-mt76/files/patches/0007-mt76-mt7915-update-mt7986-CR-for-different-adie-vers.patch b/recipes-kernel/linux-mt76/files/patches/0007-mt76-mt7915-update-mt7986-CR-for-different-adie-vers.patch
index d5c72aa..1340ac9 100644
--- a/recipes-kernel/linux-mt76/files/patches/0007-mt76-mt7915-update-mt7986-CR-for-different-adie-vers.patch
+++ b/recipes-kernel/linux-mt76/files/patches/0007-mt76-mt7915-update-mt7986-CR-for-different-adie-vers.patch
@@ -1,4 +1,4 @@
-From 87efddcc9bb605802fdabe8bf3408a106bf5b997 Mon Sep 17 00:00:00 2001
+From 14baf1e2df409bdfdf3255dbe8ad5ecc1852b8b0 Mon Sep 17 00:00:00 2001
From: Peter Chiu <chui-hao.chiu@mediatek.com>
Date: Tue, 15 Mar 2022 14:21:13 +0800
Subject: [PATCH] mt76: mt7915: update mt7986 CR for different adie version
@@ -6,14 +6,14 @@
Signed-off-by: Peter Chiu <chui-hao.chiu@mediatek.com>
---
mt7915/regs.h | 1 +
- mt7915/soc.c | 24 +++++++++++++++++++++---
- 2 files changed, 22 insertions(+), 3 deletions(-)
+ mt7915/soc.c | 21 ++++++++++++++++++---
+ 2 files changed, 19 insertions(+), 3 deletions(-)
diff --git a/mt7915/regs.h b/mt7915/regs.h
-index e5f93c40..a69ba562 100644
+index cb7c7e14..97984aaf 100644
--- a/mt7915/regs.h
+++ b/mt7915/regs.h
-@@ -794,6 +794,7 @@ enum offs_rev {
+@@ -822,6 +822,7 @@ enum offs_rev {
/* ADIE */
#define MT_ADIE_CHIP_ID 0x02c
@@ -22,17 +22,17 @@
#define MT_ADIE_IDX0 GENMASK(15, 0)
#define MT_ADIE_IDX1 GENMASK(31, 16)
diff --git a/mt7915/soc.c b/mt7915/soc.c
-index 04df47fd..e1892368 100644
+index d465f8d8..a977f90a 100644
--- a/mt7915/soc.c
+++ b/mt7915/soc.c
-@@ -468,16 +468,34 @@ static int mt7986_wmac_adie_xtal_trim_7976(struct mt7915_dev *dev, u8 adie)
+@@ -469,17 +469,32 @@ static int mt7986_wmac_adie_xtal_trim_7976(struct mt7915_dev *dev, u8 adie)
+
static int mt7986_wmac_adie_patch_7976(struct mt7915_dev *dev, u8 adie)
{
++ u32 id, version, rg_xo_01, rg_xo_03;
int ret;
-+ u32 id, version;
- ret = mt76_wmac_spi_write(dev, adie, MT_ADIE_RG_TOP_THADC, 0x4a563b00);
-+
+ ret = mt76_wmac_spi_read(dev, adie, MT_ADIE_CHIP_ID, &id);
if (ret)
return ret;
@@ -46,20 +46,18 @@
- return mt76_wmac_spi_write(dev, adie, MT_ADIE_RG_XO_03, 0x34c00fe0);
+ if (version == 0x8a00 || version == 0x8a10 || version == 0x8b00) {
-+ ret = mt76_wmac_spi_write(dev, adie, MT_ADIE_RG_XO_01, 0x1d59080f);
-+ if (ret)
-+ return ret;
-+
-+ mt76_wmac_spi_write(dev, adie, MT_ADIE_RG_XO_03, 0x34c00fe0);
++ rg_xo_01 = 0x1d59080f;
++ rg_xo_03 = 0x34c00fe0;
+ } else {
-+ ret = mt76_wmac_spi_write(dev, adie, MT_ADIE_RG_XO_01, 0x1959c80f);
-+ if (ret)
-+ return ret;
-+
-+ mt76_wmac_spi_write(dev, adie, MT_ADIE_RG_XO_03, 0x34d00fe0);
++ rg_xo_01 = 0x1959f80f;
++ rg_xo_03 = 0x34d00fe0;
+ }
+
-+ return ret;
++ ret = mt76_wmac_spi_write(dev, adie, MT_ADIE_RG_XO_01, rg_xo_01);
++ if (ret)
++ return ret;
++
++ return mt76_wmac_spi_write(dev, adie, MT_ADIE_RG_XO_03, rg_xo_03);
}
static int
diff --git a/recipes-kernel/linux-mt76/files/patches/0014-mt76-mt7915-limit-minimum-twt-duration-due-to-hw-lim.patch b/recipes-kernel/linux-mt76/files/patches/0014-mt76-mt7915-limit-minimum-twt-duration-due-to-hw-lim.patch
new file mode 100644
index 0000000..d5aafcb
--- /dev/null
+++ b/recipes-kernel/linux-mt76/files/patches/0014-mt76-mt7915-limit-minimum-twt-duration-due-to-hw-lim.patch
@@ -0,0 +1,37 @@
+From 58706d81a82726f488cda771097f5586708b47f2 Mon Sep 17 00:00:00 2001
+From: Peter Chiu <chui-hao.chiu@mediatek.com>
+Date: Tue, 12 Apr 2022 16:06:36 +0800
+Subject: [PATCH] mt76: mt7915: limit minimum twt duration due to hw limitation
+
+---
+ mt7915/mac.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/mt7915/mac.c b/mt7915/mac.c
+index 925f5eb9..fd897fd5 100644
+--- a/mt7915/mac.c
++++ b/mt7915/mac.c
+@@ -2698,6 +2698,7 @@ void mt7915_mac_add_twt_setup(struct ieee80211_hw *hw,
+ struct ieee80211_sta *sta,
+ struct ieee80211_twt_setup *twt)
+ {
++#define MT7915_MIN_TWT_DUR 64
+ enum ieee80211_twt_setup_cmd setup_cmd = TWT_SETUP_CMD_REJECT;
+ struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
+ struct ieee80211_twt_params *twt_agrt = (void *)twt->params;
+@@ -2719,6 +2720,12 @@ void mt7915_mac_add_twt_setup(struct ieee80211_hw *hw,
+ if (hweight8(msta->twt.flowid_mask) == ARRAY_SIZE(msta->twt.flow))
+ goto unlock;
+
++ if (twt_agrt->min_twt_dur < MT7915_MIN_TWT_DUR) {
++ setup_cmd = TWT_SETUP_CMD_DICTATE;
++ twt_agrt->min_twt_dur = MT7915_MIN_TWT_DUR;
++ goto unlock;
++ }
++
+ flowid = ffs(~msta->twt.flowid_mask) - 1;
+ le16p_replace_bits(&twt_agrt->req_type, flowid,
+ IEEE80211_TWT_REQTYPE_FLOWID);
+--
+2.18.0
+
diff --git a/recipes-kernel/linux-mt76/files/patches/0015-mt76-mt7915-drop-undefined-action-frame.patch b/recipes-kernel/linux-mt76/files/patches/0015-mt76-mt7915-drop-undefined-action-frame.patch
new file mode 100644
index 0000000..f8f766e
--- /dev/null
+++ b/recipes-kernel/linux-mt76/files/patches/0015-mt76-mt7915-drop-undefined-action-frame.patch
@@ -0,0 +1,36 @@
+From 573b80a984695b338e12c6c30bb4e9f7af7e3495 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] mt76: mt7915: drop undefined action frame
+
+---
+ mt7915/mac.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/mt7915/mac.c b/mt7915/mac.c
+index 1e0ddc13..81c582f2 100644
+--- a/mt7915/mac.c
++++ b/mt7915/mac.c
+@@ -1303,6 +1303,8 @@ int mt7915_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
+ struct mt76_tx_info *tx_info)
+ {
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx_info->skb->data;
++ struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)tx_info->skb->data;
++ __le16 fc = hdr->frame_control;
+ struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76);
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx_info->skb);
+ struct ieee80211_key_conf *key = info->control.hw_key;
+@@ -1333,6 +1335,10 @@ int mt7915_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
+ t = (struct mt76_txwi_cache *)(txwi + mdev->drv->txwi_size);
+ t->skb = tx_info->skb;
+
++ if (ieee80211_is_action(fc) &&
++ mgmt->u.action.category == 0xff)
++ return -1;
++
+ id = mt76_token_consume(mdev, &t);
+ if (id < 0)
+ return id;
+--
+2.18.0
+
diff --git a/recipes-kernel/linux-mt76/files/patches/0016-mt76-mt7915-reowrk-SER-debugfs-knob.patch b/recipes-kernel/linux-mt76/files/patches/0016-mt76-mt7915-reowrk-SER-debugfs-knob.patch
new file mode 100755
index 0000000..d4c81d9
--- /dev/null
+++ b/recipes-kernel/linux-mt76/files/patches/0016-mt76-mt7915-reowrk-SER-debugfs-knob.patch
@@ -0,0 +1,278 @@
+From f3f9ccbb417cae6e503084e13d627b68a141b0bd Mon Sep 17 00:00:00 2001
+From: Bo Jiao <Bo.Jiao@mediatek.com>
+Date: Thu, 5 May 2022 11:45:23 +0800
+Subject: [PATCH 02/10] mt76: mt7915: reowrk SER debugfs knob
+
+1. get status of system recovery from firmware.
+2. add more recovery points.
+3. make knob per phy.
+
+Signed-off-by: Bo Jiao <Bo.Jiao@mediatek.com>
+Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
+---
+ mt7915/debugfs.c | 106 ++++++++++++++++++++++++++++++++++++++++-------
+ mt7915/mcu.c | 5 +--
+ mt7915/mcu.h | 14 +++++++
+ mt7915/mmio.c | 3 ++
+ mt7915/regs.h | 18 +++++++-
+ 5 files changed, 126 insertions(+), 20 deletions(-)
+
+diff --git a/mt7915/debugfs.c b/mt7915/debugfs.c
+index 77bbeeed..b45181c1 100644
+--- a/mt7915/debugfs.c
++++ b/mt7915/debugfs.c
+@@ -44,35 +44,113 @@ mt7915_implicit_txbf_get(void *data, u64 *val)
+ DEFINE_DEBUGFS_ATTRIBUTE(fops_implicit_txbf, mt7915_implicit_txbf_get,
+ mt7915_implicit_txbf_set, "%lld\n");
+
+-/* test knob of system layer 1/2 error recovery */
+-static int mt7915_ser_trigger_set(void *data, u64 val)
++/* test knob of system error recovery */
++static ssize_t
++mt7915_fw_ser_set(struct file *file, const char __user *user_buf,
++ size_t count, loff_t *ppos)
+ {
+- enum {
+- SER_SET_RECOVER_L1 = 1,
+- SER_SET_RECOVER_L2,
+- SER_ENABLE = 2,
+- SER_RECOVER
+- };
+- struct mt7915_dev *dev = data;
++ struct mt7915_phy *phy = file->private_data;
++ struct mt7915_dev *dev = phy->dev;
++ bool ext_phy = phy != &dev->phy;
++ char buf[16];
+ int ret = 0;
++ u16 val;
++
++ if (count >= sizeof(buf))
++ return -EINVAL;
++
++ if (copy_from_user(buf, user_buf, count))
++ return -EFAULT;
++
++ if (count && buf[count - 1] == '\n')
++ buf[count - 1] = '\0';
++ else
++ buf[count] = '\0';
++
++ if (kstrtou16(buf, 0, &val))
++ return -EINVAL;
+
+ switch (val) {
++ case SER_QUERY:
++ /* grab firmware SER stats */
++ ret = mt7915_mcu_set_ser(dev, 0, 0, ext_phy);
++ break;
+ case SER_SET_RECOVER_L1:
+ case SER_SET_RECOVER_L2:
+- ret = mt7915_mcu_set_ser(dev, SER_ENABLE, BIT(val), 0);
++ 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 = mt7915_mcu_set_ser(dev, SER_ENABLE, BIT(val), ext_phy);
+ if (ret)
+ return ret;
+
+- return mt7915_mcu_set_ser(dev, SER_RECOVER, val, 0);
++ ret = mt7915_mcu_set_ser(dev, SER_RECOVER, val, ext_phy);
++ break;
+ default:
+ break;
+ }
+
++ return ret ? ret : count;
++}
++
++static ssize_t
++mt7915_fw_ser_get(struct file *file, char __user *user_buf,
++ size_t count, loff_t *ppos)
++{
++ struct mt7915_phy *phy = file->private_data;
++ struct mt7915_dev *dev = phy->dev;
++ char *buff;
++ int desc = 0;
++ ssize_t ret;
++ static const size_t bufsz = 400;
++
++ buff = kmalloc(bufsz, GFP_KERNEL);
++ if (!buff)
++ return -ENOMEM;
++
++ 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_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));
++
++ ret = simple_read_from_buffer(user_buf, count, ppos, buff, desc);
++ kfree(buff);
+ return ret;
+ }
+
+-DEFINE_DEBUGFS_ATTRIBUTE(fops_ser_trigger, NULL,
+- mt7915_ser_trigger_set, "%lld\n");
++static const struct file_operations mt7915_fw_ser_ops = {
++ .write = mt7915_fw_ser_set,
++ .read = mt7915_fw_ser_get,
++ .open = simple_open,
++ .llseek = default_llseek,
++};
+
+ static int
+ mt7915_radar_trigger(void *data, u64 val)
+@@ -914,6 +992,7 @@ int mt7915_init_debugfs(struct mt7915_phy *phy)
+ debugfs_create_file("xmit-queues", 0400, dir, phy,
+ &mt7915_xmit_queues_fops);
+ debugfs_create_file("tx_stats", 0400, dir, phy, &mt7915_tx_stats_fops);
++ debugfs_create_file("fw_ser", 0600, dir, phy, &mt7915_fw_ser_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);
+@@ -927,7 +1006,6 @@ int mt7915_init_debugfs(struct mt7915_phy *phy)
+ &mt7915_rate_txpower_fops);
+ debugfs_create_devm_seqfile(dev->mt76.dev, "twt_stats", dir,
+ mt7915_twt_stats);
+- debugfs_create_file("ser_trigger", 0200, dir, dev, &fops_ser_trigger);
+ debugfs_create_file("rf_regval", 0600, dir, dev, &fops_rf_regval);
+
+ if (!dev->dbdc_support || phy->band_idx) {
+diff --git a/mt7915/mcu.c b/mt7915/mcu.c
+index c215bc9e..20f32f7f 100644
+--- a/mt7915/mcu.c
++++ b/mt7915/mcu.c
+@@ -2471,10 +2471,7 @@ int mt7915_mcu_init(struct mt7915_dev *dev)
+ /* force firmware operation mode into normal state,
+ * which should be set before firmware download stage.
+ */
+- if (is_mt7915(&dev->mt76))
+- mt76_wr(dev, MT_SWDEF_MODE, MT_SWDEF_NORMAL_MODE);
+- else
+- mt76_wr(dev, MT_SWDEF_MODE_MT7916, MT_SWDEF_NORMAL_MODE);
++ mt76_wr(dev, MT_SWDEF_MODE, MT_SWDEF_NORMAL_MODE);
+
+ ret = mt7915_driver_own(dev, 0);
+ if (ret)
+diff --git a/mt7915/mcu.h b/mt7915/mcu.h
+index df7aefca..5cbc3ecf 100644
+--- a/mt7915/mcu.h
++++ b/mt7915/mcu.h
+@@ -464,6 +464,20 @@ enum {
+ MURU_GET_TXC_TX_STATS = 151,
+ };
+
++enum {
++ 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,
++ /* action */
++ SER_ENABLE = 2,
++ SER_RECOVER
++};
++
+ #define MT7915_BSS_UPDATE_MAX_SIZE (sizeof(struct sta_req_hdr) + \
+ sizeof(struct bss_info_omac) + \
+ sizeof(struct bss_info_basic) +\
+diff --git a/mt7915/mmio.c b/mt7915/mmio.c
+index 0bd32daa..2d733d32 100644
+--- a/mt7915/mmio.c
++++ b/mt7915/mmio.c
+@@ -22,6 +22,7 @@ static const u32 mt7915_reg[] = {
+ [WFDMA_EXT_CSR_ADDR] = 0xd7000,
+ [CBTOP1_PHY_END] = 0x77ffffff,
+ [INFRA_MCU_ADDR_END] = 0x7c3fffff,
++ [SWDEF_BASE_ADDR] = 0x41f200,
+ };
+
+ static const u32 mt7916_reg[] = {
+@@ -36,6 +37,7 @@ static const u32 mt7916_reg[] = {
+ [WFDMA_EXT_CSR_ADDR] = 0xd7000,
+ [CBTOP1_PHY_END] = 0x7fffffff,
+ [INFRA_MCU_ADDR_END] = 0x7c085fff,
++ [SWDEF_BASE_ADDR] = 0x411400,
+ };
+
+ static const u32 mt7986_reg[] = {
+@@ -50,6 +52,7 @@ static const u32 mt7986_reg[] = {
+ [WFDMA_EXT_CSR_ADDR] = 0x27000,
+ [CBTOP1_PHY_END] = 0x7fffffff,
+ [INFRA_MCU_ADDR_END] = 0x7c085fff,
++ [SWDEF_BASE_ADDR] = 0x411400,
+ };
+
+ static const u32 mt7915_offs[] = {
+diff --git a/mt7915/regs.h b/mt7915/regs.h
+index 97984aaf..4251cf78 100644
+--- a/mt7915/regs.h
++++ b/mt7915/regs.h
+@@ -30,6 +30,7 @@ enum reg_rev {
+ WFDMA_EXT_CSR_ADDR,
+ CBTOP1_PHY_END,
+ INFRA_MCU_ADDR_END,
++ SWDEF_BASE_ADDR,
+ __MT_REG_MAX,
+ };
+
+@@ -942,12 +943,25 @@ enum offs_rev {
+ #define MT_ADIE_TYPE_MASK BIT(1)
+
+ /* FW MODE SYNC */
+-#define MT_SWDEF_MODE 0x41f23c
+-#define MT_SWDEF_MODE_MT7916 0x41143c
++#define MT_SWDEF_BASE __REG(SWDEF_BASE_ADDR)
++
++#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_WISR7_BN0_STATS MT_SWDEF(0x060)
++#define MT_SWDEF_LAMC_WISR7_BN1_STATS MT_SWDEF(0x064)
++
+ #define MT_DIC_CMD_REG_BASE 0x41f000
+ #define MT_DIC_CMD_REG(ofs) (MT_DIC_CMD_REG_BASE + (ofs))
+ #define MT_DIC_CMD_REG_CMD MT_DIC_CMD_REG(0x10)
+--
+2.18.0
+
diff --git a/recipes-kernel/linux-mt76/files/patches/0017-mt76-mt7615-mt7915-do-reset_work-with-mt76-s-work-qu.patch b/recipes-kernel/linux-mt76/files/patches/0017-mt76-mt7615-mt7915-do-reset_work-with-mt76-s-work-qu.patch
new file mode 100755
index 0000000..9e20c45
--- /dev/null
+++ b/recipes-kernel/linux-mt76/files/patches/0017-mt76-mt7615-mt7915-do-reset_work-with-mt76-s-work-qu.patch
@@ -0,0 +1,43 @@
+From a56d23330b0ac01929a54c427bd338b02a7e727e Mon Sep 17 00:00:00 2001
+From: Bo Jiao <Bo.Jiao@mediatek.com>
+Date: Fri, 6 May 2022 21:06:55 +0800
+Subject: [PATCH 03/10] mt76: mt7615/mt7915: do reset_work with mt76's work
+ queue
+
+reset_work may be blocked when mcu message timeout occurs
+
+Signed-off-by: Bo Jiao <Bo.Jiao@mediatek.com>
+---
+ mt7615/mmio.c | 2 +-
+ mt7915/mmio.c | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/mt7615/mmio.c b/mt7615/mmio.c
+index ce45c3bf..a208035e 100644
+--- a/mt7615/mmio.c
++++ b/mt7615/mmio.c
+@@ -145,7 +145,7 @@ static void mt7615_irq_tasklet(struct tasklet_struct *t)
+ return;
+
+ dev->reset_state = mcu_int;
+- ieee80211_queue_work(mt76_hw(dev), &dev->reset_work);
++ queue_work(dev->mt76.wq, &dev->reset_work);
+ wake_up(&dev->reset_wait);
+ }
+
+diff --git a/mt7915/mmio.c b/mt7915/mmio.c
+index 2d733d32..4d4537cd 100644
+--- a/mt7915/mmio.c
++++ b/mt7915/mmio.c
+@@ -612,7 +612,7 @@ static void mt7915_irq_tasklet(struct tasklet_struct *t)
+ 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);
++ queue_work(dev->mt76.wq, &dev->reset_work);
+ wake_up(&dev->reset_wait);
+ }
+ }
+--
+2.18.0
+
diff --git a/recipes-kernel/linux-mt76/files/patches/0018-mt76-mt7915-add-support-for-6G-in-band-discovery.patch b/recipes-kernel/linux-mt76/files/patches/0018-mt76-mt7915-add-support-for-6G-in-band-discovery.patch
new file mode 100644
index 0000000..d710df8
--- /dev/null
+++ b/recipes-kernel/linux-mt76/files/patches/0018-mt76-mt7915-add-support-for-6G-in-band-discovery.patch
@@ -0,0 +1,282 @@
+From 3b12e37a1c903b7f30c1515b6eec481c206abb4e Mon Sep 17 00:00:00 2001
+From: MeiChia Chiu <MeiChia.Chiu@mediatek.com>
+Date: Mon, 25 Apr 2022 15:31:02 +0800
+Subject: [PATCH] mt76: mt7915: add support for 6G in-band discovery
+
+Add offloading FILS discovery and unsolicited broadcast probe response support.
+
+Reviewed-by: Ryder Lee <ryder.lee@mediatek.com>
+Signed-off-by: MeiChia Chiu <MeiChia.Chiu@mediatek.com>
+---
+ mt7915/init.c | 2 +
+ mt7915/mac.c | 17 +++--
+ mt7915/main.c | 8 +-
+ mt7915/mcu.c | 75 ++++++++++++++++++-
+ mt7915/mcu.h | 15 +++-
+ mt7915/mt7915.h | 4 +-
+ 6 files changed, 107 insertions(+), 14 deletions(-)
+
+diff --git a/mt7915/init.c b/mt7915/init.c
+index 70baad756dd0..d123ecb9fb0c 100644
+--- a/mt7915/init.c
++++ b/mt7915/init.c
+@@ -351,6 +351,8 @@ mt7915_init_wiphy(struct ieee80211_hw *hw)
+ wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HT);
+ wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_VHT);
+ wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HE);
++ wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_UNSOL_BCAST_PROBE_RESP);
++ wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_FILS_DISCOVERY);
+
+ if (!mdev->dev->of_node ||
+ !of_property_read_bool(mdev->dev->of_node,
+diff --git a/mt7915/mac.c b/mt7915/mac.c
+index e353e8c44d6c..de7bf137c234 100644
+--- a/mt7915/mac.c
++++ b/mt7915/mac.c
+@@ -1177,7 +1177,7 @@ mt7915_mac_tx_rate_val(struct mt76_phy *mphy, struct ieee80211_vif *vif,
+
+ void mt7915_mac_write_txwi(struct mt7915_dev *dev, __le32 *txwi,
+ struct sk_buff *skb, struct mt76_wcid *wcid, int pid,
+- struct ieee80211_key_conf *key, bool beacon)
++ struct ieee80211_key_conf *key, u32 changed)
+ {
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+ struct ieee80211_vif *vif = info->control.vif;
+@@ -1188,6 +1188,10 @@ void mt7915_mac_write_txwi(struct mt7915_dev *dev, __le32 *txwi,
+ bool mcast = false;
+ u16 tx_count = 15;
+ u32 val;
++ bool beacon = !!(changed & (BSS_CHANGED_BEACON |
++ BSS_CHANGED_BEACON_ENABLED));
++ bool inband_disc = !!(changed & (BSS_CHANGED_UNSOL_BCAST_PROBE_RESP |
++ BSS_CHANGED_FILS_DISCOVERY));
+
+ if (vif) {
+ struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
+@@ -1200,7 +1204,10 @@ void mt7915_mac_write_txwi(struct mt7915_dev *dev, __le32 *txwi,
+ if (ext_phy && dev->mt76.phy2)
+ mphy = dev->mt76.phy2;
+
+- if (beacon) {
++ if (inband_disc) {
++ p_fmt = MT_TX_TYPE_FW;
++ q_idx = MT_LMAC_ALTX0;
++ } else if (beacon) {
+ p_fmt = MT_TX_TYPE_FW;
+ q_idx = MT_LMAC_BCN0;
+ } else if (skb_get_queue_mapping(skb) >= MT_TXQ_PSD) {
+@@ -1308,8 +1315,7 @@ int mt7915_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
+ return id;
+
+ pid = mt76_tx_status_skb_add(mdev, wcid, tx_info->skb);
+- mt7915_mac_write_txwi(dev, txwi_ptr, tx_info->skb, wcid, pid, key,
+- false);
++ mt7915_mac_write_txwi(dev, txwi_ptr, tx_info->skb, wcid, pid, key, 0);
+
+ txp = (struct mt7915_txp *)(txwi + MT_TXD_SIZE);
+ for (i = 0; i < nbuf; i++) {
+@@ -1919,7 +1925,8 @@ mt7915_update_vif_beacon(void *priv, u8 *mac, struct ieee80211_vif *vif)
+ case NL80211_IFTYPE_MESH_POINT:
+ case NL80211_IFTYPE_ADHOC:
+ case NL80211_IFTYPE_AP:
+- mt7915_mcu_add_beacon(hw, vif, vif->bss_conf.enable_beacon);
++ mt7915_mcu_add_beacon(hw, vif, vif->bss_conf.enable_beacon,
++ BSS_CHANGED_BEACON_ENABLED);
+ break;
+ default:
+ break;
+diff --git a/mt7915/main.c b/mt7915/main.c
+index 5177b19f9154..c2c615931782 100644
+--- a/mt7915/main.c
++++ b/mt7915/main.c
+@@ -622,8 +622,10 @@ static void mt7915_bss_info_changed(struct ieee80211_hw *hw,
+ mt7915_update_bss_color(hw, vif, &info->he_bss_color);
+
+ if (changed & (BSS_CHANGED_BEACON |
+- BSS_CHANGED_BEACON_ENABLED))
+- mt7915_mcu_add_beacon(hw, vif, info->enable_beacon);
++ BSS_CHANGED_BEACON_ENABLED |
++ BSS_CHANGED_UNSOL_BCAST_PROBE_RESP |
++ BSS_CHANGED_FILS_DISCOVERY))
++ mt7915_mcu_add_beacon(hw, vif, info->enable_beacon, changed);
+
+ mutex_unlock(&dev->mt76.mutex);
+ }
+@@ -636,7 +638,7 @@ mt7915_channel_switch_beacon(struct ieee80211_hw *hw,
+ struct mt7915_dev *dev = mt7915_hw_dev(hw);
+
+ mutex_lock(&dev->mt76.mutex);
+- mt7915_mcu_add_beacon(hw, vif, true);
++ mt7915_mcu_add_beacon(hw, vif, true, BSS_CHANGED_BEACON);
+ mutex_unlock(&dev->mt76.mutex);
+ }
+
+diff --git a/mt7915/mcu.c b/mt7915/mcu.c
+index 2a07a5d2a439..87e44c69d72b 100644
+--- a/mt7915/mcu.c
++++ b/mt7915/mcu.c
+@@ -1892,6 +1892,7 @@ mt7915_mcu_beacon_cont(struct mt7915_dev *dev, struct ieee80211_vif *vif,
+ u8 *buf;
+ int len = sizeof(*cont) + MT_TXD_SIZE + skb->len;
+
++ len = (len & 0x3) ? ((len | 0x3) + 1) : len;
+ tlv = mt7915_mcu_add_nested_subtlv(rskb, BSS_INFO_BCN_CONTENT,
+ len, &bcn->sub_ntlv, &bcn->len);
+
+@@ -1910,7 +1911,7 @@ mt7915_mcu_beacon_cont(struct mt7915_dev *dev, struct ieee80211_vif *vif,
+
+ buf = (u8 *)tlv + sizeof(*cont);
+ mt7915_mac_write_txwi(dev, (__le32 *)buf, skb, wcid, 0, NULL,
+- true);
++ BSS_CHANGED_BEACON);
+ memcpy(buf + MT_TXD_SIZE, skb->data, skb->len);
+ }
+
+@@ -1992,8 +1993,71 @@ mt7915_mcu_beacon_check_caps(struct mt7915_phy *phy, struct ieee80211_vif *vif,
+ }
+ }
+
+-int mt7915_mcu_add_beacon(struct ieee80211_hw *hw,
+- struct ieee80211_vif *vif, int en)
++static void
++mt7915_mcu_beacon_inband_discov(struct mt7915_dev *dev, struct ieee80211_vif *vif,
++ struct sk_buff *rskb, struct bss_info_bcn *bcn,
++ u32 changed)
++{
++#define OFFLOAD_TX_MODE_SU BIT(0)
++#define OFFLOAD_TX_MODE_MU BIT(1)
++ struct ieee80211_hw *hw = mt76_hw(dev);
++ struct mt7915_phy *phy = mt7915_hw_phy(hw);
++ struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
++ struct cfg80211_chan_def *chandef = &mvif->phy->mt76->chandef;
++ enum nl80211_band band = chandef->chan->band;
++ struct mt76_wcid *wcid = &dev->mt76.global_wcid;
++ struct bss_info_inband_discovery *discov;
++ struct ieee80211_tx_info *info;
++ struct sk_buff *skb = NULL;
++ struct tlv *tlv;
++ bool ext_phy = phy != &dev->phy;
++ u8 *buf, interval;
++ int len;
++
++ if (changed & BSS_CHANGED_FILS_DISCOVERY &&
++ vif->bss_conf.fils_discovery.max_interval) {
++ 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 &&
++ vif->bss_conf.unsol_bcast_probe_resp_interval) {
++ interval = vif->bss_conf.unsol_bcast_probe_resp_interval;
++ skb = ieee80211_get_unsol_bcast_probe_resp_tmpl(hw, vif);
++ }
++
++ if (!skb)
++ return;
++
++ info = IEEE80211_SKB_CB(skb);
++ info->control.vif = vif;
++ info->band = band;
++
++ if (ext_phy)
++ info->hw_queue |= MT_TX_HW_QUEUE_EXT_PHY;
++
++ len = sizeof(*discov) + MT_TXD_SIZE + skb->len;
++ len = (len & 0x3) ? ((len | 0x3) + 1) : len;
++
++ tlv = mt7915_mcu_add_nested_subtlv(rskb, BSS_INFO_BCN_DISCOV,
++ len, &bcn->sub_ntlv, &bcn->len);
++ discov = (struct bss_info_inband_discovery *)tlv;
++ discov->tx_mode = OFFLOAD_TX_MODE_SU;
++ /* 0: UNSOL PROBE RESP, 1: FILS DISCOV */
++ discov->tx_type = !!(changed & BSS_CHANGED_FILS_DISCOVERY);
++ discov->tx_interval = interval;
++ discov->prob_rsp_len = cpu_to_le16(MT_TXD_SIZE + skb->len);
++ discov->enable = true;
++
++ buf = (u8 *)tlv + sizeof(*discov);
++
++ mt7915_mac_write_txwi(dev, (__le32 *)buf, skb, wcid, 0, NULL,
++ changed);
++ memcpy(buf + MT_TXD_SIZE, skb->data, skb->len);
++
++ dev_kfree_skb(skb);
++}
++
++int mt7915_mcu_add_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
++ int en, u32 changed)
+ {
+ #define MAX_BEACON_SIZE 512
+ struct mt7915_dev *dev = mt7915_hw_dev(hw);
+@@ -2044,6 +2108,11 @@ int mt7915_mcu_add_beacon(struct ieee80211_hw *hw,
+ mt7915_mcu_beacon_cont(dev, vif, rskb, skb, bcn, &offs);
+ dev_kfree_skb(skb);
+
++ if (changed & BSS_CHANGED_UNSOL_BCAST_PROBE_RESP ||
++ changed & BSS_CHANGED_FILS_DISCOVERY)
++ mt7915_mcu_beacon_inband_discov(dev, vif, rskb,
++ bcn, changed);
++
+ out:
+ return mt76_mcu_skb_send_msg(&phy->dev->mt76, rskb,
+ MCU_EXT_CMD(BSS_INFO_UPDATE), true);
+diff --git a/mt7915/mcu.h b/mt7915/mcu.h
+index 064d33e33738..e1d576701fdf 100644
+--- a/mt7915/mcu.h
++++ b/mt7915/mcu.h
+@@ -404,11 +404,23 @@ struct bss_info_bcn_cont {
+ __le16 pkt_len;
+ } __packed __aligned(4);
+
++struct bss_info_inband_discovery {
++ __le16 tag;
++ __le16 len;
++ u8 tx_type;
++ u8 tx_mode;
++ u8 tx_interval;
++ u8 enable;
++ __le16 rsv;
++ __le16 prob_rsp_len;
++} __packed __aligned(4);
++
+ enum {
+ BSS_INFO_BCN_CSA,
+ BSS_INFO_BCN_BCC,
+ BSS_INFO_BCN_MBSSID,
+ BSS_INFO_BCN_CONTENT,
++ BSS_INFO_BCN_DISCOV,
+ BSS_INFO_BCN_MAX
+ };
+
+@@ -476,6 +488,7 @@ enum {
+ #define MT7915_BEACON_UPDATE_SIZE (sizeof(struct sta_req_hdr) + \
+ sizeof(struct bss_info_bcn_cntdwn) + \
+ sizeof(struct bss_info_bcn_mbss) + \
+- sizeof(struct bss_info_bcn_cont))
++ sizeof(struct bss_info_bcn_cont) + \
++ sizeof(struct bss_info_inband_discovery))
+
+ #endif
+diff --git a/mt7915/mt7915.h b/mt7915/mt7915.h
+index 6c590eff14f1..03431012b2ff 100644
+--- a/mt7915/mt7915.h
++++ b/mt7915/mt7915.h
+@@ -464,7 +464,7 @@ int mt7915_mcu_add_rx_ba(struct mt7915_dev *dev,
+ int mt7915_mcu_update_bss_color(struct mt7915_dev *dev, struct ieee80211_vif *vif,
+ struct cfg80211_he_bss_color *he_bss_color);
+ int mt7915_mcu_add_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+- int enable);
++ int enable, u32 changed);
+ int mt7915_mcu_add_obss_spr(struct mt7915_dev *dev, struct ieee80211_vif *vif,
+ bool enable);
+ int mt7915_mcu_add_rate_ctrl(struct mt7915_dev *dev, struct ieee80211_vif *vif,
+@@ -551,7 +551,7 @@ void mt7915_mac_cca_stats_reset(struct mt7915_phy *phy);
+ void mt7915_mac_enable_nf(struct mt7915_dev *dev, bool ext_phy);
+ void mt7915_mac_write_txwi(struct mt7915_dev *dev, __le32 *txwi,
+ struct sk_buff *skb, struct mt76_wcid *wcid, int pid,
+- struct ieee80211_key_conf *key, bool beacon);
++ struct ieee80211_key_conf *key, u32 changed);
+ void mt7915_mac_set_timing(struct mt7915_phy *phy);
+ int mt7915_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta);
+--
+2.18.0
+
diff --git a/recipes-kernel/linux-mt76/files/patches/0019-mt76-mt7915-add-the-maximum-size-of-beacon-offload.patch b/recipes-kernel/linux-mt76/files/patches/0019-mt76-mt7915-add-the-maximum-size-of-beacon-offload.patch
new file mode 100644
index 0000000..db4638d
--- /dev/null
+++ b/recipes-kernel/linux-mt76/files/patches/0019-mt76-mt7915-add-the-maximum-size-of-beacon-offload.patch
@@ -0,0 +1,67 @@
+From f5a80422207b76c740f284719539419b6a3dcc89 Mon Sep 17 00:00:00 2001
+From: MeiChia Chiu <meichia.chiu@mediatek.com>
+Date: Mon, 23 May 2022 17:09:52 +0800
+Subject: [PATCH] mt76: mt7915: add the maximum size of beacon offload
+
+add the maximum size of beacon offload to avoid exceeding the size limit
+
+Signed-off-by: Money Wang <Money.Wang@mediatek.com>
+Signed-off-by: MeiChia Chiu <MeiChia.Chiu@mediatek.com>
+---
+ mt7915/mcu.c | 11 +++++++++--
+ mt7915/mcu.h | 3 +++
+ 2 files changed, 12 insertions(+), 2 deletions(-)
+
+diff --git a/mt7915/mcu.c b/mt7915/mcu.c
+index bdef2b3..8155900 100644
+--- a/mt7915/mcu.c
++++ b/mt7915/mcu.c
+@@ -2037,6 +2037,13 @@ mt7915_mcu_beacon_inband_discov(struct mt7915_dev *dev, struct ieee80211_vif *vi
+ len = sizeof(*discov) + MT_TXD_SIZE + skb->len;
+ len = (len & 0x3) ? ((len | 0x3) + 1) : len;
+
++ if (len > (MAX_BEACON_SIZE + MAX_INBND_FRME_SIZE +
++ MT7915_BEACON_UPDATE_SIZE) - rskb->len) {
++ dev_err(dev->mt76.dev, "inband discovery size limit exceed\n");
++ dev_kfree_skb(skb);
++ return;
++ }
++
+ tlv = mt7915_mcu_add_nested_subtlv(rskb, BSS_INFO_BCN_DISCOV,
+ len, &bcn->sub_ntlv, &bcn->len);
+ discov = (struct bss_info_inband_discovery *)tlv;
+@@ -2059,7 +2066,6 @@ mt7915_mcu_beacon_inband_discov(struct mt7915_dev *dev, struct ieee80211_vif *vi
+ int mt7915_mcu_add_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ int en, u32 changed)
+ {
+-#define MAX_BEACON_SIZE 512
+ struct mt7915_dev *dev = mt7915_hw_dev(hw);
+ struct mt7915_phy *phy = mt7915_hw_phy(hw);
+ struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
+@@ -2068,7 +2074,8 @@ int mt7915_mcu_add_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ struct sk_buff *skb, *rskb;
+ struct tlv *tlv;
+ struct bss_info_bcn *bcn;
+- int len = MT7915_BEACON_UPDATE_SIZE + MAX_BEACON_SIZE;
++ int len = MT7915_BEACON_UPDATE_SIZE + MAX_BEACON_SIZE +
++ MAX_INBND_FRME_SIZE;
+ bool ext_phy = phy != &dev->phy;
+
+ if (vif->bss_conf.nontransmitted)
+diff --git a/mt7915/mcu.h b/mt7915/mcu.h
+index 21aa963..d46c8da 100644
+--- a/mt7915/mcu.h
++++ b/mt7915/mcu.h
+@@ -490,6 +490,9 @@ enum {
+ SER_RECOVER
+ };
+
++#define MAX_BEACON_SIZE 512
++#define MAX_INBND_FRME_SIZE 256
++
+ #define MT7915_BSS_UPDATE_MAX_SIZE (sizeof(struct sta_req_hdr) + \
+ sizeof(struct bss_info_omac) + \
+ sizeof(struct bss_info_basic) +\
+--
+2.29.2
+
diff --git a/recipes-kernel/linux-mt76/files/patches/1001-mt76-mt7915-add-mtk-internal-debug-tools-for-mt76.patch b/recipes-kernel/linux-mt76/files/patches/1001-mt76-mt7915-add-mtk-internal-debug-tools-for-mt76.patch
index c912a30..94dff56 100755
--- a/recipes-kernel/linux-mt76/files/patches/1001-mt76-mt7915-add-mtk-internal-debug-tools-for-mt76.patch
+++ b/recipes-kernel/linux-mt76/files/patches/1001-mt76-mt7915-add-mtk-internal-debug-tools-for-mt76.patch
@@ -1,26 +1,26 @@
-From f45027dc3cee106b6119d1343f036eca4a00d9f8 Mon Sep 17 00:00:00 2001
+From 235e69804c130fd7381fd44b1853859984e97ac5 Mon Sep 17 00:00:00 2001
From: Bo Jiao <Bo.Jiao@mediatek.com>
Date: Thu, 21 Apr 2022 19:42:55 +0800
Subject: [PATCH] mt76: mt7915: add mtk internal debug tools for mt76
Signed-off-by: Bo Jiao <Bo.Jiao@mediatek.com>
---
- mt76_connac_mcu.h | 6 +
- mt7915/Makefile | 2 +-
- mt7915/debugfs.c | 72 +-
- mt7915/mac.c | 14 +
- mt7915/mcu.c | 41 +
- mt7915/mcu.h | 4 +
- mt7915/mt7915.h | 41 +
- mt7915/mt7915_debug.h | 1350 +++++++++++++++++++
- mt7915/mtk_debugfs.c | 2893 +++++++++++++++++++++++++++++++++++++++++
- mt7915/mtk_mcu.c | 51 +
- tools/fwlog.c | 26 +-
- 11 files changed, 4489 insertions(+), 11 deletions(-)
- mode change 100644 => 100755 mt7915/mcu.c
- create mode 100644 mt7915/mt7915_debug.h
- create mode 100644 mt7915/mtk_debugfs.c
- create mode 100644 mt7915/mtk_mcu.c
+ .../wireless/mediatek/mt76/mt76_connac_mcu.h | 6 +
+ .../wireless/mediatek/mt76/mt7915/Makefile | 2 +-
+ .../wireless/mediatek/mt76/mt7915/debugfs.c | 72 +-
+ .../net/wireless/mediatek/mt76/mt7915/mac.c | 14 +
+ .../net/wireless/mediatek/mt76/mt7915/mcu.c | 41 +
+ .../net/wireless/mediatek/mt76/mt7915/mcu.h | 4 +
+ .../wireless/mediatek/mt76/mt7915/mt7915.h | 41 +
+ .../mediatek/mt76/mt7915/mt7915_debug.h | 1350 ++++++++
+ .../mediatek/mt76/mt7915/mtk_debugfs.c | 2921 +++++++++++++++++
+ .../wireless/mediatek/mt76/mt7915/mtk_mcu.c | 51 +
+ .../net/wireless/mediatek/mt76/tools/fwlog.c | 44 +-
+ 11 files changed, 4533 insertions(+), 13 deletions(-)
+ mode change 100644 => 100755 drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
+ create mode 100644 drivers/net/wireless/mediatek/mt76/mt7915/mt7915_debug.h
+ create mode 100644 drivers/net/wireless/mediatek/mt76/mt7915/mtk_debugfs.c
+ create mode 100644 drivers/net/wireless/mediatek/mt76/mt7915/mtk_mcu.c
diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
index aa14d2d4..03134066 100644
@@ -54,7 +54,7 @@
mt7915e-$(CONFIG_MT7986_WMAC) += soc.o
\ No newline at end of file
diff --git a/mt7915/debugfs.c b/mt7915/debugfs.c
-index 77bbeeed..e8e26ac1 100644
+index b45181c1..27321528 100644
--- a/mt7915/debugfs.c
+++ b/mt7915/debugfs.c
@@ -8,6 +8,9 @@
@@ -67,7 +67,7 @@
/** global debugfs **/
-@@ -370,6 +373,9 @@ mt7915_fw_debug_wm_set(void *data, u64 val)
+@@ -448,6 +451,9 @@ mt7915_fw_debug_wm_set(void *data, u64 val)
int ret;
dev->fw_debug_wm = val ? MCU_FW_LOG_TO_HOST : 0;
@@ -77,7 +77,7 @@
if (dev->fw_debug_bin)
val = 16;
-@@ -394,6 +400,9 @@ mt7915_fw_debug_wm_set(void *data, u64 val)
+@@ -472,6 +478,9 @@ mt7915_fw_debug_wm_set(void *data, u64 val)
if (ret)
return ret;
}
@@ -87,7 +87,7 @@
/* WM CPU info record control */
mt76_clear(dev, MT_CPU_UTIL_CTRL, BIT(0));
-@@ -401,6 +410,12 @@ mt7915_fw_debug_wm_set(void *data, u64 val)
+@@ -479,6 +488,12 @@ mt7915_fw_debug_wm_set(void *data, u64 val)
mt76_wr(dev, MT_MCU_WM_CIRQ_IRQ_MASK_CLR_ADDR, BIT(5));
mt76_wr(dev, MT_MCU_WM_CIRQ_IRQ_SOFT_ADDR, BIT(5));
@@ -100,7 +100,7 @@
return 0;
}
-@@ -409,7 +424,11 @@ mt7915_fw_debug_wm_get(void *data, u64 *val)
+@@ -487,7 +502,11 @@ mt7915_fw_debug_wm_get(void *data, u64 *val)
{
struct mt7915_dev *dev = data;
@@ -113,7 +113,7 @@
return 0;
}
-@@ -489,6 +508,16 @@ mt7915_fw_debug_bin_set(void *data, u64 val)
+@@ -567,6 +586,16 @@ mt7915_fw_debug_bin_set(void *data, u64 val)
relay_reset(dev->relay_fwlog);
@@ -130,7 +130,7 @@
return mt7915_fw_debug_wm_set(dev, dev->fw_debug_wm);
}
-@@ -942,6 +971,11 @@ int mt7915_init_debugfs(struct mt7915_phy *phy)
+@@ -1020,6 +1049,11 @@ int mt7915_init_debugfs(struct mt7915_phy *phy)
if (!ext_phy)
dev->debugfs_dir = dir;
@@ -142,7 +142,7 @@
return 0;
}
-@@ -982,17 +1016,53 @@ void mt7915_debugfs_rx_fw_monitor(struct mt7915_dev *dev, const void *data, int
+@@ -1060,17 +1094,53 @@ void mt7915_debugfs_rx_fw_monitor(struct mt7915_dev *dev, const void *data, int
.msg_type = cpu_to_le16(PKT_TYPE_RX_FW_MONITOR),
};
@@ -197,7 +197,7 @@
if (dev->relay_fwlog)
diff --git a/mt7915/mac.c b/mt7915/mac.c
-index c1ff04ae..e8899590 100644
+index de5f3f10..ce760cdb 100644
--- a/mt7915/mac.c
+++ b/mt7915/mac.c
@@ -596,6 +596,10 @@ mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb)
@@ -211,7 +211,7 @@
memset(status, 0, sizeof(*status));
if ((rxd1 & MT_RXD1_NORMAL_BAND_IDX) && !phy->band_idx) {
-@@ -785,6 +789,10 @@ mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb)
+@@ -780,6 +784,10 @@ mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb)
}
hdr_gap = (u8 *)rxd - skb->data + 2 * remove_pad;
@@ -222,7 +222,7 @@
if (hdr_trans && ieee80211_has_morefrags(fc)) {
if (mt7915_reverse_frag0_hdr_trans(skb, hdr_gap))
return -EINVAL;
-@@ -1351,6 +1359,12 @@ int mt7915_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
+@@ -1352,6 +1360,12 @@ int mt7915_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
tx_info->buf[1].skip_unmap = true;
tx_info->nbuf = MT_CT_DMA_BUF_NUM;
@@ -238,7 +238,7 @@
diff --git a/mt7915/mcu.c b/mt7915/mcu.c
old mode 100644
new mode 100755
-index c215bc9e..bce14f4b
+index 20f32f7f..c325c4b6
--- a/mt7915/mcu.c
+++ b/mt7915/mcu.c
@@ -298,6 +298,10 @@ mt7915_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb,
@@ -252,7 +252,7 @@
if (wait_seq)
*wait_seq = seq;
-@@ -3660,6 +3664,43 @@ int mt7915_mcu_twt_agrt_update(struct mt7915_dev *dev,
+@@ -3657,6 +3661,43 @@ int mt7915_mcu_twt_agrt_update(struct mt7915_dev *dev,
&req, sizeof(req), true);
}
@@ -297,7 +297,7 @@
{
struct {
diff --git a/mt7915/mcu.h b/mt7915/mcu.h
-index df7aefca..c36cf511 100644
+index 5cbc3ecf..3f303885 100644
--- a/mt7915/mcu.h
+++ b/mt7915/mcu.h
@@ -296,6 +296,10 @@ enum {
@@ -377,7 +377,7 @@
#endif
diff --git a/mt7915/mt7915_debug.h b/mt7915/mt7915_debug.h
new file mode 100644
-index 00000000..59c057e0
+index 00000000..58ba2cdf
--- /dev/null
+++ b/mt7915/mt7915_debug.h
@@ -0,0 +1,1350 @@
@@ -623,7 +623,7 @@
+ [DBG_PLE_AC_OFFSET] = { DBG_INVALID_BASE, 0x040},
+ [DBG_PLE_STATION_PAUSE] = { DBG_INVALID_BASE, 0x400},
+ [DBG_PLE_DIS_STA_MAP] = { DBG_INVALID_BASE, 0x440},
-+ [DBG_PSE_PBUF_CTRL] = { DBG_INVALID_BASE, 0x004},
++ [DBG_PSE_PBUF_CTRL] = { DBG_INVALID_BASE, 0x014},
+ [DBG_PSE_FREEPG_CNT] = { DBG_INVALID_BASE, 0x100},
+ [DBG_PSE_FREEPG_HEAD_TAIL] = { DBG_INVALID_BASE, 0x104},
+ [DBG_PSE_HIF0_PG_INFO] = { DBG_INVALID_BASE, 0x114},
@@ -722,7 +722,7 @@
+ [DBG_PLE_CPU_PG_INFO] = { DBG_INVALID_BASE, 0x394},
+ [DBG_PLE_FL_QUE_CTRL] = { DBG_INVALID_BASE, 0x3e0},
+ [DBG_PLE_NATIVE_TXCMD_Q_EMPTY] = { DBG_INVALID_BASE, 0x370},
-+ [DBG_PLE_TXCMD_Q_EMPTY] = { DBG_INVALID_BASE, 0x374},
++ [DBG_PLE_TXCMD_Q_EMPTY] = { DBG_INVALID_BASE, 0x36c},
+ [DBG_PLE_AC_QEMPTY] = { DBG_INVALID_BASE, 0x600},
+ [DBG_PLE_AC_OFFSET] = { DBG_INVALID_BASE, 0x080},
+ [DBG_PLE_STATION_PAUSE] = { DBG_INVALID_BASE, 0x100},
@@ -1098,30 +1098,30 @@
+#define MT_DBG_PSE_BASE 0x820C8000
+#define MT_DBG_PSE(ofs) (MT_DBG_PSE_BASE + (ofs))
+
-+#define MT_DBG_PSE_PBUF_CTRL MT_DBG_PLE(__DBG_REG_OFFS(dev, DBG_PSE_PBUF_CTRL))
-+#define MT_DBG_PSE_QUEUE_EMPTY MT_DBG_PLE(0x0b0)
-+#define MT_DBG_PSE_FREEPG_CNT MT_DBG_PLE(__DBG_REG_OFFS(dev, DBG_PSE_FREEPG_CNT))
-+#define MT_DBG_PSE_FREEPG_HEAD_TAIL MT_DBG_PLE(__DBG_REG_OFFS(dev, DBG_PSE_FREEPG_HEAD_TAIL))
-+#define MT_DBG_PSE_PG_HIF0_GROUP MT_DBG_PLE(0x110)
-+#define MT_DBG_PSE_HIF0_PG_INFO MT_DBG_PLE(__DBG_REG_OFFS(dev, DBG_PSE_HIF0_PG_INFO))
-+#define MT_DBG_PSE_PG_HIF1_GROUP MT_DBG_PLE(__DBG_REG_OFFS(dev, DBG_PSE_PG_HIF1_GROUP))
-+#define MT_DBG_PSE_HIF1_PG_INFO MT_DBG_PLE(__DBG_REG_OFFS(dev, DBG_PSE_HIF1_PG_INFO))
-+#define MT_DBG_PSE_PG_CPU_GROUP MT_DBG_PLE(__DBG_REG_OFFS(dev, DBG_PSE_PG_CPU_GROUP))
-+#define MT_DBG_PSE_CPU_PG_INFO MT_DBG_PLE(__DBG_REG_OFFS(dev, DBG_PSE_CPU_PG_INFO))
-+#define MT_DBG_PSE_PG_LMAC0_GROUP MT_DBG_PLE(__DBG_REG_OFFS(dev, DBG_PSE_PG_LMAC0_GROUP))
-+#define MT_DBG_PSE_LMAC0_PG_INFO MT_DBG_PLE(__DBG_REG_OFFS(dev, DBG_PSE_LMAC0_PG_INFO))
-+#define MT_DBG_PSE_PG_LMAC1_GROUP MT_DBG_PLE(__DBG_REG_OFFS(dev, DBG_PSE_PG_LMAC1_GROUP))
-+#define MT_DBG_PSE_LMAC1_PG_INFO MT_DBG_PLE(__DBG_REG_OFFS(dev, DBG_PSE_LMAC1_PG_INFO))
-+#define MT_DBG_PSE_PG_LMAC2_GROUP MT_DBG_PLE(__DBG_REG_OFFS(dev, DBG_PSE_PG_LMAC2_GROUP))
-+#define MT_DBG_PSE_LMAC2_PG_INFO MT_DBG_PLE(__DBG_REG_OFFS(dev, DBG_PSE_LMAC2_PG_INFO))
-+#define MT_DBG_PSE_PG_PLE_GROUP MT_DBG_PLE(__DBG_REG_OFFS(dev, DBG_PSE_PG_PLE_GROUP))
-+#define MT_DBG_PSE_PLE_PG_INFO MT_DBG_PLE(__DBG_REG_OFFS(dev, DBG_PSE_PLE_PG_INFO))
-+#define MT_DBG_PSE_PG_LMAC3_GROUP MT_DBG_PLE(__DBG_REG_OFFS(dev, DBG_PSE_PG_LMAC3_GROUP))
-+#define MT_DBG_PSE_LMAC3_PG_INFO MT_DBG_PLE(__DBG_REG_OFFS(dev, DBG_PSE_LMAC3_PG_INFO))
-+#define MT_DBG_PSE_PG_MDP_GROUP MT_DBG_PLE(__DBG_REG_OFFS(dev, DBG_PSE_PG_MDP_GROUP))
-+#define MT_DBG_PSE_MDP_PG_INFO MT_DBG_PLE(__DBG_REG_OFFS(dev, DBG_PSE_MDP_PG_INFO))
-+#define MT_DBG_PSE_PG_PLE1_GROUP MT_DBG_PLE(__DBG_REG_OFFS(dev, DBG_PSE_PG_PLE1_GROUP))
-+#define MT_DBG_PSE_PLE1_PG_INFO MT_DBG_PLE(__DBG_REG_OFFS(dev, DBG_PSE_PLE1_PG_INFO))
++#define MT_DBG_PSE_PBUF_CTRL MT_DBG_PSE(__DBG_REG_OFFS(dev, DBG_PSE_PBUF_CTRL))
++#define MT_DBG_PSE_QUEUE_EMPTY MT_DBG_PSE(0x0b0)
++#define MT_DBG_PSE_FREEPG_CNT MT_DBG_PSE(__DBG_REG_OFFS(dev, DBG_PSE_FREEPG_CNT))
++#define MT_DBG_PSE_FREEPG_HEAD_TAIL MT_DBG_PSE(__DBG_REG_OFFS(dev, DBG_PSE_FREEPG_HEAD_TAIL))
++#define MT_DBG_PSE_PG_HIF0_GROUP MT_DBG_PSE(0x110)
++#define MT_DBG_PSE_HIF0_PG_INFO MT_DBG_PSE(__DBG_REG_OFFS(dev, DBG_PSE_HIF0_PG_INFO))
++#define MT_DBG_PSE_PG_HIF1_GROUP MT_DBG_PSE(__DBG_REG_OFFS(dev, DBG_PSE_PG_HIF1_GROUP))
++#define MT_DBG_PSE_HIF1_PG_INFO MT_DBG_PSE(__DBG_REG_OFFS(dev, DBG_PSE_HIF1_PG_INFO))
++#define MT_DBG_PSE_PG_CPU_GROUP MT_DBG_PSE(__DBG_REG_OFFS(dev, DBG_PSE_PG_CPU_GROUP))
++#define MT_DBG_PSE_CPU_PG_INFO MT_DBG_PSE(__DBG_REG_OFFS(dev, DBG_PSE_CPU_PG_INFO))
++#define MT_DBG_PSE_PG_LMAC0_GROUP MT_DBG_PSE(__DBG_REG_OFFS(dev, DBG_PSE_PG_LMAC0_GROUP))
++#define MT_DBG_PSE_LMAC0_PG_INFO MT_DBG_PSE(__DBG_REG_OFFS(dev, DBG_PSE_LMAC0_PG_INFO))
++#define MT_DBG_PSE_PG_LMAC1_GROUP MT_DBG_PSE(__DBG_REG_OFFS(dev, DBG_PSE_PG_LMAC1_GROUP))
++#define MT_DBG_PSE_LMAC1_PG_INFO MT_DBG_PSE(__DBG_REG_OFFS(dev, DBG_PSE_LMAC1_PG_INFO))
++#define MT_DBG_PSE_PG_LMAC2_GROUP MT_DBG_PSE(__DBG_REG_OFFS(dev, DBG_PSE_PG_LMAC2_GROUP))
++#define MT_DBG_PSE_LMAC2_PG_INFO MT_DBG_PSE(__DBG_REG_OFFS(dev, DBG_PSE_LMAC2_PG_INFO))
++#define MT_DBG_PSE_PG_PLE_GROUP MT_DBG_PSE(__DBG_REG_OFFS(dev, DBG_PSE_PG_PLE_GROUP))
++#define MT_DBG_PSE_PLE_PG_INFO MT_DBG_PSE(__DBG_REG_OFFS(dev, DBG_PSE_PLE_PG_INFO))
++#define MT_DBG_PSE_PG_LMAC3_GROUP MT_DBG_PSE(__DBG_REG_OFFS(dev, DBG_PSE_PG_LMAC3_GROUP))
++#define MT_DBG_PSE_LMAC3_PG_INFO MT_DBG_PSE(__DBG_REG_OFFS(dev, DBG_PSE_LMAC3_PG_INFO))
++#define MT_DBG_PSE_PG_MDP_GROUP MT_DBG_PSE(__DBG_REG_OFFS(dev, DBG_PSE_PG_MDP_GROUP))
++#define MT_DBG_PSE_MDP_PG_INFO MT_DBG_PSE(__DBG_REG_OFFS(dev, DBG_PSE_MDP_PG_INFO))
++#define MT_DBG_PSE_PG_PLE1_GROUP MT_DBG_PSE(__DBG_REG_OFFS(dev, DBG_PSE_PG_PLE1_GROUP))
++#define MT_DBG_PSE_PLE1_PG_INFO MT_DBG_PSE(__DBG_REG_OFFS(dev, DBG_PSE_PLE1_PG_INFO))
+
+#define MT_DBG_PSE_PBUF_CTRL_PAGE_SIZE_CFG_MASK BIT(31)
+#define MT_DBG_PSE_PBUF_CTRL_PBUF_OFFSET_MASK GENMASK(25, 17)
@@ -1733,10 +1733,10 @@
+#endif
diff --git a/mt7915/mtk_debugfs.c b/mt7915/mtk_debugfs.c
new file mode 100644
-index 00000000..246eb129
+index 00000000..ccaaea78
--- /dev/null
+++ b/mt7915/mtk_debugfs.c
-@@ -0,0 +1,2893 @@
+@@ -0,0 +1,2921 @@
+#include<linux/inet.h>
+#include "mt7915.h"
+#include "mt7915_debug.h"
@@ -1968,6 +1968,23 @@
+#define LWTBL_LEN_IN_DW 32
+#define UWTBL_LEN_IN_DW 8
+#define ONE_KEY_ENTRY_LEN_IN_DW 8
++static int mt7915_sta_info(struct seq_file *s, void *data)
++{
++ struct mt7915_dev *dev = dev_get_drvdata(s->private);
++ u8 lwtbl[LWTBL_LEN_IN_DW*4] = {0};
++ u16 i = 0;
++
++ for (i=0; i < mt7915_wtbl_size(dev); i++) {
++ mt7915_wtbl_read_raw(dev, i, WTBL_TYPE_LMAC, 0,
++ LWTBL_LEN_IN_DW, lwtbl);
++ if (lwtbl[4] || lwtbl[5] || lwtbl[6] || lwtbl[7] || lwtbl[0] || lwtbl[1])
++ seq_printf(s, "wcid:%d\tAddr: %02x:%02x:%02x:%02x:%02x:%02x\n",
++ i, lwtbl[4], lwtbl[5], lwtbl[6], lwtbl[7], lwtbl[0], lwtbl[1]);
++ }
++
++ return 0;
++}
++
+static int mt7915_wtbl_read(struct seq_file *s, void *data)
+{
+ struct mt7915_dev *dev = dev_get_drvdata(s->private);
@@ -2893,7 +2910,7 @@
+ return 0;
+}
+
-+#define CR_NUM_OF_AC 9
++#define CR_NUM_OF_AC 17
+
+typedef enum _ENUM_UMAC_PORT_T {
+ ENUM_UMAC_HIF_PORT_0 = 0,
@@ -3023,16 +3040,15 @@
+ u32 ac_num = 9, all_ac_num;
+
+ /* TDO: ac_num = 16 for mt7986 */
-+ /* if (!is_mt7915(&dev->mt76))
-+ ac_num = 16;
-+ */
++ if (!is_mt7915(&dev->mt76))
++ ac_num = 17;
+
+ all_ac_num = ac_num * 4;
+
+ for (j = 0; j < all_ac_num; j++) { /* show AC Q info */
+ for (i = 0; i < 32; i++) {
+ if (((ple_stat[j + 1] & (0x1 << i)) >> i) == 0) {
-+ u32 hfid, tfid, pktcnt, ac_num = j / ac_num, ctrl = 0;
++ u32 hfid, tfid, pktcnt, ac_n = j / ac_num, ctrl = 0;
+ u32 sta_num = i + (j % ac_num) * 32, fl_que_ctrl[3] = {0};
+ //struct wifi_dev *wdev = wdev_search_by_wcid(pAd, sta_num);
+ u32 wmmidx = 0;
@@ -3044,16 +3060,16 @@
+ sta = wcid_to_sta(wcid);
+ if (!sta) {
+ printk("ERROR!! no found STA wcid=%d\n", sta_num);
-+ return 0;
++ continue;
+ }
+ msta = container_of(wcid, struct mt7915_sta, wcid);
+ wmmidx = msta->vif->mt76.wmm_idx;
+
-+ seq_printf(s, "\tSTA%d AC%d: ", sta_num, ac_num);
++ seq_printf(s, "\tSTA%d AC%d: ", sta_num, ac_n);
+
+ fl_que_ctrl[0] |= MT_DBG_PLE_FL_QUE_CTRL0_EXECUTE_MASK;
+ fl_que_ctrl[0] |= (ENUM_UMAC_LMAC_PORT_2 << MT_PLE_FL_QUE_CTRL0_Q_BUF_PID_SHFT);
-+ fl_que_ctrl[0] |= (ac_num << MT_PLE_FL_QUE_CTRL0_Q_BUF_QID_SHFT);
++ fl_que_ctrl[0] |= (ac_n << MT_PLE_FL_QUE_CTRL0_Q_BUF_QID_SHFT);
+ fl_que_ctrl[0] |= sta_num;
+ mt76_wr(dev, MT_DBG_PLE_FL_QUE_CTRL0, fl_que_ctrl[0]);
+ fl_que_ctrl[1] = mt76_rr(dev, MT_DBG_PLE_FL_QUE_CTRL2);
@@ -3090,7 +3106,7 @@
+ int i;
+
+ seq_printf(s, "Nonempty TXCMD Q info:\n");
-+ for (i = 0; i < 31; i++) {
++ for (i = 0; i < 32; i++) {
+ if (((ple_txcmd_stat & (0x1 << i)) >> i) == 0) {
+ u32 hfid, tfid, pktcnt, fl_que_ctrl[3] = {0};
+
@@ -3123,10 +3139,9 @@
+ u32 ac , index;
+
+ /* TDO: cr_num = 16 for mt7986 */
-+ /*
+ if(!is_mt7915(&dev->mt76))
-+ cr_num = 16;
-+ */
++ cr_num = 17;
++
+ all_cr_num = cr_num * 4;
+
+ ple_stat[0] = mt76_rr(dev, MT_DBG_PLE_QUEUE_EMPTY);
@@ -3143,8 +3158,13 @@
+static void chip_get_dis_sta_map(struct mt7915_dev *dev, u32 *dis_sta_map)
+{
+ int i;
++ u32 ac_num = 9;
++
++ /* TDO: ac_num = 16 for mt7986 */
++ if (!is_mt7915(&dev->mt76))
++ ac_num = 17;
+
-+ for(i = 0; i < CR_NUM_OF_AC; i++) {
++ for(i = 0; i < ac_num; i++) {
+ dis_sta_map[i] = mt76_rr(dev, MT_DBG_PLE_DIS_STA_MAP(i));
+ }
+}
@@ -3152,8 +3172,13 @@
+static void chip_get_sta_pause(struct mt7915_dev *dev, u32 *sta_pause)
+{
+ int i;
++ u32 ac_num = 9;
+
-+ for(i = 0; i < CR_NUM_OF_AC; i++) {
++ /* TDO: ac_num = 16 for mt7986 */
++ if (!is_mt7915(&dev->mt76))
++ ac_num = 17;
++
++ for(i = 0; i < ac_num; i++) {
+ sta_pause[i] = mt76_rr(dev, MT_DBG_PLE_STATION_PAUSE(i));
+ }
+}
@@ -3162,7 +3187,7 @@
+{
+ struct mt7915_dev *dev = dev_get_drvdata(s->private);
+ u32 ple_buf_ctrl, pg_sz, pg_num;
-+ u32 ple_stat[65] = {0}, pg_flow_ctrl[8] = {0};
++ u32 ple_stat[70] = {0}, pg_flow_ctrl[8] = {0};
+ u32 ple_native_txcmd_stat;
+ u32 ple_txcmd_stat;
+ u32 sta_pause[CR_NUM_OF_AC] = {0}, dis_sta_map[CR_NUM_OF_AC] = {0};
@@ -3172,9 +3197,8 @@
+ u32 ac_num = 9, all_ac_num;
+
+ /* TDO: ac_num = 16 for mt7986 */
-+ /* if (!is_mt7915(&dev->mt76))
-+ ac_num = 16;
-+ */
++ if (!is_mt7915(&dev->mt76))
++ ac_num = 17;
+
+ all_ac_num = ac_num * 4;
+
@@ -3240,15 +3264,17 @@
+ seq_printf(s, "\tHIF_TXCMD group page status(0x%x): 0x%08x\n",
+ MT_DBG_PLE_HIF_TXCMD_PG_INFO, pg_flow_ctrl[7]);
+ cpu_min_q = FIELD_GET(MT_DBG_PLE_PG_HIF_TXCMD_GROUP_HIF_TXCMD_MIN_QUOTA_MASK, pg_flow_ctrl[6]);
-+ cpu_max_q = FIELD_GET(MT_DBG_PLE_PG_HIF_TXCMD_GROUP_HIF_TXCMD_MIN_QUOTA_MASK, pg_flow_ctrl[6]);
++ cpu_max_q = FIELD_GET(MT_DBG_PLE_PG_HIF_TXCMD_GROUP_HIF_TXCMD_MAX_QUOTA_MASK, pg_flow_ctrl[6]);
+ seq_printf(s, "\t\tThe max/min quota pages of HIF_TXCMD group=0x%03x/0x%03x\n", cpu_max_q, cpu_min_q);
+
+ rpg_cpu = FIELD_GET(MT_DBG_PLE_TXCMD_PG_INFO_HIF_TXCMD_RSV_CNT_MASK, pg_flow_ctrl[7]);
+ upg_cpu = FIELD_GET(MT_DBG_PLE_TXCMD_PG_INFO_HIF_TXCMD_SRC_CNT_MASK, pg_flow_ctrl[7]);
+ seq_printf(s, "\t\tThe used/reserved pages of HIF_TXCMD group=0x%03x/0x%03x\n", upg_cpu, rpg_cpu);
+
-+ seq_printf(s, "\tReserved page counter of CPU group(0x820c0150): 0x%08x\n", pg_flow_ctrl[4]);
-+ seq_printf(s, "\tCPU group page status(0x820c0154): 0x%08x\n", pg_flow_ctrl[5]);
++ seq_printf(s, "\tReserved page counter of CPU group(0x%x): 0x%08x\n",
++ MT_DBG_PLE_PG_CPU_GROUP, pg_flow_ctrl[4]);
++ seq_printf(s, "\tCPU group page status(0x%x): 0x%08x\n",
++ MT_DBG_PLE_CPU_PG_INFO, pg_flow_ctrl[5]);
+ cpu_min_q = FIELD_GET(MT_DBG_PLE_PG_CPU_GROUP_CPU_MIN_QUOTA_MASK, pg_flow_ctrl[4]);
+ cpu_max_q = FIELD_GET(MT_DBG_PLE_PG_CPU_GROUP_CPU_MAX_QUOTA_MASK, pg_flow_ctrl[4]);
+ seq_printf(s, "\t\tThe max/min quota pages of CPU group=0x%03x/0x%03x\n", cpu_max_q, cpu_min_q);
@@ -3263,7 +3289,7 @@
+ seq_printf(s, "\n\tNonempty AC%d Q of STA#: ", j / ac_num);
+ }
+
-+ for (i = 0; i < all_ac_num; i++) {
++ for (i = 0; i < 32; i++) {
+ if (((ple_stat[j + 1] & (0x1 << i)) >> i) == 0) {
+ seq_printf(s, "%d ", i + (j % ac_num) * 32);
+ }
@@ -3277,7 +3303,7 @@
+
+ seq_printf(s, "Nonempty Q info:\n");
+
-+ for (i = 0; i < all_ac_num; i++) {
++ for (i = 0; i < 32; i++) {
+ if (((ple_stat[0] & (0x1 << i)) >> i) == 0) {
+ u32 hfid, tfid, pktcnt, fl_que_ctrl[3] = {0};
+
@@ -4575,6 +4601,8 @@
+ debugfs_create_file("fw_debug_level", 0600, dir, dev,
+ &fops_fw_debug_level);
+
++ debugfs_create_devm_seqfile(dev->mt76.dev, "sta_info", dir,
++ mt7915_sta_info);
+ debugfs_create_devm_seqfile(dev->mt76.dev, "wtbl_info", dir,
+ mt7915_wtbl_read);
+ debugfs_create_devm_seqfile(dev->mt76.dev, "uwtbl_info", dir,
@@ -4688,7 +4716,7 @@
+ sizeof(req), true);
+}
diff --git a/tools/fwlog.c b/tools/fwlog.c
-index e5d4a105..58a976a9 100644
+index e5d4a105..3d51d9ec 100644
--- a/tools/fwlog.c
+++ b/tools/fwlog.c
@@ -26,7 +26,7 @@ static const char *debugfs_path(const char *phyname, const char *file)
@@ -4723,19 +4751,35 @@
struct sockaddr_in local = {
.sin_family = AF_INET,
.sin_addr.s_addr = INADDR_ANY,
-@@ -84,9 +91,9 @@ int mt76_fwlog(const char *phyname, int argc, char **argv)
+@@ -84,9 +91,10 @@ int mt76_fwlog(const char *phyname, int argc, char **argv)
.sin_family = AF_INET,
.sin_port = htons(55688),
};
- char buf[1504];
+ char *buf = calloc(BUF_SIZE, sizeof(char));
++ FILE *logfile = NULL;
int ret = 0;
- int yes = 1;
+ /* int yes = 1; */
int s, fd;
if (argc < 1) {
-@@ -105,13 +112,13 @@ int mt76_fwlog(const char *phyname, int argc, char **argv)
+@@ -99,19 +107,28 @@ int mt76_fwlog(const char *phyname, int argc, char **argv)
+ return 1;
+ }
+
++ if (argc == 3) {
++ fprintf(stdout, "start logging to file %s\n", argv[2]);
++ logfile = fopen(argv[2], "wb");
++ if (!logfile) {
++ perror("fopen");
++ return 1;
++ }
++ }
++
+ s = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ if (s < 0) {
+ perror("socket");
return 1;
}
@@ -4751,7 +4795,7 @@
return 1;
fd = open(debugfs_path(phyname, "fwlog_data"), O_RDONLY);
-@@ -145,8 +152,8 @@ int mt76_fwlog(const char *phyname, int argc, char **argv)
+@@ -145,8 +162,8 @@ int mt76_fwlog(const char *phyname, int argc, char **argv)
if (!r)
continue;
@@ -4762,16 +4806,29 @@
ret = 1;
break;
}
+@@ -164,14 +181,19 @@ int mt76_fwlog(const char *phyname, int argc, char **argv)
+ break;
+ }
-@@ -171,7 +178,8 @@ int mt76_fwlog(const char *phyname, int argc, char **argv)
+
+- /* send buf */
+- sendto(s, buf, len, 0, (struct sockaddr *)&remote, sizeof(remote));
++ if (logfile)
++ fwrite(buf, 1, len, logfile);
++ else
++ /* send buf */
++ sendto(s, buf, len, 0, (struct sockaddr *)&remote, sizeof(remote));
+ }
+
close(fd);
out:
- mt76_set_fwlog_en(phyname, false);
+ mt76_set_fwlog_en(phyname, false, NULL);
+ free(buf);
++ fclose(logfile);
return ret;
}
--
-2.18.0
+2.25.1
diff --git a/recipes-kernel/linux-mt76/files/patches/1004-mt76-mt7915-add-support-for-muru_onoff-via-debugfs.patch b/recipes-kernel/linux-mt76/files/patches/1004-mt76-mt7915-add-support-for-muru_onoff-via-debugfs.patch
index d72aab5..31bdbf4 100644
--- a/recipes-kernel/linux-mt76/files/patches/1004-mt76-mt7915-add-support-for-muru_onoff-via-debugfs.patch
+++ b/recipes-kernel/linux-mt76/files/patches/1004-mt76-mt7915-add-support-for-muru_onoff-via-debugfs.patch
@@ -1,4 +1,4 @@
-From cdccb674bc75292020be6894dcea162e585dc5ce Mon Sep 17 00:00:00 2001
+From 6820d00b2fd86c760e281ea6e3e114cf2779cb12 Mon Sep 17 00:00:00 2001
From: MeiChia Chiu <meichia.chiu@mediatek.com>
Date: Mon, 28 Mar 2022 09:19:29 +0800
Subject: [PATCH] mt76: mt7915: add support for muru_onoff via debugfs
@@ -12,7 +12,7 @@
5 files changed, 49 insertions(+), 4 deletions(-)
diff --git a/mt7915/init.c b/mt7915/init.c
-index dbcdf147..c58f045f 100644
+index ad2a9c9f..3eaf7916 100644
--- a/mt7915/init.c
+++ b/mt7915/init.c
@@ -574,6 +574,7 @@ static void mt7915_init_work(struct work_struct *work)
@@ -24,7 +24,7 @@
void mt7915_wfsys_reset(struct mt7915_dev *dev)
diff --git a/mt7915/mcu.c b/mt7915/mcu.c
-index 26831327..95825062 100644
+index c7694819..cbcd3bd4 100755
--- a/mt7915/mcu.c
+++ b/mt7915/mcu.c
@@ -944,6 +944,7 @@ mt7915_mcu_sta_muru_tlv(struct sk_buff *skb, struct ieee80211_sta *sta,
@@ -55,10 +55,10 @@
if (sta->vht_cap.vht_supported)
muru->mimo_dl.vht_mu_bfee =
diff --git a/mt7915/mcu.h b/mt7915/mcu.h
-index 007282d4..a5e5afae 100644
+index f166eaea..ccb1c9d0 100644
--- a/mt7915/mcu.h
+++ b/mt7915/mcu.h
-@@ -569,4 +569,10 @@ struct csi_data {
+@@ -573,4 +573,10 @@ struct csi_data {
};
#endif
@@ -70,7 +70,7 @@
+
#endif
diff --git a/mt7915/mt7915.h b/mt7915/mt7915.h
-index 9960785e..ec844dbe 100644
+index 1b37cef7..e6b87239 100644
--- a/mt7915/mt7915.h
+++ b/mt7915/mt7915.h
@@ -390,6 +390,7 @@ struct mt7915_dev {
@@ -82,10 +82,10 @@
const struct mt7915_dbg_reg_desc *dbg_reg;
#endif
diff --git a/mt7915/mtk_debugfs.c b/mt7915/mtk_debugfs.c
-index 246eb129..6c48f115 100644
+index ccaaea78..d2dbae45 100644
--- a/mt7915/mtk_debugfs.c
+++ b/mt7915/mtk_debugfs.c
-@@ -2454,6 +2454,38 @@ static int mt7915_token_txd_read(struct seq_file *s, void *data)
+@@ -2480,6 +2480,38 @@ static int mt7915_token_txd_read(struct seq_file *s, void *data)
return 0;
}
@@ -124,7 +124,7 @@
static int mt7915_amsduinfo_read(struct seq_file *s, void *data)
{
struct mt7915_dev *dev = dev_get_drvdata(s->private);
-@@ -2831,6 +2863,7 @@ int mt7915_mtk_init_debugfs(struct mt7915_phy *phy, struct dentry *dir)
+@@ -2857,6 +2889,7 @@ int mt7915_mtk_init_debugfs(struct mt7915_phy *phy, struct dentry *dir)
mt7915_mcu_fw_log_2_host(dev, MCU_FW_LOG_WM, 0);
diff --git a/recipes-kernel/linux-mt76/files/patches/1007-mt76-mt7915-add-L0.5-system-error-recovery-support.patch b/recipes-kernel/linux-mt76/files/patches/1007-mt76-mt7915-add-L0.5-system-error-recovery-support.patch
new file mode 100755
index 0000000..20ccd9d
--- /dev/null
+++ b/recipes-kernel/linux-mt76/files/patches/1007-mt76-mt7915-add-L0.5-system-error-recovery-support.patch
@@ -0,0 +1,935 @@
+From ce9d865db52e49410af55a3b348f00ed1511ccbc Mon Sep 17 00:00:00 2001
+From: Bo Jiao <Bo.Jiao@mediatek.com>
+Date: Thu, 5 May 2022 16:25:44 +0800
+Subject: [PATCH 04/10] mt76: mt7915: add L0.5 system error recovery support
+
+add L0.5 system error recovery support
+auto trigger l0.5 ser when detect fw exception or mem dma hang.
+
+Signed-off-by: Bo Jiao <Bo.Jiao@mediatek.com>
+---
+ mt7915/debugfs.c | 88 ++++++++++++---
+ mt7915/dma.c | 48 ++++++++
+ mt7915/init.c | 8 +-
+ mt7915/mac.c | 280 +++++++++++++++++++++++++++++++++++++----------
+ mt7915/main.c | 20 +++-
+ mt7915/mcu.c | 96 ++++++++++++++--
+ mt7915/mcu.h | 3 +-
+ mt7915/mmio.c | 8 +-
+ mt7915/mt7915.h | 23 ++++
+ mt7915/regs.h | 16 +++
+ 10 files changed, 493 insertions(+), 97 deletions(-)
+
+diff --git a/mt7915/debugfs.c b/mt7915/debugfs.c
+index b45181c1..f07df470 100644
+--- a/mt7915/debugfs.c
++++ b/mt7915/debugfs.c
+@@ -49,12 +49,17 @@ static ssize_t
+ mt7915_fw_ser_set(struct file *file, const char __user *user_buf,
+ size_t count, loff_t *ppos)
+ {
++#define SER_LEVEL GENMASK(3, 0)
++#define SER_ACTION GENMASK(11, 8)
++
+ struct mt7915_phy *phy = file->private_data;
+ struct mt7915_dev *dev = phy->dev;
+- bool ext_phy = phy != &dev->phy;
++ u8 ser_action, ser_set, set_val;
++ u8 band_idx = phy->band_idx;
+ char buf[16];
+ int ret = 0;
+ u16 val;
++ u32 intr;
+
+ if (count >= sizeof(buf))
+ return -EINVAL;
+@@ -70,28 +75,71 @@ mt7915_fw_ser_set(struct file *file, const char __user *user_buf,
+ if (kstrtou16(buf, 0, &val))
+ return -EINVAL;
+
+- switch (val) {
++ ser_action = FIELD_GET(SER_ACTION, val);
++ ser_set = set_val = FIELD_GET(SER_LEVEL, val);
++
++ switch (ser_action) {
+ case SER_QUERY:
+ /* grab firmware SER stats */
+- ret = mt7915_mcu_set_ser(dev, 0, 0, ext_phy);
++ ser_set = 0;
+ break;
+- 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 = mt7915_mcu_set_ser(dev, SER_ENABLE, BIT(val), ext_phy);
+- if (ret)
+- return ret;
+-
+- ret = mt7915_mcu_set_ser(dev, SER_RECOVER, val, ext_phy);
++ case SER_SET:
++ /*
++ * 0x100: disable system error recovery function.
++ * 0x101: enable system error recovery function.
++ * 0x103: enable l0.5 recover function.
++ */
++ ser_set = !!set_val;
++
++ dev->ser.reset_enable = ser_set;
++ intr = mt76_rr(dev, MT_WFDMA0_MCU_HOST_INT_ENA);
++ if (dev->ser.reset_enable)
++ intr |= MT_MCU_CMD_WDT_MASK;
++ else
++ intr &= ~MT_MCU_CMD_WDT_MASK;
++ mt76_set(dev, MT_WFDMA0_MCU_HOST_INT_ENA, intr);
+ break;
+- default:
++ case SER_ENABLE:
++ /*
++ * 0x200: enable system error tracking.
++ * 0x201: enable system error L1 recover.
++ * 0x202: enable system error L2 recover.
++ * 0x203: enable system error L3 rx abort.
++ * 0x204: enable system error L3 tx abort.
++ * 0x205: enable system error L3 tx disable.
++ * 0x206: enable system error L3 bf recover.
++ * 0x207: enable system error all recover.
++ */
++ ser_set = set_val > 7 ? 0x7f : BIT(set_val);
++ break;
++ case SER_RECOVER:
++ /*
++ * 0x300: trigger L0.5 recover.
++ * 0x301: trigger L1 recover.
++ * 0x302: trigger L2 recover.
++ * 0x303: trigger L3 rx abort.
++ * 0x304: trigger L3 tx abort
++ * 0x305: trigger L3 tx disable.
++ * 0x306: trigger L3 bf recover.
++ */
++ if (!ser_set) {
++ if (dev->ser.reset_enable) {
++ dev->reset_state |= MT_MCU_CMD_WDT_MASK;
++ mt7915_reset(dev);
++ } else {
++ dev_info(dev->mt76.dev, "SER: chip full recovery not enable\n");
++ }
++ goto out;
++ }
+ break;
++ default:
++ goto out;
+ }
+-
+- return ret ? ret : count;
++ ret = mt7915_mcu_set_ser(dev, ser_action, ser_set, band_idx);
++ if (ret)
++ return ret;
++out:
++ return count;
+ }
+
+ static ssize_t
+@@ -140,6 +188,12 @@ mt7915_fw_ser_get(struct file *file, char __user *user_buf,
+ "::E R , SER_LMAC_WISR7_B1 = 0x%08x\n",
+ mt76_rr(dev, MT_SWDEF_LAMC_WISR7_BN1_STATS));
+
++ desc += scnprintf(buff + desc, bufsz - desc,
++ "\nWF RESET STATUS: EN %d, WM %d, WA %d\n",
++ dev->ser.reset_enable,
++ dev->ser.wf_reset_wm_count,
++ dev->ser.wf_reset_wa_count);
++
+ ret = simple_read_from_buffer(user_buf, count, ppos, buff, desc);
+ kfree(buff);
+ return ret;
+diff --git a/mt7915/dma.c b/mt7915/dma.c
+index c2d655cd..9e3d14db 100644
+--- a/mt7915/dma.c
++++ b/mt7915/dma.c
+@@ -486,6 +486,54 @@ int mt7915_dma_init(struct mt7915_dev *dev, struct mt7915_phy *phy2)
+ return 0;
+ }
+
++int mt7915_dma_reset(struct mt7915_dev *dev, bool force)
++{
++ struct mt76_phy *mphy_ext = dev->mt76.phy2;
++ int i;
++
++ /* clean up hw queues */
++ for (i = 0; i < ARRAY_SIZE(dev->mt76.phy.q_tx); i++) {
++ mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[i], true);
++ if (mphy_ext)
++ mt76_queue_tx_cleanup(dev, mphy_ext->q_tx[i], true);
++ }
++
++ for (i = 0; i < ARRAY_SIZE(dev->mt76.q_mcu); i++)
++ mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[i], true);
++
++ mt76_for_each_q_rx(&dev->mt76, i)
++ mt76_queue_rx_cleanup(dev, &dev->mt76.q_rx[i]);
++
++ /* reset wfsys */
++ if (force)
++ mt7915_wfsys_reset(dev);
++
++ /* disable wfdma */
++ mt7915_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 (mphy_ext)
++ mt76_queue_reset(dev, mphy_ext->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);
++
++ mt7915_dma_enable(dev);
++
++ mt76_for_each_q_rx(&dev->mt76, i)
++ mt76_queue_rx_reset(dev, i);
++
++ return 0;
++}
++
+ void mt7915_dma_cleanup(struct mt7915_dev *dev)
+ {
+ mt7915_dma_disable(dev, true);
+diff --git a/mt7915/init.c b/mt7915/init.c
+index 1c956d3d..4984ec8f 100644
+--- a/mt7915/init.c
++++ b/mt7915/init.c
+@@ -262,7 +262,7 @@ static void mt7915_led_set_brightness(struct led_classdev *led_cdev,
+ mt7915_led_set_config(led_cdev, 0xff, 0);
+ }
+
+-static void
++void
+ mt7915_init_txpower(struct mt7915_dev *dev,
+ struct ieee80211_supported_band *sband)
+ {
+@@ -441,7 +441,7 @@ mt7915_mac_init_band(struct mt7915_dev *dev, u8 band)
+ mt76_clear(dev, MT_DMA_DCR0(band), MT_DMA_DCR0_RXD_G5_EN);
+ }
+
+-static void mt7915_mac_init(struct mt7915_dev *dev)
++void mt7915_mac_init(struct mt7915_dev *dev)
+ {
+ int i;
+ u32 rx_len = is_mt7915(&dev->mt76) ? 0x400 : 0x680;
+@@ -471,7 +471,7 @@ static void mt7915_mac_init(struct mt7915_dev *dev)
+ }
+ }
+
+-static int mt7915_txbf_init(struct mt7915_dev *dev)
++int mt7915_txbf_init(struct mt7915_dev *dev)
+ {
+ int ret;
+
+@@ -1112,6 +1112,8 @@ int mt7915_register_device(struct mt7915_dev *dev)
+
+ mt7915_init_debugfs(&dev->phy);
+
++ dev->ser.hw_init_done = true;
++
+ return 0;
+
+ unreg_thermal:
+diff --git a/mt7915/mac.c b/mt7915/mac.c
+index de5f3f10..1a1798d2 100644
+--- a/mt7915/mac.c
++++ b/mt7915/mac.c
+@@ -3,6 +3,7 @@
+
+ #include <linux/etherdevice.h>
+ #include <linux/timekeeping.h>
++#include <linux/pci.h>
+ #include "mt7915.h"
+ #include "../dma.h"
+ #include "mac.h"
+@@ -2037,85 +2038,188 @@ mt7915_update_beacons(struct mt7915_dev *dev)
+ mt7915_update_vif_beacon, dev->mt76.phy2->hw);
+ }
+
+-static void
+-mt7915_dma_reset(struct mt7915_dev *dev)
++void mt7915_tx_token_put(struct mt7915_dev *dev)
+ {
+- struct mt76_phy *mphy_ext = dev->mt76.phy2;
+- 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) {
++ mt7915_txwi_free(dev, txwi, NULL, NULL);
++ dev->mt76.token_count--;
++ }
++ spin_unlock_bh(&dev->mt76.token_lock);
++ idr_destroy(&dev->mt76.token);
++}
+
+- if (is_mt7915(&dev->mt76))
+- mt76_clear(dev, MT_WFDMA1_GLO_CFG,
+- MT_WFDMA1_GLO_CFG_TX_DMA_EN |
+- MT_WFDMA1_GLO_CFG_RX_DMA_EN);
++static int
++mt7915_mac_reset(struct mt7915_dev *dev)
++{
++ struct mt7915_phy *phy2;
++ struct mt76_phy *ext_phy;
++ struct mt76_dev *mdev = &dev->mt76;
++ int i, ret;
++ u32 irq_mask;
++
++ ext_phy = dev->mt76.phy2;
++ phy2 = ext_phy ? ext_phy->priv : NULL;
++
++ /* irq disable */
++ mt76_wr(dev, MT_INT_MASK_CSR, 0x0);
++ mt76_wr(dev, MT_INT_SOURCE_CSR, ~0);
+ 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);
++ mt76_wr(dev, MT_INT1_MASK_CSR, 0x0);
++ mt76_wr(dev, MT_INT1_SOURCE_CSR, ~0);
++ }
++ 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);
++ }
+
+- if (is_mt7915(&dev->mt76))
+- mt76_clear(dev, MT_WFDMA1_GLO_CFG + hif1_ofs,
+- MT_WFDMA1_GLO_CFG_TX_DMA_EN |
+- MT_WFDMA1_GLO_CFG_RX_DMA_EN);
++ set_bit(MT76_RESET, &dev->mphy.state);
++ set_bit(MT76_MCU_RESET, &dev->mphy.state);
++ wake_up(&dev->mt76.mcu.wait);
++ if (ext_phy) {
++ set_bit(MT76_RESET, &ext_phy->state);
++ set_bit(MT76_MCU_RESET, &ext_phy->state);
+ }
+
+- usleep_range(1000, 2000);
++ /* lock/unlock all queues to ensure that no tx is pending */
++ mt76_txq_schedule_all(&dev->mphy);
++ if (ext_phy)
++ mt76_txq_schedule_all(ext_phy);
+
+- for (i = 0; i < __MT_TXQ_MAX; i++) {
+- mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[i], true);
+- if (mphy_ext)
+- mt76_queue_tx_cleanup(dev, mphy_ext->q_tx[i], true);
++ /* 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);
+
+- 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);
++ /* token reinit */
++ mt7915_tx_token_put(dev);
++ idr_init(&dev->mt76.token);
+
+- mt76_tx_status_check(&dev->mt76, true);
++ mt7915_dma_reset(dev, true);
+
+- /* re-init prefetch settings after reset */
+- mt7915_dma_prefetch(dev);
++ 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_set(dev, MT_WFDMA0_GLO_CFG,
+- MT_WFDMA0_GLO_CFG_TX_DMA_EN | MT_WFDMA0_GLO_CFG_RX_DMA_EN);
+- if (is_mt7915(&dev->mt76))
+- mt76_set(dev, MT_WFDMA1_GLO_CFG,
+- MT_WFDMA1_GLO_CFG_TX_DMA_EN |
+- MT_WFDMA1_GLO_CFG_RX_DMA_EN |
+- MT_WFDMA1_GLO_CFG_OMIT_TX_INFO |
+- MT_WFDMA1_GLO_CFG_OMIT_RX_INFO);
++ mt76_wr(dev, MT_INT_MASK_CSR, dev->mt76.mmio.irqmask);
++ mt76_wr(dev, MT_INT_SOURCE_CSR, ~0);
+ 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);
++ mt76_wr(dev, MT_INT1_MASK_CSR, irq_mask);
++ 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 = mt7915_run_firmware(dev);
++ if (ret)
++ goto out;
++
++ /* set the necessary init items */
++ ret = mt7915_mcu_set_eeprom(dev, dev->flash_mode);
++ if (ret)
++ goto out;
++
++ mt7915_mac_init(dev);
++ mt7915_init_txpower(dev, &dev->mphy.sband_2g.sband);
++ mt7915_init_txpower(dev, &dev->mphy.sband_5g.sband);
++ ret = mt7915_txbf_init(dev);
+
+- if (is_mt7915(&dev->mt76))
+- mt76_set(dev, MT_WFDMA1_GLO_CFG + hif1_ofs,
+- MT_WFDMA1_GLO_CFG_TX_DMA_EN |
+- MT_WFDMA1_GLO_CFG_RX_DMA_EN |
+- MT_WFDMA1_GLO_CFG_OMIT_TX_INFO |
+- MT_WFDMA1_GLO_CFG_OMIT_RX_INFO);
++ if (test_bit(MT76_STATE_RUNNING, &dev->mphy.state)) {
++ ret = __mt7915_start(dev->mphy.hw);
++ if (ret)
++ goto out;
++ }
++
++ if (ext_phy && test_bit(MT76_STATE_RUNNING, &ext_phy->state)) {
++ ret = __mt7915_start(ext_phy->hw);
++ if (ret)
++ goto out;
+ }
++
++out:
++ /* reset done */
++ clear_bit(MT76_RESET, &dev->mphy.state);
++ if (phy2)
++ clear_bit(MT76_RESET, &phy2->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 mt7915_tx_token_put(struct mt7915_dev *dev)
++static void
++mt7915_mac_full_reset(struct mt7915_dev *dev)
+ {
+- struct mt76_txwi_cache *txwi;
+- int id;
++ struct mt7915_phy *phy2;
++ struct mt76_phy *ext_phy;
++ int i;
+
+- spin_lock_bh(&dev->mt76.token_lock);
+- idr_for_each_entry(&dev->mt76.token, txwi, id) {
+- mt7915_txwi_free(dev, txwi, NULL, NULL);
+- dev->mt76.token_count--;
++ ext_phy = dev->mt76.phy2;
++ phy2 = ext_phy ? ext_phy->priv : NULL;
++
++ dev->ser.hw_full_reset = true;
++ if (READ_ONCE(dev->reset_state) & MT_MCU_CMD_WA_WDT)
++ dev->ser.wf_reset_wa_count++;
++ else
++ dev->ser.wf_reset_wm_count++;
++
++ wake_up(&dev->mt76.mcu.wait);
++ ieee80211_stop_queues(mt76_hw(dev));
++ if (ext_phy)
++ ieee80211_stop_queues(ext_phy->hw);
++
++ cancel_delayed_work_sync(&dev->mphy.mac_work);
++ if (ext_phy)
++ cancel_delayed_work_sync(&ext_phy->mac_work);
++
++ mutex_lock(&dev->mt76.mutex);
++ for (i = 0; i < 10; i++) {
++ if (!mt7915_mac_reset(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 (ext_phy)
++ ieee80211_restart_hw(ext_phy->hw);
++
++ ieee80211_wake_queues(mt76_hw(dev));
++ if (ext_phy)
++ ieee80211_wake_queues(ext_phy->hw);
++
++ dev->ser.hw_full_reset = false;
++ ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mphy.mac_work,
++ MT7915_WATCHDOG_TIME);
++ if (ext_phy)
++ ieee80211_queue_delayed_work(ext_phy->hw,
++ &ext_phy->mac_work,
++ MT7915_WATCHDOG_TIME);
+ }
+
+ /* system error recovery */
+@@ -2129,6 +2233,36 @@ void mt7915_mac_reset_work(struct work_struct *work)
+ ext_phy = dev->mt76.phy2;
+ phy2 = ext_phy ? ext_phy->priv : NULL;
+
++ /* chip full reset */
++ if (dev->ser.reset_type == SER_TYPE_FULL_RESET) {
++ u32 intr;
++
++ /* disable WA/WM WDT */
++ intr = mt76_rr(dev, MT_WFDMA0_MCU_HOST_INT_ENA);
++ intr &= ~MT_MCU_CMD_WDT_MASK;
++ mt76_set(dev, MT_WFDMA0_MCU_HOST_INT_ENA, intr);
++
++ mt7915_mac_full_reset(dev);
++
++ /* enable the mcu irq*/
++ mt7915_irq_enable(dev, MT_INT_MCU_CMD);
++ mt7915_irq_disable(dev, 0);
++
++ /* re-enable WA/WM WDT */
++ intr = mt76_rr(dev, MT_WFDMA0_MCU_HOST_INT_ENA);
++ intr |= MT_MCU_CMD_WDT_MASK;
++ mt76_set(dev, MT_WFDMA0_MCU_HOST_INT_ENA, intr);
++
++ dev->reset_state = MT_MCU_CMD_NORMAL_STATE;
++ dev->ser.reset_type = SER_TYPE_NONE;
++ dev_info(dev->mt76.dev, "SER: chip full reset completed, WM %d, WA %d\n",
++ dev->ser.wf_reset_wm_count,
++ dev->ser.wf_reset_wa_count);
++ return;
++ }
++
++ /* chip partial reset */
++ dev->ser.reset_type = SER_TYPE_NONE;
+ if (!(READ_ONCE(dev->reset_state) & MT_MCU_CMD_STOP_DMA))
+ return;
+
+@@ -2155,7 +2289,7 @@ void mt7915_mac_reset_work(struct work_struct *work)
+ mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_DMA_STOPPED);
+
+ if (mt7915_wait_reset_state(dev, MT_MCU_CMD_RESET_DONE)) {
+- mt7915_dma_reset(dev);
++ mt7915_dma_reset(dev, false);
+
+ mt7915_tx_token_put(dev);
+ idr_init(&dev->mt76.token);
+@@ -2206,6 +2340,34 @@ void mt7915_mac_reset_work(struct work_struct *work)
+ MT7915_WATCHDOG_TIME);
+ }
+
++void mt7915_reset(struct mt7915_dev *dev)
++{
++ if (!dev->ser.hw_init_done)
++ return;
++
++ if (dev->ser.hw_full_reset)
++ return;
++
++ /* wm/wa exception: do full recovery */
++ if (READ_ONCE(dev->reset_state) & MT_MCU_CMD_WDT_MASK) {
++ dev_info(dev->mt76.dev, "SER: chip full recovery start, WM %d, WA %d\n",
++ dev->ser.wf_reset_wm_count,
++ dev->ser.wf_reset_wa_count);
++
++ dev->ser.reset_type = SER_TYPE_FULL_RESET;
++
++ mt7915_irq_disable(dev, MT_INT_MCU_CMD);
++ queue_work(dev->mt76.wq, &dev->reset_work);
++ return;
++ }
++
++ dev_info(dev->mt76.dev, "SER: chip partial recovery, reset_state(0x%08X)\n",
++ READ_ONCE(dev->reset_state));
++ dev->ser.reset_type = SER_TYPE_PARTIAL_RESET;
++ queue_work(dev->mt76.wq, &dev->reset_work);
++ wake_up(&dev->reset_wait);
++}
++
+ void mt7915_mac_update_stats(struct mt7915_phy *phy)
+ {
+ struct mt7915_dev *dev = phy->dev;
+diff --git a/mt7915/main.c b/mt7915/main.c
+index 78bf5ffa..eabcd785 100644
+--- a/mt7915/main.c
++++ b/mt7915/main.c
+@@ -20,17 +20,13 @@ static bool mt7915_dev_running(struct mt7915_dev *dev)
+ return phy && test_bit(MT76_STATE_RUNNING, &phy->mt76->state);
+ }
+
+-static int mt7915_start(struct ieee80211_hw *hw)
++int __mt7915_start(struct ieee80211_hw *hw)
+ {
+ struct mt7915_dev *dev = mt7915_hw_dev(hw);
+ struct mt7915_phy *phy = mt7915_hw_phy(hw);
+ bool running;
+ int ret;
+
+- flush_work(&dev->init_work);
+-
+- mutex_lock(&dev->mt76.mutex);
+-
+ running = mt7915_dev_running(dev);
+
+ if (!running) {
+@@ -80,6 +76,19 @@ static int mt7915_start(struct ieee80211_hw *hw)
+ mt7915_mac_reset_counters(phy);
+
+ out:
++ return ret;
++}
++
++static int mt7915_start(struct ieee80211_hw *hw)
++{
++ struct mt7915_dev *dev = mt7915_hw_dev(hw);
++ bool running;
++ int ret;
++
++ flush_work(&dev->init_work);
++
++ mutex_lock(&dev->mt76.mutex);
++ ret = __mt7915_start(hw);
+ mutex_unlock(&dev->mt76.mutex);
+
+ return ret;
+@@ -91,6 +100,7 @@ static void mt7915_stop(struct ieee80211_hw *hw)
+ struct mt7915_phy *phy = mt7915_hw_phy(hw);
+
+ cancel_delayed_work_sync(&phy->mt76->mac_work);
++ cancel_work_sync(&dev->reset_work);
+
+ mutex_lock(&dev->mt76.mutex);
+
+diff --git a/mt7915/mcu.c b/mt7915/mcu.c
+index 20f32f7f..b29776e9 100644
+--- a/mt7915/mcu.c
++++ b/mt7915/mcu.c
+@@ -203,19 +203,90 @@ mt7915_mcu_set_sta_ht_mcs(struct ieee80211_sta *sta, u8 *ht_mcs,
+ ht_mcs[nss] = sta->ht_cap.mcs.rx_mask[nss] & mask[nss];
+ }
+
++static int
++mt7915_fw_exception_chk(struct mt7915_dev *dev)
++{
++ u32 reg_val;
++
++ reg_val = mt76_rr(dev, MT_EXCEPTION_ADDR);
++
++ if (is_mt7915(&dev->mt76))
++ reg_val >>= 8;
++
++ return !!(reg_val & 0xff);
++}
++
++static void
++mt7915_fw_heart_beat_chk(struct mt7915_dev *dev)
++{
++#define WM_TIMEOUT_COUNT_CHECK 5
++#define WM_HANG_COUNT_CHECK 9
++ static u32 cidx_rec[5], didx_rec[5];
++ u32 cnt, cidx, didx, queue;
++ u32 idx, i;
++
++ if (dev->ser.hw_full_reset)
++ return;
++
++ if (dev->ser.cmd_fail_cnt >= WM_TIMEOUT_COUNT_CHECK) {
++ cnt = mt76_rr(dev, WF_WFDMA_MEM_DMA_RX_RING_CTL + 4);
++ cidx = mt76_rr(dev, WF_WFDMA_MEM_DMA_RX_RING_CTL + 8);
++ didx = mt76_rr(dev, WF_WFDMA_MEM_DMA_RX_RING_CTL + 12);
++ queue = (didx > cidx) ?
++ (didx - cidx - 1) : (didx - cidx + cnt - 1);
++
++ idx = (dev->ser.cmd_fail_cnt - WM_TIMEOUT_COUNT_CHECK) % 5;
++ cidx_rec[idx] = cidx;
++ didx_rec[idx] = didx;
++
++ if ((cnt - 1) == queue &&
++ dev->ser.cmd_fail_cnt >= WM_HANG_COUNT_CHECK) {
++
++ for (i = 0; i < 5; i++) {
++ if (cidx_rec[i] != cidx ||
++ didx_rec[i] != didx)
++ return;
++ }
++ dev_err(dev->mt76.dev, "detect mem dma hang!\n");
++ if (dev->ser.reset_enable) {
++ dev->reset_state |= MT_MCU_CMD_WDT_MASK;
++ mt7915_reset(dev);
++ }
++ dev->ser.cmd_fail_cnt = 0;
++ }
++ }
++}
++
+ static int
+ mt7915_mcu_parse_response(struct mt76_dev *mdev, int cmd,
+ struct sk_buff *skb, int seq)
+ {
++ struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76);
+ struct mt7915_mcu_rxd *rxd;
+ int ret = 0;
+
+ if (!skb) {
+ dev_err(mdev->dev, "Message %08x (seq %d) timeout\n",
+ cmd, seq);
++
++ dev->ser.cmd_fail_cnt++;
++
++ if (dev->ser.cmd_fail_cnt < 5) {
++ int exp_type = mt7915_fw_exception_chk(dev);
++
++ dev_err(mdev->dev, "Fw is status(%d)\n", exp_type);
++ if (exp_type && dev->ser.reset_enable) {
++ dev->reset_state |= MT_MCU_CMD_WDT_MASK;
++ mt7915_reset(dev);
++ }
++ }
++ mt7915_fw_heart_beat_chk(dev);
++
+ return -ETIMEDOUT;
+ }
+
++ dev->ser.cmd_fail_cnt = 0;
++
+ rxd = (struct mt7915_mcu_rxd *)skb->data;
+ if (seq != rxd->seq)
+ return -EAGAIN;
+@@ -2456,18 +2527,10 @@ mt7915_mcu_init_rx_airtime(struct mt7915_dev *dev)
+ sizeof(req), true);
+ }
+
+-int mt7915_mcu_init(struct mt7915_dev *dev)
++int mt7915_run_firmware(struct mt7915_dev *dev)
+ {
+- static const struct mt76_mcu_ops mt7915_mcu_ops = {
+- .headroom = sizeof(struct mt7915_mcu_txd),
+- .mcu_skb_send_msg = mt7915_mcu_send_message,
+- .mcu_parse_response = mt7915_mcu_parse_response,
+- .mcu_restart = mt76_connac_mcu_restart,
+- };
+ int ret;
+
+- dev->mt76.mcu_ops = &mt7915_mcu_ops;
+-
+ /* force firmware operation mode into normal state,
+ * which should be set before firmware download stage.
+ */
+@@ -2516,6 +2579,21 @@ int mt7915_mcu_init(struct mt7915_dev *dev)
+ MCU_WA_PARAM_RED, 0, 0);
+ }
+
++int mt7915_mcu_init(struct mt7915_dev *dev)
++{
++ static const struct mt76_mcu_ops mt7915_mcu_ops = {
++ .headroom = sizeof(struct mt7915_mcu_txd),
++ .mcu_skb_send_msg = mt7915_mcu_send_message,
++ .mcu_parse_response = mt7915_mcu_parse_response,
++ .mcu_restart = mt76_connac_mcu_restart,
++ };
++ int ret;
++
++ dev->mt76.mcu_ops = &mt7915_mcu_ops;
++
++ return mt7915_run_firmware(dev);
++}
++
+ void mt7915_mcu_exit(struct mt7915_dev *dev)
+ {
+ __mt76_mcu_restart(&dev->mt76);
+diff --git a/mt7915/mcu.h b/mt7915/mcu.h
+index 5cbc3ecf..229b9d72 100644
+--- a/mt7915/mcu.h
++++ b/mt7915/mcu.h
+@@ -466,8 +466,9 @@ enum {
+
+ enum {
+ SER_QUERY,
++ SER_SET,
+ /* recovery */
+- SER_SET_RECOVER_L1,
++ SER_SET_RECOVER_L1 = 1,
+ SER_SET_RECOVER_L2,
+ SER_SET_RECOVER_L3_RX_ABORT,
+ SER_SET_RECOVER_L3_TX_ABORT,
+diff --git a/mt7915/mmio.c b/mt7915/mmio.c
+index 4d4537cd..b3de3a7a 100644
+--- a/mt7915/mmio.c
++++ b/mt7915/mmio.c
+@@ -23,6 +23,7 @@ static const u32 mt7915_reg[] = {
+ [CBTOP1_PHY_END] = 0x77ffffff,
+ [INFRA_MCU_ADDR_END] = 0x7c3fffff,
+ [SWDEF_BASE_ADDR] = 0x41f200,
++ [EXCEPTION_BASE_ADDR] = 0x219848,
+ };
+
+ static const u32 mt7916_reg[] = {
+@@ -38,6 +39,7 @@ static const u32 mt7916_reg[] = {
+ [CBTOP1_PHY_END] = 0x7fffffff,
+ [INFRA_MCU_ADDR_END] = 0x7c085fff,
+ [SWDEF_BASE_ADDR] = 0x411400,
++ [EXCEPTION_BASE_ADDR] = 0x022050BC,
+ };
+
+ static const u32 mt7986_reg[] = {
+@@ -53,6 +55,7 @@ static const u32 mt7986_reg[] = {
+ [CBTOP1_PHY_END] = 0x7fffffff,
+ [INFRA_MCU_ADDR_END] = 0x7c085fff,
+ [SWDEF_BASE_ADDR] = 0x411400,
++ [EXCEPTION_BASE_ADDR] = 0x02204FFC,
+ };
+
+ static const u32 mt7915_offs[] = {
+@@ -610,10 +613,9 @@ static void mt7915_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) {
++ if (val & (MT_MCU_CMD_ERROR_MASK | MT_MCU_CMD_WDT_MASK)) {
+ dev->reset_state = val;
+- queue_work(dev->mt76.wq, &dev->reset_work);
+- wake_up(&dev->reset_wait);
++ mt7915_reset(dev);
+ }
+ }
+ }
+diff --git a/mt7915/mt7915.h b/mt7915/mt7915.h
+index e5f89161..7f7ecdfe 100644
+--- a/mt7915/mt7915.h
++++ b/mt7915/mt7915.h
+@@ -297,6 +297,15 @@ struct mt7915_dev {
+ struct work_struct reset_work;
+ wait_queue_head_t reset_wait;
+ u32 reset_state;
++ struct {
++ bool hw_full_reset:1;
++ bool hw_init_done:1;
++ bool reset_enable:1;
++ u32 reset_type;
++ u32 cmd_fail_cnt;
++ u32 wf_reset_wm_count;
++ u32 wf_reset_wa_count;
++ }ser;
+
+ struct list_head sta_rc_list;
+ struct list_head sta_poll_list;
+@@ -335,6 +344,12 @@ enum {
+ __MT_WFDMA_MAX,
+ };
+
++enum {
++ SER_TYPE_NONE,
++ SER_TYPE_PARTIAL_RESET,
++ SER_TYPE_FULL_RESET,
++};
++
+ enum {
+ MT_CTX0,
+ MT_HIF0 = 0x0,
+@@ -446,6 +461,14 @@ s8 mt7915_eeprom_get_power_delta(struct mt7915_dev *dev, int band);
+ int mt7915_dma_init(struct mt7915_dev *dev, struct mt7915_phy *phy2);
+ void mt7915_dma_prefetch(struct mt7915_dev *dev);
+ void mt7915_dma_cleanup(struct mt7915_dev *dev);
++void mt7915_reset(struct mt7915_dev *dev);
++int mt7915_dma_reset(struct mt7915_dev *dev, bool force);
++int __mt7915_start(struct ieee80211_hw *hw);
++void mt7915_init_txpower(struct mt7915_dev *dev,
++ struct ieee80211_supported_band *sband);
++int mt7915_txbf_init(struct mt7915_dev *dev);
++void mt7915_mac_init(struct mt7915_dev *dev);
++int mt7915_run_firmware(struct mt7915_dev *dev);
+ int mt7915_mcu_init(struct mt7915_dev *dev);
+ int mt7915_mcu_twt_agrt_update(struct mt7915_dev *dev,
+ struct mt7915_vif *mvif,
+diff --git a/mt7915/regs.h b/mt7915/regs.h
+index 4251cf78..99834310 100644
+--- a/mt7915/regs.h
++++ b/mt7915/regs.h
+@@ -31,6 +31,7 @@ enum reg_rev {
+ CBTOP1_PHY_END,
+ INFRA_MCU_ADDR_END,
+ SWDEF_BASE_ADDR,
++ EXCEPTION_BASE_ADDR,
+ __MT_REG_MAX,
+ };
+
+@@ -112,6 +113,11 @@ enum offs_rev {
+ #define __REG(id) (dev->reg.reg_rev[(id)])
+ #define __OFFS(id) (dev->reg.offs_rev[(id)])
+
++/* MEM WFDMA */
++#define WF_WFDMA_MEM_DMA 0x58000000
++
++#define WF_WFDMA_MEM_DMA_RX_RING_CTL (WF_WFDMA_MEM_DMA + (0x510))
++
+ /* MCU WFDMA0 */
+ #define MT_MCU_WFDMA0_BASE 0x2000
+ #define MT_MCU_WFDMA0(ofs) (MT_MCU_WFDMA0_BASE + (ofs))
+@@ -556,6 +562,10 @@ enum offs_rev {
+ #define MT_WFDMA0_PRI_DLY_INT_CFG1 MT_WFDMA0(0x2f4)
+ #define MT_WFDMA0_PRI_DLY_INT_CFG2 MT_WFDMA0(0x2f8)
+
++#define MT_WFDMA0_MCU_HOST_INT_ENA MT_WFDMA0(0x1f4)
++#define MT_WFDMA0_MT_WA_WDT_INT BIT(31)
++#define MT_WFDMA0_MT_WM_WDT_INT BIT(30)
++
+ /* WFDMA1 */
+ #define MT_WFDMA1_BASE 0xd5000
+ #define MT_WFDMA1(ofs) (MT_WFDMA1_BASE + (ofs))
+@@ -701,6 +711,10 @@ enum offs_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)
++
+ /* TOP RGU */
+ #define MT_TOP_RGU_BASE 0x18000000
+ #define MT_TOP_PWR_CTRL (MT_TOP_RGU_BASE + (0x0))
+@@ -974,6 +988,8 @@ enum offs_rev {
+ #define MT_CPU_UTIL_PEAK_IDLE_CNT MT_CPU_UTIL(0x0c)
+ #define MT_CPU_UTIL_CTRL MT_CPU_UTIL(0x1c)
+
++#define MT_EXCEPTION_ADDR __REG(EXCEPTION_BASE_ADDR)
++
+ /* LED */
+ #define MT_LED_TOP_BASE 0x18013000
+ #define MT_LED_PHYS(_n) (MT_LED_TOP_BASE + (_n))
+--
+2.18.0
+
diff --git a/recipes-kernel/linux-mt76/files/patches/1009-mt76-mt7915-add-support-for-runtime-set-in-band-disc.patch b/recipes-kernel/linux-mt76/files/patches/1009-mt76-mt7915-add-support-for-runtime-set-in-band-disc.patch
new file mode 100644
index 0000000..ae9ca75
--- /dev/null
+++ b/recipes-kernel/linux-mt76/files/patches/1009-mt76-mt7915-add-support-for-runtime-set-in-band-disc.patch
@@ -0,0 +1,36 @@
+From 71e967c4ea7f0e119ff66197491acae7b9bd87e0 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] mt76: mt7915:add support for runtime set in-band discovery
+
+Signed-off-by: MeiChia Chiu <MeiChia.Chiu@mediatek.com>
+---
+ mt7915/mcu.c | 5 ++---
+ 1 file changed, 2 insertions(+), 3 deletions(-)
+
+diff --git a/mt7915/mcu.c b/mt7915/mcu.c
+index 203fa32..73239df 100644
+--- a/mt7915/mcu.c
++++ b/mt7915/mcu.c
+@@ -2014,8 +2014,7 @@ mt7915_mcu_beacon_inband_discov(struct mt7915_dev *dev, struct ieee80211_vif *vi
+ u8 *buf, interval;
+ int len;
+
+- if (changed & BSS_CHANGED_FILS_DISCOVERY &&
+- vif->bss_conf.fils_discovery.max_interval) {
++ if (changed & BSS_CHANGED_FILS_DISCOVERY) {
+ 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 &&
+@@ -2051,7 +2050,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);
+- discov->enable = true;
++ discov->enable = !!(interval);
+
+ buf = (u8 *)tlv + sizeof(*discov);
+
+--
+2.29.2
+
diff --git a/recipes-kernel/linux-mt76/files/patches/1112-mt76-mt7915-add-L0.5-SER-for-mt7986.patch b/recipes-kernel/linux-mt76/files/patches/1112-mt76-mt7915-add-L0.5-SER-for-mt7986.patch
deleted file mode 100644
index 73b6c15..0000000
--- a/recipes-kernel/linux-mt76/files/patches/1112-mt76-mt7915-add-L0.5-SER-for-mt7986.patch
+++ /dev/null
@@ -1,930 +0,0 @@
-From 410b8c158d29137df0da4d8a1e82d494528e4fb1 Mon Sep 17 00:00:00 2001
-From: Bo Jiao <Bo.Jiao@mediatek.com>
-Date: Mon, 25 Apr 2022 10:19:29 +0800
-Subject: [PATCH] mt76: mt7915: add L0.5 SER for mt7986
-
-Signed-off-by: Bo Jiao <Bo.Jiao@mediatek.com>
----
- mt7915/debugfs.c | 168 +++++++++++++++++++++++++++++++++-
- mt7915/dma.c | 49 ++++++++++
- mt7915/init.c | 8 +-
- mt7915/mac.c | 231 ++++++++++++++++++++++++++++++++++++++++++++++-
- mt7915/main.c | 16 +++-
- mt7915/mcu.c | 52 ++++++++---
- mt7915/mmio.c | 12 ++-
- mt7915/mt7915.h | 27 ++++++
- mt7915/regs.h | 37 +++++++-
- 9 files changed, 572 insertions(+), 28 deletions(-)
-
-diff --git a/mt7915/debugfs.c b/mt7915/debugfs.c
-index e8e26ac1..003aacaa 100644
---- a/mt7915/debugfs.c
-+++ b/mt7915/debugfs.c
-@@ -47,7 +47,8 @@ mt7915_implicit_txbf_get(void *data, u64 *val)
- DEFINE_DEBUGFS_ATTRIBUTE(fops_implicit_txbf, mt7915_implicit_txbf_get,
- mt7915_implicit_txbf_set, "%lld\n");
-
--/* test knob of system layer 1/2 error recovery */
-+/* test knob of system layer 0.5/1/2 error recovery */
-+/*
- static int mt7915_ser_trigger_set(void *data, u64 val)
- {
- enum {
-@@ -74,9 +75,172 @@ static int mt7915_ser_trigger_set(void *data, u64 val)
- return ret;
- }
-
-+*/
-+static int mt7915_ser_trigger_set(void *data, u64 val)
-+{
-+#define SER_SET GENMASK(3, 0)
-+#define SER_BAND GENMASK(7, 4)
-+#define SER_ACTION GENMASK(11, 8)
-+ enum {
-+ SER_ACTION_SET = 1,
-+ SER_ACTION_SET_MASK = 2,
-+ SER_ACTION_TRIGGER = 3,
-+ };
-+
-+ struct mt7915_dev *dev = data;
-+ u8 ser_action, ser_band, ser_set, set_val;
-+
-+ ser_action = FIELD_GET(SER_ACTION, val);
-+ ser_set = set_val = FIELD_GET(SER_SET, val);
-+ ser_band = (ser_action == SER_ACTION_TRIGGER) ?
-+ FIELD_GET(SER_BAND, val) : 0;
-+
-+ if (ser_band > 1)
-+ return -1;
-+
-+ switch (ser_action) {
-+ case SER_ACTION_SET:
-+ /*
-+ * 0x100: disable system error recovery function.
-+ * 0x101: enable system error recovery function.
-+ */
-+ ser_set = !!set_val;
-+ break;
-+ case SER_ACTION_SET_MASK:
-+ /*
-+ * 0x200: enable system error tracking.
-+ * 0x201: enable system error L1 recover.
-+ * 0x202: enable system error L2 recover.
-+ * 0x203: enable system error L3 rx abort.
-+ * 0x204: enable system error L3 tx abort.
-+ * 0x205: enable system error L3 tx disable.
-+ * 0x206: enable system error L3 bf recover.
-+ * 0x207: enable system error all recover.
-+ */
-+ ser_set = set_val > 7 ? 0x7f : BIT(set_val);
-+ break;
-+ case SER_ACTION_TRIGGER:
-+ /*
-+ * 0x300: trigger L0 recover.
-+ * 0x301/0x311: trigger L1 recover for band0/band1.
-+ * 0x302/0x312: trigger L2 recover for band0/band1.
-+ * 0x303/0x313: trigger L3 rx abort for band0/band1.
-+ * 0x304/0x314: trigger L3 tx abort for band0/band1.
-+ * 0x305/0x315: trigger L3 tx disable for band0/band1.
-+ * 0x306/0x316: trigger L3 bf recover for band0/band1.
-+ */
-+ if (0x300 == val || 0x310 == val) {
-+ mt7915_reset(dev, SER_TYPE_FULL_RESET);
-+ return 0;
-+ }
-+
-+ if (ser_set > 6)
-+ return -1;
-+ break;
-+ default:
-+ return -1;
-+ }
-+
-+ return mt7915_mcu_set_ser(dev, ser_action, ser_set, ser_band);
-+}
-+
- DEFINE_DEBUGFS_ATTRIBUTE(fops_ser_trigger, NULL,
- mt7915_ser_trigger_set, "%lld\n");
-
-+static int
-+mt7915_ser_stats_show(struct seq_file *s, void *data)
-+{
-+#define SER_ACTION_QUERY 0
-+ struct mt7915_dev *dev = dev_get_drvdata(s->private);
-+ int ret = 0;
-+
-+ /* get more info from firmware */
-+ ret = mt7915_mcu_set_ser(dev, SER_ACTION_QUERY, 0, 0);
-+ msleep(100);
-+
-+ seq_printf(s, "::E R , SER_STATUS = 0x%08X\n",
-+ mt76_rr(dev, MT_SWDEF_SER_STATUS));
-+ seq_printf(s, "::E R , SER_PLE_ERR = 0x%08X\n",
-+ mt76_rr(dev, MT_SWDEF_PLE_STATUS));
-+ seq_printf(s, "::E R , SER_PLE_ERR_1 = 0x%08X\n",
-+ mt76_rr(dev, MT_SWDEF_PLE1_STATUS));
-+ seq_printf(s, "::E R , SER_PLE_ERR_AMSDU = 0x%08X\n",
-+ mt76_rr(dev, MT_SWDEF_PLE_AMSDU_STATUS));
-+ seq_printf(s, "::E R , SER_PSE_ERR = 0x%08X\n",
-+ mt76_rr(dev, MT_SWDEF_PSE_STATUS));
-+ seq_printf(s, "::E R , SER_PSE_ERR_1 = 0x%08X\n",
-+ mt76_rr(dev, MT_SWDEF_PSE1_STATUS));
-+ seq_printf(s, "::E R , SER_LMAC_WISR6_B0 = 0x%08X\n",
-+ mt76_rr(dev, MT_SWDEF_LAMC_WISR6_BN0_STATUS));
-+ seq_printf(s, "::E R , SER_LMAC_WISR6_B1 = 0x%08X\n",
-+ mt76_rr(dev, MT_SWDEF_LAMC_WISR6_BN1_STATUS));
-+ seq_printf(s, "::E R , SER_LMAC_WISR7_B0 = 0x%08X\n",
-+ mt76_rr(dev, MT_SWDEF_LAMC_WISR7_BN0_STATUS));
-+ seq_printf(s, "::E R , SER_LMAC_WISR7_B1 = 0x%08X\n",
-+ mt76_rr(dev, MT_SWDEF_LAMC_WISR7_BN1_STATUS));
-+
-+ seq_printf(s, "\nWF RESET STATUS: WM %d, WA %d, WO %d\n",
-+ dev->ser.wf_reset_wm_count,
-+ dev->ser.wf_reset_wa_count,
-+ dev->ser.wf_reset_wo_count);
-+
-+ return ret;
-+}
-+
-+
-+int mt7915_fw_exception_chk(struct mt7915_dev *dev)
-+{
-+ u32 reg_val;
-+
-+ reg_val = mt76_rr(dev, MT_EXCEPTION_ADDR);
-+
-+ if (is_mt7915(&dev->mt76))
-+ reg_val >>= 8;
-+
-+ return !!(reg_val & 0xff);
-+}
-+
-+void mt7915_fw_heart_beat_chk(struct mt7915_dev *dev)
-+{
-+#define WM_TIMEOUT_COUNT_CHECK 5
-+#define WM_HANG_COUNT_CHECK 9
-+ u32 cnt, cidx, didx, queue;
-+ u32 idx, i;
-+ static struct {
-+ u32 cidx;
-+ u32 didx;
-+ } dma_rec[5];
-+
-+ if (dev->ser.hw_full_reset)
-+ return;
-+
-+ if (dev->ser.cmd_fail_cnt >= WM_TIMEOUT_COUNT_CHECK) {
-+
-+ cnt = mt76_rr(dev, WF_WFDMA_MEM_DMA_RX_RING_CTL + 4);
-+ cidx = mt76_rr(dev, WF_WFDMA_MEM_DMA_RX_RING_CTL + 8);
-+ didx = mt76_rr(dev, WF_WFDMA_MEM_DMA_RX_RING_CTL + 12);
-+ queue = (didx > cidx) ?
-+ (didx - cidx - 1) : (didx - cidx + cnt - 1);
-+
-+ idx = (dev->ser.cmd_fail_cnt - WM_TIMEOUT_COUNT_CHECK) % 5;
-+ dma_rec[idx].cidx = cidx;
-+ dma_rec[idx].cidx = didx;
-+
-+ if (((cnt - 1) == queue) &&
-+ (dev->ser.cmd_fail_cnt >= WM_HANG_COUNT_CHECK)) {
-+
-+ for (i = 0; i < 5; i++) {
-+ if ((dma_rec[i].cidx != cidx) ||
-+ (dma_rec[i].didx != didx))
-+ return;
-+ }
-+
-+ mt7915_reset(dev, SER_TYPE_FULL_RESET);
-+ dev->ser.cmd_fail_cnt = 0;
-+ }
-+ }
-+}
-+
- static int
- mt7915_radar_trigger(void *data, u64 val)
- {
-@@ -943,6 +1107,8 @@ int mt7915_init_debugfs(struct mt7915_phy *phy)
- debugfs_create_file("xmit-queues", 0400, dir, phy,
- &mt7915_xmit_queues_fops);
- debugfs_create_file("tx_stats", 0400, dir, phy, &mt7915_tx_stats_fops);
-+ debugfs_create_devm_seqfile(dev->mt76.dev, "ser_show", dir,
-+ mt7915_ser_stats_show);
- 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);
-diff --git a/mt7915/dma.c b/mt7915/dma.c
-index c2d655cd..219b440f 100644
---- a/mt7915/dma.c
-+++ b/mt7915/dma.c
-@@ -486,6 +486,55 @@ int mt7915_dma_init(struct mt7915_dev *dev, struct mt7915_phy *phy2)
- return 0;
- }
-
-+
-+int mt7915_dma_reset(struct mt7915_dev *dev, bool force)
-+{
-+ struct mt76_phy *mphy_ext = dev->mt76.phy2;
-+ int i;
-+
-+ /* clean up hw queues */
-+ for (i = 0; i < ARRAY_SIZE(dev->mt76.phy.q_tx); i++) {
-+ mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[i], true);
-+ if (mphy_ext)
-+ mt76_queue_tx_cleanup(dev, mphy_ext->q_tx[i], true);
-+ }
-+
-+ for (i = 0; i < ARRAY_SIZE(dev->mt76.q_mcu); i++)
-+ mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[i], true);
-+
-+ for (i = 0; i < __MT_RXQ_MAX; i++)
-+ mt76_queue_rx_cleanup(dev, &dev->mt76.q_rx[i]);
-+
-+ /* reset wfsys */
-+ if (force)
-+ mt7915_wfsys_reset(dev);
-+
-+ /* disable wfdma */
-+ mt7915_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 (mphy_ext)
-+ mt76_queue_reset(dev, mphy_ext->q_tx[i]);
-+ }
-+
-+ for (i = 0; i < __MT_MCUQ_MAX; i++)
-+ mt76_queue_reset(dev, dev->mt76.q_mcu[i]);
-+
-+ for (i = 0; i < __MT_RXQ_MAX; i++)
-+ mt76_queue_reset(dev, &dev->mt76.q_rx[i]);
-+
-+ mt76_tx_status_check(&dev->mt76, true);
-+
-+ mt7915_dma_enable(dev);
-+
-+ for (i = 0; i < __MT_RXQ_MAX; i++)
-+ mt76_queue_rx_reset(dev, i);
-+
-+ return 0;
-+}
-+
- void mt7915_dma_cleanup(struct mt7915_dev *dev)
- {
- mt7915_dma_disable(dev, true);
-diff --git a/mt7915/init.c b/mt7915/init.c
-index 79dae0fc..25a9b5de 100644
---- a/mt7915/init.c
-+++ b/mt7915/init.c
-@@ -262,7 +262,7 @@ static void mt7915_led_set_brightness(struct led_classdev *led_cdev,
- mt7915_led_set_config(led_cdev, 0xff, 0);
- }
-
--static void
-+void
- mt7915_init_txpower(struct mt7915_dev *dev,
- struct ieee80211_supported_band *sband)
- {
-@@ -446,7 +446,7 @@ mt7915_mac_init_band(struct mt7915_dev *dev, u8 band)
- mt76_clear(dev, MT_DMA_DCR0(band), MT_DMA_DCR0_RXD_G5_EN);
- }
-
--static void mt7915_mac_init(struct mt7915_dev *dev)
-+void mt7915_mac_init(struct mt7915_dev *dev)
- {
- int i;
- u32 rx_len = is_mt7915(&dev->mt76) ? 0x400 : 0x680;
-@@ -476,7 +476,7 @@ static void mt7915_mac_init(struct mt7915_dev *dev)
- }
- }
-
--static int mt7915_txbf_init(struct mt7915_dev *dev)
-+int mt7915_txbf_init(struct mt7915_dev *dev)
- {
- int ret;
-
-@@ -1157,6 +1157,8 @@ int mt7915_register_device(struct mt7915_dev *dev)
-
- mt7915_init_debugfs(&dev->phy);
-
-+ dev->ser.hw_init_done = true;
-+
- return 0;
-
- unreg_thermal:
-diff --git a/mt7915/mac.c b/mt7915/mac.c
-index b899697c..e301fe52 100644
---- a/mt7915/mac.c
-+++ b/mt7915/mac.c
-@@ -3,6 +3,7 @@
-
- #include <linux/etherdevice.h>
- #include <linux/timekeeping.h>
-+#include <linux/pci.h>
- #include "mt7915.h"
- #include "../dma.h"
- #include "mac.h"
-@@ -2064,9 +2065,9 @@ mt7915_update_beacons(struct mt7915_dev *dev)
- IEEE80211_IFACE_ITER_RESUME_ALL,
- mt7915_update_vif_beacon, dev->mt76.phy2->hw);
- }
--
-+#if 0
- static void
--mt7915_dma_reset(struct mt7915_dev *dev)
-+mt7915_dma_reset(struct mt7915_dev *dev, bool force)
- {
- struct mt76_phy *mphy_ext = dev->mt76.phy2;
- u32 hif1_ofs = MT_WFDMA0_PCIE1(0) - MT_WFDMA0(0);
-@@ -2131,6 +2132,7 @@ mt7915_dma_reset(struct mt7915_dev *dev)
- MT_WFDMA1_GLO_CFG_OMIT_RX_INFO);
- }
- }
-+#endif
-
- void mt7915_tx_token_put(struct mt7915_dev *dev)
- {
-@@ -2146,6 +2148,172 @@ void mt7915_tx_token_put(struct mt7915_dev *dev)
- idr_destroy(&dev->mt76.token);
- }
-
-+static int
-+mt7915_mac_reset(struct mt7915_dev *dev)
-+{
-+ struct mt7915_phy *phy2;
-+ struct mt76_phy *ext_phy;
-+ struct mt76_dev *mdev = &dev->mt76;
-+ int i, ret;
-+ u32 irq_mask;
-+
-+ ext_phy = dev->mt76.phy2;
-+ phy2 = ext_phy ? ext_phy->priv : NULL;
-+
-+ /* irq disable */
-+ mt76_wr(dev, MT_INT_MASK_CSR, 0x0);
-+ mt76_wr(dev, MT_INT_SOURCE_CSR, ~0);
-+ if (dev->hif2) {
-+ mt76_wr(dev, MT_INT1_MASK_CSR, 0x0);
-+ mt76_wr(dev, MT_INT1_SOURCE_CSR, ~0);
-+ }
-+ 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);
-+ }
-+
-+ set_bit(MT76_RESET, &dev->mphy.state);
-+ wake_up(&dev->mt76.mcu.wait);
-+ if (ext_phy)
-+ set_bit(MT76_RESET, &ext_phy->state);
-+
-+ /* lock/unlock all queues to ensure that no tx is pending */
-+ mt76_txq_schedule_all(&dev->mphy);
-+ if (ext_phy)
-+ mt76_txq_schedule_all(ext_phy);
-+
-+ /* 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);
-+
-+ /* token reinit */
-+ mt7915_tx_token_put(dev);
-+ idr_init(&dev->mt76.token);
-+
-+ mt7915_dma_reset(dev, true);
-+ 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]);
-+ }
-+ }
-+ 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, irq_mask);
-+ 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 = mt7915_run_firmware(dev);
-+ if (ret)
-+ goto out;
-+
-+ /* set the necessary init items */
-+ ret = mt7915_mcu_set_eeprom(dev, dev->flash_mode);
-+ if (ret)
-+ goto out;
-+
-+ mt7915_mac_init(dev);
-+ mt7915_init_txpower(dev, &dev->mphy.sband_2g.sband);
-+ mt7915_init_txpower(dev, &dev->mphy.sband_5g.sband);
-+ ret = mt7915_txbf_init(dev);
-+
-+out:
-+ /* reset done */
-+ clear_bit(MT76_RESET, &dev->mphy.state);
-+ if (phy2)
-+ clear_bit(MT76_RESET, &phy2->mt76->state);
-+
-+ napi_enable(&dev->mt76.tx_napi);
-+ napi_schedule(&dev->mt76.tx_napi);
-+ mt76_worker_enable(&dev->mt76.tx_worker);
-+
-+ return ret;
-+}
-+
-+static void
-+mt7915_mac_full_reset(struct mt7915_dev *dev)
-+{
-+ struct mt7915_phy *phy2;
-+ struct mt76_phy *ext_phy;
-+ int i;
-+ struct cfg80211_scan_info info = {
-+ .aborted = true,
-+ };
-+
-+ ext_phy = dev->mt76.phy2;
-+ phy2 = ext_phy ? ext_phy->priv : NULL;
-+
-+ dev->ser.hw_full_reset = true;
-+ if (READ_ONCE(dev->reset_state) & MT_MCU_CMD_WA_WDT)
-+ dev->ser.wf_reset_wa_count++;
-+ else
-+ dev->ser.wf_reset_wm_count++;
-+
-+ wake_up(&dev->mt76.mcu.wait);
-+ ieee80211_stop_queues(mt76_hw(dev));
-+ if (ext_phy)
-+ ieee80211_stop_queues(ext_phy->hw);
-+
-+ cancel_delayed_work_sync(&dev->mphy.mac_work);
-+ if (ext_phy)
-+ cancel_delayed_work_sync(&ext_phy->mac_work);
-+
-+ mutex_lock(&dev->mt76.mutex);
-+ for (i = 0; i < 10; i++) {
-+ if (!mt7915_mac_reset(dev))
-+ break;
-+ }
-+ mutex_unlock(&dev->mt76.mutex);
-+
-+ if (i == 10)
-+ dev_err(dev->mt76.dev, "chip full reset failed\n");
-+
-+ if (test_and_clear_bit(MT76_HW_SCANNING, &dev->mphy.state))
-+ ieee80211_scan_completed(dev->mphy.hw, &info);
-+
-+ if (test_and_clear_bit(MT76_HW_SCANNING, &ext_phy->state))
-+ ieee80211_scan_completed(ext_phy->hw, &info);
-+
-+ ieee80211_wake_queues(mt76_hw(dev));
-+ if (ext_phy)
-+ ieee80211_wake_queues(ext_phy->hw);
-+
-+ if (test_bit(MT76_STATE_RUNNING, &dev->mphy.state))
-+ __mt7915_start(dev->mphy.hw);
-+
-+ if (ext_phy &&
-+ test_bit(MT76_STATE_RUNNING, &ext_phy->state))
-+ __mt7915_start(ext_phy->hw);
-+
-+ dev->ser.hw_full_reset = false;
-+
-+ ieee80211_restart_hw(mt76_hw(dev));
-+ if (ext_phy)
-+ ieee80211_restart_hw(ext_phy->hw);
-+
-+ ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mphy.mac_work,
-+ MT7915_WATCHDOG_TIME);
-+ if (ext_phy)
-+ ieee80211_queue_delayed_work(ext_phy->hw,
-+ &ext_phy->mac_work,
-+ MT7915_WATCHDOG_TIME);
-+}
-+
- /* system error recovery */
- void mt7915_mac_reset_work(struct work_struct *work)
- {
-@@ -2157,6 +2325,25 @@ void mt7915_mac_reset_work(struct work_struct *work)
- ext_phy = dev->mt76.phy2;
- phy2 = ext_phy ? ext_phy->priv : NULL;
-
-+ /* chip full reset */
-+ if (dev->ser.reset_type == SER_TYPE_FULL_RESET) {
-+ u32 val;
-+
-+ /* disable wa/wm watchdog interuppt */
-+ val = mt76_rr(dev, MT_WFDMA0_MCU_HOST_INT_ENA);
-+ val &= ~(MT_MCU_CMD_WA_WDT | MT_MCU_CMD_WM_WDT);
-+ mt76_set(dev, MT_WFDMA0_MCU_HOST_INT_ENA, val);
-+
-+ mt7915_mac_full_reset(dev);
-+
-+ /* enable the mcu irq*/
-+ mt7915_irq_enable(dev, MT_INT_MCU_CMD);
-+ mt7915_irq_disable(dev, 0);
-+ return;
-+ }
-+
-+ /* chip partial reset */
-+ dev->ser.reset_type = SER_TYPE_NONE;
- if (!(READ_ONCE(dev->reset_state) & MT_MCU_CMD_STOP_DMA))
- return;
-
-@@ -2183,7 +2370,7 @@ void mt7915_mac_reset_work(struct work_struct *work)
- mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_DMA_STOPPED);
-
- if (mt7915_wait_reset_state(dev, MT_MCU_CMD_RESET_DONE)) {
-- mt7915_dma_reset(dev);
-+ mt7915_dma_reset(dev, false);
-
- mt7915_tx_token_put(dev);
- idr_init(&dev->mt76.token);
-@@ -2234,6 +2421,44 @@ void mt7915_mac_reset_work(struct work_struct *work)
- MT7915_WATCHDOG_TIME);
- }
-
-+
-+void mt7915_reset(struct mt7915_dev *dev, u8 type)
-+{
-+ struct mt76_phy *ext_phy = dev->mt76.phy2;
-+
-+ if (!dev->ser.hw_init_done)
-+ return;
-+
-+ if (dev->ser.hw_full_reset)
-+ return;
-+
-+ dev_err(dev->mt76.dev, "SER: reset_state(0x%08X) type(0x%08X)\n",
-+ READ_ONCE(dev->reset_state), type);
-+
-+ /* WM/WA exception: do full recovery */
-+ if ((READ_ONCE(dev->reset_state) & MT_MCU_CMD_WDT_MASK) ||
-+ type == SER_TYPE_FULL_RESET) {
-+
-+ if (!is_mt7986(&dev->mt76))
-+ return;
-+
-+ dev->ser.reset_type = SER_TYPE_FULL_RESET;
-+ set_bit(MT76_MCU_RESET, &dev->mphy.state);
-+ if (ext_phy)
-+ set_bit(MT76_MCU_RESET, &ext_phy->state);
-+
-+ ieee80211_queue_work(mt76_hw(dev), &dev->reset_work);
-+ return;
-+ }
-+
-+ /* do partial recovery */
-+ mt7915_irq_enable(dev, MT_INT_MCU_CMD);
-+ mt7915_irq_disable(dev, 0);
-+ dev->ser.reset_type = SER_TYPE_PARTIAL_RESET;
-+ ieee80211_queue_work(mt76_hw(dev), &dev->reset_work);
-+ wake_up(&dev->reset_wait);
-+}
-+
- void mt7915_mac_update_stats(struct mt7915_phy *phy)
- {
- struct mt7915_dev *dev = phy->dev;
-diff --git a/mt7915/main.c b/mt7915/main.c
-index 5b0a6d02..9cc60e85 100644
---- a/mt7915/main.c
-+++ b/mt7915/main.c
-@@ -20,7 +20,7 @@ static bool mt7915_dev_running(struct mt7915_dev *dev)
- return phy && test_bit(MT76_STATE_RUNNING, &phy->mt76->state);
- }
-
--static int mt7915_start(struct ieee80211_hw *hw)
-+int __mt7915_start(struct ieee80211_hw *hw)
- {
- struct mt7915_dev *dev = mt7915_hw_dev(hw);
- struct mt7915_phy *phy = mt7915_hw_phy(hw);
-@@ -29,8 +29,6 @@ static int mt7915_start(struct ieee80211_hw *hw)
-
- flush_work(&dev->init_work);
-
-- mutex_lock(&dev->mt76.mutex);
--
- running = mt7915_dev_running(dev);
-
- if (!running) {
-@@ -85,6 +83,18 @@ out:
- return ret;
- }
-
-+static int mt7915_start(struct ieee80211_hw *hw)
-+{
-+ struct mt7915_dev *dev = mt7915_hw_dev(hw);
-+ int ret;
-+
-+ mutex_lock(&dev->mt76.mutex);
-+ ret = __mt7915_start(hw);
-+ mutex_unlock(&dev->mt76.mutex);
-+
-+ return ret;
-+}
-+
- static void mt7915_stop(struct ieee80211_hw *hw)
- {
- struct mt7915_dev *dev = mt7915_hw_dev(hw);
-diff --git a/mt7915/mcu.c b/mt7915/mcu.c
-index 681ede23..2128e4ca 100755
---- a/mt7915/mcu.c
-+++ b/mt7915/mcu.c
-@@ -212,14 +212,31 @@ mt7915_mcu_parse_response(struct mt76_dev *mdev, int cmd,
- struct sk_buff *skb, int seq)
- {
- struct mt7915_mcu_rxd *rxd;
-+ struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76);
- int ret = 0;
-
- if (!skb) {
- dev_err(mdev->dev, "Message %08x (seq %d) timeout\n",
- cmd, seq);
-+
-+ dev->ser.cmd_fail_cnt++;
-+
-+ if (dev->ser.cmd_fail_cnt < 5) {
-+ int exp_type = mt7915_fw_exception_chk(dev);
-+
-+ dev_err(mdev->dev, "Fw is status(%d)\n", exp_type);
-+ if (exp_type) {
-+ dev->ser.reset_type = SER_TYPE_FULL_RESET;
-+ mt7915_reset(dev, SER_TYPE_FULL_RESET);
-+ }
-+ }
-+ mt7915_fw_heart_beat_chk(dev);
-+
- return -ETIMEDOUT;
- }
-
-+ dev->ser.cmd_fail_cnt = 0;
-+
- rxd = (struct mt7915_mcu_rxd *)skb->data;
- if (seq != rxd->seq)
- return -EAGAIN;
-@@ -243,11 +260,17 @@ mt7915_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb,
- {
- struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76);
- struct mt7915_mcu_txd *mcu_txd;
-+ //struct mt76_phy *ext_phy = mdev->phy2;
- enum mt76_mcuq_id qid;
- __le32 *txd;
- u32 val;
- u8 seq;
-
-+ if (test_bit(MT76_MCU_RESET, &mdev->phy.state)) {
-+ dev_err(mdev->dev, "%s assert\n", __func__);
-+ return -EBUSY;
-+ }
-+
- /* TODO: make dynamic based on msg type */
- mdev->mcu.timeout = 20 * HZ;
-
-@@ -2472,25 +2495,14 @@ mt7915_mcu_init_rx_airtime(struct mt7915_dev *dev)
- sizeof(req), true);
- }
-
--int mt7915_mcu_init(struct mt7915_dev *dev)
-+int mt7915_run_firmware(struct mt7915_dev *dev)
- {
-- static const struct mt76_mcu_ops mt7915_mcu_ops = {
-- .headroom = sizeof(struct mt7915_mcu_txd),
-- .mcu_skb_send_msg = mt7915_mcu_send_message,
-- .mcu_parse_response = mt7915_mcu_parse_response,
-- .mcu_restart = mt76_connac_mcu_restart,
-- };
- int ret;
-
-- dev->mt76.mcu_ops = &mt7915_mcu_ops;
--
- /* force firmware operation mode into normal state,
- * which should be set before firmware download stage.
- */
-- if (is_mt7915(&dev->mt76))
-- mt76_wr(dev, MT_SWDEF_MODE, MT_SWDEF_NORMAL_MODE);
-- else
-- mt76_wr(dev, MT_SWDEF_MODE_MT7916, MT_SWDEF_NORMAL_MODE);
-+ mt76_wr(dev, MT_SWDEF_MODE, MT_SWDEF_NORMAL_MODE);
-
- ret = mt7915_driver_own(dev, 0);
- if (ret)
-@@ -2535,6 +2547,20 @@ int mt7915_mcu_init(struct mt7915_dev *dev)
- MCU_WA_PARAM_RED, 0, 0);
- }
-
-+int mt7915_mcu_init(struct mt7915_dev *dev)
-+{
-+ static const struct mt76_mcu_ops mt7915_mcu_ops = {
-+ .headroom = sizeof(struct mt7915_mcu_txd),
-+ .mcu_skb_send_msg = mt7915_mcu_send_message,
-+ .mcu_parse_response = mt7915_mcu_parse_response,
-+ .mcu_restart = mt76_connac_mcu_restart,
-+ };
-+
-+ dev->mt76.mcu_ops = &mt7915_mcu_ops;
-+
-+ return mt7915_run_firmware(dev);
-+}
-+
- void mt7915_mcu_exit(struct mt7915_dev *dev)
- {
- __mt76_mcu_restart(&dev->mt76);
-diff --git a/mt7915/mmio.c b/mt7915/mmio.c
-index 0bd32daa..f07b0565 100644
---- a/mt7915/mmio.c
-+++ b/mt7915/mmio.c
-@@ -22,6 +22,8 @@ static const u32 mt7915_reg[] = {
- [WFDMA_EXT_CSR_ADDR] = 0xd7000,
- [CBTOP1_PHY_END] = 0x77ffffff,
- [INFRA_MCU_ADDR_END] = 0x7c3fffff,
-+ [EXCEPTION_BASE_ADDR] = 0x219848,
-+ [SWDEF_BASE_ADDR] = 0x41f200,
- };
-
- static const u32 mt7916_reg[] = {
-@@ -36,6 +38,8 @@ static const u32 mt7916_reg[] = {
- [WFDMA_EXT_CSR_ADDR] = 0xd7000,
- [CBTOP1_PHY_END] = 0x7fffffff,
- [INFRA_MCU_ADDR_END] = 0x7c085fff,
-+ [EXCEPTION_BASE_ADDR] = 0x022050BC,
-+ [SWDEF_BASE_ADDR] = 0x411400,
- };
-
- static const u32 mt7986_reg[] = {
-@@ -50,6 +54,8 @@ static const u32 mt7986_reg[] = {
- [WFDMA_EXT_CSR_ADDR] = 0x27000,
- [CBTOP1_PHY_END] = 0x7fffffff,
- [INFRA_MCU_ADDR_END] = 0x7c085fff,
-+ [EXCEPTION_BASE_ADDR] = 0x02204FFC,
-+ [SWDEF_BASE_ADDR] = 0x411400,
- };
-
- static const u32 mt7915_offs[] = {
-@@ -607,10 +613,10 @@ static void mt7915_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) {
-+ mt7915_irq_disable(dev, MT_INT_MCU_CMD);
-+ if (val & MT_MCU_CMD_ALL_ERROR_MASK) {
- dev->reset_state = val;
-- ieee80211_queue_work(mt76_hw(dev), &dev->reset_work);
-- wake_up(&dev->reset_wait);
-+ mt7915_reset(dev, SER_TYPE_UNKNOWN);
- }
- }
- }
-diff --git a/mt7915/mt7915.h b/mt7915/mt7915.h
-index 24276da5..abd8d8c3 100644
---- a/mt7915/mt7915.h
-+++ b/mt7915/mt7915.h
-@@ -343,6 +343,15 @@ struct mt7915_dev {
- struct work_struct reset_work;
- wait_queue_head_t reset_wait;
- u32 reset_state;
-+ struct {
-+ bool hw_full_reset:1;
-+ bool hw_init_done:1;
-+ u32 reset_type;
-+ u32 cmd_fail_cnt;
-+ u32 wf_reset_wm_count;
-+ u32 wf_reset_wa_count;
-+ u32 wf_reset_wo_count;
-+ }ser;
-
- struct list_head sta_rc_list;
- struct list_head sta_poll_list;
-@@ -439,6 +448,13 @@ enum mt7915_rdd_cmd {
- RDD_IRQ_OFF,
- };
-
-+enum {
-+ SER_TYPE_NONE,
-+ SER_TYPE_PARTIAL_RESET,
-+ SER_TYPE_FULL_RESET,
-+ SER_TYPE_UNKNOWN,
-+};
-+
- static inline struct mt7915_phy *
- mt7915_hw_phy(struct ieee80211_hw *hw)
- {
-@@ -658,6 +674,17 @@ int mt7915_mcu_muru_debug_get(struct mt7915_phy *phy, void *ms);
- int mt7915_init_debugfs(struct mt7915_phy *phy);
- void mt7915_debugfs_rx_fw_monitor(struct mt7915_dev *dev, const void *data, int len);
- bool mt7915_debugfs_rx_log(struct mt7915_dev *dev, const void *data, int len);
-+int mt7915_fw_exception_chk(struct mt7915_dev *dev);
-+void mt7915_fw_heart_beat_chk(struct mt7915_dev *dev);
-+void mt7915_wfsys_reset(struct mt7915_dev *dev);
-+void mt7915_reset(struct mt7915_dev *dev, u8 type);
-+int mt7915_dma_reset(struct mt7915_dev *dev, bool force);
-+int __mt7915_start(struct ieee80211_hw *hw);
-+void mt7915_init_txpower(struct mt7915_dev *dev,
-+ struct ieee80211_supported_band *sband);
-+int mt7915_txbf_init(struct mt7915_dev *dev);
-+void mt7915_mac_init(struct mt7915_dev *dev);
-+int mt7915_run_firmware(struct mt7915_dev *dev);
- #ifdef CONFIG_MAC80211_DEBUGFS
- void mt7915_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
- struct ieee80211_sta *sta, struct dentry *dir);
-diff --git a/mt7915/regs.h b/mt7915/regs.h
-index 97984aaf..a2697e92 100644
---- a/mt7915/regs.h
-+++ b/mt7915/regs.h
-@@ -30,6 +30,8 @@ enum reg_rev {
- WFDMA_EXT_CSR_ADDR,
- CBTOP1_PHY_END,
- INFRA_MCU_ADDR_END,
-+ EXCEPTION_BASE_ADDR,
-+ SWDEF_BASE_ADDR,
- __MT_REG_MAX,
- };
-
-@@ -111,6 +113,11 @@ enum offs_rev {
- #define __REG(id) (dev->reg.reg_rev[(id)])
- #define __OFFS(id) (dev->reg.offs_rev[(id)])
-
-+/* MEM WFDMA */
-+#define WF_WFDMA_MEM_DMA 0x58000000
-+
-+#define WF_WFDMA_MEM_DMA_RX_RING_CTL (WF_WFDMA_MEM_DMA + (0x510))
-+
- /* MCU WFDMA0 */
- #define MT_MCU_WFDMA0_BASE 0x2000
- #define MT_MCU_WFDMA0(ofs) (MT_MCU_WFDMA0_BASE + (ofs))
-@@ -555,6 +562,10 @@ enum offs_rev {
- #define MT_WFDMA0_PRI_DLY_INT_CFG1 MT_WFDMA0(0x2f4)
- #define MT_WFDMA0_PRI_DLY_INT_CFG2 MT_WFDMA0(0x2f8)
-
-+#define MT_WFDMA0_MCU_HOST_INT_ENA MT_WFDMA0(0x1f4)
-+#define MT_WFDMA0_MT_WA_WDT_INT BIT(31)
-+#define MT_WFDMA0_MT_WM_WDT_INT BIT(30)
-+
- /* WFDMA1 */
- #define MT_WFDMA1_BASE 0xd5000
- #define MT_WFDMA1(ofs) (MT_WFDMA1_BASE + (ofs))
-@@ -700,6 +711,12 @@ enum offs_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)
-+#define MT_MCU_CMD_ALL_ERROR_MASK (MT_MCU_CMD_ERROR_MASK | \
-+ MT_MCU_CMD_WDT_MASK)
-+
- /* TOP RGU */
- #define MT_TOP_RGU_BASE 0x18000000
- #define MT_TOP_PWR_CTRL (MT_TOP_RGU_BASE + (0x0))
-@@ -942,12 +959,25 @@ enum offs_rev {
- #define MT_ADIE_TYPE_MASK BIT(1)
-
- /* FW MODE SYNC */
--#define MT_SWDEF_MODE 0x41f23c
--#define MT_SWDEF_MODE_MT7916 0x41143c
-+#define MT_SWDEF_BASE __REG(SWDEF_BASE_ADDR)
-+
-+#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_STATUS MT_SWDEF(0x040)
-+#define MT_SWDEF_PLE_STATUS MT_SWDEF(0x044)
-+#define MT_SWDEF_PLE1_STATUS MT_SWDEF(0x048)
-+#define MT_SWDEF_PLE_AMSDU_STATUS MT_SWDEF(0x04C)
-+#define MT_SWDEF_PSE_STATUS MT_SWDEF(0x050)
-+#define MT_SWDEF_PSE1_STATUS MT_SWDEF(0x054)
-+#define MT_SWDEF_LAMC_WISR6_BN0_STATUS MT_SWDEF(0x058)
-+#define MT_SWDEF_LAMC_WISR6_BN1_STATUS MT_SWDEF(0x05C)
-+#define MT_SWDEF_LAMC_WISR7_BN0_STATUS MT_SWDEF(0x060)
-+#define MT_SWDEF_LAMC_WISR7_BN1_STATUS MT_SWDEF(0x064)
-+
- #define MT_DIC_CMD_REG_BASE 0x41f000
- #define MT_DIC_CMD_REG(ofs) (MT_DIC_CMD_REG_BASE + (ofs))
- #define MT_DIC_CMD_REG_CMD MT_DIC_CMD_REG(0x10)
-@@ -1029,6 +1059,9 @@ enum offs_rev {
-
- #define MT_MCU_BUS_REMAP MT_MCU_BUS(0x120)
-
-+/* MISC */
-+#define MT_EXCEPTION_ADDR __REG(EXCEPTION_BASE_ADDR)
-+
- /* TOP CFG */
- #define MT_TOP_CFG_BASE 0x184b0000
- #define MT_TOP_CFG(ofs) (MT_TOP_CFG_BASE + (ofs))
---
-2.18.0
-
diff --git a/recipes-kernel/linux-mt76/files/patches/3001-mt76-mt7915-init-rssi-in-WTBL-when-add-station.patch b/recipes-kernel/linux-mt76/files/patches/1113-mt76-mt7915-init-rssi-in-WTBL-when-add-station.patch
similarity index 69%
rename from recipes-kernel/linux-mt76/files/patches/3001-mt76-mt7915-init-rssi-in-WTBL-when-add-station.patch
rename to recipes-kernel/linux-mt76/files/patches/1113-mt76-mt7915-init-rssi-in-WTBL-when-add-station.patch
index 22ae63b..fb1188e 100644
--- a/recipes-kernel/linux-mt76/files/patches/3001-mt76-mt7915-init-rssi-in-WTBL-when-add-station.patch
+++ b/recipes-kernel/linux-mt76/files/patches/1113-mt76-mt7915-init-rssi-in-WTBL-when-add-station.patch
@@ -1,17 +1,17 @@
-From 04ef8f969aa6a51dd6d9ccd2723513bed3a588a0 Mon Sep 17 00:00:00 2001
+From 9d57f49dd5ff756854029c484876325b43fc2b78 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] mt76: mt7915: init rssi in WTBL when add station
+Subject: [PATCH 1113/1116] 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 09659dc7..3c6c66b8 100644
+index 5b0a6d02..f50dbbb5 100644
--- a/mt7915/main.c
+++ b/mt7915/main.c
-@@ -671,6 +671,7 @@ int mt7915_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
+@@ -651,6 +651,7 @@ int mt7915_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
struct mt7915_phy *phy;
#endif
int ret, idx;
@@ -19,7 +19,7 @@
idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7915_WTBL_STA);
if (idx < 0)
-@@ -692,6 +693,9 @@ int mt7915_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
+@@ -672,6 +673,9 @@ int mt7915_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
if (ret)
return ret;
diff --git a/recipes-kernel/linux-mt76/files/patches/1114-mt76-mt7915-drop-packets-when-TWT-stations-use-more-.patch b/recipes-kernel/linux-mt76/files/patches/1114-mt76-mt7915-drop-packets-when-TWT-stations-use-more-.patch
new file mode 100644
index 0000000..743f41b
--- /dev/null
+++ b/recipes-kernel/linux-mt76/files/patches/1114-mt76-mt7915-drop-packets-when-TWT-stations-use-more-.patch
@@ -0,0 +1,98 @@
+From c83d3e3692a758084e4d78fad127043d8789d263 Mon Sep 17 00:00:00 2001
+From: Peter Chiu <chui-hao.chiu@mediatek.com>
+Date: Mon, 9 May 2022 16:36:38 +0800
+Subject: [PATCH] mt76: mt7915: drop packets when TWT stations use more tokens
+ than 128
+
+---
+ mt7915/mac.c | 21 ++++++++++++++++++---
+ mt7915/mt7915.h | 2 ++
+ 2 files changed, 20 insertions(+), 3 deletions(-)
+
+diff --git a/mt7915/mac.c b/mt7915/mac.c
+index c73e767b..588c0d58 100644
+--- a/mt7915/mac.c
++++ b/mt7915/mac.c
+@@ -1292,6 +1292,7 @@ int mt7915_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 mt7915_sta *msta = NULL;
+ struct mt76_txwi_cache *t;
+ struct mt7915_txp *txp;
+ int id, i, nbuf = tx_info->nbuf - 1;
+@@ -1305,8 +1306,6 @@ int mt7915_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
+ wcid = &dev->mt76.global_wcid;
+
+ if (sta) {
+- struct mt7915_sta *msta;
+-
+ msta = (struct mt7915_sta *)sta->drv_priv;
+
+ if (time_after(jiffies, msta->jiffies + HZ / 4)) {
+@@ -1318,10 +1317,22 @@ int mt7915_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
+ t = (struct mt76_txwi_cache *)(txwi + mdev->drv->txwi_size);
+ t->skb = tx_info->skb;
+
++ spin_lock_bh(&mdev->token_lock);
++ if (msta && msta->twt.flowid_mask && msta->token_count > 128) {
++ spin_unlock_bh(&mdev->token_lock);
++ return -1;
++ }
++ spin_unlock_bh(&mdev->token_lock);
++
+ id = mt76_token_consume(mdev, &t);
+ if (id < 0)
+ return id;
+
++ spin_lock_bh(&mdev->token_lock);
++ if (msta)
++ msta->token_count++;
++ spin_unlock_bh(&mdev->token_lock);
++
+ pid = mt76_tx_status_skb_add(mdev, wcid, tx_info->skb);
+ mt7915_mac_write_txwi(dev, txwi_ptr, tx_info->skb, wcid, pid, key,
+ false);
+@@ -1513,6 +1524,7 @@ mt7915_mac_tx_free(struct mt7915_dev *dev, void *data, int len)
+ struct mt76_dev *mdev = &dev->mt76;
+ struct mt76_txwi_cache *txwi;
+ struct ieee80211_sta *sta = NULL;
++ struct mt7915_sta *msta = NULL;
+ LIST_HEAD(free_list);
+ void *end = data + len;
+ bool v3, wake = false;
+@@ -1536,7 +1548,6 @@ mt7915_mac_tx_free(struct mt7915_dev *dev, void *data, int len)
+ * 1'b0: msdu_id with the same 'wcid pair' as above.
+ */
+ if (info & MT_TX_FREE_PAIR) {
+- struct mt7915_sta *msta;
+ struct mt76_wcid *wcid;
+ u16 idx;
+
+@@ -1569,6 +1580,10 @@ mt7915_mac_tx_free(struct mt7915_dev *dev, void *data, int len)
+ txwi = mt76_token_release(mdev, msdu, &wake);
+ if (!txwi)
+ continue;
++ spin_lock(&mdev->token_lock);
++ if (msta)
++ msta->token_count--;
++ spin_unlock(&mdev->token_lock);
+
+ mt7915_txwi_free(dev, txwi, sta, &free_list);
+ }
+diff --git a/mt7915/mt7915.h b/mt7915/mt7915.h
+index cd54f087..b78b1a9a 100644
+--- a/mt7915/mt7915.h
++++ b/mt7915/mt7915.h
+@@ -136,6 +136,8 @@ struct mt7915_sta {
+ u8 flowid_mask;
+ struct mt7915_twt_flow flow[MT7915_MAX_STA_TWT_AGRT];
+ } twt;
++
++ int token_count;
+ };
+
+ struct mt7915_vif_cap {
+--
+2.18.0
+
diff --git a/recipes-kernel/linux-mt76/files/patches/1115-mt76-airtime-fairness-feature-off-in-mac80211.patch b/recipes-kernel/linux-mt76/files/patches/1115-mt76-airtime-fairness-feature-off-in-mac80211.patch
new file mode 100644
index 0000000..a11702f
--- /dev/null
+++ b/recipes-kernel/linux-mt76/files/patches/1115-mt76-airtime-fairness-feature-off-in-mac80211.patch
@@ -0,0 +1,24 @@
+From fcf24bbef66458b2c44feadcd6f75f9ee20360cf 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 1115/1116] mt76: airtime fairness feature off in mac80211
+
+---
+ mac80211.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/mac80211.c b/mac80211.c
+index 49b99f36..e17b04b1 100644
+--- a/mac80211.c
++++ b/mac80211.c
+@@ -419,7 +419,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);
+- wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_AIRTIME_FAIRNESS);
+ wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_AQL);
+
+ wiphy->available_antennas_tx = phy->antenna_mask;
+--
+2.18.0
+
diff --git a/recipes-kernel/linux-mt76/files/patches/3000-mt76-remove-WED-support-patch-for-build-err.patch b/recipes-kernel/linux-mt76/files/patches/3000-mt76-remove-WED-support-patch-for-build-err.patch
index dd1e092..26fd886 100644
--- a/recipes-kernel/linux-mt76/files/patches/3000-mt76-remove-WED-support-patch-for-build-err.patch
+++ b/recipes-kernel/linux-mt76/files/patches/3000-mt76-remove-WED-support-patch-for-build-err.patch
@@ -1,4 +1,4 @@
-From f00aa90bc4a1b77e1b0c884b24a71c1b49a94ee6 Mon Sep 17 00:00:00 2001
+From 1100bd66f9de10e2091d6640d8d9952d12891a42 Mon Sep 17 00:00:00 2001
From: Sujuan Chen <sujuan.chen@mediatek.com>
Date: Tue, 12 Apr 2022 15:58:28 +0800
Subject: [PATCH] mt76:remove WED support patch for build err
@@ -232,10 +232,10 @@
}
EXPORT_SYMBOL_GPL(mt76_dma_cleanup);
diff --git a/mac80211.c b/mac80211.c
-index 21eaf994..ceab8412 100644
+index e17b04b1..1b9a400b 100644
--- a/mac80211.c
+++ b/mac80211.c
-@@ -1596,7 +1596,7 @@ EXPORT_SYMBOL_GPL(mt76_get_antenna);
+@@ -1594,7 +1594,7 @@ EXPORT_SYMBOL_GPL(mt76_get_antenna);
struct mt76_queue *
mt76_init_queue(struct mt76_dev *dev, int qid, int idx, int n_desc,
@@ -244,7 +244,7 @@
{
struct mt76_queue *hwq;
int err;
-@@ -1605,8 +1605,6 @@ mt76_init_queue(struct mt76_dev *dev, int qid, int idx, int n_desc,
+@@ -1603,8 +1603,6 @@ mt76_init_queue(struct mt76_dev *dev, int qid, int idx, int n_desc,
if (!hwq)
return ERR_PTR(-ENOMEM);
@@ -442,7 +442,7 @@
return ret;
diff --git a/mt7915/dma.c b/mt7915/dma.c
-index 219b440f..60b4368a 100644
+index 9e3d14db..4358e9bf 100644
--- a/mt7915/dma.c
+++ b/mt7915/dma.c
@@ -8,16 +8,9 @@
@@ -527,10 +527,10 @@
return ret;
diff --git a/mt7915/mac.c b/mt7915/mac.c
-index 8df38a23..8b0b90da 100644
+index 588c0d58..f3049639 100644
--- a/mt7915/mac.c
+++ b/mt7915/mac.c
-@@ -1379,29 +1379,6 @@ int mt7915_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
+@@ -1380,29 +1380,6 @@ int mt7915_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
return 0;
}
@@ -560,7 +560,7 @@
static void
mt7915_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi)
{
-@@ -1435,7 +1412,7 @@ mt7915_txp_skb_unmap(struct mt76_dev *dev, struct mt76_txwi_cache *t)
+@@ -1436,7 +1413,7 @@ mt7915_txp_skb_unmap(struct mt76_dev *dev, struct mt76_txwi_cache *t)
txp = mt7915_txwi_to_txp(dev, t);
for (i = 0; i < txp->nbuf; i++)
@@ -569,7 +569,7 @@
le16_to_cpu(txp->len[i]), DMA_TO_DEVICE);
}
-@@ -1444,7 +1421,6 @@ mt7915_txwi_free(struct mt7915_dev *dev, struct mt76_txwi_cache *t,
+@@ -1445,7 +1422,6 @@ mt7915_txwi_free(struct mt7915_dev *dev, struct mt76_txwi_cache *t,
struct ieee80211_sta *sta, struct list_head *free_list)
{
struct mt76_dev *mdev = &dev->mt76;
@@ -577,7 +577,7 @@
struct mt76_wcid *wcid;
__le32 *txwi;
u16 wcid_idx;
-@@ -1457,24 +1433,13 @@ mt7915_txwi_free(struct mt7915_dev *dev, struct mt76_txwi_cache *t,
+@@ -1458,24 +1434,13 @@ mt7915_txwi_free(struct mt7915_dev *dev, struct mt76_txwi_cache *t,
if (sta) {
wcid = (struct mt76_wcid *)sta->drv_priv;
wcid_idx = wcid->idx;
@@ -605,7 +605,7 @@
__mt76_tx_complete_skb(mdev, wcid_idx, t->skb, free_list);
out:
-@@ -1482,55 +1447,29 @@ out:
+@@ -1483,56 +1448,30 @@ out:
mt76_put_txwi(mdev, t);
}
@@ -651,6 +651,7 @@
+ struct mt76_phy *mphy_ext = mdev->phy2;
struct mt76_txwi_cache *txwi;
struct ieee80211_sta *sta = NULL;
+ struct mt7915_sta *msta = NULL;
LIST_HEAD(free_list);
+ struct sk_buff *skb, *tmp;
void *end = data + len;
@@ -670,7 +671,7 @@
total = le16_get_bits(free->ctrl, MT_TX_FREE_MSDU_CNT);
v3 = (FIELD_GET(MT_TX_FREE_VER, txd) == 0x4);
-@@ -1587,38 +1526,17 @@ mt7915_mac_tx_free(struct mt7915_dev *dev, void *data, int len)
+@@ -1589,38 +1528,17 @@ mt7915_mac_tx_free(struct mt7915_dev *dev, void *data, int len)
}
}
@@ -716,7 +717,7 @@
}
static bool
-@@ -1798,9 +1716,6 @@ bool mt7915_rx_check(struct mt76_dev *mdev, void *data, int len)
+@@ -1800,9 +1718,6 @@ bool mt7915_rx_check(struct mt76_dev *mdev, void *data, int len)
case PKT_TYPE_TXRX_NOTIFY:
mt7915_mac_tx_free(dev, data, len);
return false;
@@ -726,7 +727,7 @@
case PKT_TYPE_TXS:
for (rxd += 2; rxd + 8 <= end; rxd += 8)
mt7915_mac_add_txs(dev, rxd);
-@@ -1828,10 +1743,6 @@ void mt7915_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
+@@ -1830,10 +1745,6 @@ void mt7915_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
mt7915_mac_tx_free(dev, skb->data, skb->len);
napi_consume_skb(skb, 1);
break;
@@ -758,10 +759,10 @@
#define MT_TX_FREE_LATENCY GENMASK(12, 0)
/* 0: success, others: dropped */
diff --git a/mt7915/main.c b/mt7915/main.c
-index 23f89379..09659dc7 100644
+index 87f4c5ab..ffc2ed0d 100644
--- a/mt7915/main.c
+++ b/mt7915/main.c
-@@ -1414,39 +1414,6 @@ out:
+@@ -1405,39 +1405,6 @@ out:
return ret;
}
@@ -801,7 +802,7 @@
const struct ieee80211_ops mt7915_ops = {
.tx = mt7915_tx,
.start = mt7915_start,
-@@ -1494,7 +1461,4 @@ const struct ieee80211_ops mt7915_ops = {
+@@ -1485,7 +1452,4 @@ const struct ieee80211_ops mt7915_ops = {
.sta_add_debugfs = mt7915_sta_add_debugfs,
#endif
.set_radar_background = mt7915_set_radar_background,
@@ -810,10 +811,10 @@
-#endif
};
diff --git a/mt7915/mcu.c b/mt7915/mcu.c
-index 8d7e7422..afdbb5aa 100644
+index d547cf6f..562f3346 100755
--- a/mt7915/mcu.c
+++ b/mt7915/mcu.c
-@@ -2527,9 +2527,6 @@ int mt7915_run_firmware(struct mt7915_dev *dev)
+@@ -2575,9 +2575,6 @@ int mt7915_run_firmware(struct mt7915_dev *dev)
if (ret)
return ret;
@@ -824,7 +825,7 @@
if (ret)
return ret;
diff --git a/mt7915/mmio.c b/mt7915/mmio.c
-index f07b0565..561ac650 100644
+index b3de3a7a..3768c1a6 100644
--- a/mt7915/mmio.c
+++ b/mt7915/mmio.c
@@ -555,21 +555,15 @@ static void mt7915_rx_poll_complete(struct mt76_dev *mdev,
@@ -855,7 +856,7 @@
if (dev->hif2) {
intr1 = mt76_rr(dev, MT_INT1_SOURCE_CSR);
-@@ -624,15 +618,10 @@ static void mt7915_irq_tasklet(struct tasklet_struct *t)
+@@ -623,15 +617,10 @@ static void mt7915_irq_tasklet(struct tasklet_struct *t)
irqreturn_t mt7915_irq_handler(int irq, void *dev_instance)
{
struct mt7915_dev *dev = dev_instance;
@@ -875,7 +876,7 @@
if (!test_bit(MT76_STATE_INITIALIZED, &dev->mphy.state))
return IRQ_NONE;
diff --git a/mt7915/mt7915.h b/mt7915/mt7915.h
-index b7838385..454232ba 100644
+index b78b1a9a..fca0bfcb 100644
--- a/mt7915/mt7915.h
+++ b/mt7915/mt7915.h
@@ -517,8 +517,6 @@ struct mt7915_dev *mt7915_mmio_probe(struct device *pdev,
@@ -1026,7 +1027,7 @@
mt76_free_device(&dev->mt76);
diff --git a/mt7915/regs.h b/mt7915/regs.h
-index a3b9bf4c..27f682fe 100644
+index 99834310..02d097fa 100644
--- a/mt7915/regs.h
+++ b/mt7915/regs.h
@@ -591,31 +591,18 @@ enum offs_rev {
@@ -1077,7 +1078,7 @@
return err;
diff --git a/tx.c b/tx.c
-index 892f3618..2c26b955 100644
+index 0457c3eb..656b7090 100644
--- a/tx.c
+++ b/tx.c
@@ -725,12 +725,6 @@ int mt76_token_consume(struct mt76_dev *dev, struct mt76_txwi_cache **ptxwi)
diff --git a/recipes-kernel/linux-mt76/files/patches/patches.inc b/recipes-kernel/linux-mt76/files/patches/patches.inc
index b331b64..da8acdd 100644
--- a/recipes-kernel/linux-mt76/files/patches/patches.inc
+++ b/recipes-kernel/linux-mt76/files/patches/patches.inc
@@ -7,12 +7,20 @@
file://0007-mt76-mt7915-update-mt7986-CR-for-different-adie-vers.patch \
file://0009-mt76-mt7915-fix-table_mask-to-u16.patch \
file://0012-mt76-mt7915-reject-duplicated-twt-flow.patch \
+ file://0014-mt76-mt7915-limit-minimum-twt-duration-due-to-hw-lim.patch \
+ file://0015-mt76-mt7915-drop-undefined-action-frame.patch \
+ file://0016-mt76-mt7915-reowrk-SER-debugfs-knob.patch \
+ file://0017-mt76-mt7615-mt7915-do-reset_work-with-mt76-s-work-qu.patch \
+ file://0018-mt76-mt7915-add-support-for-6G-in-band-discovery.patch \
+ file://0019-mt76-mt7915-add-the-maximum-size-of-beacon-offload.patch \
file://100-Revert-of-net-pass-the-dst-buffer-to-of_get_mac_addr.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 \
file://1004-mt76-mt7915-add-support-for-muru_onoff-via-debugfs.patch \
file://1005-mt76-certification-patches.patch \
+ file://1007-mt76-mt7915-add-L0.5-system-error-recovery-support.patch \
+ file://1009-mt76-mt7915-add-support-for-runtime-set-in-band-disc.patch \
file://1100-mt76-testmode-support-eeprom-handle.patch \
file://1101-mt76-enable-more-5g-channels.patch \
file://1102-mt76-testmode-add-attributes-for-setting-rf-config.patch \
@@ -25,7 +33,8 @@
file://1109-mt76-testmode-add-support-to-queue-skb-of-multiple-s.patch \
file://1110-mt76-mt7915-implement-aid-support-in-testmode.patch \
file://1111-mt76-tool-add-more-commands.patch \
- file://1112-mt76-mt7915-add-L0.5-SER-for-mt7986.patch \
+ file://1113-mt76-mt7915-init-rssi-in-WTBL-when-add-station.patch \
+ file://1114-mt76-mt7915-drop-packets-when-TWT-stations-use-more-.patch \
+ file://1115-mt76-airtime-fairness-feature-off-in-mac80211.patch \
file://3000-mt76-remove-WED-support-patch-for-build-err.patch \
- file://3001-mt76-mt7915-init-rssi-in-WTBL-when-add-station.patch \
"