diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 22d2fd8f753d..534a3bf4c679 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1682,6 +1682,31 @@ static int __dwc3_gadget_start_isoc(struct dwc3_ep *dep) return ret; } +static void dwc3_gadget_ep_skip_trbs(struct dwc3_ep *dep, struct dwc3_request *req) +{ + int i; + + /* + * If request was already started, this means we had to + * stop the transfer. With that we also need to ignore + * all TRBs used by the request, however TRBs can only + * be modified after completion of END_TRANSFER + * command. So what we do here is that we wait for + * END_TRANSFER completion and only after that, we jump + * over TRBs by clearing HWO and incrementing dequeue + * pointer. + */ + for (i = 0; i < req->num_trbs; i++) { + struct dwc3_trb *trb; + + trb = &dep->trb_pool[dep->trb_dequeue]; + trb->ctrl &= ~DWC3_TRB_CTRL_HWO; + dwc3_ep_inc_deq(dep); + } + + req->num_trbs = 0; +} + static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req) { struct dwc3 *dwc = dep->dwc; @@ -1698,8 +1723,14 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req) if (WARN(req->status < DWC3_REQUEST_STATUS_COMPLETED, "%s: request %pK already in flight\n", - dep->name, &req->request)) + dep->name, &req->request)) { + if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) { + dwc3_gadget_ep_skip_trbs(dep, req); + req->status = DWC3_REQUEST_STATUS_COMPLETED; + dwc3_gadget_del_and_unmap_request(dep, req, -EINVAL); + } return -EINVAL; + } pm_runtime_get(dwc->dev); @@ -1758,31 +1789,6 @@ static int dwc3_gadget_ep_queue(struct usb_ep *ep, struct usb_request *request, return ret; } -static void dwc3_gadget_ep_skip_trbs(struct dwc3_ep *dep, struct dwc3_request *req) -{ - int i; - - /* - * If request was already started, this means we had to - * stop the transfer. With that we also need to ignore - * all TRBs used by the request, however TRBs can only - * be modified after completion of END_TRANSFER - * command. So what we do here is that we wait for - * END_TRANSFER completion and only after that, we jump - * over TRBs by clearing HWO and incrementing dequeue - * pointer. - */ - for (i = 0; i < req->num_trbs; i++) { - struct dwc3_trb *trb; - - trb = &dep->trb_pool[dep->trb_dequeue]; - trb->ctrl &= ~DWC3_TRB_CTRL_HWO; - dwc3_ep_inc_deq(dep); - } - - req->num_trbs = 0; -} - static void dwc3_gadget_ep_cleanup_cancelled_requests(struct dwc3_ep *dep) { struct dwc3_request *req;