All of lore.kernel.org
 help / color / mirror / Atom feed
From: Mika Westerberg <mika.westerberg@linux.intel.com>
To: 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 v2] thunderbolt: Add quirk to reset host interface on DMA path teardown for AMD USB4 routers
Date: Wed, 5 Aug 2026 14:28:32 +0200	[thread overview]
Message-ID: <20260805122832.GH235112@black.igk.intel.com> (raw)
In-Reply-To: <20260805111811.517996-1-Basavaraj.Natikar@amd.com>

Hi,

On Wed, Aug 05, 2026 at 04:48:11PM +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>
> ---
> v2:
> - Move the quirk to the NHI (nhi->quirks), set in nhi_pci_check_quirks()
>   by PCI ID following the QUIRK_AUTO_CLEAR_INT convention, instead of the
>   tb_quirks[] fabric table.
> - Declare nhi_host_interface_reset() in nhi.h instead of tb.h.
> 
> v1: https://lore.kernel.org/all/20260804122638.1623429-1-Basavaraj.Natikar@amd.com/
>  drivers/thunderbolt/nhi.c      | 37 ++++++++++++++++++++++++++++++++++
>  drivers/thunderbolt/nhi.h      |  2 ++
>  drivers/thunderbolt/nhi_regs.h |  4 ++++
>  drivers/thunderbolt/pci.c      | 21 +++++++++++++++++++
>  drivers/thunderbolt/tb.c       |  6 ++++++
>  5 files changed, 70 insertions(+)
> 
> diff --git a/drivers/thunderbolt/nhi.c b/drivers/thunderbolt/nhi.c
> index 383a36212f70..72a76db5ea68 100644
> --- a/drivers/thunderbolt/nhi.c
> +++ b/drivers/thunderbolt/nhi.c
> @@ -1160,6 +1160,43 @@ static void nhi_reset(struct tb_nhi *nhi)
>  	dev_warn(nhi->dev, "timeout resetting host router\n");
>  }
>  
> +/**
> + * nhi_host_interface_reset() - Issue host interface reset

nhi_reset_interface()

> + * @tb: Domain whose host interface is reset

This should take nhi as paramter.

> + *
> + * 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. Does nothing
> + * unless the host interface is known to need this (QUIRK_HOST_INTERFACE_RESET).
> + *
> + * The control channel is stopped over the reset because the reset clears
> + * the ring state as well.
> + */

This can just reset the NHI, e.g not look into the quirks.

> +void nhi_host_interface_reset(struct tb *tb)
> +{
> +	struct tb_nhi *nhi = tb->nhi;
> +	u32 val;
> +
> +	if (!(nhi->quirks & QUIRK_HOST_INTERFACE_RESET))
> +		return;
> +
> +	val = ioread32(nhi->iobase + REG_CAPS);
> +	/* Only v1 host interfaces implement the reset */
> +	if (FIELD_GET(REG_CAPS_VERSION_MASK, val) >= REG_CAPS_VERSION_2)
> +		return;
> +
> +	dev_dbg(nhi->dev, "issuing host interface reset\n");
> +
> +	tb_ctl_stop(tb->ctl);

But don't do these here. Just the actual reset. So that we can call it
whenever we want to do host internface reset.

> +
> +	iowrite32(REG_HOST_INTERFACE_RESET_RST,
> +		  nhi->iobase + REG_HOST_INTERFACE_RESET);
> +	/* Wait for tHIReset (10 ms) to complete */
> +	usleep_range(10000, 20000);
> +
> +	tb_ctl_start(tb->ctl);
> +}
> +
>  static struct tb *nhi_select_cm(struct tb_nhi *nhi)
>  {
>  	struct tb *tb;
> diff --git a/drivers/thunderbolt/nhi.h b/drivers/thunderbolt/nhi.h
> index d488eadadfce..9be0372b837e 100644
> --- a/drivers/thunderbolt/nhi.h
> +++ b/drivers/thunderbolt/nhi.h
> @@ -36,6 +36,7 @@ irqreturn_t nhi_msi(int irq, void *data);
>  irqreturn_t ring_msix(int irq, void *data);
>  int nhi_probe(struct tb_nhi *nhi);
>  void nhi_shutdown(struct tb_nhi *nhi);
> +void nhi_host_interface_reset(struct tb *tb);

>  extern const struct dev_pm_ops nhi_pm_ops;
>  
>  /**
> @@ -121,6 +122,7 @@ struct tb_nhi_ops {
>  /* Host interface quirks */
>  #define QUIRK_AUTO_CLEAR_INT	BIT(0)
>  #define QUIRK_E2E		BIT(1)
> +#define QUIRK_HOST_INTERFACE_RESET	BIT(2)

Let's call it QUIRK_RESET_DMA_ON_TEARDOWN or something like that.

>  /*
>   * Minimal number of vectors when we use MSI-X. Two for control channel
> 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/pci.c b/drivers/thunderbolt/pci.c
> index 8462ccb59b7e..02534287cb43 100644
> --- a/drivers/thunderbolt/pci.c
> +++ b/drivers/thunderbolt/pci.c
> @@ -62,6 +62,27 @@ static void nhi_pci_check_quirks(struct tb_nhi_pci *nhi_pci)
>  			nhi->quirks |= QUIRK_E2E;
>  			break;
>  		}
> +	} else if (pdev->vendor == PCI_VENDOR_ID_AMD) {
> +		switch (pdev->device) {
> +		case 0x1120:
> +		case 0x1121:
> +		case 0x113b:
> +		case 0x113c:
> +		case 0x1155:
> +		case 0x1158:
> +		case 0x1159:
> +		case 0x151c:
> +		case 0x151d:
> +		case 0x158d:
> +		case 0x158e:

I would prefer if these are defined in nhi.h similarly what we do with the
Intel stuff so we have symbolic names for them.

> +			/*
> +			 * These AMD hosts may hang the Tx ring when the
> +			 * DMA paths are torn down so they need the host
> +			 * interface reset after each teardown.
> +			 */
> +			nhi->quirks |= QUIRK_HOST_INTERFACE_RESET;
> +			break;
> +		}
>  	}
>  }
>  
> diff --git a/drivers/thunderbolt/tb.c b/drivers/thunderbolt/tb.c
> index 47753a5c0f2e..f07f2ada2346 100644
> --- a/drivers/thunderbolt/tb.c
> +++ b/drivers/thunderbolt/tb.c
> @@ -2395,6 +2395,12 @@ 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 hosts may hang the Tx ring after the DMA paths are torn
> +	 * down so reset the host interface to prevent that.
> +	 */
> +	nhi_host_interface_reset(tb);

Instead of here, do this in domain.c::tb_domain_disconnect_xdomain_paths()
and there you can also stop/start the control channel around this. You may
need to take the tb->lock here too so maybe add a helper.

I wanted to make tb.c (and domain.c) not call anything from the "upper"
layer (nhi.c) but I can't think of reasonable way to do it here, and there
is no way to handle this from nhi.c because it has no knowledge of XDomain
tunnels. Perhaps through indirection, nhi->ops->reset_interface?

>  }
>  
>  static int tb_disconnect_xdomain_paths(struct tb *tb, struct tb_xdomain *xd,
> -- 
> 2.34.1

      reply	other threads:[~2026-08-05 12:28 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-05 11:18 [PATCH -next v2] thunderbolt: Add quirk to reset host interface on DMA path teardown for AMD USB4 routers Basavaraj Natikar
2026-08-05 12:28 ` Mika Westerberg [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=20260805122832.GH235112@black.igk.intel.com \
    --to=mika.westerberg@linux.intel.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=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.