1: 0a10ca884822 ! 1: 81e926c54e95 wifi: mt76: usb: re-enable the rx worker when resuming fails @@ Commit message mt7925_init_hardware drivers/net/wireless/mediatek/mt76/mt7925/init.c:152 [inline] mt7925_init_work+0x49b/0x7e0 drivers/net/wireless/mediatek/mt76/mt7925/init.c:196  + The early return is unbalanced with the URBs as well: mt76u_stop_rx() + poisons every URB of every RX queue, while mt76u_resume_rx() would only + unpoison the queues it reached. If MT_RXQ_MAIN fails to submit, the URBs + of MT_RXQ_MCU keep urb->reject raised, the next stop/resume pair moves it + further away from zero instead of back to zero, and every later + submission on that queue fails with -EPERM. + A stalled RX endpoint makes usb_submit_urb() return -EPIPE, which is the failure that leaves the MCU unresponsive and triggers the retry loop. - Skip the remaining queues but always re-enable the worker, and still - return the error to the caller. + Unpoison and resubmit every RX queue, keep the first error, and always + re-enable the worker so that both pairs stay balanced.  Fixes: 0d2afe09fad5 ("mt76: mt7921: add mt7921u driver") Cc: stable@vger.kernel.org @@ drivers/net/wireless/mediatek/mt76/usb.c: EXPORT_SYMBOL_GPL(mt76u_stop_rx); mt76_for_each_q_rx(dev, i) { struct mt76_queue *q = &dev->q_rx[i];  - int err, j; -+ int j; ++ int ret, j;  for (j = 0; j < q->ndesc; j++) usb_unpoison_urb(q->entry[j].urb);  - err = mt76u_submit_rx_buffers(dev, i); - if (err < 0) +- err = mt76u_submit_rx_buffers(dev, i); +- if (err < 0)  - return err; -+ break; ++ ret = mt76u_submit_rx_buffers(dev, i); ++ if (ret < 0 && !err) ++ err = ret; }  mt76_worker_enable(&dev->usb.rx_worker);