diff options
| author | Vijayavardhan Vennapusa <vvreddy@codeaurora.org> | 2015-02-25 10:56:20 +0530 |
|---|---|---|
| committer | David Keitel <dkeitel@codeaurora.org> | 2016-03-22 11:02:49 -0700 |
| commit | 15d49a10511d64362bdbb597c44a3337e8f54ce7 (patch) | |
| tree | fcbc309dd5842d61460286285c0ce774a3bf3b02 /drivers/usb | |
| parent | 7010bdba62be4800a89fea2317054b46481c64ca (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.c | 14 |
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; } |
