aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/drivers/usb
diff options
context:
space:
mode:
authorThinh Nguyen <Thinh.Nguyen@synopsys.com>2020-05-15 16:40:46 -0700
committerFelipe Balbi <balbi@kernel.org>2020-05-25 11:09:44 +0300
commit63c7bb299fc9c430070c0177f0879635e9ee23d0 (patch)
tree98f575c10445c788d62f0bad36dfbd49cd677257 /drivers/usb
parentusb: gadget: Fix issue with config_ep_by_speed function (diff)
downloadwireguard-linux-63c7bb299fc9c430070c0177f0879635e9ee23d0.tar.xz
wireguard-linux-63c7bb299fc9c430070c0177f0879635e9ee23d0.zip
usb: dwc3: gadget: Check for prepared TRBs
There are cases where the endpoint needs to be restarted. For example, it may need to restart for NoStream rejection to reinitiate stream. If so, check and make sure we don't prepare beyond the current transfer when we restart the endpoint. DWC_usb32 internal burst transfer feature will look into TRBs beyond a transfer. Other controllers will stop on the last TRB, but not DWC_usb32. This may cause the controller to incorrectly process TRBs of a different transfer. Make sure to explicitly prevent preparing TRBs of a different transfer. This should only affect DWC_usb32 releases prior to v1.00a since it doesn't use SET_ENDPOINT_PRIME to reinitiate stream. However, it's better to be cautious in case users don't want to use SET_ENDPOINT_PRIME command. Also, it's possible other controller IPs may share the same features as DWC_usb32 in new releases. Signed-off-by: Thinh Nguyen <thinhn@synopsys.com> Signed-off-by: Felipe Balbi <balbi@kernel.org>
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/dwc3/gadget.c8
1 files changed, 8 insertions, 0 deletions
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 7739fe054e34..f5fbe784fa04 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -1232,6 +1232,14 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep)
if (!dwc3_calc_trbs_left(dep))
return;
+
+ /*
+ * Don't prepare beyond a transfer. In DWC_usb32, its transfer
+ * burst capability may try to read and use TRBs beyond the
+ * active transfer instead of stopping.
+ */
+ if (dep->stream_capable && req->request.is_last)
+ return;
}
list_for_each_entry_safe(req, n, &dep->pending_list, list) {