X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=drivers%2Fusb%2Fdwc3%2Fgadget.c;h=3399679513a8a310ca50156cce5642ea4572004a;hb=HEAD;hp=d7d1facc04a5984d6dbfb68ec44ea02c6597ec97;hpb=c7f6878fb82e709d17a029f9b1a26a33efbea3bf;p=firefly-linux-kernel-4.4.55.git diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index d7d1facc04a5..3399679513a8 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -189,11 +189,11 @@ void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req, if (req->request.status == -EINPROGRESS) req->request.status = status; - if (dwc->ep0_bounced && dep->number == 0) + if (dwc->ep0_bounced && dep->number <= 1) dwc->ep0_bounced = false; - else - usb_gadget_unmap_request(&dwc->gadget, &req->request, - req->direction); + + usb_gadget_unmap_request(&dwc->gadget, &req->request, + req->direction); trace_dwc3_gadget_giveback(req); @@ -289,16 +289,11 @@ int dwc3_send_gadget_ep_cmd(struct dwc3_ep *dep, unsigned cmd, if (!(reg & DWC3_DEPCMD_CMDACT)) { cmd_status = DWC3_DEPCMD_STATUS(reg); - dwc3_trace(trace_dwc3_gadget, - "Command Complete --> %d", - cmd_status); - switch (cmd_status) { case 0: ret = 0; break; case DEPEVT_TRANSFER_NO_RESOURCE: - dwc3_trace(trace_dwc3_gadget, "no resource available"); ret = -EINVAL; break; case DEPEVT_TRANSFER_BUS_EXPIRY: @@ -313,7 +308,6 @@ int dwc3_send_gadget_ep_cmd(struct dwc3_ep *dep, unsigned cmd, * give a hint to the gadget driver that this is * the case by returning -EAGAIN. */ - dwc3_trace(trace_dwc3_gadget, "bus expiry"); ret = -EAGAIN; break; default: @@ -325,8 +319,6 @@ int dwc3_send_gadget_ep_cmd(struct dwc3_ep *dep, unsigned cmd, } while (--timeout); if (timeout == 0) { - dwc3_trace(trace_dwc3_gadget, - "Command Timed Out"); ret = -ETIMEDOUT; cmd_status = -ETIMEDOUT; } @@ -470,10 +462,14 @@ static int dwc3_gadget_start_config(struct dwc3 *dwc, struct dwc3_ep *dep) static int dwc3_gadget_set_ep_config(struct dwc3 *dwc, struct dwc3_ep *dep, const struct usb_endpoint_descriptor *desc, const struct usb_ss_ep_comp_descriptor *comp_desc, - bool ignore, bool restore) + bool modify, bool restore) { struct dwc3_gadget_ep_cmd_params params; + if (dev_WARN_ONCE(dwc->dev, modify && restore, + "Can't modify and restore\n")) + return -EINVAL; + memset(¶ms, 0x00, sizeof(params)); params.param0 = DWC3_DEPCFG_EP_TYPE(usb_endpoint_type(desc)) @@ -485,12 +481,13 @@ static int dwc3_gadget_set_ep_config(struct dwc3 *dwc, struct dwc3_ep *dep, params.param0 |= DWC3_DEPCFG_BURST_SIZE(burst - 1); } - if (ignore) - params.param0 |= DWC3_DEPCFG_IGN_SEQ_NUM; - - if (restore) { + if (modify) { + params.param0 |= DWC3_DEPCFG_ACTION_MODIFY; + } else if (restore) { params.param0 |= DWC3_DEPCFG_ACTION_RESTORE; params.param2 |= dep->saved_state; + } else { + params.param0 |= DWC3_DEPCFG_ACTION_INIT; } params.param1 = DWC3_DEPCFG_XFER_COMPLETE_EN @@ -550,7 +547,7 @@ static int dwc3_gadget_set_xfer_resource(struct dwc3 *dwc, struct dwc3_ep *dep) static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep, const struct usb_endpoint_descriptor *desc, const struct usb_ss_ep_comp_descriptor *comp_desc, - bool ignore, bool restore) + bool modify, bool restore) { struct dwc3 *dwc = dep->dwc; u32 reg; @@ -564,7 +561,7 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep, return ret; } - ret = dwc3_gadget_set_ep_config(dwc, dep, desc, comp_desc, ignore, + ret = dwc3_gadget_set_ep_config(dwc, dep, desc, comp_desc, modify, restore); if (ret) return ret; @@ -609,15 +606,13 @@ static void dwc3_remove_requests(struct dwc3 *dwc, struct dwc3_ep *dep) { struct dwc3_request *req; - if (!list_empty(&dep->started_list)) { - dwc3_stop_active_transfer(dwc, dep->number, true); + dwc3_stop_active_transfer(dwc, dep->number, true); - /* - giveback all requests to gadget driver */ - while (!list_empty(&dep->started_list)) { - req = next_request(&dep->started_list); + /* - giveback all requests to gadget driver */ + while (!list_empty(&dep->started_list)) { + req = next_request(&dep->started_list); - dwc3_gadget_giveback(dep, req, -ESHUTDOWN); - } + dwc3_gadget_giveback(dep, req, -ESHUTDOWN); } while (!list_empty(&dep->pending_list)) { @@ -749,6 +744,8 @@ static struct usb_request *dwc3_gadget_ep_alloc_request(struct usb_ep *ep, req->epnum = dep->number; req->dep = dep; + dep->allocated_requests++; + trace_dwc3_alloc_request(req); return &req->request; @@ -758,7 +755,9 @@ static void dwc3_gadget_ep_free_request(struct usb_ep *ep, struct usb_request *request) { struct dwc3_request *req = to_dwc3_request(request); + struct dwc3_ep *dep = to_dwc3_ep(ep); + dep->allocated_requests--; trace_dwc3_free_request(req); kfree(req); } @@ -839,6 +838,8 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep, trb->ctrl |= DWC3_TRB_CTRL_HWO; + dep->queued_requests++; + trace_dwc3_prepare_trb(dep, trb); } @@ -875,10 +876,14 @@ static u32 dwc3_calc_trbs_left(struct dwc3_ep *dep) */ if (dep->trb_enqueue == dep->trb_dequeue) { tmp = dwc3_ep_prev_trb(dep, dep->trb_enqueue); - if (tmp->ctrl & DWC3_TRB_CTRL_HWO) - return 0; - return DWC3_TRB_NUM - 1; + if (!(tmp->ctrl & DWC3_TRB_CTRL_HWO) || + ((tmp->ctrl & DWC3_TRB_CTRL_HWO) && + (tmp->ctrl & DWC3_TRB_CTRL_CSP) && + !dep->direction)) + return DWC3_TRB_NUM - 1; + + return 0; } trbs_left = dep->trb_dequeue - dep->trb_enqueue; @@ -891,7 +896,8 @@ static u32 dwc3_calc_trbs_left(struct dwc3_ep *dep) } static void dwc3_prepare_one_trb_sg(struct dwc3_ep *dep, - struct dwc3_request *req, unsigned int trbs_left) + struct dwc3_request *req, unsigned int trbs_left, + unsigned int more_coming) { struct usb_request *request = &req->request; struct scatterlist *sg = request->sg; @@ -908,13 +914,14 @@ static void dwc3_prepare_one_trb_sg(struct dwc3_ep *dep, dma = sg_dma_address(s); if (sg_is_last(s)) { - if (list_is_last(&req->list, &dep->pending_list)) + if (usb_endpoint_xfer_int(dep->endpoint.desc) || + !more_coming) last = true; chain = false; } - if (!trbs_left) + if (!trbs_left--) last = true; if (last) @@ -929,7 +936,8 @@ static void dwc3_prepare_one_trb_sg(struct dwc3_ep *dep, } static void dwc3_prepare_one_trb_linear(struct dwc3_ep *dep, - struct dwc3_request *req, unsigned int trbs_left) + struct dwc3_request *req, unsigned int trbs_left, + unsigned int more_coming) { unsigned int last = false; unsigned int length; @@ -942,7 +950,7 @@ static void dwc3_prepare_one_trb_linear(struct dwc3_ep *dep, last = true; /* Is this the last request? */ - if (list_is_last(&req->list, &dep->pending_list)) + if (usb_endpoint_xfer_int(dep->endpoint.desc) || !more_coming) last = true; dwc3_prepare_one_trb(dep, req, dma, length, @@ -960,6 +968,7 @@ static void dwc3_prepare_one_trb_linear(struct dwc3_ep *dep, static void dwc3_prepare_trbs(struct dwc3_ep *dep) { struct dwc3_request *req, *n; + unsigned int more_coming; u32 trbs_left; BUILD_BUG_ON_NOT_POWER_OF_2(DWC3_TRB_NUM); @@ -968,11 +977,15 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep) if (!trbs_left) return; + more_coming = dep->allocated_requests - dep->queued_requests; + list_for_each_entry_safe(req, n, &dep->pending_list, list) { if (req->request.num_mapped_sgs > 0) - dwc3_prepare_one_trb_sg(dep, req, trbs_left--); + dwc3_prepare_one_trb_sg(dep, req, trbs_left--, + more_coming); else - dwc3_prepare_one_trb_linear(dep, req, trbs_left--); + dwc3_prepare_one_trb_linear(dep, req, trbs_left--, + more_coming); if (!trbs_left) return; @@ -1002,12 +1015,13 @@ static int __dwc3_gadget_kick_transfer(struct dwc3_ep *dep, u16 cmd_param) if (starting) { params.param0 = upper_32_bits(req->trb_dma); params.param1 = lower_32_bits(req->trb_dma); - cmd = DWC3_DEPCMD_STARTTRANSFER; + cmd = DWC3_DEPCMD_STARTTRANSFER | + DWC3_DEPCMD_PARAM(cmd_param); } else { - cmd = DWC3_DEPCMD_UPDATETRANSFER; + cmd = DWC3_DEPCMD_UPDATETRANSFER | + DWC3_DEPCMD_PARAM(dep->resource_index); } - cmd |= DWC3_DEPCMD_PARAM(cmd_param); ret = dwc3_send_gadget_ep_cmd(dep, cmd, ¶ms); if (ret < 0) { /* @@ -1068,14 +1082,14 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req) if (!dep->endpoint.desc) { dwc3_trace(trace_dwc3_gadget, - "trying to queue request %p to disabled %s\n", + "trying to queue request %p to disabled %s", &req->request, dep->endpoint.name); return -ESHUTDOWN; } if (WARN(req->dep != dep, "request %p belongs to '%s'\n", &req->request, req->dep->name)) { - dwc3_trace(trace_dwc3_gadget, "request %p belongs to '%s'\n", + dwc3_trace(trace_dwc3_gadget, "request %p belongs to '%s'", &req->request, req->dep->name); return -EINVAL; } @@ -1127,8 +1141,7 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req) * little bit faster. */ if (!usb_endpoint_xfer_isoc(dep->endpoint.desc) && - !usb_endpoint_xfer_int(dep->endpoint.desc) && - !(dep->flags & DWC3_EP_BUSY)) { + !usb_endpoint_xfer_int(dep->endpoint.desc)) { ret = __dwc3_gadget_kick_transfer(dep, 0); goto out; } @@ -1190,7 +1203,7 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req) out: if (ret && ret != -EBUSY) dwc3_trace(trace_dwc3_gadget, - "%s: failed to kick transfers\n", + "%s: failed to kick transfers", dep->name); if (ret == -EBUSY) ret = 0; @@ -1210,7 +1223,7 @@ static int __dwc3_gadget_ep_queue_zlp(struct dwc3 *dwc, struct dwc3_ep *dep) struct usb_request *request; struct usb_ep *ep = &dep->endpoint; - dwc3_trace(trace_dwc3_gadget, "queueing ZLP\n"); + dwc3_trace(trace_dwc3_gadget, "queueing ZLP"); request = dwc3_gadget_ep_alloc_request(ep, GFP_ATOMIC); if (!request) return -ENOMEM; @@ -1314,9 +1327,21 @@ int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value, int protocol) memset(¶ms, 0x00, sizeof(params)); if (value) { - if (!protocol && ((dep->direction && dep->flags & DWC3_EP_BUSY) || - (!list_empty(&dep->started_list) || - !list_empty(&dep->pending_list)))) { + struct dwc3_trb *trb; + + unsigned transfer_in_flight; + unsigned started; + + if (dep->number > 1) + trb = dwc3_ep_prev_trb(dep, dep->trb_enqueue); + else + trb = &dwc->ep0_trb[dep->trb_enqueue]; + + transfer_in_flight = trb->ctrl & DWC3_TRB_CTRL_HWO; + started = !list_empty(&dep->started_list); + + if (!protocol && ((dep->direction && transfer_in_flight) || + (!dep->direction && started))) { dwc3_trace(trace_dwc3_gadget, "%s: pending request, cannot halt", dep->name); @@ -1439,7 +1464,7 @@ static int __dwc3_gadget_wakeup(struct dwc3 *dwc) speed = reg & DWC3_DSTS_CONNECTSPD; if (speed == DWC3_DSTS_SUPERSPEED) { - dwc3_trace(trace_dwc3_gadget, "no wakeup on SuperSpeed\n"); + dwc3_trace(trace_dwc3_gadget, "no wakeup on SuperSpeed"); return 0; } @@ -1451,7 +1476,7 @@ static int __dwc3_gadget_wakeup(struct dwc3 *dwc) break; default: dwc3_trace(trace_dwc3_gadget, - "can't wakeup from '%s'\n", + "can't wakeup from '%s'", dwc3_gadget_link_string(link_state)); return -EINVAL; } @@ -1551,18 +1576,11 @@ static int dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on, int suspend) do { reg = dwc3_readl(dwc->regs, DWC3_DSTS); - if (is_on) { - if (!(reg & DWC3_DSTS_DEVCTRLHLT)) - break; - } else { - if (reg & DWC3_DSTS_DEVCTRLHLT) - break; - } - timeout--; - if (!timeout) - return -ETIMEDOUT; - udelay(1); - } while (1); + reg &= DWC3_DSTS_DEVCTRLHLT; + } while (--timeout && !(!is_on ^ !reg)); + + if (!timeout) + return -ETIMEDOUT; dwc3_trace(trace_dwc3_gadget, "gadget %s data soft-%s", dwc->gadget_driver @@ -1753,7 +1771,7 @@ static int dwc3_gadget_start(struct usb_gadget *g, int ret = 0; int irq; - irq = platform_get_irq(to_platform_device(dwc->dev), 0); + irq = dwc->irq_gadget; ret = request_threaded_irq(irq, dwc3_interrupt, dwc3_thread_interrupt, IRQF_SHARED, "dwc3", dwc->ev_buf); if (ret) { @@ -1761,7 +1779,6 @@ static int dwc3_gadget_start(struct usb_gadget *g, irq, ret); goto err0; } - dwc->irq_gadget = irq; spin_lock_irqsave(&dwc->lock, flags); if (dwc->gadget_driver) { @@ -1791,6 +1808,9 @@ err0: static void __dwc3_gadget_stop(struct dwc3 *dwc) { + if (pm_runtime_suspended(dwc->dev)) + return; + dwc3_gadget_disable_irq(dwc); __dwc3_gadget_ep_disable(dwc->eps[0]); __dwc3_gadget_ep_disable(dwc->eps[1]); @@ -1947,6 +1967,7 @@ static int __dwc3_cleanup_done_trbs(struct dwc3 *dwc, struct dwc3_ep *dep, unsigned int s_pkt = 0; unsigned int trb_status; + dep->queued_requests--; trace_dwc3_complete_trb(dep, trb); if ((trb->ctrl & DWC3_TRB_CTRL_HWO) && status != -ESHUTDOWN) @@ -1967,7 +1988,7 @@ static int __dwc3_cleanup_done_trbs(struct dwc3 *dwc, struct dwc3_ep *dep, trb_status = DWC3_TRB_SIZE_TRBSTS(trb->size); if (trb_status == DWC3_TRBSTS_MISSED_ISOC) { dwc3_trace(trace_dwc3_gadget, - "%s: incomplete IN transfer\n", + "%s: incomplete IN transfer", dep->name); /* * If missed isoc occurred and there is @@ -1998,14 +2019,6 @@ static int __dwc3_cleanup_done_trbs(struct dwc3 *dwc, struct dwc3_ep *dep, s_pkt = 1; } - /* - * We assume here we will always receive the entire data block - * which we should receive. Meaning, if we program RX to - * receive 4K but we receive only 2K, we assume that's all we - * should receive and we simply bounce the request back to the - * gadget driver for further processing. - */ - req->request.actual += req->request.length - count; if (s_pkt) return 1; if ((event->status & DEPEVT_STATUS_LST) && @@ -2025,6 +2038,7 @@ static int dwc3_cleanup_done_reqs(struct dwc3 *dwc, struct dwc3_ep *dep, struct dwc3_trb *trb; unsigned int slot; unsigned int i; + int count = 0; int ret; do { @@ -2039,6 +2053,8 @@ static int dwc3_cleanup_done_reqs(struct dwc3 *dwc, struct dwc3_ep *dep, slot++; slot %= DWC3_TRB_NUM; trb = &dep->trb_pool[slot]; + count += trb->size & DWC3_TRB_SIZE_MASK; + ret = __dwc3_cleanup_done_trbs(dwc, dep, req, trb, event, status); @@ -2046,6 +2062,14 @@ static int dwc3_cleanup_done_reqs(struct dwc3 *dwc, struct dwc3_ep *dep, break; } while (++i < req->request.num_mapped_sgs); + /* + * We assume here we will always receive the entire data block + * which we should receive. Meaning, if we program RX to + * receive 4K but we receive only 2K, we assume that's all we + * should receive and we simply bounce the request back to the + * gadget driver for further processing. + */ + req->request.actual += req->request.length - count; dwc3_gadget_giveback(dep, req, status); if (ret) @@ -2155,6 +2179,9 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc, return; if (epnum == 0 || epnum == 1) { + if (!dwc->connected && + event->endpoint_event == DWC3_DEPEVT_XFERCOMPLETE) + dwc->connected = true; dwc3_ep0_interrupt(dwc, event); return; } @@ -2165,7 +2192,7 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc, if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) { dwc3_trace(trace_dwc3_gadget, - "%s is an Isochronous endpoint\n", + "%s is an Isochronous endpoint", dep->name); return; } @@ -2193,7 +2220,7 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc, return; dwc3_trace(trace_dwc3_gadget, - "%s: failed to kick transfers\n", + "%s: failed to kick transfers", dep->name); } @@ -2216,11 +2243,11 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc, /* FALLTHROUGH */ default: dwc3_trace(trace_dwc3_gadget, - "unable to find suitable stream\n"); + "unable to find suitable stream"); } break; case DWC3_DEPEVT_RXTXFIFOEVT: - dwc3_trace(trace_dwc3_gadget, "%s FIFO Overrun\n", dep->name); + dwc3_trace(trace_dwc3_gadget, "%s FIFO Overrun", dep->name); break; case DWC3_DEPEVT_EPCMDCMPLT: dwc3_trace(trace_dwc3_gadget, "Endpoint Command Complete"); @@ -2374,8 +2401,6 @@ static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc) { u32 reg; - dwc->connected = true; - /* * WORKAROUND: DWC3 revisions <1.88a have an issue which * would cause a missing Disconnect Event if there's a @@ -2673,6 +2698,17 @@ static void dwc3_gadget_linksts_change_interrupt(struct dwc3 *dwc, dwc->link_state = next; } +static void dwc3_gadget_suspend_interrupt(struct dwc3 *dwc, + unsigned int evtinfo) +{ + enum dwc3_link_state next = evtinfo & DWC3_LINK_STATE_MASK; + + if (dwc->link_state != next && next == DWC3_LINK_STATE_U3) + dwc3_suspend_gadget(dwc); + + dwc->link_state = next; +} + static void dwc3_gadget_hibernation_interrupt(struct dwc3 *dwc, unsigned int evtinfo) { @@ -2724,7 +2760,20 @@ static void dwc3_gadget_interrupt(struct dwc3 *dwc, dwc3_gadget_linksts_change_interrupt(dwc, event->event_info); break; case DWC3_DEVICE_EVENT_EOPF: - dwc3_trace(trace_dwc3_gadget, "End of Periodic Frame"); + /* It changed to be suspend event for version 2.30a and above */ + if (dwc->revision < DWC3_REVISION_230A) { + dwc3_trace(trace_dwc3_gadget, "End of Periodic Frame"); + } else { + dwc3_trace(trace_dwc3_gadget, "U3/L1-L2 Suspend Event"); + + /* + * Ignore suspend event until the gadget enters into + * USB_STATE_CONFIGURED state. + */ + if (dwc->gadget.state >= USB_STATE_CONFIGURED) + dwc3_gadget_suspend_interrupt(dwc, + event->event_info); + } break; case DWC3_DEVICE_EVENT_SOF: dwc3_trace(trace_dwc3_gadget, "Start of Periodic Frame"); @@ -2830,7 +2879,10 @@ static irqreturn_t dwc3_check_event_buf(struct dwc3_event_buffer *evt) u32 count; u32 reg; - if (pm_runtime_suspended(dwc->dev)) { + reg = dwc3_readl(dwc->regs, DWC3_GCTL); + + if (pm_runtime_suspended(dwc->dev) && + DWC3_GCTL_PRTCAP(reg) != DWC3_GCTL_PRTCAP_HOST) { pm_runtime_get(dwc->dev); disable_irq_nosync(dwc->irq_gadget); dwc->pending_events = true; @@ -2868,7 +2920,33 @@ static irqreturn_t dwc3_interrupt(int irq, void *_evt) */ int dwc3_gadget_init(struct dwc3 *dwc) { - int ret; + int ret, irq; + struct platform_device *dwc3_pdev = to_platform_device(dwc->dev); + + irq = platform_get_irq_byname(dwc3_pdev, "peripheral"); + if (irq == -EPROBE_DEFER) + return irq; + + if (irq <= 0) { + irq = platform_get_irq_byname(dwc3_pdev, "dwc_usb3"); + if (irq == -EPROBE_DEFER) + return irq; + + if (irq <= 0) { + irq = platform_get_irq(dwc3_pdev, 0); + if (irq <= 0) { + if (irq != -EPROBE_DEFER) { + dev_err(dwc->dev, + "missing peripheral IRQ\n"); + } + if (!irq) + irq = -EINVAL; + return irq; + } + } + } + + dwc->irq_gadget = irq; dwc->ctrl_req = dma_alloc_coherent(dwc->dev, sizeof(*dwc->ctrl_req), &dwc->ctrl_req_addr, GFP_KERNEL); @@ -2931,7 +3009,7 @@ int dwc3_gadget_init(struct dwc3 *dwc) */ if (dwc->revision < DWC3_REVISION_220A) dwc3_trace(trace_dwc3_gadget, - "Changing max_speed on rev %08x\n", + "Changing max_speed on rev %08x", dwc->revision); dwc->gadget.max_speed = dwc->maximum_speed; @@ -2971,7 +3049,7 @@ err3: kfree(dwc->setup_buf); err2: - dma_free_coherent(dwc->dev, sizeof(*dwc->ep0_trb), + dma_free_coherent(dwc->dev, sizeof(*dwc->ep0_trb) * 2, dwc->ep0_trb, dwc->ep0_trb_addr); err1: @@ -2996,7 +3074,7 @@ void dwc3_gadget_exit(struct dwc3 *dwc) kfree(dwc->setup_buf); kfree(dwc->zlp_buf); - dma_free_coherent(dwc->dev, sizeof(*dwc->ep0_trb), + dma_free_coherent(dwc->dev, sizeof(*dwc->ep0_trb) * 2, dwc->ep0_trb, dwc->ep0_trb_addr); dma_free_coherent(dwc->dev, sizeof(*dwc->ctrl_req), @@ -3012,7 +3090,7 @@ int dwc3_gadget_suspend(struct dwc3 *dwc) ret = dwc3_gadget_run_stop(dwc, false, false); if (ret < 0) - return ret; + dev_err(dwc->dev, "dwc3 gadget stop timeout\n"); dwc3_disconnect_gadget(dwc); __dwc3_gadget_stop(dwc);