All of lore.kernel.org
 help / color / mirror / Atom feed
From: Basavaraj Natikar <bnatikar@amd.com>
To: Mika Westerberg <mika.westerberg@linux.intel.com>,
	Basavaraj Natikar <Basavaraj.Natikar@amd.com>
Cc: andreas.noever@gmail.com, westeri@kernel.org,
	YehezkelShB@gmail.com, linux-usb@vger.kernel.org,
	Mario.Limonciello@amd.com, Sanath S <Sanath.S@amd.com>
Subject: Re: [PATCH -next] thunderbolt: Add quirk to reset host interface on DMA path teardown for AMD USB4 routers
Date: Wed, 5 Aug 2026 16:40:43 +0530	[thread overview]
Message-ID: <7624adcb-77bb-4556-8e43-eeaa6735eb74@amd.com> (raw)
In-Reply-To: <20260805034908.GC235112@black.igk.intel.com>


On 8/5/2026 9:19 AM, Mika Westerberg wrote:
> Hi,
>
> On Tue, Aug 04, 2026 at 05:56:38PM +0530, Basavaraj Natikar wrote:
>> Some AMD USB4 host routers have a bug in the Host Interface where
>> DMA path setup and teardown cycles may cause the Tx ring to hang.
>>
>> Fix this by issuing a Host Interface Reset on every DMA path teardown
>> for affected routers. The Host Interface Reset brings the registers in
>> the memory BAR to their default state and clears the End-to-End Flow
>> Control state, preventing the hang condition.
>>
>> Co-developed-by: Sanath S <Sanath.S@amd.com>
>> Signed-off-by: Sanath S <Sanath.S@amd.com>
>> Signed-off-by: Basavaraj Natikar <Basavaraj.Natikar@amd.com>
>> ---
>>   drivers/thunderbolt/nhi.c      | 48 ++++++++++++++++++++++++++++++++++
>>   drivers/thunderbolt/nhi_regs.h |  4 +++
>>   drivers/thunderbolt/quirks.c   | 16 ++++++++++++
>>   drivers/thunderbolt/tb.c       |  7 +++++
>>   drivers/thunderbolt/tb.h       |  3 +++
>>   5 files changed, 78 insertions(+)
>>
>> diff --git a/drivers/thunderbolt/nhi.c b/drivers/thunderbolt/nhi.c
>> index 383a36212f70..0865cab582e7 100644
>> --- a/drivers/thunderbolt/nhi.c
>> +++ b/drivers/thunderbolt/nhi.c
>> @@ -1160,6 +1160,54 @@ static void nhi_reset(struct tb_nhi *nhi)
>>   	dev_warn(nhi->dev, "timeout resetting host router\n");
>>   }
>>   
>> +/**
>> + * nhi_host_interface_reset() - Issue a host interface reset
>> + * @nhi: Pointer to the NHI structure
>> + *
>> + * Resets the Host Interface by setting the RST bit in the Host Interface
>> + * Reset register. This brings the registers in the memory BAR to their
>> + * default state and clears the End-to-End Flow Control state.
>> + *
>> + * The caller must ensure that the control channel (Ring 0) is stopped
>> + * before calling this function, since the reset clears ring state.
>> + * The caller is responsible for restarting Ring 0 afterward.
>> + *
>> + * After setting the RST bit, waits for tHIReset (10 ms) for the reset
>> + * to complete.
>> + */
>> +static void nhi_host_interface_reset(struct tb_nhi *nhi)
>> +{
>> +	struct device *dev = nhi->dev;
>> +	u32 val;
>> +
>> +	val = ioread32(nhi->iobase + REG_CAPS);
>> +	/* Host Interface Reset only applies to Ver. 1 routers */
>> +	if (FIELD_GET(REG_CAPS_VERSION_MASK, val) >= REG_CAPS_VERSION_2)
>> +		return;
>> +
>> +	dev_dbg(dev, "issuing host interface reset\n");
>> +
>> +	iowrite32(REG_HOST_INTERFACE_RESET_RST,
>> +		  nhi->iobase + REG_HOST_INTERFACE_RESET);
>> +
>> +	/* Wait for tHIReset (10 ms) for the reset to complete */
>> +	usleep_range(10000, 20000);
>> +}
>> +
>> +/**
>> + * tb_nhi_host_interface_reset() - Reset host interface with control channel
>> + * @tb: Pointer to the thunderbolt domain
>> + *
>> + * Stops the control channel, issues a Host Interface Reset, and restarts
>> + * the control channel.
>> + */
>> +void tb_nhi_host_interface_reset(struct tb *tb)
>> +{
>> +	tb_ctl_stop(tb->ctl);
>> +	nhi_host_interface_reset(tb->nhi);
>> +	tb_ctl_start(tb->ctl);
>> +}
>> +
>>   static struct tb *nhi_select_cm(struct tb_nhi *nhi)
>>   {
>>   	struct tb *tb;
>> diff --git a/drivers/thunderbolt/nhi_regs.h b/drivers/thunderbolt/nhi_regs.h
>> index d6a197fabc74..99df60b6db36 100644
>> --- a/drivers/thunderbolt/nhi_regs.h
>> +++ b/drivers/thunderbolt/nhi_regs.h
>> @@ -115,6 +115,10 @@ struct ring_desc {
>>   #define REG_CAPS_VERSION_MASK		GENMASK(23, 16)
>>   #define REG_CAPS_VERSION_2		0x40
>>   
>> +/* Host Interface Reset - resets TX/RX rings and E2E flow control counters */
>> +#define REG_HOST_INTERFACE_RESET	0x39858
>> +#define REG_HOST_INTERFACE_RESET_RST	BIT(0)
>> +
>>   #define REG_DMA_MISC			0x39864
>>   #define REG_DMA_MISC_INT_AUTO_CLEAR     BIT(2)
>>   #define REG_DMA_MISC_DISABLE_AUTO_CLEAR	BIT(17)
>> diff --git a/drivers/thunderbolt/quirks.c b/drivers/thunderbolt/quirks.c
>> index 9f7914ac2f48..cc04d0873931 100644
>> --- a/drivers/thunderbolt/quirks.c
>> +++ b/drivers/thunderbolt/quirks.c
>> @@ -52,6 +52,12 @@ static void quirk_block_rpm_in_redrive(struct tb_switch *sw)
>>   	tb_sw_dbg(sw, "preventing runtime PM in DP redrive mode\n");
>>   }
>>   
>> +static void quirk_host_interface_reset(struct tb_switch *sw)
>> +{
>> +	sw->quirks |= QUIRK_HOST_INTERFACE_RESET;
>> +	tb_sw_dbg(sw, "enabling host interface reset on DMA path teardown\n");
>> +}
>> +
>>   struct tb_quirk {
>>   	u16 hw_vendor_id;
>>   	u16 hw_device_id;
>> @@ -114,6 +120,16 @@ static const struct tb_quirk tb_quirks[] = {
>>   	{ 0x0438, 0x0209, 0x0000, 0x0000, quirk_clx_disable },
>>   	{ 0x0438, 0x020a, 0x0000, 0x0000, quirk_clx_disable },
>>   	{ 0x0438, 0x020b, 0x0000, 0x0000, quirk_clx_disable },
>> +	/*
>> +	 * AMD USB4 host routers may hang the Tx ring after repeated
>> +	 * DMA path teardowns. Issue a Host Interface Reset on each
>> +	 * teardown to prevent the hang.
>> +	 */
>> +	{ 0x0438, 0x020d, 0x0000, 0x0000, quirk_host_interface_reset },
>> +	{ 0x0438, 0x020e, 0x0000, 0x0000, quirk_host_interface_reset },
>> +	{ 0x0438, 0x020f, 0x0000, 0x0000, quirk_host_interface_reset },
>> +	{ 0x0438, 0x0210, 0x0000, 0x0000, quirk_host_interface_reset },
>> +	{ 0x0438, 0x0211, 0x0000, 0x0000, quirk_host_interface_reset },
> These quirks are for things inside USB4 fabric. Since this is the HI, we
> have quirks for those in pci.c/nhi.c like QUIRK_AUTO_CLEAR_INT. Can you
> make this one follow that convention instead?
>
>>   };
>>   
>>   /**
>> diff --git a/drivers/thunderbolt/tb.c b/drivers/thunderbolt/tb.c
>> index 47753a5c0f2e..d40cc9e57364 100644
>> --- a/drivers/thunderbolt/tb.c
>> +++ b/drivers/thunderbolt/tb.c
>> @@ -2395,6 +2395,13 @@ static void __tb_disconnect_xdomain_paths(struct tb *tb, struct tb_xdomain *xd,
>>   	 * the same host router USB4 downstream port.
>>   	 */
>>   	tb_enable_clx(sw);
>> +
>> +	/*
>> +	 * Some host routers may hang the Tx ring after DMA path teardowns.
>> +	 * Issue a Host Interface Reset to prevent it.
>> +	 */
>> +	if (tb->root_switch->quirks & QUIRK_HOST_INTERFACE_RESET)
>> +		tb_nhi_host_interface_reset(tb);
>>   }
>>   
>>   static int tb_disconnect_xdomain_paths(struct tb *tb, struct tb_xdomain *xd,
>> diff --git a/drivers/thunderbolt/tb.h b/drivers/thunderbolt/tb.h
>> index 4373336d9425..d21feb631f3e 100644
>> --- a/drivers/thunderbolt/tb.h
>> +++ b/drivers/thunderbolt/tb.h
>> @@ -26,6 +26,8 @@
>>   #define QUIRK_NO_CLX					BIT(1)
>>   /* Need to keep power on while USB4 port is in redrive mode */
>>   #define QUIRK_KEEP_POWER_IN_DP_REDRIVE			BIT(2)
>> +/* Reset Host Interface on DMA path teardown to prevent Tx ring hang */
>> +#define QUIRK_HOST_INTERFACE_RESET			BIT(3)
>>   
>>   /**
>>    * struct tb_nvm - Structure holding NVM information
>> @@ -1507,6 +1509,7 @@ static inline bool usb4_port_device_is_offline(const struct usb4_port *usb4)
>>   }
>>   
>>   void tb_check_quirks(struct tb_switch *sw);
>> +void tb_nhi_host_interface_reset(struct tb *tb);
> Also we don't need to expose this then (and if it needs to be exposed it
> belongs to nhi.h not here.).

Sure Mika, I'll address both in v2:
- move the quirk to the NHI - set nhi->quirks in nhi_pci_check_quirks()
   by PCI ID, following the QUIRK_AUTO_CLEAR_INT convention.
- move the helper declaration to nhi.h (out of tb.h).
Will send v2 shortly.

Thanks,
--
Basavaraj

>
>>   
>>   #ifdef CONFIG_ACPI
>>   bool tb_acpi_add_links(struct tb_nhi *nhi);
>> -- 
>> 2.34.1


      reply	other threads:[~2026-08-05 11:10 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-04 12:26 [PATCH -next] thunderbolt: Add quirk to reset host interface on DMA path teardown for AMD USB4 routers Basavaraj Natikar
2026-08-05  3:49 ` Mika Westerberg
2026-08-05 11:10   ` Basavaraj Natikar [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=7624adcb-77bb-4556-8e43-eeaa6735eb74@amd.com \
    --to=bnatikar@amd.com \
    --cc=Basavaraj.Natikar@amd.com \
    --cc=Mario.Limonciello@amd.com \
    --cc=Sanath.S@amd.com \
    --cc=YehezkelShB@gmail.com \
    --cc=andreas.noever@gmail.com \
    --cc=linux-usb@vger.kernel.org \
    --cc=mika.westerberg@linux.intel.com \
    --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 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.