For the `struct descriptor`, only the `hub` part (`bNbrPorts` and `wHubCharacteristics`) is different for each controller; the other five members (device, config, interface, endpoint,ep_companion)are identical for all XHCI root hubs.
My previous patch only fixed the dynamic reading of `bNbrPorts`, but `wHubCharacteristics` is also different for each controller and will be overridden by the last controller. New patch as below for referrence. Signed-off-by: Beibei Yang <[email protected]> Index: drivers/usb/host/xhci.c =================================================================== --- drivers/usb/host/xhci.c (revision 10446) +++ drivers/usb/host/xhci.c (working copy) @@ -954,13 +954,7 @@ case USB_DT_HUB: case USB_DT_SS_HUB: debug("USB_DT_HUB config\n"); - srcptr = &descriptor.hub; + srcptr = &ctrl->hub_desc; srclen = 0x8; break; default: @@ -1221,20 +1215,21 @@ return -ENOMEM; reg = xhci_readl(&hccr->cr_hcsparams1); - descriptor.hub.bNbrPorts = ((reg & HCS_MAX_PORTS_MASK) >> - HCS_MAX_PORTS_SHIFT); - printf("Register %x NbrPorts %d\n", reg, descriptor.hub.bNbrPorts); + ctrl->hub_desc = descriptor.hub; + ctrl->hub_desc.bNbrPorts = ((reg & HCS_MAX_PORTS_MASK) >> + HCS_MAX_PORTS_SHIFT); + printf("Register %x NbrPorts %d\n", reg, ctrl->hub_desc.bNbrPorts); /* Port Indicators */ reg = xhci_readl(&hccr->cr_hccparams); if (HCS_INDICATOR(reg)) - put_unaligned(get_unaligned(&descriptor.hub.wHubCharacteristics) - | 0x80, &descriptor.hub.wHubCharacteristics); + put_unaligned(get_unaligned(&ctrl->hub_desc.wHubCharacteristics) + | 0x80, &ctrl->hub_desc.wHubCharacteristics); /* Port Power Control */ if (HCC_PPC(reg)) - put_unaligned(get_unaligned(&descriptor.hub.wHubCharacteristics) - | 0x01, &descriptor.hub.wHubCharacteristics); + put_unaligned(get_unaligned(&ctrl->hub_desc.wHubCharacteristics) + | 0x01, &ctrl->hub_desc.wHubCharacteristics); if (xhci_start(hcor)) { xhci_reset(hcor); Index: include/usb/xhci.h =================================================================== --- include/usb/xhci.h (revision 10446) +++ include/usb/xhci.h (working copy) @@ -21,6 +21,7 @@ #include <asm/io.h> #include <linux/list.h> #include <linux/compat.h> +#include <usb.h> #define MAX_EP_CTX_NUM 31 #define XHCI_ALIGNMENT 64 @@ -1229,6 +1230,7 @@ struct xhci_erst_entry entry[ERST_NUM_SEGS]; struct xhci_scratchpad *scratchpad; struct xhci_virt_device *devs[MAX_HC_SLOTS]; + struct usb_hub_descriptor hub_desc; int rootdev; }; ---- Replied Message ---- | From | Marek Vasut<[email protected]> | | Date | 06/28/2026 04:10 | | To | Beibei Yang<[email protected]>、[email protected] | | Cc | [email protected] | | Subject | Re: [PATCH] usb: xhci: Fix bNbrPorts overwritten by another controller | On 6/27/26 2:37 PM, Beibei Yang wrote: > 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. How about having one descriptor per controller ? This is probably easily doable in xhci_lowlevel_init() with some ctrl->hub_desc = kmemdup(descriptor.hub,...); and related tweaks. What do you think ?

