aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFelipe Balbi <felipe.balbi@linux.intel.com>2019-01-21 13:01:16 +0200
committerFelipe Balbi <felipe.balbi@linux.intel.com>2019-02-04 08:46:01 +0200
commit9f45581f5eec6786c6eded2b3c85345d82a910c9 (patch)
tree1165aec166fec9bf1e6926a78a2b0dedfcb6e2d5
parentusb: dwc3: gadget: don't use resource_index as a flag (diff)
downloadlinux-dev-9f45581f5eec6786c6eded2b3c85345d82a910c9.tar.xz
linux-dev-9f45581f5eec6786c6eded2b3c85345d82a910c9.zip
usb: dwc3: gadget: early giveback if End Transfer already completed
There is a rare race condition that may happen during a Disconnect Interrupt if we have a started request that happens to be dequeued *after* completion of End Transfer command. If that happens, that request will be left waiting for completion of an End Transfer command that will never happen. If End Transfer command has already completed before, we are safe to giveback the request straight away. Tested-by: Thinh Nguyen <thinhn@synopsys.com> Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
-rw-r--r--drivers/usb/dwc3/gadget.c6
1 files changed, 5 insertions, 1 deletions
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index eaeea8ff5191..b82a8885747d 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -1550,7 +1550,10 @@ static int dwc3_gadget_ep_dequeue(struct usb_ep *ep,
goto out0;
dwc3_gadget_move_cancelled_request(req);
- goto out0;
+ if (dep->flags & DWC3_EP_TRANSFER_STARTED)
+ goto out0;
+ else
+ goto out1;
}
dev_err(dwc->dev, "request %pK was not queued to %s\n",
request, ep->name);
@@ -1558,6 +1561,7 @@ static int dwc3_gadget_ep_dequeue(struct usb_ep *ep,
goto out0;
}
+out1:
dwc3_gadget_giveback(dep, req, -ECONNRESET);
out0: