91 lines
3.9 KiB
Diff
91 lines
3.9 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
|
|
To: linux-wireless@vger.kernel.org
|
|
Date: Wed, 2 Aug 2023 00:27:32 +0000
|
|
Subject: [PATCH] wifi: rtw88: sdio: Honor the host max_req_size in the RX path
|
|
|
|
Lukas reports skb_over_panic errors on his Banana Pi BPI-CM4 which comes
|
|
with an Amlogic A311D (G12B) SoC and a RTL8822CS SDIO wifi/Bluetooth
|
|
combo card. The error he observed is identical to what has been fixed
|
|
in commit e967229ead0e ("wifi: rtw88: sdio: Check the HISR RX_REQUEST
|
|
bit in rtw_sdio_rx_isr()") but that commit didn't fix Lukas' problem.
|
|
|
|
Lukas found that disabling or limiting RX aggregation fix the problem
|
|
for him. In the following discussion a few key topics have been
|
|
discussed which have an impact on this problem:
|
|
- The Amlogic A311D (G12B) SoC has a hardware bug in the SDIO controller
|
|
which prevents DMA transfers. Instead all transfers need to go through
|
|
the controller SRAM which limits transfers to 1536 bytes
|
|
- rtw88 chips don't split incoming (RX) packets, so if a big packet is
|
|
received this is forwarded to the host in it's original form
|
|
- rtw88 chips can do RX aggregation, meaning more multiple incoming
|
|
packets can be pulled by the host from the card with one MMC/SDIO
|
|
transfer. This Depends on settings in the REG_RXDMA_AGG_PG_TH
|
|
register (BIT_RXDMA_AGG_PG_TH limits the number of packets that will
|
|
be aggregated, BIT_DMA_AGG_TO_V1 configures a timeout for aggregation
|
|
and BIT_EN_PRE_CALC makes the chip honor the limits more effectively)
|
|
|
|
Use multiple consecutive reads in rtw_sdio_read_port() to limit the
|
|
number of bytes which are copied by the host from the card in one
|
|
MMC/SDIO transfer. This allows receiving a buffer that's larger than
|
|
the hosts max_req_size (number of bytes which can be transferred in
|
|
one MMC/SDIO transfer). As a result of this the skb_over_panic error
|
|
is gone as the rtw88 driver is now able to receive more than 1536 bytes
|
|
from the card (either because the incoming packet is larger than that
|
|
or because multiple packets have been aggregated).
|
|
|
|
Fixes: 65371a3f14e7 ("wifi: rtw88: sdio: Add HCI implementation for SDIO based chipsets")
|
|
Reported-by: Lukas F. Hartmann <lukas@mntre.com>
|
|
Closes: https://lore.kernel.org/linux-wireless/CAFBinCBaXtebixKbjkWKW_WXc5k=NdGNaGUjVE8NCPNxOhsb2g@mail.gmail.com/
|
|
Suggested-by: Ping-Ke Shih <pkshih@realtek.com>
|
|
Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
|
|
---
|
|
drivers/net/wireless/realtek/rtw88/sdio.c | 24 +++++++++++++++++------
|
|
1 file changed, 18 insertions(+), 6 deletions(-)
|
|
|
|
diff --git a/drivers/net/wireless/realtek/rtw88/sdio.c b/drivers/net/wireless/realtek/rtw88/sdio.c
|
|
index 2c1fb2dabd40..b19262ec5d8c 100644
|
|
--- a/drivers/net/wireless/realtek/rtw88/sdio.c
|
|
+++ b/drivers/net/wireless/realtek/rtw88/sdio.c
|
|
@@ -500,19 +500,31 @@ static u32 rtw_sdio_get_tx_addr(struct rtw_dev *rtwdev, size_t size,
|
|
static int rtw_sdio_read_port(struct rtw_dev *rtwdev, u8 *buf, size_t count)
|
|
{
|
|
struct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev->priv;
|
|
+ struct mmc_host *host = rtwsdio->sdio_func->card->host;
|
|
bool bus_claim = rtw_sdio_bus_claim_needed(rtwsdio);
|
|
u32 rxaddr = rtwsdio->rx_addr++;
|
|
+ size_t bytes;
|
|
int ret;
|
|
|
|
if (bus_claim)
|
|
sdio_claim_host(rtwsdio->sdio_func);
|
|
|
|
- ret = sdio_memcpy_fromio(rtwsdio->sdio_func, buf,
|
|
- RTW_SDIO_ADDR_RX_RX0FF_GEN(rxaddr), count);
|
|
- if (ret)
|
|
- rtw_warn(rtwdev,
|
|
- "Failed to read %zu byte(s) from SDIO port 0x%08x",
|
|
- count, rxaddr);
|
|
+ while (count > 0) {
|
|
+ bytes = min_t(size_t, host->max_req_size, count);
|
|
+
|
|
+ ret = sdio_memcpy_fromio(rtwsdio->sdio_func, buf,
|
|
+ RTW_SDIO_ADDR_RX_RX0FF_GEN(rxaddr),
|
|
+ bytes);
|
|
+ if (ret) {
|
|
+ rtw_warn(rtwdev,
|
|
+ "Failed to read %zu byte(s) from SDIO port 0x%08x",
|
|
+ bytes, rxaddr);
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ count -= bytes;
|
|
+ buf += bytes;
|
|
+ }
|
|
|
|
if (bus_claim)
|
|
sdio_release_host(rtwsdio->sdio_func);
|
|
--
|
|
2.41.0
|
|
|