usb: dwc3: omap: fix race of pm runtime with irq handler in probe
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>
This commit is contained in:
Родитель
890e6c236d
Коммит
12a7f17fac
|
@ -19,6 +19,7 @@
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
|
#include <linux/irq.h>
|
||||||
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
#include <linux/platform_data/dwc3-omap.h>
|
#include <linux/platform_data/dwc3-omap.h>
|
||||||
|
@ -510,7 +511,7 @@ static int dwc3_omap_probe(struct platform_device *pdev)
|
||||||
|
|
||||||
/* check the DMA Status */
|
/* check the DMA Status */
|
||||||
reg = dwc3_omap_readl(omap->base, USBOTGSS_SYSCONFIG);
|
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,
|
ret = devm_request_threaded_irq(dev, omap->irq, dwc3_omap_interrupt,
|
||||||
dwc3_omap_interrupt_thread, IRQF_SHARED,
|
dwc3_omap_interrupt_thread, IRQF_SHARED,
|
||||||
"dwc3-omap", omap);
|
"dwc3-omap", omap);
|
||||||
|
@ -531,7 +532,7 @@ static int dwc3_omap_probe(struct platform_device *pdev)
|
||||||
}
|
}
|
||||||
|
|
||||||
dwc3_omap_enable_irqs(omap);
|
dwc3_omap_enable_irqs(omap);
|
||||||
|
enable_irq(omap->irq);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err2:
|
err2:
|
||||||
|
@ -552,6 +553,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, &omap->vbus_nb);
|
||||||
extcon_unregister_notifier(omap->edev, EXTCON_USB_HOST, &omap->id_nb);
|
extcon_unregister_notifier(omap->edev, EXTCON_USB_HOST, &omap->id_nb);
|
||||||
dwc3_omap_disable_irqs(omap);
|
dwc3_omap_disable_irqs(omap);
|
||||||
|
disable_irq(omap->irq);
|
||||||
of_platform_depopulate(omap->dev);
|
of_platform_depopulate(omap->dev);
|
||||||
pm_runtime_put_sync(&pdev->dev);
|
pm_runtime_put_sync(&pdev->dev);
|
||||||
pm_runtime_disable(&pdev->dev);
|
pm_runtime_disable(&pdev->dev);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче