]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
usb: xhci-pci: add support for hosts with zero USB3 ports
authorNiklas Neronin <niklas.neronin@linux.intel.com>
Wed, 17 Sep 2025 21:07:22 +0000 (00:07 +0300)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 13 Nov 2025 20:34:26 +0000 (15:34 -0500)
[ Upstream commit 719de070f764e079cdcb4ddeeb5b19b3ddddf9c1 ]

Add xhci support for PCI hosts that have zero USB3 ports.
Avoid creating a shared Host Controller Driver (HCD) when there is only
one root hub. Additionally, all references to 'xhci->shared_hcd' are now
checked before use.

Only xhci-pci.c requires modification to accommodate this change, as the
xhci core already supports configurations with zero USB3 ports. This
capability was introduced when xHCI Platform and MediaTek added support
for zero USB3 ports.

Closes: https://bugzilla.kernel.org/show_bug.cgi?id=220181
Tested-by: Nick Nielsen <nick.kainielsen@free.fr>
Tested-by: grm1 <grm1@mailbox.org>
Signed-off-by: Niklas Neronin <niklas.neronin@linux.intel.com>
Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
Link: https://lore.kernel.org/r/20250917210726.97100-4-mathias.nyman@linux.intel.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/usb/host/xhci-pci.c

index 234efb9731b2cf2aa3d4795dad85c95041f84bfb..933d9fdd9516bbaa923420a0e16d3eb8e31960ad 100644 (file)
@@ -616,7 +616,7 @@ int xhci_pci_common_probe(struct pci_dev *dev, const struct pci_device_id *id)
 {
        int retval;
        struct xhci_hcd *xhci;
-       struct usb_hcd *hcd;
+       struct usb_hcd *hcd, *usb3_hcd;
        struct reset_control *reset;
 
        reset = devm_reset_control_get_optional_exclusive(&dev->dev, NULL);
@@ -642,26 +642,32 @@ int xhci_pci_common_probe(struct pci_dev *dev, const struct pci_device_id *id)
        hcd = dev_get_drvdata(&dev->dev);
        xhci = hcd_to_xhci(hcd);
        xhci->reset = reset;
-       xhci->shared_hcd = usb_create_shared_hcd(&xhci_pci_hc_driver, &dev->dev,
-                                                pci_name(dev), hcd);
-       if (!xhci->shared_hcd) {
-               retval = -ENOMEM;
-               goto dealloc_usb2_hcd;
-       }
 
-       retval = xhci_ext_cap_init(xhci);
-       if (retval)
-               goto put_usb3_hcd;
+       xhci->allow_single_roothub = 1;
+       if (!xhci_has_one_roothub(xhci)) {
+               xhci->shared_hcd = usb_create_shared_hcd(&xhci_pci_hc_driver, &dev->dev,
+                                                        pci_name(dev), hcd);
+               if (!xhci->shared_hcd) {
+                       retval = -ENOMEM;
+                       goto dealloc_usb2_hcd;
+               }
 
-       retval = usb_add_hcd(xhci->shared_hcd, dev->irq,
-                       IRQF_SHARED);
-       if (retval)
-               goto put_usb3_hcd;
-       /* Roothub already marked as USB 3.0 speed */
+               retval = xhci_ext_cap_init(xhci);
+               if (retval)
+                       goto put_usb3_hcd;
+
+               retval = usb_add_hcd(xhci->shared_hcd, dev->irq, IRQF_SHARED);
+               if (retval)
+                       goto put_usb3_hcd;
+       } else {
+               retval = xhci_ext_cap_init(xhci);
+               if (retval)
+                       goto dealloc_usb2_hcd;
+       }
 
-       if (!(xhci->quirks & XHCI_BROKEN_STREAMS) &&
-                       HCC_MAX_PSA(xhci->hcc_params) >= 4)
-               xhci->shared_hcd->can_do_streams = 1;
+       usb3_hcd = xhci_get_usb3_hcd(xhci);
+       if (usb3_hcd && !(xhci->quirks & XHCI_BROKEN_STREAMS) && HCC_MAX_PSA(xhci->hcc_params) >= 4)
+               usb3_hcd->can_do_streams = 1;
 
        /* USB-2 and USB-3 roothubs initialized, allow runtime pm suspend */
        pm_runtime_put_noidle(&dev->dev);