The Linux Kernel Mailing List
 help / color / mirror / Atom feed
* [PATCH v2] usb: xhci-pci: Limit VIA VL805 DMA addressing to 36 bits
@ 2026-06-29  2:48 Xincheng Zhang
  2026-06-29  5:09 ` Michal Pecio
  0 siblings, 1 reply; 3+ messages in thread
From: Xincheng Zhang @ 2026-06-29  2:48 UTC (permalink / raw)
  To: Mathias Nyman, Greg Kroah-Hartman
  Cc: Michal Pecio, Forest Crossman, linux-usb, linux-kernel,
	Xincheng Zhang

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.

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


^ permalink raw reply related	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2026-06-29  7:28 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
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
2026-06-29  7:28   ` Xincheng Zhang

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox