From 6a4cabff1203791797683cf6be8f56bee983dc73 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 27 Jul 2026 15:04:26 +0000 Subject: [PATCH] wifi: mt76: mt7996: do not leave state behind after a failed WED attach mt7996_mmio_wed_init() set dev->mt76.hwrro_mode and rx_token_size while building the WED configuration, before knowing whether the WED attach can succeed. A failed attach left the enlarged rx_token_size behind and reset hwrro_mode to MT76_HWRRO_OFF, clobbering the values that another RX datapath owner may have configured earlier in probe: on Airoha platforms with the wed_enable module parameter set, this broke the NPU offload configuration set up by mt76_npu_init() (NPU offload requires HW-RRO and a larger rx token space, and the attach always fails there since no SoC has both an Airoha NPU and MTK WED). Move both assignments after a successful attach, next to the existing success-only dma_dev/irq assignments. This is safe for the regular WED attach case: the first consumer of either field runs after probe continues (mtk_wed_device_attach() only invokes the init_buf callback; rx buffers are allocated via init_rx_buf from mtk_wed_start(), long after mt7996_mmio_wed_init() has returned). Within the WED configuration the HW-RRO checks were constant: the mode was assigned unconditionally right before them, and the hif2 path is only reachable after a successful main attach has set it. Resolve them to their constant values and drop the dead branches. Fixes: 377aa17d2aed ("wifi: mt76: mt7996: Add NPU offload support to MT7996 driver") Link: https://patch.msgid.link/20260727150434.1778520-7-nbd@nbd.name Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt7996/mmio.c | 53 +++++++------------ 1 file changed, 20 insertions(+), 33 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mmio.c b/drivers/net/wireless/mediatek/mt76/mt7996/mmio.c index ba064324a7cc..ac81be5fe023 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mmio.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mmio.c @@ -493,9 +493,6 @@ int mt7996_mmio_wed_init(struct mt7996_dev *dev, void *pdev_ptr, if (hif2 && !mtk_wed_device_active(&dev->mt76.mmio.wed)) return 0; - dev->mt76.hwrro_mode = is_mt7996(&dev->mt76) ? MT76_HWRRO_V3 - : MT76_HWRRO_V3_1; - hif1_ofs = dev->hif2 ? MT_WFDMA0_PCIE1(0) - MT_WFDMA0(0) : 0; if (hif2) @@ -520,23 +517,16 @@ int mt7996_mmio_wed_init(struct mt7996_dev *dev, void *pdev_ptr, wed->wlan.wpdma_tx = wed->wlan.phy_base + hif1_ofs + MT_TXQ_RING_BASE(0) + MT7996_TXQ_BAND2 * MT_RING_SIZE; - if (mt7996_has_hwrro(dev)) { - if (is_mt7996(&dev->mt76)) { - wed->wlan.txfree_tbit = ffs(MT_INT_RX_TXFREE_EXT) - 1; - wed->wlan.wpdma_txfree = wed->wlan.phy_base + hif1_ofs + - MT_RXQ_RING_BASE(0) + - MT7996_RXQ_TXFREE2 * MT_RING_SIZE; - } else { - wed->wlan.txfree_tbit = ffs(MT_INT_RX_TXFREE_BAND1_EXT) - 1; - wed->wlan.wpdma_txfree = wed->wlan.phy_base + hif1_ofs + - MT_RXQ_RING_BASE(0) + - MT7996_RXQ_MCU_WA_EXT * MT_RING_SIZE; - } - } else { + if (is_mt7996(&dev->mt76)) { + wed->wlan.txfree_tbit = ffs(MT_INT_RX_TXFREE_EXT) - 1; wed->wlan.wpdma_txfree = wed->wlan.phy_base + hif1_ofs + MT_RXQ_RING_BASE(0) + - MT7996_RXQ_MCU_WA_TRI * MT_RING_SIZE; - wed->wlan.txfree_tbit = ffs(MT_INT_RX_DONE_WA_TRI) - 1; + MT7996_RXQ_TXFREE2 * MT_RING_SIZE; + } else { + wed->wlan.txfree_tbit = ffs(MT_INT_RX_TXFREE_BAND1_EXT) - 1; + wed->wlan.wpdma_txfree = wed->wlan.phy_base + hif1_ofs + + MT_RXQ_RING_BASE(0) + + MT7996_RXQ_MCU_WA_EXT * MT_RING_SIZE; } wed->wlan.wpdma_rx_glo = wed->wlan.phy_base + hif1_ofs + MT_WFDMA0_GLO_CFG; @@ -547,7 +537,7 @@ int mt7996_mmio_wed_init(struct mt7996_dev *dev, void *pdev_ptr, wed->wlan.id = MT7996_DEVICE_ID_2; wed->wlan.tx_tbit[0] = ffs(MT_INT_TX_DONE_BAND2) - 1; } else { - wed->wlan.hw_rro = mt7996_has_hwrro(dev); + wed->wlan.hw_rro = true; wed->wlan.wpdma_int = wed->wlan.phy_base + MT_INT_SOURCE_CSR; wed->wlan.wpdma_mask = wed->wlan.phy_base + MT_INT_MASK_CSR; wed->wlan.wpdma_tx = wed->wlan.phy_base + MT_TXQ_RING_BASE(0) + @@ -600,23 +590,15 @@ int mt7996_mmio_wed_init(struct mt7996_dev *dev, void *pdev_ptr, wed->wlan.tx_tbit[0] = ffs(MT_INT_TX_DONE_BAND0) - 1; wed->wlan.tx_tbit[1] = ffs(MT_INT_TX_DONE_BAND1) - 1; if (is_mt7996(&dev->mt76)) { - if (mt7996_has_hwrro(dev)) { - wed->wlan.wpdma_txfree = wed->wlan.phy_base + - MT_RXQ_RING_BASE(0) + - MT7996_RXQ_TXFREE0 * MT_RING_SIZE; - wed->wlan.txfree_tbit = ffs(MT_INT_RX_TXFREE_MAIN) - 1; - } else { - wed->wlan.wpdma_txfree = wed->wlan.phy_base + - MT_RXQ_RING_BASE(0) + - MT7996_RXQ_MCU_WA_MAIN * MT_RING_SIZE; - wed->wlan.txfree_tbit = ffs(MT_INT_RX_DONE_WA_MAIN) - 1; - } + wed->wlan.wpdma_txfree = wed->wlan.phy_base + + MT_RXQ_RING_BASE(0) + + MT7996_RXQ_TXFREE0 * MT_RING_SIZE; + wed->wlan.txfree_tbit = ffs(MT_INT_RX_TXFREE_MAIN) - 1; } else { wed->wlan.txfree_tbit = ffs(MT_INT_RX_DONE_WA_MAIN) - 1; wed->wlan.wpdma_txfree = wed->wlan.phy_base + MT_RXQ_RING_BASE(0) + MT7996_RXQ_MCU_WA_MAIN * MT_RING_SIZE; } - dev->mt76.rx_token_size = MT7996_TOKEN_SIZE + wed->wlan.rx_npkt; if (dev->hif2 && is_mt7992(&dev->mt76)) wed->wlan.id = 0x7992; @@ -639,9 +621,14 @@ int mt7996_mmio_wed_init(struct mt7996_dev *dev, void *pdev_ptr, wed->wlan.reset_complete = mt76_wed_reset_complete; } - if (mtk_wed_device_attach(wed)) { - dev->mt76.hwrro_mode = MT76_HWRRO_OFF; + if (mtk_wed_device_attach(wed)) return 0; + + if (!hif2) { + dev->mt76.hwrro_mode = is_mt7996(&dev->mt76) ? MT76_HWRRO_V3 + : MT76_HWRRO_V3_1; + dev->mt76.rx_token_size = MT7996_TOKEN_SIZE + + wed->wlan.rx_npkt; } *irq = wed->irq;