usb: musb: Fix host mode error -71 regression
Commit467d5c9807
("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 commit9298b4aad3
("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:467d5c9807
("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>
This commit is contained in:
parent
7a308bb301
commit
407788b51d
@ -594,11 +594,11 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
|
|||||||
| MUSB_PORT_STAT_RESUME;
|
| MUSB_PORT_STAT_RESUME;
|
||||||
musb->rh_timer = jiffies
|
musb->rh_timer = jiffies
|
||||||
+ msecs_to_jiffies(USB_RESUME_TIMEOUT);
|
+ msecs_to_jiffies(USB_RESUME_TIMEOUT);
|
||||||
musb->need_finish_resume = 1;
|
|
||||||
|
|
||||||
musb->xceiv->otg->state = OTG_STATE_A_HOST;
|
musb->xceiv->otg->state = OTG_STATE_A_HOST;
|
||||||
musb->is_active = 1;
|
musb->is_active = 1;
|
||||||
musb_host_resume_root_hub(musb);
|
musb_host_resume_root_hub(musb);
|
||||||
|
schedule_delayed_work(&musb->finish_resume_work,
|
||||||
|
msecs_to_jiffies(USB_RESUME_TIMEOUT));
|
||||||
break;
|
break;
|
||||||
case OTG_STATE_B_WAIT_ACON:
|
case OTG_STATE_B_WAIT_ACON:
|
||||||
musb->xceiv->otg->state = OTG_STATE_B_PERIPHERAL;
|
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;
|
mask = MUSB_DEVCTL_BDEVICE | MUSB_DEVCTL_FSDEV | MUSB_DEVCTL_LSDEV;
|
||||||
if ((devctl & mask) != (musb->context.devctl & mask))
|
if ((devctl & mask) != (musb->context.devctl & mask))
|
||||||
musb->port1_status = 0;
|
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
|
* 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);
|
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);
|
spin_lock_irqsave(&musb->lock, flags);
|
||||||
error = musb_run_resume_work(musb);
|
error = musb_run_resume_work(musb);
|
||||||
if (error)
|
if (error)
|
||||||
|
@ -410,7 +410,6 @@ struct musb {
|
|||||||
|
|
||||||
/* is_suspended means USB B_PERIPHERAL suspend */
|
/* is_suspended means USB B_PERIPHERAL suspend */
|
||||||
unsigned is_suspended:1;
|
unsigned is_suspended:1;
|
||||||
unsigned need_finish_resume :1;
|
|
||||||
|
|
||||||
/* may_wakeup means remote wakeup is enabled */
|
/* may_wakeup means remote wakeup is enabled */
|
||||||
unsigned may_wakeup:1;
|
unsigned may_wakeup:1;
|
||||||
|
Loading…
Reference in New Issue
Block a user