aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTony Lindgren <tony@atomide.com>2017-01-24 10:18:57 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-01-25 05:02:29 -0500
commit407788b51db6f6aab499d02420082f436abf3238 (patch)
treeb2fb3c885baf47cd2bd8ee0429f423b352e11905
parent7a308bb3016f57e5be11a677d15b821536419d36 (diff)
usb: musb: Fix host mode error -71 regression
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> Cc: stable <stable@vger.kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/usb/musb/musb_core.c15
-rw-r--r--drivers/usb/musb/musb_core.h1
2 files changed, 2 insertions, 14 deletions
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index fca288bbc800..cd40467be3c5 100644
--- 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,
594 | MUSB_PORT_STAT_RESUME; 594 | MUSB_PORT_STAT_RESUME;
595 musb->rh_timer = jiffies 595 musb->rh_timer = jiffies
596 + msecs_to_jiffies(USB_RESUME_TIMEOUT); 596 + msecs_to_jiffies(USB_RESUME_TIMEOUT);
597 musb->need_finish_resume = 1;
598
599 musb->xceiv->otg->state = OTG_STATE_A_HOST; 597 musb->xceiv->otg->state = OTG_STATE_A_HOST;
600 musb->is_active = 1; 598 musb->is_active = 1;
601 musb_host_resume_root_hub(musb); 599 musb_host_resume_root_hub(musb);
600 schedule_delayed_work(&musb->finish_resume_work,
601 msecs_to_jiffies(USB_RESUME_TIMEOUT));
602 break; 602 break;
603 case OTG_STATE_B_WAIT_ACON: 603 case OTG_STATE_B_WAIT_ACON:
604 musb->xceiv->otg->state = OTG_STATE_B_PERIPHERAL; 604 musb->xceiv->otg->state = OTG_STATE_B_PERIPHERAL;
@@ -2710,11 +2710,6 @@ static int musb_resume(struct device *dev)
2710 mask = MUSB_DEVCTL_BDEVICE | MUSB_DEVCTL_FSDEV | MUSB_DEVCTL_LSDEV; 2710 mask = MUSB_DEVCTL_BDEVICE | MUSB_DEVCTL_FSDEV | MUSB_DEVCTL_LSDEV;
2711 if ((devctl & mask) != (musb->context.devctl & mask)) 2711 if ((devctl & mask) != (musb->context.devctl & mask))
2712 musb->port1_status = 0; 2712 musb->port1_status = 0;
2713 if (musb->need_finish_resume) {
2714 musb->need_finish_resume = 0;
2715 schedule_delayed_work(&musb->finish_resume_work,
2716 msecs_to_jiffies(USB_RESUME_TIMEOUT));
2717 }
2718 2713
2719 /* 2714 /*
2720 * The USB HUB code expects the device to be in RPM_ACTIVE once it came 2715 * 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)
2766 2761
2767 musb_restore_context(musb); 2762 musb_restore_context(musb);
2768 2763
2769 if (musb->need_finish_resume) {
2770 musb->need_finish_resume = 0;
2771 schedule_delayed_work(&musb->finish_resume_work,
2772 msecs_to_jiffies(USB_RESUME_TIMEOUT));
2773 }
2774
2775 spin_lock_irqsave(&musb->lock, flags); 2764 spin_lock_irqsave(&musb->lock, flags);
2776 error = musb_run_resume_work(musb); 2765 error = musb_run_resume_work(musb);
2777 if (error) 2766 if (error)
diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h
index ade902ea1221..ce5a18c98c6d 100644
--- a/drivers/usb/musb/musb_core.h
+++ b/drivers/usb/musb/musb_core.h
@@ -410,7 +410,6 @@ struct musb {
410 410
411 /* is_suspended means USB B_PERIPHERAL suspend */ 411 /* is_suspended means USB B_PERIPHERAL suspend */
412 unsigned is_suspended:1; 412 unsigned is_suspended:1;
413 unsigned need_finish_resume :1;
414 413
415 /* may_wakeup means remote wakeup is enabled */ 414 /* may_wakeup means remote wakeup is enabled */
416 unsigned may_wakeup:1; 415 unsigned may_wakeup:1;