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 majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to