Hi, On Mon, Oct 23, 2017 at 5:27 PM, Mathias Nyman <mathias.nyman@xxxxxxxxxxxxxxx> wrote: > On 23.10.2017 12:37, Thang Q. Nguyen wrote: >> >> Hi, >> In our latest ARM64-based CPU, we use the DesignWare USB which is >> xHCI-compatible. For some reasons, we disable USB3.0 support so remove the >> unnecessary USB3.0 capability structure information as specified in the >> xHCI specification 1.1, section 7.2: >> "At least one of these capability structures is required for all xHCI >> implementations. More than one may be defined for implementations that >> support more that one bus protocol." >> > > So there is no supported protocol capability with revision major == 3, in > your case. > > >> When booting kernel, linux kernel displays an error message to claim about >> no USB port on the USB3.0 roothub: >> [ 3.497767] hub 2-0:1.0: config failed, hub doesn't have any ports! >> (err -19) >> Although the error message does not affect USB functionality, error >> message will make users confused. >> >> Looking into the XHCI driver, there are always two USB hub ports >> implemented. This implements the xHCI specification as in 4.19.7: >> "In a USB3 hub, two independently addressable hub ports exist for each >> physical down stream connector; a USB2 compatible port accessed through >> the USB2 connection and a USB3 compatible port accessed through the >> SuperSpeed connection. The Root Hub of the xHCI emulates this operation by >> defining a Root Hub PORTSC register for each connection type; USB2 >> (Low-/Full-/High-Speed) or USB3 (SuperSpeed)." >> >> But the problem is that, xhci-hcd always pass both USB hub ports to >> usb-core driver. In case any of USB2 or USB3 compatible port is missing, >> there is no port on the corresponding hub and kernel will displays the >> error message. >> >> Below are some approaches we suggest to overcome the issue: >> Approach 1: Allow roothub has no port. The change will look like: >> diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c >> index b5c7336..995d62d 100644 >> --- a/drivers/usb/core/hub.c >> +++ b/drivers/usb/core/hub.c >> @@ -1347,6 +1347,9 @@ static int hub_configure(struct usb_hub >> *hub, >> ret = -ENODEV; >> goto fail; >> } else if (hub->descriptor->bNbrPorts == 0) { >> + if (hdev->parent) >> + return -ENODEV; >> + >> message = "hub doesn't have any >> ports!"; >> ret = -ENODEV; >> goto fail; >> Approach 2: do not pass a USB hub port to usb-core if it has no port. >> Don't know if this approach is feasible or not. >> Approach 3: implement maximum-speed attribute support and this will be set >> to high-speed in case of missing USB3 support. But this works only for the >> case of USB3.0 disabled. >> >> Can you help review and suggest what approach should be used to fix this >> issue? > > > Current xhci driver design assumes there are two hcds available. > Several functions assume a shared hcd exists. > > Creating a hcd with a roothub with zero ports is probably a faster way to > get > things running, but I think we should redesign parts of the xhci driver to > work with only one hcd. > > So best would be to never add the secodary hcd if there are no USB 3 ports, > meaning no: > xhci->shared_hcd = usb_create_shared_hcd(..); > usb_add_hcd(xhci->shared_hcd, dev->irq, Below code is to not add shared_hcd if no USB 3 port: diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c index 1cb6eae..0881fb5 100644 --- a/drivers/usb/host/xhci-plat.c +++ b/drivers/usb/host/xhci-plat.c @@ -285,12 +285,14 @@ static int xhci_plat_probe(struct platform_device *pdev) if (ret) goto disable_usb_phy; - if (HCC_MAX_PSA(xhci->hcc_params) >= 4) - xhci->shared_hcd->can_do_streams = 1; + if (xhci->num_usb3_ports > 0) { + if (HCC_MAX_PSA(xhci->hcc_params) >= 4) + xhci->shared_hcd->can_do_streams = 1; - ret = usb_add_hcd(xhci->shared_hcd, irq, IRQF_SHARED); - if (ret) - goto dealloc_usb2_hcd; + ret = usb_add_hcd(xhci->shared_hcd, irq, IRQF_SHARED); + if (ret) + goto dealloc_usb2_hcd; + } device_enable_async_suspend(&pdev->dev); pm_runtime_put_noidle(&pdev->dev); Then, the xhci_run should execute xhci_start() in case no USB 3 port (xhci->shared_hcd->run() will execute xhci_run_finished() which run xhci_start(). diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 51535ba..3ad41aa 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -630,6 +630,16 @@ int xhci_run(struct usb_hcd *hcd) if (ret) xhci_free_command(xhci, command); } + + /* Execute xhci_start() in case xhci->shared_hcd is not registered */ + if (xhci->num_usb3_ports > 0) { + if (xhci_start(xhci)) { + xhci_halt(xhci); + return -ENODEV; + } + xhci->cmd_ring_state = CMD_RING_STATE_RUNNING; + } + xhci_dbg_trace(xhci, trace_xhci_dbg_init, "Finished xhci_run for USB2 roothub"); return 0; > > Instead we need to make sure xhci->shared_hcd is set to NULL, > and modify at least the following functions to work with only one xhci hcd: Do we really need to set xhci->shared_hcd to NULL? when xhci->shared_hcd is not registered to usb_core, no operation work on it. > > xhci_run() > xhci_stop() > xhci_suspend() > xhci_resume() > xhci_gen_setup() > > More changes are very likely needed, but this is a place to start > > -Mathias > > - ThangQ. -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html