[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