Dave and Olav: It's easy to see that different HCDs handle suspend/resume with some important differences. IMHO we should try to make these things work as uniformly as possible. Here's a brief description of how uhci-hcd now works; do you guys think it would be worthwhile changing the other drivers to match? (For the isp116x, read "platform device" for "PCI device" below.)
There's no recursion. When the PCI device is suspended or resumed, the code does _not_ suspend or resume the root hub device. This is in keeping with my attitude that the USB subsystem shouldn't do much (or any!) recursion for suspend/resume. During a system sleep/wakeup transition it's not necessary, as the PM core will do it for us. For runtime power management the recursion can be left up to userspace tools. (This leaves unanswered the question of how to handle a situation where one user program is trying to suspend a parent device while at the same time another program is trying to resume a child device. Let's not worry about that for now.) There's an exception made if CONFIG_USB_SUSPEND isn't set. In that case the PCI device's suspend/resume routines do automatically call the internal subroutines for suspending/ resuming the root hub -- otherwise the root hub would never change state! Note that they don't call usb_suspend_device or usb_resume_device, since those routines don't do anything when CONFIG_USB_SUSPEND isn't set. On the other hand, the code does do a minimal amount of checking. The PCI device's suspend routine checks that the root hub is already suspended, and the root hub's resume routine checks that the PCI device is already resumed. If the checks fail an error is returned. Note that these checks don't actually involve dereferencing hcd->self.root_hub. The driver keeps track internally of the state of the root hub. Thus there's no danger should the code run at a time when the root hub hasn't been registered (although in fact that can't happen). Auto-suspend (called AUTO_STOP in uhci-hcd) is handled separately from the normal suspend pathway. In particular, it doesn't involve calling usb_suspend_device for the root hub. Likewise, resuming from AUTO_STOP doesn't involve calling usb_resume_device. Only internal routines are involved. This is partly so that auto-suspend can work even when CONFIG_USB_SUSPEND is off. But more importantly, it reflects a separation of responsibilities between the hub driver and the HCD. As far as usbcore is concerned, the root hub is (like every other hub) totally under the control of the hub driver. It shouldn't be suspended or resumed on the whim of the HCD, which is only supposed to manage the hardware. When the hub driver gets auto-suspend capability added, the HCD won't need it. Until then, an HCD-initiated auto-suspend is completely internal to the driver -- usbcore is unaware that anything has happened. An HCD should be largely unaware of the existence of hcd->self.root_hub. When the HCD needs to do something that affects the root hub, a facility should be provided by usbcore. In short, the HCD should never need to dereference hcd->self.root_hub. The facilities currently available for use by HCDs include usb_hc_died, usb_hcd_resume_root_hub, and usb_hcd_poll_rh_status. Normally usbcore will call usb_hc_died on behalf of the HCD, so the driver doesn't need to do so by hand. The usb_hcd_poll_rh_status routine is quite new, and drivers should convert to use IRQs rather than polling for port changes. >From looking through the code, I see that we need another facility added: usb_hcd_root_hub_lost_power. This would take over the duty of marking all the children devices as NOTATTACHED and simulating connect-change events on their ports, something which clearly belongs in usbcore and not in HCDs. I think that covers pretty much everything. If I left something out, please let me know. Olav, I noticed a couple of things in isp116c-hcd.c that could be changed. In the IRQ routine you have a comment asking what to do when an unrecoverable error occurs. The answer is to set hcd->state to HC_STATE_HALT and take whatever other actions are needed to quiesce the controller. Then usbcore will automatically call usb_hc_died for you. See uhci_irq() and hc_died() in uhci-hcd.c for an example. Also, your isp116x_rh_resume routine isn't needed. When the root hub is suspended (and usbcore knows that it's suspended!) and a resume request comes in, all you need to do is call usb_hcd_resume_root_hub. (You can call it in interrupt context.) Then khubd will take care of resuming the root hub for you, and you don't have to worry about races between the workqueue thread running and the root hub being unregistered. Alan Stern ------------------------------------------------------- SF email is sponsored by - The IT Product Guide Read honest & candid reviews on hundreds of IT Products from real users. Discover which products truly live up to the hype. Start reading now. http://ads.osdn.com/?ad_id=6595&alloc_id=14396&op=click _______________________________________________ linux-usb-devel@lists.sourceforge.net To unsubscribe, use the last form field at: https://lists.sourceforge.net/lists/listinfo/linux-usb-devel