wifi: mt76: mt7603: rework/fix rx pse hang check
authorFelix Fietkau <nbd@nbd.name>
Fri, 28 Jul 2023 07:51:01 +0000 (09:51 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 20 Nov 2023 10:58:57 +0000 (11:58 +0100)
[ Upstream commit baa19b2e4b7bbb509a7ca7939c8785477dcd40ee ]

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 <nbd@nbd.name>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/net/wireless/mediatek/mt76/mt7603/core.c
drivers/net/wireless/mediatek/mt76/mt7603/mac.c

index 60a996b..915b834 100644 (file)
@@ -42,11 +42,13 @@ irqreturn_t mt7603_irq_handler(int irq, void *dev_instance)
        }
 
        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]);
        }
index 99ae080..7a506a0 100644 (file)
@@ -1570,20 +1570,29 @@ static bool mt7603_rx_pse_busy(struct mt7603_dev *dev)
 {
        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