From: Michal Pecio <michal.pecio@gmail.com>
To: Xincheng Zhang <zhangxincheng@ultrarisc.com>
Cc: Mathias Nyman <mathias.nyman@intel.com>,
Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
Forest Crossman <cyrozap@gmail.com>,
linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH v2] usb: xhci-pci: Limit VIA VL805 DMA addressing to 36 bits
Date: Mon, 29 Jun 2026 07:09:06 +0200 [thread overview]
Message-ID: <20260629070906.37320541.michal.pecio@gmail.com> (raw)
In-Reply-To: <20260629-xhci-via-dma-fix-v2-1-380167319652@ultrarisc.com>
On Mon, 29 Jun 2026 10:48:13 +0800, Xincheng Zhang wrote:
> The VIA VL805/806 xHCI controller advertises AC64, but fails to handle
> DMA addresses at or above 0x1000000000. On systems with large amounts of
> RAM, this can cause USB device failures when the controller is given DMA
> addresses beyond its usable address width.
>
> Do not use XHCI_NO_64BIT_SUPPORT for this controller. That quirk clears
> the cached AC64 capability and limits DMA to 32 bits, causing unnecessary
> bouncing for addresses between 4GiB and 64GiB and hiding the controller's
> real AC64 capability from code that may need to distinguish register
> access width from usable DMA address width.
>
> Add a separate xHCI quirk for controllers whose usable DMA address width
> is limited to 36 bits, and apply it to VIA VL805/806. This keeps AC64
> visible while restricting the DMA mask to exactly the range that the
> controller can handle.
This may turn into multiple quirks differing only in the number at the
end. For example, ASMedia chips appear to be limited to 48 bits and we
don't even know if these two are the only bad vendors. I briefly tested
Etron and NEC/Renesas, they seem to be OK, but there are others.
The driver is getting dangerously close to filling quirks bitmap and
needing changes to support more than 64 quirks.
Alternatively, I think your 'dma_bits' variable could be allocated at
the beginning and initialized to 64, then passed by reference to
get_quirks() so it can tweak it, and lastly clamped to 32 if the AC64
capability is absent or disabled by quirk.
>
> Cc: stable@vger.kernel.org
> Signed-off-by: Xincheng Zhang <zhangxincheng@ultrarisc.com>
> ---
> Changes in v2:
> - Replace XHCI_NO_64BIT_SUPPORT with a dedicated 36-bit DMA mask quirk.
> - Preserve HCCPARAMS1.AC64 instead of clearing it for VL805/806.
> - Limit VL805/806 DMA to DMA_BIT_MASK(36) instead of 32-bit.
> - Add a stable Cc trailer.
> - Link to v1: https://lore.kernel.org/all/20260623-xhci-via-dma-fix-v1-1-3f12c81a1cf8@ultrarisc.com/
> ---
> drivers/usb/host/xhci-pci.c | 1 +
> drivers/usb/host/xhci.c | 30 ++++++++++++++++++++++++------
> drivers/usb/host/xhci.h | 1 +
> 3 files changed, 26 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
> index 039c26b241d0..e5618551e022 100644
> --- a/drivers/usb/host/xhci-pci.c
> +++ b/drivers/usb/host/xhci-pci.c
> @@ -448,6 +448,7 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
> if (pdev->vendor == PCI_VENDOR_ID_VIA && pdev->device == PCI_DEVICE_ID_VIA_VL805) {
> xhci->quirks |= XHCI_LPM_SUPPORT;
> xhci->quirks |= XHCI_TRB_OVERFETCH;
> + xhci->quirks |= XHCI_LIMIT_36BIT_DMA;
> }
>
> if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA &&
> diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
> index 6922cc5496c1..fa546e5cd300 100644
> --- a/drivers/usb/host/xhci.c
> +++ b/drivers/usb/host/xhci.c
> @@ -5506,13 +5506,31 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks)
> if (xhci->quirks & XHCI_NO_64BIT_SUPPORT)
> xhci->hcc_params &= ~BIT(0);
>
> - /* Set dma_mask and coherent_dma_mask to 64-bits,
> - * if xHC supports 64-bit addressing */
> - if ((xhci->hcc_params & HCC_64BIT_ADDR) &&
> - !dma_set_mask(dev, DMA_BIT_MASK(64))) {
> - xhci_dbg(xhci, "Enabling 64-bit DMA addresses.\n");
> - dma_set_coherent_mask(dev, DMA_BIT_MASK(64));
> + /*
> + * Set dma_mask and coherent_dma_mask to 64-bits if xHC supports
> + * 64-bit addressing, unless a controller-specific quirk limits the
> + * usable address width.
> + */
> + if (xhci->hcc_params & HCC_64BIT_ADDR) {
> + u64 dma_mask = DMA_BIT_MASK(64);
> + unsigned int dma_bits = 64;
> +
> + if (xhci->quirks & XHCI_LIMIT_36BIT_DMA) {
> + dma_mask = DMA_BIT_MASK(36);
> + dma_bits = 36;
> + }
> +
> + retval = dma_set_mask(dev, dma_mask);
> + if (!retval) {
> + xhci_dbg(xhci, "Enabling %u-bit DMA addresses.\n",
> + dma_bits);
> + dma_set_coherent_mask(dev, dma_mask);
> + }
> } else {
> + retval = -ENODEV;
> + }
> +
> + if (retval) {
> /*
> * This is to avoid error in cases where a 32-bit USB
> * controller is used on a 64-bit capable system.
I'm not sure if we really need this second call to dma_set_mask() below
when the first call fails? This code was added by fda182d80a0bf and it
really should have been an 'else' to the check for AC64 capbality, not
to the capability *and* having successfully enabled 64 bit DMA.
OTOH, one could argue against cleaning this up in a stable patch.
> diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
> index d02046a573e4..e737ab36d0a3 100644
> --- a/drivers/usb/host/xhci.h
> +++ b/drivers/usb/host/xhci.h
> @@ -1647,6 +1647,7 @@ struct xhci_hcd {
> #define XHCI_CDNS_SCTX_QUIRK BIT_ULL(48)
> #define XHCI_ETRON_HOST BIT_ULL(49)
> #define XHCI_LIMIT_ENDPOINT_INTERVAL_9 BIT_ULL(50)
> +#define XHCI_LIMIT_36BIT_DMA BIT_ULL(51)
>
> unsigned int num_active_eps;
> unsigned int limit_active_eps;
>
> ---
> base-commit: 502d801f0ab03e4f32f9a33d203154ce84887921
> change-id: 20260623-xhci-via-dma-fix-c563b889ea54
>
> Best regards,
> --
> Xincheng Zhang <zhangxincheng@ultrarisc.com>
>
next prev parent reply other threads:[~2026-06-29 5:09 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-29 2:48 [PATCH v2] usb: xhci-pci: Limit VIA VL805 DMA addressing to 36 bits Xincheng Zhang
2026-06-29 5:09 ` Michal Pecio [this message]
2026-06-29 7:28 ` Xincheng Zhang
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=20260629070906.37320541.michal.pecio@gmail.com \
--to=michal.pecio@gmail.com \
--cc=cyrozap@gmail.com \
--cc=gregkh@linuxfoundation.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-usb@vger.kernel.org \
--cc=mathias.nyman@intel.com \
--cc=zhangxincheng@ultrarisc.com \
/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