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>
This commit is contained in:
parent
7010bdba62
commit
15d49a1051
1 changed files with 7 additions and 7 deletions
|
@ -367,9 +367,7 @@ EXPORT_SYMBOL_GPL(usb_interface_id);
|
||||||
static int usb_func_wakeup_int(struct usb_function *func)
|
static int usb_func_wakeup_int(struct usb_function *func)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
unsigned long flags;
|
|
||||||
struct usb_gadget *gadget;
|
struct usb_gadget *gadget;
|
||||||
struct usb_composite_dev *cdev;
|
|
||||||
|
|
||||||
pr_debug("%s - %s function wakeup\n",
|
pr_debug("%s - %s function wakeup\n",
|
||||||
__func__, func->name ? func->name : "");
|
__func__, func->name ? func->name : "");
|
||||||
|
@ -388,11 +386,7 @@ static int usb_func_wakeup_int(struct usb_function *func)
|
||||||
return -ENOTSUPP;
|
return -ENOTSUPP;
|
||||||
}
|
}
|
||||||
|
|
||||||
cdev = get_gadget_data(gadget);
|
|
||||||
|
|
||||||
spin_lock_irqsave(&cdev->lock, flags);
|
|
||||||
ret = usb_gadget_func_wakeup(gadget, func->intf_id);
|
ret = usb_gadget_func_wakeup(gadget, func->intf_id);
|
||||||
spin_unlock_irqrestore(&cdev->lock, flags);
|
|
||||||
|
|
||||||
return ret;
|
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 usb_func_wakeup(struct usb_function *func)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
pr_debug("%s function wakeup\n",
|
pr_debug("%s function wakeup\n",
|
||||||
func->name ? func->name : "");
|
func->name ? func->name : "");
|
||||||
|
|
||||||
|
spin_lock_irqsave(&func->config->cdev->lock, flags);
|
||||||
ret = usb_func_wakeup_int(func);
|
ret = usb_func_wakeup_int(func);
|
||||||
if (ret == -EAGAIN) {
|
if (ret == -EAGAIN) {
|
||||||
DBG(func->config->cdev,
|
DBG(func->config->cdev,
|
||||||
|
@ -416,6 +412,7 @@ int usb_func_wakeup(struct usb_function *func)
|
||||||
func->name ? func->name : "", ret);
|
func->name ? func->name : "", ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&func->config->cdev->lock, flags);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(usb_func_wakeup);
|
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_composite_dev *cdev = get_gadget_data(gadget);
|
||||||
struct usb_function *f;
|
struct usb_function *f;
|
||||||
u16 maxpower;
|
u16 maxpower;
|
||||||
int ret;
|
int ret;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
/* REVISIT: should we have config level
|
/* REVISIT: should we have config level
|
||||||
* suspend/resume callbacks?
|
* suspend/resume callbacks?
|
||||||
|
@ -2259,6 +2257,7 @@ void composite_resume(struct usb_gadget *gadget)
|
||||||
if (cdev->driver->resume)
|
if (cdev->driver->resume)
|
||||||
cdev->driver->resume(cdev);
|
cdev->driver->resume(cdev);
|
||||||
|
|
||||||
|
spin_lock_irqsave(&cdev->lock, flags);
|
||||||
if (cdev->config) {
|
if (cdev->config) {
|
||||||
list_for_each_entry(f, &cdev->config->functions, list) {
|
list_for_each_entry(f, &cdev->config->functions, list) {
|
||||||
ret = usb_func_wakeup_int(f);
|
ret = usb_func_wakeup_int(f);
|
||||||
|
@ -2286,6 +2285,7 @@ void composite_resume(struct usb_gadget *gadget)
|
||||||
maxpower : CONFIG_USB_GADGET_VBUS_DRAW);
|
maxpower : CONFIG_USB_GADGET_VBUS_DRAW);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&cdev->lock, flags);
|
||||||
cdev->suspended = 0;
|
cdev->suspended = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue