usb: gadget: udc-core: Rescan pending list on driver unbind

am: 881b522555

Change-Id: Id3dac54a14ec80d311633951d0b2e1e566678c97
This commit is contained in:
Krzysztof Opasiak
2017-03-12 08:27:00 +00:00
committed by android-build-merger

View File

@@ -1080,6 +1080,24 @@ static void usb_udc_nop_release(struct device *dev)
dev_vdbg(dev, "%s\n", __func__);
}
/* should be called with udc_lock held */
static int check_pending_gadget_drivers(struct usb_udc *udc)
{
struct usb_gadget_driver *driver;
int ret = 0;
list_for_each_entry(driver, &gadget_driver_pending_list, pending)
if (!driver->udc_name || strcmp(driver->udc_name,
dev_name(&udc->dev)) == 0) {
ret = udc_bind_to_driver(udc, driver);
if (ret != -EPROBE_DEFER)
list_del(&driver->pending);
break;
}
return ret;
}
/**
* usb_add_gadget_udc_release - adds a new gadget to the udc class driver list
* @parent: the parent device to this udc. Usually the controller driver's
@@ -1093,7 +1111,6 @@ int usb_add_gadget_udc_release(struct device *parent, struct usb_gadget *gadget,
void (*release)(struct device *dev))
{
struct usb_udc *udc;
struct usb_gadget_driver *driver;
int ret = -ENOMEM;
udc = kzalloc(sizeof(*udc), GFP_KERNEL);
@@ -1136,17 +1153,9 @@ int usb_add_gadget_udc_release(struct device *parent, struct usb_gadget *gadget,
udc->vbus = true;
/* pick up one of pending gadget drivers */
list_for_each_entry(driver, &gadget_driver_pending_list, pending) {
if (!driver->udc_name || strcmp(driver->udc_name,
dev_name(&udc->dev)) == 0) {
ret = udc_bind_to_driver(udc, driver);
if (ret != -EPROBE_DEFER)
list_del(&driver->pending);
if (ret)
goto err5;
break;
}
}
ret = check_pending_gadget_drivers(udc);
if (ret)
goto err5;
mutex_unlock(&udc_lock);
@@ -1356,14 +1365,22 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
return -EINVAL;
mutex_lock(&udc_lock);
list_for_each_entry(udc, &udc_list, list)
list_for_each_entry(udc, &udc_list, list) {
if (udc->driver == driver) {
usb_gadget_remove_driver(udc);
usb_gadget_set_state(udc->gadget,
USB_STATE_NOTATTACHED);
USB_STATE_NOTATTACHED);
/* Maybe there is someone waiting for this UDC? */
check_pending_gadget_drivers(udc);
/*
* For now we ignore bind errors as probably it's
* not a valid reason to fail other's gadget unbind
*/
ret = 0;
break;
}
}
if (ret) {
list_del(&driver->pending);