Skip to content

Commit 855ed04

Browse files
rbilovolFelipe Balbi
authored andcommitted
usb: gadget: udc-core: independent registration of gadgets and gadget drivers
Change behavior during registration of gadgets and gadget drivers in udc-core. Instead of previous approach when for successful probe of usb gadget driver at least one usb gadget should be already registered use another one where gadget drivers and gadgets can be registered in udc-core independently. Independent registration of gadgets and gadget drivers is useful for built-in into kernel gadget and gadget driver case - because it's possible that gadget is really probed only on late_init stage (due to deferred probe) whereas gadget driver's probe is silently failed on module_init stage due to no any UDC added. Also it is useful for modules case - now there is no difference what module to insert first: gadget module or gadget driver one. Tested-by: Maxime Ripard <maxime.ripard@free-electrons.com> Signed-off-by: Ruslan Bilovol <ruslan.bilovol@gmail.com> [simplified code as requested by Alan Stern and Felipe Balbi, fixed checkpatch issues] Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com> Tested-by: Peter Chen <peter.chen@freescale.com> Signed-off-by: Felipe Balbi <balbi@ti.com>
1 parent 88f73eb commit 855ed04

File tree

2 files changed

+34
-9
lines changed

2 files changed

+34
-9
lines changed

drivers/usb/gadget/udc/udc-core.c

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,12 @@ struct usb_udc {
5151

5252
static struct class *udc_class;
5353
static LIST_HEAD(udc_list);
54+
static LIST_HEAD(gadget_driver_pending_list);
5455
static DEFINE_MUTEX(udc_lock);
5556

57+
static int udc_bind_to_driver(struct usb_udc *udc,
58+
struct usb_gadget_driver *driver);
59+
5660
/* ------------------------------------------------------------------------- */
5761

5862
#ifdef CONFIG_HAS_DMA
@@ -356,6 +360,7 @@ int usb_add_gadget_udc_release(struct device *parent, struct usb_gadget *gadget,
356360
void (*release)(struct device *dev))
357361
{
358362
struct usb_udc *udc;
363+
struct usb_gadget_driver *driver;
359364
int ret = -ENOMEM;
360365

361366
udc = kzalloc(sizeof(*udc), GFP_KERNEL);
@@ -403,6 +408,18 @@ int usb_add_gadget_udc_release(struct device *parent, struct usb_gadget *gadget,
403408
usb_gadget_set_state(gadget, USB_STATE_NOTATTACHED);
404409
udc->vbus = true;
405410

411+
/* pick up one of pending gadget drivers */
412+
list_for_each_entry(driver, &gadget_driver_pending_list, pending) {
413+
if (!driver->udc_name || strcmp(driver->udc_name,
414+
dev_name(&udc->dev)) == 0) {
415+
ret = udc_bind_to_driver(udc, driver);
416+
if (ret)
417+
goto err4;
418+
list_del(&driver->pending);
419+
break;
420+
}
421+
}
422+
406423
mutex_unlock(&udc_lock);
407424

408425
return 0;
@@ -473,10 +490,14 @@ void usb_del_gadget_udc(struct usb_gadget *gadget)
473490

474491
mutex_lock(&udc_lock);
475492
list_del(&udc->list);
476-
mutex_unlock(&udc_lock);
477493

478-
if (udc->driver)
494+
if (udc->driver) {
495+
struct usb_gadget_driver *driver = udc->driver;
496+
479497
usb_gadget_remove_driver(udc);
498+
list_add(&driver->pending, &gadget_driver_pending_list);
499+
}
500+
mutex_unlock(&udc_lock);
480501

481502
kobject_uevent(&udc->dev.kobj, KOBJ_REMOVE);
482503
flush_work(&gadget->work);
@@ -535,11 +556,7 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver)
535556
if (!ret)
536557
break;
537558
}
538-
if (ret)
539-
ret = -ENODEV;
540-
else if (udc->driver)
541-
ret = -EBUSY;
542-
else
559+
if (!ret && !udc->driver)
543560
goto found;
544561
} else {
545562
list_for_each_entry(udc, &udc_list, list) {
@@ -549,9 +566,11 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver)
549566
}
550567
}
551568

552-
pr_debug("couldn't find an available UDC\n");
569+
list_add_tail(&driver->pending, &gadget_driver_pending_list);
570+
pr_info("udc-core: couldn't find an available UDC - added [%s] to list of pending drivers\n",
571+
driver->function);
553572
mutex_unlock(&udc_lock);
554-
return ret;
573+
return 0;
555574
found:
556575
ret = udc_bind_to_driver(udc, driver);
557576
mutex_unlock(&udc_lock);
@@ -577,6 +596,10 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
577596
break;
578597
}
579598

599+
if (ret) {
600+
list_del(&driver->pending);
601+
ret = 0;
602+
}
580603
mutex_unlock(&udc_lock);
581604
return ret;
582605
}

include/linux/usb/gadget.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1014,6 +1014,7 @@ static inline int usb_gadget_activate(struct usb_gadget *gadget)
10141014
* @driver: Driver model state for this driver.
10151015
* @udc_name: A name of UDC this driver should be bound to. If udc_name is NULL,
10161016
* this driver will be bound to any available UDC.
1017+
* @pending: UDC core private data used for deferred probe of this driver.
10171018
*
10181019
* Devices are disabled till a gadget driver successfully bind()s, which
10191020
* means the driver will handle setup() requests needed to enumerate (and
@@ -1076,6 +1077,7 @@ struct usb_gadget_driver {
10761077
struct device_driver driver;
10771078

10781079
char *udc_name;
1080+
struct list_head pending;
10791081
};
10801082

10811083

0 commit comments

Comments
 (0)