| From 407788b51db6f6aab499d02420082f436abf3238 Mon Sep 17 00:00:00 2001 |
| From: Tony Lindgren <tony@atomide.com> |
| Date: Tue, 24 Jan 2017 09:18:57 -0600 |
| Subject: usb: musb: Fix host mode error -71 regression |
| |
| From: Tony Lindgren <tony@atomide.com> |
| |
| commit 407788b51db6f6aab499d02420082f436abf3238 upstream. |
| |
| 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 <b-liu@ti.com> |
| Signed-off-by: Tony Lindgren <tony@atomide.com> |
| Signed-off-by: Bin Liu <b-liu@ti.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/usb/musb/musb_core.c | 15 ++------------- |
| drivers/usb/musb/musb_core.h | 1 - |
| 2 files changed, 2 insertions(+), 14 deletions(-) |
| |
| --- a/drivers/usb/musb/musb_core.c |
| +++ b/drivers/usb/musb/musb_core.c |
| @@ -578,11 +578,11 @@ static irqreturn_t musb_stage0_irq(struc |
| | 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; |
| @@ -2691,11 +2691,6 @@ static int musb_resume(struct device *de |
| 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 |
| @@ -2747,12 +2742,6 @@ static int musb_runtime_resume(struct de |
| |
| 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) |
| --- 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; |