summaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2019-09-16 14:43:44 +0200
committerSascha Hauer <s.hauer@pengutronix.de>2019-09-17 11:51:18 +0200
commitb4a48f48ee7691af9aa907ad3d388f153647fb81 (patch)
tree666e31b19788b8388efb758a17cf1b595409aafc /drivers/usb
parent496576955a3889ad784ada8467de3c842338fc09 (diff)
downloadbarebox-b4a48f48ee7691af9aa907ad3d388f153647fb81.tar.gz
barebox-b4a48f48ee7691af9aa907ad3d388f153647fb81.tar.xz
usb: gadget: composite: conditionally dequeue setup requests
This is an adoption of Kernel commit a7c12eaf2 ("usb: gadget: composite: conditionally dequeue os_desc and setup requests"). Basically we only want to dequeue ep0 requests when they are actually queued. Drivers like dwc3 warn when unqueued requests are being tried to unqueued. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/gadget/composite.c43
1 files changed, 40 insertions, 3 deletions
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index 1cfc49d1c5..b66aa6be97 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -1194,10 +1194,45 @@ EXPORT_SYMBOL_GPL(usb_string_ids_n);
static void composite_setup_complete(struct usb_ep *ep, struct usb_request *req)
{
+ struct usb_composite_dev *cdev;
+
if (req->status || req->actual != req->length)
DBG((struct usb_composite_dev *) ep->driver_data,
"setup complete --> %d, %d/%d\n",
req->status, req->actual, req->length);
+
+ /*
+ * REVIST The same ep0 requests are shared with function drivers
+ * so they don't have to maintain the same ->complete() stubs.
+ *
+ * Because of that, we need to check for the validity of ->context
+ * here, even though we know we've set it to something useful.
+ */
+ if (!req->context)
+ return;
+
+ cdev = req->context;
+
+ if (cdev->req == req)
+ cdev->setup_pending = false;
+ else
+ WARN(1, "unknown request %p\n", req);
+}
+
+static int composite_ep0_queue(struct usb_composite_dev *cdev,
+ struct usb_request *req)
+{
+ int ret;
+
+ ret = usb_ep_queue(cdev->gadget->ep0, req);
+ if (ret == 0) {
+ if (cdev->req == req)
+ cdev->setup_pending = true;
+ else
+ WARN(1, "unknown request %p\n", req);
+ }
+
+ return ret;
}
/*
@@ -1226,6 +1261,7 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
* when we delegate to it.
*/
req->zero = 0;
+ req->context = cdev;
req->complete = composite_setup_complete;
req->length = 0;
gadget->ep0->driver_data = cdev;
@@ -1469,7 +1505,7 @@ unknown:
if (value >= 0 && value != USB_GADGET_DELAYED_STATUS) {
req->length = value;
req->zero = value < w_length;
- value = usb_ep_queue(gadget->ep0, req);
+ value = composite_ep0_queue(cdev, req);
if (value < 0) {
DBG(cdev, "ep_queue --> %d\n", value);
req->status = 0;
@@ -1621,7 +1657,8 @@ void composite_dev_cleanup(struct usb_composite_dev *cdev)
kfree(uc);
}
if (cdev->req) {
- usb_ep_dequeue(cdev->gadget->ep0, cdev->req);
+ if (cdev->setup_pending)
+ usb_ep_dequeue(cdev->gadget->ep0, cdev->req);
kfree(cdev->req->buf);
usb_ep_free_request(cdev->gadget->ep0, cdev->req);
}
@@ -1753,7 +1790,7 @@ void usb_composite_setup_continue(struct usb_composite_dev *cdev)
} else if (--cdev->delayed_status == 0) {
DBG(cdev, "%s: Completing delayed status\n", __func__);
req->length = 0;
- value = usb_ep_queue(cdev->gadget->ep0, req);
+ value = composite_ep0_queue(cdev, req);
if (value < 0) {
DBG(cdev, "ep_queue --> %d\n", value);
req->status = 0;