summaryrefslogtreecommitdiff
path: root/drivers/usb
diff options
context:
space:
mode:
authorVijayavardhan Vennapusa <vvreddy@codeaurora.org>2015-02-25 10:56:20 +0530
committerDavid Keitel <dkeitel@codeaurora.org>2016-03-22 11:02:49 -0700
commit15d49a10511d64362bdbb597c44a3337e8f54ce7 (patch)
treefcbc309dd5842d61460286285c0ce774a3bf3b02 /drivers/usb
parent7010bdba62be4800a89fea2317054b46481c64ca (diff)
USB: composite: Hold spinlock before calling usb_func_wakeup_int() API
There is a chance that composite_resume might race with android_disable if composition switch happens and at the same time, reset interrupt is triggered. In this case, it could lead to accessing invalid address as composite_resume() not calling usb_func_wakeup_int() without holding spinlock. Hence modfiy usb_func_wakeup_int() such that caller of this function should call it with spinlock holding to fix the issue. CRs-Fixed: 799332 Change-Id: I97ef374923504977ac8fc32954dd7de834a01041 Signed-off-by: Vijayavardhan Vennapusa <vvreddy@codeaurora.org> Signed-off-by: Azhar Shaikh <azhars@codeaurora.org>
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/gadget/composite.c14
1 files changed, 7 insertions, 7 deletions
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index bb59a2de8f1f..acb925be0482 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -367,9 +367,7 @@ EXPORT_SYMBOL_GPL(usb_interface_id);
static int usb_func_wakeup_int(struct usb_function *func)
{
int ret;
- unsigned long flags;
struct usb_gadget *gadget;
- struct usb_composite_dev *cdev;
pr_debug("%s - %s function wakeup\n",
__func__, func->name ? func->name : "");
@@ -388,11 +386,7 @@ static int usb_func_wakeup_int(struct usb_function *func)
return -ENOTSUPP;
}
- cdev = get_gadget_data(gadget);
-
- spin_lock_irqsave(&cdev->lock, flags);
ret = usb_gadget_func_wakeup(gadget, func->intf_id);
- spin_unlock_irqrestore(&cdev->lock, flags);
return ret;
}
@@ -400,10 +394,12 @@ static int usb_func_wakeup_int(struct usb_function *func)
int usb_func_wakeup(struct usb_function *func)
{
int ret;
+ unsigned long flags;
pr_debug("%s function wakeup\n",
func->name ? func->name : "");
+ spin_lock_irqsave(&func->config->cdev->lock, flags);
ret = usb_func_wakeup_int(func);
if (ret == -EAGAIN) {
DBG(func->config->cdev,
@@ -416,6 +412,7 @@ int usb_func_wakeup(struct usb_function *func)
func->name ? func->name : "", ret);
}
+ spin_unlock_irqrestore(&func->config->cdev->lock, flags);
return ret;
}
EXPORT_SYMBOL_GPL(usb_func_wakeup);
@@ -2250,7 +2247,8 @@ void composite_resume(struct usb_gadget *gadget)
struct usb_composite_dev *cdev = get_gadget_data(gadget);
struct usb_function *f;
u16 maxpower;
- int ret;
+ int ret;
+ unsigned long flags;
/* REVISIT: should we have config level
* suspend/resume callbacks?
@@ -2259,6 +2257,7 @@ void composite_resume(struct usb_gadget *gadget)
if (cdev->driver->resume)
cdev->driver->resume(cdev);
+ spin_lock_irqsave(&cdev->lock, flags);
if (cdev->config) {
list_for_each_entry(f, &cdev->config->functions, list) {
ret = usb_func_wakeup_int(f);
@@ -2286,6 +2285,7 @@ void composite_resume(struct usb_gadget *gadget)
maxpower : CONFIG_USB_GADGET_VBUS_DRAW);
}
+ spin_unlock_irqrestore(&cdev->lock, flags);
cdev->suspended = 0;
}