[PATCH v3 2/2] wifi: rtw88: sdio: Split rtw_sdio_rx_isr into 8051 and 3081 variants
From: Alastair D'Silva
Date: Wed Sep 30 2026 - 20:46:35 EST
Following the split of rtw_sdio_handle_interrupt(), the receive FIFO drain
loop in rtw_sdio_rx_isr() still contained a growing number of special
cases between 8051 and 3081 chips, evaluated twice per packet in the RX
hot path:
1. Register width: 8051 uses a 16-bit read of REG_SDIO_RX0_REQ_LEN,
while 3081 uses a 32-bit read.
2. Loop termination: 8051 must re-read REG_SDIO_HISR on each iteration
because the RX buffer may contain data while HW or FW is still filling
it. Conversely, 3081 has improved HW/FW that can use rx_len
unconditionally, previously requiring a synthetic assignment of
hisr = REG_SDIO_HISR_RX_REQUEST to trick the loop condition into
continuing.
To avoid accumulating further special cases and eliminate per-packet
branching in the RX hot path, split rtw_sdio_rx_isr() into separate
rtw_sdio_rx_isr_8051() and rtw_sdio_rx_isr_3081() functions.
This removes the artificial hisr assignment on 3081 and keeps the RX
processing logic cleanly separated by architecture.
Assisted-by: LLM
Signed-off-by: Alastair D'Silva <alastair@xxxxxxxxxxx>
---
v3:
- New patch in v3.
- Split rtw_sdio_rx_isr into 8051 and 3081 variants following the dispatcher split.
- Eliminates per-packet wcpu branching in the RX hot path and removes artificial
hisr assignments on 3081.
- Added Assisted-by tag per Documentation/process/coding-assistants.rst.
drivers/net/wireless/realtek/rtw88/sdio.c | 54 ++++++++++++-----------
1 file changed, 29 insertions(+), 25 deletions(-)
diff --git a/drivers/net/wireless/realtek/rtw88/sdio.c b/drivers/net/wireless/realtek/rtw88/sdio.c
index 63d62242ac1e..fbf67427b450 100644
--- a/drivers/net/wireless/realtek/rtw88/sdio.c
+++ b/drivers/net/wireless/realtek/rtw88/sdio.c
@@ -1418,16 +1418,12 @@ static void rtw_sdio_rxfifo_recv(struct rtw_dev *rtwdev, u32 rx_len)
}
}
-static void rtw_sdio_rx_isr(struct rtw_dev *rtwdev)
+static void rtw_sdio_rx_isr_8051(struct rtw_dev *rtwdev)
{
u32 rx_len, hisr, total_rx_bytes = 0;
do {
- if (rtw_chip_wcpu_8051(rtwdev))
- rx_len = rtw_read16(rtwdev, REG_SDIO_RX0_REQ_LEN);
- else
- rx_len = rtw_read32(rtwdev, REG_SDIO_RX0_REQ_LEN);
-
+ rx_len = rtw_read16(rtwdev, REG_SDIO_RX0_REQ_LEN);
if (!rx_len)
break;
@@ -1435,33 +1431,41 @@ static void rtw_sdio_rx_isr(struct rtw_dev *rtwdev)
total_rx_bytes += rx_len;
- if (rtw_chip_wcpu_8051(rtwdev)) {
- /* Stop if no more RX requests are pending, even if
- * rx_len could be greater than zero in the next
- * iteration. This is needed because the RX buffer may
- * already contain data while either HW or FW are not
- * done filling that buffer yet. Still reading the
- * buffer can result in packets where
- * rtw_rx_pkt_stat.pkt_len is zero or points beyond the
- * end of the buffer.
- */
- 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;
- }
+ /* Stop if no more RX requests are pending, even if
+ * rx_len could be greater than zero in the next
+ * iteration. This is needed because the RX buffer may
+ * already contain data while either HW or FW are not
+ * done filling that buffer yet. Still reading the
+ * buffer can result in packets where
+ * rtw_rx_pkt_stat.pkt_len is zero or points beyond the
+ * end of the buffer.
+ */
+ hisr = rtw_read32(rtwdev, REG_SDIO_HISR);
} while (total_rx_bytes < SZ_64K && hisr & REG_SDIO_HISR_RX_REQUEST);
}
+static void rtw_sdio_rx_isr_3081(struct rtw_dev *rtwdev)
+{
+ u32 rx_len, total_rx_bytes = 0;
+
+ do {
+ rx_len = rtw_read32(rtwdev, REG_SDIO_RX0_REQ_LEN);
+ if (!rx_len)
+ break;
+
+ rtw_sdio_rxfifo_recv(rtwdev, rx_len);
+
+ total_rx_bytes += rx_len;
+ } while (total_rx_bytes < SZ_64K);
+}
+
static void rtw_sdio_handle_interrupt_8051(struct rtw_dev *rtwdev, u32 hisr)
{
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;
- rtw_sdio_rx_isr(rtwdev);
+ rtw_sdio_rx_isr_8051(rtwdev);
}
/*
@@ -1483,7 +1487,7 @@ static void rtw_sdio_handle_interrupt_3081(struct rtw_dev *rtwdev, u32 hisr)
if (hisr & REG_SDIO_HISR_TXERR)
rtw_sdio_tx_err_isr(rtwdev);
if (hisr & REG_SDIO_HISR_RX_REQUEST)
- rtw_sdio_rx_isr(rtwdev);
+ rtw_sdio_rx_isr_3081(rtwdev);
/* Unmasking HIMR re-asserts the IRQ line if new packets arrived */
rtw_sdio_enable_interrupt(rtwdev);
--
2.53.0