Hi, On Sat, Dec 16, 2017 at 10:45 AM, Thang Q. Nguyen <tqnguyen@xxxxxxx> wrote: > From: Tung Nguyen <tunguyen@xxxxxxx> > > Currently, hcd->shared_hcd always creates and registers to the usb-core. > If, for some reasons, USB3 downstream port is disabled, no roothub port for > USB3.0 is found. This causes kernel to display an error: > hub 2-0:1.0: config failed, hub doesn't have any ports! (err -19) > This patch checks, creates and registers shared_hcd if USB3.0 downstream > port is available. > > Signed-off-by: Tung Nguyen <tunguyen@xxxxxxx> > Signed-off-by: Thang Q. Nguyen <tqnguyen@xxxxxxx> > --- > drivers/usb/host/xhci-mem.c | 2 +- > drivers/usb/host/xhci-plat.c | 26 +++++++++++---------- > drivers/usb/host/xhci.c | 54 ++++++++++++++++++++++++++++++++------------ > 3 files changed, 54 insertions(+), 28 deletions(-) > > diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c > index 554a8a5..157d1e7 100644 > --- a/drivers/usb/host/xhci-mem.c > +++ b/drivers/usb/host/xhci-mem.c > @@ -1067,7 +1067,7 @@ static u32 xhci_find_real_port_number(struct xhci_hcd *xhci, > struct usb_device *top_dev; > struct usb_hcd *hcd; > > - if (udev->speed >= USB_SPEED_SUPER) > + if (udev->speed >= USB_SPEED_SUPER && xhci->shared_hcd) > hcd = xhci->shared_hcd; > else > hcd = xhci->main_hcd; > diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c > index 6f03830..e812e3d 100644 > --- a/drivers/usb/host/xhci-plat.c > +++ b/drivers/usb/host/xhci-plat.c > @@ -253,12 +253,6 @@ static int xhci_plat_probe(struct platform_device *pdev) > > xhci->clk = clk; > xhci->main_hcd = hcd; > - xhci->shared_hcd = __usb_create_hcd(driver, sysdev, &pdev->dev, > - dev_name(&pdev->dev), hcd); > - if (!xhci->shared_hcd) { > - ret = -ENOMEM; > - goto disable_clk; > - } > > if (device_property_read_bool(sysdev, "usb2-lpm-disable")) > xhci->quirks |= XHCI_HW_LPM_DISABLE; > @@ -290,12 +284,20 @@ 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; > - > - ret = usb_add_hcd(xhci->shared_hcd, irq, IRQF_SHARED); > - if (ret) > - goto dealloc_usb2_hcd; > + if (xhci->num_usb3_ports > 0) { > + xhci->shared_hcd = __usb_create_hcd(driver, sysdev, &pdev->dev, > + dev_name(&pdev->dev), hcd); > + if (!xhci->shared_hcd) { > + ret = -ENOMEM; > + goto disable_clk; > + } > + 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; > + } > > device_enable_async_suspend(&pdev->dev); > pm_runtime_put_noidle(&pdev->dev); > diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c > index 05104bd..4824bf6 100644 > --- a/drivers/usb/host/xhci.c > +++ b/drivers/usb/host/xhci.c > @@ -417,12 +417,14 @@ static void compliance_mode_recovery(struct timer_list *t) > i + 1); > xhci_dbg_trace(xhci, trace_xhci_dbg_quirks, > "Attempting compliance mode recovery"); > - hcd = xhci->shared_hcd; > + if (xhci->shared_hcd) { > + hcd = xhci->shared_hcd; > > - if (hcd->state == HC_STATE_SUSPENDED) > - usb_hcd_resume_root_hub(hcd); > + if (hcd->state == HC_STATE_SUSPENDED) > + usb_hcd_resume_root_hub(hcd); > > - usb_hcd_poll_rh_status(hcd); > + usb_hcd_poll_rh_status(hcd); > + } > } > } > > @@ -611,6 +613,18 @@ 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 the xhci->shared_hcd doesn't exist, no one triggers to start > + * the xhci which should be done before exitting run function > + */ > + if (!xhci->shared_hcd) { > + 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"); > > @@ -861,8 +875,8 @@ int xhci_suspend(struct xhci_hcd *xhci, bool do_wakeup) > if (!hcd->state) > return 0; > > - if (hcd->state != HC_STATE_SUSPENDED || > - xhci->shared_hcd->state != HC_STATE_SUSPENDED) > + if (hcd->state != HC_STATE_SUSPENDED || (xhci->shared_hcd && > + xhci->shared_hcd->state != HC_STATE_SUSPENDED)) > return -EINVAL; > > xhci_dbc_suspend(xhci); > @@ -875,12 +889,15 @@ int xhci_suspend(struct xhci_hcd *xhci, bool do_wakeup) > xhci_dbg(xhci, "%s: stopping port polling.\n", __func__); > clear_bit(HCD_FLAG_POLL_RH, &hcd->flags); > del_timer_sync(&hcd->rh_timer); > - clear_bit(HCD_FLAG_POLL_RH, &xhci->shared_hcd->flags); > - del_timer_sync(&xhci->shared_hcd->rh_timer); > + if (xhci->shared_hcd) { > + clear_bit(HCD_FLAG_POLL_RH, &xhci->shared_hcd->flags); > + del_timer_sync(&xhci->shared_hcd->rh_timer); > + } > > spin_lock_irq(&xhci->lock); > clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); > - clear_bit(HCD_FLAG_HW_ACCESSIBLE, &xhci->shared_hcd->flags); > + if (xhci->shared_hcd) > + clear_bit(HCD_FLAG_HW_ACCESSIBLE, &xhci->shared_hcd->flags); > /* step 1: stop endpoint */ > /* skipped assuming that port suspend has done */ > > @@ -961,7 +978,8 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated) > msleep(100); > > set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); > - set_bit(HCD_FLAG_HW_ACCESSIBLE, &xhci->shared_hcd->flags); > + if (xhci->shared_hcd) > + set_bit(HCD_FLAG_HW_ACCESSIBLE, &xhci->shared_hcd->flags); > > spin_lock_irq(&xhci->lock); > if (xhci->quirks & XHCI_RESET_ON_RESUME) > @@ -998,7 +1016,9 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated) > > /* Let the USB core know _both_ roothubs lost power. */ > usb_root_hub_lost_power(xhci->main_hcd->self.root_hub); > - usb_root_hub_lost_power(xhci->shared_hcd->self.root_hub); > + if (xhci->shared_hcd) > + usb_root_hub_lost_power( > + xhci->shared_hcd->self.root_hub); > > xhci_dbg(xhci, "Stop HCD\n"); > xhci_halt(xhci); > @@ -1039,7 +1059,8 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated) > retval = xhci_run(secondary_hcd); > } > hcd->state = HC_STATE_SUSPENDED; > - xhci->shared_hcd->state = HC_STATE_SUSPENDED; > + if (xhci->shared_hcd) > + xhci->shared_hcd->state = HC_STATE_SUSPENDED; > goto done; > } > > @@ -1068,7 +1089,8 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated) > /* Resume root hubs only when have pending events. */ > status = readl(&xhci->op_regs->status); > if (status & STS_EINT) { > - usb_hcd_resume_root_hub(xhci->shared_hcd); > + if (xhci->shared_hcd) > + usb_hcd_resume_root_hub(xhci->shared_hcd); > usb_hcd_resume_root_hub(hcd); > } > } > @@ -1087,8 +1109,10 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated) > > /* Re-enable port polling. */ > xhci_dbg(xhci, "%s: starting port polling.\n", __func__); > - set_bit(HCD_FLAG_POLL_RH, &xhci->shared_hcd->flags); > - usb_hcd_poll_rh_status(xhci->shared_hcd); > + if (xhci->shared_hcd) { > + set_bit(HCD_FLAG_POLL_RH, &xhci->shared_hcd->flags); > + usb_hcd_poll_rh_status(xhci->shared_hcd); > + } > set_bit(HCD_FLAG_POLL_RH, &hcd->flags); > usb_hcd_poll_rh_status(hcd); > > -- > 1.8.3.1 > Do you have any comment on this patch? -- 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