On Fri, Oct 12, 2012 at 11:04:25AM -0400, Alan Stern wrote:
> 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.
I have tested it at Freescale i.mx6Q sabrelite board, your patch is ok.
Will you post a patch or I do it for you?

> 
> Alan Stern
> 
> 


-- 

Best Regards,
Peter Chen

--
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