Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1162308AbbKTJpp (ORCPT ); Fri, 20 Nov 2015 04:45:45 -0500 Received: from mailout2.w1.samsung.com ([210.118.77.12]:15715 "EHLO mailout2.w1.samsung.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S934085AbbKTJpm (ORCPT ); Fri, 20 Nov 2015 04:45:42 -0500 X-AuditID: cbfec7f4-f79026d00000418a-9a-564eebc35a27 Subject: Re: [PATCH v6 4/4] usb: gadget: udc-core: independent registration of gadgets and gadget drivers To: Peter Chen References: <1448009652-14716-1-git-send-email-m.szyprowski@samsung.com> <1448009652-14716-5-git-send-email-m.szyprowski@samsung.com> <20151120092652.GF30829@shlinux2> Cc: linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, Ruslan Bilovol , Bartlomiej Zolnierkiewicz From: Marek Szyprowski Message-id: <564EEBC3.3060100@samsung.com> Date: Fri, 20 Nov 2015 10:45:39 +0100 User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:38.0) Gecko/20100101 Thunderbird/38.3.0 MIME-version: 1.0 In-reply-to: <20151120092652.GF30829@shlinux2> Content-type: text/plain; charset=utf-8; format=flowed Content-transfer-encoding: 7bit X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFjrHLMWRmVeSWpSXmKPExsVy+t/xy7qHX/uFGez8a26xccZ6VovLu+aw WSxa1spscWz2XyaLnp0nGB1YPf4d7mfy2DnrLrtH35ZVjB6fN8kFsERx2aSk5mSWpRbp2yVw Zcy7nVCwR6/i2eTXLA2MPapdjJwcEgImEpt7VzJD2GISF+6tZ+ti5OIQEljKKHF+wgJGCOc5 o8SEax/ZQKqEBbIl+qcuZgSxRQQ0JdadP8YEUbSaUeLPhQOsIA6zwAJGidnHXrKAVLEJGEp0 ve0C6+YV0JL4tfgi2D4WAVWJ+38gakQFYiTeb1rFCFEjKPFj8j2wOKeAnsTkJ2dYQWxmATOJ Ly8PQ9nyEpvXvGWewCgwC0nLLCRls5CULWBkXsUomlqaXFCclJ5rqFecmFtcmpeul5yfu4kR EspfdjAuPmZ1iFGAg1GJh7dB3C9MiDWxrLgy9xCjBAezkgjvUj+gEG9KYmVValF+fFFpTmrx IUZpDhYlcd65u96HCAmkJ5akZqemFqQWwWSZODilGhi1LEJ5VzNceOf/aMNffW4mtXlXLI3D zNT+ni3/cG6yQInHwSXP2pumXbjXzflywfklRq+rS1LabrYt8MiX6zurpWnBmBdZveTiY9/9 F31jvk14P8OmId9crmgxn7PUi5I8NrP6I38iPsvZv2Fvtj4tZdF8Y7HaZ+PFJiVpbVO27Dlx VuFDU6ESS3FGoqEWc1FxIgDljodNYQIAAA== Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 6027 Lines: 171 Hello, On 2015-11-20 10:26, Peter Chen wrote: > On Fri, Nov 20, 2015 at 09:54:12AM +0100, Marek Szyprowski wrote: >> From: Ruslan Bilovol >> >> 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 >> Signed-off-by: Ruslan Bilovol >> [simplified code as requested by Alan Stern and Felipe Balbi] >> Signed-off-by: Marek Szyprowski >> --- >> drivers/usb/gadget/udc/udc-core.c | 43 +++++++++++++++++++++++++++++++-------- >> include/linux/usb/gadget.h | 2 ++ >> 2 files changed, 37 insertions(+), 8 deletions(-) >> >> diff --git a/drivers/usb/gadget/udc/udc-core.c b/drivers/usb/gadget/udc/udc-core.c >> index f76ebc8..461b311 100644 >> --- a/drivers/usb/gadget/udc/udc-core.c >> +++ b/drivers/usb/gadget/udc/udc-core.c >> @@ -51,8 +51,12 @@ struct usb_udc { >> >> static struct class *udc_class; >> static LIST_HEAD(udc_list); >> +static LIST_HEAD(gadget_driver_pending_list); >> static DEFINE_MUTEX(udc_lock); >> >> +static int udc_bind_to_driver(struct usb_udc *udc, >> + struct usb_gadget_driver *driver); >> + >> /* ------------------------------------------------------------------------- */ >> >> #ifdef CONFIG_HAS_DMA >> @@ -356,6 +360,7 @@ 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); >> @@ -403,6 +408,18 @@ int usb_add_gadget_udc_release(struct device *parent, struct usb_gadget *gadget, >> usb_gadget_set_state(gadget, USB_STATE_NOTATTACHED); >> 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) >> + goto err4; >> + list_del(&driver->pending); >> + break; >> + } >> + } >> + >> mutex_unlock(&udc_lock); >> >> return 0; >> @@ -475,9 +492,16 @@ void usb_del_gadget_udc(struct usb_gadget *gadget) >> list_del(&udc->list); >> mutex_unlock(&udc_lock); >> >> - if (udc->driver) >> + if (udc->driver) { >> + struct usb_gadget_driver *driver = udc->driver; >> + >> usb_gadget_remove_driver(udc); >> >> + mutex_lock(&udc_lock); >> + list_add(&driver->pending, &gadget_driver_pending_list); >> + mutex_unlock(&udc_lock); >> + } >> + >> kobject_uevent(&udc->dev.kobj, KOBJ_REMOVE); >> flush_work(&gadget->work); >> device_unregister(&udc->dev); >> @@ -535,11 +559,7 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver) >> if (!ret) >> break; >> } >> - if (ret) >> - ret = -ENODEV; >> - else if (udc->driver) >> - ret = -EBUSY; >> - else >> + if (!ret && !udc->driver) >> goto found; >> } else { >> list_for_each_entry(udc, &udc_list, list) { >> @@ -549,9 +569,12 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver) >> } >> } >> >> - pr_debug("couldn't find an available UDC\n"); >> + list_add_tail(&driver->pending, &gadget_driver_pending_list); >> + pr_info("udc-core: couldn't find an available UDC " >> + "- added [%s] to list of pending drivers\n", >> + driver->function); >> mutex_unlock(&udc_lock); >> - return ret; >> + return 0; >> found: >> ret = udc_bind_to_driver(udc, driver); >> mutex_unlock(&udc_lock); >> @@ -577,6 +600,10 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) >> break; >> } >> >> + if (ret) { >> + list_del(&driver->pending); >> + ret = 0; >> + } >> mutex_unlock(&udc_lock); >> return ret; >> } >> diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h >> index e11f5a2..a3436bf 100644 >> --- a/include/linux/usb/gadget.h >> +++ b/include/linux/usb/gadget.h >> @@ -1014,6 +1014,7 @@ static inline int usb_gadget_activate(struct usb_gadget *gadget) >> * @driver: Driver model state for this driver. >> * @udc_name: A name of UDC this driver should be bound to. If udc_name is NULL, >> * this driver will be bound to any available UDC. >> + * @pending: UDC core private data used for deferred probe of this driver. >> * >> * Devices are disabled till a gadget driver successfully bind()s, which >> * means the driver will handle setup() requests needed to enumerate (and >> @@ -1076,6 +1077,7 @@ struct usb_gadget_driver { >> struct device_driver driver; >> >> char *udc_name; >> + struct list_head pending; >> }; >> >> > And it seems can't apply for felipe's testing/next which I just rebased > on it. I really have no idea why it fails for You. The patchset applies correctly on both Felipe's 'next' and 'testing/next' branches from today. Best regards -- Marek Szyprowski, PhD Samsung R&D Institute Poland -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/