From: Shiji Yang <yangshij...@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 <yangshij...@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 <gree...@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.vandegri...@candelatech.com>
+Signed-off-by: Ben Greear <gree...@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 <n...@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 <n...@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 <n...@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 <n...@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 <n...@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 <n...@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 <n...@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 <n...@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 <n...@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 <n...@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 <n...@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 <n...@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 <n...@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 <n...@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


_______________________________________________
openwrt-devel mailing list
openwrt-devel@lists.openwrt.org
https://lists.openwrt.org/mailman/listinfo/openwrt-devel

Reply via email to