summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorDanny Segal <dsegal@codeaurora.org>2014-07-09 15:14:49 +0300
committerDavid Keitel <dkeitel@codeaurora.org>2016-03-22 11:02:43 -0700
commit4571803aa1530b3fdfae0e8b1ad0e5df4372d873 (patch)
tree0440487c7ee236ca8e77c6db41fadd56a926a896 /drivers
parent70ba8d2a946a2bbe736f97e3c3208fb39eaeef58 (diff)
usb: gadget: Fix Missing Function Wakeup notification sending on BAM wakeup
In Super-Speed mode, when the USB core wishes to issue remote wakeup due to new data arriving on the BAM to BAM path, it needs to send Function Wakeup notification to the USB host after the USB bus is resumed. However, the sending of this notification fails when the USB core needs to wake up from low-power mode, because the low-power mode exit is done asynchronously and the sending of the Function Wakeup notification can not be done until the USB bus is resumed. This patch fixes this issue by checking whether the USB bus is suspended, and if so, the sending Function Wakeup notification is delayed until the USB bus is resumed. Change-Id: I293476aaaf920b67fdbdf72a63524edc7a35750b Signed-off-by: Danny Segal <dsegal@codeaurora.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/usb/gadget/composite.c15
1 files changed, 14 insertions, 1 deletions
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index 7735bc9ed892..b7ca27e095f9 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -424,17 +424,21 @@ int usb_func_wakeup(struct usb_function *func)
if (ret) {
if (ret == -EAGAIN) {
DBG(func->config->cdev,
- "Function wakeup for %s could not be complete. Retry is needed.\n",
+ "Function wakeup for %s could not complete due to suspend state. Delayed until after bus resume.\n",
func->name ? func->name : "");
+ func->func_wakeup_pending = true;
+ ret = 0;
} else {
ERROR(func->config->cdev,
"Failed to wake function %s from suspend state. interface id: %d, ret=%d. Canceling USB request.\n",
func->name ? func->name : "",
interface_id, ret);
}
+
return ret;
}
+ func->func_wakeup_pending = false;
return 0;
}
EXPORT_SYMBOL_GPL(usb_func_wakeup);
@@ -2266,6 +2270,7 @@ void composite_resume(struct usb_gadget *gadget)
struct usb_composite_dev *cdev = get_gadget_data(gadget);
struct usb_function *f;
u16 maxpower;
+ int ret;
/* REVISIT: should we have config level
* suspend/resume callbacks?
@@ -2275,6 +2280,14 @@ void composite_resume(struct usb_gadget *gadget)
cdev->driver->resume(cdev);
if (cdev->config) {
list_for_each_entry(f, &cdev->config->functions, list) {
+ if (f->func_wakeup_pending) {
+ ret = usb_func_wakeup(f);
+ if (ret)
+ ERROR(cdev,
+ "Failed to send function wakeup notification for the %s function. Error code: %d\n",
+ f->name ? f->name : "", ret);
+ }
+
if (f->resume)
f->resume(f);
}