All of lore.kernel.org
 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: 3+ 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]
2026-09-23 15:04   ` abkarada

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