瀏覽代碼

Merge tag 'gadget-for-v3.9' of git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb into usb-next

Felipe writes:
	usb: gadget: patches for v3.9 merge window

	finally getting rid of the old ->start()/->stop() methods
	in favor of the better and improved ->udc_start()/->udc_stop().

	There were surprisingly quite a few users left, but all of them
	have been converted.

	f_mass_storage removed some dead code, which is always great ;-)

	There's also a big cleanup to the gadget framework from Sebastian
	which gets us a lot closer to having only function drivers in
	kernel and move over to configfs-based binding.

	Other than these, there's the usual set of cleanups: s3c UDCs are
	moving over to devm_regulator_bulk_get() API, at91_udc removed
	an unnecessary check for work_pending() before scheduling and
	there's the removal of an unused variable from uac2_pcm_trigger().
Greg Kroah-Hartman 12 年之前
父節點
當前提交
cba6c85027
共有 55 個文件被更改,包括 1751 次插入1483 次删除
  1. 20 0
      drivers/usb/gadget/Kconfig
  2. 7 1
      drivers/usb/gadget/Makefile
  3. 31 11
      drivers/usb/gadget/acm_ms.c
  4. 14 45
      drivers/usb/gadget/amd5536udc.c
  5. 2 0
      drivers/usb/gadget/amd5536udc.h
  6. 2 3
      drivers/usb/gadget/at91_udc.c
  7. 27 9
      drivers/usb/gadget/cdc2.c
  8. 268 58
      drivers/usb/gadget/composite.c
  9. 8 6
      drivers/usb/gadget/dbgp.c
  10. 104 49
      drivers/usb/gadget/f_acm.c
  11. 2 3
      drivers/usb/gadget/f_fs.c
  12. 54 49
      drivers/usb/gadget/f_loopback.c
  13. 5 32
      drivers/usb/gadget/f_mass_storage.c
  14. 9 9
      drivers/usb/gadget/f_ncm.c
  15. 0 4
      drivers/usb/gadget/f_obex.c
  16. 0 4
      drivers/usb/gadget/f_serial.c
  17. 125 75
      drivers/usb/gadget/f_sourcesink.c
  18. 2 7
      drivers/usb/gadget/f_uac2.c
  19. 1 1
      drivers/usb/gadget/fsl_qe_udc.c
  20. 12 48
      drivers/usb/gadget/fsl_udc_core.c
  21. 116 0
      drivers/usb/gadget/functions.c
  22. 19 48
      drivers/usb/gadget/fusb300_udc.c
  23. 2 0
      drivers/usb/gadget/fusb300_udc.h
  24. 27 8
      drivers/usb/gadget/g_zero.h
  25. 1 1
      drivers/usb/gadget/gmidi.c
  26. 14 56
      drivers/usb/gadget/goku_udc.c
  27. 1 0
      drivers/usb/gadget/goku_udc.h
  28. 20 52
      drivers/usb/gadget/m66592-udc.c
  29. 1 0
      drivers/usb/gadget/m66592-udc.h
  30. 56 15
      drivers/usb/gadget/multi.c
  31. 99 147
      drivers/usb/gadget/mv_udc_core.c
  32. 31 12
      drivers/usb/gadget/nokia.c
  33. 13 38
      drivers/usb/gadget/omap_udc.c
  34. 14 53
      drivers/usb/gadget/pch_udc.c
  35. 14 48
      drivers/usb/gadget/pxa25x_udc.c
  36. 1 0
      drivers/usb/gadget/pxa25x_udc.h
  37. 15 46
      drivers/usb/gadget/pxa27x_udc.c
  38. 1 0
      drivers/usb/gadget/pxa27x_udc.h
  39. 1 1
      drivers/usb/gadget/r8a66597-udc.c
  40. 2 5
      drivers/usb/gadget/s3c-hsotg.c
  41. 6 7
      drivers/usb/gadget/s3c-hsudc.c
  42. 12 53
      drivers/usb/gadget/s3c2410_udc.c
  43. 1 0
      drivers/usb/gadget/s3c2410_udc.h
  44. 100 18
      drivers/usb/gadget/serial.c
  45. 0 61
      drivers/usb/gadget/storage_common.c
  46. 157 156
      drivers/usb/gadget/u_serial.c
  47. 10 3
      drivers/usb/gadget/u_serial.h
  48. 63 94
      drivers/usb/gadget/udc-core.c
  49. 1 1
      drivers/usb/gadget/webcam.c
  50. 157 76
      drivers/usb/gadget/zero.c
  51. 0 1
      drivers/usb/host/ehci-mv.c
  52. 22 60
      drivers/usb/otg/mv_otg.c
  53. 1 1
      drivers/usb/renesas_usbhs/mod_gadget.c
  54. 73 2
      include/linux/usb/composite.h
  55. 7 6
      include/linux/usb/gadget.h

+ 20 - 0
drivers/usb/gadget/Kconfig

@@ -500,6 +500,15 @@ config USB_LIBCOMPOSITE
 	tristate
 	tristate
 	depends on USB_GADGET
 	depends on USB_GADGET
 
 
+config USB_F_ACM
+	tristate
+
+config USB_F_SS_LB
+	tristate
+
+config USB_U_SERIAL
+	tristate
+
 choice
 choice
 	tristate "USB Gadget Drivers"
 	tristate "USB Gadget Drivers"
 	default USB_ETH
 	default USB_ETH
@@ -524,6 +533,7 @@ choice
 config USB_ZERO
 config USB_ZERO
 	tristate "Gadget Zero (DEVELOPMENT)"
 	tristate "Gadget Zero (DEVELOPMENT)"
 	select USB_LIBCOMPOSITE
 	select USB_LIBCOMPOSITE
+	select USB_F_SS_LB
 	help
 	help
 	  Gadget Zero is a two-configuration device.  It either sinks and
 	  Gadget Zero is a two-configuration device.  It either sinks and
 	  sources bulk data; or it loops back a configurable number of
 	  sources bulk data; or it loops back a configurable number of
@@ -750,6 +760,8 @@ config USB_GADGET_TARGET
 
 
 config USB_G_SERIAL
 config USB_G_SERIAL
 	tristate "Serial Gadget (with CDC ACM and CDC OBEX support)"
 	tristate "Serial Gadget (with CDC ACM and CDC OBEX support)"
+	select USB_U_SERIAL
+	select USB_F_ACM
 	select USB_LIBCOMPOSITE
 	select USB_LIBCOMPOSITE
 	help
 	help
 	  The Serial Gadget talks to the Linux-USB generic serial driver.
 	  The Serial Gadget talks to the Linux-USB generic serial driver.
@@ -803,6 +815,8 @@ config USB_CDC_COMPOSITE
 	tristate "CDC Composite Device (Ethernet and ACM)"
 	tristate "CDC Composite Device (Ethernet and ACM)"
 	depends on NET
 	depends on NET
 	select USB_LIBCOMPOSITE
 	select USB_LIBCOMPOSITE
+	select USB_U_SERIAL
+	select USB_F_ACM
 	help
 	help
 	  This driver provides two functions in one configuration:
 	  This driver provides two functions in one configuration:
 	  a CDC Ethernet (ECM) link, and a CDC ACM (serial port) link.
 	  a CDC Ethernet (ECM) link, and a CDC ACM (serial port) link.
@@ -818,6 +832,7 @@ config USB_G_NOKIA
 	tristate "Nokia composite gadget"
 	tristate "Nokia composite gadget"
 	depends on PHONET
 	depends on PHONET
 	select USB_LIBCOMPOSITE
 	select USB_LIBCOMPOSITE
+	select USB_U_SERIAL
 	help
 	help
 	  The Nokia composite gadget provides support for acm, obex
 	  The Nokia composite gadget provides support for acm, obex
 	  and phonet in only one composite gadget driver.
 	  and phonet in only one composite gadget driver.
@@ -829,6 +844,8 @@ config USB_G_ACM_MS
 	tristate "CDC Composite Device (ACM and mass storage)"
 	tristate "CDC Composite Device (ACM and mass storage)"
 	depends on BLOCK
 	depends on BLOCK
 	select USB_LIBCOMPOSITE
 	select USB_LIBCOMPOSITE
+	select USB_U_SERIAL
+	select USB_F_ACM
 	help
 	help
 	  This driver provides two functions in one configuration:
 	  This driver provides two functions in one configuration:
 	  a mass storage, and a CDC ACM (serial port) link.
 	  a mass storage, and a CDC ACM (serial port) link.
@@ -841,6 +858,8 @@ config USB_G_MULTI
 	depends on BLOCK && NET
 	depends on BLOCK && NET
 	select USB_G_MULTI_CDC if !USB_G_MULTI_RNDIS
 	select USB_G_MULTI_CDC if !USB_G_MULTI_RNDIS
 	select USB_LIBCOMPOSITE
 	select USB_LIBCOMPOSITE
+	select USB_U_SERIAL
+	select USB_F_ACM
 	help
 	help
 	  The Multifunction Composite Gadget provides Ethernet (RNDIS
 	  The Multifunction Composite Gadget provides Ethernet (RNDIS
 	  and/or CDC Ethernet), mass storage and ACM serial link
 	  and/or CDC Ethernet), mass storage and ACM serial link
@@ -916,6 +935,7 @@ config USB_G_DBGP_PRINTK
 
 
 config USB_G_DBGP_SERIAL
 config USB_G_DBGP_SERIAL
 	depends on USB_G_DBGP
 	depends on USB_G_DBGP
+	select USB_U_SERIAL
 	bool "serial"
 	bool "serial"
 	help
 	help
 	  Userland can interact using /dev/ttyGSxxx.
 	  Userland can interact using /dev/ttyGSxxx.

+ 7 - 1
drivers/usb/gadget/Makefile

@@ -6,7 +6,7 @@ ccflags-$(CONFIG_USB_GADGET_DEBUG) := -DDEBUG
 obj-$(CONFIG_USB_GADGET)	+= udc-core.o
 obj-$(CONFIG_USB_GADGET)	+= udc-core.o
 obj-$(CONFIG_USB_LIBCOMPOSITE)	+= libcomposite.o
 obj-$(CONFIG_USB_LIBCOMPOSITE)	+= libcomposite.o
 libcomposite-y			:= usbstring.o config.o epautoconf.o
 libcomposite-y			:= usbstring.o config.o epautoconf.o
-libcomposite-y			+= composite.o
+libcomposite-y			+= composite.o functions.o
 obj-$(CONFIG_USB_DUMMY_HCD)	+= dummy_hcd.o
 obj-$(CONFIG_USB_DUMMY_HCD)	+= dummy_hcd.o
 obj-$(CONFIG_USB_NET2272)	+= net2272.o
 obj-$(CONFIG_USB_NET2272)	+= net2272.o
 obj-$(CONFIG_USB_NET2280)	+= net2280.o
 obj-$(CONFIG_USB_NET2280)	+= net2280.o
@@ -74,3 +74,9 @@ obj-$(CONFIG_USB_G_WEBCAM)	+= g_webcam.o
 obj-$(CONFIG_USB_G_NCM)		+= g_ncm.o
 obj-$(CONFIG_USB_G_NCM)		+= g_ncm.o
 obj-$(CONFIG_USB_G_ACM_MS)	+= g_acm_ms.o
 obj-$(CONFIG_USB_G_ACM_MS)	+= g_acm_ms.o
 obj-$(CONFIG_USB_GADGET_TARGET)	+= tcm_usb_gadget.o
 obj-$(CONFIG_USB_GADGET_TARGET)	+= tcm_usb_gadget.o
+
+# USB Functions
+obj-$(CONFIG_USB_F_ACM)		+= f_acm.o
+f_ss_lb-y			:= f_loopback.o f_sourcesink.o
+obj-$(CONFIG_USB_F_SS_LB)	+= f_ss_lb.o
+obj-$(CONFIG_USB_U_SERIAL)	+= u_serial.o

+ 31 - 11
drivers/usb/gadget/acm_ms.c

@@ -40,9 +40,6 @@
  * the runtime footprint, and giving us at least some parts of what
  * the runtime footprint, and giving us at least some parts of what
  * a "gcc --combine ... part1.c part2.c part3.c ... " build would.
  * a "gcc --combine ... part1.c part2.c part3.c ... " build would.
  */
  */
-
-#include "u_serial.c"
-#include "f_acm.c"
 #include "f_mass_storage.c"
 #include "f_mass_storage.c"
 
 
 /*-------------------------------------------------------------------------*/
 /*-------------------------------------------------------------------------*/
@@ -112,12 +109,15 @@ FSG_MODULE_PARAMETERS(/* no prefix */, fsg_mod_data);
 static struct fsg_common fsg_common;
 static struct fsg_common fsg_common;
 
 
 /*-------------------------------------------------------------------------*/
 /*-------------------------------------------------------------------------*/
-
+static unsigned char tty_line;
+static struct usb_function *f_acm;
+static struct usb_function_instance *f_acm_inst;
 /*
 /*
  * We _always_ have both ACM and mass storage functions.
  * We _always_ have both ACM and mass storage functions.
  */
  */
 static int __init acm_ms_do_config(struct usb_configuration *c)
 static int __init acm_ms_do_config(struct usb_configuration *c)
 {
 {
+	struct f_serial_opts *opts;
 	int	status;
 	int	status;
 
 
 	if (gadget_is_otg(c->cdev->gadget)) {
 	if (gadget_is_otg(c->cdev->gadget)) {
@@ -125,16 +125,35 @@ static int __init acm_ms_do_config(struct usb_configuration *c)
 		c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
 		c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
 	}
 	}
 
 
+	f_acm_inst = usb_get_function_instance("acm");
+	if (IS_ERR(f_acm_inst))
+		return PTR_ERR(f_acm_inst);
+
+	opts = container_of(f_acm_inst, struct f_serial_opts, func_inst);
+	opts->port_num = tty_line;
+
+	f_acm = usb_get_function(f_acm_inst);
+	if (IS_ERR(f_acm)) {
+		status = PTR_ERR(f_acm);
+		goto err_func;
+	}
 
 
-	status = acm_bind_config(c, 0);
+	status = usb_add_function(c, f_acm);
 	if (status < 0)
 	if (status < 0)
-		return status;
+		goto err_conf;
 
 
 	status = fsg_bind_config(c->cdev, c, &fsg_common);
 	status = fsg_bind_config(c->cdev, c, &fsg_common);
 	if (status < 0)
 	if (status < 0)
-		return status;
+		goto err_fsg;
 
 
 	return 0;
 	return 0;
+err_fsg:
+	usb_remove_function(c, f_acm);
+err_conf:
+	usb_put_function(f_acm);
+err_func:
+	usb_put_function_instance(f_acm_inst);
+	return status;
 }
 }
 
 
 static struct usb_configuration acm_ms_config_driver = {
 static struct usb_configuration acm_ms_config_driver = {
@@ -153,7 +172,7 @@ static int __init acm_ms_bind(struct usb_composite_dev *cdev)
 	void			*retp;
 	void			*retp;
 
 
 	/* set up serial link layer */
 	/* set up serial link layer */
-	status = gserial_setup(cdev->gadget, 1);
+	status = gserial_alloc_line(&tty_line);
 	if (status < 0)
 	if (status < 0)
 		return status;
 		return status;
 
 
@@ -189,14 +208,15 @@ static int __init acm_ms_bind(struct usb_composite_dev *cdev)
 fail1:
 fail1:
 	fsg_common_put(&fsg_common);
 	fsg_common_put(&fsg_common);
 fail0:
 fail0:
-	gserial_cleanup();
+	gserial_free_line(tty_line);
 	return status;
 	return status;
 }
 }
 
 
 static int __exit acm_ms_unbind(struct usb_composite_dev *cdev)
 static int __exit acm_ms_unbind(struct usb_composite_dev *cdev)
 {
 {
-	gserial_cleanup();
-
+	usb_put_function(f_acm);
+	usb_put_function_instance(f_acm_inst);
+	gserial_free_line(tty_line);
 	return 0;
 	return 0;
 }
 }
 
 

+ 14 - 45
drivers/usb/gadget/amd5536udc.c

@@ -1400,15 +1400,16 @@ static int udc_wakeup(struct usb_gadget *gadget)
 	return 0;
 	return 0;
 }
 }
 
 
-static int amd5536_start(struct usb_gadget_driver *driver,
-		int (*bind)(struct usb_gadget *, struct usb_gadget_driver *));
-static int amd5536_stop(struct usb_gadget_driver *driver);
+static int amd5536_udc_start(struct usb_gadget *g,
+		struct usb_gadget_driver *driver);
+static int amd5536_udc_stop(struct usb_gadget *g,
+		struct usb_gadget_driver *driver);
 /* gadget operations */
 /* gadget operations */
 static const struct usb_gadget_ops udc_ops = {
 static const struct usb_gadget_ops udc_ops = {
 	.wakeup		= udc_wakeup,
 	.wakeup		= udc_wakeup,
 	.get_frame	= udc_get_frame,
 	.get_frame	= udc_get_frame,
-	.start		= amd5536_start,
-	.stop		= amd5536_stop,
+	.udc_start	= amd5536_udc_start,
+	.udc_stop	= amd5536_udc_stop,
 };
 };
 
 
 /* Setups endpoint parameters, adds endpoints to linked list */
 /* Setups endpoint parameters, adds endpoints to linked list */
@@ -1913,41 +1914,22 @@ static int setup_ep0(struct udc *dev)
 }
 }
 
 
 /* Called by gadget driver to register itself */
 /* Called by gadget driver to register itself */
-static int amd5536_start(struct usb_gadget_driver *driver,
-		int (*bind)(struct usb_gadget *, struct usb_gadget_driver *))
+static int amd5536_udc_start(struct usb_gadget *g,
+		struct usb_gadget_driver *driver)
 {
 {
-	struct udc		*dev = udc;
-	int			retval;
+	struct udc *dev = to_amd5536_udc(g);
 	u32 tmp;
 	u32 tmp;
 
 
-	if (!driver || !bind || !driver->setup
-			|| driver->max_speed < USB_SPEED_HIGH)
-		return -EINVAL;
-	if (!dev)
-		return -ENODEV;
-	if (dev->driver)
-		return -EBUSY;
-
 	driver->driver.bus = NULL;
 	driver->driver.bus = NULL;
 	dev->driver = driver;
 	dev->driver = driver;
 	dev->gadget.dev.driver = &driver->driver;
 	dev->gadget.dev.driver = &driver->driver;
 
 
-	retval = bind(&dev->gadget, driver);
-
 	/* Some gadget drivers use both ep0 directions.
 	/* Some gadget drivers use both ep0 directions.
 	 * NOTE: to gadget driver, ep0 is just one endpoint...
 	 * NOTE: to gadget driver, ep0 is just one endpoint...
 	 */
 	 */
 	dev->ep[UDC_EP0OUT_IX].ep.driver_data =
 	dev->ep[UDC_EP0OUT_IX].ep.driver_data =
 		dev->ep[UDC_EP0IN_IX].ep.driver_data;
 		dev->ep[UDC_EP0IN_IX].ep.driver_data;
 
 
-	if (retval) {
-		DBG(dev, "binding to %s returning %d\n",
-				driver->driver.name, retval);
-		dev->driver = NULL;
-		dev->gadget.dev.driver = NULL;
-		return retval;
-	}
-
 	/* get ready for ep0 traffic */
 	/* get ready for ep0 traffic */
 	setup_ep0(dev);
 	setup_ep0(dev);
 
 
@@ -1969,14 +1951,9 @@ __acquires(dev->lock)
 {
 {
 	int tmp;
 	int tmp;
 
 
-	if (dev->gadget.speed != USB_SPEED_UNKNOWN) {
-		spin_unlock(&dev->lock);
-		driver->disconnect(&dev->gadget);
-		spin_lock(&dev->lock);
-	}
-
 	/* empty queues and init hardware */
 	/* empty queues and init hardware */
 	udc_basic_init(dev);
 	udc_basic_init(dev);
+
 	for (tmp = 0; tmp < UDC_EP_NUM; tmp++)
 	for (tmp = 0; tmp < UDC_EP_NUM; tmp++)
 		empty_req_queue(&dev->ep[tmp]);
 		empty_req_queue(&dev->ep[tmp]);
 
 
@@ -1984,23 +1961,18 @@ __acquires(dev->lock)
 }
 }
 
 
 /* Called by gadget driver to unregister itself */
 /* Called by gadget driver to unregister itself */
-static int amd5536_stop(struct usb_gadget_driver *driver)
+static int amd5536_udc_stop(struct usb_gadget *g,
+		struct usb_gadget_driver *driver)
 {
 {
-	struct udc	*dev = udc;
-	unsigned long	flags;
+	struct udc *dev = to_amd5536_udc(g);
+	unsigned long flags;
 	u32 tmp;
 	u32 tmp;
 
 
-	if (!dev)
-		return -ENODEV;
-	if (!driver || driver != dev->driver || !driver->unbind)
-		return -EINVAL;
-
 	spin_lock_irqsave(&dev->lock, flags);
 	spin_lock_irqsave(&dev->lock, flags);
 	udc_mask_unused_interrupts(dev);
 	udc_mask_unused_interrupts(dev);
 	shutdown(dev, driver);
 	shutdown(dev, driver);
 	spin_unlock_irqrestore(&dev->lock, flags);
 	spin_unlock_irqrestore(&dev->lock, flags);
 
 
-	driver->unbind(&dev->gadget);
 	dev->gadget.dev.driver = NULL;
 	dev->gadget.dev.driver = NULL;
 	dev->driver = NULL;
 	dev->driver = NULL;
 
 
@@ -2009,9 +1981,6 @@ static int amd5536_stop(struct usb_gadget_driver *driver)
 	tmp |= AMD_BIT(UDC_DEVCTL_SD);
 	tmp |= AMD_BIT(UDC_DEVCTL_SD);
 	writel(tmp, &dev->regs->ctl);
 	writel(tmp, &dev->regs->ctl);
 
 
-
-	DBG(dev, "%s: unregistered\n", driver->driver.name);
-
 	return 0;
 	return 0;
 }
 }
 
 

+ 2 - 0
drivers/usb/gadget/amd5536udc.h

@@ -563,6 +563,8 @@ struct udc {
 	u16				cur_alt;
 	u16				cur_alt;
 };
 };
 
 
+#define to_amd5536_udc(g)	(container_of((g), struct udc, gadget))
+
 /* setup request data */
 /* setup request data */
 union udc_setup_data {
 union udc_setup_data {
 	u32			data[2];
 	u32			data[2];

+ 2 - 3
drivers/usb/gadget/at91_udc.c

@@ -1621,8 +1621,7 @@ static void at91_vbus_timer(unsigned long data)
 	 * bus such as i2c or spi which may sleep, so schedule some work
 	 * bus such as i2c or spi which may sleep, so schedule some work
 	 * to read the vbus gpio
 	 * to read the vbus gpio
 	 */
 	 */
-	if (!work_pending(&udc->vbus_timer_work))
-		schedule_work(&udc->vbus_timer_work);
+	schedule_work(&udc->vbus_timer_work);
 }
 }
 
 
 static int at91_start(struct usb_gadget *gadget,
 static int at91_start(struct usb_gadget *gadget,
@@ -1739,7 +1738,7 @@ static int at91udc_probe(struct platform_device *pdev)
 
 
 	/* rm9200 needs manual D+ pullup; off by default */
 	/* rm9200 needs manual D+ pullup; off by default */
 	if (cpu_is_at91rm9200()) {
 	if (cpu_is_at91rm9200()) {
-		if (gpio_is_valid(udc->board.pullup_pin)) {
+		if (!gpio_is_valid(udc->board.pullup_pin)) {
 			DBG("no D+ pullup?\n");
 			DBG("no D+ pullup?\n");
 			retval = -ENODEV;
 			retval = -ENODEV;
 			goto fail0;
 			goto fail0;

+ 27 - 9
drivers/usb/gadget/cdc2.c

@@ -42,9 +42,6 @@ USB_GADGET_COMPOSITE_OPTIONS();
  * the runtime footprint, and giving us at least some parts of what
  * the runtime footprint, and giving us at least some parts of what
  * a "gcc --combine ... part1.c part2.c part3.c ... " build would.
  * a "gcc --combine ... part1.c part2.c part3.c ... " build would.
  */
  */
-
-#include "u_serial.c"
-#include "f_acm.c"
 #include "f_ecm.c"
 #include "f_ecm.c"
 #include "u_ether.c"
 #include "u_ether.c"
 
 
@@ -108,12 +105,16 @@ static struct usb_gadget_strings *dev_strings[] = {
 static u8 hostaddr[ETH_ALEN];
 static u8 hostaddr[ETH_ALEN];
 
 
 /*-------------------------------------------------------------------------*/
 /*-------------------------------------------------------------------------*/
+static struct usb_function *f_acm;
+static struct usb_function_instance *fi_serial;
 
 
+static unsigned char tty_line;
 /*
 /*
  * We _always_ have both CDC ECM and CDC ACM functions.
  * We _always_ have both CDC ECM and CDC ACM functions.
  */
  */
 static int __init cdc_do_config(struct usb_configuration *c)
 static int __init cdc_do_config(struct usb_configuration *c)
 {
 {
+	struct f_serial_opts *opts;
 	int	status;
 	int	status;
 
 
 	if (gadget_is_otg(c->cdev->gadget)) {
 	if (gadget_is_otg(c->cdev->gadget)) {
@@ -125,11 +126,26 @@ static int __init cdc_do_config(struct usb_configuration *c)
 	if (status < 0)
 	if (status < 0)
 		return status;
 		return status;
 
 
-	status = acm_bind_config(c, 0);
-	if (status < 0)
-		return status;
+	fi_serial = usb_get_function_instance("acm");
+	if (IS_ERR(fi_serial))
+		return PTR_ERR(fi_serial);
 
 
+	opts = container_of(fi_serial, struct f_serial_opts, func_inst);
+	opts->port_num = tty_line;
+
+	f_acm = usb_get_function(fi_serial);
+	if (IS_ERR(f_acm))
+		goto err_func_acm;
+
+	status = usb_add_function(c, f_acm);
+	if (status)
+		goto err_conf;
 	return 0;
 	return 0;
+err_conf:
+	usb_put_function(f_acm);
+err_func_acm:
+	usb_put_function_instance(fi_serial);
+	return status;
 }
 }
 
 
 static struct usb_configuration cdc_config_driver = {
 static struct usb_configuration cdc_config_driver = {
@@ -158,7 +174,7 @@ static int __init cdc_bind(struct usb_composite_dev *cdev)
 		return status;
 		return status;
 
 
 	/* set up serial link layer */
 	/* set up serial link layer */
-	status = gserial_setup(cdev->gadget, 1);
+	status = gserial_alloc_line(&tty_line);
 	if (status < 0)
 	if (status < 0)
 		goto fail0;
 		goto fail0;
 
 
@@ -184,7 +200,7 @@ static int __init cdc_bind(struct usb_composite_dev *cdev)
 	return 0;
 	return 0;
 
 
 fail1:
 fail1:
-	gserial_cleanup();
+	gserial_free_line(tty_line);
 fail0:
 fail0:
 	gether_cleanup();
 	gether_cleanup();
 	return status;
 	return status;
@@ -192,7 +208,9 @@ fail0:
 
 
 static int __exit cdc_unbind(struct usb_composite_dev *cdev)
 static int __exit cdc_unbind(struct usb_composite_dev *cdev)
 {
 {
-	gserial_cleanup();
+	usb_put_function(f_acm);
+	usb_put_function_instance(fi_serial);
+	gserial_free_line(tty_line);
 	gether_cleanup();
 	gether_cleanup();
 	return 0;
 	return 0;
 }
 }

+ 268 - 58
drivers/usb/gadget/composite.c

@@ -28,6 +28,12 @@
  * with the relevant device-wide data.
  * with the relevant device-wide data.
  */
  */
 
 
+static struct usb_gadget_strings **get_containers_gs(
+		struct usb_gadget_string_container *uc)
+{
+	return (struct usb_gadget_strings **)uc->stash;
+}
+
 /**
 /**
  * next_ep_desc() - advance to the next EP descriptor
  * next_ep_desc() - advance to the next EP descriptor
  * @t: currect pointer within descriptor array
  * @t: currect pointer within descriptor array
@@ -215,6 +221,18 @@ done:
 }
 }
 EXPORT_SYMBOL_GPL(usb_add_function);
 EXPORT_SYMBOL_GPL(usb_add_function);
 
 
+void usb_remove_function(struct usb_configuration *c, struct usb_function *f)
+{
+	if (f->disable)
+		f->disable(f);
+
+	bitmap_zero(f->endpoints, 32);
+	list_del(&f->list);
+	if (f->unbind)
+		f->unbind(c, f);
+}
+EXPORT_SYMBOL_GPL(usb_remove_function);
+
 /**
 /**
  * usb_function_deactivate - prevent function and gadget enumeration
  * usb_function_deactivate - prevent function and gadget enumeration
  * @function: the function that isn't yet ready to respond
  * @function: the function that isn't yet ready to respond
@@ -320,6 +338,25 @@ int usb_interface_id(struct usb_configuration *config,
 }
 }
 EXPORT_SYMBOL_GPL(usb_interface_id);
 EXPORT_SYMBOL_GPL(usb_interface_id);
 
 
+static u8 encode_bMaxPower(enum usb_device_speed speed,
+		struct usb_configuration *c)
+{
+	unsigned val;
+
+	if (c->MaxPower)
+		val = c->MaxPower;
+	else
+		val = CONFIG_USB_GADGET_VBUS_DRAW;
+	if (!val)
+		return 0;
+	switch (speed) {
+	case USB_SPEED_SUPER:
+		return DIV_ROUND_UP(val, 8);
+	default:
+		return DIV_ROUND_UP(val, 2);
+	};
+}
+
 static int config_buf(struct usb_configuration *config,
 static int config_buf(struct usb_configuration *config,
 		enum usb_device_speed speed, void *buf, u8 type)
 		enum usb_device_speed speed, void *buf, u8 type)
 {
 {
@@ -339,7 +376,7 @@ static int config_buf(struct usb_configuration *config,
 	c->bConfigurationValue = config->bConfigurationValue;
 	c->bConfigurationValue = config->bConfigurationValue;
 	c->iConfiguration = config->iConfiguration;
 	c->iConfiguration = config->iConfiguration;
 	c->bmAttributes = USB_CONFIG_ATT_ONE | config->bmAttributes;
 	c->bmAttributes = USB_CONFIG_ATT_ONE | config->bmAttributes;
-	c->bMaxPower = config->bMaxPower ? : (CONFIG_USB_GADGET_VBUS_DRAW / 2);
+	c->bMaxPower = encode_bMaxPower(speed, config);
 
 
 	/* There may be e.g. OTG descriptors */
 	/* There may be e.g. OTG descriptors */
 	if (config->descriptors) {
 	if (config->descriptors) {
@@ -656,7 +693,7 @@ static int set_config(struct usb_composite_dev *cdev,
 	}
 	}
 
 
 	/* when we return, be sure our power usage is valid */
 	/* when we return, be sure our power usage is valid */
-	power = c->bMaxPower ? (2 * c->bMaxPower) : CONFIG_USB_GADGET_VBUS_DRAW;
+	power = c->MaxPower ? c->MaxPower : CONFIG_USB_GADGET_VBUS_DRAW;
 done:
 done:
 	usb_gadget_vbus_draw(gadget, power);
 	usb_gadget_vbus_draw(gadget, power);
 	if (result >= 0 && cdev->delayed_status)
 	if (result >= 0 && cdev->delayed_status)
@@ -664,6 +701,31 @@ done:
 	return result;
 	return result;
 }
 }
 
 
+int usb_add_config_only(struct usb_composite_dev *cdev,
+		struct usb_configuration *config)
+{
+	struct usb_configuration *c;
+
+	if (!config->bConfigurationValue)
+		return -EINVAL;
+
+	/* Prevent duplicate configuration identifiers */
+	list_for_each_entry(c, &cdev->configs, list) {
+		if (c->bConfigurationValue == config->bConfigurationValue)
+			return -EBUSY;
+	}
+
+	config->cdev = cdev;
+	list_add_tail(&config->list, &cdev->configs);
+
+	INIT_LIST_HEAD(&config->functions);
+	config->next_interface_id = 0;
+	memset(config->interface, 0, sizeof(config->interface));
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(usb_add_config_only);
+
 /**
 /**
  * usb_add_config() - add a configuration to a device.
  * usb_add_config() - add a configuration to a device.
  * @cdev: wraps the USB gadget
  * @cdev: wraps the USB gadget
@@ -684,30 +746,18 @@ int usb_add_config(struct usb_composite_dev *cdev,
 		int (*bind)(struct usb_configuration *))
 		int (*bind)(struct usb_configuration *))
 {
 {
 	int				status = -EINVAL;
 	int				status = -EINVAL;
-	struct usb_configuration	*c;
+
+	if (!bind)
+		goto done;
 
 
 	DBG(cdev, "adding config #%u '%s'/%p\n",
 	DBG(cdev, "adding config #%u '%s'/%p\n",
 			config->bConfigurationValue,
 			config->bConfigurationValue,
 			config->label, config);
 			config->label, config);
 
 
-	if (!config->bConfigurationValue || !bind)
+	status = usb_add_config_only(cdev, config);
+	if (status)
 		goto done;
 		goto done;
 
 
-	/* Prevent duplicate configuration identifiers */
-	list_for_each_entry(c, &cdev->configs, list) {
-		if (c->bConfigurationValue == config->bConfigurationValue) {
-			status = -EBUSY;
-			goto done;
-		}
-	}
-
-	config->cdev = cdev;
-	list_add_tail(&config->list, &cdev->configs);
-
-	INIT_LIST_HEAD(&config->functions);
-	config->next_interface_id = 0;
-	memset(config->interface, 0, sizeof(config->interface));
-
 	status = bind(config);
 	status = bind(config);
 	if (status < 0) {
 	if (status < 0) {
 		while (!list_empty(&config->functions)) {
 		while (!list_empty(&config->functions)) {
@@ -860,6 +910,7 @@ static int get_string(struct usb_composite_dev *cdev,
 		void *buf, u16 language, int id)
 		void *buf, u16 language, int id)
 {
 {
 	struct usb_composite_driver	*composite = cdev->driver;
 	struct usb_composite_driver	*composite = cdev->driver;
+	struct usb_gadget_string_container *uc;
 	struct usb_configuration	*c;
 	struct usb_configuration	*c;
 	struct usb_function		*f;
 	struct usb_function		*f;
 	int				len;
 	int				len;
@@ -892,6 +943,12 @@ static int get_string(struct usb_composite_dev *cdev,
 					collect_langs(sp, s->wData);
 					collect_langs(sp, s->wData);
 			}
 			}
 		}
 		}
+		list_for_each_entry(uc, &cdev->gstrings, list) {
+			struct usb_gadget_strings **sp;
+
+			sp = get_containers_gs(uc);
+			collect_langs(sp, s->wData);
+		}
 
 
 		for (len = 0; len <= 126 && s->wData[len]; len++)
 		for (len = 0; len <= 126 && s->wData[len]; len++)
 			continue;
 			continue;
@@ -902,6 +959,15 @@ static int get_string(struct usb_composite_dev *cdev,
 		return s->bLength;
 		return s->bLength;
 	}
 	}
 
 
+	list_for_each_entry(uc, &cdev->gstrings, list) {
+		struct usb_gadget_strings **sp;
+
+		sp = get_containers_gs(uc);
+		len = lookup_string(sp, buf, language, id);
+		if (len > 0)
+			return len;
+	}
+
 	/* String IDs are device-scoped, so we look up each string
 	/* String IDs are device-scoped, so we look up each string
 	 * table we're told about.  These lookups are infrequent;
 	 * table we're told about.  These lookups are infrequent;
 	 * simpler-is-better here.
 	 * simpler-is-better here.
@@ -987,6 +1053,119 @@ int usb_string_ids_tab(struct usb_composite_dev *cdev, struct usb_string *str)
 }
 }
 EXPORT_SYMBOL_GPL(usb_string_ids_tab);
 EXPORT_SYMBOL_GPL(usb_string_ids_tab);
 
 
+static struct usb_gadget_string_container *copy_gadget_strings(
+		struct usb_gadget_strings **sp, unsigned n_gstrings,
+		unsigned n_strings)
+{
+	struct usb_gadget_string_container *uc;
+	struct usb_gadget_strings **gs_array;
+	struct usb_gadget_strings *gs;
+	struct usb_string *s;
+	unsigned mem;
+	unsigned n_gs;
+	unsigned n_s;
+	void *stash;
+
+	mem = sizeof(*uc);
+	mem += sizeof(void *) * (n_gstrings + 1);
+	mem += sizeof(struct usb_gadget_strings) * n_gstrings;
+	mem += sizeof(struct usb_string) * (n_strings + 1) * (n_gstrings);
+	uc = kmalloc(mem, GFP_KERNEL);
+	if (!uc)
+		return ERR_PTR(-ENOMEM);
+	gs_array = get_containers_gs(uc);
+	stash = uc->stash;
+	stash += sizeof(void *) * (n_gstrings + 1);
+	for (n_gs = 0; n_gs < n_gstrings; n_gs++) {
+		struct usb_string *org_s;
+
+		gs_array[n_gs] = stash;
+		gs = gs_array[n_gs];
+		stash += sizeof(struct usb_gadget_strings);
+		gs->language = sp[n_gs]->language;
+		gs->strings = stash;
+		org_s = sp[n_gs]->strings;
+
+		for (n_s = 0; n_s < n_strings; n_s++) {
+			s = stash;
+			stash += sizeof(struct usb_string);
+			if (org_s->s)
+				s->s = org_s->s;
+			else
+				s->s = "";
+			org_s++;
+		}
+		s = stash;
+		s->s = NULL;
+		stash += sizeof(struct usb_string);
+
+	}
+	gs_array[n_gs] = NULL;
+	return uc;
+}
+
+/**
+ * usb_gstrings_attach() - attach gadget strings to a cdev and assign ids
+ * @cdev: the device whose string descriptor IDs are being allocated
+ * and attached.
+ * @sp: an array of usb_gadget_strings to attach.
+ * @n_strings: number of entries in each usb_strings array (sp[]->strings)
+ *
+ * This function will create a deep copy of usb_gadget_strings and usb_string
+ * and attach it to the cdev. The actual string (usb_string.s) will not be
+ * copied but only a referenced will be made. The struct usb_gadget_strings
+ * array may contain multiple languges and should be NULL terminated.
+ * The ->language pointer of each struct usb_gadget_strings has to contain the
+ * same amount of entries.
+ * For instance: sp[0] is en-US, sp[1] is es-ES. It is expected that the first
+ * usb_string entry of es-ES containts the translation of the first usb_string
+ * entry of en-US. Therefore both entries become the same id assign.
+ */
+struct usb_string *usb_gstrings_attach(struct usb_composite_dev *cdev,
+		struct usb_gadget_strings **sp, unsigned n_strings)
+{
+	struct usb_gadget_string_container *uc;
+	struct usb_gadget_strings **n_gs;
+	unsigned n_gstrings = 0;
+	unsigned i;
+	int ret;
+
+	for (i = 0; sp[i]; i++)
+		n_gstrings++;
+
+	if (!n_gstrings)
+		return ERR_PTR(-EINVAL);
+
+	uc = copy_gadget_strings(sp, n_gstrings, n_strings);
+	if (IS_ERR(uc))
+		return ERR_PTR(PTR_ERR(uc));
+
+	n_gs = get_containers_gs(uc);
+	ret = usb_string_ids_tab(cdev, n_gs[0]->strings);
+	if (ret)
+		goto err;
+
+	for (i = 1; i < n_gstrings; i++) {
+		struct usb_string *m_s;
+		struct usb_string *s;
+		unsigned n;
+
+		m_s = n_gs[0]->strings;
+		s = n_gs[i]->strings;
+		for (n = 0; n < n_strings; n++) {
+			s->id = m_s->id;
+			s++;
+			m_s++;
+		}
+	}
+	list_add_tail(&uc->list, &cdev->gstrings);
+	return n_gs[0]->strings;
+err:
+	kfree(uc);
+	return ERR_PTR(ret);
+}
+EXPORT_SYMBOL_GPL(usb_gstrings_attach);
+
 /**
 /**
  * usb_string_ids_n() - allocate unused string IDs in batch
  * usb_string_ids_n() - allocate unused string IDs in batch
  * @c: the device whose string descriptor IDs are being allocated
  * @c: the device whose string descriptor IDs are being allocated
@@ -1033,7 +1212,7 @@ static void composite_setup_complete(struct usb_ep *ep, struct usb_request *req)
  * housekeeping for the gadget function we're implementing.  Most of
  * housekeeping for the gadget function we're implementing.  Most of
  * the work is in config and function specific setup.
  * the work is in config and function specific setup.
  */
  */
-static int
+int
 composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
 composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
 {
 {
 	struct usb_composite_dev	*cdev = get_gadget_data(gadget);
 	struct usb_composite_dev	*cdev = get_gadget_data(gadget);
@@ -1300,7 +1479,7 @@ done:
 	return value;
 	return value;
 }
 }
 
 
-static void composite_disconnect(struct usb_gadget *gadget)
+void composite_disconnect(struct usb_gadget *gadget)
 {
 {
 	struct usb_composite_dev	*cdev = get_gadget_data(gadget);
 	struct usb_composite_dev	*cdev = get_gadget_data(gadget);
 	unsigned long			flags;
 	unsigned long			flags;
@@ -1330,8 +1509,7 @@ static ssize_t composite_show_suspended(struct device *dev,
 
 
 static DEVICE_ATTR(suspended, 0444, composite_show_suspended, NULL);
 static DEVICE_ATTR(suspended, 0444, composite_show_suspended, NULL);
 
 
-static void
-composite_unbind(struct usb_gadget *gadget)
+static void __composite_unbind(struct usb_gadget *gadget, bool unbind_driver)
 {
 {
 	struct usb_composite_dev	*cdev = get_gadget_data(gadget);
 	struct usb_composite_dev	*cdev = get_gadget_data(gadget);
 
 
@@ -1348,19 +1526,21 @@ composite_unbind(struct usb_gadget *gadget)
 				struct usb_configuration, list);
 				struct usb_configuration, list);
 		remove_config(cdev, c);
 		remove_config(cdev, c);
 	}
 	}
-	if (cdev->driver->unbind)
+	if (cdev->driver->unbind && unbind_driver)
 		cdev->driver->unbind(cdev);
 		cdev->driver->unbind(cdev);
 
 
-	if (cdev->req) {
-		kfree(cdev->req->buf);
-		usb_ep_free_request(gadget->ep0, cdev->req);
-	}
-	device_remove_file(&gadget->dev, &dev_attr_suspended);
+	composite_dev_cleanup(cdev);
+
 	kfree(cdev->def_manufacturer);
 	kfree(cdev->def_manufacturer);
 	kfree(cdev);
 	kfree(cdev);
 	set_gadget_data(gadget, NULL);
 	set_gadget_data(gadget, NULL);
 }
 }
 
 
+static void composite_unbind(struct usb_gadget *gadget)
+{
+	__composite_unbind(gadget, true);
+}
+
 static void update_unchanged_dev_desc(struct usb_device_descriptor *new,
 static void update_unchanged_dev_desc(struct usb_device_descriptor *new,
 		const struct usb_device_descriptor *old)
 		const struct usb_device_descriptor *old)
 {
 {
@@ -1399,34 +1579,25 @@ static void update_unchanged_dev_desc(struct usb_device_descriptor *new,
 		new->iProduct = iProduct;
 		new->iProduct = iProduct;
 }
 }
 
 
-static struct usb_composite_driver *to_cdriver(struct usb_gadget_driver *gdrv)
-{
-	return container_of(gdrv, struct usb_composite_driver, gadget_driver);
-}
-
-static int composite_bind(struct usb_gadget *gadget,
-		struct usb_gadget_driver *gdriver)
+int composite_dev_prepare(struct usb_composite_driver *composite,
+		struct usb_composite_dev *cdev)
 {
 {
-	struct usb_composite_dev	*cdev;
-	struct usb_composite_driver	*composite = to_cdriver(gdriver);
-	int				status = -ENOMEM;
-
-	cdev = kzalloc(sizeof *cdev, GFP_KERNEL);
-	if (!cdev)
-		return status;
-
-	spin_lock_init(&cdev->lock);
-	cdev->gadget = gadget;
-	set_gadget_data(gadget, cdev);
-	INIT_LIST_HEAD(&cdev->configs);
+	struct usb_gadget *gadget = cdev->gadget;
+	int ret = -ENOMEM;
 
 
 	/* preallocate control response and buffer */
 	/* preallocate control response and buffer */
 	cdev->req = usb_ep_alloc_request(gadget->ep0, GFP_KERNEL);
 	cdev->req = usb_ep_alloc_request(gadget->ep0, GFP_KERNEL);
 	if (!cdev->req)
 	if (!cdev->req)
-		goto fail;
+		return -ENOMEM;
+
 	cdev->req->buf = kmalloc(USB_COMP_EP0_BUFSIZ, GFP_KERNEL);
 	cdev->req->buf = kmalloc(USB_COMP_EP0_BUFSIZ, GFP_KERNEL);
 	if (!cdev->req->buf)
 	if (!cdev->req->buf)
 		goto fail;
 		goto fail;
+
+	ret = device_create_file(&gadget->dev, &dev_attr_suspended);
+	if (ret)
+		goto fail_dev;
+
 	cdev->req->complete = composite_setup_complete;
 	cdev->req->complete = composite_setup_complete;
 	gadget->ep0->driver_data = cdev;
 	gadget->ep0->driver_data = cdev;
 
 
@@ -1444,7 +1615,51 @@ static int composite_bind(struct usb_gadget *gadget,
 	 * we force endpoints to start unassigned; few controller
 	 * we force endpoints to start unassigned; few controller
 	 * drivers will zero ep->driver_data.
 	 * drivers will zero ep->driver_data.
 	 */
 	 */
-	usb_ep_autoconfig_reset(cdev->gadget);
+	usb_ep_autoconfig_reset(gadget);
+	return 0;
+fail_dev:
+	kfree(cdev->req->buf);
+fail:
+	usb_ep_free_request(gadget->ep0, cdev->req);
+	cdev->req = NULL;
+	return ret;
+}
+
+void composite_dev_cleanup(struct usb_composite_dev *cdev)
+{
+	struct usb_gadget_string_container *uc, *tmp;
+
+	list_for_each_entry_safe(uc, tmp, &cdev->gstrings, list) {
+		list_del(&uc->list);
+		kfree(uc);
+	}
+	if (cdev->req) {
+		kfree(cdev->req->buf);
+		usb_ep_free_request(cdev->gadget->ep0, cdev->req);
+	}
+	device_remove_file(&cdev->gadget->dev, &dev_attr_suspended);
+}
+
+static int composite_bind(struct usb_gadget *gadget,
+		struct usb_gadget_driver *gdriver)
+{
+	struct usb_composite_dev	*cdev;
+	struct usb_composite_driver	*composite = to_cdriver(gdriver);
+	int				status = -ENOMEM;
+
+	cdev = kzalloc(sizeof *cdev, GFP_KERNEL);
+	if (!cdev)
+		return status;
+
+	spin_lock_init(&cdev->lock);
+	cdev->gadget = gadget;
+	set_gadget_data(gadget, cdev);
+	INIT_LIST_HEAD(&cdev->configs);
+	INIT_LIST_HEAD(&cdev->gstrings);
+
+	status = composite_dev_prepare(composite, cdev);
+	if (status)
+		goto fail;
 
 
 	/* composite gadget needs to assign strings for whole device (like
 	/* composite gadget needs to assign strings for whole device (like
 	 * serial number), register function drivers, potentially update
 	 * serial number), register function drivers, potentially update
@@ -1460,16 +1675,11 @@ static int composite_bind(struct usb_gadget *gadget,
 	if (composite->needs_serial && !cdev->desc.iSerialNumber)
 	if (composite->needs_serial && !cdev->desc.iSerialNumber)
 		WARNING(cdev, "userspace failed to provide iSerialNumber\n");
 		WARNING(cdev, "userspace failed to provide iSerialNumber\n");
 
 
-	/* finish up */
-	status = device_create_file(&gadget->dev, &dev_attr_suspended);
-	if (status)
-		goto fail;
-
 	INFO(cdev, "%s ready\n", composite->name);
 	INFO(cdev, "%s ready\n", composite->name);
 	return 0;
 	return 0;
 
 
 fail:
 fail:
-	composite_unbind(gadget);
+	__composite_unbind(gadget, false);
 	return status;
 	return status;
 }
 }
 
 
@@ -1518,10 +1728,10 @@ composite_resume(struct usb_gadget *gadget)
 				f->resume(f);
 				f->resume(f);
 		}
 		}
 
 
-		maxpower = cdev->config->bMaxPower;
+		maxpower = cdev->config->MaxPower;
 
 
 		usb_gadget_vbus_draw(gadget, maxpower ?
 		usb_gadget_vbus_draw(gadget, maxpower ?
-			(2 * maxpower) : CONFIG_USB_GADGET_VBUS_DRAW);
+			maxpower : CONFIG_USB_GADGET_VBUS_DRAW);
 	}
 	}
 
 
 	cdev->suspended = 0;
 	cdev->suspended = 0;

+ 8 - 6
drivers/usb/gadget/dbgp.c

@@ -13,9 +13,7 @@
 #include <linux/usb/ch9.h>
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
 #include <linux/usb/gadget.h>
 
 
-#ifdef CONFIG_USB_G_DBGP_SERIAL
-#include "u_serial.c"
-#endif
+#include "u_serial.h"
 
 
 #define DRIVER_VENDOR_ID	0x0525 /* NetChip */
 #define DRIVER_VENDOR_ID	0x0525 /* NetChip */
 #define DRIVER_PRODUCT_ID	0xc0de /* undefined */
 #define DRIVER_PRODUCT_ID	0xc0de /* undefined */
@@ -233,6 +231,10 @@ static void dbgp_unbind(struct usb_gadget *gadget)
 	gadget->ep0->driver_data = NULL;
 	gadget->ep0->driver_data = NULL;
 }
 }
 
 
+#ifdef CONFIG_USB_G_DBGP_SERIAL
+static unsigned char tty_line;
+#endif
+
 static int __init dbgp_configure_endpoints(struct usb_gadget *gadget)
 static int __init dbgp_configure_endpoints(struct usb_gadget *gadget)
 {
 {
 	int stp;
 	int stp;
@@ -270,7 +272,7 @@ static int __init dbgp_configure_endpoints(struct usb_gadget *gadget)
 	dbgp.serial->in->desc = &i_desc;
 	dbgp.serial->in->desc = &i_desc;
 	dbgp.serial->out->desc = &o_desc;
 	dbgp.serial->out->desc = &o_desc;
 
 
-	if (gserial_setup(gadget, 1) < 0) {
+	if (gserial_alloc_line(&tty_line)) {
 		stp = 3;
 		stp = 3;
 		goto fail_3;
 		goto fail_3;
 	}
 	}
@@ -379,7 +381,7 @@ static int dbgp_setup(struct usb_gadget *gadget,
 #ifdef CONFIG_USB_G_DBGP_PRINTK
 #ifdef CONFIG_USB_G_DBGP_PRINTK
 		err = dbgp_enable_ep();
 		err = dbgp_enable_ep();
 #else
 #else
-		err = gserial_connect(dbgp.serial, 0);
+		err = gserial_connect(dbgp.serial, tty_line);
 #endif
 #endif
 		if (err < 0)
 		if (err < 0)
 			goto fail;
 			goto fail;
@@ -422,7 +424,7 @@ static void __exit dbgp_exit(void)
 {
 {
 	usb_gadget_unregister_driver(&dbgp_driver);
 	usb_gadget_unregister_driver(&dbgp_driver);
 #ifdef CONFIG_USB_G_DBGP_SERIAL
 #ifdef CONFIG_USB_G_DBGP_SERIAL
-	gserial_cleanup();
+	gserial_free_line(tty_line);
 #endif
 #endif
 }
 }
 
 

+ 104 - 49
drivers/usb/gadget/f_acm.c

@@ -16,7 +16,9 @@
 
 
 #include <linux/slab.h>
 #include <linux/slab.h>
 #include <linux/kernel.h>
 #include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/device.h>
 #include <linux/device.h>
+#include <linux/err.h>
 
 
 #include "u_serial.h"
 #include "u_serial.h"
 #include "gadget_chips.h"
 #include "gadget_chips.h"
@@ -283,7 +285,6 @@ static struct usb_string acm_string_defs[] = {
 	[ACM_CTRL_IDX].s = "CDC Abstract Control Model (ACM)",
 	[ACM_CTRL_IDX].s = "CDC Abstract Control Model (ACM)",
 	[ACM_DATA_IDX].s = "CDC ACM Data",
 	[ACM_DATA_IDX].s = "CDC ACM Data",
 	[ACM_IAD_IDX ].s = "CDC Serial",
 	[ACM_IAD_IDX ].s = "CDC Serial",
-	{  /* ZEROES END LIST */ },
 };
 };
 
 
 static struct usb_gadget_strings acm_string_table = {
 static struct usb_gadget_strings acm_string_table = {
@@ -605,9 +606,23 @@ acm_bind(struct usb_configuration *c, struct usb_function *f)
 {
 {
 	struct usb_composite_dev *cdev = c->cdev;
 	struct usb_composite_dev *cdev = c->cdev;
 	struct f_acm		*acm = func_to_acm(f);
 	struct f_acm		*acm = func_to_acm(f);
+	struct usb_string	*us;
 	int			status;
 	int			status;
 	struct usb_ep		*ep;
 	struct usb_ep		*ep;
 
 
+	/* REVISIT might want instance-specific strings to help
+	 * distinguish instances ...
+	 */
+
+	/* maybe allocate device-global string IDs, and patch descriptors */
+	us = usb_gstrings_attach(cdev, acm_strings,
+			ARRAY_SIZE(acm_string_defs));
+	if (IS_ERR(us))
+		return PTR_ERR(us);
+	acm_control_interface_desc.iInterface = us[ACM_CTRL_IDX].id;
+	acm_data_interface_desc.iInterface = us[ACM_DATA_IDX].id;
+	acm_iad_descriptor.iFunction = us[ACM_IAD_IDX].id;
+
 	/* allocate instance-specific interface IDs, and patch descriptors */
 	/* allocate instance-specific interface IDs, and patch descriptors */
 	status = usb_interface_id(c, f);
 	status = usb_interface_id(c, f);
 	if (status < 0)
 	if (status < 0)
@@ -700,24 +715,42 @@ fail:
 	return status;
 	return status;
 }
 }
 
 
+static struct f_acm *acm_alloc_basic_func(void)
+{
+	struct f_acm	*acm;
+
+	acm = kzalloc(sizeof(*acm), GFP_KERNEL);
+	if (!acm)
+		return NULL;
+
+	spin_lock_init(&acm->lock);
+
+	acm->port.connect = acm_connect;
+	acm->port.disconnect = acm_disconnect;
+	acm->port.send_break = acm_send_break;
+
+	acm->port.func.name = "acm";
+	/* descriptors are per-instance copies */
+	acm->port.func.bind = acm_bind;
+	acm->port.func.set_alt = acm_set_alt;
+	acm->port.func.setup = acm_setup;
+	acm->port.func.disable = acm_disable;
+
+	return acm;
+}
+
+#ifdef USB_FACM_INCLUDED
 static void
 static void
-acm_unbind(struct usb_configuration *c, struct usb_function *f)
+acm_old_unbind(struct usb_configuration *c, struct usb_function *f)
 {
 {
 	struct f_acm		*acm = func_to_acm(f);
 	struct f_acm		*acm = func_to_acm(f);
 
 
-	acm_string_defs[0].id = 0;
 	usb_free_all_descriptors(f);
 	usb_free_all_descriptors(f);
-	gs_free_req(acm->notify, acm->notify_req);
+	if (acm->notify_req)
+		gs_free_req(acm->notify, acm->notify_req);
 	kfree(acm);
 	kfree(acm);
 }
 }
 
 
-/* Some controllers can't support CDC ACM ... */
-static inline bool can_support_cdc(struct usb_configuration *c)
-{
-	/* everything else is *probably* fine ... */
-	return true;
-}
-
 /**
 /**
  * acm_bind_config - add a CDC ACM function to a configuration
  * acm_bind_config - add a CDC ACM function to a configuration
  * @c: the configuration to support the CDC ACM instance
  * @c: the configuration to support the CDC ACM instance
@@ -726,58 +759,80 @@ static inline bool can_support_cdc(struct usb_configuration *c)
  *
  *
  * Returns zero on success, else negative errno.
  * Returns zero on success, else negative errno.
  *
  *
- * Caller must have called @gserial_setup() with enough ports to
- * handle all the ones it binds.  Caller is also responsible
- * for calling @gserial_cleanup() before module unload.
  */
  */
 int acm_bind_config(struct usb_configuration *c, u8 port_num)
 int acm_bind_config(struct usb_configuration *c, u8 port_num)
 {
 {
 	struct f_acm	*acm;
 	struct f_acm	*acm;
 	int		status;
 	int		status;
 
 
-	if (!can_support_cdc(c))
-		return -EINVAL;
-
-	/* REVISIT might want instance-specific strings to help
-	 * distinguish instances ...
-	 */
-
-	/* maybe allocate device-global string IDs, and patch descriptors */
-	if (acm_string_defs[0].id == 0) {
-		status = usb_string_ids_tab(c->cdev, acm_string_defs);
-		if (status < 0)
-			return status;
-		acm_control_interface_desc.iInterface =
-			acm_string_defs[ACM_CTRL_IDX].id;
-		acm_data_interface_desc.iInterface =
-			acm_string_defs[ACM_DATA_IDX].id;
-		acm_iad_descriptor.iFunction = acm_string_defs[ACM_IAD_IDX].id;
-	}
-
 	/* allocate and initialize one new instance */
 	/* allocate and initialize one new instance */
-	acm = kzalloc(sizeof *acm, GFP_KERNEL);
+	acm = acm_alloc_basic_func();
 	if (!acm)
 	if (!acm)
 		return -ENOMEM;
 		return -ENOMEM;
 
 
-	spin_lock_init(&acm->lock);
-
 	acm->port_num = port_num;
 	acm->port_num = port_num;
-
-	acm->port.connect = acm_connect;
-	acm->port.disconnect = acm_disconnect;
-	acm->port.send_break = acm_send_break;
-
-	acm->port.func.name = "acm";
-	acm->port.func.strings = acm_strings;
-	/* descriptors are per-instance copies */
-	acm->port.func.bind = acm_bind;
-	acm->port.func.unbind = acm_unbind;
-	acm->port.func.set_alt = acm_set_alt;
-	acm->port.func.setup = acm_setup;
-	acm->port.func.disable = acm_disable;
+	acm->port.func.unbind = acm_old_unbind;
 
 
 	status = usb_add_function(c, &acm->port.func);
 	status = usb_add_function(c, &acm->port.func);
 	if (status)
 	if (status)
 		kfree(acm);
 		kfree(acm);
 	return status;
 	return status;
 }
 }
+
+#else
+
+static void acm_unbind(struct usb_configuration *c, struct usb_function *f)
+{
+	struct f_acm		*acm = func_to_acm(f);
+
+	acm_string_defs[0].id = 0;
+	usb_free_all_descriptors(f);
+	if (acm->notify_req)
+		gs_free_req(acm->notify, acm->notify_req);
+}
+
+static void acm_free_func(struct usb_function *f)
+{
+	struct f_acm		*acm = func_to_acm(f);
+
+	kfree(acm);
+}
+
+static struct usb_function *acm_alloc_func(struct usb_function_instance *fi)
+{
+	struct f_serial_opts *opts;
+	struct f_acm *acm;
+
+	acm = acm_alloc_basic_func();
+	if (!acm)
+		return ERR_PTR(-ENOMEM);
+
+	opts = container_of(fi, struct f_serial_opts, func_inst);
+	acm->port_num = opts->port_num;
+	acm->port.func.unbind = acm_unbind;
+	acm->port.func.free_func = acm_free_func;
+
+	return &acm->port.func;
+}
+
+static void acm_free_instance(struct usb_function_instance *fi)
+{
+	struct f_serial_opts *opts;
+
+	opts = container_of(fi, struct f_serial_opts, func_inst);
+	kfree(opts);
+}
+
+static struct usb_function_instance *acm_alloc_instance(void)
+{
+	struct f_serial_opts *opts;
+
+	opts = kzalloc(sizeof(*opts), GFP_KERNEL);
+	if (!opts)
+		return ERR_PTR(-ENOMEM);
+	opts->func_inst.free_func_inst = acm_free_instance;
+	return &opts->func_inst;
+}
+DECLARE_USB_FUNCTION_INIT(acm, acm_alloc_instance, acm_alloc_func);
+MODULE_LICENSE("GPL");
+#endif

+ 2 - 3
drivers/usb/gadget/f_fs.c

@@ -1103,8 +1103,8 @@ static int ffs_fs_parse_opts(struct ffs_sb_fill_data *data, char *opts)
 		return 0;
 		return 0;
 
 
 	for (;;) {
 	for (;;) {
-		char *end, *eq, *comma;
 		unsigned long value;
 		unsigned long value;
+		char *eq, *comma;
 
 
 		/* Option limit */
 		/* Option limit */
 		comma = strchr(opts, ',');
 		comma = strchr(opts, ',');
@@ -1120,8 +1120,7 @@ static int ffs_fs_parse_opts(struct ffs_sb_fill_data *data, char *opts)
 		*eq = 0;
 		*eq = 0;
 
 
 		/* Parse value */
 		/* Parse value */
-		value = simple_strtoul(eq + 1, &end, 0);
-		if (unlikely(*end != ',' && *end != 0)) {
+		if (kstrtoul(eq + 1, 0, &value)) {
 			pr_err("%s: invalid value: %s\n", opts, eq + 1);
 			pr_err("%s: invalid value: %s\n", opts, eq + 1);
 			return -EINVAL;
 			return -EINVAL;
 		}
 		}

+ 54 - 49
drivers/usb/gadget/f_loopback.c

@@ -15,10 +15,11 @@
 #include <linux/slab.h>
 #include <linux/slab.h>
 #include <linux/kernel.h>
 #include <linux/kernel.h>
 #include <linux/device.h>
 #include <linux/device.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/usb/composite.h>
 
 
 #include "g_zero.h"
 #include "g_zero.h"
-#include "gadget_chips.h"
-
 
 
 /*
 /*
  * LOOPBACK FUNCTION ... a testing vehicle for USB peripherals,
  * LOOPBACK FUNCTION ... a testing vehicle for USB peripherals,
@@ -44,9 +45,8 @@ static inline struct f_loopback *func_to_loop(struct usb_function *f)
 	return container_of(f, struct f_loopback, function);
 	return container_of(f, struct f_loopback, function);
 }
 }
 
 
-static unsigned qlen = 32;
-module_param(qlen, uint, 0);
-MODULE_PARM_DESC(qlenn, "depth of loopback queue");
+static unsigned qlen;
+static unsigned buflen;
 
 
 /*-------------------------------------------------------------------------*/
 /*-------------------------------------------------------------------------*/
 
 
@@ -171,8 +171,7 @@ static struct usb_gadget_strings *loopback_strings[] = {
 
 
 /*-------------------------------------------------------------------------*/
 /*-------------------------------------------------------------------------*/
 
 
-static int __init
-loopback_bind(struct usb_configuration *c, struct usb_function *f)
+static int loopback_bind(struct usb_configuration *c, struct usb_function *f)
 {
 {
 	struct usb_composite_dev *cdev = c->cdev;
 	struct usb_composite_dev *cdev = c->cdev;
 	struct f_loopback	*loop = func_to_loop(f);
 	struct f_loopback	*loop = func_to_loop(f);
@@ -185,6 +184,12 @@ loopback_bind(struct usb_configuration *c, struct usb_function *f)
 		return id;
 		return id;
 	loopback_intf.bInterfaceNumber = id;
 	loopback_intf.bInterfaceNumber = id;
 
 
+	id = usb_string_id(cdev);
+	if (id < 0)
+		return id;
+	strings_loopback[0].id = id;
+	loopback_intf.iInterface = id;
+
 	/* allocate endpoints */
 	/* allocate endpoints */
 
 
 	loop->in_ep = usb_ep_autoconfig(cdev->gadget, &fs_loop_source_desc);
 	loop->in_ep = usb_ep_autoconfig(cdev->gadget, &fs_loop_source_desc);
@@ -223,8 +228,7 @@ autoconf_fail:
 	return 0;
 	return 0;
 }
 }
 
 
-static void
-loopback_unbind(struct usb_configuration *c, struct usb_function *f)
+static void lb_free_func(struct usb_function *f)
 {
 {
 	usb_free_all_descriptors(f);
 	usb_free_all_descriptors(f);
 	kfree(func_to_loop(f));
 	kfree(func_to_loop(f));
@@ -366,63 +370,64 @@ static void loopback_disable(struct usb_function *f)
 	disable_loopback(loop);
 	disable_loopback(loop);
 }
 }
 
 
-/*-------------------------------------------------------------------------*/
-
-static int __init loopback_bind_config(struct usb_configuration *c)
+static struct usb_function *loopback_alloc(struct usb_function_instance *fi)
 {
 {
 	struct f_loopback	*loop;
 	struct f_loopback	*loop;
-	int			status;
+	struct f_lb_opts	*lb_opts;
 
 
 	loop = kzalloc(sizeof *loop, GFP_KERNEL);
 	loop = kzalloc(sizeof *loop, GFP_KERNEL);
 	if (!loop)
 	if (!loop)
-		return -ENOMEM;
+		return ERR_PTR(-ENOMEM);
+
+	lb_opts = container_of(fi, struct f_lb_opts, func_inst);
+	buflen = lb_opts->bulk_buflen;
+	qlen = lb_opts->qlen;
+	if (!qlen)
+		qlen = 32;
 
 
 	loop->function.name = "loopback";
 	loop->function.name = "loopback";
 	loop->function.bind = loopback_bind;
 	loop->function.bind = loopback_bind;
-	loop->function.unbind = loopback_unbind;
 	loop->function.set_alt = loopback_set_alt;
 	loop->function.set_alt = loopback_set_alt;
 	loop->function.disable = loopback_disable;
 	loop->function.disable = loopback_disable;
+	loop->function.strings = loopback_strings;
 
 
-	status = usb_add_function(c, &loop->function);
-	if (status)
-		kfree(loop);
-	return status;
-}
+	loop->function.free_func = lb_free_func;
 
 
-static struct usb_configuration loopback_driver = {
-	.label		= "loopback",
-	.strings	= loopback_strings,
-	.bConfigurationValue = 2,
-	.bmAttributes	= USB_CONFIG_ATT_SELFPOWER,
-	/* .iConfiguration = DYNAMIC */
-};
+	return &loop->function;
+}
 
 
-/**
- * loopback_add - add a loopback testing configuration to a device
- * @cdev: the device to support the loopback configuration
- */
-int __init loopback_add(struct usb_composite_dev *cdev, bool autoresume)
+static void lb_free_instance(struct usb_function_instance *fi)
 {
 {
-	int id;
+	struct f_lb_opts *lb_opts;
 
 
-	/* allocate string ID(s) */
-	id = usb_string_id(cdev);
-	if (id < 0)
-		return id;
-	strings_loopback[0].id = id;
+	lb_opts = container_of(fi, struct f_lb_opts, func_inst);
+	kfree(lb_opts);
+}
 
 
-	loopback_intf.iInterface = id;
-	loopback_driver.iConfiguration = id;
+static struct usb_function_instance *loopback_alloc_instance(void)
+{
+	struct f_lb_opts *lb_opts;
 
 
-	/* support autoresume for remote wakeup testing */
-	if (autoresume)
-		loopback_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
+	lb_opts = kzalloc(sizeof(*lb_opts), GFP_KERNEL);
+	if (!lb_opts)
+		return ERR_PTR(-ENOMEM);
+	lb_opts->func_inst.free_func_inst = lb_free_instance;
+	return  &lb_opts->func_inst;
+}
+DECLARE_USB_FUNCTION(Loopback, loopback_alloc_instance, loopback_alloc);
 
 
-	/* support OTG systems */
-	if (gadget_is_otg(cdev->gadget)) {
-		loopback_driver.descriptors = otg_desc;
-		loopback_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
-	}
+int __init lb_modinit(void)
+{
+	int ret;
 
 
-	return usb_add_config(cdev, &loopback_driver, loopback_bind_config);
+	ret = usb_function_register(&Loopbackusb_func);
+	if (ret)
+		return ret;
+	return ret;
 }
 }
+void __exit lb_modexit(void)
+{
+	usb_function_unregister(&Loopbackusb_func);
+}
+
+MODULE_LICENSE("GPL");

+ 5 - 32
drivers/usb/gadget/f_mass_storage.c

@@ -246,20 +246,6 @@ struct fsg_operations {
 	 * set).
 	 * set).
 	 */
 	 */
 	int (*thread_exits)(struct fsg_common *common);
 	int (*thread_exits)(struct fsg_common *common);
-
-	/*
-	 * Called prior to ejection.  Negative return means error,
-	 * zero means to continue with ejection, positive means not to
-	 * eject.
-	 */
-	int (*pre_eject)(struct fsg_common *common,
-			 struct fsg_lun *lun, int num);
-	/*
-	 * Called after ejection.  Negative return means error, zero
-	 * or positive is just a success.
-	 */
-	int (*post_eject)(struct fsg_common *common,
-			  struct fsg_lun *lun, int num);
 };
 };
 
 
 /* Data shared by all the FSG instances. */
 /* Data shared by all the FSG instances. */
@@ -1374,26 +1360,13 @@ static int do_start_stop(struct fsg_common *common)
 	if (!loej)
 	if (!loej)
 		return 0;
 		return 0;
 
 
-	/* Simulate an unload/eject */
-	if (common->ops && common->ops->pre_eject) {
-		int r = common->ops->pre_eject(common, curlun,
-					       curlun - common->luns);
-		if (unlikely(r < 0))
-			return r;
-		else if (r)
-			return 0;
-	}
-
 	up_read(&common->filesem);
 	up_read(&common->filesem);
 	down_write(&common->filesem);
 	down_write(&common->filesem);
 	fsg_lun_close(curlun);
 	fsg_lun_close(curlun);
 	up_write(&common->filesem);
 	up_write(&common->filesem);
 	down_read(&common->filesem);
 	down_read(&common->filesem);
 
 
-	return common->ops && common->ops->post_eject
-		? min(0, common->ops->post_eject(common, curlun,
-						 curlun - common->luns))
-		: 0;
+	return 0;
 }
 }
 
 
 static int do_prevent_allow(struct fsg_common *common)
 static int do_prevent_allow(struct fsg_common *common)
@@ -1718,7 +1691,7 @@ static int check_command(struct fsg_common *common, int cmnd_size,
 			 int needs_medium, const char *name)
 			 int needs_medium, const char *name)
 {
 {
 	int			i;
 	int			i;
-	int			lun = common->cmnd[1] >> 5;
+	unsigned int		lun = common->cmnd[1] >> 5;
 	static const char	dirletter[4] = {'u', 'o', 'i', 'n'};
 	static const char	dirletter[4] = {'u', 'o', 'i', 'n'};
 	char			hdlen[20];
 	char			hdlen[20];
 	struct fsg_lun		*curlun;
 	struct fsg_lun		*curlun;
@@ -1784,7 +1757,7 @@ static int check_command(struct fsg_common *common, int cmnd_size,
 
 
 	/* Check that the LUN values are consistent */
 	/* Check that the LUN values are consistent */
 	if (common->lun != lun)
 	if (common->lun != lun)
-		DBG(common, "using LUN %d from CBW, not LUN %d from CDB\n",
+		DBG(common, "using LUN %u from CBW, not LUN %u from CDB\n",
 		    common->lun, lun);
 		    common->lun, lun);
 
 
 	/* Check the LUN */
 	/* Check the LUN */
@@ -1804,7 +1777,7 @@ static int check_command(struct fsg_common *common, int cmnd_size,
 		 */
 		 */
 		if (common->cmnd[0] != INQUIRY &&
 		if (common->cmnd[0] != INQUIRY &&
 		    common->cmnd[0] != REQUEST_SENSE) {
 		    common->cmnd[0] != REQUEST_SENSE) {
-			DBG(common, "unsupported LUN %d\n", common->lun);
+			DBG(common, "unsupported LUN %u\n", common->lun);
 			return -EINVAL;
 			return -EINVAL;
 		}
 		}
 	}
 	}
@@ -2196,7 +2169,7 @@ static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh)
 	if (common->data_size == 0)
 	if (common->data_size == 0)
 		common->data_dir = DATA_DIR_NONE;
 		common->data_dir = DATA_DIR_NONE;
 	common->lun = cbw->Lun;
 	common->lun = cbw->Lun;
-	if (common->lun >= 0 && common->lun < common->nluns)
+	if (common->lun < common->nluns)
 		common->curlun = &common->luns[common->lun];
 		common->curlun = &common->luns[common->lun];
 	else
 	else
 		common->curlun = NULL;
 		common->curlun = NULL;

+ 9 - 9
drivers/usb/gadget/f_ncm.c

@@ -56,8 +56,9 @@ struct f_ncm {
 	u8				notify_state;
 	u8				notify_state;
 	bool				is_open;
 	bool				is_open;
 
 
-	struct ndp_parser_opts		*parser_opts;
+	const struct ndp_parser_opts	*parser_opts;
 	bool				is_crc;
 	bool				is_crc;
+	u32				ndp_sign;
 
 
 	/*
 	/*
 	 * for notification, it is accessed from both
 	 * for notification, it is accessed from both
@@ -390,8 +391,8 @@ struct ndp_parser_opts {
 		.next_fp_index = 2,				\
 		.next_fp_index = 2,				\
 	}
 	}
 
 
-static struct ndp_parser_opts ndp16_opts = INIT_NDP16_OPTS;
-static struct ndp_parser_opts ndp32_opts = INIT_NDP32_OPTS;
+static const struct ndp_parser_opts ndp16_opts = INIT_NDP16_OPTS;
+static const struct ndp_parser_opts ndp32_opts = INIT_NDP32_OPTS;
 
 
 static inline void put_ncm(__le16 **p, unsigned size, unsigned val)
 static inline void put_ncm(__le16 **p, unsigned size, unsigned val)
 {
 {
@@ -732,8 +733,7 @@ static int ncm_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
 		default:
 		default:
 			goto invalid;
 			goto invalid;
 		}
 		}
-		ncm->parser_opts->ndp_sign &= ~NCM_NDP_HDR_CRC_MASK;
-		ncm->parser_opts->ndp_sign |= ndp_hdr_crc;
+		ncm->ndp_sign = ncm->parser_opts->ndp_sign | ndp_hdr_crc;
 		value = 0;
 		value = 0;
 		break;
 		break;
 	}
 	}
@@ -875,7 +875,7 @@ static struct sk_buff *ncm_wrap_ntb(struct gether *port,
 	int		ndp_align;
 	int		ndp_align;
 	int		ndp_pad;
 	int		ndp_pad;
 	unsigned	max_size = ncm->port.fixed_in_len;
 	unsigned	max_size = ncm->port.fixed_in_len;
-	struct ndp_parser_opts *opts = ncm->parser_opts;
+	const struct ndp_parser_opts *opts = ncm->parser_opts;
 	unsigned	crc_len = ncm->is_crc ? sizeof(uint32_t) : 0;
 	unsigned	crc_len = ncm->is_crc ? sizeof(uint32_t) : 0;
 
 
 	div = le16_to_cpu(ntb_parameters.wNdpInDivisor);
 	div = le16_to_cpu(ntb_parameters.wNdpInDivisor);
@@ -921,7 +921,7 @@ static struct sk_buff *ncm_wrap_ntb(struct gether *port,
 	tmp = (void *)tmp + ndp_pad;
 	tmp = (void *)tmp + ndp_pad;
 
 
 	/* NDP */
 	/* NDP */
-	put_unaligned_le32(opts->ndp_sign, tmp); /* dwSignature */
+	put_unaligned_le32(ncm->ndp_sign, tmp); /* dwSignature */
 	tmp += 2;
 	tmp += 2;
 	/* wLength */
 	/* wLength */
 	put_unaligned_le16(ncb_len - opts->nth_size - pad, tmp++);
 	put_unaligned_le16(ncb_len - opts->nth_size - pad, tmp++);
@@ -965,7 +965,7 @@ static int ncm_unwrap_ntb(struct gether *port,
 	struct sk_buff	*skb2;
 	struct sk_buff	*skb2;
 	int		ret = -EINVAL;
 	int		ret = -EINVAL;
 	unsigned	max_size = le32_to_cpu(ntb_parameters.dwNtbOutMaxSize);
 	unsigned	max_size = le32_to_cpu(ntb_parameters.dwNtbOutMaxSize);
-	struct ndp_parser_opts *opts = ncm->parser_opts;
+	const struct ndp_parser_opts *opts = ncm->parser_opts;
 	unsigned	crc_len = ncm->is_crc ? sizeof(uint32_t) : 0;
 	unsigned	crc_len = ncm->is_crc ? sizeof(uint32_t) : 0;
 	int		dgram_counter;
 	int		dgram_counter;
 
 
@@ -1002,7 +1002,7 @@ static int ncm_unwrap_ntb(struct gether *port,
 
 
 	/* walk through NDP */
 	/* walk through NDP */
 	tmp = ((void *)skb->data) + index;
 	tmp = ((void *)skb->data) + index;
-	if (get_unaligned_le32(tmp) != opts->ndp_sign) {
+	if (get_unaligned_le32(tmp) != ncm->ndp_sign) {
 		INFO(port->func.config->cdev, "Wrong NDP SIGN\n");
 		INFO(port->func.config->cdev, "Wrong NDP SIGN\n");
 		goto err;
 		goto err;
 	}
 	}

+ 0 - 4
drivers/usb/gadget/f_obex.c

@@ -406,10 +406,6 @@ static inline bool can_support_obex(struct usb_configuration *c)
  * Context: single threaded during gadget setup
  * Context: single threaded during gadget setup
  *
  *
  * Returns zero on success, else negative errno.
  * Returns zero on success, else negative errno.
- *
- * Caller must have called @gserial_setup() with enough ports to
- * handle all the ones it binds.  Caller is also responsible
- * for calling @gserial_cleanup() before module unload.
  */
  */
 int __init obex_bind_config(struct usb_configuration *c, u8 port_num)
 int __init obex_bind_config(struct usb_configuration *c, u8 port_num)
 {
 {

+ 0 - 4
drivers/usb/gadget/f_serial.c

@@ -260,10 +260,6 @@ gser_unbind(struct usb_configuration *c, struct usb_function *f)
  * Context: single threaded during gadget setup
  * Context: single threaded during gadget setup
  *
  *
  * Returns zero on success, else negative errno.
  * Returns zero on success, else negative errno.
- *
- * Caller must have called @gserial_setup() with enough ports to
- * handle all the ones it binds.  Caller is also responsible
- * for calling @gserial_cleanup() before module unload.
  */
  */
 int __init gser_bind_config(struct usb_configuration *c, u8 port_num)
 int __init gser_bind_config(struct usb_configuration *c, u8 port_num)
 {
 {

+ 125 - 75
drivers/usb/gadget/f_sourcesink.c

@@ -16,11 +16,12 @@
 #include <linux/kernel.h>
 #include <linux/kernel.h>
 #include <linux/device.h>
 #include <linux/device.h>
 #include <linux/module.h>
 #include <linux/module.h>
+#include <linux/usb/composite.h>
+#include <linux/err.h>
 
 
 #include "g_zero.h"
 #include "g_zero.h"
 #include "gadget_chips.h"
 #include "gadget_chips.h"
 
 
-
 /*
 /*
  * SOURCE/SINK FUNCTION ... a primary testing vehicle for USB peripheral
  * SOURCE/SINK FUNCTION ... a primary testing vehicle for USB peripheral
  * controller drivers.
  * controller drivers.
@@ -62,24 +63,11 @@ static inline struct f_sourcesink *func_to_ss(struct usb_function *f)
 }
 }
 
 
 static unsigned pattern;
 static unsigned pattern;
-module_param(pattern, uint, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(pattern, "0 = all zeroes, 1 = mod63, 2 = none");
-
-static unsigned isoc_interval = 4;
-module_param(isoc_interval, uint, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(isoc_interval, "1 - 16");
-
-static unsigned isoc_maxpacket = 1024;
-module_param(isoc_maxpacket, uint, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(isoc_maxpacket, "0 - 1023 (fs), 0 - 1024 (hs/ss)");
-
+static unsigned isoc_interval;
+static unsigned isoc_maxpacket;
 static unsigned isoc_mult;
 static unsigned isoc_mult;
-module_param(isoc_mult, uint, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(isoc_mult, "0 - 2 (hs/ss only)");
-
 static unsigned isoc_maxburst;
 static unsigned isoc_maxburst;
-module_param(isoc_maxburst, uint, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(isoc_maxburst, "0 - 15 (ss only)");
+static unsigned buflen;
 
 
 /*-------------------------------------------------------------------------*/
 /*-------------------------------------------------------------------------*/
 
 
@@ -313,7 +301,57 @@ static struct usb_gadget_strings *sourcesink_strings[] = {
 
 
 /*-------------------------------------------------------------------------*/
 /*-------------------------------------------------------------------------*/
 
 
-static int __init
+struct usb_request *alloc_ep_req(struct usb_ep *ep, int len)
+{
+	struct usb_request      *req;
+
+	req = usb_ep_alloc_request(ep, GFP_ATOMIC);
+	if (req) {
+		if (len)
+			req->length = len;
+		else
+			req->length = buflen;
+		req->buf = kmalloc(req->length, GFP_ATOMIC);
+		if (!req->buf) {
+			usb_ep_free_request(ep, req);
+			req = NULL;
+		}
+	}
+	return req;
+}
+
+void free_ep_req(struct usb_ep *ep, struct usb_request *req)
+{
+	kfree(req->buf);
+	usb_ep_free_request(ep, req);
+}
+
+static void disable_ep(struct usb_composite_dev *cdev, struct usb_ep *ep)
+{
+	int			value;
+
+	if (ep->driver_data) {
+		value = usb_ep_disable(ep);
+		if (value < 0)
+			DBG(cdev, "disable %s --> %d\n",
+					ep->name, value);
+		ep->driver_data = NULL;
+	}
+}
+
+void disable_endpoints(struct usb_composite_dev *cdev,
+		struct usb_ep *in, struct usb_ep *out,
+		struct usb_ep *iso_in, struct usb_ep *iso_out)
+{
+	disable_ep(cdev, in);
+	disable_ep(cdev, out);
+	if (iso_in)
+		disable_ep(cdev, iso_in);
+	if (iso_out)
+		disable_ep(cdev, iso_out);
+}
+
+static int
 sourcesink_bind(struct usb_configuration *c, struct usb_function *f)
 sourcesink_bind(struct usb_configuration *c, struct usb_function *f)
 {
 {
 	struct usb_composite_dev *cdev = c->cdev;
 	struct usb_composite_dev *cdev = c->cdev;
@@ -450,7 +488,7 @@ no_iso:
 }
 }
 
 
 static void
 static void
-sourcesink_unbind(struct usb_configuration *c, struct usb_function *f)
+sourcesink_free_func(struct usb_function *f)
 {
 {
 	usb_free_all_descriptors(f);
 	usb_free_all_descriptors(f);
 	kfree(func_to_ss(f));
 	kfree(func_to_ss(f));
@@ -531,8 +569,7 @@ static void source_sink_complete(struct usb_ep *ep, struct usb_request *req)
 			check_read_data(ss, req);
 			check_read_data(ss, req);
 			if (pattern != 2)
 			if (pattern != 2)
 				memset(req->buf, 0x55, req->length);
 				memset(req->buf, 0x55, req->length);
-		} else
-			reinit_write_data(ep, req);
+		}
 		break;
 		break;
 
 
 	/* this endpoint is normally active while we're configured */
 	/* this endpoint is normally active while we're configured */
@@ -758,31 +795,10 @@ static void sourcesink_disable(struct usb_function *f)
 
 
 /*-------------------------------------------------------------------------*/
 /*-------------------------------------------------------------------------*/
 
 
-static int __init sourcesink_bind_config(struct usb_configuration *c)
-{
-	struct f_sourcesink	*ss;
-	int			status;
-
-	ss = kzalloc(sizeof *ss, GFP_KERNEL);
-	if (!ss)
-		return -ENOMEM;
-
-	ss->function.name = "source/sink";
-	ss->function.bind = sourcesink_bind;
-	ss->function.unbind = sourcesink_unbind;
-	ss->function.set_alt = sourcesink_set_alt;
-	ss->function.get_alt = sourcesink_get_alt;
-	ss->function.disable = sourcesink_disable;
-
-	status = usb_add_function(c, &ss->function);
-	if (status)
-		kfree(ss);
-	return status;
-}
-
-static int sourcesink_setup(struct usb_configuration *c,
+static int sourcesink_setup(struct usb_function *f,
 		const struct usb_ctrlrequest *ctrl)
 		const struct usb_ctrlrequest *ctrl)
 {
 {
+	struct usb_configuration        *c = f->config;
 	struct usb_request	*req = c->cdev->req;
 	struct usb_request	*req = c->cdev->req;
 	int			value = -EOPNOTSUPP;
 	int			value = -EOPNOTSUPP;
 	u16			w_index = le16_to_cpu(ctrl->wIndex);
 	u16			w_index = le16_to_cpu(ctrl->wIndex);
@@ -851,42 +867,76 @@ unknown:
 	return value;
 	return value;
 }
 }
 
 
-static struct usb_configuration sourcesink_driver = {
-	.label			= "source/sink",
-	.strings		= sourcesink_strings,
-	.setup			= sourcesink_setup,
-	.bConfigurationValue	= 3,
-	.bmAttributes		= USB_CONFIG_ATT_SELFPOWER,
-	/* .iConfiguration	= DYNAMIC */
-};
+static struct usb_function *source_sink_alloc_func(
+		struct usb_function_instance *fi)
+{
+	struct f_sourcesink     *ss;
+	struct f_ss_opts	*ss_opts;
 
 
-/**
- * sourcesink_add - add a source/sink testing configuration to a device
- * @cdev: the device to support the configuration
- */
-int __init sourcesink_add(struct usb_composite_dev *cdev, bool autoresume)
+	ss = kzalloc(sizeof(*ss), GFP_KERNEL);
+	if (!ss)
+		return NULL;
+
+	ss_opts =  container_of(fi, struct f_ss_opts, func_inst);
+	pattern = ss_opts->pattern;
+	isoc_interval = ss_opts->isoc_interval;
+	isoc_maxpacket = ss_opts->isoc_maxpacket;
+	isoc_mult = ss_opts->isoc_mult;
+	isoc_maxburst = ss_opts->isoc_maxburst;
+	buflen = ss_opts->bulk_buflen;
+
+	ss->function.name = "source/sink";
+	ss->function.bind = sourcesink_bind;
+	ss->function.set_alt = sourcesink_set_alt;
+	ss->function.get_alt = sourcesink_get_alt;
+	ss->function.disable = sourcesink_disable;
+	ss->function.setup = sourcesink_setup;
+	ss->function.strings = sourcesink_strings;
+
+	ss->function.free_func = sourcesink_free_func;
+
+	return &ss->function;
+}
+
+static void acm_free_instance(struct usb_function_instance *fi)
 {
 {
-	int id;
+	struct f_ss_opts *ss_opts;
 
 
-	/* allocate string ID(s) */
-	id = usb_string_id(cdev);
-	if (id < 0)
-		return id;
-	strings_sourcesink[0].id = id;
+	ss_opts = container_of(fi, struct f_ss_opts, func_inst);
+	kfree(ss_opts);
+}
 
 
-	source_sink_intf_alt0.iInterface = id;
-	source_sink_intf_alt1.iInterface = id;
-	sourcesink_driver.iConfiguration = id;
+static struct usb_function_instance *source_sink_alloc_inst(void)
+{
+	struct f_ss_opts *ss_opts;
 
 
-	/* support autoresume for remote wakeup testing */
-	if (autoresume)
-		sourcesink_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
+	ss_opts = kzalloc(sizeof(*ss_opts), GFP_KERNEL);
+	if (!ss_opts)
+		return ERR_PTR(-ENOMEM);
+	ss_opts->func_inst.free_func_inst = acm_free_instance;
+	return &ss_opts->func_inst;
+}
+DECLARE_USB_FUNCTION(SourceSink, source_sink_alloc_inst,
+		source_sink_alloc_func);
 
 
-	/* support OTG systems */
-	if (gadget_is_otg(cdev->gadget)) {
-		sourcesink_driver.descriptors = otg_desc;
-		sourcesink_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
-	}
+static int __init sslb_modinit(void)
+{
+	int ret;
 
 
-	return usb_add_config(cdev, &sourcesink_driver, sourcesink_bind_config);
+	ret = usb_function_register(&SourceSinkusb_func);
+	if (ret)
+		return ret;
+	ret = lb_modinit();
+	if (ret)
+		usb_function_unregister(&SourceSinkusb_func);
+	return ret;
+}
+static void __exit sslb_modexit(void)
+{
+	usb_function_unregister(&SourceSinkusb_func);
+	lb_modexit();
 }
 }
+module_init(sslb_modinit);
+module_exit(sslb_modexit);
+
+MODULE_LICENSE("GPL");

+ 2 - 7
drivers/usb/gadget/f_uac2.c

@@ -260,19 +260,14 @@ static int
 uac2_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
 uac2_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
 {
 {
 	struct snd_uac2_chip *uac2 = snd_pcm_substream_chip(substream);
 	struct snd_uac2_chip *uac2 = snd_pcm_substream_chip(substream);
-	struct audio_dev *agdev = uac2_to_agdev(uac2);
 	struct uac2_rtd_params *prm;
 	struct uac2_rtd_params *prm;
 	unsigned long flags;
 	unsigned long flags;
-	struct usb_ep *ep;
 	int err = 0;
 	int err = 0;
 
 
-	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-		ep = agdev->in_ep;
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
 		prm = &uac2->p_prm;
 		prm = &uac2->p_prm;
-	} else {
-		ep = agdev->out_ep;
+	else
 		prm = &uac2->c_prm;
 		prm = &uac2->c_prm;
-	}
 
 
 	spin_lock_irqsave(&prm->lock, flags);
 	spin_lock_irqsave(&prm->lock, flags);
 
 

+ 1 - 1
drivers/usb/gadget/fsl_qe_udc.c

@@ -1894,7 +1894,7 @@ static int fsl_qe_stop(struct usb_gadget *gadget,
 		struct usb_gadget_driver *driver);
 		struct usb_gadget_driver *driver);
 
 
 /* defined in usb_gadget.h */
 /* defined in usb_gadget.h */
-static struct usb_gadget_ops qe_gadget_ops = {
+static const struct usb_gadget_ops qe_gadget_ops = {
 	.get_frame = qe_get_frame,
 	.get_frame = qe_get_frame,
 	.udc_start = fsl_qe_start,
 	.udc_start = fsl_qe_start,
 	.udc_stop = fsl_qe_stop,
 	.udc_stop = fsl_qe_stop,

+ 12 - 48
drivers/usb/gadget/fsl_udc_core.c

@@ -1254,19 +1254,20 @@ static int fsl_pullup(struct usb_gadget *gadget, int is_on)
 	return 0;
 	return 0;
 }
 }
 
 
-static int fsl_start(struct usb_gadget_driver *driver,
-		int (*bind)(struct usb_gadget *, struct usb_gadget_driver *));
-static int fsl_stop(struct usb_gadget_driver *driver);
+static int fsl_udc_start(struct usb_gadget *g,
+		struct usb_gadget_driver *driver);
+static int fsl_udc_stop(struct usb_gadget *g,
+		struct usb_gadget_driver *driver);
 /* defined in gadget.h */
 /* defined in gadget.h */
-static struct usb_gadget_ops fsl_gadget_ops = {
+static const struct usb_gadget_ops fsl_gadget_ops = {
 	.get_frame = fsl_get_frame,
 	.get_frame = fsl_get_frame,
 	.wakeup = fsl_wakeup,
 	.wakeup = fsl_wakeup,
 /*	.set_selfpowered = fsl_set_selfpowered,	*/ /* Always selfpowered */
 /*	.set_selfpowered = fsl_set_selfpowered,	*/ /* Always selfpowered */
 	.vbus_session = fsl_vbus_session,
 	.vbus_session = fsl_vbus_session,
 	.vbus_draw = fsl_vbus_draw,
 	.vbus_draw = fsl_vbus_draw,
 	.pullup = fsl_pullup,
 	.pullup = fsl_pullup,
-	.start = fsl_start,
-	.stop = fsl_stop,
+	.udc_start = fsl_udc_start,
+	.udc_stop = fsl_udc_stop,
 };
 };
 
 
 /* Set protocol stall on ep0, protocol stall will automatically be cleared
 /* Set protocol stall on ep0, protocol stall will automatically be cleared
@@ -1950,22 +1951,12 @@ static irqreturn_t fsl_udc_irq(int irq, void *_udc)
  * Hook to gadget drivers
  * Hook to gadget drivers
  * Called by initialization code of gadget drivers
  * Called by initialization code of gadget drivers
 *----------------------------------------------------------------*/
 *----------------------------------------------------------------*/
-static int fsl_start(struct usb_gadget_driver *driver,
-		int (*bind)(struct usb_gadget *, struct usb_gadget_driver *))
+static int fsl_udc_start(struct usb_gadget *g,
+		struct usb_gadget_driver *driver)
 {
 {
-	int retval = -ENODEV;
+	int retval = 0;
 	unsigned long flags = 0;
 	unsigned long flags = 0;
 
 
-	if (!udc_controller)
-		return -ENODEV;
-
-	if (!driver || driver->max_speed < USB_SPEED_FULL
-			|| !bind || !driver->disconnect || !driver->setup)
-		return -EINVAL;
-
-	if (udc_controller->driver)
-		return -EBUSY;
-
 	/* lock is needed but whether should use this lock or another */
 	/* lock is needed but whether should use this lock or another */
 	spin_lock_irqsave(&udc_controller->lock, flags);
 	spin_lock_irqsave(&udc_controller->lock, flags);
 
 
@@ -1975,15 +1966,6 @@ static int fsl_start(struct usb_gadget_driver *driver,
 	udc_controller->gadget.dev.driver = &driver->driver;
 	udc_controller->gadget.dev.driver = &driver->driver;
 	spin_unlock_irqrestore(&udc_controller->lock, flags);
 	spin_unlock_irqrestore(&udc_controller->lock, flags);
 
 
-	/* bind udc driver to gadget driver */
-	retval = bind(&udc_controller->gadget, driver);
-	if (retval) {
-		VDBG("bind to %s --> %d", driver->driver.name, retval);
-		udc_controller->gadget.dev.driver = NULL;
-		udc_controller->driver = NULL;
-		goto out;
-	}
-
 	if (!IS_ERR_OR_NULL(udc_controller->transceiver)) {
 	if (!IS_ERR_OR_NULL(udc_controller->transceiver)) {
 		/* Suspend the controller until OTG enable it */
 		/* Suspend the controller until OTG enable it */
 		udc_controller->stopped = 1;
 		udc_controller->stopped = 1;
@@ -2009,28 +1991,17 @@ static int fsl_start(struct usb_gadget_driver *driver,
 		udc_controller->ep0_state = WAIT_FOR_SETUP;
 		udc_controller->ep0_state = WAIT_FOR_SETUP;
 		udc_controller->ep0_dir = 0;
 		udc_controller->ep0_dir = 0;
 	}
 	}
-	printk(KERN_INFO "%s: bind to driver %s\n",
-			udc_controller->gadget.name, driver->driver.name);
 
 
-out:
-	if (retval)
-		printk(KERN_WARNING "gadget driver register failed %d\n",
-		       retval);
 	return retval;
 	return retval;
 }
 }
 
 
 /* Disconnect from gadget driver */
 /* Disconnect from gadget driver */
-static int fsl_stop(struct usb_gadget_driver *driver)
+static int fsl_udc_stop(struct usb_gadget *g,
+		struct usb_gadget_driver *driver)
 {
 {
 	struct fsl_ep *loop_ep;
 	struct fsl_ep *loop_ep;
 	unsigned long flags;
 	unsigned long flags;
 
 
-	if (!udc_controller)
-		return -ENODEV;
-
-	if (!driver || driver != udc_controller->driver || !driver->unbind)
-		return -EINVAL;
-
 	if (!IS_ERR_OR_NULL(udc_controller->transceiver))
 	if (!IS_ERR_OR_NULL(udc_controller->transceiver))
 		otg_set_peripheral(udc_controller->transceiver->otg, NULL);
 		otg_set_peripheral(udc_controller->transceiver->otg, NULL);
 
 
@@ -2051,16 +2022,9 @@ static int fsl_stop(struct usb_gadget_driver *driver)
 		nuke(loop_ep, -ESHUTDOWN);
 		nuke(loop_ep, -ESHUTDOWN);
 	spin_unlock_irqrestore(&udc_controller->lock, flags);
 	spin_unlock_irqrestore(&udc_controller->lock, flags);
 
 
-	/* report disconnect; the controller is already quiesced */
-	driver->disconnect(&udc_controller->gadget);
-
-	/* unbind gadget and unhook driver. */
-	driver->unbind(&udc_controller->gadget);
 	udc_controller->gadget.dev.driver = NULL;
 	udc_controller->gadget.dev.driver = NULL;
 	udc_controller->driver = NULL;
 	udc_controller->driver = NULL;
 
 
-	printk(KERN_WARNING "unregistered gadget driver '%s'\n",
-	       driver->driver.name);
 	return 0;
 	return 0;
 }
 }
 
 

+ 116 - 0
drivers/usb/gadget/functions.c

@@ -0,0 +1,116 @@
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/err.h>
+
+#include <linux/usb/composite.h>
+
+static LIST_HEAD(func_list);
+static DEFINE_MUTEX(func_lock);
+
+static struct usb_function_instance *try_get_usb_function_instance(const char *name)
+{
+	struct usb_function_driver *fd;
+	struct usb_function_instance *fi;
+
+	fi = ERR_PTR(-ENOENT);
+	mutex_lock(&func_lock);
+	list_for_each_entry(fd, &func_list, list) {
+
+		if (strcmp(name, fd->name))
+			continue;
+
+		if (!try_module_get(fd->mod)) {
+			fi = ERR_PTR(-EBUSY);
+			break;
+		}
+		fi = fd->alloc_inst();
+		if (IS_ERR(fi))
+			module_put(fd->mod);
+		else
+			fi->fd = fd;
+		break;
+	}
+	mutex_unlock(&func_lock);
+	return fi;
+}
+
+struct usb_function_instance *usb_get_function_instance(const char *name)
+{
+	struct usb_function_instance *fi;
+	int ret;
+
+	fi = try_get_usb_function_instance(name);
+	if (!IS_ERR(fi))
+		return fi;
+	ret = PTR_ERR(fi);
+	if (ret != -ENOENT)
+		return fi;
+	ret = request_module("usbfunc:%s", name);
+	if (ret < 0)
+		return ERR_PTR(ret);
+	return try_get_usb_function_instance(name);
+}
+EXPORT_SYMBOL_GPL(usb_get_function_instance);
+
+struct usb_function *usb_get_function(struct usb_function_instance *fi)
+{
+	struct usb_function *f;
+
+	f = fi->fd->alloc_func(fi);
+	if (IS_ERR(f))
+		return f;
+	f->fi = fi;
+	return f;
+}
+EXPORT_SYMBOL_GPL(usb_get_function);
+
+void usb_put_function_instance(struct usb_function_instance *fi)
+{
+	struct module *mod;
+
+	if (!fi)
+		return;
+
+	mod = fi->fd->mod;
+	fi->free_func_inst(fi);
+	module_put(mod);
+}
+EXPORT_SYMBOL_GPL(usb_put_function_instance);
+
+void usb_put_function(struct usb_function *f)
+{
+	if (!f)
+		return;
+
+	f->free_func(f);
+}
+EXPORT_SYMBOL_GPL(usb_put_function);
+
+int usb_function_register(struct usb_function_driver *newf)
+{
+	struct usb_function_driver *fd;
+	int ret;
+
+	ret = -EEXIST;
+
+	mutex_lock(&func_lock);
+	list_for_each_entry(fd, &func_list, list) {
+		if (!strcmp(fd->name, newf->name))
+			goto out;
+	}
+	ret = 0;
+	list_add_tail(&newf->list, &func_list);
+out:
+	mutex_unlock(&func_lock);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(usb_function_register);
+
+void usb_function_unregister(struct usb_function_driver *fd)
+{
+	mutex_lock(&func_lock);
+	list_del(&fd->list);
+	mutex_unlock(&func_lock);
+}
+EXPORT_SYMBOL_GPL(usb_function_unregister);

+ 19 - 48
drivers/usb/gadget/fusb300_udc.c

@@ -1308,65 +1308,28 @@ static void init_controller(struct fusb300 *fusb300)
 	iowrite32(0xcfffff9f, fusb300->reg + FUSB300_OFFSET_IGER1);
 	iowrite32(0xcfffff9f, fusb300->reg + FUSB300_OFFSET_IGER1);
 }
 }
 /*------------------------------------------------------------------------*/
 /*------------------------------------------------------------------------*/
-static struct fusb300 *the_controller;
-
-static int fusb300_udc_start(struct usb_gadget_driver *driver,
-		int (*bind)(struct usb_gadget *, struct usb_gadget_driver *))
+static int fusb300_udc_start(struct usb_gadget *g,
+		struct usb_gadget_driver *driver)
 {
 {
-	struct fusb300 *fusb300 = the_controller;
-	int retval;
-
-	if (!driver
-			|| driver->max_speed < USB_SPEED_FULL
-			|| !bind
-			|| !driver->setup)
-		return -EINVAL;
-
-	if (!fusb300)
-		return -ENODEV;
-
-	if (fusb300->driver)
-		return -EBUSY;
+	struct fusb300 *fusb300 = to_fusb300(g);
 
 
 	/* hook up the driver */
 	/* hook up the driver */
 	driver->driver.bus = NULL;
 	driver->driver.bus = NULL;
 	fusb300->driver = driver;
 	fusb300->driver = driver;
 	fusb300->gadget.dev.driver = &driver->driver;
 	fusb300->gadget.dev.driver = &driver->driver;
 
 
-	retval = device_add(&fusb300->gadget.dev);
-	if (retval) {
-		pr_err("device_add error (%d)\n", retval);
-		goto error;
-	}
-
-	retval = bind(&fusb300->gadget, driver);
-	if (retval) {
-		pr_err("bind to driver error (%d)\n", retval);
-		device_del(&fusb300->gadget.dev);
-		goto error;
-	}
-
 	return 0;
 	return 0;
-
-error:
-	fusb300->driver = NULL;
-	fusb300->gadget.dev.driver = NULL;
-
-	return retval;
 }
 }
 
 
-static int fusb300_udc_stop(struct usb_gadget_driver *driver)
+static int fusb300_udc_stop(struct usb_gadget *g,
+		struct usb_gadget_driver *driver)
 {
 {
-	struct fusb300 *fusb300 = the_controller;
-
-	if (driver != fusb300->driver || !driver->unbind)
-		return -EINVAL;
+	struct fusb300 *fusb300 = to_fusb300(g);
 
 
 	driver->unbind(&fusb300->gadget);
 	driver->unbind(&fusb300->gadget);
 	fusb300->gadget.dev.driver = NULL;
 	fusb300->gadget.dev.driver = NULL;
 
 
 	init_controller(fusb300);
 	init_controller(fusb300);
-	device_del(&fusb300->gadget.dev);
 	fusb300->driver = NULL;
 	fusb300->driver = NULL;
 
 
 	return 0;
 	return 0;
@@ -1378,10 +1341,10 @@ static int fusb300_udc_pullup(struct usb_gadget *_gadget, int is_active)
 	return 0;
 	return 0;
 }
 }
 
 
-static struct usb_gadget_ops fusb300_gadget_ops = {
+static const struct usb_gadget_ops fusb300_gadget_ops = {
 	.pullup		= fusb300_udc_pullup,
 	.pullup		= fusb300_udc_pullup,
-	.start		= fusb300_udc_start,
-	.stop		= fusb300_udc_stop,
+	.udc_start	= fusb300_udc_start,
+	.udc_stop	= fusb300_udc_stop,
 };
 };
 
 
 static int __exit fusb300_remove(struct platform_device *pdev)
 static int __exit fusb300_remove(struct platform_device *pdev)
@@ -1505,8 +1468,6 @@ static int __init fusb300_probe(struct platform_device *pdev)
 	fusb300->gadget.ep0 = &fusb300->ep[0]->ep;
 	fusb300->gadget.ep0 = &fusb300->ep[0]->ep;
 	INIT_LIST_HEAD(&fusb300->gadget.ep0->ep_list);
 	INIT_LIST_HEAD(&fusb300->gadget.ep0->ep_list);
 
 
-	the_controller = fusb300;
-
 	fusb300->ep0_req = fusb300_alloc_request(&fusb300->ep[0]->ep,
 	fusb300->ep0_req = fusb300_alloc_request(&fusb300->ep[0]->ep,
 				GFP_KERNEL);
 				GFP_KERNEL);
 	if (fusb300->ep0_req == NULL)
 	if (fusb300->ep0_req == NULL)
@@ -1517,9 +1478,19 @@ static int __init fusb300_probe(struct platform_device *pdev)
 	if (ret)
 	if (ret)
 		goto err_add_udc;
 		goto err_add_udc;
 
 
+	ret = device_add(&fusb300->gadget.dev);
+	if (ret) {
+		pr_err("device_add error (%d)\n", ret);
+		goto err_add_device;
+	}
+
 	dev_info(&pdev->dev, "version %s\n", DRIVER_VERSION);
 	dev_info(&pdev->dev, "version %s\n", DRIVER_VERSION);
 
 
 	return 0;
 	return 0;
+
+err_add_device:
+	usb_del_gadget_udc(&fusb300->gadget);
+
 err_add_udc:
 err_add_udc:
 	fusb300_free_request(&fusb300->ep[0]->ep, fusb300->ep0_req);
 	fusb300_free_request(&fusb300->ep[0]->ep, fusb300->ep0_req);
 
 

+ 2 - 0
drivers/usb/gadget/fusb300_udc.h

@@ -673,4 +673,6 @@ struct fusb300 {
 	u8			reenum;		/* if re-enumeration */
 	u8			reenum;		/* if re-enumeration */
 };
 };
 
 
+#define to_fusb300(g)		(container_of((g), struct fusb300, gadget))
+
 #endif
 #endif

+ 27 - 8
drivers/usb/gadget/g_zero.h

@@ -6,11 +6,34 @@
 #ifndef __G_ZERO_H
 #ifndef __G_ZERO_H
 #define __G_ZERO_H
 #define __G_ZERO_H
 
 
-#include <linux/usb/composite.h>
+struct usb_zero_options {
+	unsigned pattern;
+	unsigned isoc_interval;
+	unsigned isoc_maxpacket;
+	unsigned isoc_mult;
+	unsigned isoc_maxburst;
+	unsigned bulk_buflen;
+	unsigned qlen;
+};
 
 
-/* global state */
-extern unsigned buflen;
-extern const struct usb_descriptor_header *otg_desc[];
+struct f_ss_opts {
+	struct usb_function_instance func_inst;
+	unsigned pattern;
+	unsigned isoc_interval;
+	unsigned isoc_maxpacket;
+	unsigned isoc_mult;
+	unsigned isoc_maxburst;
+	unsigned bulk_buflen;
+};
+
+struct f_lb_opts {
+	struct usb_function_instance func_inst;
+	unsigned bulk_buflen;
+	unsigned qlen;
+};
+
+void lb_modexit(void);
+int lb_modinit(void);
 
 
 /* common utilities */
 /* common utilities */
 struct usb_request *alloc_ep_req(struct usb_ep *ep, int len);
 struct usb_request *alloc_ep_req(struct usb_ep *ep, int len);
@@ -19,8 +42,4 @@ void disable_endpoints(struct usb_composite_dev *cdev,
 		struct usb_ep *in, struct usb_ep *out,
 		struct usb_ep *in, struct usb_ep *out,
 		struct usb_ep *iso_in, struct usb_ep *iso_out);
 		struct usb_ep *iso_in, struct usb_ep *iso_out);
 
 
-/* configuration-specific linkup */
-int sourcesink_add(struct usb_composite_dev *cdev, bool autoresume);
-int loopback_add(struct usb_composite_dev *cdev, bool autoresume);
-
 #endif /* __G_ZERO_H */
 #endif /* __G_ZERO_H */

+ 1 - 1
drivers/usb/gadget/gmidi.c

@@ -125,7 +125,7 @@ static struct usb_configuration midi_config = {
 	.bConfigurationValue = 1,
 	.bConfigurationValue = 1,
 	/* .iConfiguration = DYNAMIC */
 	/* .iConfiguration = DYNAMIC */
 	.bmAttributes	= USB_CONFIG_ATT_ONE,
 	.bmAttributes	= USB_CONFIG_ATT_ONE,
-	.bMaxPower	= CONFIG_USB_GADGET_VBUS_DRAW / 2,
+	.MaxPower	= CONFIG_USB_GADGET_VBUS_DRAW,
 };
 };
 
 
 static int __init midi_bind_config(struct usb_configuration *c)
 static int __init midi_bind_config(struct usb_configuration *c)

+ 14 - 56
drivers/usb/gadget/goku_udc.c

@@ -993,14 +993,15 @@ static int goku_get_frame(struct usb_gadget *_gadget)
 	return -EOPNOTSUPP;
 	return -EOPNOTSUPP;
 }
 }
 
 
-static int goku_start(struct usb_gadget_driver *driver,
-		int (*bind)(struct usb_gadget *, struct usb_gadget_driver *));
-static int goku_stop(struct usb_gadget_driver *driver);
+static int goku_udc_start(struct usb_gadget *g,
+		struct usb_gadget_driver *driver);
+static int goku_udc_stop(struct usb_gadget *g,
+		struct usb_gadget_driver *driver);
 
 
 static const struct usb_gadget_ops goku_ops = {
 static const struct usb_gadget_ops goku_ops = {
 	.get_frame	= goku_get_frame,
 	.get_frame	= goku_get_frame,
-	.start		= goku_start,
-	.stop		= goku_stop,
+	.udc_start	= goku_udc_start,
+	.udc_stop	= goku_udc_stop,
 	// no remote wakeup
 	// no remote wakeup
 	// not selfpowered
 	// not selfpowered
 };
 };
@@ -1339,50 +1340,28 @@ static void udc_enable(struct goku_udc *dev)
  * - one function driver, initted second
  * - one function driver, initted second
  */
  */
 
 
-static struct goku_udc	*the_controller;
-
 /* when a driver is successfully registered, it will receive
 /* when a driver is successfully registered, it will receive
  * control requests including set_configuration(), which enables
  * control requests including set_configuration(), which enables
  * non-control requests.  then usb traffic follows until a
  * non-control requests.  then usb traffic follows until a
  * disconnect is reported.  then a host may connect again, or
  * disconnect is reported.  then a host may connect again, or
  * the driver might get unbound.
  * the driver might get unbound.
  */
  */
-static int goku_start(struct usb_gadget_driver *driver,
-		int (*bind)(struct usb_gadget *, struct usb_gadget_driver *))
+static int goku_udc_start(struct usb_gadget *g,
+		struct usb_gadget_driver *driver)
 {
 {
-	struct goku_udc	*dev = the_controller;
-	int			retval;
-
-	if (!driver
-			|| driver->max_speed < USB_SPEED_FULL
-			|| !bind
-			|| !driver->disconnect
-			|| !driver->setup)
-		return -EINVAL;
-	if (!dev)
-		return -ENODEV;
-	if (dev->driver)
-		return -EBUSY;
+	struct goku_udc	*dev = to_goku_udc(g);
 
 
 	/* hook up the driver */
 	/* hook up the driver */
 	driver->driver.bus = NULL;
 	driver->driver.bus = NULL;
 	dev->driver = driver;
 	dev->driver = driver;
 	dev->gadget.dev.driver = &driver->driver;
 	dev->gadget.dev.driver = &driver->driver;
-	retval = bind(&dev->gadget, driver);
-	if (retval) {
-		DBG(dev, "bind to driver %s --> error %d\n",
-				driver->driver.name, retval);
-		dev->driver = NULL;
-		dev->gadget.dev.driver = NULL;
-		return retval;
-	}
 
 
-	/* then enable host detection and ep0; and we're ready
+	/*
+	 * then enable host detection and ep0; and we're ready
 	 * for set_configuration as well as eventual disconnect.
 	 * for set_configuration as well as eventual disconnect.
 	 */
 	 */
 	udc_enable(dev);
 	udc_enable(dev);
 
 
-	DBG(dev, "registered gadget driver '%s'\n", driver->driver.name);
 	return 0;
 	return 0;
 }
 }
 
 
@@ -1400,35 +1379,23 @@ stop_activity(struct goku_udc *dev, struct usb_gadget_driver *driver)
 	udc_reset (dev);
 	udc_reset (dev);
 	for (i = 0; i < 4; i++)
 	for (i = 0; i < 4; i++)
 		nuke(&dev->ep [i], -ESHUTDOWN);
 		nuke(&dev->ep [i], -ESHUTDOWN);
-	if (driver) {
-		spin_unlock(&dev->lock);
-		driver->disconnect(&dev->gadget);
-		spin_lock(&dev->lock);
-	}
 
 
 	if (dev->driver)
 	if (dev->driver)
 		udc_enable(dev);
 		udc_enable(dev);
 }
 }
 
 
-static int goku_stop(struct usb_gadget_driver *driver)
+static int goku_udc_stop(struct usb_gadget *g,
+		struct usb_gadget_driver *driver)
 {
 {
-	struct goku_udc	*dev = the_controller;
+	struct goku_udc	*dev = to_goku_udc(g);
 	unsigned long	flags;
 	unsigned long	flags;
 
 
-	if (!dev)
-		return -ENODEV;
-	if (!driver || driver != dev->driver || !driver->unbind)
-		return -EINVAL;
-
 	spin_lock_irqsave(&dev->lock, flags);
 	spin_lock_irqsave(&dev->lock, flags);
 	dev->driver = NULL;
 	dev->driver = NULL;
 	stop_activity(dev, driver);
 	stop_activity(dev, driver);
 	spin_unlock_irqrestore(&dev->lock, flags);
 	spin_unlock_irqrestore(&dev->lock, flags);
-
-	driver->unbind(&dev->gadget);
 	dev->gadget.dev.driver = NULL;
 	dev->gadget.dev.driver = NULL;
 
 
-	DBG(dev, "unregistered driver '%s'\n", driver->driver.name);
 	return 0;
 	return 0;
 }
 }
 
 
@@ -1754,7 +1721,6 @@ static void goku_remove(struct pci_dev *pdev)
 
 
 	pci_set_drvdata(pdev, NULL);
 	pci_set_drvdata(pdev, NULL);
 	dev->regs = NULL;
 	dev->regs = NULL;
-	the_controller = NULL;
 
 
 	INFO(dev, "unbind\n");
 	INFO(dev, "unbind\n");
 }
 }
@@ -1770,13 +1736,6 @@ static int goku_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 	void __iomem		*base = NULL;
 	void __iomem		*base = NULL;
 	int			retval;
 	int			retval;
 
 
-	/* if you want to support more than one controller in a system,
-	 * usb_gadget_driver_{register,unregister}() must change.
-	 */
-	if (the_controller) {
-		pr_warning("ignoring %s\n", pci_name(pdev));
-		return -EBUSY;
-	}
 	if (!pdev->irq) {
 	if (!pdev->irq) {
 		printk(KERN_ERR "Check PCI %s IRQ setup!\n", pci_name(pdev));
 		printk(KERN_ERR "Check PCI %s IRQ setup!\n", pci_name(pdev));
 		retval = -ENODEV;
 		retval = -ENODEV;
@@ -1851,7 +1810,6 @@ static int goku_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 	create_proc_read_entry(proc_node_name, 0, NULL, udc_proc_read, dev);
 	create_proc_read_entry(proc_node_name, 0, NULL, udc_proc_read, dev);
 #endif
 #endif
 
 
-	the_controller = dev;
 	retval = device_register(&dev->gadget.dev);
 	retval = device_register(&dev->gadget.dev);
 	if (retval) {
 	if (retval) {
 		put_device(&dev->gadget.dev);
 		put_device(&dev->gadget.dev);

+ 1 - 0
drivers/usb/gadget/goku_udc.h

@@ -261,6 +261,7 @@ struct goku_udc {
 	/* statistics... */
 	/* statistics... */
 	unsigned long			irqs;
 	unsigned long			irqs;
 };
 };
+#define to_goku_udc(g)		(container_of((g), struct goku_udc, gadget))
 
 
 /*-------------------------------------------------------------------------*/
 /*-------------------------------------------------------------------------*/
 
 

+ 20 - 52
drivers/usb/gadget/m66592-udc.c

@@ -1463,42 +1463,16 @@ static struct usb_ep_ops m66592_ep_ops = {
 };
 };
 
 
 /*-------------------------------------------------------------------------*/
 /*-------------------------------------------------------------------------*/
-static struct m66592 *the_controller;
-
-static int m66592_start(struct usb_gadget_driver *driver,
-		int (*bind)(struct usb_gadget *, struct usb_gadget_driver *))
+static int m66592_udc_start(struct usb_gadget *g,
+		struct usb_gadget_driver *driver)
 {
 {
-	struct m66592 *m66592 = the_controller;
-	int retval;
-
-	if (!driver
-			|| driver->max_speed < USB_SPEED_HIGH
-			|| !bind
-			|| !driver->setup)
-		return -EINVAL;
-	if (!m66592)
-		return -ENODEV;
-	if (m66592->driver)
-		return -EBUSY;
+	struct m66592 *m66592 = to_m66592(g);
 
 
 	/* hook up the driver */
 	/* hook up the driver */
 	driver->driver.bus = NULL;
 	driver->driver.bus = NULL;
 	m66592->driver = driver;
 	m66592->driver = driver;
 	m66592->gadget.dev.driver = &driver->driver;
 	m66592->gadget.dev.driver = &driver->driver;
 
 
-	retval = device_add(&m66592->gadget.dev);
-	if (retval) {
-		pr_err("device_add error (%d)\n", retval);
-		goto error;
-	}
-
-	retval = bind(&m66592->gadget, driver);
-	if (retval) {
-		pr_err("bind to driver error (%d)\n", retval);
-		device_del(&m66592->gadget.dev);
-		goto error;
-	}
-
 	m66592_bset(m66592, M66592_VBSE | M66592_URST, M66592_INTENB0);
 	m66592_bset(m66592, M66592_VBSE | M66592_URST, M66592_INTENB0);
 	if (m66592_read(m66592, M66592_INTSTS0) & M66592_VBSTS) {
 	if (m66592_read(m66592, M66592_INTSTS0) & M66592_VBSTS) {
 		m66592_start_xclock(m66592);
 		m66592_start_xclock(m66592);
@@ -1510,26 +1484,12 @@ static int m66592_start(struct usb_gadget_driver *driver,
 	}
 	}
 
 
 	return 0;
 	return 0;
-
-error:
-	m66592->driver = NULL;
-	m66592->gadget.dev.driver = NULL;
-
-	return retval;
 }
 }
 
 
-static int m66592_stop(struct usb_gadget_driver *driver)
+static int m66592_udc_stop(struct usb_gadget *g,
+		struct usb_gadget_driver *driver)
 {
 {
-	struct m66592 *m66592 = the_controller;
-	unsigned long flags;
-
-	if (driver != m66592->driver || !driver->unbind)
-		return -EINVAL;
-
-	spin_lock_irqsave(&m66592->lock, flags);
-	if (m66592->gadget.speed != USB_SPEED_UNKNOWN)
-		m66592_usb_disconnect(m66592);
-	spin_unlock_irqrestore(&m66592->lock, flags);
+	struct m66592 *m66592 = to_m66592(g);
 
 
 	m66592_bclr(m66592, M66592_VBSE | M66592_URST, M66592_INTENB0);
 	m66592_bclr(m66592, M66592_VBSE | M66592_URST, M66592_INTENB0);
 
 
@@ -1539,8 +1499,8 @@ static int m66592_stop(struct usb_gadget_driver *driver)
 	init_controller(m66592);
 	init_controller(m66592);
 	disable_controller(m66592);
 	disable_controller(m66592);
 
 
-	device_del(&m66592->gadget.dev);
 	m66592->driver = NULL;
 	m66592->driver = NULL;
+
 	return 0;
 	return 0;
 }
 }
 
 
@@ -1566,10 +1526,10 @@ static int m66592_pullup(struct usb_gadget *gadget, int is_on)
 	return 0;
 	return 0;
 }
 }
 
 
-static struct usb_gadget_ops m66592_gadget_ops = {
+static const struct usb_gadget_ops m66592_gadget_ops = {
 	.get_frame		= m66592_get_frame,
 	.get_frame		= m66592_get_frame,
-	.start			= m66592_start,
-	.stop			= m66592_stop,
+	.udc_start		= m66592_udc_start,
+	.udc_stop		= m66592_udc_stop,
 	.pullup			= m66592_pullup,
 	.pullup			= m66592_pullup,
 };
 };
 
 
@@ -1578,6 +1538,7 @@ static int __exit m66592_remove(struct platform_device *pdev)
 	struct m66592		*m66592 = dev_get_drvdata(&pdev->dev);
 	struct m66592		*m66592 = dev_get_drvdata(&pdev->dev);
 
 
 	usb_del_gadget_udc(&m66592->gadget);
 	usb_del_gadget_udc(&m66592->gadget);
+	device_del(&m66592->gadget.dev);
 
 
 	del_timer_sync(&m66592->timer);
 	del_timer_sync(&m66592->timer);
 	iounmap(m66592->reg);
 	iounmap(m66592->reg);
@@ -1706,8 +1667,6 @@ static int __init m66592_probe(struct platform_device *pdev)
 	m66592->pipenum2ep[0] = &m66592->ep[0];
 	m66592->pipenum2ep[0] = &m66592->ep[0];
 	m66592->epaddr2ep[0] = &m66592->ep[0];
 	m66592->epaddr2ep[0] = &m66592->ep[0];
 
 
-	the_controller = m66592;
-
 	m66592->ep0_req = m66592_alloc_request(&m66592->ep[0].ep, GFP_KERNEL);
 	m66592->ep0_req = m66592_alloc_request(&m66592->ep[0].ep, GFP_KERNEL);
 	if (m66592->ep0_req == NULL)
 	if (m66592->ep0_req == NULL)
 		goto clean_up3;
 		goto clean_up3;
@@ -1715,6 +1674,12 @@ static int __init m66592_probe(struct platform_device *pdev)
 
 
 	init_controller(m66592);
 	init_controller(m66592);
 
 
+	ret = device_add(&m66592->gadget.dev);
+	if (ret) {
+		pr_err("device_add error (%d)\n", ret);
+		goto err_device_add;
+	}
+
 	ret = usb_add_gadget_udc(&pdev->dev, &m66592->gadget);
 	ret = usb_add_gadget_udc(&pdev->dev, &m66592->gadget);
 	if (ret)
 	if (ret)
 		goto err_add_udc;
 		goto err_add_udc;
@@ -1723,6 +1688,9 @@ static int __init m66592_probe(struct platform_device *pdev)
 	return 0;
 	return 0;
 
 
 err_add_udc:
 err_add_udc:
+	device_del(&m66592->gadget.dev);
+
+err_device_add:
 	m66592_free_request(&m66592->ep[0].ep, m66592->ep0_req);
 	m66592_free_request(&m66592->ep[0].ep, m66592->ep0_req);
 
 
 clean_up3:
 clean_up3:

+ 1 - 0
drivers/usb/gadget/m66592-udc.h

@@ -492,6 +492,7 @@ struct m66592 {
 	int isochronous;
 	int isochronous;
 	int num_dma;
 	int num_dma;
 };
 };
+#define to_m66592(g)	(container_of((g), struct m66592, gadget))
 
 
 #define gadget_to_m66592(_gadget) container_of(_gadget, struct m66592, gadget)
 #define gadget_to_m66592(_gadget) container_of(_gadget, struct m66592, gadget)
 #define m66592_to_gadget(m66592) (&m66592->gadget)
 #define m66592_to_gadget(m66592) (&m66592->gadget)

+ 56 - 15
drivers/usb/gadget/multi.c

@@ -16,6 +16,7 @@
 #include <linux/kernel.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/module.h>
 
 
+#include "u_serial.h"
 #if defined USB_ETH_RNDIS
 #if defined USB_ETH_RNDIS
 #  undef USB_ETH_RNDIS
 #  undef USB_ETH_RNDIS
 #endif
 #endif
@@ -42,9 +43,6 @@ MODULE_LICENSE("GPL");
  */
  */
 #include "f_mass_storage.c"
 #include "f_mass_storage.c"
 
 
-#include "u_serial.c"
-#include "f_acm.c"
-
 #include "f_ecm.c"
 #include "f_ecm.c"
 #include "f_subset.c"
 #include "f_subset.c"
 #ifdef USB_ETH_RNDIS
 #ifdef USB_ETH_RNDIS
@@ -137,10 +135,13 @@ static struct fsg_common fsg_common;
 
 
 static u8 hostaddr[ETH_ALEN];
 static u8 hostaddr[ETH_ALEN];
 
 
+static unsigned char tty_line;
+static struct usb_function_instance *fi_acm;
 
 
 /********** RNDIS **********/
 /********** RNDIS **********/
 
 
 #ifdef USB_ETH_RNDIS
 #ifdef USB_ETH_RNDIS
+static struct usb_function *f_acm_rndis;
 
 
 static __init int rndis_do_config(struct usb_configuration *c)
 static __init int rndis_do_config(struct usb_configuration *c)
 {
 {
@@ -155,15 +156,25 @@ static __init int rndis_do_config(struct usb_configuration *c)
 	if (ret < 0)
 	if (ret < 0)
 		return ret;
 		return ret;
 
 
-	ret = acm_bind_config(c, 0);
-	if (ret < 0)
-		return ret;
+	f_acm_rndis = usb_get_function(fi_acm);
+	if (IS_ERR(f_acm_rndis))
+		goto err_func_acm;
+
+	ret = usb_add_function(c, f_acm_rndis);
+	if (ret)
+		goto err_conf;
 
 
 	ret = fsg_bind_config(c->cdev, c, &fsg_common);
 	ret = fsg_bind_config(c->cdev, c, &fsg_common);
 	if (ret < 0)
 	if (ret < 0)
-		return ret;
+		goto err_fsg;
 
 
 	return 0;
 	return 0;
+err_fsg:
+	usb_remove_function(c, f_acm_rndis);
+err_conf:
+	usb_put_function(f_acm_rndis);
+err_func_acm:
+	return ret;
 }
 }
 
 
 static int rndis_config_register(struct usb_composite_dev *cdev)
 static int rndis_config_register(struct usb_composite_dev *cdev)
@@ -192,6 +203,7 @@ static int rndis_config_register(struct usb_composite_dev *cdev)
 /********** CDC ECM **********/
 /********** CDC ECM **********/
 
 
 #ifdef CONFIG_USB_G_MULTI_CDC
 #ifdef CONFIG_USB_G_MULTI_CDC
+static struct usb_function *f_acm_multi;
 
 
 static __init int cdc_do_config(struct usb_configuration *c)
 static __init int cdc_do_config(struct usb_configuration *c)
 {
 {
@@ -206,15 +218,26 @@ static __init int cdc_do_config(struct usb_configuration *c)
 	if (ret < 0)
 	if (ret < 0)
 		return ret;
 		return ret;
 
 
-	ret = acm_bind_config(c, 0);
-	if (ret < 0)
-		return ret;
+	/* implicit port_num is zero */
+	f_acm_multi = usb_get_function(fi_acm);
+	if (IS_ERR(f_acm_multi))
+		goto err_func_acm;
+
+	ret = usb_add_function(c, f_acm_multi);
+	if (ret)
+		goto err_conf;
 
 
 	ret = fsg_bind_config(c->cdev, c, &fsg_common);
 	ret = fsg_bind_config(c->cdev, c, &fsg_common);
 	if (ret < 0)
 	if (ret < 0)
-		return ret;
+		goto err_fsg;
 
 
 	return 0;
 	return 0;
+err_fsg:
+	usb_remove_function(c, f_acm_multi);
+err_conf:
+	usb_put_function(f_acm_multi);
+err_func_acm:
+	return ret;
 }
 }
 
 
 static int cdc_config_register(struct usb_composite_dev *cdev)
 static int cdc_config_register(struct usb_composite_dev *cdev)
@@ -243,10 +266,10 @@ static int cdc_config_register(struct usb_composite_dev *cdev)
 
 
 /****************************** Gadget Bind ******************************/
 /****************************** Gadget Bind ******************************/
 
 
-
 static int __ref multi_bind(struct usb_composite_dev *cdev)
 static int __ref multi_bind(struct usb_composite_dev *cdev)
 {
 {
 	struct usb_gadget *gadget = cdev->gadget;
 	struct usb_gadget *gadget = cdev->gadget;
+	struct f_serial_opts *opts;
 	int status;
 	int status;
 
 
 	if (!can_support_ecm(cdev->gadget)) {
 	if (!can_support_ecm(cdev->gadget)) {
@@ -261,10 +284,19 @@ static int __ref multi_bind(struct usb_composite_dev *cdev)
 		return status;
 		return status;
 
 
 	/* set up serial link layer */
 	/* set up serial link layer */
-	status = gserial_setup(cdev->gadget, 1);
+	status = gserial_alloc_line(&tty_line);
 	if (status < 0)
 	if (status < 0)
 		goto fail0;
 		goto fail0;
 
 
+	fi_acm = usb_get_function_instance("acm");
+	if (IS_ERR(fi_acm)) {
+		status = PTR_ERR(fi_acm);
+		goto fail0dot5;
+	}
+
+	opts = container_of(fi_acm, struct f_serial_opts, func_inst);
+	opts->port_num = tty_line;
+
 	/* set up mass storage function */
 	/* set up mass storage function */
 	{
 	{
 		void *retp;
 		void *retp;
@@ -301,7 +333,9 @@ static int __ref multi_bind(struct usb_composite_dev *cdev)
 fail2:
 fail2:
 	fsg_common_put(&fsg_common);
 	fsg_common_put(&fsg_common);
 fail1:
 fail1:
-	gserial_cleanup();
+	usb_put_function_instance(fi_acm);
+fail0dot5:
+	gserial_free_line(tty_line);
 fail0:
 fail0:
 	gether_cleanup();
 	gether_cleanup();
 	return status;
 	return status;
@@ -309,7 +343,14 @@ fail0:
 
 
 static int __exit multi_unbind(struct usb_composite_dev *cdev)
 static int __exit multi_unbind(struct usb_composite_dev *cdev)
 {
 {
-	gserial_cleanup();
+#ifdef CONFIG_USB_G_MULTI_CDC
+	usb_put_function(f_acm_multi);
+#endif
+#ifdef USB_ETH_RNDIS
+	usb_put_function(f_acm_rndis);
+#endif
+	usb_put_function_instance(fi_acm);
+	gserial_free_line(tty_line);
 	gether_cleanup();
 	gether_cleanup();
 	return 0;
 	return 0;
 }
 }

+ 99 - 147
drivers/usb/gadget/mv_udc_core.c

@@ -61,9 +61,6 @@ static DECLARE_COMPLETION(release_done);
 static const char driver_name[] = "mv_udc";
 static const char driver_name[] = "mv_udc";
 static const char driver_desc[] = DRIVER_DESC;
 static const char driver_desc[] = DRIVER_DESC;
 
 
-/* controller device global variable */
-static struct mv_udc	*the_controller;
-
 static void nuke(struct mv_ep *ep, int status);
 static void nuke(struct mv_ep *ep, int status);
 static void stop_activity(struct mv_udc *udc, struct usb_gadget_driver *driver);
 static void stop_activity(struct mv_udc *udc, struct usb_gadget_driver *driver);
 
 
@@ -1268,9 +1265,8 @@ static int mv_udc_pullup(struct usb_gadget *gadget, int is_on)
 	return retval;
 	return retval;
 }
 }
 
 
-static int mv_udc_start(struct usb_gadget_driver *driver,
-		int (*bind)(struct usb_gadget *, struct usb_gadget_driver *));
-static int mv_udc_stop(struct usb_gadget_driver *driver);
+static int mv_udc_start(struct usb_gadget *, struct usb_gadget_driver *);
+static int mv_udc_stop(struct usb_gadget *, struct usb_gadget_driver *);
 /* device controller usb_gadget_ops structure */
 /* device controller usb_gadget_ops structure */
 static const struct usb_gadget_ops mv_ops = {
 static const struct usb_gadget_ops mv_ops = {
 
 
@@ -1285,8 +1281,8 @@ static const struct usb_gadget_ops mv_ops = {
 
 
 	/* D+ pullup, software-controlled connect/disconnect to USB host */
 	/* D+ pullup, software-controlled connect/disconnect to USB host */
 	.pullup		= mv_udc_pullup,
 	.pullup		= mv_udc_pullup,
-	.start		= mv_udc_start,
-	.stop		= mv_udc_stop,
+	.udc_start	= mv_udc_start,
+	.udc_stop	= mv_udc_stop,
 };
 };
 
 
 static int eps_init(struct mv_udc *udc)
 static int eps_init(struct mv_udc *udc)
@@ -1373,15 +1369,14 @@ static void stop_activity(struct mv_udc *udc, struct usb_gadget_driver *driver)
 	}
 	}
 }
 }
 
 
-static int mv_udc_start(struct usb_gadget_driver *driver,
-		int (*bind)(struct usb_gadget *, struct usb_gadget_driver *))
+static int mv_udc_start(struct usb_gadget *gadget,
+		struct usb_gadget_driver *driver)
 {
 {
-	struct mv_udc *udc = the_controller;
+	struct mv_udc *udc;
 	int retval = 0;
 	int retval = 0;
 	unsigned long flags;
 	unsigned long flags;
 
 
-	if (!udc)
-		return -ENODEV;
+	udc = container_of(gadget, struct mv_udc, gadget);
 
 
 	if (udc->driver)
 	if (udc->driver)
 		return -EBUSY;
 		return -EBUSY;
@@ -1399,26 +1394,14 @@ static int mv_udc_start(struct usb_gadget_driver *driver,
 
 
 	spin_unlock_irqrestore(&udc->lock, flags);
 	spin_unlock_irqrestore(&udc->lock, flags);
 
 
-	retval = bind(&udc->gadget, driver);
-	if (retval) {
-		dev_err(&udc->dev->dev, "bind to driver %s --> %d\n",
-				driver->driver.name, retval);
-		udc->driver = NULL;
-		udc->gadget.dev.driver = NULL;
-		return retval;
-	}
-
-	if (!IS_ERR_OR_NULL(udc->transceiver)) {
+	if (udc->transceiver) {
 		retval = otg_set_peripheral(udc->transceiver->otg,
 		retval = otg_set_peripheral(udc->transceiver->otg,
 					&udc->gadget);
 					&udc->gadget);
 		if (retval) {
 		if (retval) {
 			dev_err(&udc->dev->dev,
 			dev_err(&udc->dev->dev,
 				"unable to register peripheral to otg\n");
 				"unable to register peripheral to otg\n");
-			if (driver->unbind) {
-				driver->unbind(&udc->gadget);
-				udc->gadget.dev.driver = NULL;
-				udc->driver = NULL;
-			}
+			udc->driver = NULL;
+			udc->gadget.dev.driver = NULL;
 			return retval;
 			return retval;
 		}
 		}
 	}
 	}
@@ -1433,13 +1416,13 @@ static int mv_udc_start(struct usb_gadget_driver *driver,
 	return 0;
 	return 0;
 }
 }
 
 
-static int mv_udc_stop(struct usb_gadget_driver *driver)
+static int mv_udc_stop(struct usb_gadget *gadget,
+		struct usb_gadget_driver *driver)
 {
 {
-	struct mv_udc *udc = the_controller;
+	struct mv_udc *udc;
 	unsigned long flags;
 	unsigned long flags;
 
 
-	if (!udc)
-		return -ENODEV;
+	udc = container_of(gadget, struct mv_udc, gadget);
 
 
 	spin_lock_irqsave(&udc->lock, flags);
 	spin_lock_irqsave(&udc->lock, flags);
 
 
@@ -1454,7 +1437,6 @@ static int mv_udc_stop(struct usb_gadget_driver *driver)
 	spin_unlock_irqrestore(&udc->lock, flags);
 	spin_unlock_irqrestore(&udc->lock, flags);
 
 
 	/* unbind gadget driver */
 	/* unbind gadget driver */
-	driver->unbind(&udc->gadget);
 	udc->gadget.dev.driver = NULL;
 	udc->gadget.dev.driver = NULL;
 	udc->driver = NULL;
 	udc->driver = NULL;
 
 
@@ -1472,10 +1454,13 @@ static void mv_set_ptc(struct mv_udc *udc, u32 mode)
 
 
 static void prime_status_complete(struct usb_ep *ep, struct usb_request *_req)
 static void prime_status_complete(struct usb_ep *ep, struct usb_request *_req)
 {
 {
-	struct mv_udc *udc = the_controller;
+	struct mv_ep *mvep = container_of(ep, struct mv_ep, ep);
 	struct mv_req *req = container_of(_req, struct mv_req, req);
 	struct mv_req *req = container_of(_req, struct mv_req, req);
+	struct mv_udc *udc;
 	unsigned long flags;
 	unsigned long flags;
 
 
+	udc = mvep->udc;
+
 	dev_info(&udc->dev->dev, "switch to test mode %d\n", req->test_mode);
 	dev_info(&udc->dev->dev, "switch to test mode %d\n", req->test_mode);
 
 
 	spin_lock_irqsave(&udc->lock, flags);
 	spin_lock_irqsave(&udc->lock, flags);
@@ -2123,15 +2108,18 @@ static void mv_udc_vbus_work(struct work_struct *work)
 /* release device structure */
 /* release device structure */
 static void gadget_release(struct device *_dev)
 static void gadget_release(struct device *_dev)
 {
 {
-	struct mv_udc *udc = the_controller;
+	struct mv_udc *udc;
+
+	udc = dev_get_drvdata(_dev);
 
 
 	complete(udc->done);
 	complete(udc->done);
 }
 }
 
 
-static int mv_udc_remove(struct platform_device *dev)
+static int mv_udc_remove(struct platform_device *pdev)
 {
 {
-	struct mv_udc *udc = the_controller;
-	int clk_i;
+	struct mv_udc *udc;
+
+	udc = platform_get_drvdata(pdev);
 
 
 	usb_del_gadget_udc(&udc->gadget);
 	usb_del_gadget_udc(&udc->gadget);
 
 
@@ -2140,57 +2128,27 @@ static int mv_udc_remove(struct platform_device *dev)
 		destroy_workqueue(udc->qwork);
 		destroy_workqueue(udc->qwork);
 	}
 	}
 
 
-	/*
-	 * If we have transceiver inited,
-	 * then vbus irq will not be requested in udc driver.
-	 */
-	if (udc->pdata && udc->pdata->vbus
-		&& udc->clock_gating && IS_ERR_OR_NULL(udc->transceiver))
-		free_irq(udc->pdata->vbus->irq, &dev->dev);
-
 	/* free memory allocated in probe */
 	/* free memory allocated in probe */
 	if (udc->dtd_pool)
 	if (udc->dtd_pool)
 		dma_pool_destroy(udc->dtd_pool);
 		dma_pool_destroy(udc->dtd_pool);
 
 
 	if (udc->ep_dqh)
 	if (udc->ep_dqh)
-		dma_free_coherent(&dev->dev, udc->ep_dqh_size,
+		dma_free_coherent(&pdev->dev, udc->ep_dqh_size,
 			udc->ep_dqh, udc->ep_dqh_dma);
 			udc->ep_dqh, udc->ep_dqh_dma);
 
 
-	kfree(udc->eps);
-
-	if (udc->irq)
-		free_irq(udc->irq, &dev->dev);
-
 	mv_udc_disable(udc);
 	mv_udc_disable(udc);
 
 
-	if (udc->cap_regs)
-		iounmap(udc->cap_regs);
-
-	if (udc->phy_regs)
-		iounmap(udc->phy_regs);
-
-	if (udc->status_req) {
-		kfree(udc->status_req->req.buf);
-		kfree(udc->status_req);
-	}
-
-	for (clk_i = 0; clk_i <= udc->clknum; clk_i++)
-		clk_put(udc->clk[clk_i]);
-
 	device_unregister(&udc->gadget.dev);
 	device_unregister(&udc->gadget.dev);
 
 
 	/* free dev, wait for the release() finished */
 	/* free dev, wait for the release() finished */
 	wait_for_completion(udc->done);
 	wait_for_completion(udc->done);
-	kfree(udc);
-
-	the_controller = NULL;
 
 
 	return 0;
 	return 0;
 }
 }
 
 
-static int mv_udc_probe(struct platform_device *dev)
+static int mv_udc_probe(struct platform_device *pdev)
 {
 {
-	struct mv_usb_platform_data *pdata = dev->dev.platform_data;
+	struct mv_usb_platform_data *pdata = pdev->dev.platform_data;
 	struct mv_udc *udc;
 	struct mv_udc *udc;
 	int retval = 0;
 	int retval = 0;
 	int clk_i = 0;
 	int clk_i = 0;
@@ -2198,71 +2156,73 @@ static int mv_udc_probe(struct platform_device *dev)
 	size_t size;
 	size_t size;
 
 
 	if (pdata == NULL) {
 	if (pdata == NULL) {
-		dev_err(&dev->dev, "missing platform_data\n");
+		dev_err(&pdev->dev, "missing platform_data\n");
 		return -ENODEV;
 		return -ENODEV;
 	}
 	}
 
 
 	size = sizeof(*udc) + sizeof(struct clk *) * pdata->clknum;
 	size = sizeof(*udc) + sizeof(struct clk *) * pdata->clknum;
-	udc = kzalloc(size, GFP_KERNEL);
+	udc = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
 	if (udc == NULL) {
 	if (udc == NULL) {
-		dev_err(&dev->dev, "failed to allocate memory for udc\n");
+		dev_err(&pdev->dev, "failed to allocate memory for udc\n");
 		return -ENOMEM;
 		return -ENOMEM;
 	}
 	}
 
 
-	the_controller = udc;
 	udc->done = &release_done;
 	udc->done = &release_done;
-	udc->pdata = dev->dev.platform_data;
+	udc->pdata = pdev->dev.platform_data;
 	spin_lock_init(&udc->lock);
 	spin_lock_init(&udc->lock);
 
 
-	udc->dev = dev;
+	udc->dev = pdev;
 
 
 #ifdef CONFIG_USB_OTG_UTILS
 #ifdef CONFIG_USB_OTG_UTILS
-	if (pdata->mode == MV_USB_MODE_OTG)
-		udc->transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
+	if (pdata->mode == MV_USB_MODE_OTG) {
+		udc->transceiver = devm_usb_get_phy(&pdev->dev,
+					USB_PHY_TYPE_USB2);
+		if (IS_ERR_OR_NULL(udc->transceiver)) {
+			udc->transceiver = NULL;
+			return -ENODEV;
+		}
+	}
 #endif
 #endif
 
 
 	udc->clknum = pdata->clknum;
 	udc->clknum = pdata->clknum;
 	for (clk_i = 0; clk_i < udc->clknum; clk_i++) {
 	for (clk_i = 0; clk_i < udc->clknum; clk_i++) {
-		udc->clk[clk_i] = clk_get(&dev->dev, pdata->clkname[clk_i]);
+		udc->clk[clk_i] = devm_clk_get(&pdev->dev,
+					pdata->clkname[clk_i]);
 		if (IS_ERR(udc->clk[clk_i])) {
 		if (IS_ERR(udc->clk[clk_i])) {
 			retval = PTR_ERR(udc->clk[clk_i]);
 			retval = PTR_ERR(udc->clk[clk_i]);
-			goto err_put_clk;
+			return retval;
 		}
 		}
 	}
 	}
 
 
 	r = platform_get_resource_byname(udc->dev, IORESOURCE_MEM, "capregs");
 	r = platform_get_resource_byname(udc->dev, IORESOURCE_MEM, "capregs");
 	if (r == NULL) {
 	if (r == NULL) {
-		dev_err(&dev->dev, "no I/O memory resource defined\n");
-		retval = -ENODEV;
-		goto err_put_clk;
+		dev_err(&pdev->dev, "no I/O memory resource defined\n");
+		return -ENODEV;
 	}
 	}
 
 
 	udc->cap_regs = (struct mv_cap_regs __iomem *)
 	udc->cap_regs = (struct mv_cap_regs __iomem *)
-		ioremap(r->start, resource_size(r));
+		devm_ioremap(&pdev->dev, r->start, resource_size(r));
 	if (udc->cap_regs == NULL) {
 	if (udc->cap_regs == NULL) {
-		dev_err(&dev->dev, "failed to map I/O memory\n");
-		retval = -EBUSY;
-		goto err_put_clk;
+		dev_err(&pdev->dev, "failed to map I/O memory\n");
+		return -EBUSY;
 	}
 	}
 
 
 	r = platform_get_resource_byname(udc->dev, IORESOURCE_MEM, "phyregs");
 	r = platform_get_resource_byname(udc->dev, IORESOURCE_MEM, "phyregs");
 	if (r == NULL) {
 	if (r == NULL) {
-		dev_err(&dev->dev, "no phy I/O memory resource defined\n");
-		retval = -ENODEV;
-		goto err_iounmap_capreg;
+		dev_err(&pdev->dev, "no phy I/O memory resource defined\n");
+		return -ENODEV;
 	}
 	}
 
 
 	udc->phy_regs = ioremap(r->start, resource_size(r));
 	udc->phy_regs = ioremap(r->start, resource_size(r));
 	if (udc->phy_regs == NULL) {
 	if (udc->phy_regs == NULL) {
-		dev_err(&dev->dev, "failed to map phy I/O memory\n");
-		retval = -EBUSY;
-		goto err_iounmap_capreg;
+		dev_err(&pdev->dev, "failed to map phy I/O memory\n");
+		return -EBUSY;
 	}
 	}
 
 
 	/* we will acces controller register, so enable the clk */
 	/* we will acces controller register, so enable the clk */
 	retval = mv_udc_enable_internal(udc);
 	retval = mv_udc_enable_internal(udc);
 	if (retval)
 	if (retval)
-		goto err_iounmap_phyreg;
+		return retval;
 
 
 	udc->op_regs =
 	udc->op_regs =
 		(struct mv_op_regs __iomem *)((unsigned long)udc->cap_regs
 		(struct mv_op_regs __iomem *)((unsigned long)udc->cap_regs
@@ -2279,11 +2239,11 @@ static int mv_udc_probe(struct platform_device *dev)
 
 
 	size = udc->max_eps * sizeof(struct mv_dqh) *2;
 	size = udc->max_eps * sizeof(struct mv_dqh) *2;
 	size = (size + DQH_ALIGNMENT - 1) & ~(DQH_ALIGNMENT - 1);
 	size = (size + DQH_ALIGNMENT - 1) & ~(DQH_ALIGNMENT - 1);
-	udc->ep_dqh = dma_alloc_coherent(&dev->dev, size,
+	udc->ep_dqh = dma_alloc_coherent(&pdev->dev, size,
 					&udc->ep_dqh_dma, GFP_KERNEL);
 					&udc->ep_dqh_dma, GFP_KERNEL);
 
 
 	if (udc->ep_dqh == NULL) {
 	if (udc->ep_dqh == NULL) {
-		dev_err(&dev->dev, "allocate dQH memory failed\n");
+		dev_err(&pdev->dev, "allocate dQH memory failed\n");
 		retval = -ENOMEM;
 		retval = -ENOMEM;
 		goto err_disable_clock;
 		goto err_disable_clock;
 	}
 	}
@@ -2291,7 +2251,7 @@ static int mv_udc_probe(struct platform_device *dev)
 
 
 	/* create dTD dma_pool resource */
 	/* create dTD dma_pool resource */
 	udc->dtd_pool = dma_pool_create("mv_dtd",
 	udc->dtd_pool = dma_pool_create("mv_dtd",
-			&dev->dev,
+			&pdev->dev,
 			sizeof(struct mv_dtd),
 			sizeof(struct mv_dtd),
 			DTD_ALIGNMENT,
 			DTD_ALIGNMENT,
 			DMA_BOUNDARY);
 			DMA_BOUNDARY);
@@ -2302,19 +2262,20 @@ static int mv_udc_probe(struct platform_device *dev)
 	}
 	}
 
 
 	size = udc->max_eps * sizeof(struct mv_ep) *2;
 	size = udc->max_eps * sizeof(struct mv_ep) *2;
-	udc->eps = kzalloc(size, GFP_KERNEL);
+	udc->eps = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
 	if (udc->eps == NULL) {
 	if (udc->eps == NULL) {
-		dev_err(&dev->dev, "allocate ep memory failed\n");
+		dev_err(&pdev->dev, "allocate ep memory failed\n");
 		retval = -ENOMEM;
 		retval = -ENOMEM;
 		goto err_destroy_dma;
 		goto err_destroy_dma;
 	}
 	}
 
 
 	/* initialize ep0 status request structure */
 	/* initialize ep0 status request structure */
-	udc->status_req = kzalloc(sizeof(struct mv_req), GFP_KERNEL);
+	udc->status_req = devm_kzalloc(&pdev->dev, sizeof(struct mv_req),
+					GFP_KERNEL);
 	if (!udc->status_req) {
 	if (!udc->status_req) {
-		dev_err(&dev->dev, "allocate status_req memory failed\n");
+		dev_err(&pdev->dev, "allocate status_req memory failed\n");
 		retval = -ENOMEM;
 		retval = -ENOMEM;
-		goto err_free_eps;
+		goto err_destroy_dma;
 	}
 	}
 	INIT_LIST_HEAD(&udc->status_req->queue);
 	INIT_LIST_HEAD(&udc->status_req->queue);
 
 
@@ -2329,17 +2290,17 @@ static int mv_udc_probe(struct platform_device *dev)
 
 
 	r = platform_get_resource(udc->dev, IORESOURCE_IRQ, 0);
 	r = platform_get_resource(udc->dev, IORESOURCE_IRQ, 0);
 	if (r == NULL) {
 	if (r == NULL) {
-		dev_err(&dev->dev, "no IRQ resource defined\n");
+		dev_err(&pdev->dev, "no IRQ resource defined\n");
 		retval = -ENODEV;
 		retval = -ENODEV;
-		goto err_free_status_req;
+		goto err_destroy_dma;
 	}
 	}
 	udc->irq = r->start;
 	udc->irq = r->start;
-	if (request_irq(udc->irq, mv_udc_irq,
+	if (devm_request_irq(&pdev->dev, udc->irq, mv_udc_irq,
 		IRQF_SHARED, driver_name, udc)) {
 		IRQF_SHARED, driver_name, udc)) {
-		dev_err(&dev->dev, "Request irq %d for UDC failed\n",
+		dev_err(&pdev->dev, "Request irq %d for UDC failed\n",
 			udc->irq);
 			udc->irq);
 		retval = -ENODEV;
 		retval = -ENODEV;
-		goto err_free_status_req;
+		goto err_destroy_dma;
 	}
 	}
 
 
 	/* initialize gadget structure */
 	/* initialize gadget structure */
@@ -2351,26 +2312,27 @@ static int mv_udc_probe(struct platform_device *dev)
 
 
 	/* the "gadget" abstracts/virtualizes the controller */
 	/* the "gadget" abstracts/virtualizes the controller */
 	dev_set_name(&udc->gadget.dev, "gadget");
 	dev_set_name(&udc->gadget.dev, "gadget");
-	udc->gadget.dev.parent = &dev->dev;
-	udc->gadget.dev.dma_mask = dev->dev.dma_mask;
+	udc->gadget.dev.parent = &pdev->dev;
+	udc->gadget.dev.dma_mask = pdev->dev.dma_mask;
 	udc->gadget.dev.release = gadget_release;
 	udc->gadget.dev.release = gadget_release;
 	udc->gadget.name = driver_name;		/* gadget name */
 	udc->gadget.name = driver_name;		/* gadget name */
 
 
 	retval = device_register(&udc->gadget.dev);
 	retval = device_register(&udc->gadget.dev);
 	if (retval)
 	if (retval)
-		goto err_free_irq;
+		goto err_destroy_dma;
 
 
 	eps_init(udc);
 	eps_init(udc);
 
 
 	/* VBUS detect: we can disable/enable clock on demand.*/
 	/* VBUS detect: we can disable/enable clock on demand.*/
-	if (!IS_ERR_OR_NULL(udc->transceiver))
+	if (udc->transceiver)
 		udc->clock_gating = 1;
 		udc->clock_gating = 1;
 	else if (pdata->vbus) {
 	else if (pdata->vbus) {
 		udc->clock_gating = 1;
 		udc->clock_gating = 1;
-		retval = request_threaded_irq(pdata->vbus->irq, NULL,
+		retval = devm_request_threaded_irq(&pdev->dev,
+				pdata->vbus->irq, NULL,
 				mv_udc_vbus_irq, IRQF_ONESHOT, "vbus", udc);
 				mv_udc_vbus_irq, IRQF_ONESHOT, "vbus", udc);
 		if (retval) {
 		if (retval) {
-			dev_info(&dev->dev,
+			dev_info(&pdev->dev,
 				"Can not request irq for VBUS, "
 				"Can not request irq for VBUS, "
 				"disable clock gating\n");
 				"disable clock gating\n");
 			udc->clock_gating = 0;
 			udc->clock_gating = 0;
@@ -2378,7 +2340,7 @@ static int mv_udc_probe(struct platform_device *dev)
 
 
 		udc->qwork = create_singlethread_workqueue("mv_udc_queue");
 		udc->qwork = create_singlethread_workqueue("mv_udc_queue");
 		if (!udc->qwork) {
 		if (!udc->qwork) {
-			dev_err(&dev->dev, "cannot create workqueue\n");
+			dev_err(&pdev->dev, "cannot create workqueue\n");
 			retval = -ENOMEM;
 			retval = -ENOMEM;
 			goto err_unregister;
 			goto err_unregister;
 		}
 		}
@@ -2396,53 +2358,40 @@ static int mv_udc_probe(struct platform_device *dev)
 	else
 	else
 		udc->vbus_active = 1;
 		udc->vbus_active = 1;
 
 
-	retval = usb_add_gadget_udc(&dev->dev, &udc->gadget);
+	retval = usb_add_gadget_udc(&pdev->dev, &udc->gadget);
 	if (retval)
 	if (retval)
-		goto err_unregister;
+		goto err_create_workqueue;
 
 
-	dev_info(&dev->dev, "successful probe UDC device %s clock gating.\n",
+	platform_set_drvdata(pdev, udc);
+	dev_info(&pdev->dev, "successful probe UDC device %s clock gating.\n",
 		udc->clock_gating ? "with" : "without");
 		udc->clock_gating ? "with" : "without");
 
 
 	return 0;
 	return 0;
 
 
+err_create_workqueue:
+	destroy_workqueue(udc->qwork);
 err_unregister:
 err_unregister:
-	if (udc->pdata && udc->pdata->vbus
-		&& udc->clock_gating && IS_ERR_OR_NULL(udc->transceiver))
-		free_irq(pdata->vbus->irq, &dev->dev);
 	device_unregister(&udc->gadget.dev);
 	device_unregister(&udc->gadget.dev);
-err_free_irq:
-	free_irq(udc->irq, &dev->dev);
-err_free_status_req:
-	kfree(udc->status_req->req.buf);
-	kfree(udc->status_req);
-err_free_eps:
-	kfree(udc->eps);
 err_destroy_dma:
 err_destroy_dma:
 	dma_pool_destroy(udc->dtd_pool);
 	dma_pool_destroy(udc->dtd_pool);
 err_free_dma:
 err_free_dma:
-	dma_free_coherent(&dev->dev, udc->ep_dqh_size,
+	dma_free_coherent(&pdev->dev, udc->ep_dqh_size,
 			udc->ep_dqh, udc->ep_dqh_dma);
 			udc->ep_dqh, udc->ep_dqh_dma);
 err_disable_clock:
 err_disable_clock:
 	mv_udc_disable_internal(udc);
 	mv_udc_disable_internal(udc);
-err_iounmap_phyreg:
-	iounmap(udc->phy_regs);
-err_iounmap_capreg:
-	iounmap(udc->cap_regs);
-err_put_clk:
-	for (clk_i--; clk_i >= 0; clk_i--)
-		clk_put(udc->clk[clk_i]);
-	the_controller = NULL;
-	kfree(udc);
+
 	return retval;
 	return retval;
 }
 }
 
 
 #ifdef CONFIG_PM
 #ifdef CONFIG_PM
-static int mv_udc_suspend(struct device *_dev)
+static int mv_udc_suspend(struct device *dev)
 {
 {
-	struct mv_udc *udc = the_controller;
+	struct mv_udc *udc;
+
+	udc = dev_get_drvdata(dev);
 
 
 	/* if OTG is enabled, the following will be done in OTG driver*/
 	/* if OTG is enabled, the following will be done in OTG driver*/
-	if (!IS_ERR_OR_NULL(udc->transceiver))
+	if (udc->transceiver)
 		return 0;
 		return 0;
 
 
 	if (udc->pdata->vbus && udc->pdata->vbus->poll)
 	if (udc->pdata->vbus && udc->pdata->vbus->poll)
@@ -2469,13 +2418,15 @@ static int mv_udc_suspend(struct device *_dev)
 	return 0;
 	return 0;
 }
 }
 
 
-static int mv_udc_resume(struct device *_dev)
+static int mv_udc_resume(struct device *dev)
 {
 {
-	struct mv_udc *udc = the_controller;
+	struct mv_udc *udc;
 	int retval;
 	int retval;
 
 
+	udc = dev_get_drvdata(dev);
+
 	/* if OTG is enabled, the following will be done in OTG driver*/
 	/* if OTG is enabled, the following will be done in OTG driver*/
-	if (!IS_ERR_OR_NULL(udc->transceiver))
+	if (udc->transceiver)
 		return 0;
 		return 0;
 
 
 	if (!udc->clock_gating) {
 	if (!udc->clock_gating) {
@@ -2499,11 +2450,12 @@ static const struct dev_pm_ops mv_udc_pm_ops = {
 };
 };
 #endif
 #endif
 
 
-static void mv_udc_shutdown(struct platform_device *dev)
+static void mv_udc_shutdown(struct platform_device *pdev)
 {
 {
-	struct mv_udc *udc = the_controller;
+	struct mv_udc *udc;
 	u32 mode;
 	u32 mode;
 
 
+	udc = platform_get_drvdata(pdev);
 	/* reset controller mode to IDLE */
 	/* reset controller mode to IDLE */
 	mv_udc_enable(udc);
 	mv_udc_enable(udc);
 	mode = readl(&udc->op_regs->usbmode);
 	mode = readl(&udc->op_regs->usbmode);
@@ -2514,7 +2466,7 @@ static void mv_udc_shutdown(struct platform_device *dev)
 
 
 static struct platform_driver udc_driver = {
 static struct platform_driver udc_driver = {
 	.probe		= mv_udc_probe,
 	.probe		= mv_udc_probe,
-	.remove		= __exit_p(mv_udc_remove),
+	.remove		= mv_udc_remove,
 	.shutdown	= mv_udc_shutdown,
 	.shutdown	= mv_udc_shutdown,
 	.driver		= {
 	.driver		= {
 		.owner	= THIS_MODULE,
 		.owner	= THIS_MODULE,

+ 31 - 12
drivers/usb/gadget/nokia.c

@@ -37,7 +37,7 @@
  * the runtime footprint, and giving us at least some parts of what
  * the runtime footprint, and giving us at least some parts of what
  * a "gcc --combine ... part1.c part2.c part3.c ... " build would.
  * a "gcc --combine ... part1.c part2.c part3.c ... " build would.
  */
  */
-#include "u_serial.c"
+#define USB_FACM_INCLUDED
 #include "f_acm.c"
 #include "f_acm.c"
 #include "f_ecm.c"
 #include "f_ecm.c"
 #include "f_obex.c"
 #include "f_obex.c"
@@ -101,6 +101,15 @@ MODULE_LICENSE("GPL");
 
 
 static u8 hostaddr[ETH_ALEN];
 static u8 hostaddr[ETH_ALEN];
 
 
+enum {
+	TTY_PORT_OBEX0,
+	TTY_PORT_OBEX1,
+	TTY_PORT_ACM,
+	TTY_PORTS_MAX,
+};
+
+static unsigned char tty_lines[TTY_PORTS_MAX];
+
 static int __init nokia_bind_config(struct usb_configuration *c)
 static int __init nokia_bind_config(struct usb_configuration *c)
 {
 {
 	int status = 0;
 	int status = 0;
@@ -109,15 +118,15 @@ static int __init nokia_bind_config(struct usb_configuration *c)
 	if (status)
 	if (status)
 		printk(KERN_DEBUG "could not bind phonet config\n");
 		printk(KERN_DEBUG "could not bind phonet config\n");
 
 
-	status = obex_bind_config(c, 0);
+	status = obex_bind_config(c, tty_lines[TTY_PORT_OBEX0]);
 	if (status)
 	if (status)
 		printk(KERN_DEBUG "could not bind obex config %d\n", 0);
 		printk(KERN_DEBUG "could not bind obex config %d\n", 0);
 
 
-	status = obex_bind_config(c, 1);
+	status = obex_bind_config(c, tty_lines[TTY_PORT_OBEX1]);
 	if (status)
 	if (status)
 		printk(KERN_DEBUG "could not bind obex config %d\n", 0);
 		printk(KERN_DEBUG "could not bind obex config %d\n", 0);
 
 
-	status = acm_bind_config(c, 2);
+	status = acm_bind_config(c, tty_lines[TTY_PORT_ACM]);
 	if (status)
 	if (status)
 		printk(KERN_DEBUG "could not bind acm config\n");
 		printk(KERN_DEBUG "could not bind acm config\n");
 
 
@@ -133,7 +142,7 @@ static struct usb_configuration nokia_config_500ma_driver = {
 	.bConfigurationValue = 1,
 	.bConfigurationValue = 1,
 	/* .iConfiguration = DYNAMIC */
 	/* .iConfiguration = DYNAMIC */
 	.bmAttributes	= USB_CONFIG_ATT_ONE,
 	.bmAttributes	= USB_CONFIG_ATT_ONE,
-	.bMaxPower	= 250, /* 500mA */
+	.MaxPower	= 500,
 };
 };
 
 
 static struct usb_configuration nokia_config_100ma_driver = {
 static struct usb_configuration nokia_config_100ma_driver = {
@@ -141,21 +150,24 @@ static struct usb_configuration nokia_config_100ma_driver = {
 	.bConfigurationValue = 2,
 	.bConfigurationValue = 2,
 	/* .iConfiguration = DYNAMIC */
 	/* .iConfiguration = DYNAMIC */
 	.bmAttributes	= USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
 	.bmAttributes	= USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
-	.bMaxPower	= 50, /* 100 mA */
+	.MaxPower	= 100,
 };
 };
 
 
 static int __init nokia_bind(struct usb_composite_dev *cdev)
 static int __init nokia_bind(struct usb_composite_dev *cdev)
 {
 {
 	struct usb_gadget	*gadget = cdev->gadget;
 	struct usb_gadget	*gadget = cdev->gadget;
 	int			status;
 	int			status;
+	int			cur_line;
 
 
 	status = gphonet_setup(cdev->gadget);
 	status = gphonet_setup(cdev->gadget);
 	if (status < 0)
 	if (status < 0)
 		goto err_phonet;
 		goto err_phonet;
 
 
-	status = gserial_setup(cdev->gadget, 3);
-	if (status < 0)
-		goto err_serial;
+	for (cur_line = 0; cur_line < TTY_PORTS_MAX; cur_line++) {
+		status = gserial_alloc_line(&tty_lines[cur_line]);
+		if (status)
+			goto err_ether;
+	}
 
 
 	status = gether_setup(cdev->gadget, hostaddr);
 	status = gether_setup(cdev->gadget, hostaddr);
 	if (status < 0)
 	if (status < 0)
@@ -192,8 +204,10 @@ static int __init nokia_bind(struct usb_composite_dev *cdev)
 err_usb:
 err_usb:
 	gether_cleanup();
 	gether_cleanup();
 err_ether:
 err_ether:
-	gserial_cleanup();
-err_serial:
+	cur_line--;
+	while (cur_line >= 0)
+		gserial_free_line(tty_lines[cur_line--]);
+
 	gphonet_cleanup();
 	gphonet_cleanup();
 err_phonet:
 err_phonet:
 	return status;
 	return status;
@@ -201,8 +215,13 @@ err_phonet:
 
 
 static int __exit nokia_unbind(struct usb_composite_dev *cdev)
 static int __exit nokia_unbind(struct usb_composite_dev *cdev)
 {
 {
+	int i;
+
 	gphonet_cleanup();
 	gphonet_cleanup();
-	gserial_cleanup();
+
+	for (i = 0; i < TTY_PORTS_MAX; i++)
+		gserial_free_line(tty_lines[i]);
+
 	gether_cleanup();
 	gether_cleanup();
 
 
 	return 0;
 	return 0;

+ 13 - 38
drivers/usb/gadget/omap_udc.c

@@ -1309,19 +1309,20 @@ static int omap_pullup(struct usb_gadget *gadget, int is_on)
 	return 0;
 	return 0;
 }
 }
 
 
-static int omap_udc_start(struct usb_gadget_driver *driver,
-		int (*bind)(struct usb_gadget *, struct usb_gadget_driver *));
-static int omap_udc_stop(struct usb_gadget_driver *driver);
+static int omap_udc_start(struct usb_gadget *g,
+		struct usb_gadget_driver *driver)
+static int omap_udc_stop(struct usb_gadget *g,
+		struct usb_gadget_driver *driver);
 
 
-static struct usb_gadget_ops omap_gadget_ops = {
+static const struct usb_gadget_ops omap_gadget_ops = {
 	.get_frame		= omap_get_frame,
 	.get_frame		= omap_get_frame,
 	.wakeup			= omap_wakeup,
 	.wakeup			= omap_wakeup,
 	.set_selfpowered	= omap_set_selfpowered,
 	.set_selfpowered	= omap_set_selfpowered,
 	.vbus_session		= omap_vbus_session,
 	.vbus_session		= omap_vbus_session,
 	.vbus_draw		= omap_vbus_draw,
 	.vbus_draw		= omap_vbus_draw,
 	.pullup			= omap_pullup,
 	.pullup			= omap_pullup,
-	.start			= omap_udc_start,
-	.stop			= omap_udc_stop,
+	.udc_start		= omap_udc_start,
+	.udc_stop		= omap_udc_stop,
 };
 };
 
 
 /*-------------------------------------------------------------------------*/
 /*-------------------------------------------------------------------------*/
@@ -2041,28 +2042,15 @@ static inline int machine_without_vbus_sense(void)
 		|| cpu_is_omap7xx();
 		|| cpu_is_omap7xx();
 }
 }
 
 
-static int omap_udc_start(struct usb_gadget_driver *driver,
-		int (*bind)(struct usb_gadget *, struct usb_gadget_driver *))
+static int omap_udc_start(struct usb_gadget *g,
+		struct usb_gadget_driver *driver)
 {
 {
 	int		status = -ENODEV;
 	int		status = -ENODEV;
 	struct omap_ep	*ep;
 	struct omap_ep	*ep;
 	unsigned long	flags;
 	unsigned long	flags;
 
 
-	/* basic sanity tests */
-	if (!udc)
-		return -ENODEV;
-	if (!driver
-			/* FIXME if otg, check:  driver->is_otg */
-			|| driver->max_speed < USB_SPEED_FULL
-			|| !bind || !driver->setup)
-		return -EINVAL;
 
 
 	spin_lock_irqsave(&udc->lock, flags);
 	spin_lock_irqsave(&udc->lock, flags);
-	if (udc->driver) {
-		spin_unlock_irqrestore(&udc->lock, flags);
-		return -EBUSY;
-	}
-
 	/* reset state */
 	/* reset state */
 	list_for_each_entry(ep, &udc->gadget.ep_list, ep.ep_list) {
 	list_for_each_entry(ep, &udc->gadget.ep_list, ep.ep_list) {
 		ep->irqs = 0;
 		ep->irqs = 0;
@@ -2084,15 +2072,6 @@ static int omap_udc_start(struct usb_gadget_driver *driver,
 	if (udc->dc_clk != NULL)
 	if (udc->dc_clk != NULL)
 		omap_udc_enable_clock(1);
 		omap_udc_enable_clock(1);
 
 
-	status = bind(&udc->gadget, driver);
-	if (status) {
-		DBG("bind to %s --> %d\n", driver->driver.name, status);
-		udc->gadget.dev.driver = NULL;
-		udc->driver = NULL;
-		goto done;
-	}
-	DBG("bound to driver %s\n", driver->driver.name);
-
 	omap_writew(UDC_IRQ_SRC_MASK, UDC_IRQ_SRC);
 	omap_writew(UDC_IRQ_SRC_MASK, UDC_IRQ_SRC);
 
 
 	/* connect to bus through transceiver */
 	/* connect to bus through transceiver */
@@ -2124,19 +2103,16 @@ static int omap_udc_start(struct usb_gadget_driver *driver,
 done:
 done:
 	if (udc->dc_clk != NULL)
 	if (udc->dc_clk != NULL)
 		omap_udc_enable_clock(0);
 		omap_udc_enable_clock(0);
+
 	return status;
 	return status;
 }
 }
 
 
-static int omap_udc_stop(struct usb_gadget_driver *driver)
+static int omap_udc_stop(struct usb_gadget *g,
+		struct usb_gadget_driver *driver)
 {
 {
 	unsigned long	flags;
 	unsigned long	flags;
 	int		status = -ENODEV;
 	int		status = -ENODEV;
 
 
-	if (!udc)
-		return -ENODEV;
-	if (!driver || driver != udc->driver || !driver->unbind)
-		return -EINVAL;
-
 	if (udc->dc_clk != NULL)
 	if (udc->dc_clk != NULL)
 		omap_udc_enable_clock(1);
 		omap_udc_enable_clock(1);
 
 
@@ -2152,13 +2128,12 @@ static int omap_udc_stop(struct usb_gadget_driver *driver)
 	udc_quiesce(udc);
 	udc_quiesce(udc);
 	spin_unlock_irqrestore(&udc->lock, flags);
 	spin_unlock_irqrestore(&udc->lock, flags);
 
 
-	driver->unbind(&udc->gadget);
 	udc->gadget.dev.driver = NULL;
 	udc->gadget.dev.driver = NULL;
 	udc->driver = NULL;
 	udc->driver = NULL;
 
 
 	if (udc->dc_clk != NULL)
 	if (udc->dc_clk != NULL)
 		omap_udc_enable_clock(0);
 		omap_udc_enable_clock(0);
-	DBG("unregistered driver '%s'\n", driver->driver.name);
+
 	return status;
 	return status;
 }
 }
 
 

+ 14 - 53
drivers/usb/gadget/pch_udc.c

@@ -375,6 +375,7 @@ struct pch_udc_dev {
 	struct pch_udc_cfg_data		cfg_data;
 	struct pch_udc_cfg_data		cfg_data;
 	struct pch_vbus_gpio_data	vbus_gpio;
 	struct pch_vbus_gpio_data	vbus_gpio;
 };
 };
+#define to_pch_udc(g)	(container_of((g), struct pch_udc_dev, gadget))
 
 
 #define PCH_UDC_PCI_BAR			1
 #define PCH_UDC_PCI_BAR			1
 #define PCI_DEVICE_ID_INTEL_EG20T_UDC	0x8808
 #define PCI_DEVICE_ID_INTEL_EG20T_UDC	0x8808
@@ -384,7 +385,6 @@ struct pch_udc_dev {
 
 
 static const char	ep0_string[] = "ep0in";
 static const char	ep0_string[] = "ep0in";
 static DEFINE_SPINLOCK(udc_stall_spinlock);	/* stall spin lock */
 static DEFINE_SPINLOCK(udc_stall_spinlock);	/* stall spin lock */
-struct pch_udc_dev *pch_udc;		/* pointer to device object */
 static bool speed_fs;
 static bool speed_fs;
 module_param_named(speed_fs, speed_fs, bool, S_IRUGO);
 module_param_named(speed_fs, speed_fs, bool, S_IRUGO);
 MODULE_PARM_DESC(speed_fs, "true for Full speed operation");
 MODULE_PARM_DESC(speed_fs, "true for Full speed operation");
@@ -1235,9 +1235,10 @@ static int pch_udc_pcd_vbus_draw(struct usb_gadget *gadget, unsigned int mA)
 	return -EOPNOTSUPP;
 	return -EOPNOTSUPP;
 }
 }
 
 
-static int pch_udc_start(struct usb_gadget_driver *driver,
-	int (*bind)(struct usb_gadget *, struct usb_gadget_driver *));
-static int pch_udc_stop(struct usb_gadget_driver *driver);
+static int pch_udc_start(struct usb_gadget *g,
+		struct usb_gadget_driver *driver);
+static int pch_udc_stop(struct usb_gadget *g,
+		struct usb_gadget_driver *driver);
 static const struct usb_gadget_ops pch_udc_ops = {
 static const struct usb_gadget_ops pch_udc_ops = {
 	.get_frame = pch_udc_pcd_get_frame,
 	.get_frame = pch_udc_pcd_get_frame,
 	.wakeup = pch_udc_pcd_wakeup,
 	.wakeup = pch_udc_pcd_wakeup,
@@ -1245,8 +1246,8 @@ static const struct usb_gadget_ops pch_udc_ops = {
 	.pullup = pch_udc_pcd_pullup,
 	.pullup = pch_udc_pcd_pullup,
 	.vbus_session = pch_udc_pcd_vbus_session,
 	.vbus_session = pch_udc_pcd_vbus_session,
 	.vbus_draw = pch_udc_pcd_vbus_draw,
 	.vbus_draw = pch_udc_pcd_vbus_draw,
-	.start	= pch_udc_start,
-	.stop	= pch_udc_stop,
+	.udc_start = pch_udc_start,
+	.udc_stop = pch_udc_stop,
 };
 };
 
 
 /**
 /**
@@ -2981,40 +2982,15 @@ static int init_dma_pools(struct pch_udc_dev *dev)
 	return 0;
 	return 0;
 }
 }
 
 
-static int pch_udc_start(struct usb_gadget_driver *driver,
-	int (*bind)(struct usb_gadget *, struct usb_gadget_driver *))
+static int pch_udc_start(struct usb_gadget *g,
+		struct usb_gadget_driver *driver)
 {
 {
-	struct pch_udc_dev	*dev = pch_udc;
-	int			retval;
-
-	if (!driver || (driver->max_speed == USB_SPEED_UNKNOWN) || !bind ||
-	    !driver->setup || !driver->unbind || !driver->disconnect) {
-		dev_err(&dev->pdev->dev,
-			"%s: invalid driver parameter\n", __func__);
-		return -EINVAL;
-	}
+	struct pch_udc_dev	*dev = to_pch_udc(g);
 
 
-	if (!dev)
-		return -ENODEV;
-
-	if (dev->driver) {
-		dev_err(&dev->pdev->dev, "%s: already bound\n", __func__);
-		return -EBUSY;
-	}
 	driver->driver.bus = NULL;
 	driver->driver.bus = NULL;
 	dev->driver = driver;
 	dev->driver = driver;
 	dev->gadget.dev.driver = &driver->driver;
 	dev->gadget.dev.driver = &driver->driver;
 
 
-	/* Invoke the bind routine of the gadget driver */
-	retval = bind(&dev->gadget, driver);
-
-	if (retval) {
-		dev_err(&dev->pdev->dev, "%s: binding to %s returning %d\n",
-		       __func__, driver->driver.name, retval);
-		dev->driver = NULL;
-		dev->gadget.dev.driver = NULL;
-		return retval;
-	}
 	/* get ready for ep0 traffic */
 	/* get ready for ep0 traffic */
 	pch_udc_setup_ep0(dev);
 	pch_udc_setup_ep0(dev);
 
 
@@ -3026,30 +3002,21 @@ static int pch_udc_start(struct usb_gadget_driver *driver,
 	return 0;
 	return 0;
 }
 }
 
 
-static int pch_udc_stop(struct usb_gadget_driver *driver)
+static int pch_udc_stop(struct usb_gadget *g,
+		struct usb_gadget_driver *driver)
 {
 {
-	struct pch_udc_dev	*dev = pch_udc;
-
-	if (!dev)
-		return -ENODEV;
-
-	if (!driver || (driver != dev->driver)) {
-		dev_err(&dev->pdev->dev,
-			"%s: invalid driver parameter\n", __func__);
-		return -EINVAL;
-	}
+	struct pch_udc_dev	*dev = to_pch_udc(g);
 
 
 	pch_udc_disable_interrupts(dev, UDC_DEVINT_MSK);
 	pch_udc_disable_interrupts(dev, UDC_DEVINT_MSK);
 
 
 	/* Assures that there are no pending requests with this driver */
 	/* Assures that there are no pending requests with this driver */
-	driver->disconnect(&dev->gadget);
-	driver->unbind(&dev->gadget);
 	dev->gadget.dev.driver = NULL;
 	dev->gadget.dev.driver = NULL;
 	dev->driver = NULL;
 	dev->driver = NULL;
 	dev->connected = 0;
 	dev->connected = 0;
 
 
 	/* set SD */
 	/* set SD */
 	pch_udc_set_disconnect(dev);
 	pch_udc_set_disconnect(dev);
+
 	return 0;
 	return 0;
 }
 }
 
 
@@ -3164,11 +3131,6 @@ static int pch_udc_probe(struct pci_dev *pdev,
 	int			retval;
 	int			retval;
 	struct pch_udc_dev	*dev;
 	struct pch_udc_dev	*dev;
 
 
-	/* one udc only */
-	if (pch_udc) {
-		pr_err("%s: already probed\n", __func__);
-		return -EBUSY;
-	}
 	/* init */
 	/* init */
 	dev = kzalloc(sizeof *dev, GFP_KERNEL);
 	dev = kzalloc(sizeof *dev, GFP_KERNEL);
 	if (!dev) {
 	if (!dev) {
@@ -3207,7 +3169,6 @@ static int pch_udc_probe(struct pci_dev *pdev,
 		retval = -ENODEV;
 		retval = -ENODEV;
 		goto finished;
 		goto finished;
 	}
 	}
-	pch_udc = dev;
 	/* initialize the hardware */
 	/* initialize the hardware */
 	if (pch_udc_pcd_init(dev)) {
 	if (pch_udc_pcd_init(dev)) {
 		retval = -ENODEV;
 		retval = -ENODEV;

+ 14 - 48
drivers/usb/gadget/pxa25x_udc.c

@@ -996,9 +996,10 @@ static int pxa25x_udc_vbus_draw(struct usb_gadget *_gadget, unsigned mA)
 	return -EOPNOTSUPP;
 	return -EOPNOTSUPP;
 }
 }
 
 
-static int pxa25x_start(struct usb_gadget_driver *driver,
-		int (*bind)(struct usb_gadget *, struct usb_gadget_driver *));
-static int pxa25x_stop(struct usb_gadget_driver *driver);
+static int pxa25x_udc_start(struct usb_gadget *g,
+		struct usb_gadget_driver *driver);
+static int pxa25x_udc_stop(struct usb_gadget *g,
+		struct usb_gadget_driver *driver);
 
 
 static const struct usb_gadget_ops pxa25x_udc_ops = {
 static const struct usb_gadget_ops pxa25x_udc_ops = {
 	.get_frame	= pxa25x_udc_get_frame,
 	.get_frame	= pxa25x_udc_get_frame,
@@ -1006,8 +1007,8 @@ static const struct usb_gadget_ops pxa25x_udc_ops = {
 	.vbus_session	= pxa25x_udc_vbus_session,
 	.vbus_session	= pxa25x_udc_vbus_session,
 	.pullup		= pxa25x_udc_pullup,
 	.pullup		= pxa25x_udc_pullup,
 	.vbus_draw	= pxa25x_udc_vbus_draw,
 	.vbus_draw	= pxa25x_udc_vbus_draw,
-	.start		= pxa25x_start,
-	.stop		= pxa25x_stop,
+	.udc_start	= pxa25x_udc_start,
+	.udc_stop	= pxa25x_udc_stop,
 };
 };
 
 
 /*-------------------------------------------------------------------------*/
 /*-------------------------------------------------------------------------*/
@@ -1254,23 +1255,12 @@ static void udc_enable (struct pxa25x_udc *dev)
  * disconnect is reported.  then a host may connect again, or
  * disconnect is reported.  then a host may connect again, or
  * the driver might get unbound.
  * the driver might get unbound.
  */
  */
-static int pxa25x_start(struct usb_gadget_driver *driver,
-		int (*bind)(struct usb_gadget *, struct usb_gadget_driver *))
+static int pxa25x_udc_start(struct usb_gadget *g,
+		struct usb_gadget_driver *driver)
 {
 {
-	struct pxa25x_udc	*dev = the_controller;
+	struct pxa25x_udc	*dev = to_pxa25x(g);
 	int			retval;
 	int			retval;
 
 
-	if (!driver
-			|| driver->max_speed < USB_SPEED_FULL
-			|| !bind
-			|| !driver->disconnect
-			|| !driver->setup)
-		return -EINVAL;
-	if (!dev)
-		return -ENODEV;
-	if (dev->driver)
-		return -EBUSY;
-
 	/* first hook up the driver ... */
 	/* first hook up the driver ... */
 	dev->driver = driver;
 	dev->driver = driver;
 	dev->gadget.dev.driver = &driver->driver;
 	dev->gadget.dev.driver = &driver->driver;
@@ -1278,34 +1268,20 @@ static int pxa25x_start(struct usb_gadget_driver *driver,
 
 
 	retval = device_add (&dev->gadget.dev);
 	retval = device_add (&dev->gadget.dev);
 	if (retval) {
 	if (retval) {
-fail:
 		dev->driver = NULL;
 		dev->driver = NULL;
 		dev->gadget.dev.driver = NULL;
 		dev->gadget.dev.driver = NULL;
 		return retval;
 		return retval;
 	}
 	}
-	retval = bind(&dev->gadget, driver);
-	if (retval) {
-		DMSG("bind to driver %s --> error %d\n",
-				driver->driver.name, retval);
-		device_del (&dev->gadget.dev);
-		goto fail;
-	}
 
 
 	/* ... then enable host detection and ep0; and we're ready
 	/* ... then enable host detection and ep0; and we're ready
 	 * for set_configuration as well as eventual disconnect.
 	 * for set_configuration as well as eventual disconnect.
 	 */
 	 */
-	DMSG("registered gadget driver '%s'\n", driver->driver.name);
-
 	/* connect to bus through transceiver */
 	/* connect to bus through transceiver */
 	if (!IS_ERR_OR_NULL(dev->transceiver)) {
 	if (!IS_ERR_OR_NULL(dev->transceiver)) {
 		retval = otg_set_peripheral(dev->transceiver->otg,
 		retval = otg_set_peripheral(dev->transceiver->otg,
 						&dev->gadget);
 						&dev->gadget);
-		if (retval) {
-			DMSG("can't bind to transceiver\n");
-			if (driver->unbind)
-				driver->unbind(&dev->gadget);
+		if (retval)
 			goto bind_fail;
 			goto bind_fail;
-		}
 	}
 	}
 
 
 	pullup(dev);
 	pullup(dev);
@@ -1334,22 +1310,14 @@ stop_activity(struct pxa25x_udc *dev, struct usb_gadget_driver *driver)
 	}
 	}
 	del_timer_sync(&dev->timer);
 	del_timer_sync(&dev->timer);
 
 
-	/* report disconnect; the driver is already quiesced */
-	if (driver)
-		driver->disconnect(&dev->gadget);
-
 	/* re-init driver-visible data structures */
 	/* re-init driver-visible data structures */
 	udc_reinit(dev);
 	udc_reinit(dev);
 }
 }
 
 
-static int pxa25x_stop(struct usb_gadget_driver *driver)
+static int pxa25x_udc_stop(struct usb_gadget*g,
+		struct usb_gadget_driver *driver)
 {
 {
-	struct pxa25x_udc	*dev = the_controller;
-
-	if (!dev)
-		return -ENODEV;
-	if (!driver || driver != dev->driver || !driver->unbind)
-		return -EINVAL;
+	struct pxa25x_udc	*dev = to_pxa25x(g);
 
 
 	local_irq_disable();
 	local_irq_disable();
 	dev->pullup = 0;
 	dev->pullup = 0;
@@ -1360,14 +1328,12 @@ static int pxa25x_stop(struct usb_gadget_driver *driver)
 	if (!IS_ERR_OR_NULL(dev->transceiver))
 	if (!IS_ERR_OR_NULL(dev->transceiver))
 		(void) otg_set_peripheral(dev->transceiver->otg, NULL);
 		(void) otg_set_peripheral(dev->transceiver->otg, NULL);
 
 
-	driver->unbind(&dev->gadget);
 	dev->gadget.dev.driver = NULL;
 	dev->gadget.dev.driver = NULL;
 	dev->driver = NULL;
 	dev->driver = NULL;
 
 
 	device_del (&dev->gadget.dev);
 	device_del (&dev->gadget.dev);
-
-	DMSG("unregistered gadget driver '%s'\n", driver->driver.name);
 	dump_state(dev);
 	dump_state(dev);
+
 	return 0;
 	return 0;
 }
 }
 
 

+ 1 - 0
drivers/usb/gadget/pxa25x_udc.h

@@ -126,6 +126,7 @@ struct pxa25x_udc {
 	struct dentry				*debugfs_udc;
 	struct dentry				*debugfs_udc;
 #endif
 #endif
 };
 };
+#define to_pxa25x(g)	(container_of((g), struct pxa25x_udc, gadget))
 
 
 /*-------------------------------------------------------------------------*/
 /*-------------------------------------------------------------------------*/
 
 

+ 15 - 46
drivers/usb/gadget/pxa27x_udc.c

@@ -1671,9 +1671,10 @@ static int pxa_udc_vbus_draw(struct usb_gadget *_gadget, unsigned mA)
 	return -EOPNOTSUPP;
 	return -EOPNOTSUPP;
 }
 }
 
 
-static int pxa27x_udc_start(struct usb_gadget_driver *driver,
-		int (*bind)(struct usb_gadget *, struct usb_gadget_driver *));
-static int pxa27x_udc_stop(struct usb_gadget_driver *driver);
+static int pxa27x_udc_start(struct usb_gadget *g,
+		struct usb_gadget_driver *driver);
+static int pxa27x_udc_stop(struct usb_gadget *g,
+		struct usb_gadget_driver *driver);
 
 
 static const struct usb_gadget_ops pxa_udc_ops = {
 static const struct usb_gadget_ops pxa_udc_ops = {
 	.get_frame	= pxa_udc_get_frame,
 	.get_frame	= pxa_udc_get_frame,
@@ -1681,8 +1682,8 @@ static const struct usb_gadget_ops pxa_udc_ops = {
 	.pullup		= pxa_udc_pullup,
 	.pullup		= pxa_udc_pullup,
 	.vbus_session	= pxa_udc_vbus_session,
 	.vbus_session	= pxa_udc_vbus_session,
 	.vbus_draw	= pxa_udc_vbus_draw,
 	.vbus_draw	= pxa_udc_vbus_draw,
-	.start		= pxa27x_udc_start,
-	.stop		= pxa27x_udc_stop,
+	.udc_start	= pxa27x_udc_start,
+	.udc_stop	= pxa27x_udc_stop,
 };
 };
 
 
 /**
 /**
@@ -1802,20 +1803,12 @@ static void udc_enable(struct pxa_udc *udc)
  *
  *
  * Returns 0 if no error, -EINVAL, -ENODEV, -EBUSY otherwise
  * Returns 0 if no error, -EINVAL, -ENODEV, -EBUSY otherwise
  */
  */
-static int pxa27x_udc_start(struct usb_gadget_driver *driver,
-		int (*bind)(struct usb_gadget *, struct usb_gadget_driver *))
+static int pxa27x_udc_start(struct usb_gadget *g,
+		struct usb_gadget_driver *driver)
 {
 {
-	struct pxa_udc *udc = the_controller;
+	struct pxa_udc *udc = to_pxa(g);
 	int retval;
 	int retval;
 
 
-	if (!driver || driver->max_speed < USB_SPEED_FULL || !bind
-			|| !driver->disconnect || !driver->setup)
-		return -EINVAL;
-	if (!udc)
-		return -ENODEV;
-	if (udc->driver)
-		return -EBUSY;
-
 	/* first hook up the driver ... */
 	/* first hook up the driver ... */
 	udc->driver = driver;
 	udc->driver = driver;
 	udc->gadget.dev.driver = &driver->driver;
 	udc->gadget.dev.driver = &driver->driver;
@@ -1824,23 +1817,14 @@ static int pxa27x_udc_start(struct usb_gadget_driver *driver,
 	retval = device_add(&udc->gadget.dev);
 	retval = device_add(&udc->gadget.dev);
 	if (retval) {
 	if (retval) {
 		dev_err(udc->dev, "device_add error %d\n", retval);
 		dev_err(udc->dev, "device_add error %d\n", retval);
-		goto add_fail;
+		goto fail;
 	}
 	}
-	retval = bind(&udc->gadget, driver);
-	if (retval) {
-		dev_err(udc->dev, "bind to driver %s --> error %d\n",
-			driver->driver.name, retval);
-		goto bind_fail;
-	}
-	dev_dbg(udc->dev, "registered gadget driver '%s'\n",
-		driver->driver.name);
-
 	if (!IS_ERR_OR_NULL(udc->transceiver)) {
 	if (!IS_ERR_OR_NULL(udc->transceiver)) {
 		retval = otg_set_peripheral(udc->transceiver->otg,
 		retval = otg_set_peripheral(udc->transceiver->otg,
 						&udc->gadget);
 						&udc->gadget);
 		if (retval) {
 		if (retval) {
 			dev_err(udc->dev, "can't bind to transceiver\n");
 			dev_err(udc->dev, "can't bind to transceiver\n");
-			goto transceiver_fail;
+			goto fail;
 		}
 		}
 	}
 	}
 
 
@@ -1848,12 +1832,7 @@ static int pxa27x_udc_start(struct usb_gadget_driver *driver,
 		udc_enable(udc);
 		udc_enable(udc);
 	return 0;
 	return 0;
 
 
-transceiver_fail:
-	if (driver->unbind)
-		driver->unbind(&udc->gadget);
-bind_fail:
-	device_del(&udc->gadget.dev);
-add_fail:
+fail:
 	udc->driver = NULL;
 	udc->driver = NULL;
 	udc->gadget.dev.driver = NULL;
 	udc->gadget.dev.driver = NULL;
 	return retval;
 	return retval;
@@ -1878,9 +1857,6 @@ static void stop_activity(struct pxa_udc *udc, struct usb_gadget_driver *driver)
 
 
 	for (i = 0; i < NR_USB_ENDPOINTS; i++)
 	for (i = 0; i < NR_USB_ENDPOINTS; i++)
 		pxa_ep_disable(&udc->udc_usb_ep[i].usb_ep);
 		pxa_ep_disable(&udc->udc_usb_ep[i].usb_ep);
-
-	if (driver)
-		driver->disconnect(&udc->gadget);
 }
 }
 
 
 /**
 /**
@@ -1889,25 +1865,18 @@ static void stop_activity(struct pxa_udc *udc, struct usb_gadget_driver *driver)
  *
  *
  * Returns 0 if no error, -ENODEV, -EINVAL otherwise
  * Returns 0 if no error, -ENODEV, -EINVAL otherwise
  */
  */
-static int pxa27x_udc_stop(struct usb_gadget_driver *driver)
+static int pxa27x_udc_stop(struct usb_gadget *g,
+		struct usb_gadget_driver *driver)
 {
 {
-	struct pxa_udc *udc = the_controller;
-
-	if (!udc)
-		return -ENODEV;
-	if (!driver || driver != udc->driver || !driver->unbind)
-		return -EINVAL;
+	struct pxa_udc *udc = to_pxa(g);
 
 
 	stop_activity(udc, driver);
 	stop_activity(udc, driver);
 	udc_disable(udc);
 	udc_disable(udc);
 	dplus_pullup(udc, 0);
 	dplus_pullup(udc, 0);
 
 
-	driver->unbind(&udc->gadget);
 	udc->driver = NULL;
 	udc->driver = NULL;
 
 
 	device_del(&udc->gadget.dev);
 	device_del(&udc->gadget.dev);
-	dev_info(udc->dev, "unregistered gadget driver '%s'\n",
-		 driver->driver.name);
 
 
 	if (!IS_ERR_OR_NULL(udc->transceiver))
 	if (!IS_ERR_OR_NULL(udc->transceiver))
 		return otg_set_peripheral(udc->transceiver->otg, NULL);
 		return otg_set_peripheral(udc->transceiver->otg, NULL);

+ 1 - 0
drivers/usb/gadget/pxa27x_udc.h

@@ -473,6 +473,7 @@ struct pxa_udc {
 	struct dentry				*debugfs_eps;
 	struct dentry				*debugfs_eps;
 #endif
 #endif
 };
 };
+#define to_pxa(g)	(container_of((g), struct pxa_udc, gadget))
 
 
 static inline struct pxa_udc *to_gadget_udc(struct usb_gadget *gadget)
 static inline struct pxa_udc *to_gadget_udc(struct usb_gadget *gadget)
 {
 {

+ 1 - 1
drivers/usb/gadget/r8a66597-udc.c

@@ -1812,7 +1812,7 @@ static int r8a66597_set_selfpowered(struct usb_gadget *gadget, int is_self)
 	return 0;
 	return 0;
 }
 }
 
 
-static struct usb_gadget_ops r8a66597_gadget_ops = {
+static const struct usb_gadget_ops r8a66597_gadget_ops = {
 	.get_frame		= r8a66597_get_frame,
 	.get_frame		= r8a66597_get_frame,
 	.udc_start		= r8a66597_start,
 	.udc_start		= r8a66597_start,
 	.udc_stop		= r8a66597_stop,
 	.udc_stop		= r8a66597_stop,

+ 2 - 5
drivers/usb/gadget/s3c-hsotg.c

@@ -3055,7 +3055,7 @@ static int s3c_hsotg_pullup(struct usb_gadget *gadget, int is_on)
 	return 0;
 	return 0;
 }
 }
 
 
-static struct usb_gadget_ops s3c_hsotg_gadget_ops = {
+static const struct usb_gadget_ops s3c_hsotg_gadget_ops = {
 	.get_frame	= s3c_hsotg_gadget_getframe,
 	.get_frame	= s3c_hsotg_gadget_getframe,
 	.udc_start		= s3c_hsotg_udc_start,
 	.udc_start		= s3c_hsotg_udc_start,
 	.udc_stop		= s3c_hsotg_udc_stop,
 	.udc_stop		= s3c_hsotg_udc_stop,
@@ -3572,7 +3572,7 @@ static int s3c_hsotg_probe(struct platform_device *pdev)
 	for (i = 0; i < ARRAY_SIZE(hsotg->supplies); i++)
 	for (i = 0; i < ARRAY_SIZE(hsotg->supplies); i++)
 		hsotg->supplies[i].supply = s3c_hsotg_supply_names[i];
 		hsotg->supplies[i].supply = s3c_hsotg_supply_names[i];
 
 
-	ret = regulator_bulk_get(dev, ARRAY_SIZE(hsotg->supplies),
+	ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(hsotg->supplies),
 				 hsotg->supplies);
 				 hsotg->supplies);
 	if (ret) {
 	if (ret) {
 		dev_err(dev, "failed to request supplies: %d\n", ret);
 		dev_err(dev, "failed to request supplies: %d\n", ret);
@@ -3662,8 +3662,6 @@ err_ep_mem:
 	kfree(eps);
 	kfree(eps);
 err_supplies:
 err_supplies:
 	s3c_hsotg_phy_disable(hsotg);
 	s3c_hsotg_phy_disable(hsotg);
-	regulator_bulk_free(ARRAY_SIZE(hsotg->supplies), hsotg->supplies);
-
 err_clk:
 err_clk:
 	clk_disable_unprepare(hsotg->clk);
 	clk_disable_unprepare(hsotg->clk);
 
 
@@ -3688,7 +3686,6 @@ static int s3c_hsotg_remove(struct platform_device *pdev)
 	}
 	}
 
 
 	s3c_hsotg_phy_disable(hsotg);
 	s3c_hsotg_phy_disable(hsotg);
-	regulator_bulk_free(ARRAY_SIZE(hsotg->supplies), hsotg->supplies);
 
 
 	clk_disable_unprepare(hsotg->clk);
 	clk_disable_unprepare(hsotg->clk);
 
 

+ 6 - 7
drivers/usb/gadget/s3c-hsudc.c

@@ -435,7 +435,7 @@ static void s3c_hsudc_epin_intr(struct s3c_hsudc *hsudc, u32 ep_idx)
 	struct s3c_hsudc_req *hsreq;
 	struct s3c_hsudc_req *hsreq;
 	u32 csr;
 	u32 csr;
 
 
-	csr = readl((u32)hsudc->regs + S3C_ESR);
+	csr = readl(hsudc->regs + S3C_ESR);
 	if (csr & S3C_ESR_STALL) {
 	if (csr & S3C_ESR_STALL) {
 		writel(S3C_ESR_STALL, hsudc->regs + S3C_ESR);
 		writel(S3C_ESR_STALL, hsudc->regs + S3C_ESR);
 		return;
 		return;
@@ -468,7 +468,7 @@ static void s3c_hsudc_epout_intr(struct s3c_hsudc *hsudc, u32 ep_idx)
 	struct s3c_hsudc_req *hsreq;
 	struct s3c_hsudc_req *hsreq;
 	u32 csr;
 	u32 csr;
 
 
-	csr = readl((u32)hsudc->regs + S3C_ESR);
+	csr = readl(hsudc->regs + S3C_ESR);
 	if (csr & S3C_ESR_STALL) {
 	if (csr & S3C_ESR_STALL) {
 		writel(S3C_ESR_STALL, hsudc->regs + S3C_ESR);
 		writel(S3C_ESR_STALL, hsudc->regs + S3C_ESR);
 		return;
 		return;
@@ -901,12 +901,12 @@ static int s3c_hsudc_queue(struct usb_ep *_ep, struct usb_request *_req,
 	if (list_empty(&hsep->queue) && !hsep->stopped) {
 	if (list_empty(&hsep->queue) && !hsep->stopped) {
 		offset = (ep_index(hsep)) ? S3C_ESR : S3C_EP0SR;
 		offset = (ep_index(hsep)) ? S3C_ESR : S3C_EP0SR;
 		if (ep_is_in(hsep)) {
 		if (ep_is_in(hsep)) {
-			csr = readl((u32)hsudc->regs + offset);
+			csr = readl(hsudc->regs + offset);
 			if (!(csr & S3C_ESR_TX_SUCCESS) &&
 			if (!(csr & S3C_ESR_TX_SUCCESS) &&
 				(s3c_hsudc_write_fifo(hsep, hsreq) == 1))
 				(s3c_hsudc_write_fifo(hsep, hsreq) == 1))
 				hsreq = NULL;
 				hsreq = NULL;
 		} else {
 		} else {
-			csr = readl((u32)hsudc->regs + offset);
+			csr = readl(hsudc->regs + offset);
 			if ((csr & S3C_ESR_RX_SUCCESS)
 			if ((csr & S3C_ESR_RX_SUCCESS)
 				   && (s3c_hsudc_read_fifo(hsep, hsreq) == 1))
 				   && (s3c_hsudc_read_fifo(hsep, hsreq) == 1))
 				hsreq = NULL;
 				hsreq = NULL;
@@ -1254,7 +1254,7 @@ static int s3c_hsudc_vbus_draw(struct usb_gadget *gadget, unsigned mA)
 	return -EOPNOTSUPP;
 	return -EOPNOTSUPP;
 }
 }
 
 
-static struct usb_gadget_ops s3c_hsudc_gadget_ops = {
+static const struct usb_gadget_ops s3c_hsudc_gadget_ops = {
 	.get_frame	= s3c_hsudc_gadget_getframe,
 	.get_frame	= s3c_hsudc_gadget_getframe,
 	.udc_start	= s3c_hsudc_start,
 	.udc_start	= s3c_hsudc_start,
 	.udc_stop	= s3c_hsudc_stop,
 	.udc_stop	= s3c_hsudc_stop,
@@ -1286,7 +1286,7 @@ static int s3c_hsudc_probe(struct platform_device *pdev)
 	for (i = 0; i < ARRAY_SIZE(hsudc->supplies); i++)
 	for (i = 0; i < ARRAY_SIZE(hsudc->supplies); i++)
 		hsudc->supplies[i].supply = s3c_hsudc_supply_names[i];
 		hsudc->supplies[i].supply = s3c_hsudc_supply_names[i];
 
 
-	ret = regulator_bulk_get(dev, ARRAY_SIZE(hsudc->supplies),
+	ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(hsudc->supplies),
 				 hsudc->supplies);
 				 hsudc->supplies);
 	if (ret != 0) {
 	if (ret != 0) {
 		dev_err(dev, "failed to request supplies: %d\n", ret);
 		dev_err(dev, "failed to request supplies: %d\n", ret);
@@ -1367,7 +1367,6 @@ err_res:
 	if (!IS_ERR_OR_NULL(hsudc->transceiver))
 	if (!IS_ERR_OR_NULL(hsudc->transceiver))
 		usb_put_phy(hsudc->transceiver);
 		usb_put_phy(hsudc->transceiver);
 
 
-	regulator_bulk_free(ARRAY_SIZE(hsudc->supplies), hsudc->supplies);
 err_supplies:
 err_supplies:
 	return ret;
 	return ret;
 }
 }

+ 12 - 53
drivers/usb/gadget/s3c2410_udc.c

@@ -1538,9 +1538,10 @@ static int s3c2410_vbus_draw(struct usb_gadget *_gadget, unsigned ma)
 	return -ENOTSUPP;
 	return -ENOTSUPP;
 }
 }
 
 
-static int s3c2410_udc_start(struct usb_gadget_driver *driver,
-		int (*bind)(struct usb_gadget *, struct usb_gadget_driver *));
-static int s3c2410_udc_stop(struct usb_gadget_driver *driver);
+static int s3c2410_udc_start(struct usb_gadget *g,
+		struct usb_gadget_driver *driver);
+static int s3c2410_udc_stop(struct usb_gadget *g,
+		struct usb_gadget_driver *driver);
 
 
 static const struct usb_gadget_ops s3c2410_ops = {
 static const struct usb_gadget_ops s3c2410_ops = {
 	.get_frame		= s3c2410_udc_get_frame,
 	.get_frame		= s3c2410_udc_get_frame,
@@ -1549,8 +1550,8 @@ static const struct usb_gadget_ops s3c2410_ops = {
 	.pullup			= s3c2410_udc_pullup,
 	.pullup			= s3c2410_udc_pullup,
 	.vbus_session		= s3c2410_udc_vbus_session,
 	.vbus_session		= s3c2410_udc_vbus_session,
 	.vbus_draw		= s3c2410_vbus_draw,
 	.vbus_draw		= s3c2410_vbus_draw,
-	.start			= s3c2410_udc_start,
-	.stop			= s3c2410_udc_stop,
+	.udc_start		= s3c2410_udc_start,
+	.udc_stop		= s3c2410_udc_stop,
 };
 };
 
 
 static void s3c2410_udc_command(enum s3c2410_udc_cmd_e cmd)
 static void s3c2410_udc_command(enum s3c2410_udc_cmd_e cmd)
@@ -1664,33 +1665,14 @@ static void s3c2410_udc_enable(struct s3c2410_udc *dev)
 	s3c2410_udc_command(S3C2410_UDC_P_ENABLE);
 	s3c2410_udc_command(S3C2410_UDC_P_ENABLE);
 }
 }
 
 
-static int s3c2410_udc_start(struct usb_gadget_driver *driver,
-		int (*bind)(struct usb_gadget *, struct usb_gadget_driver *))
+static int s3c2410_udc_start(struct usb_gadget *g,
+		struct usb_gadget_driver *driver)
 {
 {
-	struct s3c2410_udc *udc = the_controller;
+	struct s3c2410_udc *udc = to_s3c2410(g)
 	int		retval;
 	int		retval;
 
 
 	dprintk(DEBUG_NORMAL, "%s() '%s'\n", __func__, driver->driver.name);
 	dprintk(DEBUG_NORMAL, "%s() '%s'\n", __func__, driver->driver.name);
 
 
-	/* Sanity checks */
-	if (!udc)
-		return -ENODEV;
-
-	if (udc->driver)
-		return -EBUSY;
-
-	if (!bind || !driver->setup || driver->max_speed < USB_SPEED_FULL) {
-		dev_err(&udc->gadget.dev, "Invalid driver: bind %p setup %p speed %d\n",
-			bind, driver->setup, driver->max_speed);
-		return -EINVAL;
-	}
-#if defined(MODULE)
-	if (!driver->unbind) {
-		dev_err(&udc->gadget.dev, "Invalid driver: no unbind method\n");
-		return -EINVAL;
-	}
-#endif
-
 	/* Hook the driver */
 	/* Hook the driver */
 	udc->driver = driver;
 	udc->driver = driver;
 	udc->gadget.dev.driver = &driver->driver;
 	udc->gadget.dev.driver = &driver->driver;
@@ -1702,15 +1684,6 @@ static int s3c2410_udc_start(struct usb_gadget_driver *driver,
 		goto register_error;
 		goto register_error;
 	}
 	}
 
 
-	dprintk(DEBUG_NORMAL, "binding gadget driver '%s'\n",
-		driver->driver.name);
-
-	retval = bind(&udc->gadget, driver);
-	if (retval) {
-		device_del(&udc->gadget.dev);
-		goto register_error;
-	}
-
 	/* Enable udc */
 	/* Enable udc */
 	s3c2410_udc_enable(udc);
 	s3c2410_udc_enable(udc);
 
 
@@ -1722,24 +1695,10 @@ register_error:
 	return retval;
 	return retval;
 }
 }
 
 
-static int s3c2410_udc_stop(struct usb_gadget_driver *driver)
+static int s3c2410_udc_stop(struct usb_gadget *g,
+		struct usb_gadget_driver *driver)
 {
 {
-	struct s3c2410_udc *udc = the_controller;
-
-	if (!udc)
-		return -ENODEV;
-
-	if (!driver || driver != udc->driver || !driver->unbind)
-		return -EINVAL;
-
-	dprintk(DEBUG_NORMAL, "usb_gadget_unregister_driver() '%s'\n",
-		driver->driver.name);
-
-	/* report disconnect */
-	if (driver->disconnect)
-		driver->disconnect(&udc->gadget);
-
-	driver->unbind(&udc->gadget);
+	struct s3c2410_udc *udc = to_s3c2410(g);
 
 
 	device_del(&udc->gadget.dev);
 	device_del(&udc->gadget.dev);
 	udc->driver = NULL;
 	udc->driver = NULL;

+ 1 - 0
drivers/usb/gadget/s3c2410_udc.h

@@ -95,5 +95,6 @@ struct s3c2410_udc {
 	u8				vbus;
 	u8				vbus;
 	struct dentry			*regs_info;
 	struct dentry			*regs_info;
 };
 };
+#define to_s3c2410(g)	(container_of((g), struct s3c2410_udc, gadget))
 
 
 #endif
 #endif

+ 100 - 18
drivers/usb/gadget/serial.c

@@ -36,10 +36,8 @@
  * the runtime footprint, and giving us at least some parts of what
  * the runtime footprint, and giving us at least some parts of what
  * a "gcc --combine ... part1.c part2.c part3.c ... " build would.
  * a "gcc --combine ... part1.c part2.c part3.c ... " build would.
  */
  */
-#include "f_acm.c"
 #include "f_obex.c"
 #include "f_obex.c"
 #include "f_serial.c"
 #include "f_serial.c"
-#include "u_serial.c"
 
 
 /*-------------------------------------------------------------------------*/
 /*-------------------------------------------------------------------------*/
 USB_GADGET_COMPOSITE_OPTIONS();
 USB_GADGET_COMPOSITE_OPTIONS();
@@ -128,20 +126,25 @@ module_param(n_ports, uint, 0);
 MODULE_PARM_DESC(n_ports, "number of ports to create, default=1");
 MODULE_PARM_DESC(n_ports, "number of ports to create, default=1");
 
 
 /*-------------------------------------------------------------------------*/
 /*-------------------------------------------------------------------------*/
+static unsigned char tty_lines[MAX_U_SERIAL_PORTS];
 
 
-static int __init serial_bind_config(struct usb_configuration *c)
+static int __init serial_bind_obex_config(struct usb_configuration *c)
 {
 {
 	unsigned i;
 	unsigned i;
 	int status = 0;
 	int status = 0;
 
 
-	for (i = 0; i < n_ports && status == 0; i++) {
-		if (use_acm)
-			status = acm_bind_config(c, i);
-		else if (use_obex)
-			status = obex_bind_config(c, i);
-		else
-			status = gser_bind_config(c, i);
-	}
+	for (i = 0; i < n_ports && status == 0; i++)
+		status = obex_bind_config(c, tty_lines[i]);
+	return status;
+}
+
+static int __init serial_bind_gser_config(struct usb_configuration *c)
+{
+	unsigned i;
+	int status = 0;
+
+	for (i = 0; i < n_ports && status == 0; i++)
+		status = gser_bind_config(c, tty_lines[i]);
 	return status;
 	return status;
 }
 }
 
 
@@ -152,13 +155,70 @@ static struct usb_configuration serial_config_driver = {
 	.bmAttributes	= USB_CONFIG_ATT_SELFPOWER,
 	.bmAttributes	= USB_CONFIG_ATT_SELFPOWER,
 };
 };
 
 
+static struct usb_function_instance *fi_serial[MAX_U_SERIAL_PORTS];
+static struct usb_function *f_serial[MAX_U_SERIAL_PORTS];
+
+static int serial_register_ports(struct usb_composite_dev *cdev,
+		struct usb_configuration *c, const char *f_name)
+{
+	int i;
+	int ret;
+
+	ret = usb_add_config_only(cdev, c);
+	if (ret)
+		goto out;
+
+	for (i = 0; i < n_ports; i++) {
+		struct f_serial_opts *opts;
+
+		fi_serial[i] = usb_get_function_instance(f_name);
+		if (IS_ERR(fi_serial[i])) {
+			ret = PTR_ERR(fi_serial[i]);
+			goto fail;
+		}
+		opts = container_of(fi_serial[i], struct f_serial_opts, func_inst);
+		opts->port_num = tty_lines[i];
+
+		f_serial[i] = usb_get_function(fi_serial[i]);
+		if (IS_ERR(f_serial[i])) {
+			ret = PTR_ERR(f_serial[i]);
+			goto err_get_func;
+		}
+
+		ret = usb_add_function(c, f_serial[i]);
+		if (ret)
+			goto err_add_func;
+	}
+
+	return 0;
+
+err_add_func:
+	usb_put_function(f_serial[i]);
+err_get_func:
+	usb_put_function_instance(fi_serial[i]);
+
+fail:
+	i--;
+	while (i >= 0) {
+		usb_remove_function(c, f_serial[i]);
+		usb_put_function(f_serial[i]);
+		usb_put_function_instance(fi_serial[i]);
+		i--;
+	}
+out:
+	return ret;
+}
+
 static int __init gs_bind(struct usb_composite_dev *cdev)
 static int __init gs_bind(struct usb_composite_dev *cdev)
 {
 {
 	int			status;
 	int			status;
+	int			cur_line;
 
 
-	status = gserial_setup(cdev->gadget, n_ports);
-	if (status < 0)
-		return status;
+	for (cur_line = 0; cur_line < n_ports; cur_line++) {
+		status = gserial_alloc_line(&tty_lines[cur_line]);
+		if (status)
+			goto fail;
+	}
 
 
 	/* Allocate string descriptor numbers ... note that string
 	/* Allocate string descriptor numbers ... note that string
 	 * contents can be overridden by the composite_dev glue.
 	 * contents can be overridden by the composite_dev glue.
@@ -178,8 +238,16 @@ static int __init gs_bind(struct usb_composite_dev *cdev)
 	}
 	}
 
 
 	/* register our configuration */
 	/* register our configuration */
-	status = usb_add_config(cdev, &serial_config_driver,
-			serial_bind_config);
+	if (use_acm) {
+		status  = serial_register_ports(cdev, &serial_config_driver,
+				"acm");
+		usb_ep_autoconfig_reset(cdev->gadget);
+	} else if (use_obex)
+		status = usb_add_config(cdev, &serial_config_driver,
+				serial_bind_obex_config);
+	else
+		status = usb_add_config(cdev, &serial_config_driver,
+				serial_bind_gser_config);
 	if (status < 0)
 	if (status < 0)
 		goto fail;
 		goto fail;
 
 
@@ -189,16 +257,31 @@ static int __init gs_bind(struct usb_composite_dev *cdev)
 	return 0;
 	return 0;
 
 
 fail:
 fail:
-	gserial_cleanup();
+	cur_line--;
+	while (cur_line >= 0)
+		gserial_free_line(tty_lines[cur_line--]);
 	return status;
 	return status;
 }
 }
 
 
+static int gs_unbind(struct usb_composite_dev *cdev)
+{
+	int i;
+
+	for (i = 0; i < n_ports; i++) {
+		usb_put_function(f_serial[i]);
+		usb_put_function_instance(fi_serial[i]);
+		gserial_free_line(tty_lines[i]);
+	}
+	return 0;
+}
+
 static __refdata struct usb_composite_driver gserial_driver = {
 static __refdata struct usb_composite_driver gserial_driver = {
 	.name		= "g_serial",
 	.name		= "g_serial",
 	.dev		= &device_desc,
 	.dev		= &device_desc,
 	.strings	= dev_strings,
 	.strings	= dev_strings,
 	.max_speed	= USB_SPEED_SUPER,
 	.max_speed	= USB_SPEED_SUPER,
 	.bind		= gs_bind,
 	.bind		= gs_bind,
+	.unbind		= gs_unbind,
 };
 };
 
 
 static int __init init(void)
 static int __init init(void)
@@ -234,6 +317,5 @@ module_init(init);
 static void __exit cleanup(void)
 static void __exit cleanup(void)
 {
 {
 	usb_composite_unregister(&gserial_driver);
 	usb_composite_unregister(&gserial_driver);
-	gserial_cleanup();
 }
 }
 module_exit(cleanup);
 module_exit(cleanup);

+ 0 - 61
drivers/usb/gadget/storage_common.c

@@ -93,18 +93,6 @@
 
 
 /*-------------------------------------------------------------------------*/
 /*-------------------------------------------------------------------------*/
 
 
-/* CBI Interrupt data structure */
-struct interrupt_data {
-	u8	bType;
-	u8	bValue;
-};
-
-#define CBI_INTERRUPT_DATA_LEN		2
-
-/* CBI Accept Device-Specific Command request */
-#define USB_CBI_ADSC_REQUEST		0x00
-
-
 /* Length of a SCSI Command Data Block */
 /* Length of a SCSI Command Data Block */
 #define MAX_COMMAND_SIZE	16
 #define MAX_COMMAND_SIZE	16
 
 
@@ -385,41 +373,6 @@ static struct usb_ss_ep_comp_descriptor fsg_ss_bulk_out_comp_desc = {
 	/*.bMaxBurst =		DYNAMIC, */
 	/*.bMaxBurst =		DYNAMIC, */
 };
 };
 
 
-static __maybe_unused struct usb_ext_cap_descriptor fsg_ext_cap_desc = {
-	.bLength =		USB_DT_USB_EXT_CAP_SIZE,
-	.bDescriptorType =	USB_DT_DEVICE_CAPABILITY,
-	.bDevCapabilityType =	USB_CAP_TYPE_EXT,
-
-	.bmAttributes =		cpu_to_le32(USB_LPM_SUPPORT),
-};
-
-static __maybe_unused struct usb_ss_cap_descriptor fsg_ss_cap_desc = {
-	.bLength =		USB_DT_USB_SS_CAP_SIZE,
-	.bDescriptorType =	USB_DT_DEVICE_CAPABILITY,
-	.bDevCapabilityType =	USB_SS_CAP_TYPE,
-
-	/* .bmAttributes = LTM is not supported yet */
-
-	.wSpeedSupported =	cpu_to_le16(USB_LOW_SPEED_OPERATION
-		| USB_FULL_SPEED_OPERATION
-		| USB_HIGH_SPEED_OPERATION
-		| USB_5GBPS_OPERATION),
-	.bFunctionalitySupport = USB_LOW_SPEED_OPERATION,
-	.bU1devExitLat =	USB_DEFAULT_U1_DEV_EXIT_LAT,
-	.bU2DevExitLat =	cpu_to_le16(USB_DEFAULT_U2_DEV_EXIT_LAT),
-};
-
-static __maybe_unused struct usb_bos_descriptor fsg_bos_desc = {
-	.bLength =		USB_DT_BOS_SIZE,
-	.bDescriptorType =	USB_DT_BOS,
-
-	.wTotalLength =		cpu_to_le16(USB_DT_BOS_SIZE
-				+ USB_DT_USB_EXT_CAP_SIZE
-				+ USB_DT_USB_SS_CAP_SIZE),
-
-	.bNumDeviceCaps =	2,
-};
-
 static struct usb_descriptor_header *fsg_ss_function[] = {
 static struct usb_descriptor_header *fsg_ss_function[] = {
 	(struct usb_descriptor_header *) &fsg_intf_desc,
 	(struct usb_descriptor_header *) &fsg_intf_desc,
 	(struct usb_descriptor_header *) &fsg_ss_bulk_in_desc,
 	(struct usb_descriptor_header *) &fsg_ss_bulk_in_desc,
@@ -429,20 +382,6 @@ static struct usb_descriptor_header *fsg_ss_function[] = {
 	NULL,
 	NULL,
 };
 };
 
 
-/* Maxpacket and other transfer characteristics vary by speed. */
-static __maybe_unused struct usb_endpoint_descriptor *
-fsg_ep_desc(struct usb_gadget *g, struct usb_endpoint_descriptor *fs,
-		struct usb_endpoint_descriptor *hs,
-		struct usb_endpoint_descriptor *ss)
-{
-	if (gadget_is_superspeed(g) && g->speed == USB_SPEED_SUPER)
-		return ss;
-	else if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH)
-		return hs;
-	return fs;
-}
-
-
 /* Static strings, in UTF-8 (for simplicity we use only ASCII characters) */
 /* Static strings, in UTF-8 (for simplicity we use only ASCII characters) */
 static struct usb_string		fsg_strings[] = {
 static struct usb_string		fsg_strings[] = {
 	{FSG_STRING_INTERFACE,		fsg_string_interface},
 	{FSG_STRING_INTERFACE,		fsg_string_interface},

+ 157 - 156
drivers/usb/gadget/u_serial.c

@@ -26,6 +26,7 @@
 #include <linux/tty_flip.h>
 #include <linux/tty_flip.h>
 #include <linux/slab.h>
 #include <linux/slab.h>
 #include <linux/export.h>
 #include <linux/export.h>
+#include <linux/module.h>
 
 
 #include "u_serial.h"
 #include "u_serial.h"
 
 
@@ -35,11 +36,12 @@
  * "serial port" functionality through the USB gadget stack.  Each such
  * "serial port" functionality through the USB gadget stack.  Each such
  * port is exposed through a /dev/ttyGS* node.
  * port is exposed through a /dev/ttyGS* node.
  *
  *
- * After initialization (gserial_setup), these TTY port devices stay
- * available until they are removed (gserial_cleanup).  Each one may be
- * connected to a USB function (gserial_connect), or disconnected (with
- * gserial_disconnect) when the USB host issues a config change event.
- * Data can only flow when the port is connected to the host.
+ * After this module has been loaded, the individual TTY port can be requested
+ * (gserial_alloc_line()) and it will stay available until they are removed
+ * (gserial_free_line()). Each one may be connected to a USB function
+ * (gserial_connect), or disconnected (with gserial_disconnect) when the USB
+ * host issues a config change event. Data can only flow when the port is
+ * connected to the host.
  *
  *
  * A given TTY port can be made available in multiple configurations.
  * A given TTY port can be made available in multiple configurations.
  * For example, each one might expose a ttyGS0 node which provides a
  * For example, each one might expose a ttyGS0 node which provides a
@@ -119,13 +121,10 @@ struct gs_port {
 	struct usb_cdc_line_coding port_line_coding;	/* 8-N-1 etc */
 	struct usb_cdc_line_coding port_line_coding;	/* 8-N-1 etc */
 };
 };
 
 
-/* increase N_PORTS if you need more */
-#define N_PORTS		4
 static struct portmaster {
 static struct portmaster {
 	struct mutex	lock;			/* protect open/close */
 	struct mutex	lock;			/* protect open/close */
 	struct gs_port	*port;
 	struct gs_port	*port;
-} ports[N_PORTS];
-static unsigned	n_ports;
+} ports[MAX_U_SERIAL_PORTS];
 
 
 #define GS_CLOSE_TIMEOUT		15		/* seconds */
 #define GS_CLOSE_TIMEOUT		15		/* seconds */
 
 
@@ -309,6 +308,7 @@ gs_alloc_req(struct usb_ep *ep, unsigned len, gfp_t kmalloc_flags)
 
 
 	return req;
 	return req;
 }
 }
+EXPORT_SYMBOL_GPL(gs_alloc_req);
 
 
 /*
 /*
  * gs_free_req
  * gs_free_req
@@ -320,6 +320,7 @@ void gs_free_req(struct usb_ep *ep, struct usb_request *req)
 	kfree(req->buf);
 	kfree(req->buf);
 	usb_ep_free_request(ep, req);
 	usb_ep_free_request(ep, req);
 }
 }
+EXPORT_SYMBOL_GPL(gs_free_req);
 
 
 /*
 /*
  * gs_send_packet
  * gs_send_packet
@@ -1030,10 +1031,19 @@ static int
 gs_port_alloc(unsigned port_num, struct usb_cdc_line_coding *coding)
 gs_port_alloc(unsigned port_num, struct usb_cdc_line_coding *coding)
 {
 {
 	struct gs_port	*port;
 	struct gs_port	*port;
+	int		ret = 0;
+
+	mutex_lock(&ports[port_num].lock);
+	if (ports[port_num].port) {
+		ret = -EBUSY;
+		goto out;
+	}
 
 
 	port = kzalloc(sizeof(struct gs_port), GFP_KERNEL);
 	port = kzalloc(sizeof(struct gs_port), GFP_KERNEL);
-	if (port == NULL)
-		return -ENOMEM;
+	if (port == NULL) {
+		ret = -ENOMEM;
+		goto out;
+	}
 
 
 	tty_port_init(&port->port);
 	tty_port_init(&port->port);
 	spin_lock_init(&port->port_lock);
 	spin_lock_init(&port->port_lock);
@@ -1049,109 +1059,9 @@ gs_port_alloc(unsigned port_num, struct usb_cdc_line_coding *coding)
 	port->port_line_coding = *coding;
 	port->port_line_coding = *coding;
 
 
 	ports[port_num].port = port;
 	ports[port_num].port = port;
-
-	return 0;
-}
-
-/**
- * gserial_setup - initialize TTY driver for one or more ports
- * @g: gadget to associate with these ports
- * @count: how many ports to support
- * Context: may sleep
- *
- * The TTY stack needs to know in advance how many devices it should
- * plan to manage.  Use this call to set up the ports you will be
- * exporting through USB.  Later, connect them to functions based
- * on what configuration is activated by the USB host; and disconnect
- * them as appropriate.
- *
- * An example would be a two-configuration device in which both
- * configurations expose port 0, but through different functions.
- * One configuration could even expose port 1 while the other
- * one doesn't.
- *
- * Returns negative errno or zero.
- */
-int gserial_setup(struct usb_gadget *g, unsigned count)
-{
-	unsigned			i;
-	struct usb_cdc_line_coding	coding;
-	int				status;
-
-	if (count == 0 || count > N_PORTS)
-		return -EINVAL;
-
-	gs_tty_driver = alloc_tty_driver(count);
-	if (!gs_tty_driver)
-		return -ENOMEM;
-
-	gs_tty_driver->driver_name = "g_serial";
-	gs_tty_driver->name = PREFIX;
-	/* uses dynamically assigned dev_t values */
-
-	gs_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
-	gs_tty_driver->subtype = SERIAL_TYPE_NORMAL;
-	gs_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
-	gs_tty_driver->init_termios = tty_std_termios;
-
-	/* 9600-8-N-1 ... matches defaults expected by "usbser.sys" on
-	 * MS-Windows.  Otherwise, most of these flags shouldn't affect
-	 * anything unless we were to actually hook up to a serial line.
-	 */
-	gs_tty_driver->init_termios.c_cflag =
-			B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-	gs_tty_driver->init_termios.c_ispeed = 9600;
-	gs_tty_driver->init_termios.c_ospeed = 9600;
-
-	coding.dwDTERate = cpu_to_le32(9600);
-	coding.bCharFormat = 8;
-	coding.bParityType = USB_CDC_NO_PARITY;
-	coding.bDataBits = USB_CDC_1_STOP_BITS;
-
-	tty_set_operations(gs_tty_driver, &gs_tty_ops);
-
-	/* make devices be openable */
-	for (i = 0; i < count; i++) {
-		mutex_init(&ports[i].lock);
-		status = gs_port_alloc(i, &coding);
-		if (status) {
-			count = i;
-			goto fail;
-		}
-	}
-	n_ports = count;
-
-	/* export the driver ... */
-	status = tty_register_driver(gs_tty_driver);
-	if (status) {
-		pr_err("%s: cannot register, err %d\n",
-				__func__, status);
-		goto fail;
-	}
-
-	/* ... and sysfs class devices, so mdev/udev make /dev/ttyGS* */
-	for (i = 0; i < count; i++) {
-		struct device	*tty_dev;
-
-		tty_dev = tty_port_register_device(&ports[i].port->port,
-				gs_tty_driver, i, &g->dev);
-		if (IS_ERR(tty_dev))
-			pr_warning("%s: no classdev for port %d, err %ld\n",
-				__func__, i, PTR_ERR(tty_dev));
-	}
-
-	pr_debug("%s: registered %d ttyGS* device%s\n", __func__,
-			count, (count == 1) ? "" : "s");
-
-	return status;
-fail:
-	while (count--) {
-		tty_port_destroy(&ports[count].port->port);
-		kfree(ports[count].port);
-	}
-	put_tty_driver(gs_tty_driver);
-	gs_tty_driver = NULL;
-	return status;
+out:
+	mutex_unlock(&ports[port_num].lock);
+	return ret;
 }
 }
 
 
 static int gs_closed(struct gs_port *port)
 static int gs_closed(struct gs_port *port)
@@ -1164,55 +1074,77 @@ static int gs_closed(struct gs_port *port)
 	return cond;
 	return cond;
 }
 }
 
 
-/**
- * gserial_cleanup - remove TTY-over-USB driver and devices
- * Context: may sleep
- *
- * This is called to free all resources allocated by @gserial_setup().
- * Accordingly, it may need to wait until some open /dev/ files have
- * closed.
- *
- * The caller must have issued @gserial_disconnect() for any ports
- * that had previously been connected, so that there is never any
- * I/O pending when it's called.
- */
-void gserial_cleanup(void)
+static void gserial_free_port(struct gs_port *port)
+{
+	tasklet_kill(&port->push);
+	/* wait for old opens to finish */
+	wait_event(port->port.close_wait, gs_closed(port));
+	WARN_ON(port->port_usb != NULL);
+	tty_port_destroy(&port->port);
+	kfree(port);
+}
+
+void gserial_free_line(unsigned char port_num)
 {
 {
-	unsigned	i;
 	struct gs_port	*port;
 	struct gs_port	*port;
 
 
-	if (!gs_tty_driver)
+	mutex_lock(&ports[port_num].lock);
+	if (WARN_ON(!ports[port_num].port)) {
+		mutex_unlock(&ports[port_num].lock);
 		return;
 		return;
+	}
+	port = ports[port_num].port;
+	ports[port_num].port = NULL;
+	mutex_unlock(&ports[port_num].lock);
 
 
-	/* start sysfs and /dev/ttyGS* node removal */
-	for (i = 0; i < n_ports; i++)
-		tty_unregister_device(gs_tty_driver, i);
-
-	for (i = 0; i < n_ports; i++) {
-		/* prevent new opens */
-		mutex_lock(&ports[i].lock);
-		port = ports[i].port;
-		ports[i].port = NULL;
-		mutex_unlock(&ports[i].lock);
-
-		tasklet_kill(&port->push);
+	gserial_free_port(port);
+	tty_unregister_device(gs_tty_driver, port_num);
+}
+EXPORT_SYMBOL_GPL(gserial_free_line);
 
 
-		/* wait for old opens to finish */
-		wait_event(port->port.close_wait, gs_closed(port));
+int gserial_alloc_line(unsigned char *line_num)
+{
+	struct usb_cdc_line_coding	coding;
+	struct device			*tty_dev;
+	int				ret;
+	int				port_num;
 
 
-		WARN_ON(port->port_usb != NULL);
+	coding.dwDTERate = cpu_to_le32(9600);
+	coding.bCharFormat = 8;
+	coding.bParityType = USB_CDC_NO_PARITY;
+	coding.bDataBits = USB_CDC_1_STOP_BITS;
 
 
-		tty_port_destroy(&port->port);
-		kfree(port);
+	for (port_num = 0; port_num < MAX_U_SERIAL_PORTS; port_num++) {
+		ret = gs_port_alloc(port_num, &coding);
+		if (ret == -EBUSY)
+			continue;
+		if (ret)
+			return ret;
+		break;
 	}
 	}
-	n_ports = 0;
+	if (ret)
+		return ret;
 
 
-	tty_unregister_driver(gs_tty_driver);
-	put_tty_driver(gs_tty_driver);
-	gs_tty_driver = NULL;
+	/* ... and sysfs class devices, so mdev/udev make /dev/ttyGS* */
+
+	tty_dev = tty_port_register_device(&ports[port_num].port->port,
+			gs_tty_driver, port_num, NULL);
+	if (IS_ERR(tty_dev)) {
+		struct gs_port	*port;
+		pr_err("%s: failed to register tty for port %d, err %ld\n",
+				__func__, port_num, PTR_ERR(tty_dev));
 
 
-	pr_debug("%s: cleaned up ttyGS* support\n", __func__);
+		ret = PTR_ERR(tty_dev);
+		port = ports[port_num].port;
+		ports[port_num].port = NULL;
+		gserial_free_port(port);
+		goto err;
+	}
+	*line_num = port_num;
+err:
+	return ret;
 }
 }
+EXPORT_SYMBOL_GPL(gserial_alloc_line);
 
 
 /**
 /**
  * gserial_connect - notify TTY I/O glue that USB link is active
  * gserial_connect - notify TTY I/O glue that USB link is active
@@ -1229,8 +1161,8 @@ void gserial_cleanup(void)
  *
  *
  * Caller needs to have set up the endpoints and USB function in @dev
  * Caller needs to have set up the endpoints and USB function in @dev
  * before calling this, as well as the appropriate (speed-specific)
  * before calling this, as well as the appropriate (speed-specific)
- * endpoint descriptors, and also have set up the TTY driver by calling
- * @gserial_setup().
+ * endpoint descriptors, and also have allocate @port_num by calling
+ * @gserial_alloc_line().
  *
  *
  * Returns negative errno or zero.
  * Returns negative errno or zero.
  * On success, ep->driver_data will be overwritten.
  * On success, ep->driver_data will be overwritten.
@@ -1241,11 +1173,18 @@ int gserial_connect(struct gserial *gser, u8 port_num)
 	unsigned long	flags;
 	unsigned long	flags;
 	int		status;
 	int		status;
 
 
-	if (!gs_tty_driver || port_num >= n_ports)
+	if (port_num >= MAX_U_SERIAL_PORTS)
 		return -ENXIO;
 		return -ENXIO;
 
 
-	/* we "know" gserial_cleanup() hasn't been called */
 	port = ports[port_num].port;
 	port = ports[port_num].port;
+	if (!port) {
+		pr_err("serial line %d not allocated.\n", port_num);
+		return -EINVAL;
+	}
+	if (port->port_usb) {
+		pr_err("serial line %d is in use.\n", port_num);
+		return -EBUSY;
+	}
 
 
 	/* activate the endpoints */
 	/* activate the endpoints */
 	status = usb_ep_enable(gser->in);
 	status = usb_ep_enable(gser->in);
@@ -1292,7 +1231,7 @@ fail_out:
 	gser->in->driver_data = NULL;
 	gser->in->driver_data = NULL;
 	return status;
 	return status;
 }
 }
-
+EXPORT_SYMBOL_GPL(gserial_connect);
 /**
 /**
  * gserial_disconnect - notify TTY I/O glue that USB link is inactive
  * gserial_disconnect - notify TTY I/O glue that USB link is inactive
  * @gser: the function, on which gserial_connect() was called
  * @gser: the function, on which gserial_connect() was called
@@ -1347,3 +1286,65 @@ void gserial_disconnect(struct gserial *gser)
 
 
 	spin_unlock_irqrestore(&port->port_lock, flags);
 	spin_unlock_irqrestore(&port->port_lock, flags);
 }
 }
+EXPORT_SYMBOL_GPL(gserial_disconnect);
+
+static int userial_init(void)
+{
+	unsigned			i;
+	int				status;
+
+	gs_tty_driver = alloc_tty_driver(MAX_U_SERIAL_PORTS);
+	if (!gs_tty_driver)
+		return -ENOMEM;
+
+	gs_tty_driver->driver_name = "g_serial";
+	gs_tty_driver->name = PREFIX;
+	/* uses dynamically assigned dev_t values */
+
+	gs_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
+	gs_tty_driver->subtype = SERIAL_TYPE_NORMAL;
+	gs_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
+	gs_tty_driver->init_termios = tty_std_termios;
+
+	/* 9600-8-N-1 ... matches defaults expected by "usbser.sys" on
+	 * MS-Windows.  Otherwise, most of these flags shouldn't affect
+	 * anything unless we were to actually hook up to a serial line.
+	 */
+	gs_tty_driver->init_termios.c_cflag =
+			B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+	gs_tty_driver->init_termios.c_ispeed = 9600;
+	gs_tty_driver->init_termios.c_ospeed = 9600;
+
+	tty_set_operations(gs_tty_driver, &gs_tty_ops);
+	for (i = 0; i < MAX_U_SERIAL_PORTS; i++)
+		mutex_init(&ports[i].lock);
+
+	/* export the driver ... */
+	status = tty_register_driver(gs_tty_driver);
+	if (status) {
+		pr_err("%s: cannot register, err %d\n",
+				__func__, status);
+		goto fail;
+	}
+
+	pr_debug("%s: registered %d ttyGS* device%s\n", __func__,
+			MAX_U_SERIAL_PORTS,
+			(MAX_U_SERIAL_PORTS == 1) ? "" : "s");
+
+	return status;
+fail:
+	put_tty_driver(gs_tty_driver);
+	gs_tty_driver = NULL;
+	return status;
+}
+module_init(userial_init);
+
+static void userial_cleanup(void)
+{
+	tty_unregister_driver(gs_tty_driver);
+	put_tty_driver(gs_tty_driver);
+	gs_tty_driver = NULL;
+}
+module_exit(userial_cleanup);
+
+MODULE_LICENSE("GPL");

+ 10 - 3
drivers/usb/gadget/u_serial.h

@@ -15,6 +15,13 @@
 #include <linux/usb/composite.h>
 #include <linux/usb/composite.h>
 #include <linux/usb/cdc.h>
 #include <linux/usb/cdc.h>
 
 
+#define MAX_U_SERIAL_PORTS	4
+
+struct f_serial_opts {
+	struct usb_function_instance func_inst;
+	u8 port_num;
+};
+
 /*
 /*
  * One non-multiplexed "serial" I/O port ... there can be several of these
  * One non-multiplexed "serial" I/O port ... there can be several of these
  * on any given USB peripheral device, if it provides enough endpoints.
  * on any given USB peripheral device, if it provides enough endpoints.
@@ -49,9 +56,9 @@ struct gserial {
 struct usb_request *gs_alloc_req(struct usb_ep *ep, unsigned len, gfp_t flags);
 struct usb_request *gs_alloc_req(struct usb_ep *ep, unsigned len, gfp_t flags);
 void gs_free_req(struct usb_ep *, struct usb_request *req);
 void gs_free_req(struct usb_ep *, struct usb_request *req);
 
 
-/* port setup/teardown is handled by gadget driver */
-int gserial_setup(struct usb_gadget *g, unsigned n_ports);
-void gserial_cleanup(void);
+/* management of individual TTY ports */
+int gserial_alloc_line(unsigned char *port_line);
+void gserial_free_line(unsigned char port_line);
 
 
 /* connect/disconnect is handled by individual functions */
 /* connect/disconnect is handled by individual functions */
 int gserial_connect(struct gserial *, u8 port_num);
 int gserial_connect(struct gserial *, u8 port_num);

+ 63 - 94
drivers/usb/gadget/udc-core.c

@@ -101,28 +101,6 @@ EXPORT_SYMBOL_GPL(usb_gadget_unmap_request);
 
 
 /* ------------------------------------------------------------------------- */
 /* ------------------------------------------------------------------------- */
 
 
-/**
- * usb_gadget_start - tells usb device controller to start up
- * @gadget: The gadget we want to get started
- * @driver: The driver we want to bind to @gadget
- * @bind: The bind function for @driver
- *
- * This call is issued by the UDC Class driver when it's about
- * to register a gadget driver to the device controller, before
- * calling gadget driver's bind() method.
- *
- * It allows the controller to be powered off until strictly
- * necessary to have it powered on.
- *
- * Returns zero on success, else negative errno.
- */
-static inline int usb_gadget_start(struct usb_gadget *gadget,
-		struct usb_gadget_driver *driver,
-		int (*bind)(struct usb_gadget *, struct usb_gadget_driver *))
-{
-	return gadget->ops->start(driver, bind);
-}
-
 /**
 /**
  * usb_gadget_udc_start - tells usb device controller to start up
  * usb_gadget_udc_start - tells usb device controller to start up
  * @gadget: The gadget we want to get started
  * @gadget: The gadget we want to get started
@@ -143,24 +121,6 @@ static inline int usb_gadget_udc_start(struct usb_gadget *gadget,
 	return gadget->ops->udc_start(gadget, driver);
 	return gadget->ops->udc_start(gadget, driver);
 }
 }
 
 
-/**
- * usb_gadget_stop - tells usb device controller we don't need it anymore
- * @gadget: The device we want to stop activity
- * @driver: The driver to unbind from @gadget
- *
- * This call is issued by the UDC Class driver after calling
- * gadget driver's unbind() method.
- *
- * The details are implementation specific, but it can go as
- * far as powering off UDC completely and disable its data
- * line pullups.
- */
-static inline void usb_gadget_stop(struct usb_gadget *gadget,
-		struct usb_gadget_driver *driver)
-{
-	gadget->ops->stop(driver);
-}
-
 /**
 /**
  * usb_gadget_udc_stop - tells usb device controller we don't need it anymore
  * usb_gadget_udc_stop - tells usb device controller we don't need it anymore
  * @gadget: The device we want to stop activity
  * @gadget: The device we want to stop activity
@@ -246,14 +206,6 @@ err1:
 }
 }
 EXPORT_SYMBOL_GPL(usb_add_gadget_udc);
 EXPORT_SYMBOL_GPL(usb_add_gadget_udc);
 
 
-static int udc_is_newstyle(struct usb_udc *udc)
-{
-	if (udc->gadget->ops->udc_start && udc->gadget->ops->udc_stop)
-		return 1;
-	return 0;
-}
-
-
 static void usb_gadget_remove_driver(struct usb_udc *udc)
 static void usb_gadget_remove_driver(struct usb_udc *udc)
 {
 {
 	dev_dbg(&udc->dev, "unregistering UDC driver [%s]\n",
 	dev_dbg(&udc->dev, "unregistering UDC driver [%s]\n",
@@ -261,14 +213,10 @@ static void usb_gadget_remove_driver(struct usb_udc *udc)
 
 
 	kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE);
 	kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE);
 
 
-	if (udc_is_newstyle(udc)) {
-		usb_gadget_disconnect(udc->gadget);
-		udc->driver->disconnect(udc->gadget);
-		udc->driver->unbind(udc->gadget);
-		usb_gadget_udc_stop(udc->gadget, udc->driver);
-	} else {
-		usb_gadget_stop(udc->gadget, udc->driver);
-	}
+	usb_gadget_disconnect(udc->gadget);
+	udc->driver->disconnect(udc->gadget);
+	udc->driver->unbind(udc->gadget);
+	usb_gadget_udc_stop(udc->gadget, udc->driver);
 
 
 	udc->driver = NULL;
 	udc->driver = NULL;
 	udc->dev.driver = NULL;
 	udc->dev.driver = NULL;
@@ -311,6 +259,62 @@ EXPORT_SYMBOL_GPL(usb_del_gadget_udc);
 
 
 /* ------------------------------------------------------------------------- */
 /* ------------------------------------------------------------------------- */
 
 
+static int udc_bind_to_driver(struct usb_udc *udc, struct usb_gadget_driver *driver)
+{
+	int ret;
+
+	dev_dbg(&udc->dev, "registering UDC driver [%s]\n",
+			driver->function);
+
+	udc->driver = driver;
+	udc->dev.driver = &driver->driver;
+
+	ret = driver->bind(udc->gadget, driver);
+	if (ret)
+		goto err1;
+	ret = usb_gadget_udc_start(udc->gadget, driver);
+	if (ret) {
+		driver->unbind(udc->gadget);
+		goto err1;
+	}
+	usb_gadget_connect(udc->gadget);
+
+	kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE);
+	return 0;
+err1:
+	dev_err(&udc->dev, "failed to start %s: %d\n",
+			udc->driver->function, ret);
+	udc->driver = NULL;
+	udc->dev.driver = NULL;
+	return ret;
+}
+
+int udc_attach_driver(const char *name, struct usb_gadget_driver *driver)
+{
+	struct usb_udc *udc = NULL;
+	int ret = -ENODEV;
+
+	mutex_lock(&udc_lock);
+	list_for_each_entry(udc, &udc_list, list) {
+		ret = strcmp(name, dev_name(&udc->dev));
+		if (!ret)
+			break;
+	}
+	if (ret) {
+		ret = -ENODEV;
+		goto out;
+	}
+	if (udc->driver) {
+		ret = -EBUSY;
+		goto out;
+	}
+	ret = udc_bind_to_driver(udc, driver);
+out:
+	mutex_unlock(&udc_lock);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(udc_attach_driver);
+
 int usb_gadget_probe_driver(struct usb_gadget_driver *driver)
 int usb_gadget_probe_driver(struct usb_gadget_driver *driver)
 {
 {
 	struct usb_udc		*udc = NULL;
 	struct usb_udc		*udc = NULL;
@@ -329,41 +333,8 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver)
 	pr_debug("couldn't find an available UDC\n");
 	pr_debug("couldn't find an available UDC\n");
 	mutex_unlock(&udc_lock);
 	mutex_unlock(&udc_lock);
 	return -ENODEV;
 	return -ENODEV;
-
 found:
 found:
-	dev_dbg(&udc->dev, "registering UDC driver [%s]\n",
-			driver->function);
-
-	udc->driver = driver;
-	udc->dev.driver = &driver->driver;
-
-	if (udc_is_newstyle(udc)) {
-		ret = driver->bind(udc->gadget, driver);
-		if (ret)
-			goto err1;
-		ret = usb_gadget_udc_start(udc->gadget, driver);
-		if (ret) {
-			driver->unbind(udc->gadget);
-			goto err1;
-		}
-		usb_gadget_connect(udc->gadget);
-	} else {
-
-		ret = usb_gadget_start(udc->gadget, driver, driver->bind);
-		if (ret)
-			goto err1;
-
-	}
-
-	kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE);
-	mutex_unlock(&udc_lock);
-	return 0;
-
-err1:
-	dev_err(&udc->dev, "failed to start %s: %d\n",
-			udc->driver->function, ret);
-	udc->driver = NULL;
-	udc->dev.driver = NULL;
+	ret = udc_bind_to_driver(udc, driver);
 	mutex_unlock(&udc_lock);
 	mutex_unlock(&udc_lock);
 	return ret;
 	return ret;
 }
 }
@@ -410,13 +381,11 @@ static ssize_t usb_udc_softconn_store(struct device *dev,
 	struct usb_udc		*udc = container_of(dev, struct usb_udc, dev);
 	struct usb_udc		*udc = container_of(dev, struct usb_udc, dev);
 
 
 	if (sysfs_streq(buf, "connect")) {
 	if (sysfs_streq(buf, "connect")) {
-		if (udc_is_newstyle(udc))
-			usb_gadget_udc_start(udc->gadget, udc->driver);
+		usb_gadget_udc_start(udc->gadget, udc->driver);
 		usb_gadget_connect(udc->gadget);
 		usb_gadget_connect(udc->gadget);
 	} else if (sysfs_streq(buf, "disconnect")) {
 	} else if (sysfs_streq(buf, "disconnect")) {
 		usb_gadget_disconnect(udc->gadget);
 		usb_gadget_disconnect(udc->gadget);
-		if (udc_is_newstyle(udc))
-			usb_gadget_udc_stop(udc->gadget, udc->driver);
+		usb_gadget_udc_stop(udc->gadget, udc->driver);
 	} else {
 	} else {
 		dev_err(dev, "unsupported command '%s'\n", buf);
 		dev_err(dev, "unsupported command '%s'\n", buf);
 		return -EINVAL;
 		return -EINVAL;

+ 1 - 1
drivers/usb/gadget/webcam.c

@@ -336,7 +336,7 @@ static struct usb_configuration webcam_config_driver = {
 	.bConfigurationValue	= 1,
 	.bConfigurationValue	= 1,
 	.iConfiguration		= 0, /* dynamic */
 	.iConfiguration		= 0, /* dynamic */
 	.bmAttributes		= USB_CONFIG_ATT_SELFPOWER,
 	.bmAttributes		= USB_CONFIG_ATT_SELFPOWER,
-	.bMaxPower		= CONFIG_USB_GADGET_VBUS_DRAW / 2,
+	.MaxPower		= CONFIG_USB_GADGET_VBUS_DRAW,
 };
 };
 
 
 static int /* __init_or_exit */
 static int /* __init_or_exit */

+ 157 - 76
drivers/usb/gadget/zero.c

@@ -10,7 +10,6 @@
  * (at your option) any later version.
  * (at your option) any later version.
  */
  */
 
 
-
 /*
 /*
  * Gadget Zero only needs two bulk endpoints, and is an example of how you
  * Gadget Zero only needs two bulk endpoints, and is an example of how you
  * can write a hardware-agnostic gadget driver running inside a USB device.
  * can write a hardware-agnostic gadget driver running inside a USB device.
@@ -43,23 +42,11 @@
 #include <linux/kernel.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/slab.h>
 #include <linux/device.h>
 #include <linux/device.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/usb/composite.h>
 
 
 #include "g_zero.h"
 #include "g_zero.h"
-#include "gadget_chips.h"
-
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * Kbuild is not very cooperative with respect to linking separately
- * compiled library objects into one module.  So for now we won't use
- * separate compilation ... ensuring init/exit sections work to shrink
- * the runtime footprint, and giving us at least some parts of what
- * a "gcc --combine ... part1.c part2.c part3.c ... " build would.
- */
-#include "f_sourcesink.c"
-#include "f_loopback.c"
-
 /*-------------------------------------------------------------------------*/
 /*-------------------------------------------------------------------------*/
 USB_GADGET_COMPOSITE_OPTIONS();
 USB_GADGET_COMPOSITE_OPTIONS();
 
 
@@ -67,9 +54,6 @@ USB_GADGET_COMPOSITE_OPTIONS();
 
 
 static const char longname[] = "Gadget Zero";
 static const char longname[] = "Gadget Zero";
 
 
-unsigned buflen = 4096;		/* only used for bulk endpoints */
-module_param(buflen, uint, 0);
-
 /*
 /*
  * Normally the "loopback" configuration is second (index 1) so
  * Normally the "loopback" configuration is second (index 1) so
  * it's not the default.  Here's where to change that order, to
  * it's not the default.  Here's where to change that order, to
@@ -79,6 +63,13 @@ module_param(buflen, uint, 0);
 static bool loopdefault = 0;
 static bool loopdefault = 0;
 module_param(loopdefault, bool, S_IRUGO|S_IWUSR);
 module_param(loopdefault, bool, S_IRUGO|S_IWUSR);
 
 
+static struct usb_zero_options gzero_options = {
+	.isoc_interval = 4,
+	.isoc_maxpacket = 1024,
+	.bulk_buflen = 4096,
+	.qlen = 32,
+};
+
 /*-------------------------------------------------------------------------*/
 /*-------------------------------------------------------------------------*/
 
 
 /* Thanks to NetChip Technologies for donating this product ID.
 /* Thanks to NetChip Technologies for donating this product ID.
@@ -129,20 +120,27 @@ static struct usb_otg_descriptor otg_descriptor = {
 	.bmAttributes =		USB_OTG_SRP | USB_OTG_HNP,
 	.bmAttributes =		USB_OTG_SRP | USB_OTG_HNP,
 };
 };
 
 
-const struct usb_descriptor_header *otg_desc[] = {
+static const struct usb_descriptor_header *otg_desc[] = {
 	(struct usb_descriptor_header *) &otg_descriptor,
 	(struct usb_descriptor_header *) &otg_descriptor,
 	NULL,
 	NULL,
 };
 };
+#else
+#define otg_desc	NULL
 #endif
 #endif
 
 
 /* string IDs are assigned dynamically */
 /* string IDs are assigned dynamically */
 /* default serial number takes at least two packets */
 /* default serial number takes at least two packets */
 static char serial[] = "0123456789.0123456789.0123456789";
 static char serial[] = "0123456789.0123456789.0123456789";
 
 
+#define USB_GZERO_SS_DESC	(USB_GADGET_FIRST_AVAIL_IDX + 0)
+#define USB_GZERO_LB_DESC	(USB_GADGET_FIRST_AVAIL_IDX + 1)
+
 static struct usb_string strings_dev[] = {
 static struct usb_string strings_dev[] = {
 	[USB_GADGET_MANUFACTURER_IDX].s = "",
 	[USB_GADGET_MANUFACTURER_IDX].s = "",
 	[USB_GADGET_PRODUCT_IDX].s = longname,
 	[USB_GADGET_PRODUCT_IDX].s = longname,
 	[USB_GADGET_SERIAL_IDX].s = serial,
 	[USB_GADGET_SERIAL_IDX].s = serial,
+	[USB_GZERO_SS_DESC].s	= "source and sink data",
+	[USB_GZERO_LB_DESC].s	= "loop input to output",
 	{  }			/* end of list */
 	{  }			/* end of list */
 };
 };
 
 
@@ -158,58 +156,6 @@ static struct usb_gadget_strings *dev_strings[] = {
 
 
 /*-------------------------------------------------------------------------*/
 /*-------------------------------------------------------------------------*/
 
 
-struct usb_request *alloc_ep_req(struct usb_ep *ep, int len)
-{
-	struct usb_request	*req;
-
-	req = usb_ep_alloc_request(ep, GFP_ATOMIC);
-	if (req) {
-		if (len)
-			req->length = len;
-		else
-			req->length = buflen;
-		req->buf = kmalloc(req->length, GFP_ATOMIC);
-		if (!req->buf) {
-			usb_ep_free_request(ep, req);
-			req = NULL;
-		}
-	}
-	return req;
-}
-
-void free_ep_req(struct usb_ep *ep, struct usb_request *req)
-{
-	kfree(req->buf);
-	usb_ep_free_request(ep, req);
-}
-
-static void disable_ep(struct usb_composite_dev *cdev, struct usb_ep *ep)
-{
-	int			value;
-
-	if (ep->driver_data) {
-		value = usb_ep_disable(ep);
-		if (value < 0)
-			DBG(cdev, "disable %s --> %d\n",
-					ep->name, value);
-		ep->driver_data = NULL;
-	}
-}
-
-void disable_endpoints(struct usb_composite_dev *cdev,
-		struct usb_ep *in, struct usb_ep *out,
-		struct usb_ep *iso_in, struct usb_ep *iso_out)
-{
-	disable_ep(cdev, in);
-	disable_ep(cdev, out);
-	if (iso_in)
-		disable_ep(cdev, iso_in);
-	if (iso_out)
-		disable_ep(cdev, iso_out);
-}
-
-/*-------------------------------------------------------------------------*/
-
 static struct timer_list	autoresume_timer;
 static struct timer_list	autoresume_timer;
 
 
 static void zero_autoresume(unsigned long _c)
 static void zero_autoresume(unsigned long _c)
@@ -251,8 +197,65 @@ static void zero_resume(struct usb_composite_dev *cdev)
 
 
 /*-------------------------------------------------------------------------*/
 /*-------------------------------------------------------------------------*/
 
 
+static struct usb_configuration loopback_driver = {
+	.label          = "loopback",
+	.bConfigurationValue = 2,
+	.bmAttributes   = USB_CONFIG_ATT_SELFPOWER,
+	/* .iConfiguration = DYNAMIC */
+};
+
+static struct usb_function *func_ss;
+static struct usb_function_instance *func_inst_ss;
+
+static int ss_config_setup(struct usb_configuration *c,
+		const struct usb_ctrlrequest *ctrl)
+{
+	switch (ctrl->bRequest) {
+	case 0x5b:
+	case 0x5c:
+		return func_ss->setup(func_ss, ctrl);
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
+static struct usb_configuration sourcesink_driver = {
+	.label                  = "source/sink",
+	.setup                  = ss_config_setup,
+	.bConfigurationValue    = 3,
+	.bmAttributes           = USB_CONFIG_ATT_SELFPOWER,
+	/* .iConfiguration      = DYNAMIC */
+};
+
+module_param_named(buflen, gzero_options.bulk_buflen, uint, 0);
+module_param_named(pattern, gzero_options.pattern, uint, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(pattern, "0 = all zeroes, 1 = mod63, 2 = none");
+
+module_param_named(isoc_interval, gzero_options.isoc_interval, uint,
+		S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(isoc_interval, "1 - 16");
+
+module_param_named(isoc_maxpacket, gzero_options.isoc_maxpacket, uint,
+		S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(isoc_maxpacket, "0 - 1023 (fs), 0 - 1024 (hs/ss)");
+
+module_param_named(isoc_mult, gzero_options.isoc_mult, uint, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(isoc_mult, "0 - 2 (hs/ss only)");
+
+module_param_named(isoc_maxburst, gzero_options.isoc_maxburst, uint,
+		S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(isoc_maxburst, "0 - 15 (ss only)");
+
+static struct usb_function *func_lb;
+static struct usb_function_instance *func_inst_lb;
+
+module_param_named(qlen, gzero_options.qlen, uint, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(qlen, "depth of loopback queue");
+
 static int __init zero_bind(struct usb_composite_dev *cdev)
 static int __init zero_bind(struct usb_composite_dev *cdev)
 {
 {
+	struct f_ss_opts	*ss_opts;
+	struct f_lb_opts	*lb_opts;
 	int			status;
 	int			status;
 
 
 	/* Allocate string descriptor numbers ... note that string
 	/* Allocate string descriptor numbers ... note that string
@@ -268,27 +271,105 @@ static int __init zero_bind(struct usb_composite_dev *cdev)
 
 
 	setup_timer(&autoresume_timer, zero_autoresume, (unsigned long) cdev);
 	setup_timer(&autoresume_timer, zero_autoresume, (unsigned long) cdev);
 
 
+	func_inst_ss = usb_get_function_instance("SourceSink");
+	if (IS_ERR(func_inst_ss))
+		return PTR_ERR(func_inst_ss);
+
+	ss_opts =  container_of(func_inst_ss, struct f_ss_opts, func_inst);
+	ss_opts->pattern = gzero_options.pattern;
+	ss_opts->isoc_interval = gzero_options.isoc_interval;
+	ss_opts->isoc_maxpacket = gzero_options.isoc_maxpacket;
+	ss_opts->isoc_mult = gzero_options.isoc_mult;
+	ss_opts->isoc_maxburst = gzero_options.isoc_maxpacket;
+	ss_opts->bulk_buflen = gzero_options.bulk_buflen;
+
+	func_ss = usb_get_function(func_inst_ss);
+	if (IS_ERR(func_ss))
+		goto err_put_func_inst_ss;
+
+	func_inst_lb = usb_get_function_instance("Loopback");
+	if (IS_ERR(func_inst_lb))
+		goto err_put_func_ss;
+
+	lb_opts = container_of(func_inst_lb, struct f_lb_opts, func_inst);
+	lb_opts->bulk_buflen = gzero_options.bulk_buflen;
+	lb_opts->qlen = gzero_options.qlen;
+
+	func_lb = usb_get_function(func_inst_lb);
+	if (IS_ERR(func_lb)) {
+		status = PTR_ERR(func_lb);
+		goto err_put_func_inst_lb;
+	}
+
+	sourcesink_driver.iConfiguration = strings_dev[USB_GZERO_SS_DESC].id;
+	loopback_driver.iConfiguration = strings_dev[USB_GZERO_LB_DESC].id;
+
+	/* support autoresume for remote wakeup testing */
+	sourcesink_driver.bmAttributes &= ~USB_CONFIG_ATT_WAKEUP;
+	loopback_driver.bmAttributes &= ~USB_CONFIG_ATT_WAKEUP;
+	sourcesink_driver.descriptors = NULL;
+	loopback_driver.descriptors = NULL;
+	if (autoresume) {
+		sourcesink_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
+		loopback_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
+	}
+
+	/* support OTG systems */
+	if (gadget_is_otg(cdev->gadget)) {
+		sourcesink_driver.descriptors = otg_desc;
+		sourcesink_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
+		loopback_driver.descriptors = otg_desc;
+		loopback_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
+	}
+
 	/* Register primary, then secondary configuration.  Note that
 	/* Register primary, then secondary configuration.  Note that
 	 * SH3 only allows one config...
 	 * SH3 only allows one config...
 	 */
 	 */
 	if (loopdefault) {
 	if (loopdefault) {
-		loopback_add(cdev, autoresume != 0);
-		sourcesink_add(cdev, autoresume != 0);
+		usb_add_config_only(cdev, &loopback_driver);
+		usb_add_config_only(cdev, &sourcesink_driver);
 	} else {
 	} else {
-		sourcesink_add(cdev, autoresume != 0);
-		loopback_add(cdev, autoresume != 0);
+		usb_add_config_only(cdev, &sourcesink_driver);
+		usb_add_config_only(cdev, &loopback_driver);
 	}
 	}
+	status = usb_add_function(&sourcesink_driver, func_ss);
+	if (status)
+		goto err_conf_flb;
+
+	usb_ep_autoconfig_reset(cdev->gadget);
+	status = usb_add_function(&loopback_driver, func_lb);
+	if (status)
+		goto err_conf_flb;
 
 
+	usb_ep_autoconfig_reset(cdev->gadget);
 	usb_composite_overwrite_options(cdev, &coverwrite);
 	usb_composite_overwrite_options(cdev, &coverwrite);
 
 
 	INFO(cdev, "%s, version: " DRIVER_VERSION "\n", longname);
 	INFO(cdev, "%s, version: " DRIVER_VERSION "\n", longname);
 
 
 	return 0;
 	return 0;
+
+err_conf_flb:
+	usb_put_function(func_lb);
+	func_lb = NULL;
+err_put_func_inst_lb:
+	usb_put_function_instance(func_inst_lb);
+	func_inst_lb = NULL;
+err_put_func_ss:
+	usb_put_function(func_ss);
+	func_ss = NULL;
+err_put_func_inst_ss:
+	usb_put_function_instance(func_inst_ss);
+	func_inst_ss = NULL;
+	return status;
 }
 }
 
 
 static int zero_unbind(struct usb_composite_dev *cdev)
 static int zero_unbind(struct usb_composite_dev *cdev)
 {
 {
 	del_timer_sync(&autoresume_timer);
 	del_timer_sync(&autoresume_timer);
+	if (!IS_ERR_OR_NULL(func_ss))
+		usb_put_function(func_ss);
+	if (!IS_ERR_OR_NULL(func_lb))
+		usb_put_function(func_lb);
 	return 0;
 	return 0;
 }
 }
 
 

+ 0 - 1
drivers/usb/host/ehci-mv.c

@@ -302,7 +302,6 @@ static int mv_ehci_remove(struct platform_device *pdev)
 {
 {
 	struct ehci_hcd_mv *ehci_mv = platform_get_drvdata(pdev);
 	struct ehci_hcd_mv *ehci_mv = platform_get_drvdata(pdev);
 	struct usb_hcd *hcd = ehci_mv->hcd;
 	struct usb_hcd *hcd = ehci_mv->hcd;
-	int clk_i;
 
 
 	if (hcd->rh_registered)
 	if (hcd->rh_registered)
 		usb_remove_hcd(hcd);
 		usb_remove_hcd(hcd);

+ 22 - 60
drivers/usb/otg/mv_otg.c

@@ -662,18 +662,9 @@ static struct attribute_group inputs_attr_group = {
 int mv_otg_remove(struct platform_device *pdev)
 int mv_otg_remove(struct platform_device *pdev)
 {
 {
 	struct mv_otg *mvotg = platform_get_drvdata(pdev);
 	struct mv_otg *mvotg = platform_get_drvdata(pdev);
-	int clk_i;
 
 
 	sysfs_remove_group(&mvotg->pdev->dev.kobj, &inputs_attr_group);
 	sysfs_remove_group(&mvotg->pdev->dev.kobj, &inputs_attr_group);
 
 
-	if (mvotg->irq)
-		free_irq(mvotg->irq, mvotg);
-
-	if (mvotg->pdata->vbus)
-		free_irq(mvotg->pdata->vbus->irq, mvotg);
-	if (mvotg->pdata->id)
-		free_irq(mvotg->pdata->id->irq, mvotg);
-
 	if (mvotg->qwork) {
 	if (mvotg->qwork) {
 		flush_workqueue(mvotg->qwork);
 		flush_workqueue(mvotg->qwork);
 		destroy_workqueue(mvotg->qwork);
 		destroy_workqueue(mvotg->qwork);
@@ -681,21 +672,9 @@ int mv_otg_remove(struct platform_device *pdev)
 
 
 	mv_otg_disable(mvotg);
 	mv_otg_disable(mvotg);
 
 
-	if (mvotg->cap_regs)
-		iounmap(mvotg->cap_regs);
-
-	if (mvotg->phy_regs)
-		iounmap(mvotg->phy_regs);
-
-	for (clk_i = 0; clk_i <= mvotg->clknum; clk_i++)
-		clk_put(mvotg->clk[clk_i]);
-
 	usb_remove_phy(&mvotg->phy);
 	usb_remove_phy(&mvotg->phy);
 	platform_set_drvdata(pdev, NULL);
 	platform_set_drvdata(pdev, NULL);
 
 
-	kfree(mvotg->phy.otg);
-	kfree(mvotg);
-
 	return 0;
 	return 0;
 }
 }
 
 
@@ -714,17 +693,15 @@ static int mv_otg_probe(struct platform_device *pdev)
 	}
 	}
 
 
 	size = sizeof(*mvotg) + sizeof(struct clk *) * pdata->clknum;
 	size = sizeof(*mvotg) + sizeof(struct clk *) * pdata->clknum;
-	mvotg = kzalloc(size, GFP_KERNEL);
+	mvotg = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
 	if (!mvotg) {
 	if (!mvotg) {
 		dev_err(&pdev->dev, "failed to allocate memory!\n");
 		dev_err(&pdev->dev, "failed to allocate memory!\n");
 		return -ENOMEM;
 		return -ENOMEM;
 	}
 	}
 
 
-	otg = kzalloc(sizeof *otg, GFP_KERNEL);
-	if (!otg) {
-		kfree(mvotg);
+	otg = devm_kzalloc(&pdev->dev, sizeof(*otg), GFP_KERNEL);
+	if (!otg)
 		return -ENOMEM;
 		return -ENOMEM;
-	}
 
 
 	platform_set_drvdata(pdev, mvotg);
 	platform_set_drvdata(pdev, mvotg);
 
 
@@ -733,18 +710,18 @@ static int mv_otg_probe(struct platform_device *pdev)
 
 
 	mvotg->clknum = pdata->clknum;
 	mvotg->clknum = pdata->clknum;
 	for (clk_i = 0; clk_i < mvotg->clknum; clk_i++) {
 	for (clk_i = 0; clk_i < mvotg->clknum; clk_i++) {
-		mvotg->clk[clk_i] = clk_get(&pdev->dev, pdata->clkname[clk_i]);
+		mvotg->clk[clk_i] = devm_clk_get(&pdev->dev,
+						pdata->clkname[clk_i]);
 		if (IS_ERR(mvotg->clk[clk_i])) {
 		if (IS_ERR(mvotg->clk[clk_i])) {
 			retval = PTR_ERR(mvotg->clk[clk_i]);
 			retval = PTR_ERR(mvotg->clk[clk_i]);
-			goto err_put_clk;
+			return retval;
 		}
 		}
 	}
 	}
 
 
 	mvotg->qwork = create_singlethread_workqueue("mv_otg_queue");
 	mvotg->qwork = create_singlethread_workqueue("mv_otg_queue");
 	if (!mvotg->qwork) {
 	if (!mvotg->qwork) {
 		dev_dbg(&pdev->dev, "cannot create workqueue for OTG\n");
 		dev_dbg(&pdev->dev, "cannot create workqueue for OTG\n");
-		retval = -ENOMEM;
-		goto err_put_clk;
+		return -ENOMEM;
 	}
 	}
 
 
 	INIT_DELAYED_WORK(&mvotg->work, mv_otg_work);
 	INIT_DELAYED_WORK(&mvotg->work, mv_otg_work);
@@ -772,7 +749,7 @@ static int mv_otg_probe(struct platform_device *pdev)
 		goto err_destroy_workqueue;
 		goto err_destroy_workqueue;
 	}
 	}
 
 
-	mvotg->phy_regs = ioremap(r->start, resource_size(r));
+	mvotg->phy_regs = devm_ioremap(&pdev->dev, r->start, resource_size(r));
 	if (mvotg->phy_regs == NULL) {
 	if (mvotg->phy_regs == NULL) {
 		dev_err(&pdev->dev, "failed to map phy I/O memory\n");
 		dev_err(&pdev->dev, "failed to map phy I/O memory\n");
 		retval = -EFAULT;
 		retval = -EFAULT;
@@ -784,21 +761,21 @@ static int mv_otg_probe(struct platform_device *pdev)
 	if (r == NULL) {
 	if (r == NULL) {
 		dev_err(&pdev->dev, "no I/O memory resource defined\n");
 		dev_err(&pdev->dev, "no I/O memory resource defined\n");
 		retval = -ENODEV;
 		retval = -ENODEV;
-		goto err_unmap_phyreg;
+		goto err_destroy_workqueue;
 	}
 	}
 
 
-	mvotg->cap_regs = ioremap(r->start, resource_size(r));
+	mvotg->cap_regs = devm_ioremap(&pdev->dev, r->start, resource_size(r));
 	if (mvotg->cap_regs == NULL) {
 	if (mvotg->cap_regs == NULL) {
 		dev_err(&pdev->dev, "failed to map I/O memory\n");
 		dev_err(&pdev->dev, "failed to map I/O memory\n");
 		retval = -EFAULT;
 		retval = -EFAULT;
-		goto err_unmap_phyreg;
+		goto err_destroy_workqueue;
 	}
 	}
 
 
 	/* we will acces controller register, so enable the udc controller */
 	/* we will acces controller register, so enable the udc controller */
 	retval = mv_otg_enable_internal(mvotg);
 	retval = mv_otg_enable_internal(mvotg);
 	if (retval) {
 	if (retval) {
 		dev_err(&pdev->dev, "mv otg enable error %d\n", retval);
 		dev_err(&pdev->dev, "mv otg enable error %d\n", retval);
-		goto err_unmap_capreg;
+		goto err_destroy_workqueue;
 	}
 	}
 
 
 	mvotg->op_regs =
 	mvotg->op_regs =
@@ -806,9 +783,9 @@ static int mv_otg_probe(struct platform_device *pdev)
 			+ (readl(mvotg->cap_regs) & CAPLENGTH_MASK));
 			+ (readl(mvotg->cap_regs) & CAPLENGTH_MASK));
 
 
 	if (pdata->id) {
 	if (pdata->id) {
-		retval = request_threaded_irq(pdata->id->irq, NULL,
-					      mv_otg_inputs_irq,
-					      IRQF_ONESHOT, "id", mvotg);
+		retval = devm_request_threaded_irq(&pdev->dev, pdata->id->irq,
+						NULL, mv_otg_inputs_irq,
+						IRQF_ONESHOT, "id", mvotg);
 		if (retval) {
 		if (retval) {
 			dev_info(&pdev->dev,
 			dev_info(&pdev->dev,
 				 "Failed to request irq for ID\n");
 				 "Failed to request irq for ID\n");
@@ -818,9 +795,9 @@ static int mv_otg_probe(struct platform_device *pdev)
 
 
 	if (pdata->vbus) {
 	if (pdata->vbus) {
 		mvotg->clock_gating = 1;
 		mvotg->clock_gating = 1;
-		retval = request_threaded_irq(pdata->vbus->irq, NULL,
-					      mv_otg_inputs_irq,
-					      IRQF_ONESHOT, "vbus", mvotg);
+		retval = devm_request_threaded_irq(&pdev->dev, pdata->vbus->irq,
+						NULL, mv_otg_inputs_irq,
+						IRQF_ONESHOT, "vbus", mvotg);
 		if (retval) {
 		if (retval) {
 			dev_info(&pdev->dev,
 			dev_info(&pdev->dev,
 				 "Failed to request irq for VBUS, "
 				 "Failed to request irq for VBUS, "
@@ -844,7 +821,7 @@ static int mv_otg_probe(struct platform_device *pdev)
 	}
 	}
 
 
 	mvotg->irq = r->start;
 	mvotg->irq = r->start;
-	if (request_irq(mvotg->irq, mv_otg_irq, IRQF_SHARED,
+	if (devm_request_irq(&pdev->dev, mvotg->irq, mv_otg_irq, IRQF_SHARED,
 			driver_name, mvotg)) {
 			driver_name, mvotg)) {
 		dev_err(&pdev->dev, "Request irq %d for OTG failed\n",
 		dev_err(&pdev->dev, "Request irq %d for OTG failed\n",
 			mvotg->irq);
 			mvotg->irq);
@@ -857,14 +834,14 @@ static int mv_otg_probe(struct platform_device *pdev)
 	if (retval < 0) {
 	if (retval < 0) {
 		dev_err(&pdev->dev, "can't register transceiver, %d\n",
 		dev_err(&pdev->dev, "can't register transceiver, %d\n",
 			retval);
 			retval);
-		goto err_free_irq;
+		goto err_disable_clk;
 	}
 	}
 
 
 	retval = sysfs_create_group(&pdev->dev.kobj, &inputs_attr_group);
 	retval = sysfs_create_group(&pdev->dev.kobj, &inputs_attr_group);
 	if (retval < 0) {
 	if (retval < 0) {
 		dev_dbg(&pdev->dev,
 		dev_dbg(&pdev->dev,
 			"Can't register sysfs attr group: %d\n", retval);
 			"Can't register sysfs attr group: %d\n", retval);
-		goto err_set_transceiver;
+		goto err_remove_phy;
 	}
 	}
 
 
 	spin_lock_init(&mvotg->wq_lock);
 	spin_lock_init(&mvotg->wq_lock);
@@ -879,30 +856,15 @@ static int mv_otg_probe(struct platform_device *pdev)
 
 
 	return 0;
 	return 0;
 
 
-err_set_transceiver:
+err_remove_phy:
 	usb_remove_phy(&mvotg->phy);
 	usb_remove_phy(&mvotg->phy);
-err_free_irq:
-	free_irq(mvotg->irq, mvotg);
 err_disable_clk:
 err_disable_clk:
-	if (pdata->vbus)
-		free_irq(pdata->vbus->irq, mvotg);
-	if (pdata->id)
-		free_irq(pdata->id->irq, mvotg);
 	mv_otg_disable_internal(mvotg);
 	mv_otg_disable_internal(mvotg);
-err_unmap_capreg:
-	iounmap(mvotg->cap_regs);
-err_unmap_phyreg:
-	iounmap(mvotg->phy_regs);
 err_destroy_workqueue:
 err_destroy_workqueue:
 	flush_workqueue(mvotg->qwork);
 	flush_workqueue(mvotg->qwork);
 	destroy_workqueue(mvotg->qwork);
 	destroy_workqueue(mvotg->qwork);
-err_put_clk:
-	for (clk_i--; clk_i >= 0; clk_i--)
-		clk_put(mvotg->clk[clk_i]);
 
 
 	platform_set_drvdata(pdev, NULL);
 	platform_set_drvdata(pdev, NULL);
-	kfree(otg);
-	kfree(mvotg);
 
 
 	return retval;
 	return retval;
 }
 }

+ 1 - 1
drivers/usb/renesas_usbhs/mod_gadget.c

@@ -900,7 +900,7 @@ static int usbhsg_set_selfpowered(struct usb_gadget *gadget, int is_self)
 	return 0;
 	return 0;
 }
 }
 
 
-static struct usb_gadget_ops usbhsg_gadget_ops = {
+static const struct usb_gadget_ops usbhsg_gadget_ops = {
 	.get_frame		= usbhsg_get_frame,
 	.get_frame		= usbhsg_get_frame,
 	.set_selfpowered	= usbhsg_set_selfpowered,
 	.set_selfpowered	= usbhsg_set_selfpowered,
 	.udc_start		= usbhsg_gadget_start,
 	.udc_start		= usbhsg_gadget_start,

+ 73 - 2
include/linux/usb/composite.h

@@ -77,6 +77,8 @@ struct usb_configuration;
  *	in interface or class descriptors; endpoints; I/O buffers; and so on.
  *	in interface or class descriptors; endpoints; I/O buffers; and so on.
  * @unbind: Reverses @bind; called as a side effect of unregistering the
  * @unbind: Reverses @bind; called as a side effect of unregistering the
  *	driver which added this function.
  *	driver which added this function.
+ * @free_func: free the struct usb_function.
+ * @mod: (internal) points to the module that created this structure.
  * @set_alt: (REQUIRED) Reconfigures altsettings; function drivers may
  * @set_alt: (REQUIRED) Reconfigures altsettings; function drivers may
  *	initialize usb_ep.driver data at this time (when it is used).
  *	initialize usb_ep.driver data at this time (when it is used).
  *	Note that setting an interface to its current altsetting resets
  *	Note that setting an interface to its current altsetting resets
@@ -116,6 +118,7 @@ struct usb_configuration;
  * two or more distinct instances within the same configuration, providing
  * two or more distinct instances within the same configuration, providing
  * several independent logical data links to a USB host.
  * several independent logical data links to a USB host.
  */
  */
+
 struct usb_function {
 struct usb_function {
 	const char			*name;
 	const char			*name;
 	struct usb_gadget_strings	**strings;
 	struct usb_gadget_strings	**strings;
@@ -136,6 +139,8 @@ struct usb_function {
 					struct usb_function *);
 					struct usb_function *);
 	void			(*unbind)(struct usb_configuration *,
 	void			(*unbind)(struct usb_configuration *,
 					struct usb_function *);
 					struct usb_function *);
+	void			(*free_func)(struct usb_function *f);
+	struct module		*mod;
 
 
 	/* runtime state management */
 	/* runtime state management */
 	int			(*set_alt)(struct usb_function *,
 	int			(*set_alt)(struct usb_function *,
@@ -156,6 +161,7 @@ struct usb_function {
 	/* internals */
 	/* internals */
 	struct list_head		list;
 	struct list_head		list;
 	DECLARE_BITMAP(endpoints, 32);
 	DECLARE_BITMAP(endpoints, 32);
+	const struct usb_function_instance *fi;
 };
 };
 
 
 int usb_add_function(struct usb_configuration *, struct usb_function *);
 int usb_add_function(struct usb_configuration *, struct usb_function *);
@@ -184,7 +190,8 @@ int config_ep_by_speed(struct usb_gadget *g, struct usb_function *f,
  * @bConfigurationValue: Copied into configuration descriptor.
  * @bConfigurationValue: Copied into configuration descriptor.
  * @iConfiguration: Copied into configuration descriptor.
  * @iConfiguration: Copied into configuration descriptor.
  * @bmAttributes: Copied into configuration descriptor.
  * @bmAttributes: Copied into configuration descriptor.
- * @bMaxPower: Copied into configuration descriptor.
+ * @MaxPower: Power consumtion in mA. Used to compute bMaxPower in the
+ *	configuration descriptor after considering the bus speed.
  * @cdev: assigned by @usb_add_config() before calling @bind(); this is
  * @cdev: assigned by @usb_add_config() before calling @bind(); this is
  *	the device associated with this configuration.
  *	the device associated with this configuration.
  *
  *
@@ -230,7 +237,7 @@ struct usb_configuration {
 	u8			bConfigurationValue;
 	u8			bConfigurationValue;
 	u8			iConfiguration;
 	u8			iConfiguration;
 	u8			bmAttributes;
 	u8			bmAttributes;
-	u8			bMaxPower;
+	u16			MaxPower;
 
 
 	struct usb_composite_dev	*cdev;
 	struct usb_composite_dev	*cdev;
 
 
@@ -316,7 +323,15 @@ struct usb_composite_driver {
 extern int usb_composite_probe(struct usb_composite_driver *driver);
 extern int usb_composite_probe(struct usb_composite_driver *driver);
 extern void usb_composite_unregister(struct usb_composite_driver *driver);
 extern void usb_composite_unregister(struct usb_composite_driver *driver);
 extern void usb_composite_setup_continue(struct usb_composite_dev *cdev);
 extern void usb_composite_setup_continue(struct usb_composite_dev *cdev);
+extern int composite_dev_prepare(struct usb_composite_driver *composite,
+		struct usb_composite_dev *cdev);
+void composite_dev_cleanup(struct usb_composite_dev *cdev);
 
 
+static inline struct usb_composite_driver *to_cdriver(
+		struct usb_gadget_driver *gdrv)
+{
+	return container_of(gdrv, struct usb_composite_driver, gadget_driver);
+}
 
 
 /**
 /**
  * struct usb_composite_device - represents one composite usb gadget
  * struct usb_composite_device - represents one composite usb gadget
@@ -360,6 +375,7 @@ struct usb_composite_dev {
 	unsigned int			suspended:1;
 	unsigned int			suspended:1;
 	struct usb_device_descriptor	desc;
 	struct usb_device_descriptor	desc;
 	struct list_head		configs;
 	struct list_head		configs;
+	struct list_head		gstrings;
 	struct usb_composite_driver	*driver;
 	struct usb_composite_driver	*driver;
 	u8				next_string_id;
 	u8				next_string_id;
 	char				*def_manufacturer;
 	char				*def_manufacturer;
@@ -381,8 +397,15 @@ struct usb_composite_dev {
 extern int usb_string_id(struct usb_composite_dev *c);
 extern int usb_string_id(struct usb_composite_dev *c);
 extern int usb_string_ids_tab(struct usb_composite_dev *c,
 extern int usb_string_ids_tab(struct usb_composite_dev *c,
 			      struct usb_string *str);
 			      struct usb_string *str);
+extern struct usb_string *usb_gstrings_attach(struct usb_composite_dev *cdev,
+		struct usb_gadget_strings **sp, unsigned n_strings);
+
 extern int usb_string_ids_n(struct usb_composite_dev *c, unsigned n);
 extern int usb_string_ids_n(struct usb_composite_dev *c, unsigned n);
 
 
+extern void composite_disconnect(struct usb_gadget *gadget);
+extern int composite_setup(struct usb_gadget *gadget,
+		const struct usb_ctrlrequest *ctrl);
+
 /*
 /*
  * Some systems will need runtime overrides for the  product identifiers
  * Some systems will need runtime overrides for the  product identifiers
  * published in the device descriptor, either numbers or strings or both.
  * published in the device descriptor, either numbers or strings or both.
@@ -431,6 +454,54 @@ static inline u16 get_default_bcdDevice(void)
 	return bcdDevice;
 	return bcdDevice;
 }
 }
 
 
+struct usb_function_driver {
+	const char *name;
+	struct module *mod;
+	struct list_head list;
+	struct usb_function_instance *(*alloc_inst)(void);
+	struct usb_function *(*alloc_func)(struct usb_function_instance *inst);
+};
+
+struct usb_function_instance {
+	struct usb_function_driver *fd;
+	void (*free_func_inst)(struct usb_function_instance *inst);
+};
+
+void usb_function_unregister(struct usb_function_driver *f);
+int usb_function_register(struct usb_function_driver *newf);
+void usb_put_function_instance(struct usb_function_instance *fi);
+void usb_put_function(struct usb_function *f);
+struct usb_function_instance *usb_get_function_instance(const char *name);
+struct usb_function *usb_get_function(struct usb_function_instance *fi);
+
+struct usb_configuration *usb_get_config(struct usb_composite_dev *cdev,
+		int val);
+int usb_add_config_only(struct usb_composite_dev *cdev,
+		struct usb_configuration *config);
+void usb_remove_function(struct usb_configuration *c, struct usb_function *f);
+
+#define DECLARE_USB_FUNCTION(_name, _inst_alloc, _func_alloc)		\
+	static struct usb_function_driver _name ## usb_func = {		\
+		.name = __stringify(_name),				\
+		.mod  = THIS_MODULE,					\
+		.alloc_inst = _inst_alloc,				\
+		.alloc_func = _func_alloc,				\
+	};								\
+	MODULE_ALIAS("usbfunc:"__stringify(_name));
+
+#define DECLARE_USB_FUNCTION_INIT(_name, _inst_alloc, _func_alloc)	\
+	DECLARE_USB_FUNCTION(_name, _inst_alloc, _func_alloc)		\
+	static int __init _name ## mod_init(void)			\
+	{								\
+		return usb_function_register(&_name ## usb_func);	\
+	}								\
+	static void __exit _name ## mod_exit(void)			\
+	{								\
+		usb_function_unregister(&_name ## usb_func);		\
+	}								\
+	module_init(_name ## mod_init);					\
+	module_exit(_name ## mod_exit)
+
 /* messaging utils */
 /* messaging utils */
 #define DBG(d, fmt, args...) \
 #define DBG(d, fmt, args...) \
 	dev_dbg(&(d)->gadget->dev , fmt , ## args)
 	dev_dbg(&(d)->gadget->dev , fmt , ## args)

+ 7 - 6
include/linux/usb/gadget.h

@@ -471,12 +471,6 @@ struct usb_gadget_ops {
 			struct usb_gadget_driver *);
 			struct usb_gadget_driver *);
 	int	(*udc_stop)(struct usb_gadget *,
 	int	(*udc_stop)(struct usb_gadget *,
 			struct usb_gadget_driver *);
 			struct usb_gadget_driver *);
-
-	/* Those two are deprecated */
-	int	(*start)(struct usb_gadget_driver *,
-			int (*bind)(struct usb_gadget *,
-				struct usb_gadget_driver *driver));
-	int	(*stop)(struct usb_gadget_driver *);
 };
 };
 
 
 /**
 /**
@@ -880,6 +874,8 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver);
 
 
 extern int usb_add_gadget_udc(struct device *parent, struct usb_gadget *gadget);
 extern int usb_add_gadget_udc(struct device *parent, struct usb_gadget *gadget);
 extern void usb_del_gadget_udc(struct usb_gadget *gadget);
 extern void usb_del_gadget_udc(struct usb_gadget *gadget);
+extern int udc_attach_driver(const char *name,
+		struct usb_gadget_driver *driver);
 
 
 /*-------------------------------------------------------------------------*/
 /*-------------------------------------------------------------------------*/
 
 
@@ -911,6 +907,11 @@ struct usb_gadget_strings {
 	struct usb_string	*strings;
 	struct usb_string	*strings;
 };
 };
 
 
+struct usb_gadget_string_container {
+	struct list_head        list;
+	u8                      *stash[0];
+};
+
 /* put descriptor for string with that id into buf (buflen >= 256) */
 /* put descriptor for string with that id into buf (buflen >= 256) */
 int usb_gadget_get_string(struct usb_gadget_strings *table, int id, u8 *buf);
 int usb_gadget_get_string(struct usb_gadget_strings *table, int id, u8 *buf);