Loading drivers/usb/dwc3/gadget.c +70 −21 Original line number Diff line number Diff line Loading @@ -811,39 +811,39 @@ static void dwc3_remove_requests(struct dwc3 *dwc, struct dwc3_ep *dep) dwc3_stop_active_transfer(dep, true, false); if (dep->number == 1 && dwc->ep0state != EP0_SETUP_PHASE) { unsigned int dir; dbg_log_string("CTRLPEND", dwc->ep0state); dir = !!dwc->ep0_expect_in; if (dwc->ep0state == EP0_DATA_PHASE) dwc3_ep0_end_control_data(dwc, dwc->eps[dir]); else dwc3_ep0_end_control_data(dwc, dwc->eps[!dir]); dwc->eps[0]->trb_enqueue = 0; dwc->eps[1]->trb_enqueue = 0; } /* - giveback all requests to gadget driver */ while (!list_empty(&dep->started_list)) { req = next_request(&dep->started_list); if (req) dwc3_gadget_giveback(dep, req, -ESHUTDOWN); } while (!list_empty(&dep->pending_list)) { req = next_request(&dep->pending_list); if (req) dwc3_gadget_giveback(dep, req, -ESHUTDOWN); } while (!list_empty(&dep->cancelled_list)) { req = next_request(&dep->cancelled_list); if (req) dwc3_gadget_giveback(dep, req, -ESHUTDOWN); } if (dep->number == 1 && dwc->ep0state != EP0_SETUP_PHASE) { unsigned int dir; dbg_log_string("CTRLPEND", dwc->ep0state); dir = !!dwc->ep0_expect_in; if (dwc->ep0state == EP0_DATA_PHASE) dwc3_ep0_end_control_data(dwc, dwc->eps[dir]); else dwc3_ep0_end_control_data(dwc, dwc->eps[!dir]); dwc->eps[0]->trb_enqueue = 0; dwc->eps[1]->trb_enqueue = 0; } dbg_log_string("DONE for %s(%d)", dep->name, dep->number); } Loading Loading @@ -1980,6 +1980,38 @@ static void dwc3_stop_active_transfers(struct dwc3 *dwc) } } /** * dwc3_device_core_soft_reset - Issues device core soft reset * @dwc: pointer to our context structure */ static int dwc3_device_core_soft_reset(struct dwc3 *dwc) { u32 reg; int retries = 10; reg = dwc3_readl(dwc->regs, DWC3_DCTL); reg |= DWC3_DCTL_CSFTRST; dwc3_writel(dwc->regs, DWC3_DCTL, reg); do { reg = dwc3_readl(dwc->regs, DWC3_DCTL); if (!(reg & DWC3_DCTL_CSFTRST)) goto done; usleep_range(1000, 1100); } while (--retries); dev_err(dwc->dev, "%s timedout\n", __func__); return -ETIMEDOUT; done: /* phy sync delay as per data book */ msleep(50); return 0; } static int dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on, int suspend) { u32 reg, reg1; Loading Loading @@ -2142,6 +2174,10 @@ 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); if (!is_on && ret == -ETIMEDOUT) { dev_err(dwc->dev, "%s: Core soft reset...\n", __func__); dwc3_device_core_soft_reset(dwc); } enable_irq(dwc->irq); pm_runtime_mark_last_busy(dwc->dev); Loading Loading @@ -2226,6 +2262,7 @@ static int dwc3_gadget_vbus_session(struct usb_gadget *_gadget, int is_active) { struct dwc3 *dwc = gadget_to_dwc(_gadget); unsigned long flags; int ret = 0; if (dwc->dr_mode != USB_DR_MODE_OTG) return -EPERM; Loading @@ -2233,6 +2270,11 @@ static int dwc3_gadget_vbus_session(struct usb_gadget *_gadget, int is_active) is_active = !!is_active; dbg_event(0xFF, "VbusSess", is_active); disable_irq(dwc->irq); flush_work(&dwc->bh_work); spin_lock_irqsave(&dwc->lock, flags); /* Mark that the vbus was powered */ Loading @@ -2248,9 +2290,9 @@ static int dwc3_gadget_vbus_session(struct usb_gadget *_gadget, int is_active) * Both vbus was activated by otg and pullup was * signaled by the gadget driver. */ dwc3_gadget_run_stop(dwc, 1, false); ret = dwc3_gadget_run_stop(dwc, 1, false); } else { dwc3_gadget_run_stop(dwc, 0, false); ret = dwc3_gadget_run_stop(dwc, 0, false); } } Loading @@ -2264,6 +2306,13 @@ static int dwc3_gadget_vbus_session(struct usb_gadget *_gadget, int is_active) } spin_unlock_irqrestore(&dwc->lock, flags); if (!is_active && ret == -ETIMEDOUT) { dev_err(dwc->dev, "%s: Core soft reset...\n", __func__); dwc3_device_core_soft_reset(dwc); } enable_irq(dwc->irq); return 0; } Loading Loading
drivers/usb/dwc3/gadget.c +70 −21 Original line number Diff line number Diff line Loading @@ -811,39 +811,39 @@ static void dwc3_remove_requests(struct dwc3 *dwc, struct dwc3_ep *dep) dwc3_stop_active_transfer(dep, true, false); if (dep->number == 1 && dwc->ep0state != EP0_SETUP_PHASE) { unsigned int dir; dbg_log_string("CTRLPEND", dwc->ep0state); dir = !!dwc->ep0_expect_in; if (dwc->ep0state == EP0_DATA_PHASE) dwc3_ep0_end_control_data(dwc, dwc->eps[dir]); else dwc3_ep0_end_control_data(dwc, dwc->eps[!dir]); dwc->eps[0]->trb_enqueue = 0; dwc->eps[1]->trb_enqueue = 0; } /* - giveback all requests to gadget driver */ while (!list_empty(&dep->started_list)) { req = next_request(&dep->started_list); if (req) dwc3_gadget_giveback(dep, req, -ESHUTDOWN); } while (!list_empty(&dep->pending_list)) { req = next_request(&dep->pending_list); if (req) dwc3_gadget_giveback(dep, req, -ESHUTDOWN); } while (!list_empty(&dep->cancelled_list)) { req = next_request(&dep->cancelled_list); if (req) dwc3_gadget_giveback(dep, req, -ESHUTDOWN); } if (dep->number == 1 && dwc->ep0state != EP0_SETUP_PHASE) { unsigned int dir; dbg_log_string("CTRLPEND", dwc->ep0state); dir = !!dwc->ep0_expect_in; if (dwc->ep0state == EP0_DATA_PHASE) dwc3_ep0_end_control_data(dwc, dwc->eps[dir]); else dwc3_ep0_end_control_data(dwc, dwc->eps[!dir]); dwc->eps[0]->trb_enqueue = 0; dwc->eps[1]->trb_enqueue = 0; } dbg_log_string("DONE for %s(%d)", dep->name, dep->number); } Loading Loading @@ -1980,6 +1980,38 @@ static void dwc3_stop_active_transfers(struct dwc3 *dwc) } } /** * dwc3_device_core_soft_reset - Issues device core soft reset * @dwc: pointer to our context structure */ static int dwc3_device_core_soft_reset(struct dwc3 *dwc) { u32 reg; int retries = 10; reg = dwc3_readl(dwc->regs, DWC3_DCTL); reg |= DWC3_DCTL_CSFTRST; dwc3_writel(dwc->regs, DWC3_DCTL, reg); do { reg = dwc3_readl(dwc->regs, DWC3_DCTL); if (!(reg & DWC3_DCTL_CSFTRST)) goto done; usleep_range(1000, 1100); } while (--retries); dev_err(dwc->dev, "%s timedout\n", __func__); return -ETIMEDOUT; done: /* phy sync delay as per data book */ msleep(50); return 0; } static int dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on, int suspend) { u32 reg, reg1; Loading Loading @@ -2142,6 +2174,10 @@ 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); if (!is_on && ret == -ETIMEDOUT) { dev_err(dwc->dev, "%s: Core soft reset...\n", __func__); dwc3_device_core_soft_reset(dwc); } enable_irq(dwc->irq); pm_runtime_mark_last_busy(dwc->dev); Loading Loading @@ -2226,6 +2262,7 @@ static int dwc3_gadget_vbus_session(struct usb_gadget *_gadget, int is_active) { struct dwc3 *dwc = gadget_to_dwc(_gadget); unsigned long flags; int ret = 0; if (dwc->dr_mode != USB_DR_MODE_OTG) return -EPERM; Loading @@ -2233,6 +2270,11 @@ static int dwc3_gadget_vbus_session(struct usb_gadget *_gadget, int is_active) is_active = !!is_active; dbg_event(0xFF, "VbusSess", is_active); disable_irq(dwc->irq); flush_work(&dwc->bh_work); spin_lock_irqsave(&dwc->lock, flags); /* Mark that the vbus was powered */ Loading @@ -2248,9 +2290,9 @@ static int dwc3_gadget_vbus_session(struct usb_gadget *_gadget, int is_active) * Both vbus was activated by otg and pullup was * signaled by the gadget driver. */ dwc3_gadget_run_stop(dwc, 1, false); ret = dwc3_gadget_run_stop(dwc, 1, false); } else { dwc3_gadget_run_stop(dwc, 0, false); ret = dwc3_gadget_run_stop(dwc, 0, false); } } Loading @@ -2264,6 +2306,13 @@ static int dwc3_gadget_vbus_session(struct usb_gadget *_gadget, int is_active) } spin_unlock_irqrestore(&dwc->lock, flags); if (!is_active && ret == -ETIMEDOUT) { dev_err(dwc->dev, "%s: Core soft reset...\n", __func__); dwc3_device_core_soft_reset(dwc); } enable_irq(dwc->irq); return 0; } Loading