Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 407788b5 authored by Tony Lindgren's avatar Tony Lindgren Committed by Greg Kroah-Hartman
Browse files

usb: musb: Fix host mode error -71 regression



Commit 467d5c98 ("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 9298b4aa ("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: 467d5c98 ("usb: musb: Implement session bit based runtime PM for musb-core")
Reported-by: default avatarBin Liu <b-liu@ti.com>
Signed-off-by: default avatarTony Lindgren <tony@atomide.com>
Signed-off-by: default avatarBin Liu <b-liu@ti.com>
Cc: stable <stable@vger.kernel.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 7a308bb3
Loading
Loading
Loading
Loading
+2 −13
Original line number Diff line number Diff line
@@ -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)
+0 −1
Original line number Diff line number Diff line
@@ -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;