summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/mediatek/mt76/sdio_txrx.c
diff options
context:
space:
mode:
authorSean Wang <sean.wang@mediatek.com>2021-10-19 07:11:47 +0800
committerFelix Fietkau <nbd@nbd.name>2021-10-20 10:37:00 +0200
commitca74b9b907f93424ea16785871e68d705b276d5e (patch)
tree34c3adb1cbc0f28acd576322439bb89fe7faf641 /drivers/net/wireless/mediatek/mt76/sdio_txrx.c
parent48fab5bbef4092d925ab3214773ad12e68807223 (diff)
mt76: mt7921s: add reset support
Introduce wifi chip reset support for mt7921 device to recover mcu hangs or abnormal wifi system. Tested-by: Deren Wu <deren.wu@mediatek.com> Acked-by: Lorenzo Bianconi <lorenzo@kernel.org> Co-developed-by: Deren Wu <deren.wu@mediatek.com> Signed-off-by: Deren Wu <deren.wu@mediatek.com> Signed-off-by: Sean Wang <sean.wang@mediatek.com> Signed-off-by: Felix Fietkau <nbd@nbd.name>
Diffstat (limited to 'drivers/net/wireless/mediatek/mt76/sdio_txrx.c')
-rw-r--r--drivers/net/wireless/mediatek/mt76/sdio_txrx.c32
1 files changed, 31 insertions, 1 deletions
diff --git a/drivers/net/wireless/mediatek/mt76/sdio_txrx.c b/drivers/net/wireless/mediatek/mt76/sdio_txrx.c
index 9b4c95a47d47..649a56790b89 100644
--- a/drivers/net/wireless/mediatek/mt76/sdio_txrx.c
+++ b/drivers/net/wireless/mediatek/mt76/sdio_txrx.c
@@ -235,6 +235,9 @@ static int mt76s_tx_run_queue(struct mt76_dev *dev, struct mt76_queue *q)
smp_rmb();
+ if (test_bit(MT76_MCU_RESET, &dev->phy.state))
+ goto next;
+
if (!test_bit(MT76_STATE_MCU_RUNNING, &dev->phy.state)) {
__skb_put_zero(e->skb, 4);
err = __mt76s_xmit_queue(dev, e->skb->data,
@@ -313,6 +316,13 @@ void mt76s_txrx_worker(struct mt76_sdio *sdio)
ret = mt76s_rx_handler(dev);
if (ret > 0)
nframes += ret;
+
+ if (test_bit(MT76_MCU_RESET, &dev->phy.state)) {
+ if (!mt76s_txqs_empty(dev))
+ continue;
+ else
+ wake_up(&sdio->wait);
+ }
} while (nframes > 0);
/* enable interrupt */
@@ -326,9 +336,29 @@ void mt76s_sdio_irq(struct sdio_func *func)
struct mt76_dev *dev = sdio_get_drvdata(func);
struct mt76_sdio *sdio = &dev->sdio;
- if (!test_bit(MT76_STATE_INITIALIZED, &dev->phy.state))
+ if (!test_bit(MT76_STATE_INITIALIZED, &dev->phy.state) ||
+ test_bit(MT76_MCU_RESET, &dev->phy.state))
return;
mt76_worker_schedule(&sdio->txrx_worker);
}
EXPORT_SYMBOL_GPL(mt76s_sdio_irq);
+
+bool mt76s_txqs_empty(struct mt76_dev *dev)
+{
+ struct mt76_queue *q;
+ int i;
+
+ for (i = 0; i <= MT_TXQ_PSD + 1; i++) {
+ if (i <= MT_TXQ_PSD)
+ q = dev->phy.q_tx[i];
+ else
+ q = dev->q_mcu[MT_MCUQ_WM];
+
+ if (q->first != q->head)
+ return false;
+ }
+
+ return true;
+}
+EXPORT_SYMBOL_GPL(mt76s_txqs_empty);