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