summaryrefslogtreecommitdiff
path: root/drivers/usb/gadget/composite.c
diff options
context:
space:
mode:
authorHemant Kumar <hemantk@codeaurora.org>2015-09-24 21:05:53 -0700
committerDavid Keitel <dkeitel@codeaurora.org>2016-03-22 11:02:54 -0700
commit28ddcdd099b0514ac938eac487324f7b2c365ef5 (patch)
treef8c5c4f1c797bad51b1f753b4c109d6fd09a2f0f /drivers/usb/gadget/composite.c
parentf8f56d6a1dce29eeaf1523fe4a0c490fe3bc1a3b (diff)
usb: gadget: Fix bug is queuing req upon Function Suspend
In case of Super speed function suspend without bus suspend, if function driver queues a request, usb_gadget_func_wakeup() directly issues Function Wakeup command to controller and returns success. As a result request is queued to endpoint before receiving function resume from host. This causes ep queue to fail when it is done upon function resume as request is already queued. If function driver tries to queue any request further this results into request packet drop as ep queue returns error -EBUSY. Hence do not queue request in function wake up context, instead wait for function resume to queue the request. CRs-Fixed: 848622 Change-Id: I00aea59fb2cbe59190dadb4c838534cc9e4ffcf3 Signed-off-by: Hemant Kumar <hemantk@codeaurora.org>
Diffstat (limited to 'drivers/usb/gadget/composite.c')
-rw-r--r--drivers/usb/gadget/composite.c19
1 files changed, 12 insertions, 7 deletions
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index 420fae593b0a..474b6ac1b5fb 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -422,12 +422,14 @@ EXPORT_SYMBOL_GPL(usb_func_wakeup);
int usb_func_ep_queue(struct usb_function *func, struct usb_ep *ep,
struct usb_request *req, gfp_t gfp_flags)
{
- int ret = -ENOTSUPP;
+ int ret;
struct usb_gadget *gadget;
if (!func || !func->config || !func->config->cdev ||
- !func->config->cdev->gadget || !ep || !req)
- return -EINVAL;
+ !func->config->cdev->gadget || !ep || !req) {
+ ret = -EINVAL;
+ goto done;
+ }
pr_debug("Function %s queueing new data into ep %u\n",
func->name ? func->name : "", ep->address);
@@ -443,13 +445,16 @@ int usb_func_ep_queue(struct usb_function *func, struct usb_ep *ep,
pr_err("Failed to wake function %s from suspend state. ret=%d.\n",
func->name ? func->name : "", ret);
}
+ goto done;
}
- if (!func->func_is_suspended)
- ret = 0;
+ if (func->func_is_suspended && !func->func_wakeup_allowed) {
+ ret = -ENOTSUPP;
+ goto done;
+ }
- if (!ret)
- ret = usb_ep_queue(ep, req, gfp_flags);
+ ret = usb_ep_queue(ep, req, gfp_flags);
+done:
return ret;
}