From: Sasha Levin Date: Fri, 28 Jun 2019 22:58:15 +0000 (-0400) Subject: fixes for 4.19 X-Git-Tag: v5.1.16~40 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=c9bcca34aa4634ff22706050c96d44aae2df5256;p=thirdparty%2Fkernel%2Fstable-queue.git fixes for 4.19 Signed-off-by: Sasha Levin --- diff --git a/queue-4.19/revert-usb-dwc3-gadget-clear-req-needs_extra_trb-fla.patch b/queue-4.19/revert-usb-dwc3-gadget-clear-req-needs_extra_trb-fla.patch new file mode 100644 index 00000000000..3a19d6d1899 --- /dev/null +++ b/queue-4.19/revert-usb-dwc3-gadget-clear-req-needs_extra_trb-fla.patch @@ -0,0 +1,38 @@ +From 383babf3c68e744a82a6b3267697bb0de65ad113 Mon Sep 17 00:00:00 2001 +From: John Stultz +Date: Fri, 28 Jun 2019 18:24:05 +0000 +Subject: Revert "usb: dwc3: gadget: Clear req->needs_extra_trb flag on + cleanup" + +This reverts commit 25ad17d692ad54c3c33b2a31e5ce2a82e38de14e, +as we will be cherry-picking a number of changes from upstream +that allows us to later cherry-pick the same fix from upstream +rather than using this modified backported version. + +Cc: Fei Yang +Cc: Sam Protsenko +Cc: Felipe Balbi +Cc: linux-usb@vger.kernel.org +Cc: stable@vger.kernel.org # 4.19.y +Signed-off-by: John Stultz +Signed-off-by: Sasha Levin +--- + drivers/usb/dwc3/gadget.c | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c +index 65ba1038b111..eaa78e6c972c 100644 +--- a/drivers/usb/dwc3/gadget.c ++++ b/drivers/usb/dwc3/gadget.c +@@ -177,8 +177,6 @@ static void dwc3_gadget_del_and_unmap_request(struct dwc3_ep *dep, + req->started = false; + list_del(&req->list); + req->remaining = 0; +- req->unaligned = false; +- req->zero = false; + + if (req->request.status == -EINPROGRESS) + req->request.status = status; +-- +2.20.1 + diff --git a/queue-4.19/series b/queue-4.19/series index 96917eb49c9..ce67d108df7 100644 --- a/queue-4.19/series +++ b/queue-4.19/series @@ -20,3 +20,12 @@ ib-hfi1-close-psm-sdma_progress-sleep-window.patch 9p-trans_fd-put-worker-reqs-on-destroy.patch net-9p-include-trans_common.h-to-fix-missing-prototy.patch qmi_wwan-fix-out-of-bounds-read.patch +revert-usb-dwc3-gadget-clear-req-needs_extra_trb-fla.patch +usb-dwc3-gadget-combine-unaligned-and-zero-flags.patch +usb-dwc3-gadget-track-number-of-trbs-per-request.patch +usb-dwc3-gadget-use-num_trbs-when-skipping-trbs-on-d.patch +usb-dwc3-gadget-extract-dwc3_gadget_ep_skip_trbs.patch +usb-dwc3-gadget-introduce-cancelled_list.patch +usb-dwc3-gadget-move-requests-to-cancelled_list.patch +usb-dwc3-gadget-remove-wait_end_transfer.patch +usb-dwc3-gadget-clear-req-needs_extra_trb-flag-on-cl.patch diff --git a/queue-4.19/usb-dwc3-gadget-clear-req-needs_extra_trb-flag-on-cl.patch b/queue-4.19/usb-dwc3-gadget-clear-req-needs_extra_trb-flag-on-cl.patch new file mode 100644 index 00000000000..77c0fd58395 --- /dev/null +++ b/queue-4.19/usb-dwc3-gadget-clear-req-needs_extra_trb-flag-on-cl.patch @@ -0,0 +1,56 @@ +From 672f3900ba0271479da5c46d0a06a2dbf9c4fad5 Mon Sep 17 00:00:00 2001 +From: Jack Pham +Date: Fri, 28 Jun 2019 18:24:13 +0000 +Subject: usb: dwc3: gadget: Clear req->needs_extra_trb flag on cleanup + +commit bd6742249b9ca918565e4e3abaa06665e587f4b5 upstream + +OUT endpoint requests may somtimes have this flag set when +preparing to be submitted to HW indicating that there is an +additional TRB chained to the request for alignment purposes. +If that request is removed before the controller can execute the +transfer (e.g. ep_dequeue/ep_disable), the request will not go +through the dwc3_gadget_ep_cleanup_completed_request() handler +and will not have its needs_extra_trb flag cleared when +dwc3_gadget_giveback() is called. This same request could be +later requeued for a new transfer that does not require an +extra TRB and if it is successfully completed, the cleanup +and TRB reclamation will incorrectly process the additional TRB +which belongs to the next request, and incorrectly advances the +TRB dequeue pointer, thereby messing up calculation of the next +requeust's actual/remaining count when it completes. + +The right thing to do here is to ensure that the flag is cleared +before it is given back to the function driver. A good place +to do that is in dwc3_gadget_del_and_unmap_request(). + +Fixes: c6267a51639b ("usb: dwc3: gadget: align transfers to wMaxPacketSize") +Cc: Fei Yang +Cc: Sam Protsenko +Cc: Felipe Balbi +Cc: linux-usb@vger.kernel.org +Cc: stable@vger.kernel.org # 4.19.y +Signed-off-by: Jack Pham +Signed-off-by: Felipe Balbi +(cherry picked from commit bd6742249b9ca918565e4e3abaa06665e587f4b5) +Signed-off-by: John Stultz +Signed-off-by: Sasha Levin +--- + drivers/usb/dwc3/gadget.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c +index 843586f20572..e7122b5199d2 100644 +--- a/drivers/usb/dwc3/gadget.c ++++ b/drivers/usb/dwc3/gadget.c +@@ -177,6 +177,7 @@ static void dwc3_gadget_del_and_unmap_request(struct dwc3_ep *dep, + req->started = false; + list_del(&req->list); + req->remaining = 0; ++ req->needs_extra_trb = false; + + if (req->request.status == -EINPROGRESS) + req->request.status = status; +-- +2.20.1 + diff --git a/queue-4.19/usb-dwc3-gadget-combine-unaligned-and-zero-flags.patch b/queue-4.19/usb-dwc3-gadget-combine-unaligned-and-zero-flags.patch new file mode 100644 index 00000000000..5969f1fbdc8 --- /dev/null +++ b/queue-4.19/usb-dwc3-gadget-combine-unaligned-and-zero-flags.patch @@ -0,0 +1,133 @@ +From 066d3127ddc05c6d95a155451e85a83d183fae0e Mon Sep 17 00:00:00 2001 +From: Felipe Balbi +Date: Fri, 28 Jun 2019 18:24:06 +0000 +Subject: usb: dwc3: gadget: combine unaligned and zero flags + +commit 1a22ec643580626f439c8583edafdcc73798f2fb upstream + +Both flags are used for the same purpose in dwc3: appending an extra +TRB at the end to deal with controller requirements. By combining both +flags into one, we make it clear that the situation is the same and +that they should be treated equally. + +Cc: Fei Yang +Cc: Sam Protsenko +Cc: Felipe Balbi +Cc: linux-usb@vger.kernel.org +Cc: stable@vger.kernel.org # 4.19.y +Signed-off-by: Felipe Balbi +(cherry picked from commit 1a22ec643580626f439c8583edafdcc73798f2fb) +Signed-off-by: John Stultz +Signed-off-by: Sasha Levin +--- + drivers/usb/dwc3/core.h | 7 +++---- + drivers/usb/dwc3/gadget.c | 18 +++++++++--------- + 2 files changed, 12 insertions(+), 13 deletions(-) + +diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h +index 5bfb62533e0f..4872cba8699b 100644 +--- a/drivers/usb/dwc3/core.h ++++ b/drivers/usb/dwc3/core.h +@@ -847,11 +847,11 @@ struct dwc3_hwparams { + * @epnum: endpoint number to which this request refers + * @trb: pointer to struct dwc3_trb + * @trb_dma: DMA address of @trb +- * @unaligned: true for OUT endpoints with length not divisible by maxp ++ * @needs_extra_trb: true when request needs one extra TRB (either due to ZLP ++ * or unaligned OUT) + * @direction: IN or OUT direction flag + * @mapped: true when request has been dma-mapped + * @started: request is started +- * @zero: wants a ZLP + */ + struct dwc3_request { + struct usb_request request; +@@ -867,11 +867,10 @@ struct dwc3_request { + struct dwc3_trb *trb; + dma_addr_t trb_dma; + +- unsigned unaligned:1; ++ unsigned needs_extra_trb:1; + unsigned direction:1; + unsigned mapped:1; + unsigned started:1; +- unsigned zero:1; + }; + + /* +diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c +index eaa78e6c972c..8db7466e4f76 100644 +--- a/drivers/usb/dwc3/gadget.c ++++ b/drivers/usb/dwc3/gadget.c +@@ -1068,7 +1068,7 @@ static void dwc3_prepare_one_trb_sg(struct dwc3_ep *dep, + struct dwc3 *dwc = dep->dwc; + struct dwc3_trb *trb; + +- req->unaligned = true; ++ req->needs_extra_trb = true; + + /* prepare normal TRB */ + dwc3_prepare_one_trb(dep, req, true, i); +@@ -1112,7 +1112,7 @@ static void dwc3_prepare_one_trb_linear(struct dwc3_ep *dep, + struct dwc3 *dwc = dep->dwc; + struct dwc3_trb *trb; + +- req->unaligned = true; ++ req->needs_extra_trb = true; + + /* prepare normal TRB */ + dwc3_prepare_one_trb(dep, req, true, 0); +@@ -1128,7 +1128,7 @@ static void dwc3_prepare_one_trb_linear(struct dwc3_ep *dep, + struct dwc3 *dwc = dep->dwc; + struct dwc3_trb *trb; + +- req->zero = true; ++ req->needs_extra_trb = true; + + /* prepare normal TRB */ + dwc3_prepare_one_trb(dep, req, true, 0); +@@ -1410,7 +1410,7 @@ static int dwc3_gadget_ep_dequeue(struct usb_ep *ep, + dwc3_ep_inc_deq(dep); + } + +- if (r->unaligned || r->zero) { ++ if (r->needs_extra_trb) { + trb = r->trb + r->num_pending_sgs + 1; + trb->ctrl &= ~DWC3_TRB_CTRL_HWO; + dwc3_ep_inc_deq(dep); +@@ -1421,7 +1421,7 @@ static int dwc3_gadget_ep_dequeue(struct usb_ep *ep, + trb->ctrl &= ~DWC3_TRB_CTRL_HWO; + dwc3_ep_inc_deq(dep); + +- if (r->unaligned || r->zero) { ++ if (r->needs_extra_trb) { + trb = r->trb + 1; + trb->ctrl &= ~DWC3_TRB_CTRL_HWO; + dwc3_ep_inc_deq(dep); +@@ -2250,7 +2250,8 @@ static int dwc3_gadget_ep_reclaim_completed_trb(struct dwc3_ep *dep, + * with one TRB pending in the ring. We need to manually clear HWO bit + * from that TRB. + */ +- if ((req->zero || req->unaligned) && !(trb->ctrl & DWC3_TRB_CTRL_CHN)) { ++ ++ if (req->needs_extra_trb && !(trb->ctrl & DWC3_TRB_CTRL_CHN)) { + trb->ctrl &= ~DWC3_TRB_CTRL_HWO; + return 1; + } +@@ -2327,11 +2328,10 @@ static int dwc3_gadget_ep_cleanup_completed_request(struct dwc3_ep *dep, + ret = dwc3_gadget_ep_reclaim_trb_linear(dep, req, event, + status); + +- if (req->unaligned || req->zero) { ++ if (req->needs_extra_trb) { + ret = dwc3_gadget_ep_reclaim_trb_linear(dep, req, event, + status); +- req->unaligned = false; +- req->zero = false; ++ req->needs_extra_trb = false; + } + + req->request.actual = req->request.length - req->remaining; +-- +2.20.1 + diff --git a/queue-4.19/usb-dwc3-gadget-extract-dwc3_gadget_ep_skip_trbs.patch b/queue-4.19/usb-dwc3-gadget-extract-dwc3_gadget_ep_skip_trbs.patch new file mode 100644 index 00000000000..e72b0b3a5e3 --- /dev/null +++ b/queue-4.19/usb-dwc3-gadget-extract-dwc3_gadget_ep_skip_trbs.patch @@ -0,0 +1,115 @@ +From 65a9c574fd3f26275974b8439b02467385bee6b2 Mon Sep 17 00:00:00 2001 +From: Felipe Balbi +Date: Fri, 28 Jun 2019 18:24:09 +0000 +Subject: usb: dwc3: gadget: extract dwc3_gadget_ep_skip_trbs() + +commit 7746a8dfb3f9c91b3a0b63a1d5c2664410e6498d upstream + +Extract the logic for skipping over TRBs to its own function. This +makes the code slightly more readable and makes it easier to move this +call to its final resting place as a following patch. + +Cc: Fei Yang +Cc: Sam Protsenko +Cc: Felipe Balbi +Cc: linux-usb@vger.kernel.org +Cc: stable@vger.kernel.org # 4.19.y +Signed-off-by: Felipe Balbi +(cherry picked from commit 7746a8dfb3f9c91b3a0b63a1d5c2664410e6498d) +Signed-off-by: John Stultz +Signed-off-by: Sasha Levin +--- + drivers/usb/dwc3/gadget.c | 61 +++++++++++++++------------------------ + 1 file changed, 24 insertions(+), 37 deletions(-) + +diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c +index 4e08904890ed..46aa20b376cd 100644 +--- a/drivers/usb/dwc3/gadget.c ++++ b/drivers/usb/dwc3/gadget.c +@@ -1341,6 +1341,29 @@ 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 = req->trb + i; ++ trb->ctrl &= ~DWC3_TRB_CTRL_HWO; ++ dwc3_ep_inc_deq(dep); ++ } ++} ++ + static int dwc3_gadget_ep_dequeue(struct usb_ep *ep, + struct usb_request *request) + { +@@ -1368,38 +1391,8 @@ static int dwc3_gadget_ep_dequeue(struct usb_ep *ep, + break; + } + if (r == req) { +- int i; +- + /* wait until it is processed */ + dwc3_stop_active_transfer(dep, true); +- +- /* +- * 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. +- * +- * Note that we have 2 possible types of transfers here: +- * +- * i) Linear buffer request +- * ii) SG-list based request +- * +- * SG-list based requests will have r->num_pending_sgs +- * set to a valid number (> 0). Linear requests, +- * normally use a single TRB. +- * +- * For each of these two cases, if r->unaligned flag is +- * set, one extra TRB has been used to align transfer +- * size to wMaxPacketSize. +- * +- * All of these cases need to be taken into +- * consideration so we don't mess up our TRB ring +- * pointers. +- */ + wait_event_lock_irq(dep->wait_end_transfer, + !(dep->flags & DWC3_EP_END_TRANSFER_PENDING), + dwc->lock); +@@ -1407,13 +1400,7 @@ static int dwc3_gadget_ep_dequeue(struct usb_ep *ep, + if (!r->trb) + goto out0; + +- for (i = 0; i < r->num_trbs; i++) { +- struct dwc3_trb *trb; +- +- trb = r->trb + i; +- trb->ctrl &= ~DWC3_TRB_CTRL_HWO; +- dwc3_ep_inc_deq(dep); +- } ++ dwc3_gadget_ep_skip_trbs(dep, r); + goto out1; + } + dev_err(dwc->dev, "request %pK was not queued to %s\n", +-- +2.20.1 + diff --git a/queue-4.19/usb-dwc3-gadget-introduce-cancelled_list.patch b/queue-4.19/usb-dwc3-gadget-introduce-cancelled_list.patch new file mode 100644 index 00000000000..be67c93d2d5 --- /dev/null +++ b/queue-4.19/usb-dwc3-gadget-introduce-cancelled_list.patch @@ -0,0 +1,86 @@ +From a799155f5ba66fdcb68346beb825da7a2a5877f5 Mon Sep 17 00:00:00 2001 +From: Felipe Balbi +Date: Fri, 28 Jun 2019 18:24:10 +0000 +Subject: usb: dwc3: gadget: introduce cancelled_list + +commit d5443bbf5fc8f8389cce146b1fc2987cdd229d12 upstream + +This list will host cancelled requests who still have TRBs being +processed. + +Cc: Fei Yang +Cc: Sam Protsenko +Cc: Felipe Balbi +Cc: linux-usb@vger.kernel.org +Cc: stable@vger.kernel.org # 4.19.y +Signed-off-by: Felipe Balbi +(cherry picked from commit d5443bbf5fc8f8389cce146b1fc2987cdd229d12) +Signed-off-by: John Stultz +Signed-off-by: Sasha Levin +--- + drivers/usb/dwc3/core.h | 2 ++ + drivers/usb/dwc3/gadget.c | 1 + + drivers/usb/dwc3/gadget.h | 15 +++++++++++++++ + 3 files changed, 18 insertions(+) + +diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h +index 0de78cb29f2c..24f0b108b7f6 100644 +--- a/drivers/usb/dwc3/core.h ++++ b/drivers/usb/dwc3/core.h +@@ -636,6 +636,7 @@ struct dwc3_event_buffer { + /** + * struct dwc3_ep - device side endpoint representation + * @endpoint: usb endpoint ++ * @cancelled_list: list of cancelled requests for this endpoint + * @pending_list: list of pending requests for this endpoint + * @started_list: list of started requests on this endpoint + * @wait_end_transfer: wait_queue_head_t for waiting on End Transfer complete +@@ -659,6 +660,7 @@ struct dwc3_event_buffer { + */ + struct dwc3_ep { + struct usb_ep endpoint; ++ struct list_head cancelled_list; + struct list_head pending_list; + struct list_head started_list; + +diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c +index 46aa20b376cd..c2169bc626c8 100644 +--- a/drivers/usb/dwc3/gadget.c ++++ b/drivers/usb/dwc3/gadget.c +@@ -2144,6 +2144,7 @@ static int dwc3_gadget_init_endpoint(struct dwc3 *dwc, u8 epnum) + + INIT_LIST_HEAD(&dep->pending_list); + INIT_LIST_HEAD(&dep->started_list); ++ INIT_LIST_HEAD(&dep->cancelled_list); + + return 0; + } +diff --git a/drivers/usb/dwc3/gadget.h b/drivers/usb/dwc3/gadget.h +index 2aacd1afd9ff..023a473648eb 100644 +--- a/drivers/usb/dwc3/gadget.h ++++ b/drivers/usb/dwc3/gadget.h +@@ -79,6 +79,21 @@ static inline void dwc3_gadget_move_started_request(struct dwc3_request *req) + list_move_tail(&req->list, &dep->started_list); + } + ++/** ++ * dwc3_gadget_move_cancelled_request - move @req to the cancelled_list ++ * @req: the request to be moved ++ * ++ * Caller should take care of locking. This function will move @req from its ++ * current list to the endpoint's cancelled_list. ++ */ ++static inline void dwc3_gadget_move_cancelled_request(struct dwc3_request *req) ++{ ++ struct dwc3_ep *dep = req->dep; ++ ++ req->started = false; ++ list_move_tail(&req->list, &dep->cancelled_list); ++} ++ + void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req, + int status); + +-- +2.20.1 + diff --git a/queue-4.19/usb-dwc3-gadget-move-requests-to-cancelled_list.patch b/queue-4.19/usb-dwc3-gadget-move-requests-to-cancelled_list.patch new file mode 100644 index 00000000000..c16e1944bd5 --- /dev/null +++ b/queue-4.19/usb-dwc3-gadget-move-requests-to-cancelled_list.patch @@ -0,0 +1,69 @@ +From 38fdd396262017d599552ec3738aad99b32c6e7a Mon Sep 17 00:00:00 2001 +From: Felipe Balbi +Date: Fri, 28 Jun 2019 18:24:11 +0000 +Subject: usb: dwc3: gadget: move requests to cancelled_list + +commit d4f1afe5e896c18ae01099a85dab5e1a198bd2a8 upstream + +Whenever we have a request in flight, we can move it to the cancelled +list and later simply iterate over that list and skip over any TRBs we +find. + +Cc: Fei Yang +Cc: Sam Protsenko +Cc: Felipe Balbi +Cc: linux-usb@vger.kernel.org +Cc: stable@vger.kernel.org # 4.19.y +Signed-off-by: Felipe Balbi +(cherry picked from commit d4f1afe5e896c18ae01099a85dab5e1a198bd2a8) +Signed-off-by: John Stultz +Signed-off-by: Sasha Levin +--- + drivers/usb/dwc3/gadget.c | 17 ++++++++++++++--- + 1 file changed, 14 insertions(+), 3 deletions(-) + +diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c +index c2169bc626c8..8291fa1624e1 100644 +--- a/drivers/usb/dwc3/gadget.c ++++ b/drivers/usb/dwc3/gadget.c +@@ -1364,6 +1364,17 @@ static void dwc3_gadget_ep_skip_trbs(struct dwc3_ep *dep, struct dwc3_request *r + } + } + ++static void dwc3_gadget_ep_cleanup_cancelled_requests(struct dwc3_ep *dep) ++{ ++ struct dwc3_request *req; ++ struct dwc3_request *tmp; ++ ++ list_for_each_entry_safe(req, tmp, &dep->cancelled_list, list) { ++ dwc3_gadget_ep_skip_trbs(dep, req); ++ dwc3_gadget_giveback(dep, req, -ECONNRESET); ++ } ++} ++ + static int dwc3_gadget_ep_dequeue(struct usb_ep *ep, + struct usb_request *request) + { +@@ -1400,8 +1411,9 @@ static int dwc3_gadget_ep_dequeue(struct usb_ep *ep, + if (!r->trb) + goto out0; + +- dwc3_gadget_ep_skip_trbs(dep, r); +- goto out1; ++ dwc3_gadget_move_cancelled_request(req); ++ dwc3_gadget_ep_cleanup_cancelled_requests(dep); ++ goto out0; + } + dev_err(dwc->dev, "request %pK was not queued to %s\n", + request, ep->name); +@@ -1409,7 +1421,6 @@ static int dwc3_gadget_ep_dequeue(struct usb_ep *ep, + goto out0; + } + +-out1: + dwc3_gadget_giveback(dep, req, -ECONNRESET); + + out0: +-- +2.20.1 + diff --git a/queue-4.19/usb-dwc3-gadget-remove-wait_end_transfer.patch b/queue-4.19/usb-dwc3-gadget-remove-wait_end_transfer.patch new file mode 100644 index 00000000000..fa9b8ff0d3c --- /dev/null +++ b/queue-4.19/usb-dwc3-gadget-remove-wait_end_transfer.patch @@ -0,0 +1,132 @@ +From 45d69293b7484dbda73aa4160b2e05c86962334f Mon Sep 17 00:00:00 2001 +From: Felipe Balbi +Date: Fri, 28 Jun 2019 18:24:12 +0000 +Subject: usb: dwc3: gadget: remove wait_end_transfer + +commit fec9095bdef4e7c988adb603d0d4f92ee735d4a1 upstream + +Now that we have a list of cancelled requests, we can skip over TRBs +when END_TRANSFER command completes. + +Cc: Fei Yang +Cc: Sam Protsenko +Cc: Felipe Balbi +Cc: linux-usb@vger.kernel.org +Cc: stable@vger.kernel.org # 4.19.y +Signed-off-by: Felipe Balbi +(cherry picked from commit fec9095bdef4e7c988adb603d0d4f92ee735d4a1) +Signed-off-by: John Stultz +Signed-off-by: Sasha Levin +--- + drivers/usb/dwc3/core.h | 3 --- + drivers/usb/dwc3/gadget.c | 40 +-------------------------------------- + 2 files changed, 1 insertion(+), 42 deletions(-) + +diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h +index 24f0b108b7f6..131028501752 100644 +--- a/drivers/usb/dwc3/core.h ++++ b/drivers/usb/dwc3/core.h +@@ -639,7 +639,6 @@ struct dwc3_event_buffer { + * @cancelled_list: list of cancelled requests for this endpoint + * @pending_list: list of pending requests for this endpoint + * @started_list: list of started requests on this endpoint +- * @wait_end_transfer: wait_queue_head_t for waiting on End Transfer complete + * @lock: spinlock for endpoint request queue traversal + * @regs: pointer to first endpoint register + * @trb_pool: array of transaction buffers +@@ -664,8 +663,6 @@ struct dwc3_ep { + struct list_head pending_list; + struct list_head started_list; + +- wait_queue_head_t wait_end_transfer; +- + spinlock_t lock; + void __iomem *regs; + +diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c +index 8291fa1624e1..843586f20572 100644 +--- a/drivers/usb/dwc3/gadget.c ++++ b/drivers/usb/dwc3/gadget.c +@@ -638,8 +638,6 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep, unsigned int action) + reg |= DWC3_DALEPENA_EP(dep->number); + dwc3_writel(dwc->regs, DWC3_DALEPENA, reg); + +- init_waitqueue_head(&dep->wait_end_transfer); +- + if (usb_endpoint_xfer_control(desc)) + goto out; + +@@ -1404,15 +1402,11 @@ static int dwc3_gadget_ep_dequeue(struct usb_ep *ep, + if (r == req) { + /* wait until it is processed */ + dwc3_stop_active_transfer(dep, true); +- wait_event_lock_irq(dep->wait_end_transfer, +- !(dep->flags & DWC3_EP_END_TRANSFER_PENDING), +- dwc->lock); + + if (!r->trb) + goto out0; + + dwc3_gadget_move_cancelled_request(req); +- dwc3_gadget_ep_cleanup_cancelled_requests(dep); + goto out0; + } + dev_err(dwc->dev, "request %pK was not queued to %s\n", +@@ -1913,8 +1907,6 @@ static int dwc3_gadget_stop(struct usb_gadget *g) + { + struct dwc3 *dwc = gadget_to_dwc(g); + unsigned long flags; +- int epnum; +- u32 tmo_eps = 0; + + spin_lock_irqsave(&dwc->lock, flags); + +@@ -1923,36 +1915,6 @@ static int dwc3_gadget_stop(struct usb_gadget *g) + + __dwc3_gadget_stop(dwc); + +- for (epnum = 2; epnum < DWC3_ENDPOINTS_NUM; epnum++) { +- struct dwc3_ep *dep = dwc->eps[epnum]; +- int ret; +- +- if (!dep) +- continue; +- +- if (!(dep->flags & DWC3_EP_END_TRANSFER_PENDING)) +- continue; +- +- ret = wait_event_interruptible_lock_irq_timeout(dep->wait_end_transfer, +- !(dep->flags & DWC3_EP_END_TRANSFER_PENDING), +- dwc->lock, msecs_to_jiffies(5)); +- +- if (ret <= 0) { +- /* Timed out or interrupted! There's nothing much +- * we can do so we just log here and print which +- * endpoints timed out at the end. +- */ +- tmo_eps |= 1 << epnum; +- dep->flags &= DWC3_EP_END_TRANSFER_PENDING; +- } +- } +- +- if (tmo_eps) { +- dev_err(dwc->dev, +- "end transfer timed out on endpoints 0x%x [bitmap]\n", +- tmo_eps); +- } +- + out: + dwc->gadget_driver = NULL; + spin_unlock_irqrestore(&dwc->lock, flags); +@@ -2449,7 +2411,7 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc, + + if (cmd == DWC3_DEPCMD_ENDTRANSFER) { + dep->flags &= ~DWC3_EP_END_TRANSFER_PENDING; +- wake_up(&dep->wait_end_transfer); ++ dwc3_gadget_ep_cleanup_cancelled_requests(dep); + } + break; + case DWC3_DEPEVT_STREAMEVT: +-- +2.20.1 + diff --git a/queue-4.19/usb-dwc3-gadget-track-number-of-trbs-per-request.patch b/queue-4.19/usb-dwc3-gadget-track-number-of-trbs-per-request.patch new file mode 100644 index 00000000000..8da4fd61d36 --- /dev/null +++ b/queue-4.19/usb-dwc3-gadget-track-number-of-trbs-per-request.patch @@ -0,0 +1,92 @@ +From 5ae9f5d5db673a7888f50346268eaaa66ed5ff98 Mon Sep 17 00:00:00 2001 +From: Felipe Balbi +Date: Fri, 28 Jun 2019 18:24:07 +0000 +Subject: usb: dwc3: gadget: track number of TRBs per request + +commit 09fe1f8d7e2f461275b1cdd832f2cfa5e9be346d upstream + +This will help us remove the wait_event() from our ->dequeue(). + +Cc: Fei Yang +Cc: Sam Protsenko +Cc: Felipe Balbi +Cc: linux-usb@vger.kernel.org +Cc: stable@vger.kernel.org # 4.19.y +Signed-off-by: Felipe Balbi +(cherry picked from commit 09fe1f8d7e2f461275b1cdd832f2cfa5e9be346d) +Signed-off-by: John Stultz +Signed-off-by: Sasha Levin +--- + drivers/usb/dwc3/core.h | 3 +++ + drivers/usb/dwc3/gadget.c | 6 ++++++ + 2 files changed, 9 insertions(+) + +diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h +index 4872cba8699b..0de78cb29f2c 100644 +--- a/drivers/usb/dwc3/core.h ++++ b/drivers/usb/dwc3/core.h +@@ -847,6 +847,7 @@ struct dwc3_hwparams { + * @epnum: endpoint number to which this request refers + * @trb: pointer to struct dwc3_trb + * @trb_dma: DMA address of @trb ++ * @num_trbs: number of TRBs used by this request + * @needs_extra_trb: true when request needs one extra TRB (either due to ZLP + * or unaligned OUT) + * @direction: IN or OUT direction flag +@@ -867,6 +868,8 @@ struct dwc3_request { + struct dwc3_trb *trb; + dma_addr_t trb_dma; + ++ unsigned num_trbs; ++ + unsigned needs_extra_trb:1; + unsigned direction:1; + unsigned mapped:1; +diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c +index 8db7466e4f76..fd91c494307c 100644 +--- a/drivers/usb/dwc3/gadget.c ++++ b/drivers/usb/dwc3/gadget.c +@@ -1041,6 +1041,8 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep, + req->trb_dma = dwc3_trb_dma_offset(dep, trb); + } + ++ req->num_trbs++; ++ + __dwc3_prepare_one_trb(dep, trb, dma, length, chain, node, + stream_id, short_not_ok, no_interrupt); + } +@@ -1075,6 +1077,7 @@ static void dwc3_prepare_one_trb_sg(struct dwc3_ep *dep, + + /* Now prepare one extra TRB to align transfer size */ + trb = &dep->trb_pool[dep->trb_enqueue]; ++ req->num_trbs++; + __dwc3_prepare_one_trb(dep, trb, dwc->bounce_addr, + maxp - rem, false, 1, + req->request.stream_id, +@@ -1119,6 +1122,7 @@ static void dwc3_prepare_one_trb_linear(struct dwc3_ep *dep, + + /* Now prepare one extra TRB to align transfer size */ + trb = &dep->trb_pool[dep->trb_enqueue]; ++ req->num_trbs++; + __dwc3_prepare_one_trb(dep, trb, dwc->bounce_addr, maxp - rem, + false, 1, req->request.stream_id, + req->request.short_not_ok, +@@ -1135,6 +1139,7 @@ static void dwc3_prepare_one_trb_linear(struct dwc3_ep *dep, + + /* Now prepare one extra TRB to handle ZLP */ + trb = &dep->trb_pool[dep->trb_enqueue]; ++ req->num_trbs++; + __dwc3_prepare_one_trb(dep, trb, dwc->bounce_addr, 0, + false, 1, req->request.stream_id, + req->request.short_not_ok, +@@ -2231,6 +2236,7 @@ static int dwc3_gadget_ep_reclaim_completed_trb(struct dwc3_ep *dep, + dwc3_ep_inc_deq(dep); + + trace_dwc3_complete_trb(dep, trb); ++ req->num_trbs--; + + /* + * If we're in the middle of series of chained TRBs and we +-- +2.20.1 + diff --git a/queue-4.19/usb-dwc3-gadget-use-num_trbs-when-skipping-trbs-on-d.patch b/queue-4.19/usb-dwc3-gadget-use-num_trbs-when-skipping-trbs-on-d.patch new file mode 100644 index 00000000000..68483dd79bf --- /dev/null +++ b/queue-4.19/usb-dwc3-gadget-use-num_trbs-when-skipping-trbs-on-d.patch @@ -0,0 +1,84 @@ +From f1a868f2114e07cea86b4c3d561e14d03dc7d0fa Mon Sep 17 00:00:00 2001 +From: Felipe Balbi +Date: Fri, 28 Jun 2019 18:24:08 +0000 +Subject: usb: dwc3: gadget: use num_trbs when skipping TRBs on ->dequeue() + +commit c3acd59014148470dc58519870fbc779785b4bf7 upstream + +Now that we track how many TRBs a request uses, it's easier to skip +over them in case of a call to usb_ep_dequeue(). Let's do so and +simplify the code a bit. + +Cc: Fei Yang +Cc: Sam Protsenko +Cc: Felipe Balbi +Cc: linux-usb@vger.kernel.org +Cc: stable@vger.kernel.org # 4.19.y +Signed-off-by: Felipe Balbi +(cherry picked from commit c3acd59014148470dc58519870fbc779785b4bf7) +Signed-off-by: John Stultz +Signed-off-by: Sasha Levin +--- + drivers/usb/dwc3/gadget.c | 28 ++++------------------------ + 1 file changed, 4 insertions(+), 24 deletions(-) + +diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c +index fd91c494307c..4e08904890ed 100644 +--- a/drivers/usb/dwc3/gadget.c ++++ b/drivers/usb/dwc3/gadget.c +@@ -1368,6 +1368,8 @@ static int dwc3_gadget_ep_dequeue(struct usb_ep *ep, + break; + } + if (r == req) { ++ int i; ++ + /* wait until it is processed */ + dwc3_stop_active_transfer(dep, true); + +@@ -1405,32 +1407,12 @@ static int dwc3_gadget_ep_dequeue(struct usb_ep *ep, + if (!r->trb) + goto out0; + +- if (r->num_pending_sgs) { ++ for (i = 0; i < r->num_trbs; i++) { + struct dwc3_trb *trb; +- int i = 0; +- +- for (i = 0; i < r->num_pending_sgs; i++) { +- trb = r->trb + i; +- trb->ctrl &= ~DWC3_TRB_CTRL_HWO; +- dwc3_ep_inc_deq(dep); +- } +- +- if (r->needs_extra_trb) { +- trb = r->trb + r->num_pending_sgs + 1; +- trb->ctrl &= ~DWC3_TRB_CTRL_HWO; +- dwc3_ep_inc_deq(dep); +- } +- } else { +- struct dwc3_trb *trb = r->trb; + ++ trb = r->trb + i; + trb->ctrl &= ~DWC3_TRB_CTRL_HWO; + dwc3_ep_inc_deq(dep); +- +- if (r->needs_extra_trb) { +- trb = r->trb + 1; +- trb->ctrl &= ~DWC3_TRB_CTRL_HWO; +- dwc3_ep_inc_deq(dep); +- } + } + goto out1; + } +@@ -1441,8 +1423,6 @@ static int dwc3_gadget_ep_dequeue(struct usb_ep *ep, + } + + out1: +- /* giveback the request */ +- + dwc3_gadget_giveback(dep, req, -ECONNRESET); + + out0: +-- +2.20.1 +