[RFC][PATCH v2 10/13] udc-core: fix lock circular dependency on udc_lock

From: Roger Quadros
Date: Tue Apr 14 2015 - 06:43:51 EST


we need to unlock the usb_lock mutex before calling
usb_otg_register_gadget() else it will cause a
circular locking dependency.

Signed-off-by: Roger Quadros <rogerq@xxxxxx>
---
drivers/usb/gadget/udc/udc-core.c | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/gadget/udc/udc-core.c b/drivers/usb/gadget/udc/udc-core.c
index ad162e5..6246d09 100644
--- a/drivers/usb/gadget/udc/udc-core.c
+++ b/drivers/usb/gadget/udc/udc-core.c
@@ -399,6 +399,7 @@ int usb_add_gadget_udc(struct device *parent, struct usb_gadget *gadget)
}
EXPORT_SYMBOL_GPL(usb_add_gadget_udc);

+/* udc_lock must be held */
static void usb_gadget_remove_driver(struct usb_udc *udc)
{
dev_dbg(&udc->dev, "unregistering UDC driver [%s]\n",
@@ -407,7 +408,11 @@ static void usb_gadget_remove_driver(struct usb_udc *udc)
kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE);

/* If OTG, the otg core ensures UDC is stopped on unregister */
- if (usb_otg_unregister_gadget(udc->gadget)) {
+ if (udc->is_otg) {
+ mutex_unlock(&udc_lock);
+ usb_otg_unregister_gadget(udc->gadget);
+ mutex_lock(&udc_lock);
+ } else {
usb_gadget_disconnect(udc->gadget);
udc->driver->disconnect(udc->gadget);
usb_gadget_udc_stop(udc);
@@ -445,11 +450,12 @@ found:
dev_vdbg(gadget->dev.parent, "unregistering gadget\n");

list_del(&udc->list);
- mutex_unlock(&udc_lock);

if (udc->driver)
usb_gadget_remove_driver(udc);

+ mutex_unlock(&udc_lock);
+
kobject_uevent(&udc->dev.kobj, KOBJ_REMOVE);
flush_work(&gadget->work);
device_unregister(&udc->dev);
@@ -459,6 +465,7 @@ EXPORT_SYMBOL_GPL(usb_del_gadget_udc);

/* ------------------------------------------------------------------------- */

+/* udc_lock must be held */
static int udc_bind_to_driver(struct usb_udc *udc, struct usb_gadget_driver *driver)
{
int ret;
@@ -475,7 +482,9 @@ static int udc_bind_to_driver(struct usb_udc *udc, struct usb_gadget_driver *dri
goto err1;

/* If OTG, the otg core starts the UDC when needed */
+ mutex_unlock(&udc_lock);
udc->is_otg = !usb_otg_register_gadget(udc->gadget);
+ mutex_lock(&udc_lock);
if (!udc->is_otg) {
ret = usb_gadget_udc_start(udc);
if (ret) {
--
2.1.0

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/