diff options
author | Grygorii Strashko <grygorii.strashko@ti.com> | 2016-12-12 19:37:52 (GMT) |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2017-08-07 01:59:46 (GMT) |
commit | 8af0937aee50d1d1f41f1caf56aefcf364d3b1b9 (patch) | |
tree | d32ec4a33dd639812f1dda8333713d350367a903 /drivers/usb/dwc3 | |
parent | 29e0adf8bacd3cb91893ec90eb6a61d938209a24 (diff) | |
download | linux-8af0937aee50d1d1f41f1caf56aefcf364d3b1b9.tar.xz |
usb: dwc3: omap: fix race of pm runtime with irq handler in probe
[ Upstream commit 12a7f17fac5b370bec87259e4c718faf563ce900 ]
Now races can happen between interrupt handler execution and PM runtime in
error handling code path in probe and in dwc3_omap_remove() which will lead
to system crash:
in probe:
...
err1:
pm_runtime_put_sync(dev);
^^ PM runtime can race with IRQ handler when deferred probing happening
due to extcon
pm_runtime_disable(dev);
return ret;
in dwc3_omap_remove:
...
dwc3_omap_disable_irqs(omap);
^^ IRQs are disabled in HW, but handler may still run
of_platform_depopulate(omap->dev);
pm_runtime_put_sync(&pdev->dev);
^^ PM runtime can race with IRQ handler
pm_runtime_disable(&pdev->dev);
return 0;
So, OMAP DWC3 IRQ need to be disabled before calling
pm_runtime_put() in probe and in dwc3_omap_remove().
Acked-by: Tony Lindgren <tony@atomide.com>
Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/dwc3')
-rw-r--r-- | drivers/usb/dwc3/dwc3-omap.c | 6 |
1 files changed, 4 insertions, 2 deletions
diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c index 5dd1832..35b6351 100644 --- a/drivers/usb/dwc3/dwc3-omap.c +++ b/drivers/usb/dwc3/dwc3-omap.c @@ -19,6 +19,7 @@ #include <linux/module.h> #include <linux/kernel.h> #include <linux/slab.h> +#include <linux/irq.h> #include <linux/interrupt.h> #include <linux/platform_device.h> #include <linux/platform_data/dwc3-omap.h> @@ -511,7 +512,7 @@ static int dwc3_omap_probe(struct platform_device *pdev) /* check the DMA Status */ reg = dwc3_omap_readl(omap->base, USBOTGSS_SYSCONFIG); - + irq_set_status_flags(omap->irq, IRQ_NOAUTOEN); ret = devm_request_threaded_irq(dev, omap->irq, dwc3_omap_interrupt, dwc3_omap_interrupt_thread, IRQF_SHARED, "dwc3-omap", omap); @@ -532,7 +533,7 @@ static int dwc3_omap_probe(struct platform_device *pdev) } dwc3_omap_enable_irqs(omap); - + enable_irq(omap->irq); return 0; err2: @@ -553,6 +554,7 @@ static int dwc3_omap_remove(struct platform_device *pdev) extcon_unregister_notifier(omap->edev, EXTCON_USB, &omap->vbus_nb); extcon_unregister_notifier(omap->edev, EXTCON_USB_HOST, &omap->id_nb); dwc3_omap_disable_irqs(omap); + disable_irq(omap->irq); of_platform_depopulate(omap->dev); pm_runtime_put_sync(&pdev->dev); pm_runtime_disable(&pdev->dev); |