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 --- 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