Loading drivers/usb/dwc3/gadget.c +30 −8 Original line number Diff line number Diff line Loading @@ -2098,24 +2098,27 @@ static int dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on, int suspend) */ dwc3_stop_active_transfers(dwc); reg &= ~DWC3_DCTL_RUN_STOP; if (dwc->has_hibernation && !suspend) reg &= ~DWC3_DCTL_KEEP_CONNECT; } dwc3_writel(dwc->regs, DWC3_DCTL, reg); /* Controller is not halted until the events are acknowledged */ if (!is_on) { /* * Clear out any pending events (i.e. End Transfer Command * Complete) before clearing run/stop * Complete). */ reg1 = dwc3_readl(dwc->regs, DWC3_GEVNTCOUNT(0)); reg1 &= DWC3_GEVNTCOUNT_MASK; dbg_log_string("remaining EVNTCOUNT(0)=%d", reg1); dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(0), reg1); dwc3_notify_event(dwc, DWC3_GSI_EVT_BUF_CLEAR, 0); reg &= ~DWC3_DCTL_RUN_STOP; if (dwc->has_hibernation && !suspend) reg &= ~DWC3_DCTL_KEEP_CONNECT; } dwc3_writel(dwc->regs, DWC3_DCTL, reg); do { reg = dwc3_readl(dwc->regs, DWC3_DSTS); reg &= DWC3_DSTS_DEVCTRLHLT; Loading Loading @@ -3749,6 +3752,12 @@ 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) { dbg_event(0xFF, "NO_PULLUP", 0); 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 Loading @@ -3763,6 +3772,19 @@ static irqreturn_t dwc3_check_event_buf(struct dwc3_event_buffer *evt) if (!count) return IRQ_NONE; if (count > evt->length) { dbg_event(0xFF, "HUGE_EVCNT", count); /* * If writes from dwc3_interrupt and run_stop(0) races * with each other, the count can result in a very large * value.In that case setting the evt->lpos here * is a no-op. The value will be reset as part of run_stop(1). */ evt->lpos = (evt->lpos + count) % DWC3_EVENT_BUFFERS_SIZE; dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(0), count); return IRQ_HANDLED; } evt->count = count; evt->flags |= DWC3_EVENT_PENDING; Loading Loading
drivers/usb/dwc3/gadget.c +30 −8 Original line number Diff line number Diff line Loading @@ -2098,24 +2098,27 @@ static int dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on, int suspend) */ dwc3_stop_active_transfers(dwc); reg &= ~DWC3_DCTL_RUN_STOP; if (dwc->has_hibernation && !suspend) reg &= ~DWC3_DCTL_KEEP_CONNECT; } dwc3_writel(dwc->regs, DWC3_DCTL, reg); /* Controller is not halted until the events are acknowledged */ if (!is_on) { /* * Clear out any pending events (i.e. End Transfer Command * Complete) before clearing run/stop * Complete). */ reg1 = dwc3_readl(dwc->regs, DWC3_GEVNTCOUNT(0)); reg1 &= DWC3_GEVNTCOUNT_MASK; dbg_log_string("remaining EVNTCOUNT(0)=%d", reg1); dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(0), reg1); dwc3_notify_event(dwc, DWC3_GSI_EVT_BUF_CLEAR, 0); reg &= ~DWC3_DCTL_RUN_STOP; if (dwc->has_hibernation && !suspend) reg &= ~DWC3_DCTL_KEEP_CONNECT; } dwc3_writel(dwc->regs, DWC3_DCTL, reg); do { reg = dwc3_readl(dwc->regs, DWC3_DSTS); reg &= DWC3_DSTS_DEVCTRLHLT; Loading Loading @@ -3749,6 +3752,12 @@ 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) { dbg_event(0xFF, "NO_PULLUP", 0); 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 Loading @@ -3763,6 +3772,19 @@ static irqreturn_t dwc3_check_event_buf(struct dwc3_event_buffer *evt) if (!count) return IRQ_NONE; if (count > evt->length) { dbg_event(0xFF, "HUGE_EVCNT", count); /* * If writes from dwc3_interrupt and run_stop(0) races * with each other, the count can result in a very large * value.In that case setting the evt->lpos here * is a no-op. The value will be reset as part of run_stop(1). */ evt->lpos = (evt->lpos + count) % DWC3_EVENT_BUFFERS_SIZE; dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(0), count); return IRQ_HANDLED; } evt->count = count; evt->flags |= DWC3_EVENT_PENDING; Loading