RE: Disable bus's drivers_autoprobe before rootfs has mounted

From: Alan Stern
Date: Fri Jun 13 2014 - 10:19:43 EST


On Fri, 13 Jun 2014, Peter Chen wrote:

> OK, we can keep our g_xxx gadget driver just support the basic feature. But
> the bug that causes gadget driver load fail due to udc is probed deferral should
> be fixed, do you think so, we can't wait until configfs has total been ready.

That problem has always existed. There never has been a time when a
gadget driver could be loaded before the UDC driver was ready. Does it
really need to be fixed now?

If you do want to fix the problem, there's a much easier way than what
you posted. See below.

Alan Stern



Index: usb-3.15/include/linux/usb/gadget.h
===================================================================
--- usb-3.15.orig/include/linux/usb/gadget.h
+++ usb-3.15/include/linux/usb/gadget.h
@@ -821,6 +821,7 @@ static inline int usb_gadget_disconnect(
* @suspend: Invoked on USB suspend. May be called in_interrupt.
* @resume: Invoked on USB resume. May be called in_interrupt.
* @driver: Driver model state for this driver.
+ * @probe_list: List of drivers waiting to be probed.
*
* Devices are disabled till a gadget driver successfully bind()s, which
* means the driver will handle setup() requests needed to enumerate (and
@@ -881,6 +882,7 @@ struct usb_gadget_driver {

/* FIXME support safe rmmod */
struct device_driver driver;
+ struct list_head probe_list;
};


Index: usb-3.15/drivers/usb/gadget/udc-core.c
===================================================================
--- usb-3.15.orig/drivers/usb/gadget/udc-core.c
+++ usb-3.15/drivers/usb/gadget/udc-core.c
@@ -47,8 +47,12 @@ struct usb_udc {

static struct class *udc_class;
static LIST_HEAD(udc_list);
+static LIST_HEAD(pending_drivers);
static DEFINE_MUTEX(udc_lock);

+static int udc_bind_to_driver(struct usb_udc *udc,
+ struct usb_gadget_driver *driver);
+
/* ------------------------------------------------------------------------- */

#ifdef CONFIG_HAS_DMA
@@ -242,6 +246,15 @@ int usb_add_gadget_udc_release(struct de

usb_gadget_set_state(gadget, USB_STATE_NOTATTACHED);

+ while (!list_empty(&pending_drivers)) {
+ struct usb_gadget_driver *driver;
+
+ driver = list_first_entry(&pending_drivers,
+ struct usb_gadget_driver, probe_list);
+ if (udc_bind_to_driver(udc, driver) == 0)
+ break;
+ }
+
mutex_unlock(&udc_lock);

return 0;
@@ -338,6 +351,7 @@ static int udc_bind_to_driver(struct usb

dev_dbg(&udc->dev, "registering UDC driver [%s]\n",
driver->function);
+ list_del_init(&driver->probe_list);

udc->driver = driver;
udc->dev.driver = &driver->driver;
@@ -400,6 +414,7 @@ int usb_gadget_probe_driver(struct usb_g
return -EINVAL;

mutex_lock(&udc_lock);
+ INIT_LIST_HEAD(&driver->probe_list);
list_for_each_entry(udc, &udc_list, list) {
/* For now we take the first one */
if (!udc->driver)
@@ -407,8 +422,9 @@ int usb_gadget_probe_driver(struct usb_g
}

pr_debug("couldn't find an available UDC\n");
+ list_add_tail(&driver->probe_list, &pending_drivers);
mutex_unlock(&udc_lock);
- return -ENODEV;
+ return 0;
found:
ret = udc_bind_to_driver(udc, driver);
mutex_unlock(&udc_lock);
@@ -425,6 +441,7 @@ int usb_gadget_unregister_driver(struct
return -EINVAL;

mutex_lock(&udc_lock);
+ list_del(&driver->probe_list);
list_for_each_entry(udc, &udc_list, list)
if (udc->driver == driver) {
usb_gadget_remove_driver(udc);


--
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/