From 970a014b7d7dd9b78084fbb498a3ec7591517774 Mon Sep 17 00:00:00 2001 From: Udipto Goswami Date: Mon, 10 May 2021 14:05:18 +0530 Subject: [PATCH] usb: dwc3: Handle race between remove_request and ep_dequeue Commit 3ef97296e7b5 ("usb: dwc3: gadget: Handle race between remove_request & ep_dequeue") was introduced to fix the race between remove_requests & dequeue process,but it exposes a new issue where we see crash on ep_set_halt where the started list gets corrupted since composite cleanup already did a free_req. Fix this by reverting the older patch and handling the race of remove_requests & dequeue in cleanup_cancelled_request by iterating over the list using while loop which will insure to access the first node from list_head. Change-Id: I727ca54e5ac839ceb55efb644a7cd8d514db63b6 Signed-off-by: Udipto Goswami --- drivers/usb/dwc3/gadget.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index c6dab7fa8351..f2b8665324f1 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1778,11 +1778,11 @@ 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; struct dwc3 *dwc = dep->dwc; int request_count = 0; - list_for_each_entry_safe(req, tmp, &dep->cancelled_list, list) { + while (!list_empty(&dep->cancelled_list)) { + req = next_request(&dep->cancelled_list); dwc3_gadget_ep_skip_trbs(dep, req); dwc3_gadget_giveback(dep, req, -ECONNRESET); request_count++; @@ -1851,8 +1851,7 @@ static int dwc3_gadget_ep_dequeue(struct usb_ep *ep, /* If ep isn't started, then there's no end transfer * pending */ - if ((dep->flags & DWC3_EP_TRANSFER_STARTED) && - !(dep->flags & DWC3_EP_END_TRANSFER_PENDING)) + if (!(dep->flags & DWC3_EP_END_TRANSFER_PENDING)) dwc3_gadget_ep_cleanup_cancelled_requests(dep); goto out; @@ -3583,11 +3582,8 @@ int dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force, bool interrupt) ret = dwc3_send_gadget_ep_cmd(dep, cmd, ¶ms); WARN_ON_ONCE(ret); dep->resource_index = 0; - if (ret == -ETIMEDOUT) { - dbg_log_string("%s(%d): endxfer ret:%d", - dep->name, dep->number, ret); - return ret; - } + + dbg_log_string("%s(%d): endxfer ret:%d", dep->name, dep->number, ret); if (!interrupt) dep->flags &= ~DWC3_EP_TRANSFER_STARTED;