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
_______________________________________________
[email protected]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel