On Fri, 12 Oct 2012, Peter Chen wrote:
> Taking EHCI controller as an example, it just needs to change ehci_bus_resume,
> if there is any enabled, unsuspended port, set hcd->unsuspended_device_on_port
We don't need to do that. See below.
> > usb_bus_resume() can poll the port statuses to see if there are any
> > enabled, unsuspended ports. If there aren't any, the delay can be
> > skipped.
> Taking EHCI controller as an example, you mean:
>
> - Change hcd_bus_resume like below:
>
> status = hcd->driver->bus_resume(hcd);
> clear_bit(HCD_FLAG_WAKEUP_PENDING, &hcd->flags);
> if (status == 0) {
> char buffer[6];
>
> status = hcd->driver->hub_status_data(hcd, buffer);
> if (status != 0) {
> /* There are any enabled unsuspended ports */
> /* TRSMRCY = 10 msec */
> msleep(10);
> spin_lock_irq(&hcd_root_hub_lock);
> - Add get any enabled, unsuspended port as port change condition at
> ehci_hub_status_data.
No, like this:
--- usb-3.6.orig/drivers/usb/core/hcd.c
+++ usb-3.6/drivers/usb/core/hcd.c
@@ -2023,6 +2023,7 @@ int hcd_bus_resume(struct usb_device *rh
struct usb_hcd *hcd = container_of(rhdev->bus, struct usb_hcd, self);
int status;
int old_state = hcd->state;
+ int port1;
dev_dbg(&rhdev->dev, "usb %sresume\n",
(PMSG_IS_AUTO(msg) ? "auto-" : ""));
@@ -2039,8 +2040,6 @@ int hcd_bus_resume(struct usb_device *rh
status = hcd->driver->bus_resume(hcd);
clear_bit(HCD_FLAG_WAKEUP_PENDING, &hcd->flags);
if (status == 0) {
- /* TRSMRCY = 10 msec */
- msleep(10);
spin_lock_irq(&hcd_root_hub_lock);
if (!HCD_DEAD(hcd)) {
usb_set_device_state(rhdev, rhdev->actconfig
@@ -2050,6 +2049,22 @@ int hcd_bus_resume(struct usb_device *rh
hcd->state = HC_STATE_RUNNING;
}
spin_unlock_irq(&hcd_root_hub_lock);
+
+ /* Any enabled non-suspended port requires TRSMRCY delay */
+ for (port1 = 1; port1 <= rhdev->maxchild; ++port1) {
+ __le16 buf[2];
+ unsigned pstatus;
+
+ buf[0] = 0;
+ hcd->driver->hub_control(hcd, USB_DIR_IN | USB_RT_PORT,
+ 0, port1, (char *) buf, 4);
+ pstatus = le16_to_cpu(buf[0]);
+ if ((pstatus & USB_PORT_STAT_ENABLE) &&
+ !(pstatus & USB_PORT_STAT_SUSPEND)) {
+ msleep(10); /* TRSMRCY */
+ break;
+ }
+ }
} else {
hcd->state = old_state;
dev_dbg(&rhdev->dev, "bus %s fail, err %d\n",
I haven't tested this, just compiled it.
Alan Stern
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html