Linux USB
 help / color / mirror / Atom feed
From: Sven Neuhaus <sven-kernel@sven.de>
To: linux-usb@vger.kernel.org
Cc: westeri@kernel.org, andreas.noever@gmail.com,
	YehezkelShB@gmail.com, linux-kernel@vger.kernel.org,
	Sven Neuhaus <sven-kernel@sven.de>,
	stable@vger.kernel.org, Mario Limonciello <superm1@kernel.org>
Subject: [PATCH 2/2] thunderbolt: Flush the ring interrupt status clear
Date: Thu, 12 Nov 2026 22:51:43 +0100	[thread overview]
Message-ID: <1794520303-5758-3-git-send-email-sven-kernel@sven.de> (raw)
In-Reply-To: <1794520303-5758-1-git-send-email-sven-kernel@sven.de>

On hosts without QUIRK_AUTO_CLEAR_INT, ring_msix() clears the ring's
bit in REG_RING_INT_CLEAR before it schedules ring_work(). This is a
posted write and nothing is read from the NHI afterwards, so the clear
can take effect after the next frame on the ring has completed. It
then clears the status of that frame as well. The descriptor stays
completed and the interrupt stays enabled, but no MSI-X is raised, and
the frame waits until another interrupt on the ring runs ring_work().

Before commit 468c49f44759 ("thunderbolt: Disable interrupt auto clear
for rings") the status was cleared by reading REG_RING_NOTIFY_BASE,
and a read is not posted.

Read back REG_RING_INTERRUPT_BASE after the write, so the clear has
taken effect before ring_work() looks at the descriptors. A frame that
completed before that point is seen by ring_work(), and a later one
raises a new interrupt.

This was seen between two hosts with AMD Strix Halo USB4 host routers
(1022:158d, 1022:158e) connected by USB4 cables, running an
out-of-tree service driver that exchanges XDomain requests and
responses and moves data over its own rings. When one host sent a
response and a request back to back, the request sometimes stayed in
the peer's control RX ring until tb_xdomain_request() timed out and
sent it again. In a request/reply test with 300 us between exchanges,
3-7% of the exchanges took the whole request timeout (about 75 ms).
A debug build that checked the control RX ring every 500 us found
these frames with RING_DESC_COMPLETED set, the ring's bit set in
REG_RING_INTERRUPT_BASE and its bit clear in REG_RING_NOTIFY_BASE.
The data rings of the driver lost completions the same way, which
showed up as retransmissions after the driver's ack timeout.

With this patch, 6000 exchanges of 8-64 KiB had none above 1.7 ms
(99th percentile 0.35-0.58 ms, before about 75 ms), no request was
sent twice, and the retransmissions went away (84 in 1000 exchanges
before, none after). ib_write_bw at 4 and 8 MiB stayed within
run-to-run noise.

Tested on 7.3.3; ring_clear_msix() is unchanged in the thunderbolt.git
fixes branch, where the patch applies as is. Not tested: other AMD
host routers. Intel hosts set QUIRK_AUTO_CLEAR_INT and return before
the write, so they are not affected.

The analysis, the fix and the tests were done with an AI coding
assistant.

Fixes: 468c49f44759 ("thunderbolt: Disable interrupt auto clear for rings")
Cc: stable@vger.kernel.org
Cc: Mario Limonciello <superm1@kernel.org>
Signed-off-by: Sven Neuhaus <sven-kernel@sven.de>
---
 drivers/thunderbolt/nhi.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/drivers/thunderbolt/nhi.c b/drivers/thunderbolt/nhi.c
index e99a3fcc4a29..dd109f6ac70f 100644
--- a/drivers/thunderbolt/nhi.c
+++ b/drivers/thunderbolt/nhi.c
@@ -533,6 +533,14 @@ static void ring_clear_msix(const struct tb_ring *ring)
 	else
 		iowrite32(BIT(bit), ring->nhi->iobase + REG_RING_INT_CLEAR +
 			  4 * (ring->nhi->hop_count / 32));
+
+	/*
+	 * Flush the posted write before ring_work() looks at the
+	 * descriptors. Otherwise the clear can take effect after the next
+	 * frame has completed and clear its status too, and that frame
+	 * never raises an interrupt.
+	 */
+	ioread32(ring->nhi->iobase + REG_RING_INTERRUPT_BASE);
 }
 
 irqreturn_t ring_msix(int irq, void *data)
-- 
2.47.3


  parent reply	other threads:[~2026-11-12 21:51 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-12 21:51 [PATCH 0/2] thunderbolt: Fix lost ring interrupts and an XDomain use-after-free Sven Neuhaus
2026-11-12 21:51 ` [PATCH 1/2] thunderbolt: Do not match XDomain responses to received packets Sven Neuhaus
2026-11-12 21:58   ` sashiko-bot
2026-11-12 21:51 ` Sven Neuhaus [this message]
2026-11-12 22:02   ` [PATCH 2/2] thunderbolt: Flush the ring interrupt status clear sashiko-bot

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=1794520303-5758-3-git-send-email-sven-kernel@sven.de \
    --to=sven-kernel@sven.de \
    --cc=YehezkelShB@gmail.com \
    --cc=andreas.noever@gmail.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-usb@vger.kernel.org \
    --cc=stable@vger.kernel.org \
    --cc=superm1@kernel.org \
    --cc=westeri@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