summaryrefslogtreecommitdiff
path: root/drivers/staging/dwc2/core.c
diff options
context:
space:
mode:
authorMatthijs Kooijman <matthijs@stdin.nl>2013-04-11 15:52:41 (GMT)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-04-11 19:58:39 (GMT)
commit6706c721b22aadffbffec7550b81efedddd05cfb (patch)
treee763faf21c606750ae874fcd45258744f6fd1116 /drivers/staging/dwc2/core.c
parent7c360aa7cd6b469671fc2ea7a889516095cd0efe (diff)
downloadlinux-fsl-qoriq-6706c721b22aadffbffec7550b81efedddd05cfb.tar.xz
staging: dwc2: register common irq handler in dwc2_core_init
Before, this was initialized in pci.c, after the dwc2_hcd_init was called and the interrupts were enabled. This opened up a small time window where common interrupts could be triggered, but there was no handler for them, causing them to keep triggering infinitely and locking up the machine. On my RT3052 board this bug could be easily reproduced by hardcoding the console log level to 8, so that a bunch of debug output from the dwc2 driver was generated inside this time window. This caused the interrupt lockup to occur almost every time. By requesting the irq inside dwc2_core_init and by disabling interrupts before calling dwc2_core_init instead of after, we can be sure the handler is registered before the interrupts are enabled, which should close this window. Reported-by: Stephen Warren <swarren@wwwdotorg.org> Signed-off-by: Matthijs Kooijman <matthijs@stdin.nl> Acked-by: Paul Zimmerman <paulz@synopsys.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/staging/dwc2/core.c')
-rw-r--r--drivers/staging/dwc2/core.c13
1 files changed, 12 insertions, 1 deletions
diff --git a/drivers/staging/dwc2/core.c b/drivers/staging/dwc2/core.c
index 549cd3d..3177db2 100644
--- a/drivers/staging/dwc2/core.c
+++ b/drivers/staging/dwc2/core.c
@@ -365,8 +365,9 @@ static void dwc2_gusbcfg_init(struct dwc2_hsotg *hsotg)
*
* @hsotg: Programming view of the DWC_otg controller
* @select_phy: If true then also set the Phy type
+ * @irq: If >= 0, the irq to register
*/
-int dwc2_core_init(struct dwc2_hsotg *hsotg, bool select_phy)
+int dwc2_core_init(struct dwc2_hsotg *hsotg, bool select_phy, int irq)
{
u32 usbcfg, otgctl;
int retval;
@@ -430,6 +431,16 @@ int dwc2_core_init(struct dwc2_hsotg *hsotg, bool select_phy)
/* Clear the SRP success bit for FS-I2c */
hsotg->srp_success = 0;
+ if (irq >= 0) {
+ dev_dbg(hsotg->dev, "registering common handler for irq%d\n",
+ irq);
+ retval = devm_request_irq(hsotg->dev, irq,
+ dwc2_handle_common_intr, IRQF_SHARED,
+ dev_name(hsotg->dev), hsotg);
+ if (retval)
+ return retval;
+ }
+
/* Enable common interrupts */
dwc2_enable_common_interrupts(hsotg);