Skip to content

Commit fb4a7df

Browse files
committed
wifi: mt7996: harden FE/WED recovery against SCS and WDMA reset races
Crash analysis points to the FE/WED/mt7996 recovery path rather than a standalone Wi-Fi fault. The observed sequence is: - mtk_eth detects an ADMA Rx hang and enters FE reset - mtk_wed forwards the reset into mt7996 recovery - mt7996 SCS work is still active and keeps sending MCU commands - L1 SER starts while FE/WED reset is already in progress - the system later hits a write-to-read-only-memory oops during the recovery window The exact faulting instruction is not available from the crash log, but the repeated "failed to send SCS MCU command" messages immediately before L1 SER strongly indicate a reset-time race. Vendor Mediatek trees also carry WDMA link handling around Wi-Fi L1 SER, which is missing here. Fix this by: - canceling scs_work in mt7996_mac_full_reset() so SCS MCU traffic cannot continue into reset/recovery - disabling the PSE WDMA link before WED DMA reset and re-enabling it on WED start, matching the vendor SER flow more closely Together these changes make the FE/WED/mt7996 reset path more robust under hang recovery. Signed-off-by: Rudy Andram <rmandrad@gmail.com>
1 parent 2120744 commit fb4a7df

3 files changed

Lines changed: 16 additions & 0 deletions

File tree

‎drivers/net/ethernet/mediatek/mtk_eth_soc.h‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1853,6 +1853,18 @@ void mtk_w32(struct mtk_eth *eth, u32 val, unsigned reg);
18531853
u32 mtk_r32(struct mtk_eth *eth, unsigned reg);
18541854
u32 mtk_m32(struct mtk_eth *eth, u32 mask, u32 set, unsigned int reg);
18551855

1856+
static inline void mtk_pse_wdma_enable(struct mtk_eth *eth, int id, bool enable)
1857+
{
1858+
u32 val;
1859+
1860+
val = mtk_r32(eth, MTK_FE_GLO_CFG(PSE_WDMA_PORT(id)));
1861+
if (enable)
1862+
val &= ~MTK_FE_LINK_DOWN_P(PSE_WDMA_PORT(id));
1863+
else
1864+
val |= MTK_FE_LINK_DOWN_P(PSE_WDMA_PORT(id));
1865+
mtk_w32(eth, val, MTK_FE_GLO_CFG(PSE_WDMA_PORT(id)));
1866+
}
1867+
18561868
int mtk_gmac_sgmii_path_setup(struct mtk_eth *eth, int mac_id);
18571869
int mtk_gmac_2p5gphy_path_setup(struct mtk_eth *eth, int mac_id);
18581870
int mtk_gmac_gephy_path_setup(struct mtk_eth *eth, int mac_id);

‎drivers/net/ethernet/mediatek/mtk_wed.c‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1762,6 +1762,8 @@ mtk_wed_reset_dma(struct mtk_wed_device *dev)
17621762
u32 val;
17631763
int i;
17641764

1765+
mtk_pse_wdma_enable(dev->hw->eth, dev->wdma_idx, false);
1766+
17651767
for (i = 0; i < ARRAY_SIZE(dev->tx_ring); i++) {
17661768
if (!dev->tx_ring[i].desc)
17671769
continue;
@@ -2434,6 +2436,7 @@ mtk_wed_start(struct mtk_wed_device *dev, u32 irq_mask)
24342436
mtk_wed_amsdu_init(dev);
24352437

24362438
mtk_wed_dma_enable(dev);
2439+
mtk_pse_wdma_enable(dev->hw->eth, dev->wdma_idx, true);
24372440
dev->running = true;
24382441
}
24392442

‎drivers/net/wireless/mediatek/mt76/mt7996/mac.c‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2554,6 +2554,7 @@ mt7996_mac_full_reset(struct mt7996_dev *dev)
25542554
ieee80211_stop_queues(hw);
25552555

25562556
cancel_work_sync(&dev->wed_rro.work);
2557+
cancel_delayed_work_sync(&dev->scs_work);
25572558
mt7996_for_each_phy(dev, phy)
25582559
cancel_delayed_work_sync(&phy->mt76->mac_work);
25592560

0 commit comments

Comments
 (0)