mt76: mt76x02: improve tx hang detection
authorFelix Fietkau <nbd@nbd.name>
Mon, 31 Jan 2022 14:04:43 +0000 (15:04 +0100)
committerFelix Fietkau <nbd@nbd.name>
Thu, 3 Feb 2022 13:34:35 +0000 (14:34 +0100)
Instead of checking if any queue has not made progress since the last run,
only trigger hang detection if one of the queues has not made any progress
in 10 subsequent runs. This should reduce false positive firmware restarts

Signed-off-by: Felix Fietkau <nbd@nbd.name>
drivers/net/wireless/mediatek/mt76/mt76x02.h
drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c

index 3232083e991658d0f44b2b9404d8e785ae5f2ca5..f76fd22ee03560da8c65c6693a5a7df97143207e 100644 (file)
@@ -103,7 +103,7 @@ struct mt76x02_dev {
        u8 tbtt_count;
 
        u32 tx_hang_reset;
-       u8 tx_hang_check;
+       u8 tx_hang_check[4];
        u8 beacon_hang_check;
        u8 mcu_timeout;
 
index ec0de691129af3a389dec0b1aaa7bfeeea22f572..8bcd8afa0d3a19253b19c4cff69ae9fb4c5e1821 100644 (file)
@@ -348,18 +348,20 @@ static bool mt76x02_tx_hang(struct mt76x02_dev *dev)
        for (i = 0; i < 4; i++) {
                q = dev->mphy.q_tx[i];
 
-               if (!q->queued)
-                       continue;
-
                prev_dma_idx = dev->mt76.tx_dma_idx[i];
                dma_idx = readl(&q->regs->dma_idx);
                dev->mt76.tx_dma_idx[i] = dma_idx;
 
-               if (prev_dma_idx == dma_idx)
-                       break;
+               if (!q->queued || prev_dma_idx != dma_idx) {
+                       dev->tx_hang_check[i] = 0;
+                       continue;
+               }
+
+               if (++dev->tx_hang_check[i] >= MT_TX_HANG_TH)
+                       return true;
        }
 
-       return i < 4;
+       return false;
 }
 
 static void mt76x02_key_sync(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
@@ -530,23 +532,13 @@ static void mt76x02_check_tx_hang(struct mt76x02_dev *dev)
        if (test_bit(MT76_RESTART, &dev->mphy.state))
                return;
 
-       if (mt76x02_tx_hang(dev)) {
-               if (++dev->tx_hang_check >= MT_TX_HANG_TH)
-                       goto restart;
-       } else {
-               dev->tx_hang_check = 0;
-       }
-
-       if (dev->mcu_timeout)
-               goto restart;
-
-       return;
+       if (!mt76x02_tx_hang(dev) && !dev->mcu_timeout)
+               return;
 
-restart:
        mt76x02_watchdog_reset(dev);
 
        dev->tx_hang_reset++;
-       dev->tx_hang_check = 0;
+       memset(dev->tx_hang_check, 0, sizeof(dev->tx_hang_check));
        memset(dev->mt76.tx_dma_idx, 0xff,
               sizeof(dev->mt76.tx_dma_idx));
 }