Re: [PATCH 3/7] xhci: Don't suspend a xhci usb bus if there is a pending event.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Fri, 8 Apr 2016, Mathias Nyman wrote:

> > A USB3 device connected to a runtime suspended host woke up the host, polled the roothub,
> > found nothing and immediately tried to suspend again.
> >
> > Logs show:
> > Feb 16 20:03:33 xhci_hcd 0000:0e:00.0: // Setting command ring address to 0xffffe001
> > Feb 16 20:03:33 xhci_hcd 0000:0e:00.0: xhci_resume: starting port polling.
> > Feb 16 20:03:33 xhci_hcd 0000:0e:00.0: xhci_hub_status_data: stopping port polling.
> > Feb 16 20:03:33 xhci_hcd 0000:0e:00.0: xhci_suspend: stopping port polling.
> > Feb 16 20:03:33 xhci_hcd 0000:0e:00.0: Port Status Change Event for port 3
> > Feb 16 20:03:33 xhci_hcd 0000:0e:00.0: resume root hub
> > ..other entries..
> > Feb 16 20:03:33 xhci_hcd 0000:0e:00.0: Port Status Change Event for port 1
> > Feb 16 20:03:33 xhci_hcd 0000:0e:00.0: resume root hub
> >
> >
> > So what probably happened here was that connecting the usb device caused a
> > PCI PME# event to wake up the xhci PCI controller, calling
> >    xhci_pci_resume(), calling
> >      xhci_resume(), calling
> >        usb_hcd_resume_root_hub(both usb2 and usb3 hcds) and
> >        usb_hcd_poll_rh_status(both usb2 and usb3 hcd). polling rh status calls
> >          hcd->driver->hub_status_data() -> xhci_hub_status_data()
> >          xhci_hub_status_data() reads PORTSCs -> no change -> stop polling -> return 0

That sounds like a hardware bug.  If the controller knows a device was 
connected (because it signalled a PME# event), why doesn't the PORTSC 
register show a status change?

> > In core/hub.c hub_probe() autosuspend is set to 0 for roothubs with a long explanation why.
> > I assume that as xhci_hub_status_data clears the HCD_FLAG_POLL_RH flag and returns 0 (no changes)
> > we immediately runtime suspend the hub -> runtime suspend host.

Right.  Since apparently nothing happened, there's no reason to keep 
the root hub active.

> To continue, it looks like calling usb_hcd_resume_root_hub() is ends calling autosuspend
> 
> usb_hcd_resume_root_hub (hcd)
>    set_bit(HCD_FLAG_WAKEUP_PENDING, &hcd->flags);
>    queue_work(pm_wq, &hcd->wakeup_work);  -> hcd_resume_work()
>      ..workqueue async..
>      hcd_resume_work()
>        usb_remote_wakeup(hcd->self.root_hub)
>          status = usb_autoresume_device(udev);   // calls pm_runtime_get_sync, returns 0
>          if (status == 0)
>            usb_autosuspend_device(udev); // calls pm_runtime_put_sync_autosuspend(&udev->dev)
> 
> 
> pm_runtime_get_sync() probably calls xhci_bus_resume() for the roothub,
> but apparently that doesn't prevent suspending either.

If the PORTSC register had indicated a status change then the hub
driver would have called usb_autopm_get_interface_no_resume(), which
would prevent the root hub from being autosuspended.

> Maybe I should increase the autosuspend delay for xhci roothubs, or then see if there is
> something wrong with xhci_bus_resume()

Try to find out why the PORTSC register doesn't indicate a connect 
status change.

Alan Stern

--
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



[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux