[PATCH 22.03] mt76: backport various mt7603 fixes to improve Wi-Fi stability

Shiji Yang yangshiji66 at outlook.com
Thu Aug 24 22:44:48 PDT 2023


From: Shiji Yang <yangshiji66 at qq.com>

The SSID of MT7628 will disappear under heavy load, which makes
wireless unusable. These patches can fix this critical issue. Since
the mt76 mainline is no longer compatible with OpenWrt-22.03. So
let's backport them separately.

b14c2351dd wifi: mt76: mt7603: disable A-MSDU tx support on MT7628
85cc58378d wifi: mt76: mt7603: add missing register initialization for MT7628
c03d84c0d0 wifi: mt76: mt7603: improve stuck beacon handling
a8d9553d8f wifi: mt76: mt7603: improve watchdog reset reliablity
80b8bcf0e3 wifi: mt76: mt7603: rework/fix rx pse hang check
7ef4dd12d9 wifi: mt76: mt7603: fix tx filter/flush function
53edfc7aaa wifi: mt76: mt7603: fix beacon interval after disabling a single vif
72b87836d3 Revert "mt76: use IEEE80211_OFFLOAD_ENCAP_ENABLED instead of MT_DRV_AMSDU_OFFLOAD"

Fixes: https://github.com/openwrt/openwrt/issues/13283
Fixes: https://github.com/openwrt/openwrt/issues/10074
Fixes: https://github.com/openwrt/openwrt/issues/9219
Fixes: https://github.com/openwrt/openwrt/issues/8757
Fixes: https://github.com/openwrt/openwrt/issues/8314
Fixes: https://github.com/openwrt/openwrt/issues/8184
Signed-off-by: Shiji Yang <yangshiji66 at qq.com>
---
 package/kernel/mt76/Makefile                  |   2 +-
 ...211_OFFLOAD_ENCAP_ENABLED-instead-of.patch |  71 ++++++++
 ...ix-beacon-interval-after-disabling-a.patch |  26 +++
 ...-mt7603-fix-tx-filter-flush-function.patch | 134 ++++++++++++++
 ...-mt7603-rework-fix-rx-pse-hang-check.patch |  74 ++++++++
 ...03-improve-watchdog-reset-reliablity.patch |  73 ++++++++
 ...mt7603-improve-stuck-beacon-handling.patch | 163 ++++++++++++++++++
 ...-missing-register-initialization-for.patch |  28 +++
 ...-disable-A-MSDU-tx-support-on-MT7628.patch |  36 ++++
 9 files changed, 606 insertions(+), 1 deletion(-)
 create mode 100644 package/kernel/mt76/patches/130-Revert-mt76-use-IEEE80211_OFFLOAD_ENCAP_ENABLED-instead-of.patch
 create mode 100644 package/kernel/mt76/patches/131-wifi-mt76-mt7603-fix-beacon-interval-after-disabling-a.patch
 create mode 100644 package/kernel/mt76/patches/132-wifi-mt76-mt7603-fix-tx-filter-flush-function.patch
 create mode 100644 package/kernel/mt76/patches/133-wifi-mt76-mt7603-rework-fix-rx-pse-hang-check.patch
 create mode 100644 package/kernel/mt76/patches/134-wifi-mt76-mt7603-improve-watchdog-reset-reliablity.patch
 create mode 100644 package/kernel/mt76/patches/135-wifi-mt76-mt7603-improve-stuck-beacon-handling.patch
 create mode 100644 package/kernel/mt76/patches/136-wifi-mt76-mt7603-add-missing-register-initialization-for.patch
 create mode 100644 package/kernel/mt76/patches/137-wifi-mt76-mt7603-disable-A-MSDU-tx-support-on-MT7628.patch

diff --git a/package/kernel/mt76/Makefile b/package/kernel/mt76/Makefile
index 63d3a48085..44cee72f0c 100644
--- a/package/kernel/mt76/Makefile
+++ b/package/kernel/mt76/Makefile
@@ -1,7 +1,7 @@
 include $(TOPDIR)/rules.mk
 
 PKG_NAME:=mt76
-PKG_RELEASE=5
+PKG_RELEASE=6
 
 PKG_LICENSE:=GPLv2
 PKG_LICENSE_FILES:=
diff --git a/package/kernel/mt76/patches/130-Revert-mt76-use-IEEE80211_OFFLOAD_ENCAP_ENABLED-instead-of.patch b/package/kernel/mt76/patches/130-Revert-mt76-use-IEEE80211_OFFLOAD_ENCAP_ENABLED-instead-of.patch
new file mode 100644
index 0000000000..4135aedeef
--- /dev/null
+++ b/package/kernel/mt76/patches/130-Revert-mt76-use-IEEE80211_OFFLOAD_ENCAP_ENABLED-instead-of.patch
@@ -0,0 +1,71 @@
+From: Ben Greear <greearb at candelatech.com>
+Date: Sat, 1 Oct 2022 07:19:20 -0700
+Subject: [PATCH] Revert "mt76: use IEEE80211_OFFLOAD_ENCAP_ENABLED instead of
+ MT_DRV_AMSDU_OFFLOAD"
+
+This reverts commit f17f4864504d754bcbf31e4c89412cdf9946c409.
+
+The reverted commit significantly decreases performance when running
+a test where two MT7915 radios have 16 station vdevs each, configured
+for AC mode, and transmitting UDP traffic to AP.
+
+Reported-by: Carson Vandegriffe <carson.vandegriffe at candelatech.com>
+Signed-off-by: Ben Greear <greearb at candelatech.com>
+---
+ mac80211.c    | 8 ++++++--
+ mt76.h        | 1 +
+ mt7915/mmio.c | 3 ++-
+ mt7921/pci.c  | 3 ++-
+ 4 files changed, 11 insertions(+), 4 deletions(-)
+
+--- a/mac80211.c
++++ b/mac80211.c
+@@ -443,8 +443,12 @@ mt76_phy_init(struct mt76_phy *phy, stru
+ 	ieee80211_hw_set(hw, SUPPORTS_CLONED_SKBS);
+ 	ieee80211_hw_set(hw, SUPPORTS_AMSDU_IN_AMPDU);
+ 	ieee80211_hw_set(hw, SUPPORTS_REORDERING_BUFFER);
+-	ieee80211_hw_set(hw, TX_AMSDU);
+-	ieee80211_hw_set(hw, TX_FRAG_LIST);
++
++	if (!(dev->drv->drv_flags & MT_DRV_AMSDU_OFFLOAD)) {
++		ieee80211_hw_set(hw, TX_AMSDU);
++		ieee80211_hw_set(hw, TX_FRAG_LIST);
++	}
++
+ 	ieee80211_hw_set(hw, MFP_CAPABLE);
+ 	ieee80211_hw_set(hw, AP_LINK_PS);
+ 	ieee80211_hw_set(hw, REPORTS_TX_ACK_STATUS);
+--- a/mt76.h
++++ b/mt76.h
+@@ -388,6 +388,7 @@ struct mt76_hw_cap {
+ #define MT_DRV_SW_RX_AIRTIME		BIT(2)
+ #define MT_DRV_RX_DMA_HDR		BIT(3)
+ #define MT_DRV_HW_MGMT_TXQ		BIT(4)
++#define MT_DRV_AMSDU_OFFLOAD		BIT(5)
+ 
+ struct mt76_driver_ops {
+ 	u32 drv_flags;
+--- a/mt7915/mmio.c
++++ b/mt7915/mmio.c
+@@ -646,7 +646,8 @@ struct mt7915_dev *mt7915_mmio_probe(str
+ 	static const struct mt76_driver_ops drv_ops = {
+ 		/* txwi_size = txd size + txp size */
+ 		.txwi_size = MT_TXD_SIZE + sizeof(struct mt76_connac_fw_txp),
+-		.drv_flags = MT_DRV_TXWI_NO_FREE | MT_DRV_HW_MGMT_TXQ,
++		.drv_flags = MT_DRV_TXWI_NO_FREE | MT_DRV_HW_MGMT_TXQ |
++			     MT_DRV_AMSDU_OFFLOAD,
+ 		.survey_flags = SURVEY_INFO_TIME_TX |
+ 				SURVEY_INFO_TIME_RX |
+ 				SURVEY_INFO_TIME_BSS_RX,
+--- a/mt7921/pci.c
++++ b/mt7921/pci.c
+@@ -227,7 +227,8 @@ static int mt7921_pci_probe(struct pci_d
+ 	static const struct mt76_driver_ops drv_ops = {
+ 		/* txwi_size = txd size + txp size */
+ 		.txwi_size = MT_TXD_SIZE + sizeof(struct mt76_connac_hw_txp),
+-		.drv_flags = MT_DRV_TXWI_NO_FREE | MT_DRV_HW_MGMT_TXQ,
++		.drv_flags = MT_DRV_TXWI_NO_FREE | MT_DRV_HW_MGMT_TXQ |
++			     MT_DRV_AMSDU_OFFLOAD,
+ 		.survey_flags = SURVEY_INFO_TIME_TX |
+ 				SURVEY_INFO_TIME_RX |
+ 				SURVEY_INFO_TIME_BSS_RX,
diff --git a/package/kernel/mt76/patches/131-wifi-mt76-mt7603-fix-beacon-interval-after-disabling-a.patch b/package/kernel/mt76/patches/131-wifi-mt76-mt7603-fix-beacon-interval-after-disabling-a.patch
new file mode 100644
index 0000000000..a66d45742b
--- /dev/null
+++ b/package/kernel/mt76/patches/131-wifi-mt76-mt7603-fix-beacon-interval-after-disabling-a.patch
@@ -0,0 +1,26 @@
+From: Felix Fietkau <nbd at nbd.name>
+Date: Tue, 25 Jul 2023 12:37:59 +0200
+Subject: [PATCH] wifi: mt76: mt7603: fix beacon interval after disabling a
+ single vif
+
+When disabling beacons on a vif, intval is 0. Ensure that dev->mt76.beacon_int
+is not overwritten in this case, so that beacons continue to work for other
+interfaces.
+
+Signed-off-by: Felix Fietkau <nbd at nbd.name>
+---
+ mt7603/beacon.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/mt7603/beacon.c
++++ b/mt7603/beacon.c
+@@ -161,7 +161,8 @@ void mt7603_beacon_set_timer(struct mt76
+ 		return;
+ 	}
+ 
+-	dev->mt76.beacon_int = intval;
++	if (intval)
++		dev->mt76.beacon_int = intval;
+ 	mt76_wr(dev, MT_TBTT,
+ 		FIELD_PREP(MT_TBTT_PERIOD, intval) | MT_TBTT_CAL_ENABLE);
+ 
diff --git a/package/kernel/mt76/patches/132-wifi-mt76-mt7603-fix-tx-filter-flush-function.patch b/package/kernel/mt76/patches/132-wifi-mt76-mt7603-fix-tx-filter-flush-function.patch
new file mode 100644
index 0000000000..8242a9a41a
--- /dev/null
+++ b/package/kernel/mt76/patches/132-wifi-mt76-mt7603-fix-tx-filter-flush-function.patch
@@ -0,0 +1,134 @@
+From: Felix Fietkau <nbd at nbd.name>
+Date: Tue, 25 Jul 2023 21:06:03 +0200
+Subject: [PATCH] wifi: mt76: mt7603: fix tx filter/flush function
+
+Setting MT_TX_ABORT does not abort any transmission for a wtbl index on its
+own. Instead, it modifies the behavior of a queue flush to make it selectively
+flush packets for a particular wtbl index.
+Adjust powersave filtering to make use of this in order to avoid running into
+unnecessary timeouts while flushing
+
+Signed-off-by: Felix Fietkau <nbd at nbd.name>
+---
+ mt7603/mac.c    | 21 ++++++++++++++++-----
+ mt7603/main.c   |  5 ++++-
+ mt7603/mt7603.h |  2 +-
+ mt7603/regs.h   |  7 +++++++
+ 4 files changed, 28 insertions(+), 7 deletions(-)
+
+--- a/mt7603/mac.c
++++ b/mt7603/mac.c
+@@ -178,8 +178,9 @@ mt7603_wtbl_set_skip_tx(struct mt7603_de
+ 	mt76_wr(dev, addr + 3 * 4, val);
+ }
+ 
+-void mt7603_filter_tx(struct mt7603_dev *dev, int idx, bool abort)
++void mt7603_filter_tx(struct mt7603_dev *dev, int mac_idx, int idx, bool abort)
+ {
++	u32 flush_mask;
+ 	int i, port, queue;
+ 
+ 	if (abort) {
+@@ -195,6 +196,18 @@ void mt7603_filter_tx(struct mt7603_dev
+ 	mt76_wr(dev, MT_TX_ABORT, MT_TX_ABORT_EN |
+ 			FIELD_PREP(MT_TX_ABORT_WCID, idx));
+ 
++	flush_mask = MT_WF_ARB_TX_FLUSH_AC0 |
++		     MT_WF_ARB_TX_FLUSH_AC1 |
++		     MT_WF_ARB_TX_FLUSH_AC2 |
++		     MT_WF_ARB_TX_FLUSH_AC3;
++	flush_mask <<= mac_idx;
++
++	mt76_wr(dev, MT_WF_ARB_TX_FLUSH_0, flush_mask);
++	mt76_poll(dev, MT_WF_ARB_TX_FLUSH_0, flush_mask, 0, 20000);
++	mt76_wr(dev, MT_WF_ARB_TX_START_0, flush_mask);
++
++	mt76_wr(dev, MT_TX_ABORT, 0);
++
+ 	for (i = 0; i < 4; i++) {
+ 		mt76_wr(dev, MT_DMA_FQCR0, MT_DMA_FQCR0_BUSY |
+ 			FIELD_PREP(MT_DMA_FQCR0_TARGET_WCID, idx) |
+@@ -202,13 +215,11 @@ void mt7603_filter_tx(struct mt7603_dev
+ 			FIELD_PREP(MT_DMA_FQCR0_DEST_PORT_ID, port) |
+ 			FIELD_PREP(MT_DMA_FQCR0_DEST_QUEUE_ID, queue));
+ 
+-		mt76_poll(dev, MT_DMA_FQCR0, MT_DMA_FQCR0_BUSY, 0, 15000);
++		mt76_poll(dev, MT_DMA_FQCR0, MT_DMA_FQCR0_BUSY, 0, 5000);
+ 	}
+ 
+ 	WARN_ON_ONCE(mt76_rr(dev, MT_DMA_FQCR0) & MT_DMA_FQCR0_BUSY);
+ 
+-	mt76_wr(dev, MT_TX_ABORT, 0);
+-
+ 	mt7603_wtbl_set_skip_tx(dev, idx, false);
+ }
+ 
+@@ -245,7 +256,7 @@ void mt7603_wtbl_set_ps(struct mt7603_de
+ 	mt76_poll(dev, MT_PSE_RTA, MT_PSE_RTA_BUSY, 0, 5000);
+ 
+ 	if (enabled)
+-		mt7603_filter_tx(dev, idx, false);
++		mt7603_filter_tx(dev, sta->vif->idx, idx, false);
+ 
+ 	addr = mt7603_wtbl1_addr(idx);
+ 	mt76_set(dev, MT_WTBL1_OR, MT_WTBL1_OR_PSM_WRITE);
+--- a/mt7603/main.c
++++ b/mt7603/main.c
+@@ -69,6 +69,7 @@ mt7603_add_interface(struct ieee80211_hw
+ 	INIT_LIST_HEAD(&mvif->sta.poll_list);
+ 	mvif->sta.wcid.idx = idx;
+ 	mvif->sta.wcid.hw_key_idx = -1;
++	mvif->sta.vif = mvif;
+ 	mt76_packet_id_init(&mvif->sta.wcid);
+ 
+ 	eth_broadcast_addr(bc_addr);
+@@ -357,6 +358,7 @@ mt7603_sta_add(struct mt76_dev *mdev, st
+ 	msta->smps = ~0;
+ 	msta->wcid.sta = 1;
+ 	msta->wcid.idx = idx;
++	msta->vif = mvif;
+ 	mt7603_wtbl_init(dev, idx, mvif->idx, sta->addr);
+ 	mt7603_wtbl_set_ps(dev, msta, false);
+ 
+@@ -380,12 +382,13 @@ mt7603_sta_remove(struct mt76_dev *mdev,
+ 		  struct ieee80211_sta *sta)
+ {
+ 	struct mt7603_dev *dev = container_of(mdev, struct mt7603_dev, mt76);
++	struct mt7603_vif *mvif = (struct mt7603_vif *)vif->drv_priv;
+ 	struct mt7603_sta *msta = (struct mt7603_sta *)sta->drv_priv;
+ 	struct mt76_wcid *wcid = (struct mt76_wcid *)sta->drv_priv;
+ 
+ 	spin_lock_bh(&dev->ps_lock);
+ 	__skb_queue_purge(&msta->psq);
+-	mt7603_filter_tx(dev, wcid->idx, true);
++	mt7603_filter_tx(dev, mvif->idx, wcid->idx, true);
+ 	spin_unlock_bh(&dev->ps_lock);
+ 
+ 	spin_lock_bh(&dev->sta_poll_lock);
+--- a/mt7603/mt7603.h
++++ b/mt7603/mt7603.h
+@@ -234,7 +234,7 @@ void mt7603_wtbl_set_ps(struct mt7603_de
+ 			bool enabled);
+ void mt7603_wtbl_set_smps(struct mt7603_dev *dev, struct mt7603_sta *sta,
+ 			  bool enabled);
+-void mt7603_filter_tx(struct mt7603_dev *dev, int idx, bool abort);
++void mt7603_filter_tx(struct mt7603_dev *dev, int mac_idx, int idx, bool abort);
+ 
+ int mt7603_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
+ 			  enum mt76_txq_id qid, struct mt76_wcid *wcid,
+--- a/mt7603/regs.h
++++ b/mt7603/regs.h
+@@ -309,6 +309,13 @@ enum {
+ #define MT_WF_ARB_TX_STOP_0		MT_WF_ARB(0x110)
+ #define MT_WF_ARB_TX_STOP_1		MT_WF_ARB(0x114)
+ 
++#define MT_WF_ARB_TX_FLUSH_AC0		BIT(0)
++#define MT_WF_ARB_TX_FLUSH_AC1		BIT(5)
++#define MT_WF_ARB_TX_FLUSH_AC2		BIT(10)
++#define MT_WF_ARB_TX_FLUSH_AC3		BIT(16)
++#define MT_WF_ARB_TX_FLUSH_AC4		BIT(21)
++#define MT_WF_ARB_TX_FLUSH_AC5		BIT(26)
++
+ #define MT_WF_ARB_BCN_START		MT_WF_ARB(0x118)
+ #define MT_WF_ARB_BCN_START_BSSn(n)	BIT(0 + (n))
+ #define MT_WF_ARB_BCN_START_T_PRE_TTTT	BIT(10)
diff --git a/package/kernel/mt76/patches/133-wifi-mt76-mt7603-rework-fix-rx-pse-hang-check.patch b/package/kernel/mt76/patches/133-wifi-mt76-mt7603-rework-fix-rx-pse-hang-check.patch
new file mode 100644
index 0000000000..48d417d5ac
--- /dev/null
+++ b/package/kernel/mt76/patches/133-wifi-mt76-mt7603-rework-fix-rx-pse-hang-check.patch
@@ -0,0 +1,74 @@
+From: Felix Fietkau <nbd at nbd.name>
+Date: Fri, 28 Jul 2023 09:51:01 +0200
+Subject: [PATCH] wifi: mt76: mt7603: rework/fix rx pse hang check
+
+It turns out that the code in mt7603_rx_pse_busy() does not detect actual
+hardware hangs, it only checks for busy conditions in PSE.
+A reset should only be performed if these conditions are true and if there
+is no rx activity as well.
+Reset the counter whenever a rx interrupt occurs. In order to also deal with
+a fully loaded CPU that leaves interrupts disabled with continuous NAPI
+polling, also check for pending rx interrupts in the function itself.
+
+Fixes: c8846e101502 ("mt76: add driver for MT7603E and MT7628/7688")
+Signed-off-by: Felix Fietkau <nbd at nbd.name>
+---
+ mt7603/core.c |  2 ++
+ mt7603/mac.c  | 23 ++++++++++++++++-------
+ 2 files changed, 18 insertions(+), 7 deletions(-)
+
+--- a/mt7603/core.c
++++ b/mt7603/core.c
+@@ -42,11 +42,13 @@ irqreturn_t mt7603_irq_handler(int irq,
+ 	}
+ 
+ 	if (intr & MT_INT_RX_DONE(0)) {
++		dev->rx_pse_check = 0;
+ 		mt7603_irq_disable(dev, MT_INT_RX_DONE(0));
+ 		napi_schedule(&dev->mt76.napi[0]);
+ 	}
+ 
+ 	if (intr & MT_INT_RX_DONE(1)) {
++		dev->rx_pse_check = 0;
+ 		mt7603_irq_disable(dev, MT_INT_RX_DONE(1));
+ 		napi_schedule(&dev->mt76.napi[1]);
+ 	}
+--- a/mt7603/mac.c
++++ b/mt7603/mac.c
+@@ -1565,20 +1565,29 @@ static bool mt7603_rx_pse_busy(struct mt
+ {
+ 	u32 addr, val;
+ 
+-	if (mt76_rr(dev, MT_MCU_DEBUG_RESET) & MT_MCU_DEBUG_RESET_QUEUES)
+-		return true;
+-
+ 	if (mt7603_rx_fifo_busy(dev))
+-		return false;
++		goto out;
+ 
+ 	addr = mt7603_reg_map(dev, MT_CLIENT_BASE_PHYS_ADDR + MT_CLIENT_STATUS);
+ 	mt76_wr(dev, addr, 3);
+ 	val = mt76_rr(dev, addr) >> 16;
+ 
+-	if (is_mt7628(dev) && (val & 0x4001) == 0x4001)
+-		return true;
++	if (!(val & BIT(0)))
++		return false;
++
++	if (is_mt7628(dev))
++		val &= 0xa000;
++	else
++		val &= 0x8000;
++	if (!val)
++		return false;
++
++out:
++	if (mt76_rr(dev, MT_INT_SOURCE_CSR) &
++	    (MT_INT_RX_DONE(0) | MT_INT_RX_DONE(1)))
++		return false;
+ 
+-	return (val & 0x8001) == 0x8001 || (val & 0xe001) == 0xe001;
++	return true;
+ }
+ 
+ static bool
diff --git a/package/kernel/mt76/patches/134-wifi-mt76-mt7603-improve-watchdog-reset-reliablity.patch b/package/kernel/mt76/patches/134-wifi-mt76-mt7603-improve-watchdog-reset-reliablity.patch
new file mode 100644
index 0000000000..71a33bb97e
--- /dev/null
+++ b/package/kernel/mt76/patches/134-wifi-mt76-mt7603-improve-watchdog-reset-reliablity.patch
@@ -0,0 +1,73 @@
+From: Felix Fietkau <nbd at nbd.name>
+Date: Fri, 28 Jul 2023 16:04:40 +0200
+Subject: [PATCH] wifi: mt76: mt7603: improve watchdog reset reliablity
+
+Only trigger PSE reset if PSE was stuck, otherwise it can cause DMA issues.
+Trigger the PSE reset while DMA is fully stopped in order to improve
+reliabilty.
+
+Fixes: c8846e101502 ("mt76: add driver for MT7603E and MT7628/7688")
+Signed-off-by: Felix Fietkau <nbd at nbd.name>
+---
+ mt7603/mac.c | 29 ++++++++++++-----------------
+ 1 file changed, 12 insertions(+), 17 deletions(-)
+
+--- a/mt7603/mac.c
++++ b/mt7603/mac.c
+@@ -1436,15 +1436,6 @@ static void mt7603_mac_watchdog_reset(st
+ 
+ 	mt7603_beacon_set_timer(dev, -1, 0);
+ 
+-	if (dev->reset_cause[RESET_CAUSE_RESET_FAILED] ||
+-	    dev->cur_reset_cause == RESET_CAUSE_RX_PSE_BUSY ||
+-	    dev->cur_reset_cause == RESET_CAUSE_BEACON_STUCK ||
+-	    dev->cur_reset_cause == RESET_CAUSE_TX_HANG)
+-		mt7603_pse_reset(dev);
+-
+-	if (dev->reset_cause[RESET_CAUSE_RESET_FAILED])
+-		goto skip_dma_reset;
+-
+ 	mt7603_mac_stop(dev);
+ 
+ 	mt76_clear(dev, MT_WPDMA_GLO_CFG,
+@@ -1454,28 +1445,32 @@ static void mt7603_mac_watchdog_reset(st
+ 
+ 	mt7603_irq_disable(dev, mask);
+ 
+-	mt76_set(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_FORCE_TX_EOF);
+-
+ 	mt7603_pse_client_reset(dev);
+ 
+ 	mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[MT_MCUQ_WM], true);
+ 	for (i = 0; i < __MT_TXQ_MAX; i++)
+ 		mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[i], true);
+ 
++	mt7603_dma_sched_reset(dev);
++
++	mt76_tx_status_check(&dev->mt76, true);
++
+ 	mt76_for_each_q_rx(&dev->mt76, i) {
+ 		mt76_queue_rx_reset(dev, i);
+ 	}
+ 
+-	mt76_tx_status_check(&dev->mt76, true);
++	if (dev->reset_cause[RESET_CAUSE_RESET_FAILED] ||
++	    dev->cur_reset_cause == RESET_CAUSE_RX_PSE_BUSY)
++		mt7603_pse_reset(dev);
+ 
+-	mt7603_dma_sched_reset(dev);
++	if (!dev->reset_cause[RESET_CAUSE_RESET_FAILED]) {
++		mt7603_mac_dma_start(dev);
+ 
+-	mt7603_mac_dma_start(dev);
++		mt7603_irq_enable(dev, mask);
+ 
+-	mt7603_irq_enable(dev, mask);
++		clear_bit(MT76_RESET, &dev->mphy.state);
++	}
+ 
+-skip_dma_reset:
+-	clear_bit(MT76_RESET, &dev->mphy.state);
+ 	mutex_unlock(&dev->mt76.mutex);
+ 
+ 	mt76_worker_enable(&dev->mt76.tx_worker);
diff --git a/package/kernel/mt76/patches/135-wifi-mt76-mt7603-improve-stuck-beacon-handling.patch b/package/kernel/mt76/patches/135-wifi-mt76-mt7603-improve-stuck-beacon-handling.patch
new file mode 100644
index 0000000000..1e5212b039
--- /dev/null
+++ b/package/kernel/mt76/patches/135-wifi-mt76-mt7603-improve-stuck-beacon-handling.patch
@@ -0,0 +1,163 @@
+From: Felix Fietkau <nbd at nbd.name>
+Date: Fri, 28 Jul 2023 16:21:18 +0200
+Subject: [PATCH] wifi: mt76: mt7603: improve stuck beacon handling
+
+Before preparing the new beacon, check the queue status, flush out all
+previous beacons and buffered multicast packets, then (if necessary)
+try to recover more gracefully from a stuck beacon condition by making a
+less invasive attempt at getting the MAC un-stuck.
+
+Fixes: c8846e101502 ("mt76: add driver for MT7603E and MT7628/7688")
+Signed-off-by: Felix Fietkau <nbd at nbd.name>
+---
+ mt7603/beacon.c | 76 +++++++++++++++++++++++++++++++++++--------------
+ mt7603/regs.h   |  5 ++++
+ 2 files changed, 60 insertions(+), 21 deletions(-)
+
+--- a/mt7603/beacon.c
++++ b/mt7603/beacon.c
+@@ -10,12 +10,31 @@ struct beacon_bc_data {
+ };
+ 
+ static void
++mt7603_mac_stuck_beacon_recovery(struct mt7603_dev *dev)
++{
++	if (dev->beacon_check % 5 != 4)
++		return;
++
++	mt76_clear(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_TX_DMA_EN);
++	mt76_set(dev, MT_SCH_4, MT_SCH_4_RESET);
++	mt76_clear(dev, MT_SCH_4, MT_SCH_4_RESET);
++	mt76_set(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_TX_DMA_EN);
++
++	mt76_set(dev, MT_WF_CFG_OFF_WOCCR, MT_WF_CFG_OFF_WOCCR_TMAC_GC_DIS);
++	mt76_set(dev, MT_ARB_SCR, MT_ARB_SCR_TX_DISABLE);
++	mt76_clear(dev, MT_ARB_SCR, MT_ARB_SCR_TX_DISABLE);
++	mt76_clear(dev, MT_WF_CFG_OFF_WOCCR, MT_WF_CFG_OFF_WOCCR_TMAC_GC_DIS);
++}
++
++static void
+ mt7603_update_beacon_iter(void *priv, u8 *mac, struct ieee80211_vif *vif)
+ {
+ 	struct mt7603_dev *dev = (struct mt7603_dev *)priv;
+ 	struct mt76_dev *mdev = &dev->mt76;
+ 	struct mt7603_vif *mvif = (struct mt7603_vif *)vif->drv_priv;
+ 	struct sk_buff *skb = NULL;
++	u32 om_idx = mvif->idx;
++	u32 val;
+ 
+ 	if (!(mdev->beacon_mask & BIT(mvif->idx)))
+ 		return;
+@@ -24,20 +43,33 @@ mt7603_update_beacon_iter(void *priv, u8
+ 	if (!skb)
+ 		return;
+ 
+-	mt76_tx_queue_skb(dev, dev->mphy.q_tx[MT_TXQ_BEACON],
+-			  MT_TXQ_BEACON, skb, &mvif->sta.wcid, NULL);
++	if (om_idx)
++		om_idx |= 0x10;
++	val = MT_DMA_FQCR0_BUSY | MT_DMA_FQCR0_MODE |
++		FIELD_PREP(MT_DMA_FQCR0_TARGET_BSS, om_idx) |
++		FIELD_PREP(MT_DMA_FQCR0_DEST_PORT_ID, 3) |
++		FIELD_PREP(MT_DMA_FQCR0_DEST_QUEUE_ID, 8);
+ 
+ 	spin_lock_bh(&dev->ps_lock);
+-	mt76_wr(dev, MT_DMA_FQCR0, MT_DMA_FQCR0_BUSY |
+-		FIELD_PREP(MT_DMA_FQCR0_TARGET_WCID, mvif->sta.wcid.idx) |
+-		FIELD_PREP(MT_DMA_FQCR0_TARGET_QID,
+-			   dev->mphy.q_tx[MT_TXQ_CAB]->hw_idx) |
+-		FIELD_PREP(MT_DMA_FQCR0_DEST_PORT_ID, 3) |
+-		FIELD_PREP(MT_DMA_FQCR0_DEST_QUEUE_ID, 8));
+ 
+-	if (!mt76_poll(dev, MT_DMA_FQCR0, MT_DMA_FQCR0_BUSY, 0, 5000))
++	mt76_wr(dev, MT_DMA_FQCR0, val |
++		FIELD_PREP(MT_DMA_FQCR0_TARGET_QID, MT_TX_HW_QUEUE_BCN));
++	if (!mt76_poll(dev, MT_DMA_FQCR0, MT_DMA_FQCR0_BUSY, 0, 5000)) {
+ 		dev->beacon_check = MT7603_WATCHDOG_TIMEOUT;
++		goto out;
++	}
++
++	mt76_wr(dev, MT_DMA_FQCR0, val |
++		FIELD_PREP(MT_DMA_FQCR0_TARGET_QID, MT_TX_HW_QUEUE_BMC));
++	if (!mt76_poll(dev, MT_DMA_FQCR0, MT_DMA_FQCR0_BUSY, 0, 5000)) {
++		dev->beacon_check = MT7603_WATCHDOG_TIMEOUT;
++		goto out;
++	}
+ 
++	mt76_tx_queue_skb(dev, dev->mphy.q_tx[MT_TXQ_BEACON],
++			  MT_TXQ_BEACON, skb, &mvif->sta.wcid, NULL);
++
++out:
+ 	spin_unlock_bh(&dev->ps_lock);
+ }
+ 
+@@ -81,6 +113,18 @@ void mt7603_pre_tbtt_tasklet(struct task
+ 	data.dev = dev;
+ 	__skb_queue_head_init(&data.q);
+ 
++	/* Flush all previous CAB queue packets and beacons */
++	mt76_wr(dev, MT_WF_ARB_CAB_FLUSH, GENMASK(30, 16) | BIT(0));
++
++	mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[MT_TXQ_CAB], false);
++	mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[MT_TXQ_BEACON], false);
++
++	if (dev->mphy.q_tx[MT_TXQ_BEACON]->queued > 0)
++		dev->beacon_check++;
++	else
++		dev->beacon_check = 0;
++	mt7603_mac_stuck_beacon_recovery(dev);
++
+ 	q = dev->mphy.q_tx[MT_TXQ_BEACON];
+ 	spin_lock(&q->lock);
+ 	ieee80211_iterate_active_interfaces_atomic(mt76_hw(dev),
+@@ -89,14 +133,9 @@ void mt7603_pre_tbtt_tasklet(struct task
+ 	mt76_queue_kick(dev, q);
+ 	spin_unlock(&q->lock);
+ 
+-	/* Flush all previous CAB queue packets */
+-	mt76_wr(dev, MT_WF_ARB_CAB_FLUSH, GENMASK(30, 16) | BIT(0));
+-
+-	mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[MT_TXQ_CAB], false);
+-
+ 	mt76_csa_check(mdev);
+ 	if (mdev->csa_complete)
+-		goto out;
++		return;
+ 
+ 	q = dev->mphy.q_tx[MT_TXQ_CAB];
+ 	do {
+@@ -108,7 +147,7 @@ void mt7603_pre_tbtt_tasklet(struct task
+ 		 skb_queue_len(&data.q) < 8);
+ 
+ 	if (skb_queue_empty(&data.q))
+-		goto out;
++		return;
+ 
+ 	for (i = 0; i < ARRAY_SIZE(data.tail); i++) {
+ 		if (!data.tail[i])
+@@ -136,11 +175,6 @@ void mt7603_pre_tbtt_tasklet(struct task
+ 		MT_WF_ARB_CAB_START_BSSn(0) |
+ 		(MT_WF_ARB_CAB_START_BSS0n(1) *
+ 		 ((1 << (MT7603_MAX_INTERFACES - 1)) - 1)));
+-
+-out:
+-	mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[MT_TXQ_BEACON], false);
+-	if (dev->mphy.q_tx[MT_TXQ_BEACON]->queued > hweight8(mdev->beacon_mask))
+-		dev->beacon_check++;
+ }
+ 
+ void mt7603_beacon_set_timer(struct mt7603_dev *dev, int idx, int intval)
+--- a/mt7603/regs.h
++++ b/mt7603/regs.h
+@@ -469,6 +469,11 @@ enum {
+ #define MT_WF_SEC_BASE			0x21a00
+ #define MT_WF_SEC(ofs)			(MT_WF_SEC_BASE + (ofs))
+ 
++#define MT_WF_CFG_OFF_BASE		0x21e00
++#define MT_WF_CFG_OFF(ofs)		(MT_WF_CFG_OFF_BASE + (ofs))
++#define MT_WF_CFG_OFF_WOCCR		MT_WF_CFG_OFF(0x004)
++#define MT_WF_CFG_OFF_WOCCR_TMAC_GC_DIS	BIT(4)
++
+ #define MT_SEC_SCR			MT_WF_SEC(0x004)
+ #define MT_SEC_SCR_MASK_ORDER		GENMASK(1, 0)
+ 
diff --git a/package/kernel/mt76/patches/136-wifi-mt76-mt7603-add-missing-register-initialization-for.patch b/package/kernel/mt76/patches/136-wifi-mt76-mt7603-add-missing-register-initialization-for.patch
new file mode 100644
index 0000000000..b728fee062
--- /dev/null
+++ b/package/kernel/mt76/patches/136-wifi-mt76-mt7603-add-missing-register-initialization-for.patch
@@ -0,0 +1,28 @@
+From: Felix Fietkau <nbd at nbd.name>
+Date: Fri, 28 Jul 2023 16:23:47 +0200
+Subject: [PATCH] wifi: mt76: mt7603: add missing register initialization for
+ MT7628
+
+Ported from the vendor driver code
+
+Signed-off-by: Felix Fietkau <nbd at nbd.name>
+---
+ mt7603/init.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+--- a/mt7603/init.c
++++ b/mt7603/init.c
+@@ -184,6 +184,13 @@ mt7603_mac_init(struct mt7603_dev *dev)
+ 
+ 	mt76_set(dev, MT_TMAC_TCR, MT_TMAC_TCR_RX_RIFS_MODE);
+ 
++	if (is_mt7628(dev)) {
++		mt76_set(dev, MT_TMAC_TCR,
++			 MT_TMAC_TCR_TXOP_BURST_STOP | BIT(1) | BIT(0));
++		mt76_set(dev, MT_TXREQ, BIT(27));
++		mt76_set(dev, MT_AGG_TMP, GENMASK(4, 2));
++	}
++
+ 	mt7603_set_tmac_template(dev);
+ 
+ 	/* Enable RX group to HIF */
diff --git a/package/kernel/mt76/patches/137-wifi-mt76-mt7603-disable-A-MSDU-tx-support-on-MT7628.patch b/package/kernel/mt76/patches/137-wifi-mt76-mt7603-disable-A-MSDU-tx-support-on-MT7628.patch
new file mode 100644
index 0000000000..f3fdd1d499
--- /dev/null
+++ b/package/kernel/mt76/patches/137-wifi-mt76-mt7603-disable-A-MSDU-tx-support-on-MT7628.patch
@@ -0,0 +1,36 @@
+From: Felix Fietkau <nbd at nbd.name>
+Date: Mon, 14 Aug 2023 14:10:51 +0200
+Subject: [PATCH] wifi: mt76: mt7603: disable A-MSDU tx support on MT7628
+
+It was reported that this can cause the PSE hang issues, even with a low
+number of fragments.
+
+Link: https://github.com/openwrt/mt76/issues/793#issuecomment-1676529138
+Signed-off-by: Felix Fietkau <nbd at nbd.name>
+---
+ mac80211.c    | 3 ++-
+ mt7603/init.c | 1 +
+ 2 files changed, 3 insertions(+), 1 deletion(-)
+
+--- a/mac80211.c
++++ b/mac80211.c
+@@ -444,7 +444,8 @@ mt76_phy_init(struct mt76_phy *phy, stru
+ 	ieee80211_hw_set(hw, SUPPORTS_AMSDU_IN_AMPDU);
+ 	ieee80211_hw_set(hw, SUPPORTS_REORDERING_BUFFER);
+ 
+-	if (!(dev->drv->drv_flags & MT_DRV_AMSDU_OFFLOAD)) {
++	if (!(dev->drv->drv_flags & MT_DRV_AMSDU_OFFLOAD) &&
++	    hw->max_tx_fragments > 1) {
+ 		ieee80211_hw_set(hw, TX_AMSDU);
+ 		ieee80211_hw_set(hw, TX_FRAG_LIST);
+ 	}
+--- a/mt7603/init.c
++++ b/mt7603/init.c
+@@ -526,6 +526,7 @@ int mt7603_register_device(struct mt7603
+ 	hw->max_rates = 3;
+ 	hw->max_report_rates = 7;
+ 	hw->max_rate_tries = 11;
++	hw->max_tx_fragments = 1;
+ 
+ 	hw->radiotap_timestamp.units_pos =
+ 		IEEE80211_RADIOTAP_TIMESTAMP_UNIT_US;
-- 
2.41.0




More information about the openwrt-devel mailing list