[PATCH 0/3] USB: fix race between root-hub suspend and remote wakeup

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

 



Greg:

The following series of patches fixes an outstanding race between
suspending a root hub and getting a wakeup event on any of the root
hub's ports.

Currently we don't handle these races very well.  The host controller
drivers check for some wakeup events before starting a suspend but not
for all (e.g., they check for port resume in progress but not port
connect change).  Also, the drivers don't check for wakeup events that
occur while the root hub is being suspended, or events that occurred
before the suspend began but have not yet been handled.

The first patch fixes the general problem by making 
usb_hcd_bus_suspend() query each HCD's hub_status_data method after 
suspending its root hub, if that root hub is enabled for wakeup.  A 
nonzero return value, indicating that a status change is pending, will 
cause the root hub to be resumed and the suspend attempt to fail with 
-EBUSY.

The second and third patches make some necessary adjustments to
ehci-hcd and uhci-hcd.  Right now the hub_status_data methods return a
nonzero value only when some of the status bits are set.  However, in
the case of a remote wakeup request received from downstream, the
port's suspend-change status bit doesn't get set until _after_ the port
resume is complete, which is at least 25 ms after the CPU is notified
about the wakeup request.  The patches make the hub_status_data methods
return nonzero while the port resume is in progress, even if none of
the status bits are set.

Although I'm not familiar with the details of xhci-hcd's root-hub
management, I assume that it will need adjustments quite similar to
those for ehci-hcd.  Sarah, please take note.  For the most part, you
or Andiry ought to be able to copy the changes I made -- they are
pretty simple.

The MUSB driver and others may need a similar change, or they may not.  
I don't know enough about them to say.

No analogous adjustment is needed for ohci-hcd, because the OHCI
hardware doesn't notify the CPU until after the entire port-resume
procedure is finished.

In theory the same is true for external hubs, although here the
situation isn't quite so straightforward.  An external hub will
continue to indicate a port status change until the hub driver
explicitly clears the status-change bit (unlike OHCI controllers, which
have Root Hub Status Change and Resume Detected interrupt bits that are
separate from the Port Connect Status Change and Port Suspend Status
Change bits).

If a USB-1.1 or USB-2.0 hub is suspended with a status-change bit set,
it will immediately generate a wakeup request. That's what the spec
says, at least -- in practice I have found hubs that don't do this.  
No way to work around such bugs, though; we can't query a hub's port
statuses while the hub is suspended.

USB-3.0 hubs may also require special attention.  In this case the
problem goes deeper; the spec itself does not say what a hub is
supposed to do when suspended while a port is resumed or resuming.

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