From: Ping-Ke Shih <pkshih@realtek.com>
To: "luka.gejak@linux.dev" <luka.gejak@linux.dev>,
"linux-wireless@vger.kernel.org" <linux-wireless@vger.kernel.org>
Cc: "linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>,
"Michael Straube" <straube.linux@gmail.com>,
Bitterblue Smith <rtl8821cerfe2@gmail.com>,
Peter Robinson <pbrobinson@gmail.com>,
"Hans de Goede" <johannes.goede@oss.qualcomm.com>
Subject: RE: [PATCH v4 5/7] wifi: rtw88: sdio: track free TX pages and OQT credits for RTL8723BS
Date: Fri, 14 Aug 2026 06:32:15 +0000 [thread overview]
Message-ID: <4e17292f3b424b71a4194c0b8ebb705e@realtek.com> (raw)
In-Reply-To: <20260811091203.26841-6-luka.gejak@linux.dev>
luka.gejak@linux.dev <luka.gejak@linux.dev> wrote:
> From: Luka Gejak <luka.gejak@linux.dev>
>
> The RTL8723BS reports free TX page counts that the generic 8051 path
> reads back from the chip on every transfer, which is both slow over SDIO
> and unreliable on this part: the register frequently reads back zero
> while pages are in fact available. It also gates transmission on a free
> count in the SDIO output queue, REG_SDIO_OQT_FREE_PG, which rtw88 does
It seems like I asked you what OQT is... Output Queue Track?
Please mention it in commit message. I'd be easier to reviewers.
> not track at all. That count is how many more descriptors the SDIO
> engine can accept, and the chip discards writes that arrive with none
> left.
>
> Mirror the vendor driver and keep the per-queue and public page counts
> in software, seeded at start and resynchronised from the chip only when
> the cached counts say there is not enough room. Wait for a free output
> queue entry before writing, and account for the pages consumed after a
> successful transfer.
>
> Transfers also have to be padded up to the SDIO block size for this
> chip rather than using the generic alignment, so size the write
> separately from the frame and trim the skb back afterwards.
>
> Measured on RTL8723BS hardware against an iperf3 server one hop behind
> the AP, with the wlan0 byte counters as ground truth. On the generic
> path the association completes but no data passes at all: TCP and UDP
> both measure 0 bit/s in either direction. With this patch TCP is
> 25.3 Mbit/s up and 37.3 Mbit/s down, and UDP is 25.0 Mbit/s up at 0%
> loss.
>
> Signed-off-by: Luka Gejak <luka.gejak@linux.dev>
> ---
> drivers/net/wireless/realtek/rtw88/sdio.c | 245 ++++++++++++++++++++--
> drivers/net/wireless/realtek/rtw88/sdio.h | 10 +
> 2 files changed, 243 insertions(+), 12 deletions(-)
>
> diff --git a/drivers/net/wireless/realtek/rtw88/sdio.c b/drivers/net/wireless/realtek/rtw88/sdio.c
> index 5b40d74b16ee..493eda559607 100644
> --- a/drivers/net/wireless/realtek/rtw88/sdio.c
> +++ b/drivers/net/wireless/realtek/rtw88/sdio.c
> @@ -20,6 +20,7 @@
> #include "tx.h"
>
> #define RTW_SDIO_INDIRECT_RW_RETRIES 50
> +#define RTW_SDIO_OQT_TIMEOUT_MS 1000
nit: The unit can be '_MS' only if the delay in the loop is
'usleep_range(1000, 2000);' (1ms).
With _MS, it is easier to understand, but any opinion to improve it?
>
> static bool rtw_sdio_is_bus_addr(u32 addr)
> {
> @@ -548,12 +549,122 @@ static int rtw_sdio_read_port(struct rtw_dev *rtwdev, u8 *buf, size_t count)
> return ret;
> }
>
> +/*
> + * The cached free page counters are a fast path hint only. They are written
> + * from the single threaded TX work and, for H2C and reserved page writes,
> + * from process context, so they are atomic_t; whenever they claim there is
> + * not enough room they are resynchronised from the chip before the caller
> + * gives up, which also absorbs a lost update.
> + */
> +static void rtw_sdio_8723bs_store_free_txpg(struct rtw_dev *rtwdev,
> + u32 free_txpg)
> +{
nit: It looks like you can combine callers of rtw_sdio_8723bs_store_free_txpg()
into single function. Maybe, just rtw_sdio_8723bs_sync_free_txpg(), and add
a return value for rtw_sdio_8723bs_init_free_txpg().
How about you?
> + struct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev->priv;
> +
> + atomic_set(&rtwsdio->free_pg_high,
> + u32_get_bits(free_txpg, BIT_FREE_TXPG_HIGH));
> + atomic_set(&rtwsdio->free_pg_normal,
> + u32_get_bits(free_txpg, BIT_FREE_TXPG_NORMAL));
> + atomic_set(&rtwsdio->free_pg_low,
> + u32_get_bits(free_txpg, BIT_FREE_TXPG_LOW));
> + atomic_set(&rtwsdio->free_pg_pub,
> + u32_get_bits(free_txpg, BIT_FREE_TXPG_PUB));
> +}
> +
[...]
> @@ -749,8 +939,39 @@ static int rtw_sdio_setup(struct rtw_dev *rtwdev)
> return 0;
> }
>
> +static void rtw_sdio_8723bs_check_rqpn(struct rtw_dev *rtwdev)
> +{
> + const struct rtw_chip_info *chip = rtwdev->chip;
> + struct rtw_fifo_conf *fifo = &rtwdev->fifo;
> + const struct rtw_page_table *pg_tbl;
> + u16 reserved_num;
> + u32 free_txpg;
> + u16 pubq_num;
> +
> + free_txpg = rtw_read32(rtwdev, REG_SDIO_FREE_TXPG);
> + if (free_txpg || !fifo->acq_pg_num)
It will return directly if free_txpg is not zero... what does it mean?
> + return;
> +
> + pg_tbl = &chip->page_table[0];
> + reserved_num = pg_tbl->hq_num + pg_tbl->lq_num + pg_tbl->nq_num +
> + pg_tbl->exq_num + pg_tbl->gapq_num;
> + if (fifo->acq_pg_num <= reserved_num)
If it falls into this case, can it still work? If not, should it return
an error?
> + return;
> +
> + pubq_num = fifo->acq_pg_num - reserved_num;
> + rtw_write32(rtwdev, REG_RQPN_NPQ,
> + BIT_RQPN_NE(pg_tbl->nq_num, pg_tbl->exq_num));
> + rtw_write32(rtwdev, REG_RQPN,
> + BIT_RQPN_HLP(pg_tbl->hq_num, pg_tbl->lq_num, pubq_num));
> +}
> +
> static int rtw_sdio_start(struct rtw_dev *rtwdev)
> {
> + if (rtw_is_8723bs(rtwdev)) {
> + rtw_sdio_8723bs_check_rqpn(rtwdev);
> + rtw_sdio_8723bs_init_free_txpg(rtwdev);
> + }
> +
> rtw_sdio_enable_rx_aggregation(rtwdev);
> rtw_sdio_enable_interrupt(rtwdev);
>
[...]
next prev parent reply other threads:[~2026-08-14 6:32 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-11 9:11 [PATCH v4 0/7] wifi: rtw88: preparations for RTL8723B/RTL8723BS luka.gejak
2026-08-11 9:11 ` [PATCH v4 1/7] wifi: rtw88: add the RTL8723B chip type and SDIO helper luka.gejak
2026-08-14 7:15 ` Ping-Ke Shih
2026-08-11 9:11 ` [PATCH v4 2/7] wifi: rtw88: rx: mark zero length packets on RTL8723BS luka.gejak
2026-08-14 5:44 ` Ping-Ke Shih
2026-08-11 9:11 ` [PATCH v4 3/7] wifi: rtw88: tx: extend the TX report purge timeout to RTL8723BS luka.gejak
2026-08-14 7:15 ` Ping-Ke Shih
2026-08-11 9:12 ` [PATCH v4 4/7] wifi: rtw88: fw: handle the RTL8723BS management TX reports luka.gejak
2026-08-11 11:42 ` Bitterblue Smith
2026-08-14 5:52 ` Ping-Ke Shih
2026-08-11 9:12 ` [PATCH v4 5/7] wifi: rtw88: sdio: track free TX pages and OQT credits for RTL8723BS luka.gejak
2026-08-14 6:32 ` Ping-Ke Shih [this message]
2026-08-11 9:12 ` [PATCH v4 6/7] wifi: rtw88: sdio: set up RX aggregation and interrupts " luka.gejak
2026-08-14 6:41 ` Ping-Ke Shih
2026-08-11 9:12 ` [PATCH v4 7/7] wifi: rtw88: sdio: add TX back-pressure and retry on page starvation luka.gejak
2026-08-14 7:14 ` Ping-Ke Shih
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4e17292f3b424b71a4194c0b8ebb705e@realtek.com \
--to=pkshih@realtek.com \
--cc=johannes.goede@oss.qualcomm.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-wireless@vger.kernel.org \
--cc=luka.gejak@linux.dev \
--cc=pbrobinson@gmail.com \
--cc=rtl8821cerfe2@gmail.com \
--cc=straube.linux@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.