[PATCH v11 4/7] wifi: rtw88: sdio: zero the padding added to a TX transfer

From: luka . gejak

Date: Wed Sep 09 2026 - 03:51:52 EST


From: Luka Gejak <luka.gejak@xxxxxxxxx>

rtw_sdio_write_port() rounds the transfer up with sdio_align_size() and
then hands that length to sdio_memcpy_toio() while the skb still only
holds skb->len bytes. The difference, between one and 511 bytes, is read
from beyond the end of the frame and transmitted. Whether it stays
inside the skb's allocation depends on how much tailroom the skb happens
to have, so this is at best sending uninitialised memory over the air.

Pad the skb up to the transfer size first. __skb_pad() zeroes the added
bytes, reallocates a cloned skb rather than writing into a buffer a
clone still shares, and leaves skb->len alone, so nothing else in the
transmit path has to change.

It must not free the skb on failure: rtw_sdio_write_data() frees the skb
itself and rtw_sdio_process_tx_queue() requeues it, so both callers
still own it and would double free.

Found while reworking this path for the RTL8723BS. Measured on RTL8723BS
hardware, padding the transfer costs nothing observable: uplink is
19.5 to 19.8 Mbit/s padded against 20.9 to 21.1 Mbit/s unpadded in an
interleaved A/B, with scans, reconnection and a UDP flood clean in both.
The other SDIO parts sharing this path are untested; I have only the
RTL8723BS.

Fixes: 65371a3f14e7 ("wifi: rtw88: sdio: Add HCI implementation for SDIO based chipsets")
Signed-off-by: Luka Gejak <luka.gejak@xxxxxxxxx>
---

Notes:
New in v11.

Ping-Ke asked for this to come before the RTL8723BS accounting patch
rather than after the series, so that it backports on its own and so
that it is clear it is an existing problem rather than something the
RTL8723BS work introduced.

The pad_size local is the shape he asked for on v9: declared at the
top, computed unconditionally, and tested with if (pad_size > 0).

drivers/net/wireless/realtek/rtw88/sdio.c | 12 ++++++++++++
1 file changed, 12 insertions(+)

diff --git a/drivers/net/wireless/realtek/rtw88/sdio.c b/drivers/net/wireless/realtek/rtw88/sdio.c
index 5b40d74b16ee..8466abad972a 100644
--- a/drivers/net/wireless/realtek/rtw88/sdio.c
+++ b/drivers/net/wireless/realtek/rtw88/sdio.c
@@ -636,6 +636,7 @@ static int rtw_sdio_write_port(struct rtw_dev *rtwdev, struct sk_buff *skb,
enum rtw_tx_queue_type queue)
{
struct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev->priv;
+ size_t pad_size;
bool bus_claim;
size_t txsize;
u32 txaddr;
@@ -646,6 +647,17 @@ static int rtw_sdio_write_port(struct rtw_dev *rtwdev, struct sk_buff *skb,
return -EINVAL;

txsize = sdio_align_size(rtwsdio->sdio_func, skb->len);
+ pad_size = txsize - skb->len;
+
+ if (pad_size > 0) {
+ /*
+ * __skb_pad() must not free the skb on failure: both callers
+ * still own it, one requeues it and the other frees it.
+ */
+ ret = __skb_pad(skb, pad_size, false);
+ if (ret)
+ return ret;
+ }

ret = rtw_sdio_check_free_txpg(rtwdev, queue, txsize);
if (ret)
--
2.55.0