1: 9d61753fe26a = 1: a9335d40623d wifi: rtw88: sdio: Handle allocation and read errors in rtw_sdio_rxfifo_recv 2: d4854e18c586 ! 2: c4e63f18f15a wifi: rtw88: sdio: Track running state and cancel TX worker on stop @@ Commit message Track the operational state in rtwsdio->running with an irq_lock mutex (similar to PCI), check it at the entry of rtw_sdio_handle_interrupt() and rtw_sdio_tx_handler(), serialize state transitions in rtw_sdio_start() - and rtw_sdio_stop() under sdio_claim_host() and irq_lock, and cancel the - TX worker synchronously in rtw_sdio_stop(). + and rtw_sdio_stop() under sdio_claim_host() and irq_lock, cancel the TX + worker synchronously in rtw_sdio_stop(), and re-arm it in rtw_sdio_start() + so any frames left parked across a stop are drained and stopped queues are + woken.  Fixes: 28eaf7971a20 ("wifi: rtw88: sdio: add TX back-pressure and retry on page starvation") Cc: stable@vger.kernel.org @@ drivers/net/wireless/realtek/rtw88/sdio.c: static int rtw_sdio_start(struct rtw_  + }  +  + sdio_release_host(rtwsdio->sdio_func); ++ ++ queue_delayed_work(rtwsdio->txwq, &rtwsdio->tx_handler_data->work, 0);  return 0; } 3: e068bfea6332 ! 3: d760e1391170 wifi: rtw88: sdio: Fix unhandled RX request interrupt storm @@ Metadata ## Commit message ## wifi: rtw88: sdio: Fix unhandled RX request interrupt storm  - On 3081-based SDIO chips (e.g. RTL8821CS), hardware does not automatically - clear REG_SDIO_HISR_RX_REQUEST when the RX buffer is empty. Masking this - bit out before writing back to HISR prevents it from being acknowledged, - causing an infinite interrupt storm loop that locks up the system. + On 3081-based SDIO chips (observed on RTL8821CS; RTL8822BS and RTL8822CS + are inferred to be affected as they share the 3081 architecture), clearing + REG_SDIO_HISR_RX_REQUEST requires both a software W1C acknowledge and an + empty RX FIFO. Masking this bit out before writing back to HISR prevents + the software acknowledge from happening, leaving the bit asserted even + after the FIFO is drained and causing an infinite interrupt storm loop + that locks up the system.  - 8051-based chips instead rely on hardware to clear this bit automatically - once the buffer is empty, and software must not clear it. + 8051-based chips instead clear this bit in hardware once the RX buffer is + empty without a W1C writeback, and software must not clear it.  Split rtw_sdio_handle_interrupt() into separate 8051 and 3081 handlers. For 3081, disable interrupts via HIMR, acknowledge all pending status @@ Commit message REG_SDIO_HISR_RX_REQUEST), service pending events, and re-enable interrupts under irq_lock if still running.  - On 3081 hardware, REG_SDIO_HISR_RX_REQUEST is level-sensitive to FIFO - occupancy: if unread packets remain in the FIFO when interrupts are - re-enabled (or if new packets arrived), the chip re-asserts - REG_SDIO_HISR_RX_REQUEST and re-triggers the IRQ line. For 8051 chips, - preserve the existing behavior. + If unread packets remain in the FIFO when interrupts are re-enabled (or + if new packets arrived), REG_SDIO_HISR_RX_REQUEST remains asserted and + re-triggers the IRQ line. For 8051 chips, preserve the existing behavior.  Fixes: 65371a3f14e7 ("wifi: rtw88: sdio: Add HCI implementation for SDIO based chipsets") Cc: stable@vger.kernel.org @@ drivers/net/wireless/realtek/rtw88/sdio.c: static void rtw_sdio_rx_isr(struct rt  + /*  + * Unmasking HIMR re-asserts the IRQ line if new packets arrived or if  + * unread data remains in the RX FIFO (e.g. if the 64KB budget was -+ * reached or an RX error occurred). On 3081 hardware, -+ * REG_SDIO_HISR_RX_REQUEST is level-sensitive to FIFO occupancy: -+ * although cleared by the W1C writeback above, the chip automatically -+ * re-asserts REG_SDIO_HISR_RX_REQUEST as long as the RX buffer is -+ * non-empty, re-triggering the interrupt when unmasked. ++ * reached or an RX error occurred). On 3081 hardware, clearing ++ * REG_SDIO_HISR_RX_REQUEST requires both the W1C writeback above and ++ * an empty RX FIFO, so the bit remains asserted as long as unread ++ * data is in the buffer and re-triggers the interrupt when unmasked.  + */  + scoped_guard(mutex, &rtwsdio->irq_lock) {  + if (rtwsdio->running) 4: 12b781872120 = 4: 42d50000a62f wifi: rtw88: sdio: Split rtw_sdio_rx_isr into 8051 and 3081 variants