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: stable@vger.kernel.org Signed-off-by: Jack Pham jackp@codeaurora.org --- v2: Added Fixes tag and Cc: stable
Felipe, as I mentioned in the cover for v1, for stable (from 4.11 where c6267a51639b first landed through 4.20), the fix needs to be modified to assign to the separate req->unaligned and req->zero flags in lieu of needs_extra_trb which appeared in 5.0-rc1 in:
commit 1a22ec643580626f439c8583edafdcc73798f2fb Author: Felipe Balbi felipe.balbi@linux.intel.com Date: Wed Aug 1 13:15:05 2018 +0300
usb: dwc3: gadget: combine unaligned and zero flags
Do I need to send a separate patch for <= 4.20 or will you handle it? It's straightforward really, the code change should instead be
+ req->unaligned = false; + req->zero = false;
Thanks, Jack
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 2ecde30ad0b7..e97b14f444c8 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;
linux-stable-mirror@lists.linaro.org