In a system with multiple XHCI controllers, the global descriptor.hub
(bNbrPorts) can be overwritten by a later initialized controller,
causing the root hub of an earlier controller to report wrong port
numbers.

Fix this by dynamically setting bNbrPorts from the current controller's
hcsparams1 in the USB_DT_HUB request handler, instead of relying on
a stale global value.

Signed-off-by: Beibei Yang <[email protected]>

diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index dbeb88a..f7984de 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -942,6 +942,12 @@ static int xhci_submit_root(struct usb_device *udev, 
unsigned long pipe,
                case USB_DT_HUB:
                case USB_DT_SS_HUB:
                        debug("USB_DT_HUB config\n");
+                       /* Dynamically set bNbrPorts from this controller's
+                       * hcsparams1, because the global descriptor.hub
+                       * may have been overwritten by another controller
+                       * that initialized after this one. */
+                       descriptor.hub.bNbrPorts =
+                               HCS_MAX_PORTS(xhci_readl(&hccr->cr_hcsparams1));
                        srcptr = &descriptor.hub;
                        srclen = 0x8;
                        break;

Reply via email to