Re: Disable bus's drivers_autoprobe before rootfs has mounted

From: Peter Chen
Date: Sun Jun 15 2014 - 23:04:09 EST


On Fri, Jun 13, 2014 at 10:19:36AM -0400, Alan Stern wrote:
> 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?
>

Yes, otherwise, the device which the udc is probed deferral and the
gadget driver is build-in will never work. If we skip fixing it, this
problem will exist for more than 2 years, it is too long.

I have a support request from android team that usb peripheral function
never works from 3.10.x kernel at one device, I think it is a common problem,
no only I meet it.

Below are links which this problem reports:

http://marc.info/?l=linux-usb&m=139380872501745&w=2
http://marc.info/?l=linux-usb&m=137706435611447&w=2

> If you do want to fix the problem, there's a much easier way than what
> you posted. See below.
>
Robert Baldyga posts the similar solution, but seems Felipe doesn't
agree it.
http://www.spinics.net/lists/linux-usb/msg102795.html

Then, you and Felipe has a discussion for this problem:
http://www.spinics.net/lists/linux-usb/msg106760.html

>
> 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);
>
>

--

Best Regards,
Peter Chen
--
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/