1: 2669060f036c ! 1: 5512493c52c9 wifi: rtw88: sdio: Fix unhandled RX request interrupt storm @@ Commit message In rtw_sdio_handle_interrupt(), the HISR status register is cleared using Write-1-to-Clear (W1C) semantics. However, the driver masks out the REG_SDIO_HISR_RX_REQUEST bit in the local 'hisr' variable before writing - it back, causing a 0 to be written to that bit. + it back, causing a 0 to be written to that bit. This prevents the RX + request interrupt from being acknowledged and cleared in hardware, trapping + the CPU core in an infinite interrupt storm loop (starving the RCU preempt + kthread and locking up the system).  - This prevents the RX request interrupt from being acknowledged and - cleared by the hardware, trapping the CPU core in an infinite interrupt - storm loop upon receiving packets and triggering RCU stalls and system - lockups. + Masking out the bit in software was originally intended to allow + budget-limited polling without losing interrupts. However, because the + status register was never acknowledged, the hardware interrupt line + remained asserted continuously.  - Remove the masking of REG_SDIO_HISR_RX_REQUEST so that the interrupt - status is correctly written back as a 1 and acknowledged. + Resolve this by adopting the standard interrupt masking pattern: + 1. Mask interrupts via rtw_sdio_disable_interrupt(rtwdev) upon entry. + 2. Acknowledge pending status bits via rtw_write32(rtwdev, REG_SDIO_HISR, + hisr) without clearing REG_SDIO_HISR_RX_REQUEST from the writeback mask. + 3. Service the pending interrupt events (rtw_sdio_rx_isr). + 4. Re-enable interrupts via rtw_sdio_enable_interrupt(rtwdev). + + Any packet arriving over the air while interrupts are masked latches + REG_SDIO_HISR_RX_REQUEST in hardware. Unmasking HIMR restores the interrupt + mask and immediately re-asserts the SDIO interrupt line (DAT[1]), causing + ksdioirqd to run another pass and drain the new packets.  Fixes: 65371a3f14e7 ("wifi: rtw88: sdio: Add HCI implementation for SDIO based chipsets") Cc: stable@vger.kernel.org - Assisted-by: LLM Signed-off-by: Alastair D'Silva   ## drivers/net/wireless/realtek/rtw88/sdio.c ##  @@ drivers/net/wireless/realtek/rtw88/sdio.c: static void rtw_sdio_handle_interrupt(struct sdio_func *sdio_func) + rtwsdio->irq_thread = current; +  + hisr = rtw_read32(rtwdev, REG_SDIO_HISR); ++ if (!hisr) ++ goto out; ++ ++ rtw_sdio_disable_interrupt(rtwdev); ++ rtw_write32(rtwdev, REG_SDIO_HISR, hisr);  if (hisr & REG_SDIO_HISR_TXERR) rtw_sdio_tx_err_isr(rtwdev); @@ drivers/net/wireless/realtek/rtw88/sdio.c: static void rtw_sdio_handle_interrupt rtw_sdio_rx_isr(rtwdev);  - }  - rtw_write32(rtwdev, REG_SDIO_HISR, hisr); +- rtw_write32(rtwdev, REG_SDIO_HISR, hisr); ++ /* Unmasking HIMR re-asserts the IRQ line if new packets arrived */ ++ rtw_sdio_enable_interrupt(rtwdev); +  ++out: + rtwsdio->irq_thread = NULL; + }