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