aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/dwc2/core_intr.c
diff options
context:
space:
mode:
authorGregory Herrero <gregory.herrero@intel.com>2015-04-29 22:09:03 +0200
committerFelipe Balbi <balbi@ti.com>2015-04-29 15:18:49 -0500
commit3eb42df3ebfbd8d46b831c26ecb90e128ad474a5 (patch)
treec2a2c523d1599779d44e992b79375e8017aff440 /drivers/usb/dwc2/core_intr.c
parentusb: dwc2: implement hibernation during bus suspend/resume (diff)
downloadlinux-dev-3eb42df3ebfbd8d46b831c26ecb90e128ad474a5.tar.xz
linux-dev-3eb42df3ebfbd8d46b831c26ecb90e128ad474a5.zip
usb: dwc2: controller must update lx_state before releasing lock
During suspend, there could a race condition between ep_queue and suspend interrupt if lx_state is updated after releasing spinlock in call_gadget(hsotg, suspend). Acked-by: John Youn <johnyoun@synopsys.com> Signed-off-by: Gregory Herrero <gregory.herrero@intel.com> Signed-off-by: Felipe Balbi <balbi@ti.com>
Diffstat (limited to 'drivers/usb/dwc2/core_intr.c')
-rw-r--r--drivers/usb/dwc2/core_intr.c11
1 files changed, 8 insertions, 3 deletions
diff --git a/drivers/usb/dwc2/core_intr.c b/drivers/usb/dwc2/core_intr.c
index 6ffb5a9c385e..0b7f2b2e580e 100644
--- a/drivers/usb/dwc2/core_intr.c
+++ b/drivers/usb/dwc2/core_intr.c
@@ -439,6 +439,12 @@ static void dwc2_handle_usb_suspend_intr(struct dwc2_hsotg *hsotg)
if (!IS_ERR_OR_NULL(hsotg->uphy))
usb_phy_set_suspend(hsotg->uphy, true);
skip_power_saving:
+ /*
+ * Change to L2 (suspend) state before releasing
+ * spinlock
+ */
+ hsotg->lx_state = DWC2_L2;
+
/* Call gadget suspend callback */
call_gadget(hsotg, suspend);
}
@@ -446,6 +452,8 @@ skip_power_saving:
if (hsotg->op_state == OTG_STATE_A_PERIPHERAL) {
dev_dbg(hsotg->dev, "a_peripheral->a_host\n");
+ /* Change to L2 (suspend) state */
+ hsotg->lx_state = DWC2_L2;
/* Clear the a_peripheral flag, back to a_host */
spin_unlock(&hsotg->lock);
dwc2_hcd_start(hsotg);
@@ -454,9 +462,6 @@ skip_power_saving:
}
}
- /* Change to L2 (suspend) state */
- hsotg->lx_state = DWC2_L2;
-
clear_int:
/* Clear interrupt */
writel(GINTSTS_USBSUSP, hsotg->regs + GINTSTS);