On Thu, 15 Sep 2005, David Brownell wrote:
> > But I was talking about a
> > different problem. Even when CONFIG_USB_SUSPEND is set, your patch will
> > prevent usbcore from suspending root hubs during FREEZE events.
>
> Actually it _does_ suspend them ... in the same way it does without
> that CONFIG option. That is, as part of suspending the controller
> itself. Though (as you pointed out later) because those #ifdefs, the
> HCDs don't expect that path when USB_SUSPEND is enabled; we don't
> want that to stick around either.
>
> At any rate, that'd only break an EXPERIMENTAL feature, one that's
> clearly labeled as "... may not work as expected ...".
True. See below.
> > The patch should have said something more like this:
> >
> > + udev = to_usb_device(dev);
> > + if (message.event == PM_EVENT_FREEZE && udev->parent) {
> > + dev->power.power_state = message;
> > + return 0;
> > + }
> > + return usb_suspend_device (udev);
>
> The operative change being testing udev->parent. I think I prefer
> the solution of having the hub suspend code call the root hub suspend
> code, to make layering a bit more clear.
Do you mean having the HCD suspend code call the root hub suspend code?
Either way could work. I prefer to do it this way, though. (1) It would
mean we don't lie to the PM core for a brief while, saying that the root
hub is in FREEZE when it isn't. (2) The logic is located in this one
spot, instead of being copied (error-prone!) among a bunch of different
HCDs.
Or perhaps you were referring to the change I suggested to the
non-USB_SUSPEND version of usb_suspend_device? That won't help with this
problem, since without the change above that code wouldn't get called.
> > > This seems related to two OHCI regressions I noticed, by the way.
> > >
> > > In one case, resume-via-reset seems broken without CONFIG_USB_SUSPEND;
> > > the root hub timer doesn't restart correctly. (It tries to resubmit
> > > the URB while the hub is suspended, fails, then dies.) In the other,
> > > wakeup is broken since khubd never notices USB_PORT_STAT_C_SUSPEND;
> > > as if the root hub timer stopped (new behavior?) and didn't restart.
> >
> > It looks like the first problem is a logical error in the USB resume code:
> > Device states are set back to USB_STATE_CONFIGURED _after_ the devices are
> > resumed. Naturally, URBs can complete as soon as the physical resume is
> > done, and completion handlers may try to resubmit -- but they will fail
> > until the state is set back. Clearly the state needs to be changed
> > _before_ the resume is done.
>
> Sounds right, but I'll look at that again. There were (are!!) some
> funky interactions with root hubs; they've been getting less funky
> over time, and are soon (I hope!) to become even less funky.
Well, it was close but not quite right. I looked at the ohci_hub_suspend
and ohci_hub_resume routines; the problem seems to be that they set
hcd->state in the wrong place. For instance, the resume routine doesn't
set it back to HC_STATE_RUNNING until just before returning, but
port-change interrupts (which will trigger the completion and resubmission
of the status URB) can start up many milliseconds earlier.
In fact, it seems a little odd that the root-hub routines should affect
hcd->state. In the UHCI driver, only the HC routines change it. But of
course, that's a matter of personal programming style.
> > I don't understand the second problem. Why would you expect wakeup to
> > work when CONFIG_USB_SUSPEND isn't set? Why should it have to work at
> > all in that case?
>
> The second case assumed USB_SUSPEND, otherwise there'd be no wakeup!
> Sorry for the confusion. :)
Maybe fixing the first problem will cure the second problem too.
> > Maybe a better fix for this problem would be to make the non-USB_SUSPEND
> > version of usb_suspend_device more than just an empty placeholder.
>
> It's not empty ... it has a "return 0"! And a comment!!
By George, you're right about the "return 0"! But I don't see any
comments in the routine, although there is a comment on the "#else" line.
> Which is part of why your small patch above bothers me: it's NOP unless
> the USB_SUSPEND stuff is present. So the two paths would still act
> different, and HCDs would still need special casing.
>
>
> > If the
> > device is a root hub, do perform the hcd->hub_suspend call. And likewise
> > for usb_resume_device, of course. Then all that special indirect upstream
> > stuff could be removed from the HCDs.
>
> We do want to get rid of that special casing in the HCDs, yes. The sooner
> the better; it was expedient at the time (when hub_suspend was young, just
> last year!, and few HCDs supported it) but now it's just confusing.
If we make the second change (non-USB_SUSPEND version of
usb_suspend_device) then the first change (usb_generic_suspend) will no
longer be a NOP. Making _both_ changes will not only allow removal of the
special casing from the HCDs, it also means that the oddball
parallel-execution paths are localized to one spot, clearly marked by
#ifdef. Furthermore it puts the decision about how to handle a FREEZE
where it logically belongs, at the interface between usbcore and the PM
core. Above that point we have all the pm_state weirdness, while below it
there's nothing but USB suspend or resume.
Alan Stern
-------------------------------------------------------
SF.Net email is sponsored by:
Tame your development challenges with Apache's Geronimo App Server. Download
it for free - -and be entered to win a 42" plasma tv or your very own
Sony(tm)PSP. Click here to play: http://sourceforge.net/geronimo.php
_______________________________________________
[email protected]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel