diff options
author | Hemant Kumar <hemantk@codeaurora.org> | 2015-09-24 21:05:53 -0700 |
---|---|---|
committer | David Keitel <dkeitel@codeaurora.org> | 2016-03-22 11:02:54 -0700 |
commit | 28ddcdd099b0514ac938eac487324f7b2c365ef5 (patch) | |
tree | f8c5c4f1c797bad51b1f753b4c109d6fd09a2f0f /drivers/usb/gadget/composite.c | |
parent | f8f56d6a1dce29eeaf1523fe4a0c490fe3bc1a3b (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.c | 19 |
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; } |