From bd1c66bfdb14498cc3722ba48c8185437e293618 Mon Sep 17 00:00:00 2001 From: Hemant Kumar Date: Fri, 16 Nov 2018 17:24:39 -0800 Subject: [PATCH] usb: dwc3: Do not traverse list using list_for_each_safe There is a possibility of race between endpoint transfer completion context and stop active transfer context. As a result dwc3_gadget_ep_cleanup_completed_requests() iterates over started_list using list_for_each_safe while dwc3_remove_requests() is deleting req from started list. While iterating over current list node list_for_each_safe caches next list node. If the cached list node is getting deleted by dwc3_remove_requests() then request for same list node would be given back as part of endpoint transfer completion. This result into list_del corruption because list node is getting deleted twice. Fix this issue by iterating started_list using while loop and always accessing first node from list head. Change-Id: I64104a43ade015923deeb1f230a17dea08817052 Signed-off-by: Hemant Kumar Signed-off-by: Jack Pham --- drivers/usb/dwc3/gadget.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 3dfe03adc1c8..17be8ba52cfb 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -2804,11 +2804,11 @@ static void dwc3_gadget_ep_cleanup_completed_requests(struct dwc3_ep *dep, const struct dwc3_event_depevt *event, int status) { struct dwc3_request *req; - struct dwc3_request *tmp; - list_for_each_entry_safe(req, tmp, &dep->started_list, list) { + while (!list_empty(&dep->started_list)) { int ret; + req = next_request(&dep->started_list); ret = dwc3_gadget_ep_cleanup_completed_request(dep, event, req, status); if (ret)