Linux wireless drivers development
 help / color / mirror / Atom feed
From: Ping-Ke Shih <pkshih@realtek.com>
To: Abdurrahman Karadag <abdurrahmankaradag19@gmail.com>,
	"linux-wireless@vger.kernel.org" <linux-wireless@vger.kernel.org>
Cc: "kvalo@kernel.org" <kvalo@kernel.org>,
	"briannorris@chromium.org" <briannorris@chromium.org>,
	"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>
Subject: RE: [PATCH rtw-next] wifi: rtw88: pci: recover from a stalled TX ring
Date: Sun, 6 Sep 2026 04:16:46 +0000	[thread overview]
Message-ID: <6f2a314798c64ccfbfd59ac8a8ee6e01@realtek.com> (raw)
In-Reply-To: <20260902091738.41047-1-abdurrahmankaradag19@gmail.com>

Abdurrahman Karadag <abdurrahmankaradag19@gmail.com> wrote:

[...]

> diff --git a/drivers/net/wireless/realtek/rtw88/pci.c b/drivers/net/wireless/realtek/rtw88/pci.c
> index 66d2e5f51..f9875cb07 100644
> --- a/drivers/net/wireless/realtek/rtw88/pci.c
> +++ b/drivers/net/wireless/realtek/rtw88/pci.c
> @@ -787,6 +787,72 @@ static void rtw_pci_tx_kick_off_queue(struct rtw_dev *rtwdev,
>         spin_unlock_bh(&rtwpci->irq_lock);
>  }
> 
> +/* The hardware read pointer of a TX ring can stop advancing while the driver

First line of comment block should be empty. We don't use special style for
networking subsystem anymroe.

> + * keeps queueing descriptors. Once the ring is full, rtw_pci_tx_write() stops
> + * the mac80211 queue, and because the only wake up is inside the completion
> + * loop of rtw_pci_tx_isr(), which does not run while the read pointer is
> + * frozen, the queue would stay stopped forever. Detect a ring that is not
> + * draining and kick it off again.
> + */
> +#define RTW_PCI_TX_STALL_LIMIT 3
> +
> +static void rtw_pci_tx_stall_check(struct rtw_dev *rtwdev)
> +{
> +       struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv;
> +       struct rtw_pci_tx_ring *ring;
> +       enum rtw_tx_queue_type queue;
> +       u32 bd_idx, cur_rp, wp;
> +       bool pending, kick, warn, stopped;
> +
> +       for (queue = 0; queue < RTK_MAX_TX_QUEUE_NUM; queue++) {
> +               /* BCN is the reserved page and H2C is managed by the
> +                * firmware, neither is flow controlled through mac80211
> +                */
> +               if (queue == RTW_TX_QUEUE_BCN || queue == RTW_TX_QUEUE_H2C)
> +                       continue;
> +
> +               ring = &rtwpci->tx_rings[queue];
> +               kick = false;
> +               warn = false;
> +
> +               spin_lock_bh(&rtwpci->irq_lock);
> +
> +               /* nothing in flight, do not touch the device */
> +               if (skb_queue_empty(&ring->queue) && !ring->queue_stopped) {
> +                       ring->stall_cnt = 0;
> +                       ring->stall_warned = false;
> +                       spin_unlock_bh(&rtwpci->irq_lock);
> +                       continue;
> +               }
> +
> +               bd_idx = rtw_read32(rtwdev, rtw_pci_tx_queue_idx_addr[queue]);
> +               cur_rp = (bd_idx >> 16) & TRX_BD_IDX_MASK;
> +               wp = ring->r.wp;
> +               pending = ring->queue_stopped || cur_rp != wp;
> +
> +               if (pending && cur_rp == ring->last_rp) {
> +                       if (++ring->stall_cnt >= RTW_PCI_TX_STALL_LIMIT) {
> +                               ring->stall_cnt = 0;
> +                               kick = true;
> +                               warn = !ring->stall_warned;
> +                               ring->stall_warned = true;
> +                       }
> +               } else {
> +                       ring->stall_cnt = 0;
> +                       ring->stall_warned = false;
> +               }
> +               stopped = ring->queue_stopped;
> +               ring->last_rp = cur_rp;

Does software pointer cause driver doesn't restart queue?
Or without changes of this chunk, the stuck can be resolved?

> +               spin_unlock_bh(&rtwpci->irq_lock);
> +
> +               if (warn)
> +                       rtw_warn(rtwdev, "TX queue %d stalled (rp %u wp %u%s), kicking\n",
> +                                queue, cur_rp, wp, stopped ? ", stopped" : "");
> +               if (kick)
> +                       rtw_pci_tx_kick_off_queue(rtwdev, queue);

I mean just doing this kick is enough to resolve the stuck?

> +       }
> +}
> +
>  static void rtw_pci_tx_kick_off(struct rtw_dev *rtwdev)
>  {
>         struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv;




      reply	other threads:[~2026-09-06  4:17 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-02  9:17 [PATCH rtw-next] wifi: rtw88: pci: recover from a stalled TX ring Abdurrahman Karadag
2026-09-06  4:16 ` Ping-Ke Shih [this message]

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=6f2a314798c64ccfbfd59ac8a8ee6e01@realtek.com \
    --to=pkshih@realtek.com \
    --cc=abdurrahmankaradag19@gmail.com \
    --cc=briannorris@chromium.org \
    --cc=kvalo@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-wireless@vger.kernel.org \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox