| From b564f20d2b4a768f6da78669a95cbbbb85729985 Mon Sep 17 00:00:00 2001 |
| From: Thinh Nguyen <Thinh.Nguyen@synopsys.com> |
| Date: Sun, 29 Mar 2020 16:12:57 -0700 |
| Subject: [PATCH] usb: dwc3: gadget: Properly handle failed kick_transfer |
| |
| commit 8d99087c2db863c5fa3a4a1f3cb82b3a493705ca upstream. |
| |
| If dwc3 fails to issue START_TRANSFER/UPDATE_TRANSFER command, then we |
| should properly end an active transfer and give back all the started |
| requests. However if it's for an isoc endpoint, the failure maybe due to |
| bus-expiry status. In this case, don't give back the requests and wait |
| for the next retry. |
| |
| Fixes: 72246da40f37 ("usb: Introduce DesignWare USB3 DRD Driver") |
| Signed-off-by: Thinh Nguyen <thinhn@synopsys.com> |
| Signed-off-by: Felipe Balbi <balbi@kernel.org> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c |
| index be2ad9e5e6ad..7a28048faa3e 100644 |
| --- a/drivers/usb/dwc3/gadget.c |
| +++ b/drivers/usb/dwc3/gadget.c |
| @@ -1217,6 +1217,8 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep) |
| } |
| } |
| |
| +static void dwc3_gadget_ep_cleanup_cancelled_requests(struct dwc3_ep *dep); |
| + |
| static int __dwc3_gadget_kick_transfer(struct dwc3_ep *dep) |
| { |
| struct dwc3_gadget_ep_cmd_params params; |
| @@ -1256,14 +1258,20 @@ static int __dwc3_gadget_kick_transfer(struct dwc3_ep *dep) |
| |
| ret = dwc3_send_gadget_ep_cmd(dep, cmd, ¶ms); |
| if (ret < 0) { |
| - /* |
| - * FIXME we need to iterate over the list of requests |
| - * here and stop, unmap, free and del each of the linked |
| - * requests instead of what we do now. |
| - */ |
| - if (req->trb) |
| - memset(req->trb, 0, sizeof(struct dwc3_trb)); |
| - dwc3_gadget_del_and_unmap_request(dep, req, ret); |
| + struct dwc3_request *tmp; |
| + |
| + if (ret == -EAGAIN) |
| + return ret; |
| + |
| + dwc3_stop_active_transfer(dep, true, true); |
| + |
| + list_for_each_entry_safe(req, tmp, &dep->started_list, list) |
| + dwc3_gadget_move_cancelled_request(req); |
| + |
| + /* If ep isn't started, then there's no end transfer pending */ |
| + if (!(dep->flags & DWC3_EP_END_TRANSFER_PENDING)) |
| + dwc3_gadget_ep_cleanup_cancelled_requests(dep); |
| + |
| return ret; |
| } |
| |
| -- |
| 2.27.0 |
| |