patch "usb: gadget: udc-core: Rescan pending list on driver unbind" added to usb-testing
Subsystems (2)
This is a note to let you know that I've just added the patch titled
usb: gadget: udc-core: Rescan pending list on driver unbind
to my usb git tree which can be found at
git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb.git
in the usb-testing branch.
The patch will show up in the next release of the linux-next tree (usually sometime within the next 24 hours during the week.)
The patch will be merged to the usb-next branch sometime soon, after it passes testing, and the merge window is open.
If you have any questions about this process, please let me know.
Quoted 1 line
From
8236800da115a3e24b9165c573067343f51cf5eaMon Sep 17 00:00:00 2001
From: Krzysztof Opasiak <[email protected]>
Date: Mon, 16 Jan 2017 08:40:57 +0100
Subject: usb: gadget: udc-core: Rescan pending list on driver unbind
Since:
commit 855ed04a3758 ("usb: gadget: udc-core: independent registration of gadgets and gadget drivers")
if we load gadget module but there is no free udc available then it will be stored on a pending gadgets list.
$ modprobe g_zero.ko $ modprobe g_ether.ko [] udc-core: couldn't find an available UDC - added [g_ether] to list of pending drivers
We scan this list each time when new UDC appears in system. But we can get a free UDC each time after gadget unbind. This commit add scanning of that list directly after unbinding gadget from udc.
Thanks to this, when we unload first gadget:
$ rmmod g_zero.ko
gadget which is pending is automatically
attached to that UDC (if name matches).
--- drivers/usb/gadget/udc/core.c | 45 +++++++++++++++++++++++++++++-------------- 1 file changed, 31 insertions(+), 14 deletions(-)
drivers/usb/gadget/udc/core.c +31 -14
@@ -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);
Signature · 1 line
2.11.0