summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNiklas Neronin <niklas.neronin@linux.intel.com>2025-09-18 00:07:22 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2025-09-18 09:53:11 +0200
commit719de070f764e079cdcb4ddeeb5b19b3ddddf9c1 (patch)
treeb00cf013f928bdd676f068f91aa9320d7ce13d0a
parent0ed023a88396088d4221c345a3911f553dd42598 (diff)
usb: xhci-pci: add support for hosts with zero USB3 ports
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>
-rw-r--r--drivers/usb/host/xhci-pci.c42
1 files changed, 24 insertions, 18 deletions
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index 00fac8b233d2..5c8ab519f497 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -610,7 +610,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);
@@ -636,26 +636,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);