@@ -510,6 +510,20 @@ mt76_dma_tx_queue_skb_raw(struct mt76_dev *dev, struct mt76_queue *q,
if (test_bit(MT76_MCU_RESET, &dev->phy.state))
goto error;
+ /* Check for non responsive radios. Better to just stop sending it messages
+ * than continuously block the OS (since rtnl and similar are often held while
+ * the timeout is happening).
+ */
+ if (dev->mcu_timeouts > MAX_MCU_TIMEOUTS) {
+ static unsigned long last_log;
+
+ if (time_after(jiffies, last_log + 5 * HZ)) {
+ last_log = jiffies;
+ mtk_dbg(dev, WRN, "mt76-dma-tx-queue-skb-raw, too many timeouts, msg is dropped.\n");
+ }
+ goto error;
+ }
+
if (q->queued + 1 >= q->ndesc - 1)
goto error;
@@ -832,6 +832,9 @@ struct mt76_dev {
struct mt76_mcu mcu;
u32 first_failed_mcu_cmd; /* for debugging */
u32 last_successful_mcu_cmd; /* for debugging */
+ u32 mcu_timeouts; /* sequential timeout counter */
+ #define MAX_MCU_TIMEOUTS 3
+
struct net_device napi_dev;
struct net_device tx_napi_dev;
@@ -161,11 +161,13 @@ mt7915_mcu_parse_response(struct mt76_dev *mdev, int cmd,
int ret = 0;
if (!skb) {
+ mdev->mcu_timeouts++;
dev_err(mdev->dev, "Message %08x (seq %d) timeout\n",
cmd, seq);
return -ETIMEDOUT;
}
+ mdev->mcu_timeouts = 0;
rxd = (struct mt76_connac2_mcu_rxd *)skb->data;
if (seq != rxd->seq &&
!(rxd->eid == MCU_CMD_EXT_CID &&