mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH] wifi: rtw88: sdio: Fix unhandled RX request interrupt storm
@ 2026-09-16  4:06 Alastair D'Silva
  2026-09-17  7:59 ` Ping-Ke Shih
  0 siblings, 1 reply; 4+ messages in thread
From: Alastair D'Silva @ 2026-09-16  4:06 UTC (permalink / raw)
  To: Ping-Ke Shih, Kalle Valo
  Cc: linux-wireless, linux-kernel, stable, Martin Blumenstingl,
	Alastair D'Silva

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.

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.

Remove the masking of REG_SDIO_HISR_RX_REQUEST so that the interrupt
status is correctly written back as a 1 and acknowledged.

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 <alastair@d-silva.org>
---

Notes:
    Tested on Mellow Fly-C5 (Allwinner H618) with onboard Realtek RTL8821CS
    SDIO Wi-Fi under Armbian, resolving immediate RCU stalls upon packet arrival
    and achieving stable Wi-Fi throughput.

 drivers/net/wireless/realtek/rtw88/sdio.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/net/wireless/realtek/rtw88/sdio.c b/drivers/net/wireless/realtek/rtw88/sdio.c
index 5b40d74b16ee..73686b462957 100644
--- a/drivers/net/wireless/realtek/rtw88/sdio.c
+++ b/drivers/net/wireless/realtek/rtw88/sdio.c
@@ -1090,10 +1090,8 @@ static void rtw_sdio_handle_interrupt(struct sdio_func *sdio_func)
 
 	if (hisr & REG_SDIO_HISR_TXERR)
 		rtw_sdio_tx_err_isr(rtwdev);
-	if (hisr & REG_SDIO_HISR_RX_REQUEST) {
-		hisr &= ~REG_SDIO_HISR_RX_REQUEST;
+	if (hisr & REG_SDIO_HISR_RX_REQUEST)
 		rtw_sdio_rx_isr(rtwdev);
-	}
 
 	rtw_write32(rtwdev, REG_SDIO_HISR, hisr);
 
-- 
2.53.0


^ permalink raw reply	[flat|nested] 4+ messages in thread

* RE: [PATCH] wifi: rtw88: sdio: Fix unhandled RX request interrupt storm
  2026-09-16  4:06 [PATCH] wifi: rtw88: sdio: Fix unhandled RX request interrupt storm Alastair D'Silva
@ 2026-09-17  7:59 ` Ping-Ke Shih
  2026-09-17  9:09   ` Ping-Ke Shih
  0 siblings, 1 reply; 4+ messages in thread
From: Ping-Ke Shih @ 2026-09-17  7:59 UTC (permalink / raw)
  To: Alastair D'Silva, Kalle Valo, Martin Blumenstingl
  Cc: linux-wireless, linux-kernel, stable

Hi Martin,

Alastair D'Silva <alastair@d-silva.org> wrote:
> 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.

I feel this patch makes sense.

Did you remember why you clear the bit locally? Can you share vendor
driver you referenced?

Ping-Ke


^ permalink raw reply	[flat|nested] 4+ messages in thread

* RE: [PATCH] wifi: rtw88: sdio: Fix unhandled RX request interrupt storm
  2026-09-17  7:59 ` Ping-Ke Shih
@ 2026-09-17  9:09   ` Ping-Ke Shih
  2026-09-17 10:04     ` Alastair D'Silva
  0 siblings, 1 reply; 4+ messages in thread
From: Ping-Ke Shih @ 2026-09-17  9:09 UTC (permalink / raw)
  To: Alastair D'Silva, Kalle Valo, Martin Blumenstingl
  Cc: linux-wireless, linux-kernel, stable

Ping-Ke Shih wrote:
> 
> Hi Martin,
> 
> Alastair D'Silva <alastair@d-silva.org> wrote:
> > 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.
> 
> I feel this patch makes sense.
> 
> Did you remember why you clear the bit locally? Can you share vendor
> driver you referenced?
> 

I asked internal expert who said this bit will be cleared automatically
if all packets in RX buffer are received. If we clear this bit here,
the interrupt will not raise again if no newly incoming packet even
there are remaining packets in RX buffer. 

Checking rtw_sdio_rx_isr(), we can see it reads hisr for each iteration,
which this is also the evidence that the bit will be cleared automatically.

Therefore, we need to dig further why the RX buffer can't be empty
and get stuck. 

Ping-Ke



^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] wifi: rtw88: sdio: Fix unhandled RX request interrupt storm
  2026-09-17  9:09   ` Ping-Ke Shih
@ 2026-09-17 10:04     ` Alastair D'Silva
  0 siblings, 0 replies; 4+ messages in thread
From: Alastair D'Silva @ 2026-09-17 10:04 UTC (permalink / raw)
  To: Ping-Ke Shih, Kalle Valo, Martin Blumenstingl
  Cc: linux-wireless, linux-kernel, stable

On Thu, 2026-09-17 at 09:09 +0000, Ping-Ke Shih wrote:
> Ping-Ke Shih wrote:
> > 
> > Hi Martin,
> > 
> > Alastair D'Silva <alastair@d-silva.org> wrote:
> > > 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.
> > 
> > I feel this patch makes sense.
> > 
> > Did you remember why you clear the bit locally? Can you share
> > vendor
> > driver you referenced?
> > 
> 
> I asked internal expert who said this bit will be cleared
> automatically
> if all packets in RX buffer are received. If we clear this bit here,
> the interrupt will not raise again if no newly incoming packet even
> there are remaining packets in RX buffer. 
> 
> Checking rtw_sdio_rx_isr(), we can see it reads hisr for each
> iteration,
> which this is also the evidence that the bit will be cleared
> automatically.
> 
> Therefore, we need to dig further why the RX buffer can't be empty
> and get stuck. 
> 
> Ping-Ke
> 

Hi Ping-Ke and Martin,

Thank you for following up and consulting with the internal hardware
team. We have extensive test telemetry and logs from our bring-up of
the Mellow Fly-C5 board in Armbian that provide full context on this
issue.

1. Test Platform & Failure Telemetry:
-------------------------------------
- Hardware: Mellow Fly-C5 (Allwinner H618 SoC, sun50i-h618).

- Wi-Fi Chip: Onboard Realtek RTL8821CS connected over SDIO (mmc1 /
sunxi-mmc).

- Kernels: Tested on mainline Linux 6.18 and 7.x branches using
rtw88_8821cs.

- Reproduction: On stock mainline kernels, immediately upon interface
bring-up and association (wlan0: associated), the CPU core servicing
the SDIO IRQ became 100% pegged in an interrupt storm, triggering RCU
stalls:
    rcu: INFO: rcu_preempt detected stalls on CPUs/tasks:
            0-...0: (1 GPs behind) idle=... softirq=...
    rcu: rcu_preempt kthread starved for 5126 jiffies!

- Verification: With this patch applied (leaving 
REG_SDIO_HISR_RX_REQUEST set so W1C acknowledges it), the board
completed 100/100 consecutive reboots under active network traffic
(continuous ping, SSH, Moonraker HTTP) with zero RCU stalls and zero
packet loss.


2. Why the bit was cleared locally (Vendor driver reference):
-------------------------------------------------------------

In Realtek's vendor drivers (such as rtl8822bs and rtl8723ds):
- In hal/rtl8822b/sdio/rtl8822bs_io.c:
    if (phal->sdio_hisr & BIT_RX_REQUEST_8822B) {
        /* No need to write 1 clear for RX_REQUEST */
        phal->sdio_hisr ^= BIT_RX_REQUEST_8822B;
- In include/hal_com_reg.h:
    MASK_SDIO_HISR_CLEAR explicitly excludes SDIO_HISR_RX_REQUEST.

Martin appears to have ported this comment and software-clearing
convention directly into rtw88_sdio_handle_interrupt().


3. Difference between 8051 and 3081 chips in rtw_sdio_rx_isr():
---------------------------------------------------------------

Regarding the observation that rtw_sdio_rx_isr() re-reads HISR in each
iteration:

Notice that in rtw_sdio_rx_isr() (sdio.c:1057-1073):
    if (rtw_chip_wcpu_8051(rtwdev)) {
        hisr = rtw_read32(rtwdev, REG_SDIO_HISR);
    } else {
        /* RTW_WCPU_3081 chips have improved hardware or
         * firmware and can use rx_len unconditionally.
         */
        hisr = REG_SDIO_HISR_RX_REQUEST;
    }

RTL8821CS (and RTL8822C/B) has wlan_cpu == RTW_WCPU_3081. For 3081
chips, rtw_sdio_rx_isr() never actually reads REG_SDIO_HISR! It sets
hisr to REG_SDIO_HISR_RX_REQUEST unconditionally and loops purely based
on REG_SDIO_RX0_REQ_LEN.


4. The RX buffer IS empty when the storm occurs:
------------------------------------------------

The buffer is not getting stuck with unread data. In our testing:

- rtw_sdio_rx_isr() drains all available packets until
REG_SDIO_RX0_REQ_LEN reads as 0, and then breaks out of the loop.

- rtw_sdio_handle_interrupt() then writes back to REG_SDIO_HISR with
  REG_SDIO_HISR_RX_REQUEST masked out (writing 0).

- Because the bit was not cleared in hardware via W1C (and was not
automatically de-asserted by hardware when rx_len reached 0), the SDIO
host controller sees the IRQ line still asserted and immediately re-
invokes the handler.

- On re-entry, REG_SDIO_HISR_RX_REQUEST is still 1, but
REG_SDIO_RX0_REQ_LEN is 0. rtw_sdio_rx_isr() immediately breaks out,
hisr writes 0 again, and the CPU is trapped in a 100% spin loop.


5. Effect on future interrupts:
-------------------------------

Regarding the internal expert's concern that clearing the bit prevents
future interrupts: in our testing, writing 1 to clear
REG_SDIO_HISR_RX_REQUEST after the FIFO is drained did NOT prevent
subsequent RX interrupts. When new packets arrived over the air, the
hardware asserted REG_SDIO_HISR_RX_REQUEST again normally.

If there is concern about edge cases (such as hitting the 64KB
total_rx_bytes limit before the FIFO is completely empty), would it be
acceptable to only clear REG_SDIO_HISR_RX_REQUEST if
REG_SDIO_RX0_REQ_LEN reads 0, or re-read REG_SDIO_HISR at the end of
rtw_sdio_rx_isr()?

Cheers,

-- 
Alastair D'Silva

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2026-09-17 10:04 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-16  4:06 [PATCH] wifi: rtw88: sdio: Fix unhandled RX request interrupt storm Alastair D'Silva
2026-09-17  7:59 ` Ping-Ke Shih
2026-09-17  9:09   ` Ping-Ke Shih
2026-09-17 10:04     ` Alastair D'Silva

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®