Skip to content

Commit 87714bf

Browse files
Quanzhoucennbd168
authored andcommitted
wifi: mt76: mt7921e: improve reliability of dma reset
The hardware team has advised the driver that it is necessary to first put WFDMA into an idle state before resetting the WFDMA. Otherwise, the WFDMA may enter an unknown state where it cannot be polled with the right state successfully. To ensure that the DMA can work properly while a stressful cold reboot test was being made, we have reordered the programming sequence in the driver based on the hardware team's guidance. The patch would modify the WFDMA disabling flow from "DMA reset -> disabling DMASHDL -> disabling WFDMA -> polling and waiting until DMA idle" to "disabling WFDMA -> polling and waiting for DMA idle -> disabling DMASHDL -> DMA reset. Where he polling and waiting until WFDMA is idle is coordinated with the operation of disabling WFDMA. Even while WFDMA is being disabled, it can still handle Tx/Rx requests. The additional polling allows sufficient time for WFDMA to process the last T/Rx request. When the idle state of WFDMA is reached, it is a reliable indication that DMASHDL is also idle to ensure it is safe to disable it and perform the DMA reset. Fixes: 0a1059d ("mt76: mt7921: move mt7921_dma_reset in dma.c") Co-developed-by: Sean Wang <sean.wang@mediatek.com> Signed-off-by: Sean Wang <sean.wang@mediatek.com> Co-developed-by: Deren Wu <deren.wu@mediatek.com> Signed-off-by: Deren Wu <deren.wu@mediatek.com> Co-developed-by: Wang Zhao <wang.zhao@mediatek.com> Signed-off-by: Wang Zhao <wang.zhao@mediatek.com> Signed-off-by: Quan Zhou <quan.zhou@mediatek.com> Signed-off-by: Felix Fietkau <nbd@nbd.name>
1 parent 5c47cde commit 87714bf

1 file changed

Lines changed: 20 additions & 16 deletions

File tree

  • drivers/net/wireless/mediatek/mt76/mt7921

drivers/net/wireless/mediatek/mt76/mt7921/dma.c

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -66,22 +66,6 @@ static void mt7921_dma_prefetch(struct mt7921_dev *dev)
6666

6767
static int mt7921_dma_disable(struct mt7921_dev *dev, bool force)
6868
{
69-
if (force) {
70-
/* reset */
71-
mt76_clear(dev, MT_WFDMA0_RST,
72-
MT_WFDMA0_RST_DMASHDL_ALL_RST |
73-
MT_WFDMA0_RST_LOGIC_RST);
74-
75-
mt76_set(dev, MT_WFDMA0_RST,
76-
MT_WFDMA0_RST_DMASHDL_ALL_RST |
77-
MT_WFDMA0_RST_LOGIC_RST);
78-
}
79-
80-
/* disable dmashdl */
81-
mt76_clear(dev, MT_WFDMA0_GLO_CFG_EXT0,
82-
MT_WFDMA0_CSR_TX_DMASHDL_ENABLE);
83-
mt76_set(dev, MT_DMASHDL_SW_CONTROL, MT_DMASHDL_DMASHDL_BYPASS);
84-
8569
/* disable WFDMA0 */
8670
mt76_clear(dev, MT_WFDMA0_GLO_CFG,
8771
MT_WFDMA0_GLO_CFG_TX_DMA_EN | MT_WFDMA0_GLO_CFG_RX_DMA_EN |
@@ -95,6 +79,22 @@ static int mt7921_dma_disable(struct mt7921_dev *dev, bool force)
9579
MT_WFDMA0_GLO_CFG_RX_DMA_BUSY, 0, 100, 1))
9680
return -ETIMEDOUT;
9781

82+
/* disable dmashdl */
83+
mt76_clear(dev, MT_WFDMA0_GLO_CFG_EXT0,
84+
MT_WFDMA0_CSR_TX_DMASHDL_ENABLE);
85+
mt76_set(dev, MT_DMASHDL_SW_CONTROL, MT_DMASHDL_DMASHDL_BYPASS);
86+
87+
if (force) {
88+
/* reset */
89+
mt76_clear(dev, MT_WFDMA0_RST,
90+
MT_WFDMA0_RST_DMASHDL_ALL_RST |
91+
MT_WFDMA0_RST_LOGIC_RST);
92+
93+
mt76_set(dev, MT_WFDMA0_RST,
94+
MT_WFDMA0_RST_DMASHDL_ALL_RST |
95+
MT_WFDMA0_RST_LOGIC_RST);
96+
}
97+
9898
return 0;
9999
}
100100

@@ -301,6 +301,10 @@ void mt7921_dma_cleanup(struct mt7921_dev *dev)
301301
MT_WFDMA0_GLO_CFG_OMIT_RX_INFO |
302302
MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2);
303303

304+
mt76_poll_msec_tick(dev, MT_WFDMA0_GLO_CFG,
305+
MT_WFDMA0_GLO_CFG_TX_DMA_BUSY |
306+
MT_WFDMA0_GLO_CFG_RX_DMA_BUSY, 0, 100, 1);
307+
304308
/* reset */
305309
mt76_clear(dev, MT_WFDMA0_RST,
306310
MT_WFDMA0_RST_DMASHDL_ALL_RST |

0 commit comments

Comments
 (0)