diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 6627a79920c3..b0672c299a00 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -2082,7 +2082,18 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on) dev_err(dwc->dev, "timed out waiting for SETUP phase\n"); } + /* pull-up disable: clear pending events without queueing bh */ + dwc->pullups_connected = is_on; + + disable_irq(dwc->irq); + + /* prevent pending bh to run later */ + flush_work(&dwc->bh_work); + spin_lock_irqsave(&dwc->lock, flags); + if (dwc->ep0state != EP0_SETUP_PHASE) + dbg_event(0xFF, "EP0 is not in SETUP phase\n", 0); + /* * If we are here after bus suspend notify otg state machine to * increment pm usage count of dwc to prevent pm_runtime_suspend @@ -2093,6 +2104,7 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on) ret = dwc3_gadget_run_stop(dwc, is_on, false); spin_unlock_irqrestore(&dwc->lock, flags); + enable_irq(dwc->irq); pm_runtime_mark_last_busy(dwc->dev); pm_runtime_put_autosuspend(dwc->dev); @@ -3636,6 +3648,15 @@ static irqreturn_t dwc3_check_event_buf(struct dwc3_event_buffer *evt) if (dwc->err_evt_seen) return IRQ_HANDLED; + /* Controller is being halted, ignore the interrupts */ + if (!dwc->pullups_connected) { + count = dwc3_readl(dwc->regs, DWC3_GEVNTCOUNT(0)); + count &= DWC3_GEVNTCOUNT_MASK; + dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(0), count); + dbg_event(0xFF, "NO_PULLUP", count); + return IRQ_HANDLED; + } + /* * With PCIe legacy interrupt, test shows that top-half irq handler can * be called again after HW interrupt deassertion. Check if bottom-half