Consider a scenario where cable disconnect happens when there is an active usb reqest queued to the UDC. As part of the disconnect we would issue an end transfer with no interrupt-on-completion before giving back this request. Since we are giving back the request without skipping TRBs the num_trbs field of dwc3_request still holds the stale value previously used. Function drivers re-use same request for a given bind-unbind session and hence their dwc3_request context gets preserved across cable disconnect/connect. When such a request gets re-queued after cable connect, we would increase the num_trbs field on top of the previous stale value thus incorrectly representing the number of TRBs used. Fix this by invoking skip_trbs() in the ep disable path. Signed-off-by: Elson Roy Serrao <quic_eserrao@xxxxxxxxxxx> --- drivers/usb/dwc3/gadget.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 578804d..b45e917 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -986,6 +986,8 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep, unsigned int action) return 0; } +static void dwc3_gadget_ep_skip_trbs(struct dwc3_ep *dep, struct dwc3_request *req); + void dwc3_remove_requests(struct dwc3 *dwc, struct dwc3_ep *dep, int status) { struct dwc3_request *req; @@ -1000,6 +1002,7 @@ void dwc3_remove_requests(struct dwc3 *dwc, struct dwc3_ep *dep, int status) while (!list_empty(&dep->started_list)) { req = next_request(&dep->started_list); + dwc3_gadget_ep_skip_trbs(dep, req); dwc3_gadget_giveback(dep, req, status); } @@ -1012,6 +1015,7 @@ void dwc3_remove_requests(struct dwc3 *dwc, struct dwc3_ep *dep, int status) while (!list_empty(&dep->cancelled_list)) { req = next_request(&dep->cancelled_list); + dwc3_gadget_ep_skip_trbs(dep, req); dwc3_gadget_giveback(dep, req, status); } } -- 2.7.4