On Wed, Jan 18, 2017 at 06:29:58PM -0800, Tony Lindgren wrote:
> Commit 467d5c980709 ("usb: musb: Implement session bit based runtime PM for
> musb-core") started implementing musb generic runtime PM support by
> introducing devctl register session bit based state control.
>
> This caused a regression where if a USB mass storage device is connected
> to a USB hub, we can get:
>
> usb 1-1: reset high-speed USB device number 2 using musb-hdrc
> usb 1-1: device descriptor read/64, error -71
> usb 1-1.1: new high-speed USB device number 4 using musb-hdrc
>
> This is because before the USB storage device is connected, musb is
> in OTG_STATE_A_SUSPEND. And we currently only set need_finish_resume
> in musb_stage0_irq() and the related code calling finish_resume_work
> in musb_resume() and musb_runtime_resume() never gets called.
>
> To fix the issue, we can call schedule_delayed_work() directly in
> musb_stage0_irq() to have finish_resume_work run.
>
> And we should no longer never get interrupts when when suspended.
> We have changed musb to no longer need pm_runtime_irqsafe().
> The need_finish_resume flag was added in commit 9298b4aad37e ("usb:
> musb: fix device hotplug behind hub") and no longer applies as far
> as I can tell. So let's just remove the earlier code that no longer
> is needed.
>
> Fixes: 467d5c980709 ("usb: musb: Implement session bit based
> runtime PM for musb-core")
> Reported-by: Bin Liu <[email protected]>
> Signed-off-by: Tony Lindgren <[email protected]>
Applied. Thanks.
-Bin.
> ---
> drivers/usb/musb/musb_core.c | 15 ++-------------
> drivers/usb/musb/musb_core.h | 1 -
> 2 files changed, 2 insertions(+), 14 deletions(-)
>
> diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
> --- a/drivers/usb/musb/musb_core.c
> +++ b/drivers/usb/musb/musb_core.c
> @@ -594,11 +594,11 @@ static irqreturn_t musb_stage0_irq(struct musb *musb,
> u8 int_usb,
> | MUSB_PORT_STAT_RESUME;
> musb->rh_timer = jiffies
> + msecs_to_jiffies(USB_RESUME_TIMEOUT);
> - musb->need_finish_resume = 1;
> -
> musb->xceiv->otg->state = OTG_STATE_A_HOST;
> musb->is_active = 1;
> musb_host_resume_root_hub(musb);
> + schedule_delayed_work(&musb->finish_resume_work,
> + msecs_to_jiffies(USB_RESUME_TIMEOUT));
> break;
> case OTG_STATE_B_WAIT_ACON:
> musb->xceiv->otg->state =
> OTG_STATE_B_PERIPHERAL;
> @@ -2710,11 +2710,6 @@ static int musb_resume(struct device *dev)
> mask = MUSB_DEVCTL_BDEVICE | MUSB_DEVCTL_FSDEV | MUSB_DEVCTL_LSDEV;
> if ((devctl & mask) != (musb->context.devctl & mask))
> musb->port1_status = 0;
> - if (musb->need_finish_resume) {
> - musb->need_finish_resume = 0;
> - schedule_delayed_work(&musb->finish_resume_work,
> - msecs_to_jiffies(USB_RESUME_TIMEOUT));
> - }
>
> /*
> * The USB HUB code expects the device to be in RPM_ACTIVE once it came
> @@ -2766,12 +2761,6 @@ static int musb_runtime_resume(struct device *dev)
>
> musb_restore_context(musb);
>
> - if (musb->need_finish_resume) {
> - musb->need_finish_resume = 0;
> - schedule_delayed_work(&musb->finish_resume_work,
> - msecs_to_jiffies(USB_RESUME_TIMEOUT));
> - }
> -
> spin_lock_irqsave(&musb->lock, flags);
> error = musb_run_resume_work(musb);
> if (error)
> diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h
> --- a/drivers/usb/musb/musb_core.h
> +++ b/drivers/usb/musb/musb_core.h
> @@ -410,7 +410,6 @@ struct musb {
>
> /* is_suspended means USB B_PERIPHERAL suspend */
> unsigned is_suspended:1;
> - unsigned need_finish_resume :1;
>
> /* may_wakeup means remote wakeup is enabled */
> unsigned may_wakeup:1;
> --
> 2.11.0
--
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