Browse Source

Merge tag 'usb-3.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb

Pull USB patches from Greg Kroah-Hartman:
 "Here's the big USB merge for 3.9-rc1

  Nothing major, lots of gadget fixes, and of course, xhci stuff.

  All of this has been in linux-next for a while, with the exception of
  the last 3 patches, which were reverts of patches in the tree that
  caused problems, they went in yesterday."

* tag 'usb-3.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (190 commits)
  Revert "USB: EHCI: make ehci-vt8500 a separate driver"
  Revert "USB: EHCI: make ehci-orion a separate driver"
  Revert "USB: update host controller Kconfig entries"
  USB: update host controller Kconfig entries
  USB: EHCI: make ehci-orion a separate driver
  USB: EHCI: make ehci-vt8500 a separate driver
  USB: usb-storage: unusual_devs update for Super TOP SATA bridge
  USB: ehci-omap: Fix autoloading of module
  USB: ehci-omap: Don't free gpios that we didn't request
  USB: option: add Huawei "ACM" devices using protocol = vendor
  USB: serial: fix null-pointer dereferences on disconnect
  USB: option: add Yota / Megafon M100-1 4g modem
  drivers/usb: add missing GENERIC_HARDIRQS dependencies
  USB: storage: properly handle the endian issues of idProduct
  testusb: remove all mentions of 'usbfs'
  usb: gadget: imx_udc: make it depend on BROKEN
  usb: omap_control_usb: fix compile warning
  ARM: OMAP: USB: Add phy binding information
  ARM: OMAP2: MUSB: Specify omap4 has mailbox
  ARM: OMAP: devices: create device for usb part of control module
  ...
Linus Torvalds 12 years ago
parent
commit
74e1a2a393
100 changed files with 2784 additions and 1792 deletions
  1. 9 0
      Documentation/ABI/testing/sysfs-bus-usb
  2. 22 0
      Documentation/devicetree/bindings/usb/dwc3.txt
  3. 33 1
      Documentation/devicetree/bindings/usb/omap-usb.txt
  4. 55 0
      Documentation/devicetree/bindings/usb/samsung-usbphy.txt
  5. 30 5
      Documentation/devicetree/bindings/usb/usb-phy.txt
  6. 20 0
      Documentation/devicetree/bindings/usb/usb3503.txt
  7. 2 1
      MAINTAINERS
  8. 2 0
      arch/arm/mach-omap2/board-2430sdp.c
  9. 2 0
      arch/arm/mach-omap2/board-3430sdp.c
  10. 2 0
      arch/arm/mach-omap2/board-4430sdp.c
  11. 2 0
      arch/arm/mach-omap2/board-cm-t35.c
  12. 2 0
      arch/arm/mach-omap2/board-devkit8000.c
  13. 2 0
      arch/arm/mach-omap2/board-igep0020.c
  14. 2 0
      arch/arm/mach-omap2/board-ldp.c
  15. 2 0
      arch/arm/mach-omap2/board-omap3beagle.c
  16. 2 0
      arch/arm/mach-omap2/board-omap3evm.c
  17. 2 0
      arch/arm/mach-omap2/board-omap3logic.c
  18. 2 0
      arch/arm/mach-omap2/board-omap3pandora.c
  19. 2 0
      arch/arm/mach-omap2/board-omap3stalker.c
  20. 2 0
      arch/arm/mach-omap2/board-omap3touchbook.c
  21. 2 0
      arch/arm/mach-omap2/board-omap4panda.c
  22. 2 0
      arch/arm/mach-omap2/board-overo.c
  23. 2 0
      arch/arm/mach-omap2/board-rm680.c
  24. 2 0
      arch/arm/mach-omap2/board-zoom-peripherals.c
  25. 45 0
      arch/arm/mach-omap2/devices.c
  26. 0 13
      arch/arm/mach-omap2/omap_hwmod_44xx_data.c
  27. 3 0
      arch/arm/mach-omap2/usb-musb.c
  28. 1 0
      drivers/base/power/qos.c
  29. 1 1
      drivers/usb/c67x00/c67x00-ll-hpi.c
  30. 1 1
      drivers/usb/chipidea/ci13xxx_imx.h
  31. 1 1
      drivers/usb/chipidea/core.c
  32. 1 0
      drivers/usb/core/Makefile
  33. 10 3
      drivers/usb/core/devices.c
  34. 2 1
      drivers/usb/core/devio.c
  35. 1 1
      drivers/usb/core/generic.c
  36. 4 1
      drivers/usb/core/hcd.c
  37. 280 258
      drivers/usb/core/hub.c
  38. 122 0
      drivers/usb/core/hub.h
  39. 1 1
      drivers/usb/core/message.c
  40. 202 0
      drivers/usb/core/port.c
  41. 22 9
      drivers/usb/core/sysfs.c
  42. 12 0
      drivers/usb/core/usb.h
  43. 30 1
      drivers/usb/dwc3/Kconfig
  44. 8 2
      drivers/usb/dwc3/Makefile
  45. 25 6
      drivers/usb/dwc3/core.c
  46. 20 4
      drivers/usb/dwc3/core.h
  47. 14 24
      drivers/usb/dwc3/debugfs.c
  48. 26 31
      drivers/usb/dwc3/dwc3-exynos.c
  49. 93 59
      drivers/usb/dwc3/dwc3-omap.c
  50. 179 113
      drivers/usb/dwc3/gadget.c
  51. 1 1
      drivers/usb/dwc3/host.c
  52. 23 1
      drivers/usb/gadget/Kconfig
  53. 7 1
      drivers/usb/gadget/Makefile
  54. 31 11
      drivers/usb/gadget/acm_ms.c
  55. 14 45
      drivers/usb/gadget/amd5536udc.c
  56. 2 0
      drivers/usb/gadget/amd5536udc.h
  57. 2 3
      drivers/usb/gadget/at91_udc.c
  58. 27 9
      drivers/usb/gadget/cdc2.c
  59. 268 58
      drivers/usb/gadget/composite.c
  60. 8 6
      drivers/usb/gadget/dbgp.c
  61. 104 49
      drivers/usb/gadget/f_acm.c
  62. 2 3
      drivers/usb/gadget/f_fs.c
  63. 54 49
      drivers/usb/gadget/f_loopback.c
  64. 5 32
      drivers/usb/gadget/f_mass_storage.c
  65. 9 9
      drivers/usb/gadget/f_ncm.c
  66. 0 4
      drivers/usb/gadget/f_obex.c
  67. 0 4
      drivers/usb/gadget/f_serial.c
  68. 125 75
      drivers/usb/gadget/f_sourcesink.c
  69. 2 7
      drivers/usb/gadget/f_uac2.c
  70. 2 1
      drivers/usb/gadget/f_uvc.c
  71. 1 1
      drivers/usb/gadget/fsl_qe_udc.c
  72. 12 48
      drivers/usb/gadget/fsl_udc_core.c
  73. 116 0
      drivers/usb/gadget/functions.c
  74. 19 48
      drivers/usb/gadget/fusb300_udc.c
  75. 2 0
      drivers/usb/gadget/fusb300_udc.h
  76. 27 8
      drivers/usb/gadget/g_zero.h
  77. 1 1
      drivers/usb/gadget/gmidi.c
  78. 14 56
      drivers/usb/gadget/goku_udc.c
  79. 1 0
      drivers/usb/gadget/goku_udc.h
  80. 20 52
      drivers/usb/gadget/m66592-udc.c
  81. 1 0
      drivers/usb/gadget/m66592-udc.h
  82. 56 15
      drivers/usb/gadget/multi.c
  83. 99 147
      drivers/usb/gadget/mv_udc_core.c
  84. 15 0
      drivers/usb/gadget/net2280.c
  85. 31 12
      drivers/usb/gadget/nokia.c
  86. 13 38
      drivers/usb/gadget/omap_udc.c
  87. 14 53
      drivers/usb/gadget/pch_udc.c
  88. 14 48
      drivers/usb/gadget/pxa25x_udc.c
  89. 1 0
      drivers/usb/gadget/pxa25x_udc.h
  90. 15 46
      drivers/usb/gadget/pxa27x_udc.c
  91. 1 0
      drivers/usb/gadget/pxa27x_udc.h
  92. 1 1
      drivers/usb/gadget/r8a66597-udc.c
  93. 29 15
      drivers/usb/gadget/s3c-hsotg.c
  94. 6 7
      drivers/usb/gadget/s3c-hsudc.c
  95. 12 53
      drivers/usb/gadget/s3c2410_udc.c
  96. 1 0
      drivers/usb/gadget/s3c2410_udc.h
  97. 100 18
      drivers/usb/gadget/serial.c
  98. 0 61
      drivers/usb/gadget/storage_common.c
  99. 157 156
      drivers/usb/gadget/u_serial.c
  100. 10 3
      drivers/usb/gadget/u_serial.h

+ 9 - 0
Documentation/ABI/testing/sysfs-bus-usb

@@ -227,3 +227,12 @@ Contact:	Lan Tianyu <tianyu.lan@intel.com>
 Description:
 		The /sys/bus/usb/devices/.../(hub interface)/portX
 		is usb port device's sysfs directory.
+
+What:		/sys/bus/usb/devices/.../(hub interface)/portX/connect_type
+Date:		January 2013
+Contact:	Lan Tianyu <tianyu.lan@intel.com>
+Description:
+		Some platforms provide usb port connect types through ACPI.
+		This attribute is to expose these information to user space.
+		The file will read "hotplug", "wired" and "not used" if the
+		information is available, and "unknown" otherwise.

+ 22 - 0
Documentation/devicetree/bindings/usb/dwc3.txt

@@ -0,0 +1,22 @@
+synopsys DWC3 CORE
+
+DWC3- USB3 CONTROLLER
+
+Required properties:
+ - compatible: must be "synopsys,dwc3"
+ - reg : Address and length of the register set for the device
+ - interrupts: Interrupts used by the dwc3 controller.
+ - usb-phy : array of phandle for the PHY device
+
+Optional properties:
+ - tx-fifo-resize: determines if the FIFO *has* to be reallocated.
+
+This is usually a subnode to DWC3 glue to which it is connected.
+
+dwc3@4a030000 {
+	compatible = "synopsys,dwc3";
+	reg = <0x4a030000 0xcfff>;
+	interrupts = <0 92 4>
+	usb-phy = <&usb2_phy>, <&usb3,phy>;
+	tx-fifo-resize;
+};

+ 33 - 1
Documentation/devicetree/bindings/usb/omap-usb.txt

@@ -1,8 +1,11 @@
-OMAP GLUE
+OMAP GLUE AND OTHER OMAP SPECIFIC COMPONENTS
 
 OMAP MUSB GLUE
  - compatible : Should be "ti,omap4-musb" or "ti,omap3-musb"
  - ti,hwmods : must be "usb_otg_hs"
+ - ti,has-mailbox : to specify that omap uses an external mailbox
+   (in control module) to communicate with the musb core during device connect
+   and disconnect.
  - multipoint : Should be "1" indicating the musb controller supports
    multipoint. This is a MUSB configuration-specific setting.
  - num_eps : Specifies the number of endpoints. This is also a
@@ -16,13 +19,19 @@ OMAP MUSB GLUE
  - power : Should be "50". This signifies the controller can supply upto
    100mA when operating in host mode.
 
+Optional properties:
+ - ctrl-module : phandle of the control module this glue uses to write to
+   mailbox
+
 SOC specific device node entry
 usb_otg_hs: usb_otg_hs@4a0ab000 {
 	compatible = "ti,omap4-musb";
 	ti,hwmods = "usb_otg_hs";
+	ti,has-mailbox;
 	multipoint = <1>;
 	num_eps = <16>;
 	ram_bits = <12>;
+	ctrl-module = <&omap_control_usb>;
 };
 
 Board specific device node entry
@@ -31,3 +40,26 @@ Board specific device node entry
 	mode = <3>;
 	power = <50>;
 };
+
+OMAP CONTROL USB
+
+Required properties:
+ - compatible: Should be "ti,omap-control-usb"
+ - reg : Address and length of the register set for the device. It contains
+   the address of "control_dev_conf" and "otghs_control" or "phy_power_usb"
+   depending upon omap4 or omap5.
+ - reg-names: The names of the register addresses corresponding to the registers
+   filled in "reg".
+ - ti,type: This is used to differentiate whether the control module has
+   usb mailbox or usb3 phy power. omap4 has usb mailbox in control module to
+   notify events to the musb core and omap5 has usb3 phy power register to
+   power on usb3 phy. Should be "1" if it has mailbox and "2" if it has usb3
+   phy power.
+
+omap_control_usb: omap-control-usb@4a002300 {
+	compatible = "ti,omap-control-usb";
+	reg = <0x4a002300 0x4>,
+	      <0x4a00233c 0x4>;
+	reg-names = "control_dev_conf", "otghs_control";
+	ti,type = <1>;
+};

+ 55 - 0
Documentation/devicetree/bindings/usb/samsung-usbphy.txt

@@ -0,0 +1,55 @@
+* Samsung's usb phy transceiver
+
+The Samsung's phy transceiver is used for controlling usb phy for
+s3c-hsotg as well as ehci-s5p and ohci-exynos usb controllers
+across Samsung SOCs.
+TODO: Adding the PHY binding with controller(s) according to the under
+developement generic PHY driver.
+
+Required properties:
+
+Exynos4210:
+- compatible : should be "samsung,exynos4210-usbphy"
+- reg : base physical address of the phy registers and length of memory mapped
+	region.
+
+Exynos5250:
+- compatible : should be "samsung,exynos5250-usbphy"
+- reg : base physical address of the phy registers and length of memory mapped
+	region.
+
+Optional properties:
+- #address-cells: should be '1' when usbphy node has a child node with 'reg'
+		  property.
+- #size-cells: should be '1' when usbphy node has a child node with 'reg'
+	       property.
+- ranges: allows valid translation between child's address space and parent's
+	  address space.
+
+- The child node 'usbphy-sys' to the node 'usbphy' is for the system controller
+  interface for usb-phy. It should provide the following information required by
+  usb-phy controller to control phy.
+  - reg : base physical address of PHY_CONTROL registers.
+	  The size of this register is the total sum of size of all PHY_CONTROL
+	  registers that the SoC has. For example, the size will be
+	  '0x4' in case we have only one PHY_CONTROL register (e.g.
+	  OTHERS register in S3C64XX or USB_PHY_CONTROL register in S5PV210)
+	  and, '0x8' in case we have two PHY_CONTROL registers (e.g.
+	  USBDEVICE_PHY_CONTROL and USBHOST_PHY_CONTROL registers in exynos4x).
+	  and so on.
+
+Example:
+ - Exynos4210
+
+	usbphy@125B0000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "samsung,exynos4210-usbphy";
+		reg = <0x125B0000 0x100>;
+		ranges;
+
+		usbphy-sys {
+			/* USB device and host PHY_CONTROL registers */
+			reg = <0x10020704 0x8>;
+		};
+	};

+ 30 - 5
Documentation/devicetree/bindings/usb/usb-phy.txt

@@ -4,14 +4,39 @@ OMAP USB2 PHY
 
 Required properties:
  - compatible: Should be "ti,omap-usb2"
- - reg : Address and length of the register set for the device. Also
-add the address of control module dev conf register until a driver for
-control module is added
+ - reg : Address and length of the register set for the device.
+
+Optional properties:
+ - ctrl-module : phandle of the control module used by PHY driver to power on
+   the PHY.
 
 This is usually a subnode of ocp2scp to which it is connected.
 
 usb2phy@4a0ad080 {
 	compatible = "ti,omap-usb2";
-	reg = <0x4a0ad080 0x58>,
-	      <0x4a002300 0x4>;
+	reg = <0x4a0ad080 0x58>;
+	ctrl-module = <&omap_control_usb>;
+};
+
+OMAP USB3 PHY
+
+Required properties:
+ - compatible: Should be "ti,omap-usb3"
+ - reg : Address and length of the register set for the device.
+ - reg-names: The names of the register addresses corresponding to the registers
+   filled in "reg".
+
+Optional properties:
+ - ctrl-module : phandle of the control module used by PHY driver to power on
+   the PHY.
+
+This is usually a subnode of ocp2scp to which it is connected.
+
+usb3phy@4a084400 {
+	compatible = "ti,omap-usb3";
+	reg = <0x4a084400 0x80>,
+	      <0x4a084800 0x64>,
+	      <0x4a084c00 0x40>;
+	reg-names = "phy_rx", "phy_tx", "pll_ctrl";
+	ctrl-module = <&omap_control_usb>;
 };

+ 20 - 0
Documentation/devicetree/bindings/usb/usb3503.txt

@@ -0,0 +1,20 @@
+SMSC USB3503 High-Speed Hub Controller
+
+Required properties:
+- compatible: Should be "smsc,usb3503".
+- reg: Specifies the i2c slave address, it should be 0x08.
+- connect-gpios: Should specify GPIO for connect.
+- intn-gpios: Should specify GPIO for interrupt.
+- reset-gpios: Should specify GPIO for reset.
+- initial-mode: Should specify initial mode.
+                (1 for HUB mode, 2 for STANDBY mode)
+
+Examples:
+	usb3503@08 {
+		compatible = "smsc,usb3503";
+		reg = <0x08>;
+		connect-gpios = <&gpx3 0 1>;
+		intn-gpios = <&gpx3 4 1>;
+		reset-gpios = <&gpx3 5 1>;
+		initial-mode = <1>;
+	};

+ 2 - 1
MAINTAINERS

@@ -7927,9 +7927,10 @@ F:	drivers/net/wireless/ath/ar5523/
 USB ATTACHED SCSI
 M:	Matthew Wilcox <willy@linux.intel.com>
 M:	Sarah Sharp <sarah.a.sharp@linux.intel.com>
+M:	Gerd Hoffmann <kraxel@redhat.com>
 L:	linux-usb@vger.kernel.org
 L:	linux-scsi@vger.kernel.org
-S:	Supported
+S:	Maintained
 F:	drivers/usb/storage/uas.c
 
 USB CDC ETHERNET DRIVER

+ 2 - 0
arch/arm/mach-omap2/board-2430sdp.c

@@ -27,6 +27,7 @@
 #include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/gpio.h>
+#include <linux/usb/phy.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -263,6 +264,7 @@ static void __init omap_2430sdp_init(void)
 	omap_hsmmc_init(mmc);
 
 	omap_mux_init_signal("usb0hs_stp", OMAP_PULL_ENA | OMAP_PULL_UP);
+	usb_bind_phy("musb-hdrc.0.auto", 0, "twl4030_usb");
 	usb_musb_init(NULL);
 
 	board_smc91x_init();

+ 2 - 0
arch/arm/mach-omap2/board-3430sdp.c

@@ -25,6 +25,7 @@
 #include <linux/gpio.h>
 #include <linux/mmc/host.h>
 #include <linux/platform_data/spi-omap2-mcspi.h>
+#include <linux/usb/phy.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -579,6 +580,7 @@ static void __init omap_3430sdp_init(void)
 	omap_ads7846_init(1, gpio_pendown, 310, NULL);
 	omap_serial_init();
 	omap_sdrc_init(hyb18m512160af6_sdrc_params, NULL);
+	usb_bind_phy("musb-hdrc.0.auto", 0, "twl4030_usb");
 	usb_musb_init(NULL);
 	board_smc91x_init();
 	board_flash_init(sdp_flash_partitions, chip_sel_3430, 0);

+ 2 - 0
arch/arm/mach-omap2/board-4430sdp.c

@@ -28,6 +28,7 @@
 #include <linux/leds_pwm.h>
 #include <linux/platform_data/omap4-keypad.h>
 #include <linux/usb/musb.h>
+#include <linux/usb/phy.h>
 
 #include <asm/hardware/gic.h>
 #include <asm/mach-types.h>
@@ -696,6 +697,7 @@ static void __init omap_4430sdp_init(void)
 	omap4_sdp4430_wifi_init();
 	omap4_twl6030_hsmmc_init(mmc);
 
+	usb_bind_phy("musb-hdrc.0.auto", 0, "omap-usb2.1.auto");
 	usb_musb_init(&musb_board_data);
 
 	status = omap_ethernet_init();

+ 2 - 0
arch/arm/mach-omap2/board-cm-t35.c

@@ -30,6 +30,7 @@
 #include <linux/regulator/fixed.h>
 #include <linux/regulator/machine.h>
 #include <linux/mmc/host.h>
+#include <linux/usb/phy.h>
 
 #include <linux/spi/spi.h>
 #include <linux/spi/tdo24m.h>
@@ -724,6 +725,7 @@ static void __init cm_t3x_common_init(void)
 	cm_t35_init_display();
 	omap_twl4030_audio_init("cm-t3x");
 
+	usb_bind_phy("musb-hdrc.0.auto", 0, "twl4030_usb");
 	usb_musb_init(NULL);
 	cm_t35_init_usbh();
 	cm_t35_init_camera();

+ 2 - 0
arch/arm/mach-omap2/board-devkit8000.c

@@ -29,6 +29,7 @@
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/nand.h>
 #include <linux/mmc/host.h>
+#include <linux/usb/phy.h>
 
 #include <linux/regulator/machine.h>
 #include <linux/i2c/twl.h>
@@ -622,6 +623,7 @@ static void __init devkit8000_init(void)
 
 	omap_ads7846_init(2, OMAP3_DEVKIT_TS_GPIO, 0, NULL);
 
+	usb_bind_phy("musb-hdrc.0.auto", 0, "twl4030_usb");
 	usb_musb_init(NULL);
 	usbhs_init(&usbhs_bdata);
 	board_nand_init(devkit8000_nand_partitions,

+ 2 - 0
arch/arm/mach-omap2/board-igep0020.c

@@ -18,6 +18,7 @@
 #include <linux/gpio.h>
 #include <linux/interrupt.h>
 #include <linux/input.h>
+#include <linux/usb/phy.h>
 
 #include <linux/regulator/machine.h>
 #include <linux/regulator/fixed.h>
@@ -625,6 +626,7 @@ static void __init igep_init(void)
 	omap_serial_init();
 	omap_sdrc_init(m65kxxxxam_sdrc_params,
 				  m65kxxxxam_sdrc_params);
+	usb_bind_phy("musb-hdrc.0.auto", 0, "twl4030_usb");
 	usb_musb_init(NULL);
 
 	igep_flash_init();

+ 2 - 0
arch/arm/mach-omap2/board-ldp.c

@@ -28,6 +28,7 @@
 #include <linux/io.h>
 #include <linux/smsc911x.h>
 #include <linux/mmc/host.h>
+#include <linux/usb/phy.h>
 #include <linux/platform_data/spi-omap2-mcspi.h>
 
 #include <asm/mach-types.h>
@@ -418,6 +419,7 @@ static void __init omap_ldp_init(void)
 	omap_ads7846_init(1, 54, 310, NULL);
 	omap_serial_init();
 	omap_sdrc_init(NULL, NULL);
+	usb_bind_phy("musb-hdrc.0.auto", 0, "twl4030_usb");
 	usb_musb_init(NULL);
 	board_nand_init(ldp_nand_partitions, ARRAY_SIZE(ldp_nand_partitions),
 			ZOOM_NAND_CS, 0, nand_default_timings);

+ 2 - 0
arch/arm/mach-omap2/board-omap3beagle.c

@@ -30,6 +30,7 @@
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/nand.h>
 #include <linux/mmc/host.h>
+#include <linux/usb/phy.h>
 
 #include <linux/regulator/machine.h>
 #include <linux/i2c/twl.h>
@@ -519,6 +520,7 @@ static void __init omap3_beagle_init(void)
 	omap_sdrc_init(mt46h32m32lf6_sdrc_params,
 				  mt46h32m32lf6_sdrc_params);
 
+	usb_bind_phy("musb-hdrc.0.auto", 0, "twl4030_usb");
 	usb_musb_init(NULL);
 	usbhs_init(&usbhs_bdata);
 	board_nand_init(omap3beagle_nand_partitions,

+ 2 - 0
arch/arm/mach-omap2/board-omap3evm.c

@@ -41,6 +41,7 @@
 #include <linux/regulator/machine.h>
 #include <linux/mmc/host.h>
 #include <linux/export.h>
+#include <linux/usb/phy.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -734,6 +735,7 @@ static void __init omap3_evm_init(void)
 		omap_mux_init_gpio(135, OMAP_PIN_OUTPUT);
 		usbhs_bdata.reset_gpio_port[1] = 135;
 	}
+	usb_bind_phy("musb-hdrc.0.auto", 0, "twl4030_usb");
 	usb_musb_init(&musb_board_data);
 	usbhs_init(&usbhs_bdata);
 	board_nand_init(omap3evm_nand_partitions,

+ 2 - 0
arch/arm/mach-omap2/board-omap3logic.c

@@ -29,6 +29,7 @@
 
 #include <linux/i2c/twl.h>
 #include <linux/mmc/host.h>
+#include <linux/usb/phy.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -215,6 +216,7 @@ static void __init omap3logic_init(void)
 	board_mmc_init();
 	board_smsc911x_init();
 
+	usb_bind_phy("musb-hdrc.0.auto", 0, "twl4030_usb");
 	usb_musb_init(NULL);
 
 	/* Ensure SDRC pins are mux'd for self-refresh */

+ 2 - 0
arch/arm/mach-omap2/board-omap3pandora.c

@@ -35,6 +35,7 @@
 #include <linux/mmc/host.h>
 #include <linux/mmc/card.h>
 #include <linux/regulator/fixed.h>
+#include <linux/usb/phy.h>
 #include <linux/platform_data/spi-omap2-mcspi.h>
 
 #include <asm/mach-types.h>
@@ -601,6 +602,7 @@ static void __init omap3pandora_init(void)
 			ARRAY_SIZE(omap3pandora_spi_board_info));
 	omap_ads7846_init(1, OMAP3_PANDORA_TS_GPIO, 0, NULL);
 	usbhs_init(&usbhs_bdata);
+	usb_bind_phy("musb-hdrc.0.auto", 0, "twl4030_usb");
 	usb_musb_init(NULL);
 	gpmc_nand_init(&pandora_nand_data, NULL);
 

+ 2 - 0
arch/arm/mach-omap2/board-omap3stalker.c

@@ -33,6 +33,7 @@
 #include <linux/interrupt.h>
 #include <linux/smsc911x.h>
 #include <linux/i2c/at24.h>
+#include <linux/usb/phy.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -404,6 +405,7 @@ static void __init omap3_stalker_init(void)
 
 	omap_serial_init();
 	omap_sdrc_init(mt46h32m32lf6_sdrc_params, NULL);
+	usb_bind_phy("musb-hdrc.0.auto", 0, "twl4030_usb");
 	usb_musb_init(NULL);
 	usbhs_init(&usbhs_bdata);
 	omap_ads7846_init(1, OMAP3_STALKER_TS_GPIO, 310, NULL);

+ 2 - 0
arch/arm/mach-omap2/board-omap3touchbook.c

@@ -28,6 +28,7 @@
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/nand.h>
 #include <linux/mmc/host.h>
+#include <linux/usb/phy.h>
 
 #include <linux/platform_data/spi-omap2-mcspi.h>
 #include <linux/spi/spi.h>
@@ -365,6 +366,7 @@ static void __init omap3_touchbook_init(void)
 
 	/* Touchscreen and accelerometer */
 	omap_ads7846_init(4, OMAP3_TS_GPIO, 310, &ads7846_pdata);
+	usb_bind_phy("musb-hdrc.0.auto", 0, "twl4030_usb");
 	usb_musb_init(NULL);
 	usbhs_init(&usbhs_bdata);
 	board_nand_init(omap3touchbook_nand_partitions,

+ 2 - 0
arch/arm/mach-omap2/board-omap4panda.c

@@ -30,6 +30,7 @@
 #include <linux/regulator/fixed.h>
 #include <linux/ti_wilink_st.h>
 #include <linux/usb/musb.h>
+#include <linux/usb/phy.h>
 #include <linux/wl12xx.h>
 #include <linux/platform_data/omap-abe-twl6040.h>
 
@@ -447,6 +448,7 @@ static void __init omap4_panda_init(void)
 	omap_sdrc_init(NULL, NULL);
 	omap4_twl6030_hsmmc_init(mmc);
 	omap4_ehci_init();
+	usb_bind_phy("musb-hdrc.0.auto", 0, "omap-usb2.1.auto");
 	usb_musb_init(&musb_board_data);
 	omap4_panda_display_init();
 }

+ 2 - 0
arch/arm/mach-omap2/board-overo.c

@@ -36,6 +36,7 @@
 #include <linux/mtd/nand.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mmc/host.h>
+#include <linux/usb/phy.h>
 
 #include <linux/platform_data/mtd-nand-omap2.h>
 #include <linux/platform_data/spi-omap2-mcspi.h>
@@ -499,6 +500,7 @@ static void __init overo_init(void)
 				  mt46h32m32lf6_sdrc_params);
 	board_nand_init(overo_nand_partitions,
 			ARRAY_SIZE(overo_nand_partitions), NAND_CS, 0, NULL);
+	usb_bind_phy("musb-hdrc.0.auto", 0, "twl4030_usb");
 	usb_musb_init(NULL);
 	usbhs_init(&usbhs_bdata);
 	overo_spi_init();

+ 2 - 0
arch/arm/mach-omap2/board-rm680.c

@@ -18,6 +18,7 @@
 #include <linux/regulator/machine.h>
 #include <linux/regulator/consumer.h>
 #include <linux/platform_data/mtd-onenand-omap2.h>
+#include <linux/usb/phy.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
@@ -134,6 +135,7 @@ static void __init rm680_init(void)
 	sdrc_params = nokia_get_sdram_timings();
 	omap_sdrc_init(sdrc_params, sdrc_params);
 
+	usb_bind_phy("musb-hdrc.0.auto", 0, "twl4030_usb");
 	usb_musb_init(NULL);
 	rm680_peripherals_init();
 }

+ 2 - 0
arch/arm/mach-omap2/board-zoom-peripherals.c

@@ -20,6 +20,7 @@
 #include <linux/wl12xx.h>
 #include <linux/mmc/host.h>
 #include <linux/platform_data/gpio-omap.h>
+#include <linux/usb/phy.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -298,6 +299,7 @@ void __init zoom_peripherals_init(void)
 	omap_hsmmc_init(mmc);
 	omap_i2c_init();
 	platform_device_register(&omap_vwlan_device);
+	usb_bind_phy("musb-hdrc.0.auto", 0, "twl4030_usb");
 	usb_musb_init(NULL);
 	enable_board_wakeup_source();
 	omap_serial_init();

+ 45 - 0
arch/arm/mach-omap2/devices.c

@@ -20,6 +20,7 @@
 #include <linux/pinctrl/machine.h>
 #include <linux/platform_data/omap4-keypad.h>
 #include <linux/platform_data/omap_ocp2scp.h>
+#include <linux/usb/omap_control_usb.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/map.h>
@@ -254,6 +255,49 @@ static inline void omap_init_camera(void)
 #endif
 }
 
+#if IS_ENABLED(CONFIG_OMAP_CONTROL_USB)
+static struct omap_control_usb_platform_data omap4_control_usb_pdata = {
+	.type = 1,
+};
+
+struct resource omap4_control_usb_res[] = {
+	{
+		.name	= "control_dev_conf",
+		.start	= 0x4a002300,
+		.end	= 0x4a002303,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.name	= "otghs_control",
+		.start	= 0x4a00233c,
+		.end	= 0x4a00233f,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct platform_device omap4_control_usb = {
+	.name = "omap-control-usb",
+	.id = -1,
+	.dev = {
+		.platform_data = &omap4_control_usb_pdata,
+	},
+	.num_resources = 2,
+	.resource = omap4_control_usb_res,
+};
+
+static inline void __init omap_init_control_usb(void)
+{
+	if (!cpu_is_omap44xx())
+		return;
+
+	if (platform_device_register(&omap4_control_usb))
+		pr_err("Error registering omap_control_usb device\n");
+}
+
+#else
+static inline void omap_init_control_usb(void) { }
+#endif /* CONFIG_OMAP_CONTROL_USB */
+
 int __init omap4_keyboard_init(struct omap4_keypad_platform_data
 			*sdp4430_keypad_data, struct omap_board_data *bdata)
 {
@@ -721,6 +765,7 @@ static int __init omap2_init_devices(void)
 	omap_init_mbox();
 	/* If dtb is there, the devices will be created dynamically */
 	if (!of_have_populated_dt()) {
+		omap_init_control_usb();
 		omap_init_dmic();
 		omap_init_mcpdm();
 		omap_init_mcspi();

+ 0 - 13
arch/arm/mach-omap2/omap_hwmod_44xx_data.c

@@ -2702,13 +2702,6 @@ static struct resource omap44xx_usb_phy_and_pll_addrs[] = {
 		.end		= 0x4a0ae000,
 		.flags		= IORESOURCE_MEM,
 	},
-	{
-		/* XXX: Remove this once control module driver is in place */
-		.name		= "ctrl_dev",
-		.start		= 0x4a002300,
-		.end		= 0x4a002303,
-		.flags		= IORESOURCE_MEM,
-	},
 	{ }
 };
 
@@ -6156,12 +6149,6 @@ static struct omap_hwmod_addr_space omap44xx_usb_otg_hs_addrs[] = {
 		.pa_end		= 0x4a0ab7ff,
 		.flags		= ADDR_TYPE_RT
 	},
-	{
-		/* XXX: Remove this once control module driver is in place */
-		.pa_start	= 0x4a00233c,
-		.pa_end		= 0x4a00233f,
-		.flags		= ADDR_TYPE_RT
-	},
 	{ }
 };
 

+ 3 - 0
arch/arm/mach-omap2/usb-musb.c

@@ -85,6 +85,9 @@ void __init usb_musb_init(struct omap_musb_board_data *musb_board_data)
 	musb_plat.mode = board_data->mode;
 	musb_plat.extvbus = board_data->extvbus;
 
+	if (cpu_is_omap44xx())
+		musb_plat.has_mailbox = true;
+
 	if (soc_is_am35xx()) {
 		oh_name = "am35x_otg_hs";
 		name = "musb-am35x";

+ 1 - 0
drivers/base/power/qos.c

@@ -91,6 +91,7 @@ enum pm_qos_flags_status dev_pm_qos_flags(struct device *dev, s32 mask)
 
 	return ret;
 }
+EXPORT_SYMBOL_GPL(dev_pm_qos_flags);
 
 /**
  * __dev_pm_qos_read_value - Get PM QoS constraint for a given device.

+ 1 - 1
drivers/usb/c67x00/c67x00-ll-hpi.c

@@ -237,7 +237,7 @@ void c67x00_ll_hpi_disable_sofeop(struct c67x00_sie *sie)
 /* -------------------------------------------------------------------------- */
 /* Transactions */
 
-static inline u16 ll_recv_msg(struct c67x00_device *dev)
+static inline int ll_recv_msg(struct c67x00_device *dev)
 {
 	u16 res;
 

+ 1 - 1
drivers/usb/chipidea/ci13xxx_imx.h

@@ -19,7 +19,7 @@ struct usbmisc_usb_device {
 	struct device *dev; /* usb controller device */
 	int index;
 
-	int disable_oc:1; /* over current detect disabled */
+	unsigned int disable_oc:1; /* over current detect disabled */
 };
 
 int usbmisc_set_ops(const struct usbmisc_ops *ops);

+ 1 - 1
drivers/usb/chipidea/core.c

@@ -411,7 +411,7 @@ static int ci_hdrc_probe(struct platform_device *pdev)
 	}
 
 	base = devm_request_and_ioremap(dev, res);
-	if (!res) {
+	if (!base) {
 		dev_err(dev, "can't request and ioremap resource\n");
 		return -ENOMEM;
 	}

+ 1 - 0
drivers/usb/core/Makefile

@@ -7,6 +7,7 @@ ccflags-$(CONFIG_USB_DEBUG) := -DDEBUG
 usbcore-y := usb.o hub.o hcd.o urb.o message.o driver.o
 usbcore-y += config.o file.o buffer.o sysfs.o endpoint.o
 usbcore-y += devio.o notify.o generic.o quirks.o devices.o
+usbcore-y += port.o
 
 usbcore-$(CONFIG_PCI)		+= hcd-pci.o
 usbcore-$(CONFIG_ACPI)		+= usb-acpi.o

+ 10 - 3
drivers/usb/core/devices.c

@@ -316,17 +316,23 @@ static char *usb_dump_iad_descriptor(char *start, char *end,
  */
 static char *usb_dump_config_descriptor(char *start, char *end,
 				const struct usb_config_descriptor *desc,
-				int active)
+				int active, int speed)
 {
+	int mul;
+
 	if (start > end)
 		return start;
+	if (speed == USB_SPEED_SUPER)
+		mul = 8;
+	else
+		mul = 2;
 	start += sprintf(start, format_config,
 			 /* mark active/actual/current cfg. */
 			 active ? '*' : ' ',
 			 desc->bNumInterfaces,
 			 desc->bConfigurationValue,
 			 desc->bmAttributes,
-			 desc->bMaxPower * 2);
+			 desc->bMaxPower * mul);
 	return start;
 }
 
@@ -342,7 +348,8 @@ static char *usb_dump_config(int speed, char *start, char *end,
 	if (!config)
 		/* getting these some in 2.3.7; none in 2.3.6 */
 		return start + sprintf(start, "(null Cfg. desc.)\n");
-	start = usb_dump_config_descriptor(start, end, &config->desc, active);
+	start = usb_dump_config_descriptor(start, end, &config->desc, active,
+			speed);
 	for (i = 0; i < USB_MAXIADS; i++) {
 		if (config->intf_assoc[i] == NULL)
 			break;

+ 2 - 1
drivers/usb/core/devio.c

@@ -40,6 +40,7 @@
 #include <linux/signal.h>
 #include <linux/poll.h>
 #include <linux/module.h>
+#include <linux/string.h>
 #include <linux/usb.h>
 #include <linux/usbdevice_fs.h>
 #include <linux/usb/hcd.h>	/* for usbcore internals */
@@ -1077,7 +1078,7 @@ static int proc_getdriver(struct dev_state *ps, void __user *arg)
 	if (!intf || !intf->dev.driver)
 		ret = -ENODATA;
 	else {
-		strncpy(gd.driver, intf->dev.driver->name,
+		strlcpy(gd.driver, intf->dev.driver->name,
 				sizeof(gd.driver));
 		ret = (copy_to_user(arg, &gd, sizeof(gd)) ? -EFAULT : 0);
 	}

+ 1 - 1
drivers/usb/core/generic.c

@@ -100,7 +100,7 @@ int usb_choose_configuration(struct usb_device *udev)
 		 */
 
 		/* Rule out configs that draw too much bus current */
-		if (c->desc.bMaxPower * 2 > udev->bus_mA) {
+		if (usb_get_max_power(udev, c) > udev->bus_mA) {
 			insufficient_power++;
 			continue;
 		}

+ 4 - 1
drivers/usb/core/hcd.c

@@ -620,6 +620,10 @@ nongeneric:
 		status = hcd->driver->hub_control (hcd,
 			typeReq, wValue, wIndex,
 			tbuf, wLength);
+
+		if (typeReq == GetHubDescriptor)
+			usb_hub_adjust_deviceremovable(hcd->self.root_hub,
+				(struct usb_hub_descriptor *)tbuf);
 		break;
 error:
 		/* "protocol stall" on error */
@@ -2550,7 +2554,6 @@ int usb_add_hcd(struct usb_hcd *hcd,
 	}
 
 	/* starting here, usbcore will pay attention to this root hub */
-	rhdev->bus_mA = min(500u, hcd->power_budget);
 	if ((retval = register_root_hub(hcd)) != 0)
 		goto err_register_root_hub;
 

File diff suppressed because it is too large
+ 280 - 258
drivers/usb/core/hub.c


+ 122 - 0
drivers/usb/core/hub.h

@@ -0,0 +1,122 @@
+/*
+ * usb hub driver head file
+ *
+ * Copyright (C) 1999 Linus Torvalds
+ * Copyright (C) 1999 Johannes Erdfelt
+ * Copyright (C) 1999 Gregory P. Smith
+ * Copyright (C) 2001 Brad Hards (bhards@bigpond.net.au)
+ * Copyright (C) 2012 Intel Corp (tianyu.lan@intel.com)
+ *
+ *  move struct usb_hub to this file.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+#include <linux/usb.h>
+#include <linux/usb/ch11.h>
+#include <linux/usb/hcd.h>
+#include "usb.h"
+
+struct usb_hub {
+	struct device		*intfdev;	/* the "interface" device */
+	struct usb_device	*hdev;
+	struct kref		kref;
+	struct urb		*urb;		/* for interrupt polling pipe */
+
+	/* buffer for urb ... with extra space in case of babble */
+	u8			(*buffer)[8];
+	union {
+		struct usb_hub_status	hub;
+		struct usb_port_status	port;
+	}			*status;	/* buffer for status reports */
+	struct mutex		status_mutex;	/* for the status buffer */
+
+	int			error;		/* last reported error */
+	int			nerrors;	/* track consecutive errors */
+
+	struct list_head	event_list;	/* hubs w/data or errs ready */
+	unsigned long		event_bits[1];	/* status change bitmask */
+	unsigned long		change_bits[1];	/* ports with logical connect
+							status change */
+	unsigned long		busy_bits[1];	/* ports being reset or
+							resumed */
+	unsigned long		removed_bits[1]; /* ports with a "removed"
+							device present */
+	unsigned long		wakeup_bits[1];	/* ports that have signaled
+							remote wakeup */
+#if USB_MAXCHILDREN > 31 /* 8*sizeof(unsigned long) - 1 */
+#error event_bits[] is too short!
+#endif
+
+	struct usb_hub_descriptor *descriptor;	/* class descriptor */
+	struct usb_tt		tt;		/* Transaction Translator */
+
+	unsigned		mA_per_port;	/* current for each child */
+
+	unsigned		limited_power:1;
+	unsigned		quiescing:1;
+	unsigned		disconnected:1;
+
+	unsigned		quirk_check_port_auto_suspend:1;
+
+	unsigned		has_indicators:1;
+	u8			indicator[USB_MAXCHILDREN];
+	struct delayed_work	leds;
+	struct delayed_work	init_work;
+	struct usb_port		**ports;
+};
+
+/**
+ * struct usb port - kernel's representation of a usb port
+ * @child: usb device attatched to the port
+ * @dev: generic device interface
+ * @port_owner: port's owner
+ * @connect_type: port's connect type
+ * @portnum: port index num based one
+ * @power_is_on: port's power state
+ * @did_runtime_put: port has done pm_runtime_put().
+ */
+struct usb_port {
+	struct usb_device *child;
+	struct device dev;
+	struct dev_state *port_owner;
+	enum usb_port_connect_type connect_type;
+	u8 portnum;
+	unsigned power_is_on:1;
+	unsigned did_runtime_put:1;
+};
+
+#define to_usb_port(_dev) \
+	container_of(_dev, struct usb_port, dev)
+
+extern int usb_hub_create_port_device(struct usb_hub *hub,
+		int port1);
+extern void usb_hub_remove_port_device(struct usb_hub *hub,
+		int port1);
+extern int usb_hub_set_port_power(struct usb_device *hdev,
+		int port1, bool set);
+extern struct usb_hub *usb_hub_to_struct_hub(struct usb_device *hdev);
+extern int hub_port_debounce(struct usb_hub *hub, int port1,
+		bool must_be_connected);
+extern int usb_clear_port_feature(struct usb_device *hdev,
+		int port1, int feature);
+
+static inline int hub_port_debounce_be_connected(struct usb_hub *hub,
+		int port1)
+{
+	return hub_port_debounce(hub, port1, true);
+}
+
+static inline int hub_port_debounce_be_stable(struct usb_hub *hub,
+		int port1)
+{
+	return hub_port_debounce(hub, port1, false);
+}
+

+ 1 - 1
drivers/usb/core/message.c

@@ -1751,7 +1751,7 @@ free_interfaces:
 			}
 		}
 
-		i = dev->bus_mA - cp->desc.bMaxPower * 2;
+		i = dev->bus_mA - usb_get_max_power(dev, cp);
 		if (i < 0)
 			dev_warn(&dev->dev, "new config #%d exceeds power "
 					"limit by %dmA\n",

+ 202 - 0
drivers/usb/core/port.c

@@ -0,0 +1,202 @@
+/*
+ * usb port device code
+ *
+ * Copyright (C) 2012 Intel Corp
+ *
+ * Author: Lan Tianyu <tianyu.lan@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ */
+
+#include <linux/slab.h>
+#include <linux/pm_qos.h>
+
+#include "hub.h"
+
+static const struct attribute_group *port_dev_group[];
+
+static ssize_t show_port_connect_type(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+	struct usb_port *port_dev = to_usb_port(dev);
+	char *result;
+
+	switch (port_dev->connect_type) {
+	case USB_PORT_CONNECT_TYPE_HOT_PLUG:
+		result = "hotplug";
+		break;
+	case USB_PORT_CONNECT_TYPE_HARD_WIRED:
+		result = "hardwired";
+		break;
+	case USB_PORT_NOT_USED:
+		result = "not used";
+		break;
+	default:
+		result = "unknown";
+		break;
+	}
+
+	return sprintf(buf, "%s\n", result);
+}
+static DEVICE_ATTR(connect_type, S_IRUGO, show_port_connect_type,
+		NULL);
+
+static struct attribute *port_dev_attrs[] = {
+	&dev_attr_connect_type.attr,
+	NULL,
+};
+
+static struct attribute_group port_dev_attr_grp = {
+	.attrs = port_dev_attrs,
+};
+
+static const struct attribute_group *port_dev_group[] = {
+	&port_dev_attr_grp,
+	NULL,
+};
+
+static void usb_port_device_release(struct device *dev)
+{
+	struct usb_port *port_dev = to_usb_port(dev);
+
+	dev_pm_qos_hide_flags(dev);
+	kfree(port_dev);
+}
+
+#ifdef CONFIG_USB_SUSPEND
+static int usb_port_runtime_resume(struct device *dev)
+{
+	struct usb_port *port_dev = to_usb_port(dev);
+	struct usb_device *hdev = to_usb_device(dev->parent->parent);
+	struct usb_interface *intf = to_usb_interface(dev->parent);
+	struct usb_hub *hub = usb_hub_to_struct_hub(hdev);
+	int port1 = port_dev->portnum;
+	int retval;
+
+	if (!hub)
+		return -EINVAL;
+
+	usb_autopm_get_interface(intf);
+	set_bit(port1, hub->busy_bits);
+
+	retval = usb_hub_set_port_power(hdev, port1, true);
+	if (port_dev->child && !retval) {
+		/*
+		 * Wait for usb hub port to be reconnected in order to make
+		 * the resume procedure successful.
+		 */
+		retval = hub_port_debounce_be_connected(hub, port1);
+		if (retval < 0) {
+			dev_dbg(&port_dev->dev, "can't get reconnection after setting port  power on, status %d\n",
+					retval);
+			goto out;
+		}
+		usb_clear_port_feature(hdev, port1, USB_PORT_FEAT_C_ENABLE);
+
+		/* Set return value to 0 if debounce successful */
+		retval = 0;
+	}
+
+out:
+	clear_bit(port1, hub->busy_bits);
+	usb_autopm_put_interface(intf);
+	return retval;
+}
+
+static int usb_port_runtime_suspend(struct device *dev)
+{
+	struct usb_port *port_dev = to_usb_port(dev);
+	struct usb_device *hdev = to_usb_device(dev->parent->parent);
+	struct usb_interface *intf = to_usb_interface(dev->parent);
+	struct usb_hub *hub = usb_hub_to_struct_hub(hdev);
+	int port1 = port_dev->portnum;
+	int retval;
+
+	if (!hub)
+		return -EINVAL;
+
+	if (dev_pm_qos_flags(&port_dev->dev, PM_QOS_FLAG_NO_POWER_OFF)
+			== PM_QOS_FLAGS_ALL)
+		return -EAGAIN;
+
+	usb_autopm_get_interface(intf);
+	set_bit(port1, hub->busy_bits);
+	retval = usb_hub_set_port_power(hdev, port1, false);
+	usb_clear_port_feature(hdev, port1, USB_PORT_FEAT_C_CONNECTION);
+	usb_clear_port_feature(hdev, port1,	USB_PORT_FEAT_C_ENABLE);
+	clear_bit(port1, hub->busy_bits);
+	usb_autopm_put_interface(intf);
+	return retval;
+}
+#endif
+
+static const struct dev_pm_ops usb_port_pm_ops = {
+#ifdef CONFIG_USB_SUSPEND
+	.runtime_suspend =	usb_port_runtime_suspend,
+	.runtime_resume =	usb_port_runtime_resume,
+	.runtime_idle =		pm_generic_runtime_idle,
+#endif
+};
+
+struct device_type usb_port_device_type = {
+	.name =		"usb_port",
+	.release =	usb_port_device_release,
+	.pm =		&usb_port_pm_ops,
+};
+
+int usb_hub_create_port_device(struct usb_hub *hub, int port1)
+{
+	struct usb_port *port_dev = NULL;
+	int retval;
+
+	port_dev = kzalloc(sizeof(*port_dev), GFP_KERNEL);
+	if (!port_dev) {
+		retval = -ENOMEM;
+		goto exit;
+	}
+
+	hub->ports[port1 - 1] = port_dev;
+	port_dev->portnum = port1;
+	port_dev->power_is_on = true;
+	port_dev->dev.parent = hub->intfdev;
+	port_dev->dev.groups = port_dev_group;
+	port_dev->dev.type = &usb_port_device_type;
+	dev_set_name(&port_dev->dev, "port%d", port1);
+
+	retval = device_register(&port_dev->dev);
+	if (retval)
+		goto error_register;
+
+	pm_runtime_set_active(&port_dev->dev);
+
+	/* It would be dangerous if user space couldn't
+	 * prevent usb device from being powered off. So don't
+	 * enable port runtime pm if failed to expose port's pm qos.
+	 */
+	if (!dev_pm_qos_expose_flags(&port_dev->dev,
+			PM_QOS_FLAG_NO_POWER_OFF))
+		pm_runtime_enable(&port_dev->dev);
+
+	device_enable_async_suspend(&port_dev->dev);
+	return 0;
+
+error_register:
+	put_device(&port_dev->dev);
+exit:
+	return retval;
+}
+
+void usb_hub_remove_port_device(struct usb_hub *hub,
+				       int port1)
+{
+	device_unregister(&hub->ports[port1 - 1]->dev);
+}
+

+ 22 - 9
drivers/usb/core/sysfs.c

@@ -17,7 +17,7 @@
 #include "usb.h"
 
 /* Active configuration fields */
-#define usb_actconfig_show(field, multiplier, format_string)		\
+#define usb_actconfig_show(field, format_string)			\
 static ssize_t  show_##field(struct device *dev,			\
 		struct device_attribute *attr, char *buf)		\
 {									\
@@ -28,18 +28,31 @@ static ssize_t  show_##field(struct device *dev,			\
 	actconfig = udev->actconfig;					\
 	if (actconfig)							\
 		return sprintf(buf, format_string,			\
-				actconfig->desc.field * multiplier);	\
+				actconfig->desc.field);			\
 	else								\
 		return 0;						\
 }									\
 
-#define usb_actconfig_attr(field, multiplier, format_string)		\
-usb_actconfig_show(field, multiplier, format_string)			\
-static DEVICE_ATTR(field, S_IRUGO, show_##field, NULL);
+#define usb_actconfig_attr(field, format_string)		\
+	usb_actconfig_show(field, format_string)		\
+	static DEVICE_ATTR(field, S_IRUGO, show_##field, NULL);
+
+usb_actconfig_attr(bNumInterfaces, "%2d\n")
+usb_actconfig_attr(bmAttributes, "%2x\n")
 
-usb_actconfig_attr(bNumInterfaces, 1, "%2d\n")
-usb_actconfig_attr(bmAttributes, 1, "%2x\n")
-usb_actconfig_attr(bMaxPower, 2, "%3dmA\n")
+static ssize_t show_bMaxPower(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct usb_device *udev;
+	struct usb_host_config *actconfig;
+
+	udev = to_usb_device(dev);
+	actconfig = udev->actconfig;
+	if (!actconfig)
+		return 0;
+	return sprintf(buf, "%dmA\n", usb_get_max_power(udev, actconfig));
+}
+static DEVICE_ATTR(bMaxPower, S_IRUGO, show_bMaxPower, NULL);
 
 static ssize_t show_configuration_string(struct device *dev,
 		struct device_attribute *attr, char *buf)
@@ -56,7 +69,7 @@ static ssize_t show_configuration_string(struct device *dev,
 static DEVICE_ATTR(configuration, S_IRUGO, show_configuration_string, NULL);
 
 /* configuration value is always present, and r/w */
-usb_actconfig_show(bConfigurationValue, 1, "%u\n");
+usb_actconfig_show(bConfigurationValue, "%u\n");
 
 static ssize_t
 set_bConfigurationValue(struct device *dev, struct device_attribute *attr,

+ 12 - 0
drivers/usb/core/usb.h

@@ -1,6 +1,7 @@
 #include <linux/pm.h>
 #include <linux/acpi.h>
 
+struct usb_hub_descriptor;
 struct dev_state;
 
 /* Functions local to drivers/usb/core/ */
@@ -38,6 +39,15 @@ extern char *usb_cache_string(struct usb_device *udev, int index);
 extern int usb_set_configuration(struct usb_device *dev, int configuration);
 extern int usb_choose_configuration(struct usb_device *udev);
 
+static inline unsigned usb_get_max_power(struct usb_device *udev,
+		struct usb_host_config *c)
+{
+	/* SuperSpeed power is in 8 mA units; others are in 2 mA units */
+	unsigned mul = (udev->speed == USB_SPEED_SUPER ? 8 : 2);
+
+	return c->desc.bMaxPower * mul;
+}
+
 extern void usb_kick_khubd(struct usb_device *dev);
 extern int usb_match_one_id_intf(struct usb_device *dev,
 				 struct usb_host_interface *intf,
@@ -173,6 +183,8 @@ extern enum usb_port_connect_type
 	usb_get_hub_port_connect_type(struct usb_device *hdev, int port1);
 extern void usb_set_hub_port_connect_type(struct usb_device *hdev, int port1,
 	enum usb_port_connect_type type);
+extern void usb_hub_adjust_deviceremovable(struct usb_device *hdev,
+		struct usb_hub_descriptor *desc);
 
 #ifdef CONFIG_ACPI
 extern int usb_acpi_register(void);

+ 30 - 1
drivers/usb/dwc3/Kconfig

@@ -1,6 +1,6 @@
 config USB_DWC3
 	tristate "DesignWare USB3 DRD Core Support"
-	depends on (USB && USB_GADGET)
+	depends on (USB || USB_GADGET) && GENERIC_HARDIRQS
 	select USB_OTG_UTILS
 	select USB_XHCI_PLATFORM if USB_SUPPORT && USB_XHCI_HCD
 	help
@@ -12,6 +12,35 @@ config USB_DWC3
 
 if USB_DWC3
 
+choice
+	bool "DWC3 Mode Selection"
+	default USB_DWC3_DUAL_ROLE if (USB && USB_GADGET)
+	default USB_DWC3_HOST if (USB && !USB_GADGET)
+	default USB_DWC3_GADGET if (!USB && USB_GADGET)
+
+config USB_DWC3_HOST
+	bool "Host only mode"
+	depends on USB
+	help
+	  Select this when you want to use DWC3 in host mode only,
+	  thereby the gadget feature will be regressed.
+
+config USB_DWC3_GADGET
+	bool "Gadget only mode"
+	depends on USB_GADGET
+	help
+	  Select this when you want to use DWC3 in gadget mode only,
+	  thereby the host feature will be regressed.
+
+config USB_DWC3_DUAL_ROLE
+	bool "Dual Role mode"
+	depends on (USB && USB_GADGET)
+	help
+	  This is the default mode of working of DWC3 controller where
+	  both host and gadget features are enabled.
+
+endchoice
+
 config USB_DWC3_DEBUG
 	bool "Enable Debugging Messages"
 	help

+ 8 - 2
drivers/usb/dwc3/Makefile

@@ -4,8 +4,14 @@ ccflags-$(CONFIG_USB_DWC3_VERBOSE)	+= -DVERBOSE_DEBUG
 obj-$(CONFIG_USB_DWC3)			+= dwc3.o
 
 dwc3-y					:= core.o
-dwc3-y					+= host.o
-dwc3-y					+= gadget.o ep0.o
+
+ifneq ($(filter y,$(CONFIG_USB_DWC3_HOST) $(CONFIG_USB_DWC3_DUAL_ROLE)),)
+	dwc3-y				+= host.o
+endif
+
+ifneq ($(filter y,$(CONFIG_USB_DWC3_GADGET) $(CONFIG_USB_DWC3_DUAL_ROLE)),)
+	dwc3-y				+= gadget.o ep0.o
+endif
 
 ifneq ($(CONFIG_DEBUG_FS),)
 	dwc3-y				+= debugfs.o

+ 25 - 6
drivers/usb/dwc3/core.c

@@ -420,18 +420,27 @@ static int dwc3_probe(struct platform_device *pdev)
 		return -ENOMEM;
 	}
 
-	dwc->usb2_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
+	if (node) {
+		dwc->usb2_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 0);
+		dwc->usb3_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 1);
+	} else {
+		dwc->usb2_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
+		dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3);
+	}
+
 	if (IS_ERR_OR_NULL(dwc->usb2_phy)) {
 		dev_err(dev, "no usb2 phy configured\n");
 		return -EPROBE_DEFER;
 	}
 
-	dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3);
 	if (IS_ERR_OR_NULL(dwc->usb3_phy)) {
 		dev_err(dev, "no usb3 phy configured\n");
 		return -EPROBE_DEFER;
 	}
 
+	usb_phy_set_suspend(dwc->usb2_phy, 0);
+	usb_phy_set_suspend(dwc->usb3_phy, 0);
+
 	spin_lock_init(&dwc->lock);
 	platform_set_drvdata(pdev, dwc);
 
@@ -450,8 +459,7 @@ static int dwc3_probe(struct platform_device *pdev)
 	else
 		dwc->maximum_speed = DWC3_DCFG_SUPERSPEED;
 
-	if (of_get_property(node, "tx-fifo-resize", NULL))
-		dwc->needs_fifo_resize = true;
+	dwc->needs_fifo_resize = of_property_read_bool(node, "tx-fifo-resize");
 
 	pm_runtime_enable(dev);
 	pm_runtime_get_sync(dev);
@@ -550,9 +558,9 @@ err0:
 static int dwc3_remove(struct platform_device *pdev)
 {
 	struct dwc3	*dwc = platform_get_drvdata(pdev);
-	struct resource	*res;
 
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	usb_phy_set_suspend(dwc->usb2_phy, 1);
+	usb_phy_set_suspend(dwc->usb3_phy, 1);
 
 	pm_runtime_put(&pdev->dev);
 	pm_runtime_disable(&pdev->dev);
@@ -580,11 +588,22 @@ static int dwc3_remove(struct platform_device *pdev)
 	return 0;
 }
 
+#ifdef CONFIG_OF
+static const struct of_device_id of_dwc3_match[] = {
+	{
+		.compatible = "synopsys,dwc3"
+	},
+	{ },
+};
+MODULE_DEVICE_TABLE(of, of_dwc3_match);
+#endif
+
 static struct platform_driver dwc3_driver = {
 	.probe		= dwc3_probe,
 	.remove		= dwc3_remove,
 	.driver		= {
 		.name	= "dwc3",
+		.of_match_table	= of_match_ptr(of_dwc3_match),
 	},
 };
 

+ 20 - 4
drivers/usb/dwc3/core.h

@@ -55,7 +55,9 @@
 #define DWC3_ENDPOINTS_NUM	32
 #define DWC3_XHCI_RESOURCES_NUM	2
 
-#define DWC3_EVENT_BUFFERS_SIZE	PAGE_SIZE
+#define DWC3_EVENT_SIZE		4	/* bytes */
+#define DWC3_EVENT_MAX_NUM	64	/* 2 events/endpoint */
+#define DWC3_EVENT_BUFFERS_SIZE	(DWC3_EVENT_SIZE * DWC3_EVENT_MAX_NUM)
 #define DWC3_EVENT_TYPE_MASK	0xfe
 
 #define DWC3_EVENT_TYPE_DEV	0
@@ -405,7 +407,6 @@ struct dwc3_event_buffer {
  * @number: endpoint number (1 - 15)
  * @type: set to bmAttributes & USB_ENDPOINT_XFERTYPE_MASK
  * @resource_index: Resource transfer index
- * @current_uf: Current uf received through last event parameter
  * @interval: the intervall on which the ISOC transfer is started
  * @name: a human readable name e.g. ep1out-bulk
  * @direction: true for TX, false for RX
@@ -439,7 +440,6 @@ struct dwc3_ep {
 	u8			number;
 	u8			type;
 	u8			resource_index;
-	u16			current_uf;
 	u32			interval;
 
 	char			name[20];
@@ -581,6 +581,7 @@ struct dwc3_request {
 	struct usb_request	request;
 	struct list_head	list;
 	struct dwc3_ep		*dep;
+	u32			start_slot;
 
 	u8			epnum;
 	struct dwc3_trb		*trb;
@@ -721,6 +722,7 @@ struct dwc3 {
 
 	struct dwc3_hwparams	hwparams;
 	struct dentry		*root;
+	struct debugfs_regset32	*regset;
 
 	u8			test_mode;
 	u8			test_mode_nr;
@@ -862,10 +864,24 @@ union dwc3_event {
 void dwc3_set_mode(struct dwc3 *dwc, u32 mode);
 int dwc3_gadget_resize_tx_fifos(struct dwc3 *dwc);
 
+#if IS_ENABLED(CONFIG_USB_DWC3_HOST) || IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE)
 int dwc3_host_init(struct dwc3 *dwc);
 void dwc3_host_exit(struct dwc3 *dwc);
-
+#else
+static inline int dwc3_host_init(struct dwc3 *dwc)
+{ return 0; }
+static inline void dwc3_host_exit(struct dwc3 *dwc)
+{ }
+#endif
+
+#if IS_ENABLED(CONFIG_USB_DWC3_GADGET) || IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE)
 int dwc3_gadget_init(struct dwc3 *dwc);
 void dwc3_gadget_exit(struct dwc3 *dwc);
+#else
+static inline int dwc3_gadget_init(struct dwc3 *dwc)
+{ return 0; }
+static inline void dwc3_gadget_exit(struct dwc3 *dwc)
+{ }
+#endif
 
 #endif /* __DRIVERS_USB_DWC3_CORE_H */

+ 14 - 24
drivers/usb/dwc3/debugfs.c

@@ -59,7 +59,7 @@
 	.offset	= DWC3_ ##nm - DWC3_GLOBALS_REGS_START,	\
 }
 
-static const struct debugfs_reg32 dwc3_regs[] = {
+static struct debugfs_reg32 dwc3_regs[] = {
 	dump_register(GSBUSCFG0),
 	dump_register(GSBUSCFG1),
 	dump_register(GTXTHRCFG),
@@ -376,27 +376,6 @@ static const struct debugfs_reg32 dwc3_regs[] = {
 	dump_register(OSTS),
 };
 
-static int dwc3_regdump_show(struct seq_file *s, void *unused)
-{
-	struct dwc3		*dwc = s->private;
-
-	seq_printf(s, "DesignWare USB3 Core Register Dump\n");
-	debugfs_print_regs32(s, dwc3_regs, ARRAY_SIZE(dwc3_regs),
-			     dwc->regs, "");
-	return 0;
-}
-
-static int dwc3_regdump_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, dwc3_regdump_show, inode->i_private);
-}
-
-static const struct file_operations dwc3_regdump_fops = {
-	.open			= dwc3_regdump_open,
-	.read			= seq_read,
-	.release		= single_release,
-};
-
 static int dwc3_mode_show(struct seq_file *s, void *unused)
 {
 	struct dwc3		*dwc = s->private;
@@ -666,13 +645,23 @@ int dwc3_debugfs_init(struct dwc3 *dwc)
 
 	dwc->root = root;
 
-	file = debugfs_create_file("regdump", S_IRUGO, root, dwc,
-			&dwc3_regdump_fops);
+	dwc->regset = kzalloc(sizeof(*dwc->regset), GFP_KERNEL);
+	if (!dwc->regset) {
+		ret = -ENOMEM;
+		goto err1;
+	}
+
+	dwc->regset->regs = dwc3_regs;
+	dwc->regset->nregs = ARRAY_SIZE(dwc3_regs);
+	dwc->regset->base = dwc->regs;
+
+	file = debugfs_create_regset32("regdump", S_IRUGO, root, dwc->regset);
 	if (!file) {
 		ret = -ENOMEM;
 		goto err1;
 	}
 
+#if IS_ENABLED(CONFIG_USB_DWC3_GADGET)
 	file = debugfs_create_file("mode", S_IRUGO | S_IWUSR, root,
 			dwc, &dwc3_mode_fops);
 	if (!file) {
@@ -693,6 +682,7 @@ int dwc3_debugfs_init(struct dwc3 *dwc)
 		ret = -ENOMEM;
 		goto err1;
 	}
+#endif
 
 	return 0;
 

+ 26 - 31
drivers/usb/dwc3/dwc3-exynos.c

@@ -42,7 +42,7 @@ static int dwc3_exynos_register_phys(struct dwc3_exynos *exynos)
 
 	memset(&pdata, 0x00, sizeof(pdata));
 
-	pdev = platform_device_alloc("nop_usb_xceiv", 0);
+	pdev = platform_device_alloc("nop_usb_xceiv", PLATFORM_DEVID_AUTO);
 	if (!pdev)
 		return -ENOMEM;
 
@@ -53,7 +53,7 @@ static int dwc3_exynos_register_phys(struct dwc3_exynos *exynos)
 	if (ret)
 		goto err1;
 
-	pdev = platform_device_alloc("nop_usb_xceiv", 1);
+	pdev = platform_device_alloc("nop_usb_xceiv", PLATFORM_DEVID_AUTO);
 	if (!pdev) {
 		ret = -ENOMEM;
 		goto err1;
@@ -95,13 +95,14 @@ static int dwc3_exynos_probe(struct platform_device *pdev)
 	struct platform_device	*dwc3;
 	struct dwc3_exynos	*exynos;
 	struct clk		*clk;
+	struct device		*dev = &pdev->dev;
 
 	int			ret = -ENOMEM;
 
-	exynos = kzalloc(sizeof(*exynos), GFP_KERNEL);
+	exynos = devm_kzalloc(dev, sizeof(*exynos), GFP_KERNEL);
 	if (!exynos) {
-		dev_err(&pdev->dev, "not enough memory\n");
-		goto err0;
+		dev_err(dev, "not enough memory\n");
+		return -ENOMEM;
 	}
 
 	/*
@@ -116,30 +117,30 @@ static int dwc3_exynos_probe(struct platform_device *pdev)
 
 	ret = dwc3_exynos_register_phys(exynos);
 	if (ret) {
-		dev_err(&pdev->dev, "couldn't register PHYs\n");
-		goto err1;
+		dev_err(dev, "couldn't register PHYs\n");
+		return ret;
 	}
 
 	dwc3 = platform_device_alloc("dwc3", PLATFORM_DEVID_AUTO);
 	if (!dwc3) {
-		dev_err(&pdev->dev, "couldn't allocate dwc3 device\n");
-		goto err1;
+		dev_err(dev, "couldn't allocate dwc3 device\n");
+		return -ENOMEM;
 	}
 
-	clk = clk_get(&pdev->dev, "usbdrd30");
+	clk = devm_clk_get(dev, "usbdrd30");
 	if (IS_ERR(clk)) {
-		dev_err(&pdev->dev, "couldn't get clock\n");
+		dev_err(dev, "couldn't get clock\n");
 		ret = -EINVAL;
-		goto err3;
+		goto err1;
 	}
 
-	dma_set_coherent_mask(&dwc3->dev, pdev->dev.coherent_dma_mask);
+	dma_set_coherent_mask(&dwc3->dev, dev->coherent_dma_mask);
 
-	dwc3->dev.parent = &pdev->dev;
-	dwc3->dev.dma_mask = pdev->dev.dma_mask;
-	dwc3->dev.dma_parms = pdev->dev.dma_parms;
+	dwc3->dev.parent = dev;
+	dwc3->dev.dma_mask = dev->dma_mask;
+	dwc3->dev.dma_parms = dev->dma_parms;
 	exynos->dwc3	= dwc3;
-	exynos->dev	= &pdev->dev;
+	exynos->dev	= dev;
 	exynos->clk	= clk;
 
 	clk_enable(exynos->clk);
@@ -147,26 +148,23 @@ static int dwc3_exynos_probe(struct platform_device *pdev)
 	ret = platform_device_add_resources(dwc3, pdev->resource,
 			pdev->num_resources);
 	if (ret) {
-		dev_err(&pdev->dev, "couldn't add resources to dwc3 device\n");
-		goto err4;
+		dev_err(dev, "couldn't add resources to dwc3 device\n");
+		goto err2;
 	}
 
 	ret = platform_device_add(dwc3);
 	if (ret) {
-		dev_err(&pdev->dev, "failed to register dwc3 device\n");
-		goto err4;
+		dev_err(dev, "failed to register dwc3 device\n");
+		goto err2;
 	}
 
 	return 0;
 
-err4:
+err2:
 	clk_disable(clk);
-	clk_put(clk);
-err3:
-	platform_device_put(dwc3);
 err1:
-	kfree(exynos);
-err0:
+	platform_device_put(dwc3);
+
 	return ret;
 }
 
@@ -179,16 +177,13 @@ static int dwc3_exynos_remove(struct platform_device *pdev)
 	platform_device_unregister(exynos->usb3_phy);
 
 	clk_disable(exynos->clk);
-	clk_put(exynos->clk);
-
-	kfree(exynos);
 
 	return 0;
 }
 
 #ifdef CONFIG_OF
 static const struct of_device_id exynos_dwc3_match[] = {
-	{ .compatible = "samsung,exynos-dwc3" },
+	{ .compatible = "samsung,exynos5250-dwusb3" },
 	{},
 };
 MODULE_DEVICE_TABLE(of, exynos_dwc3_match);

+ 93 - 59
drivers/usb/dwc3/dwc3-omap.c

@@ -43,10 +43,13 @@
 #include <linux/spinlock.h>
 #include <linux/platform_device.h>
 #include <linux/platform_data/dwc3-omap.h>
+#include <linux/usb/dwc3-omap.h>
+#include <linux/pm_runtime.h>
 #include <linux/dma-mapping.h>
 #include <linux/ioport.h>
 #include <linux/io.h>
 #include <linux/of.h>
+#include <linux/of_platform.h>
 
 #include <linux/usb/otg.h>
 #include <linux/usb/nop-usb-xceiv.h>
@@ -78,23 +81,6 @@
 
 /* SYSCONFIG REGISTER */
 #define USBOTGSS_SYSCONFIG_DMADISABLE		(1 << 16)
-#define USBOTGSS_SYSCONFIG_STANDBYMODE(x)	((x) << 4)
-
-#define USBOTGSS_STANDBYMODE_FORCE_STANDBY	0
-#define USBOTGSS_STANDBYMODE_NO_STANDBY		1
-#define USBOTGSS_STANDBYMODE_SMART_STANDBY	2
-#define USBOTGSS_STANDBYMODE_SMART_WAKEUP	3
-
-#define USBOTGSS_STANDBYMODE_MASK		(0x03 << 4)
-
-#define USBOTGSS_SYSCONFIG_IDLEMODE(x)		((x) << 2)
-
-#define USBOTGSS_IDLEMODE_FORCE_IDLE		0
-#define USBOTGSS_IDLEMODE_NO_IDLE		1
-#define USBOTGSS_IDLEMODE_SMART_IDLE		2
-#define USBOTGSS_IDLEMODE_SMART_WAKEUP		3
-
-#define USBOTGSS_IDLEMODE_MASK			(0x03 << 2)
 
 /* IRQ_EOI REGISTER */
 #define USBOTGSS_IRQ_EOI_LINE_NUMBER		(1 << 0)
@@ -133,7 +119,6 @@ struct dwc3_omap {
 	/* device lock */
 	spinlock_t		lock;
 
-	struct platform_device	*dwc3;
 	struct platform_device	*usb2_phy;
 	struct platform_device	*usb3_phy;
 	struct device		*dev;
@@ -147,6 +132,8 @@ struct dwc3_omap {
 	u32			dma_status:1;
 };
 
+struct dwc3_omap		*_omap;
+
 static inline u32 dwc3_omap_readl(void __iomem *base, u32 offset)
 {
 	return readl(base + offset);
@@ -157,6 +144,57 @@ static inline void dwc3_omap_writel(void __iomem *base, u32 offset, u32 value)
 	writel(value, base + offset);
 }
 
+void dwc3_omap_mailbox(enum omap_dwc3_vbus_id_status status)
+{
+	u32			val;
+	struct dwc3_omap	*omap = _omap;
+
+	switch (status) {
+	case OMAP_DWC3_ID_GROUND:
+		dev_dbg(omap->dev, "ID GND\n");
+
+		val = dwc3_omap_readl(omap->base, USBOTGSS_UTMI_OTG_STATUS);
+		val &= ~(USBOTGSS_UTMI_OTG_STATUS_IDDIG
+				| USBOTGSS_UTMI_OTG_STATUS_VBUSVALID
+				| USBOTGSS_UTMI_OTG_STATUS_SESSEND);
+		val |= USBOTGSS_UTMI_OTG_STATUS_SESSVALID
+				| USBOTGSS_UTMI_OTG_STATUS_POWERPRESENT;
+		dwc3_omap_writel(omap->base, USBOTGSS_UTMI_OTG_STATUS, val);
+		break;
+
+	case OMAP_DWC3_VBUS_VALID:
+		dev_dbg(omap->dev, "VBUS Connect\n");
+
+		val = dwc3_omap_readl(omap->base, USBOTGSS_UTMI_OTG_STATUS);
+		val &= ~USBOTGSS_UTMI_OTG_STATUS_SESSEND;
+		val |= USBOTGSS_UTMI_OTG_STATUS_IDDIG
+				| USBOTGSS_UTMI_OTG_STATUS_VBUSVALID
+				| USBOTGSS_UTMI_OTG_STATUS_SESSVALID
+				| USBOTGSS_UTMI_OTG_STATUS_POWERPRESENT;
+		dwc3_omap_writel(omap->base, USBOTGSS_UTMI_OTG_STATUS, val);
+		break;
+
+	case OMAP_DWC3_ID_FLOAT:
+	case OMAP_DWC3_VBUS_OFF:
+		dev_dbg(omap->dev, "VBUS Disconnect\n");
+
+		val = dwc3_omap_readl(omap->base, USBOTGSS_UTMI_OTG_STATUS);
+		val &= ~(USBOTGSS_UTMI_OTG_STATUS_SESSVALID
+				| USBOTGSS_UTMI_OTG_STATUS_VBUSVALID
+				| USBOTGSS_UTMI_OTG_STATUS_POWERPRESENT);
+		val |= USBOTGSS_UTMI_OTG_STATUS_SESSEND
+				| USBOTGSS_UTMI_OTG_STATUS_IDDIG;
+		dwc3_omap_writel(omap->base, USBOTGSS_UTMI_OTG_STATUS, val);
+		break;
+
+	default:
+		dev_dbg(omap->dev, "ID float\n");
+	}
+
+	return;
+}
+EXPORT_SYMBOL_GPL(dwc3_omap_mailbox);
+
 static int dwc3_omap_register_phys(struct dwc3_omap *omap)
 {
 	struct nop_usb_xceiv_platform_data pdata;
@@ -165,7 +203,7 @@ static int dwc3_omap_register_phys(struct dwc3_omap *omap)
 
 	memset(&pdata, 0x00, sizeof(pdata));
 
-	pdev = platform_device_alloc("nop_usb_xceiv", 0);
+	pdev = platform_device_alloc("nop_usb_xceiv", PLATFORM_DEVID_AUTO);
 	if (!pdev)
 		return -ENOMEM;
 
@@ -176,7 +214,7 @@ static int dwc3_omap_register_phys(struct dwc3_omap *omap)
 	if (ret)
 		goto err1;
 
-	pdev = platform_device_alloc("nop_usb_xceiv", 1);
+	pdev = platform_device_alloc("nop_usb_xceiv", PLATFORM_DEVID_AUTO);
 	if (!pdev) {
 		ret = -ENOMEM;
 		goto err1;
@@ -262,12 +300,20 @@ static irqreturn_t dwc3_omap_interrupt(int irq, void *_omap)
 	return IRQ_HANDLED;
 }
 
+static int dwc3_omap_remove_core(struct device *dev, void *c)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+
+	platform_device_unregister(pdev);
+
+	return 0;
+}
+
 static int dwc3_omap_probe(struct platform_device *pdev)
 {
 	struct dwc3_omap_data	*pdata = pdev->dev.platform_data;
 	struct device_node	*node = pdev->dev.of_node;
 
-	struct platform_device	*dwc3;
 	struct dwc3_omap	*omap;
 	struct resource		*res;
 	struct device		*dev = &pdev->dev;
@@ -314,30 +360,32 @@ static int dwc3_omap_probe(struct platform_device *pdev)
 		return ret;
 	}
 
-	dwc3 = platform_device_alloc("dwc3", PLATFORM_DEVID_AUTO);
-	if (!dwc3) {
-		dev_err(dev, "couldn't allocate dwc3 device\n");
-		return -ENOMEM;
-	}
-
 	context = devm_kzalloc(dev, resource_size(res), GFP_KERNEL);
 	if (!context) {
 		dev_err(dev, "couldn't allocate dwc3 context memory\n");
-		goto err2;
+		return -ENOMEM;
 	}
 
 	spin_lock_init(&omap->lock);
-	dma_set_coherent_mask(&dwc3->dev, dev->coherent_dma_mask);
 
-	dwc3->dev.parent = dev;
-	dwc3->dev.dma_mask = dev->dma_mask;
-	dwc3->dev.dma_parms = dev->dma_parms;
 	omap->resource_size = resource_size(res);
 	omap->context	= context;
 	omap->dev	= dev;
 	omap->irq	= irq;
 	omap->base	= base;
-	omap->dwc3	= dwc3;
+
+	/*
+	 * REVISIT if we ever have two instances of the wrapper, we will be
+	 * in big trouble
+	 */
+	_omap	= omap;
+
+	pm_runtime_enable(dev);
+	ret = pm_runtime_get_sync(dev);
+	if (ret < 0) {
+		dev_err(dev, "get_sync failed with err %d\n", ret);
+		return ret;
+	}
 
 	reg = dwc3_omap_readl(omap->base, USBOTGSS_UTMI_OTG_STATUS);
 
@@ -368,21 +416,12 @@ static int dwc3_omap_probe(struct platform_device *pdev)
 	reg = dwc3_omap_readl(omap->base, USBOTGSS_SYSCONFIG);
 	omap->dma_status = !!(reg & USBOTGSS_SYSCONFIG_DMADISABLE);
 
-	/* Set No-Idle and No-Standby */
-	reg &= ~(USBOTGSS_STANDBYMODE_MASK
-			| USBOTGSS_IDLEMODE_MASK);
-
-	reg |= (USBOTGSS_SYSCONFIG_STANDBYMODE(USBOTGSS_STANDBYMODE_NO_STANDBY)
-		| USBOTGSS_SYSCONFIG_IDLEMODE(USBOTGSS_IDLEMODE_NO_IDLE));
-
-	dwc3_omap_writel(omap->base, USBOTGSS_SYSCONFIG, reg);
-
 	ret = devm_request_irq(dev, omap->irq, dwc3_omap_interrupt, 0,
 			"dwc3-omap", omap);
 	if (ret) {
 		dev_err(dev, "failed to request IRQ #%d --> %d\n",
 				omap->irq, ret);
-		goto err2;
+		return ret;
 	}
 
 	/* enable all IRQs */
@@ -401,33 +440,28 @@ static int dwc3_omap_probe(struct platform_device *pdev)
 
 	dwc3_omap_writel(omap->base, USBOTGSS_IRQENABLE_SET_1, reg);
 
-	ret = platform_device_add_resources(dwc3, pdev->resource,
-			pdev->num_resources);
-	if (ret) {
-		dev_err(dev, "couldn't add resources to dwc3 device\n");
-		goto err2;
-	}
-
-	ret = platform_device_add(dwc3);
-	if (ret) {
-		dev_err(dev, "failed to register dwc3 device\n");
-		goto err2;
+	if (node) {
+		ret = of_platform_populate(node, NULL, NULL, dev);
+		if (ret) {
+			dev_err(&pdev->dev,
+				"failed to add create dwc3 core\n");
+			return ret;
+		}
 	}
 
 	return 0;
-
-err2:
-	platform_device_put(dwc3);
-	return ret;
 }
 
 static int dwc3_omap_remove(struct platform_device *pdev)
 {
 	struct dwc3_omap	*omap = platform_get_drvdata(pdev);
 
-	platform_device_unregister(omap->dwc3);
 	platform_device_unregister(omap->usb2_phy);
 	platform_device_unregister(omap->usb3_phy);
+	pm_runtime_put_sync(&pdev->dev);
+	pm_runtime_disable(&pdev->dev);
+	device_for_each_child(&pdev->dev, NULL, dwc3_omap_remove_core);
+
 	return 0;
 }
 

+ 179 - 113
drivers/usb/dwc3/gadget.c

@@ -241,21 +241,23 @@ void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req,
 		int status)
 {
 	struct dwc3			*dwc = dep->dwc;
+	int				i;
 
 	if (req->queued) {
-		if (req->request.num_mapped_sgs)
-			dep->busy_slot += req->request.num_mapped_sgs;
-		else
+		i = 0;
+		do {
 			dep->busy_slot++;
-
-		/*
-		 * Skip LINK TRB. We can't use req->trb and check for
-		 * DWC3_TRBCTL_LINK_TRB because it points the TRB we just
-		 * completed (not the LINK TRB).
-		 */
-		if (((dep->busy_slot & DWC3_TRB_MASK) == DWC3_TRB_NUM - 1) &&
+			/*
+			 * Skip LINK TRB. We can't use req->trb and check for
+			 * DWC3_TRBCTL_LINK_TRB because it points the TRB we
+			 * just completed (not the LINK TRB).
+			 */
+			if (((dep->busy_slot & DWC3_TRB_MASK) ==
+				DWC3_TRB_NUM- 1) &&
 				usb_endpoint_xfer_isoc(dep->endpoint.desc))
-			dep->busy_slot++;
+				dep->busy_slot++;
+		} while(++i < req->request.num_mapped_sgs);
+		req->queued = false;
 	}
 	list_del(&req->list);
 	req->trb = NULL;
@@ -749,33 +751,32 @@ static void dwc3_gadget_ep_free_request(struct usb_ep *ep,
  */
 static void dwc3_prepare_one_trb(struct dwc3_ep *dep,
 		struct dwc3_request *req, dma_addr_t dma,
-		unsigned length, unsigned last, unsigned chain)
+		unsigned length, unsigned last, unsigned chain, unsigned node)
 {
 	struct dwc3		*dwc = dep->dwc;
 	struct dwc3_trb		*trb;
 
-	unsigned int		cur_slot;
-
 	dev_vdbg(dwc->dev, "%s: req %p dma %08llx length %d%s%s\n",
 			dep->name, req, (unsigned long long) dma,
 			length, last ? " last" : "",
 			chain ? " chain" : "");
 
-	trb = &dep->trb_pool[dep->free_slot & DWC3_TRB_MASK];
-	cur_slot = dep->free_slot;
-	dep->free_slot++;
-
 	/* Skip the LINK-TRB on ISOC */
-	if (((cur_slot & DWC3_TRB_MASK) == DWC3_TRB_NUM - 1) &&
+	if (((dep->free_slot & DWC3_TRB_MASK) == DWC3_TRB_NUM - 1) &&
 			usb_endpoint_xfer_isoc(dep->endpoint.desc))
-		return;
+		dep->free_slot++;
+
+	trb = &dep->trb_pool[dep->free_slot & DWC3_TRB_MASK];
 
 	if (!req->trb) {
 		dwc3_gadget_move_request_queued(req);
 		req->trb = trb;
 		req->trb_dma = dwc3_trb_dma_offset(dep, trb);
+		req->start_slot = dep->free_slot & DWC3_TRB_MASK;
 	}
 
+	dep->free_slot++;
+
 	trb->size = DWC3_TRB_SIZE_LENGTH(length);
 	trb->bpl = lower_32_bits(dma);
 	trb->bph = upper_32_bits(dma);
@@ -786,9 +787,12 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep,
 		break;
 
 	case USB_ENDPOINT_XFER_ISOC:
-		trb->ctrl = DWC3_TRBCTL_ISOCHRONOUS_FIRST;
+		if (!node)
+			trb->ctrl = DWC3_TRBCTL_ISOCHRONOUS_FIRST;
+		else
+			trb->ctrl = DWC3_TRBCTL_ISOCHRONOUS;
 
-		if (!req->request.no_interrupt)
+		if (!req->request.no_interrupt && !chain)
 			trb->ctrl |= DWC3_TRB_CTRL_IOC;
 		break;
 
@@ -807,14 +811,13 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep,
 	if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) {
 		trb->ctrl |= DWC3_TRB_CTRL_ISP_IMI;
 		trb->ctrl |= DWC3_TRB_CTRL_CSP;
-	} else {
-		if (chain)
-			trb->ctrl |= DWC3_TRB_CTRL_CHN;
-
-		if (last)
-			trb->ctrl |= DWC3_TRB_CTRL_LST;
+	} else if (last) {
+		trb->ctrl |= DWC3_TRB_CTRL_LST;
 	}
 
+	if (chain)
+		trb->ctrl |= DWC3_TRB_CTRL_CHN;
+
 	if (usb_endpoint_xfer_bulk(dep->endpoint.desc) && dep->stream_capable)
 		trb->ctrl |= DWC3_TRB_CTRL_SID_SOFN(req->request.stream_id);
 
@@ -885,6 +888,7 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep, bool starting)
 	list_for_each_entry_safe(req, n, &dep->request_list, list) {
 		unsigned	length;
 		dma_addr_t	dma;
+		last_one = false;
 
 		if (req->request.num_mapped_sgs > 0) {
 			struct usb_request *request = &req->request;
@@ -900,7 +904,9 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep, bool starting)
 
 				if (i == (request->num_mapped_sgs - 1) ||
 						sg_is_last(s)) {
-					last_one = true;
+					if (list_is_last(&req->list,
+							&dep->request_list))
+						last_one = true;
 					chain = false;
 				}
 
@@ -912,7 +918,7 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep, bool starting)
 					chain = false;
 
 				dwc3_prepare_one_trb(dep, req, dma, length,
-						last_one, chain);
+						last_one, chain, i);
 
 				if (last_one)
 					break;
@@ -930,7 +936,7 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep, bool starting)
 				last_one = 1;
 
 			dwc3_prepare_one_trb(dep, req, dma, length,
-					last_one, false);
+					last_one, false, 0);
 
 			if (last_one)
 				break;
@@ -977,13 +983,14 @@ static int __dwc3_gadget_kick_transfer(struct dwc3_ep *dep, u16 cmd_param,
 	}
 
 	memset(&params, 0, sizeof(params));
-	params.param0 = upper_32_bits(req->trb_dma);
-	params.param1 = lower_32_bits(req->trb_dma);
 
-	if (start_new)
+	if (start_new) {
+		params.param0 = upper_32_bits(req->trb_dma);
+		params.param1 = lower_32_bits(req->trb_dma);
 		cmd = DWC3_DEPCMD_STARTTRANSFER;
-	else
+	} else {
 		cmd = DWC3_DEPCMD_UPDATETRANSFER;
+	}
 
 	cmd |= DWC3_DEPCMD_PARAM(cmd_param);
 	ret = dwc3_send_gadget_ep_cmd(dwc, dep->number, cmd, &params);
@@ -1082,8 +1089,6 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
 	 *
 	 */
 	if (dep->flags & DWC3_EP_PENDING_REQUEST) {
-		int	ret;
-
 		/*
 		 * If xfernotready is already elapsed and it is a case
 		 * of isoc transfer, then issue END TRANSFER, so that
@@ -1091,7 +1096,10 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
 		 * notion of current microframe.
 		 */
 		if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) {
-			dwc3_stop_active_transfer(dwc, dep->number);
+			if (list_empty(&dep->req_queued)) {
+				dwc3_stop_active_transfer(dwc, dep->number);
+				dep->flags = DWC3_EP_ENABLED;
+			}
 			return 0;
 		}
 
@@ -1099,6 +1107,7 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
 		if (ret && ret != -EBUSY)
 			dev_dbg(dwc->dev, "%s: failed to kick transfers\n",
 					dep->name);
+		return ret;
 	}
 
 	/*
@@ -1115,16 +1124,7 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
 		if (ret && ret != -EBUSY)
 			dev_dbg(dwc->dev, "%s: failed to kick transfers\n",
 					dep->name);
-	}
-
-	/*
-	 * 3. Missed ISOC Handling. We need to start isoc transfer on the saved
-	 * uframe number.
-	 */
-	if (usb_endpoint_xfer_isoc(dep->endpoint.desc) &&
-		(dep->flags & DWC3_EP_MISSED_ISOC)) {
-			__dwc3_gadget_start_isoc(dwc, dep, dep->current_uf);
-			dep->flags &= ~DWC3_EP_MISSED_ISOC;
+		return ret;
 	}
 
 	return 0;
@@ -1652,76 +1652,134 @@ static void dwc3_gadget_release(struct device *dev)
 }
 
 /* -------------------------------------------------------------------------- */
-static int dwc3_cleanup_done_reqs(struct dwc3 *dwc, struct dwc3_ep *dep,
+static int __dwc3_cleanup_done_trbs(struct dwc3 *dwc, struct dwc3_ep *dep,
+		struct dwc3_request *req, struct dwc3_trb *trb,
 		const struct dwc3_event_depevt *event, int status)
 {
-	struct dwc3_request	*req;
-	struct dwc3_trb		*trb;
 	unsigned int		count;
 	unsigned int		s_pkt = 0;
 	unsigned int		trb_status;
 
+	if ((trb->ctrl & DWC3_TRB_CTRL_HWO) && status != -ESHUTDOWN)
+		/*
+		 * We continue despite the error. There is not much we
+		 * can do. If we don't clean it up we loop forever. If
+		 * we skip the TRB then it gets overwritten after a
+		 * while since we use them in a ring buffer. A BUG()
+		 * would help. Lets hope that if this occurs, someone
+		 * fixes the root cause instead of looking away :)
+		 */
+		dev_err(dwc->dev, "%s's TRB (%p) still owned by HW\n",
+				dep->name, trb);
+	count = trb->size & DWC3_TRB_SIZE_MASK;
+
+	if (dep->direction) {
+		if (count) {
+			trb_status = DWC3_TRB_SIZE_TRBSTS(trb->size);
+			if (trb_status == DWC3_TRBSTS_MISSED_ISOC) {
+				dev_dbg(dwc->dev, "incomplete IN transfer %s\n",
+						dep->name);
+				/*
+				 * If missed isoc occurred and there is
+				 * no request queued then issue END
+				 * TRANSFER, so that core generates
+				 * next xfernotready and we will issue
+				 * a fresh START TRANSFER.
+				 * If there are still queued request
+				 * then wait, do not issue either END
+				 * or UPDATE TRANSFER, just attach next
+				 * request in request_list during
+				 * giveback.If any future queued request
+				 * is successfully transferred then we
+				 * will issue UPDATE TRANSFER for all
+				 * request in the request_list.
+				 */
+				dep->flags |= DWC3_EP_MISSED_ISOC;
+			} else {
+				dev_err(dwc->dev, "incomplete IN transfer %s\n",
+						dep->name);
+				status = -ECONNRESET;
+			}
+		} else {
+			dep->flags &= ~DWC3_EP_MISSED_ISOC;
+		}
+	} else {
+		if (count && (event->status & DEPEVT_STATUS_SHORT))
+			s_pkt = 1;
+	}
+
+	/*
+	 * We assume here we will always receive the entire data block
+	 * which we should receive. Meaning, if we program RX to
+	 * receive 4K but we receive only 2K, we assume that's all we
+	 * should receive and we simply bounce the request back to the
+	 * gadget driver for further processing.
+	 */
+	req->request.actual += req->request.length - count;
+	if (s_pkt)
+		return 1;
+	if ((event->status & DEPEVT_STATUS_LST) &&
+			(trb->ctrl & (DWC3_TRB_CTRL_LST |
+				DWC3_TRB_CTRL_HWO)))
+		return 1;
+	if ((event->status & DEPEVT_STATUS_IOC) &&
+			(trb->ctrl & DWC3_TRB_CTRL_IOC))
+		return 1;
+	return 0;
+}
+
+static int dwc3_cleanup_done_reqs(struct dwc3 *dwc, struct dwc3_ep *dep,
+		const struct dwc3_event_depevt *event, int status)
+{
+	struct dwc3_request	*req;
+	struct dwc3_trb		*trb;
+	unsigned int		slot;
+	unsigned int		i;
+	int			ret;
+
 	do {
 		req = next_request(&dep->req_queued);
 		if (!req) {
 			WARN_ON_ONCE(1);
 			return 1;
 		}
+		i = 0;
+		do {
+			slot = req->start_slot + i;
+			if ((slot == DWC3_TRB_NUM - 1) &&
+				usb_endpoint_xfer_isoc(dep->endpoint.desc))
+				slot++;
+			slot %= DWC3_TRB_NUM;
+			trb = &dep->trb_pool[slot];
 
-		trb = req->trb;
+			ret = __dwc3_cleanup_done_trbs(dwc, dep, req, trb,
+					event, status);
+			if (ret)
+				break;
+		}while (++i < req->request.num_mapped_sgs);
 
-		if ((trb->ctrl & DWC3_TRB_CTRL_HWO) && status != -ESHUTDOWN)
+		dwc3_gadget_giveback(dep, req, status);
+
+		if (ret)
+			break;
+	} while (1);
+
+	if (usb_endpoint_xfer_isoc(dep->endpoint.desc) &&
+			list_empty(&dep->req_queued)) {
+		if (list_empty(&dep->request_list)) {
 			/*
-			 * We continue despite the error. There is not much we
-			 * can do. If we don't clean it up we loop forever. If
-			 * we skip the TRB then it gets overwritten after a
-			 * while since we use them in a ring buffer. A BUG()
-			 * would help. Lets hope that if this occurs, someone
-			 * fixes the root cause instead of looking away :)
+			 * If there is no entry in request list then do
+			 * not issue END TRANSFER now. Just set PENDING
+			 * flag, so that END TRANSFER is issued when an
+			 * entry is added into request list.
 			 */
-			dev_err(dwc->dev, "%s's TRB (%p) still owned by HW\n",
-					dep->name, req->trb);
-		count = trb->size & DWC3_TRB_SIZE_MASK;
-
-		if (dep->direction) {
-			if (count) {
-				trb_status = DWC3_TRB_SIZE_TRBSTS(trb->size);
-				if (trb_status == DWC3_TRBSTS_MISSED_ISOC) {
-					dev_dbg(dwc->dev, "incomplete IN transfer %s\n",
-							dep->name);
-					dep->current_uf = event->parameters &
-						~(dep->interval - 1);
-					dep->flags |= DWC3_EP_MISSED_ISOC;
-				} else {
-					dev_err(dwc->dev, "incomplete IN transfer %s\n",
-							dep->name);
-					status = -ECONNRESET;
-				}
-			}
+			dep->flags = DWC3_EP_PENDING_REQUEST;
 		} else {
-			if (count && (event->status & DEPEVT_STATUS_SHORT))
-				s_pkt = 1;
+			dwc3_stop_active_transfer(dwc, dep->number);
+			dep->flags = DWC3_EP_ENABLED;
 		}
-
-		/*
-		 * We assume here we will always receive the entire data block
-		 * which we should receive. Meaning, if we program RX to
-		 * receive 4K but we receive only 2K, we assume that's all we
-		 * should receive and we simply bounce the request back to the
-		 * gadget driver for further processing.
-		 */
-		req->request.actual += req->request.length - count;
-		dwc3_gadget_giveback(dep, req, status);
-		if (s_pkt)
-			break;
-		if ((event->status & DEPEVT_STATUS_LST) &&
-				(trb->ctrl & (DWC3_TRB_CTRL_LST |
-						DWC3_TRB_CTRL_HWO)))
-			break;
-		if ((event->status & DEPEVT_STATUS_IOC) &&
-				(trb->ctrl & DWC3_TRB_CTRL_IOC))
-			break;
-	} while (1);
+		return 1;
+	}
 
 	if ((event->status & DEPEVT_STATUS_IOC) &&
 			(trb->ctrl & DWC3_TRB_CTRL_IOC))
@@ -2157,6 +2215,26 @@ static void dwc3_gadget_conndone_interrupt(struct dwc3 *dwc)
 		break;
 	}
 
+	/* Enable USB2 LPM Capability */
+
+	if ((dwc->revision > DWC3_REVISION_194A)
+			&& (speed != DWC3_DCFG_SUPERSPEED)) {
+		reg = dwc3_readl(dwc->regs, DWC3_DCFG);
+		reg |= DWC3_DCFG_LPM_CAP;
+		dwc3_writel(dwc->regs, DWC3_DCFG, reg);
+
+		reg = dwc3_readl(dwc->regs, DWC3_DCTL);
+		reg &= ~(DWC3_DCTL_HIRD_THRES_MASK | DWC3_DCTL_L1_HIBER_EN);
+
+		/*
+		 * TODO: This should be configurable. For now using
+		 * maximum allowed HIRD threshold value of 0b1100
+		 */
+		reg |= DWC3_DCTL_HIRD_THRES(12);
+
+		dwc3_writel(dwc->regs, DWC3_DCTL, reg);
+	}
+
 	/* Recent versions support automatic phy suspend and don't need this */
 	if (dwc->revision < DWC3_REVISION_194A) {
 		/* Suspend unneeded PHY */
@@ -2463,20 +2541,8 @@ int dwc3_gadget_init(struct dwc3 *dwc)
 			DWC3_DEVTEN_DISCONNEVTEN);
 	dwc3_writel(dwc->regs, DWC3_DEVTEN, reg);
 
-	/* Enable USB2 LPM and automatic phy suspend only on recent versions */
+	/* automatic phy suspend only on recent versions */
 	if (dwc->revision >= DWC3_REVISION_194A) {
-		reg = dwc3_readl(dwc->regs, DWC3_DCFG);
-		reg |= DWC3_DCFG_LPM_CAP;
-		dwc3_writel(dwc->regs, DWC3_DCFG, reg);
-
-		reg = dwc3_readl(dwc->regs, DWC3_DCTL);
-		reg &= ~(DWC3_DCTL_HIRD_THRES_MASK | DWC3_DCTL_L1_HIBER_EN);
-
-		/* TODO: This should be configurable */
-		reg |= DWC3_DCTL_HIRD_THRES(28);
-
-		dwc3_writel(dwc->regs, DWC3_DCTL, reg);
-
 		dwc3_gadget_usb2_phy_suspend(dwc, false);
 		dwc3_gadget_usb3_phy_suspend(dwc, false);
 	}

+ 1 - 1
drivers/usb/dwc3/host.c

@@ -44,7 +44,7 @@ int dwc3_host_init(struct dwc3 *dwc)
 	struct platform_device	*xhci;
 	int			ret;
 
-	xhci = platform_device_alloc("xhci-hcd", -1);
+	xhci = platform_device_alloc("xhci-hcd", PLATFORM_DEVID_AUTO);
 	if (!xhci) {
 		dev_err(dwc->dev, "couldn't allocate xHCI device\n");
 		ret = -ENOMEM;

+ 23 - 1
drivers/usb/gadget/Kconfig

@@ -281,6 +281,7 @@ config USB_S3C_HSOTG
 config USB_IMX
 	tristate "Freescale i.MX1 USB Peripheral Controller"
 	depends on ARCH_MXC
+	depends on BROKEN
 	help
 	   Freescale's i.MX1 includes an integrated full speed
 	   USB 1.1 device controller.
@@ -319,6 +320,7 @@ config USB_S3C_HSUDC
 
 config USB_MV_UDC
 	tristate "Marvell USB2.0 Device Controller"
+	depends on GENERIC_HARDIRQS
 	help
 	  Marvell Socs (including PXA and MMP series) include a high speed
 	  USB2.0 OTG controller, which can be configured as high speed or
@@ -440,7 +442,7 @@ config USB_GOKU
 
 config USB_EG20T
 	tristate "Intel EG20T PCH/LAPIS Semiconductor IOH(ML7213/ML7831) UDC"
-	depends on PCI
+	depends on PCI && GENERIC_HARDIRQS
 	help
 	  This is a USB device driver for EG20T PCH.
 	  EG20T PCH is the platform controller hub that is used in Intel's
@@ -500,6 +502,15 @@ config USB_LIBCOMPOSITE
 	tristate
 	depends on USB_GADGET
 
+config USB_F_ACM
+	tristate
+
+config USB_F_SS_LB
+	tristate
+
+config USB_U_SERIAL
+	tristate
+
 choice
 	tristate "USB Gadget Drivers"
 	default USB_ETH
@@ -524,6 +535,7 @@ choice
 config USB_ZERO
 	tristate "Gadget Zero (DEVELOPMENT)"
 	select USB_LIBCOMPOSITE
+	select USB_F_SS_LB
 	help
 	  Gadget Zero is a two-configuration device.  It either sinks and
 	  sources bulk data; or it loops back a configurable number of
@@ -750,6 +762,8 @@ config USB_GADGET_TARGET
 
 config USB_G_SERIAL
 	tristate "Serial Gadget (with CDC ACM and CDC OBEX support)"
+	select USB_U_SERIAL
+	select USB_F_ACM
 	select USB_LIBCOMPOSITE
 	help
 	  The Serial Gadget talks to the Linux-USB generic serial driver.
@@ -803,6 +817,8 @@ config USB_CDC_COMPOSITE
 	tristate "CDC Composite Device (Ethernet and ACM)"
 	depends on NET
 	select USB_LIBCOMPOSITE
+	select USB_U_SERIAL
+	select USB_F_ACM
 	help
 	  This driver provides two functions in one configuration:
 	  a CDC Ethernet (ECM) link, and a CDC ACM (serial port) link.
@@ -818,6 +834,7 @@ config USB_G_NOKIA
 	tristate "Nokia composite gadget"
 	depends on PHONET
 	select USB_LIBCOMPOSITE
+	select USB_U_SERIAL
 	help
 	  The Nokia composite gadget provides support for acm, obex
 	  and phonet in only one composite gadget driver.
@@ -829,6 +846,8 @@ config USB_G_ACM_MS
 	tristate "CDC Composite Device (ACM and mass storage)"
 	depends on BLOCK
 	select USB_LIBCOMPOSITE
+	select USB_U_SERIAL
+	select USB_F_ACM
 	help
 	  This driver provides two functions in one configuration:
 	  a mass storage, and a CDC ACM (serial port) link.
@@ -841,6 +860,8 @@ config USB_G_MULTI
 	depends on BLOCK && NET
 	select USB_G_MULTI_CDC if !USB_G_MULTI_RNDIS
 	select USB_LIBCOMPOSITE
+	select USB_U_SERIAL
+	select USB_F_ACM
 	help
 	  The Multifunction Composite Gadget provides Ethernet (RNDIS
 	  and/or CDC Ethernet), mass storage and ACM serial link
@@ -916,6 +937,7 @@ config USB_G_DBGP_PRINTK
 
 config USB_G_DBGP_SERIAL
 	depends on USB_G_DBGP
+	select USB_U_SERIAL
 	bool "serial"
 	help
 	  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_LIBCOMPOSITE)	+= libcomposite.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_NET2272)	+= net2272.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_ACM_MS)	+= g_acm_ms.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
  * a "gcc --combine ... part1.c part2.c part3.c ... " build would.
  */
-
-#include "u_serial.c"
-#include "f_acm.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 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.
  */
 static int __init acm_ms_do_config(struct usb_configuration *c)
 {
+	struct f_serial_opts *opts;
 	int	status;
 
 	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;
 	}
 
+	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)
-		return status;
+		goto err_conf;
 
 	status = fsg_bind_config(c->cdev, c, &fsg_common);
 	if (status < 0)
-		return status;
+		goto err_fsg;
 
 	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 = {
@@ -153,7 +172,7 @@ static int __init acm_ms_bind(struct usb_composite_dev *cdev)
 	void			*retp;
 
 	/* set up serial link layer */
-	status = gserial_setup(cdev->gadget, 1);
+	status = gserial_alloc_line(&tty_line);
 	if (status < 0)
 		return status;
 
@@ -189,14 +208,15 @@ static int __init acm_ms_bind(struct usb_composite_dev *cdev)
 fail1:
 	fsg_common_put(&fsg_common);
 fail0:
-	gserial_cleanup();
+	gserial_free_line(tty_line);
 	return status;
 }
 
 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;
 }
 

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

@@ -1400,15 +1400,16 @@ static int udc_wakeup(struct usb_gadget *gadget)
 	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 */
 static const struct usb_gadget_ops udc_ops = {
 	.wakeup		= udc_wakeup,
 	.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 */
@@ -1913,41 +1914,22 @@ static int setup_ep0(struct udc *dev)
 }
 
 /* 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;
 
-	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;
 	dev->driver = driver;
 	dev->gadget.dev.driver = &driver->driver;
 
-	retval = bind(&dev->gadget, driver);
-
 	/* Some gadget drivers use both ep0 directions.
 	 * NOTE: to gadget driver, ep0 is just one endpoint...
 	 */
 	dev->ep[UDC_EP0OUT_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 */
 	setup_ep0(dev);
 
@@ -1969,14 +1951,9 @@ __acquires(dev->lock)
 {
 	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 */
 	udc_basic_init(dev);
+
 	for (tmp = 0; tmp < UDC_EP_NUM; tmp++)
 		empty_req_queue(&dev->ep[tmp]);
 
@@ -1984,23 +1961,18 @@ __acquires(dev->lock)
 }
 
 /* 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;
 
-	if (!dev)
-		return -ENODEV;
-	if (!driver || driver != dev->driver || !driver->unbind)
-		return -EINVAL;
-
 	spin_lock_irqsave(&dev->lock, flags);
 	udc_mask_unused_interrupts(dev);
 	shutdown(dev, driver);
 	spin_unlock_irqrestore(&dev->lock, flags);
 
-	driver->unbind(&dev->gadget);
 	dev->gadget.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);
 	writel(tmp, &dev->regs->ctl);
 
-
-	DBG(dev, "%s: unregistered\n", driver->driver.name);
-
 	return 0;
 }
 

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

@@ -563,6 +563,8 @@ struct udc {
 	u16				cur_alt;
 };
 
+#define to_amd5536_udc(g)	(container_of((g), struct udc, gadget))
+
 /* setup request data */
 union udc_setup_data {
 	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
 	 * 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,
@@ -1739,7 +1738,7 @@ static int at91udc_probe(struct platform_device *pdev)
 
 	/* rm9200 needs manual D+ pullup; off by default */
 	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");
 			retval = -ENODEV;
 			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
  * a "gcc --combine ... part1.c part2.c part3.c ... " build would.
  */
-
-#include "u_serial.c"
-#include "f_acm.c"
 #include "f_ecm.c"
 #include "u_ether.c"
 
@@ -108,12 +105,16 @@ static struct usb_gadget_strings *dev_strings[] = {
 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.
  */
 static int __init cdc_do_config(struct usb_configuration *c)
 {
+	struct f_serial_opts *opts;
 	int	status;
 
 	if (gadget_is_otg(c->cdev->gadget)) {
@@ -125,11 +126,26 @@ static int __init cdc_do_config(struct usb_configuration *c)
 	if (status < 0)
 		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;
+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 = {
@@ -158,7 +174,7 @@ static int __init cdc_bind(struct usb_composite_dev *cdev)
 		return status;
 
 	/* set up serial link layer */
-	status = gserial_setup(cdev->gadget, 1);
+	status = gserial_alloc_line(&tty_line);
 	if (status < 0)
 		goto fail0;
 
@@ -184,7 +200,7 @@ static int __init cdc_bind(struct usb_composite_dev *cdev)
 	return 0;
 
 fail1:
-	gserial_cleanup();
+	gserial_free_line(tty_line);
 fail0:
 	gether_cleanup();
 	return status;
@@ -192,7 +208,9 @@ fail0:
 
 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();
 	return 0;
 }

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

@@ -28,6 +28,12 @@
  * 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
  * @t: currect pointer within descriptor array
@@ -215,6 +221,18 @@ done:
 }
 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
  * @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);
 
+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,
 		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->iConfiguration = config->iConfiguration;
 	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 */
 	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 */
-	power = c->bMaxPower ? (2 * c->bMaxPower) : CONFIG_USB_GADGET_VBUS_DRAW;
+	power = c->MaxPower ? c->MaxPower : CONFIG_USB_GADGET_VBUS_DRAW;
 done:
 	usb_gadget_vbus_draw(gadget, power);
 	if (result >= 0 && cdev->delayed_status)
@@ -664,6 +701,31 @@ done:
 	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.
  * @cdev: wraps the USB gadget
@@ -684,30 +746,18 @@ int usb_add_config(struct usb_composite_dev *cdev,
 		int (*bind)(struct usb_configuration *))
 {
 	int				status = -EINVAL;
-	struct usb_configuration	*c;
+
+	if (!bind)
+		goto done;
 
 	DBG(cdev, "adding config #%u '%s'/%p\n",
 			config->bConfigurationValue,
 			config->label, config);
 
-	if (!config->bConfigurationValue || !bind)
+	status = usb_add_config_only(cdev, config);
+	if (status)
 		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);
 	if (status < 0) {
 		while (!list_empty(&config->functions)) {
@@ -860,6 +910,7 @@ static int get_string(struct usb_composite_dev *cdev,
 		void *buf, u16 language, int id)
 {
 	struct usb_composite_driver	*composite = cdev->driver;
+	struct usb_gadget_string_container *uc;
 	struct usb_configuration	*c;
 	struct usb_function		*f;
 	int				len;
@@ -892,6 +943,12 @@ static int get_string(struct usb_composite_dev *cdev,
 					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++)
 			continue;
@@ -902,6 +959,15 @@ static int get_string(struct usb_composite_dev *cdev,
 		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
 	 * table we're told about.  These lookups are infrequent;
 	 * 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);
 
+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
  * @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
  * the work is in config and function specific setup.
  */
-static int
+int
 composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
 {
 	struct usb_composite_dev	*cdev = get_gadget_data(gadget);
@@ -1300,7 +1479,7 @@ done:
 	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);
 	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 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);
 
@@ -1348,19 +1526,21 @@ composite_unbind(struct usb_gadget *gadget)
 				struct usb_configuration, list);
 		remove_config(cdev, c);
 	}
-	if (cdev->driver->unbind)
+	if (cdev->driver->unbind && unbind_driver)
 		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);
 	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,
 		const struct usb_device_descriptor *old)
 {
@@ -1399,34 +1579,25 @@ static void update_unchanged_dev_desc(struct usb_device_descriptor *new,
 		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 */
 	cdev->req = usb_ep_alloc_request(gadget->ep0, GFP_KERNEL);
 	if (!cdev->req)
-		goto fail;
+		return -ENOMEM;
+
 	cdev->req->buf = kmalloc(USB_COMP_EP0_BUFSIZ, GFP_KERNEL);
 	if (!cdev->req->buf)
 		goto fail;
+
+	ret = device_create_file(&gadget->dev, &dev_attr_suspended);
+	if (ret)
+		goto fail_dev;
+
 	cdev->req->complete = composite_setup_complete;
 	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
 	 * 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
 	 * 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)
 		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);
 	return 0;
 
 fail:
-	composite_unbind(gadget);
+	__composite_unbind(gadget, false);
 	return status;
 }
 
@@ -1518,10 +1728,10 @@ composite_resume(struct usb_gadget *gadget)
 				f->resume(f);
 		}
 
-		maxpower = cdev->config->bMaxPower;
+		maxpower = cdev->config->MaxPower;
 
 		usb_gadget_vbus_draw(gadget, maxpower ?
-			(2 * maxpower) : CONFIG_USB_GADGET_VBUS_DRAW);
+			maxpower : CONFIG_USB_GADGET_VBUS_DRAW);
 	}
 
 	cdev->suspended = 0;

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

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

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

@@ -16,7 +16,9 @@
 
 #include <linux/slab.h>
 #include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/device.h>
+#include <linux/err.h>
 
 #include "u_serial.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_DATA_IDX].s = "CDC ACM Data",
 	[ACM_IAD_IDX ].s = "CDC Serial",
-	{  /* ZEROES END LIST */ },
 };
 
 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 f_acm		*acm = func_to_acm(f);
+	struct usb_string	*us;
 	int			status;
 	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 */
 	status = usb_interface_id(c, f);
 	if (status < 0)
@@ -700,24 +715,42 @@ fail:
 	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
-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);
 
-	acm_string_defs[0].id = 0;
 	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);
 }
 
-/* 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
  * @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.
  *
- * 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)
 {
 	struct f_acm	*acm;
 	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 */
-	acm = kzalloc(sizeof *acm, GFP_KERNEL);
+	acm = acm_alloc_basic_func();
 	if (!acm)
 		return -ENOMEM;
 
-	spin_lock_init(&acm->lock);
-
 	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);
 	if (status)
 		kfree(acm);
 	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;
 
 	for (;;) {
-		char *end, *eq, *comma;
 		unsigned long value;
+		char *eq, *comma;
 
 		/* Option limit */
 		comma = strchr(opts, ',');
@@ -1120,8 +1120,7 @@ static int ffs_fs_parse_opts(struct ffs_sb_fill_data *data, char *opts)
 		*eq = 0;
 
 		/* 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);
 			return -EINVAL;
 		}

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

@@ -15,10 +15,11 @@
 #include <linux/slab.h>
 #include <linux/kernel.h>
 #include <linux/device.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/usb/composite.h>
 
 #include "g_zero.h"
-#include "gadget_chips.h"
-
 
 /*
  * 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);
 }
 
-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 f_loopback	*loop = func_to_loop(f);
@@ -185,6 +184,12 @@ loopback_bind(struct usb_configuration *c, struct usb_function *f)
 		return 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 */
 
 	loop->in_ep = usb_ep_autoconfig(cdev->gadget, &fs_loop_source_desc);
@@ -223,8 +228,7 @@ autoconf_fail:
 	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);
 	kfree(func_to_loop(f));
@@ -366,63 +370,64 @@ static void loopback_disable(struct usb_function *f)
 	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;
-	int			status;
+	struct f_lb_opts	*lb_opts;
 
 	loop = kzalloc(sizeof *loop, GFP_KERNEL);
 	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.bind = loopback_bind;
-	loop->function.unbind = loopback_unbind;
 	loop->function.set_alt = loopback_set_alt;
 	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).
 	 */
 	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. */
@@ -1374,26 +1360,13 @@ static int do_start_stop(struct fsg_common *common)
 	if (!loej)
 		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);
 	down_write(&common->filesem);
 	fsg_lun_close(curlun);
 	up_write(&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)
@@ -1718,7 +1691,7 @@ static int check_command(struct fsg_common *common, int cmnd_size,
 			 int needs_medium, const char *name)
 {
 	int			i;
-	int			lun = common->cmnd[1] >> 5;
+	unsigned int		lun = common->cmnd[1] >> 5;
 	static const char	dirletter[4] = {'u', 'o', 'i', 'n'};
 	char			hdlen[20];
 	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 */
 	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);
 
 	/* Check the LUN */
@@ -1804,7 +1777,7 @@ static int check_command(struct fsg_common *common, int cmnd_size,
 		 */
 		if (common->cmnd[0] != INQUIRY &&
 		    common->cmnd[0] != REQUEST_SENSE) {
-			DBG(common, "unsupported LUN %d\n", common->lun);
+			DBG(common, "unsupported LUN %u\n", common->lun);
 			return -EINVAL;
 		}
 	}
@@ -2196,7 +2169,7 @@ static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh)
 	if (common->data_size == 0)
 		common->data_dir = DATA_DIR_NONE;
 	common->lun = cbw->Lun;
-	if (common->lun >= 0 && common->lun < common->nluns)
+	if (common->lun < common->nluns)
 		common->curlun = &common->luns[common->lun];
 	else
 		common->curlun = NULL;

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

@@ -56,8 +56,9 @@ struct f_ncm {
 	u8				notify_state;
 	bool				is_open;
 
-	struct ndp_parser_opts		*parser_opts;
+	const struct ndp_parser_opts	*parser_opts;
 	bool				is_crc;
+	u32				ndp_sign;
 
 	/*
 	 * for notification, it is accessed from both
@@ -390,8 +391,8 @@ struct ndp_parser_opts {
 		.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)
 {
@@ -732,8 +733,7 @@ static int ncm_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
 		default:
 			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;
 		break;
 	}
@@ -875,7 +875,7 @@ static struct sk_buff *ncm_wrap_ntb(struct gether *port,
 	int		ndp_align;
 	int		ndp_pad;
 	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;
 
 	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;
 
 	/* NDP */
-	put_unaligned_le32(opts->ndp_sign, tmp); /* dwSignature */
+	put_unaligned_le32(ncm->ndp_sign, tmp); /* dwSignature */
 	tmp += 2;
 	/* wLength */
 	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;
 	int		ret = -EINVAL;
 	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;
 	int		dgram_counter;
 
@@ -1002,7 +1002,7 @@ static int ncm_unwrap_ntb(struct gether *port,
 
 	/* walk through NDP */
 	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");
 		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
  *
  * 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)
 {

+ 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
  *
  * 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)
 {

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

@@ -16,11 +16,12 @@
 #include <linux/kernel.h>
 #include <linux/device.h>
 #include <linux/module.h>
+#include <linux/usb/composite.h>
+#include <linux/err.h>
 
 #include "g_zero.h"
 #include "gadget_chips.h"
 
-
 /*
  * SOURCE/SINK FUNCTION ... a primary testing vehicle for USB peripheral
  * controller drivers.
@@ -62,24 +63,11 @@ static inline struct f_sourcesink *func_to_ss(struct usb_function *f)
 }
 
 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;
-module_param(isoc_mult, uint, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(isoc_mult, "0 - 2 (hs/ss only)");
-
 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)
 {
 	struct usb_composite_dev *cdev = c->cdev;
@@ -450,7 +488,7 @@ no_iso:
 }
 
 static void
-sourcesink_unbind(struct usb_configuration *c, struct usb_function *f)
+sourcesink_free_func(struct usb_function *f)
 {
 	usb_free_all_descriptors(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);
 			if (pattern != 2)
 				memset(req->buf, 0x55, req->length);
-		} else
-			reinit_write_data(ep, req);
+		}
 		break;
 
 	/* 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)
 {
+	struct usb_configuration        *c = f->config;
 	struct usb_request	*req = c->cdev->req;
 	int			value = -EOPNOTSUPP;
 	u16			w_index = le16_to_cpu(ctrl->wIndex);
@@ -851,42 +867,76 @@ unknown:
 	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)
 {
 	struct snd_uac2_chip *uac2 = snd_pcm_substream_chip(substream);
-	struct audio_dev *agdev = uac2_to_agdev(uac2);
 	struct uac2_rtd_params *prm;
 	unsigned long flags;
-	struct usb_ep *ep;
 	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;
-	} else {
-		ep = agdev->out_ep;
+	else
 		prm = &uac2->c_prm;
-	}
 
 	spin_lock_irqsave(&prm->lock, flags);
 

+ 2 - 1
drivers/usb/gadget/f_uvc.c

@@ -16,6 +16,7 @@
 #include <linux/fs.h>
 #include <linux/list.h>
 #include <linux/mutex.h>
+#include <linux/string.h>
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
 #include <linux/usb/video.h>
@@ -419,7 +420,7 @@ uvc_register_video(struct uvc_device *uvc)
 	video->parent = &cdev->gadget->dev;
 	video->fops = &uvc_v4l2_fops;
 	video->release = video_device_release;
-	strncpy(video->name, cdev->gadget->name, sizeof(video->name));
+	strlcpy(video->name, cdev->gadget->name, sizeof(video->name));
 
 	uvc->vdev = video;
 	video_set_drvdata(video, uvc);

+ 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);
 
 /* 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,
 	.udc_start = fsl_qe_start,
 	.udc_stop = fsl_qe_stop,

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

@@ -1255,19 +1255,20 @@ static int fsl_pullup(struct usb_gadget *gadget, int is_on)
 	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 */
-static struct usb_gadget_ops fsl_gadget_ops = {
+static const struct usb_gadget_ops fsl_gadget_ops = {
 	.get_frame = fsl_get_frame,
 	.wakeup = fsl_wakeup,
 /*	.set_selfpowered = fsl_set_selfpowered,	*/ /* Always selfpowered */
 	.vbus_session = fsl_vbus_session,
 	.vbus_draw = fsl_vbus_draw,
 	.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
@@ -1951,22 +1952,12 @@ static irqreturn_t fsl_udc_irq(int irq, void *_udc)
  * Hook to 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;
 
-	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 */
 	spin_lock_irqsave(&udc_controller->lock, flags);
 
@@ -1976,15 +1967,6 @@ static int fsl_start(struct usb_gadget_driver *driver,
 	udc_controller->gadget.dev.driver = &driver->driver;
 	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)) {
 		/* Suspend the controller until OTG enable it */
 		udc_controller->stopped = 1;
@@ -2010,28 +1992,17 @@ static int fsl_start(struct usb_gadget_driver *driver,
 		udc_controller->ep0_state = WAIT_FOR_SETUP;
 		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;
 }
 
 /* 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;
 	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))
 		otg_set_peripheral(udc_controller->transceiver->otg, NULL);
 
@@ -2052,16 +2023,9 @@ static int fsl_stop(struct usb_gadget_driver *driver)
 		nuke(loop_ep, -ESHUTDOWN);
 	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->driver = NULL;
 
-	printk(KERN_WARNING "unregistered gadget driver '%s'\n",
-	       driver->driver.name);
 	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);
 }
 /*------------------------------------------------------------------------*/
-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 */
 	driver->driver.bus = NULL;
 	fusb300->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;
-
-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);
 	fusb300->gadget.dev.driver = NULL;
 
 	init_controller(fusb300);
-	device_del(&fusb300->gadget.dev);
 	fusb300->driver = NULL;
 
 	return 0;
@@ -1378,10 +1341,10 @@ static int fusb300_udc_pullup(struct usb_gadget *_gadget, int is_active)
 	return 0;
 }
 
-static struct usb_gadget_ops fusb300_gadget_ops = {
+static const struct usb_gadget_ops fusb300_gadget_ops = {
 	.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)
@@ -1505,8 +1468,6 @@ static int __init fusb300_probe(struct platform_device *pdev)
 	fusb300->gadget.ep0 = &fusb300->ep[0]->ep;
 	INIT_LIST_HEAD(&fusb300->gadget.ep0->ep_list);
 
-	the_controller = fusb300;
-
 	fusb300->ep0_req = fusb300_alloc_request(&fusb300->ep[0]->ep,
 				GFP_KERNEL);
 	if (fusb300->ep0_req == NULL)
@@ -1517,9 +1478,19 @@ static int __init fusb300_probe(struct platform_device *pdev)
 	if (ret)
 		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);
 
 	return 0;
+
+err_add_device:
+	usb_del_gadget_udc(&fusb300->gadget);
+
 err_add_udc:
 	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 */
 };
 
+#define to_fusb300(g)		(container_of((g), struct fusb300, gadget))
+
 #endif

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

@@ -6,11 +6,34 @@
 #ifndef __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 */
 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 *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 */

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

@@ -125,7 +125,7 @@ static struct usb_configuration midi_config = {
 	.bConfigurationValue = 1,
 	/* .iConfiguration = DYNAMIC */
 	.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)

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

@@ -993,14 +993,15 @@ static int goku_get_frame(struct usb_gadget *_gadget)
 	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 = {
 	.get_frame	= goku_get_frame,
-	.start		= goku_start,
-	.stop		= goku_stop,
+	.udc_start	= goku_udc_start,
+	.udc_stop	= goku_udc_stop,
 	// no remote wakeup
 	// not selfpowered
 };
@@ -1339,50 +1340,28 @@ static void udc_enable(struct goku_udc *dev)
  * - one function driver, initted second
  */
 
-static struct goku_udc	*the_controller;
-
 /* when a driver is successfully registered, it will receive
  * control requests including set_configuration(), which enables
  * non-control requests.  then usb traffic follows until a
  * disconnect is reported.  then a host may connect again, or
  * 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 */
 	driver->driver.bus = NULL;
 	dev->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.
 	 */
 	udc_enable(dev);
 
-	DBG(dev, "registered gadget driver '%s'\n", driver->driver.name);
 	return 0;
 }
 
@@ -1400,35 +1379,23 @@ stop_activity(struct goku_udc *dev, struct usb_gadget_driver *driver)
 	udc_reset (dev);
 	for (i = 0; i < 4; i++)
 		nuke(&dev->ep [i], -ESHUTDOWN);
-	if (driver) {
-		spin_unlock(&dev->lock);
-		driver->disconnect(&dev->gadget);
-		spin_lock(&dev->lock);
-	}
 
 	if (dev->driver)
 		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;
 
-	if (!dev)
-		return -ENODEV;
-	if (!driver || driver != dev->driver || !driver->unbind)
-		return -EINVAL;
-
 	spin_lock_irqsave(&dev->lock, flags);
 	dev->driver = NULL;
 	stop_activity(dev, driver);
 	spin_unlock_irqrestore(&dev->lock, flags);
-
-	driver->unbind(&dev->gadget);
 	dev->gadget.dev.driver = NULL;
 
-	DBG(dev, "unregistered driver '%s'\n", driver->driver.name);
 	return 0;
 }
 
@@ -1754,7 +1721,6 @@ static void goku_remove(struct pci_dev *pdev)
 
 	pci_set_drvdata(pdev, NULL);
 	dev->regs = NULL;
-	the_controller = NULL;
 
 	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;
 	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) {
 		printk(KERN_ERR "Check PCI %s IRQ setup!\n", pci_name(pdev));
 		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);
 #endif
 
-	the_controller = dev;
 	retval = device_register(&dev->gadget.dev);
 	if (retval) {
 		put_device(&dev->gadget.dev);

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

@@ -261,6 +261,7 @@ struct goku_udc {
 	/* statistics... */
 	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 */
 	driver->driver.bus = NULL;
 	m66592->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);
 	if (m66592_read(m66592, M66592_INTSTS0) & M66592_VBSTS) {
 		m66592_start_xclock(m66592);
@@ -1510,26 +1484,12 @@ static int m66592_start(struct usb_gadget_driver *driver,
 	}
 
 	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);
 
@@ -1539,8 +1499,8 @@ static int m66592_stop(struct usb_gadget_driver *driver)
 	init_controller(m66592);
 	disable_controller(m66592);
 
-	device_del(&m66592->gadget.dev);
 	m66592->driver = NULL;
+
 	return 0;
 }
 
@@ -1566,10 +1526,10 @@ static int m66592_pullup(struct usb_gadget *gadget, int is_on)
 	return 0;
 }
 
-static struct usb_gadget_ops m66592_gadget_ops = {
+static const struct usb_gadget_ops m66592_gadget_ops = {
 	.get_frame		= m66592_get_frame,
-	.start			= m66592_start,
-	.stop			= m66592_stop,
+	.udc_start		= m66592_udc_start,
+	.udc_stop		= m66592_udc_stop,
 	.pullup			= m66592_pullup,
 };
 
@@ -1578,6 +1538,7 @@ static int __exit m66592_remove(struct platform_device *pdev)
 	struct m66592		*m66592 = dev_get_drvdata(&pdev->dev);
 
 	usb_del_gadget_udc(&m66592->gadget);
+	device_del(&m66592->gadget.dev);
 
 	del_timer_sync(&m66592->timer);
 	iounmap(m66592->reg);
@@ -1706,8 +1667,6 @@ static int __init m66592_probe(struct platform_device *pdev)
 	m66592->pipenum2ep[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);
 	if (m66592->ep0_req == NULL)
 		goto clean_up3;
@@ -1715,6 +1674,12 @@ static int __init m66592_probe(struct platform_device *pdev)
 
 	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);
 	if (ret)
 		goto err_add_udc;
@@ -1723,6 +1688,9 @@ static int __init m66592_probe(struct platform_device *pdev)
 	return 0;
 
 err_add_udc:
+	device_del(&m66592->gadget.dev);
+
+err_device_add:
 	m66592_free_request(&m66592->ep[0].ep, m66592->ep0_req);
 
 clean_up3:

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

@@ -492,6 +492,7 @@ struct m66592 {
 	int isochronous;
 	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 m66592_to_gadget(m66592) (&m66592->gadget)

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

@@ -16,6 +16,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 
+#include "u_serial.h"
 #if defined USB_ETH_RNDIS
 #  undef USB_ETH_RNDIS
 #endif
@@ -42,9 +43,6 @@ MODULE_LICENSE("GPL");
  */
 #include "f_mass_storage.c"
 
-#include "u_serial.c"
-#include "f_acm.c"
-
 #include "f_ecm.c"
 #include "f_subset.c"
 #ifdef USB_ETH_RNDIS
@@ -137,10 +135,13 @@ static struct fsg_common fsg_common;
 
 static u8 hostaddr[ETH_ALEN];
 
+static unsigned char tty_line;
+static struct usb_function_instance *fi_acm;
 
 /********** RNDIS **********/
 
 #ifdef USB_ETH_RNDIS
+static struct usb_function *f_acm_rndis;
 
 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)
 		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);
 	if (ret < 0)
-		return ret;
+		goto err_fsg;
 
 	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)
@@ -192,6 +203,7 @@ static int rndis_config_register(struct usb_composite_dev *cdev)
 /********** CDC ECM **********/
 
 #ifdef CONFIG_USB_G_MULTI_CDC
+static struct usb_function *f_acm_multi;
 
 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)
 		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);
 	if (ret < 0)
-		return ret;
+		goto err_fsg;
 
 	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)
@@ -243,10 +266,10 @@ static int cdc_config_register(struct usb_composite_dev *cdev)
 
 /****************************** Gadget Bind ******************************/
 
-
 static int __ref multi_bind(struct usb_composite_dev *cdev)
 {
 	struct usb_gadget *gadget = cdev->gadget;
+	struct f_serial_opts *opts;
 	int status;
 
 	if (!can_support_ecm(cdev->gadget)) {
@@ -261,10 +284,19 @@ static int __ref multi_bind(struct usb_composite_dev *cdev)
 		return status;
 
 	/* set up serial link layer */
-	status = gserial_setup(cdev->gadget, 1);
+	status = gserial_alloc_line(&tty_line);
 	if (status < 0)
 		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 */
 	{
 		void *retp;
@@ -301,7 +333,9 @@ static int __ref multi_bind(struct usb_composite_dev *cdev)
 fail2:
 	fsg_common_put(&fsg_common);
 fail1:
-	gserial_cleanup();
+	usb_put_function_instance(fi_acm);
+fail0dot5:
+	gserial_free_line(tty_line);
 fail0:
 	gether_cleanup();
 	return status;
@@ -309,7 +343,14 @@ fail0:
 
 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();
 	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_desc[] = DRIVER_DESC;
 
-/* controller device global variable */
-static struct mv_udc	*the_controller;
-
 static void nuke(struct mv_ep *ep, int status);
 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;
 }
 
-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 */
 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 */
 	.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)
@@ -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;
 	unsigned long flags;
 
-	if (!udc)
-		return -ENODEV;
+	udc = container_of(gadget, struct mv_udc, gadget);
 
 	if (udc->driver)
 		return -EBUSY;
@@ -1399,26 +1394,14 @@ static int mv_udc_start(struct usb_gadget_driver *driver,
 
 	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,
 					&udc->gadget);
 		if (retval) {
 			dev_err(&udc->dev->dev,
 				"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;
 		}
 	}
@@ -1433,13 +1416,13 @@ static int mv_udc_start(struct usb_gadget_driver *driver,
 	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;
 
-	if (!udc)
-		return -ENODEV;
+	udc = container_of(gadget, struct mv_udc, gadget);
 
 	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);
 
 	/* unbind gadget driver */
-	driver->unbind(&udc->gadget);
 	udc->gadget.dev.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)
 {
-	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_udc *udc;
 	unsigned long flags;
 
+	udc = mvep->udc;
+
 	dev_info(&udc->dev->dev, "switch to test mode %d\n", req->test_mode);
 
 	spin_lock_irqsave(&udc->lock, flags);
@@ -2123,15 +2108,18 @@ static void mv_udc_vbus_work(struct work_struct *work)
 /* release device structure */
 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);
 }
 
-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);
 
@@ -2140,57 +2128,27 @@ static int mv_udc_remove(struct platform_device *dev)
 		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 */
 	if (udc->dtd_pool)
 		dma_pool_destroy(udc->dtd_pool);
 
 	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);
 
-	kfree(udc->eps);
-
-	if (udc->irq)
-		free_irq(udc->irq, &dev->dev);
-
 	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);
 
 	/* free dev, wait for the release() finished */
 	wait_for_completion(udc->done);
-	kfree(udc);
-
-	the_controller = NULL;
 
 	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;
 	int retval = 0;
 	int clk_i = 0;
@@ -2198,71 +2156,73 @@ static int mv_udc_probe(struct platform_device *dev)
 	size_t size;
 
 	if (pdata == NULL) {
-		dev_err(&dev->dev, "missing platform_data\n");
+		dev_err(&pdev->dev, "missing platform_data\n");
 		return -ENODEV;
 	}
 
 	size = sizeof(*udc) + sizeof(struct clk *) * pdata->clknum;
-	udc = kzalloc(size, GFP_KERNEL);
+	udc = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
 	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;
 	}
 
-	the_controller = udc;
 	udc->done = &release_done;
-	udc->pdata = dev->dev.platform_data;
+	udc->pdata = pdev->dev.platform_data;
 	spin_lock_init(&udc->lock);
 
-	udc->dev = dev;
+	udc->dev = pdev;
 
 #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
 
 	udc->clknum = pdata->clknum;
 	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])) {
 			retval = PTR_ERR(udc->clk[clk_i]);
-			goto err_put_clk;
+			return retval;
 		}
 	}
 
 	r = platform_get_resource_byname(udc->dev, IORESOURCE_MEM, "capregs");
 	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 *)
-		ioremap(r->start, resource_size(r));
+		devm_ioremap(&pdev->dev, r->start, resource_size(r));
 	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");
 	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));
 	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 */
 	retval = mv_udc_enable_internal(udc);
 	if (retval)
-		goto err_iounmap_phyreg;
+		return retval;
 
 	udc->op_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 = (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);
 
 	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;
 		goto err_disable_clock;
 	}
@@ -2291,7 +2251,7 @@ static int mv_udc_probe(struct platform_device *dev)
 
 	/* create dTD dma_pool resource */
 	udc->dtd_pool = dma_pool_create("mv_dtd",
-			&dev->dev,
+			&pdev->dev,
 			sizeof(struct mv_dtd),
 			DTD_ALIGNMENT,
 			DMA_BOUNDARY);
@@ -2302,19 +2262,20 @@ static int mv_udc_probe(struct platform_device *dev)
 	}
 
 	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) {
-		dev_err(&dev->dev, "allocate ep memory failed\n");
+		dev_err(&pdev->dev, "allocate ep memory failed\n");
 		retval = -ENOMEM;
 		goto err_destroy_dma;
 	}
 
 	/* 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) {
-		dev_err(&dev->dev, "allocate status_req memory failed\n");
+		dev_err(&pdev->dev, "allocate status_req memory failed\n");
 		retval = -ENOMEM;
-		goto err_free_eps;
+		goto err_destroy_dma;
 	}
 	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);
 	if (r == NULL) {
-		dev_err(&dev->dev, "no IRQ resource defined\n");
+		dev_err(&pdev->dev, "no IRQ resource defined\n");
 		retval = -ENODEV;
-		goto err_free_status_req;
+		goto err_destroy_dma;
 	}
 	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)) {
-		dev_err(&dev->dev, "Request irq %d for UDC failed\n",
+		dev_err(&pdev->dev, "Request irq %d for UDC failed\n",
 			udc->irq);
 		retval = -ENODEV;
-		goto err_free_status_req;
+		goto err_destroy_dma;
 	}
 
 	/* initialize gadget structure */
@@ -2351,26 +2312,27 @@ static int mv_udc_probe(struct platform_device *dev)
 
 	/* the "gadget" abstracts/virtualizes the controller */
 	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.name = driver_name;		/* gadget name */
 
 	retval = device_register(&udc->gadget.dev);
 	if (retval)
-		goto err_free_irq;
+		goto err_destroy_dma;
 
 	eps_init(udc);
 
 	/* VBUS detect: we can disable/enable clock on demand.*/
-	if (!IS_ERR_OR_NULL(udc->transceiver))
+	if (udc->transceiver)
 		udc->clock_gating = 1;
 	else if (pdata->vbus) {
 		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);
 		if (retval) {
-			dev_info(&dev->dev,
+			dev_info(&pdev->dev,
 				"Can not request irq for VBUS, "
 				"disable clock gating\n");
 			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");
 		if (!udc->qwork) {
-			dev_err(&dev->dev, "cannot create workqueue\n");
+			dev_err(&pdev->dev, "cannot create workqueue\n");
 			retval = -ENOMEM;
 			goto err_unregister;
 		}
@@ -2396,53 +2358,40 @@ static int mv_udc_probe(struct platform_device *dev)
 	else
 		udc->vbus_active = 1;
 
-	retval = usb_add_gadget_udc(&dev->dev, &udc->gadget);
+	retval = usb_add_gadget_udc(&pdev->dev, &udc->gadget);
 	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");
 
 	return 0;
 
+err_create_workqueue:
+	destroy_workqueue(udc->qwork);
 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);
-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:
 	dma_pool_destroy(udc->dtd_pool);
 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);
 err_disable_clock:
 	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;
 }
 
 #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 (!IS_ERR_OR_NULL(udc->transceiver))
+	if (udc->transceiver)
 		return 0;
 
 	if (udc->pdata->vbus && udc->pdata->vbus->poll)
@@ -2469,13 +2418,15 @@ static int mv_udc_suspend(struct device *_dev)
 	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;
 
+	udc = dev_get_drvdata(dev);
+
 	/* if OTG is enabled, the following will be done in OTG driver*/
-	if (!IS_ERR_OR_NULL(udc->transceiver))
+	if (udc->transceiver)
 		return 0;
 
 	if (!udc->clock_gating) {
@@ -2499,11 +2450,12 @@ static const struct dev_pm_ops mv_udc_pm_ops = {
 };
 #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;
 
+	udc = platform_get_drvdata(pdev);
 	/* reset controller mode to IDLE */
 	mv_udc_enable(udc);
 	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 = {
 	.probe		= mv_udc_probe,
-	.remove		= __exit_p(mv_udc_remove),
+	.remove		= mv_udc_remove,
 	.shutdown	= mv_udc_shutdown,
 	.driver		= {
 		.owner	= THIS_MODULE,

+ 15 - 0
drivers/usb/gadget/net2280.c

@@ -116,6 +116,10 @@ static bool enable_suspend = 0;
 /* "modprobe net2280 enable_suspend=1" etc */
 module_param (enable_suspend, bool, S_IRUGO);
 
+/* force full-speed operation */
+static bool full_speed;
+module_param(full_speed, bool, 0444);
+MODULE_PARM_DESC(full_speed, "force full-speed mode -- for testing only!");
 
 #define	DIR_STRING(bAddress) (((bAddress) & USB_DIR_IN) ? "in" : "out")
 
@@ -1899,6 +1903,10 @@ static int net2280_start(struct usb_gadget *_gadget,
 	retval = device_create_file (&dev->pdev->dev, &dev_attr_queues);
 	if (retval) goto err_func;
 
+	/* Enable force-full-speed testing mode, if desired */
+	if (full_speed)
+		writel(1 << FORCE_FULL_SPEED_MODE, &dev->usb->xcvrdiag);
+
 	/* ... then enable host detection and ep0; and we're ready
 	 * for set_configuration as well as eventual disconnect.
 	 */
@@ -1957,6 +1965,10 @@ static int net2280_stop(struct usb_gadget *_gadget,
 	dev->driver = NULL;
 
 	net2280_led_active (dev, 0);
+
+	/* Disable full-speed test mode */
+	writel(0, &dev->usb->xcvrdiag);
+
 	device_remove_file (&dev->pdev->dev, &dev_attr_function);
 	device_remove_file (&dev->pdev->dev, &dev_attr_queues);
 
@@ -2841,6 +2853,9 @@ static void net2280_shutdown (struct pci_dev *pdev)
 
 	/* disable the pullup so the host will think we're gone */
 	writel (0, &dev->usb->usbctl);
+
+	/* Disable full-speed test mode */
+	writel(0, &dev->usb->xcvrdiag);
 }
 
 

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

@@ -37,7 +37,7 @@
  * the runtime footprint, and giving us at least some parts of what
  * 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_ecm.c"
 #include "f_obex.c"
@@ -101,6 +101,15 @@ MODULE_LICENSE("GPL");
 
 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)
 {
 	int status = 0;
@@ -109,15 +118,15 @@ static int __init nokia_bind_config(struct usb_configuration *c)
 	if (status)
 		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)
 		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)
 		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)
 		printk(KERN_DEBUG "could not bind acm config\n");
 
@@ -133,7 +142,7 @@ static struct usb_configuration nokia_config_500ma_driver = {
 	.bConfigurationValue = 1,
 	/* .iConfiguration = DYNAMIC */
 	.bmAttributes	= USB_CONFIG_ATT_ONE,
-	.bMaxPower	= 250, /* 500mA */
+	.MaxPower	= 500,
 };
 
 static struct usb_configuration nokia_config_100ma_driver = {
@@ -141,21 +150,24 @@ static struct usb_configuration nokia_config_100ma_driver = {
 	.bConfigurationValue = 2,
 	/* .iConfiguration = DYNAMIC */
 	.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)
 {
 	struct usb_gadget	*gadget = cdev->gadget;
 	int			status;
+	int			cur_line;
 
 	status = gphonet_setup(cdev->gadget);
 	if (status < 0)
 		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);
 	if (status < 0)
@@ -192,8 +204,10 @@ static int __init nokia_bind(struct usb_composite_dev *cdev)
 err_usb:
 	gether_cleanup();
 err_ether:
-	gserial_cleanup();
-err_serial:
+	cur_line--;
+	while (cur_line >= 0)
+		gserial_free_line(tty_lines[cur_line--]);
+
 	gphonet_cleanup();
 err_phonet:
 	return status;
@@ -201,8 +215,13 @@ err_phonet:
 
 static int __exit nokia_unbind(struct usb_composite_dev *cdev)
 {
+	int i;
+
 	gphonet_cleanup();
-	gserial_cleanup();
+
+	for (i = 0; i < TTY_PORTS_MAX; i++)
+		gserial_free_line(tty_lines[i]);
+
 	gether_cleanup();
 
 	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;
 }
 
-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,
 	.wakeup			= omap_wakeup,
 	.set_selfpowered	= omap_set_selfpowered,
 	.vbus_session		= omap_vbus_session,
 	.vbus_draw		= omap_vbus_draw,
 	.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();
 }
 
-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;
 	struct omap_ep	*ep;
 	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);
-	if (udc->driver) {
-		spin_unlock_irqrestore(&udc->lock, flags);
-		return -EBUSY;
-	}
-
 	/* reset state */
 	list_for_each_entry(ep, &udc->gadget.ep_list, ep.ep_list) {
 		ep->irqs = 0;
@@ -2084,15 +2072,6 @@ static int omap_udc_start(struct usb_gadget_driver *driver,
 	if (udc->dc_clk != NULL)
 		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);
 
 	/* connect to bus through transceiver */
@@ -2124,19 +2103,16 @@ static int omap_udc_start(struct usb_gadget_driver *driver,
 done:
 	if (udc->dc_clk != NULL)
 		omap_udc_enable_clock(0);
+
 	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;
 	int		status = -ENODEV;
 
-	if (!udc)
-		return -ENODEV;
-	if (!driver || driver != udc->driver || !driver->unbind)
-		return -EINVAL;
-
 	if (udc->dc_clk != NULL)
 		omap_udc_enable_clock(1);
 
@@ -2152,13 +2128,12 @@ static int omap_udc_stop(struct usb_gadget_driver *driver)
 	udc_quiesce(udc);
 	spin_unlock_irqrestore(&udc->lock, flags);
 
-	driver->unbind(&udc->gadget);
 	udc->gadget.dev.driver = NULL;
 	udc->driver = NULL;
 
 	if (udc->dc_clk != NULL)
 		omap_udc_enable_clock(0);
-	DBG("unregistered driver '%s'\n", driver->driver.name);
+
 	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_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 PCI_DEVICE_ID_INTEL_EG20T_UDC	0x8808
@@ -384,7 +385,6 @@ struct pch_udc_dev {
 
 static const char	ep0_string[] = "ep0in";
 static DEFINE_SPINLOCK(udc_stall_spinlock);	/* stall spin lock */
-struct pch_udc_dev *pch_udc;		/* pointer to device object */
 static bool speed_fs;
 module_param_named(speed_fs, speed_fs, bool, S_IRUGO);
 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;
 }
 
-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 = {
 	.get_frame = pch_udc_pcd_get_frame,
 	.wakeup = pch_udc_pcd_wakeup,
@@ -1245,8 +1246,8 @@ static const struct usb_gadget_ops pch_udc_ops = {
 	.pullup = pch_udc_pcd_pullup,
 	.vbus_session = pch_udc_pcd_vbus_session,
 	.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;
 }
 
-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;
 	dev->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 */
 	pch_udc_setup_ep0(dev);
 
@@ -3026,30 +3002,21 @@ static int pch_udc_start(struct usb_gadget_driver *driver,
 	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);
 
 	/* Assures that there are no pending requests with this driver */
-	driver->disconnect(&dev->gadget);
-	driver->unbind(&dev->gadget);
 	dev->gadget.dev.driver = NULL;
 	dev->driver = NULL;
 	dev->connected = 0;
 
 	/* set SD */
 	pch_udc_set_disconnect(dev);
+
 	return 0;
 }
 
@@ -3164,11 +3131,6 @@ static int pch_udc_probe(struct pci_dev *pdev,
 	int			retval;
 	struct pch_udc_dev	*dev;
 
-	/* one udc only */
-	if (pch_udc) {
-		pr_err("%s: already probed\n", __func__);
-		return -EBUSY;
-	}
 	/* init */
 	dev = kzalloc(sizeof *dev, GFP_KERNEL);
 	if (!dev) {
@@ -3207,7 +3169,6 @@ static int pch_udc_probe(struct pci_dev *pdev,
 		retval = -ENODEV;
 		goto finished;
 	}
-	pch_udc = dev;
 	/* initialize the hardware */
 	if (pch_udc_pcd_init(dev)) {
 		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;
 }
 
-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 = {
 	.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,
 	.pullup		= pxa25x_udc_pullup,
 	.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
  * 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;
 
-	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 ... */
 	dev->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);
 	if (retval) {
-fail:
 		dev->driver = NULL;
 		dev->gadget.dev.driver = NULL;
 		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
 	 * for set_configuration as well as eventual disconnect.
 	 */
-	DMSG("registered gadget driver '%s'\n", driver->driver.name);
-
 	/* connect to bus through transceiver */
 	if (!IS_ERR_OR_NULL(dev->transceiver)) {
 		retval = otg_set_peripheral(dev->transceiver->otg,
 						&dev->gadget);
-		if (retval) {
-			DMSG("can't bind to transceiver\n");
-			if (driver->unbind)
-				driver->unbind(&dev->gadget);
+		if (retval)
 			goto bind_fail;
-		}
 	}
 
 	pullup(dev);
@@ -1334,22 +1310,14 @@ stop_activity(struct pxa25x_udc *dev, struct usb_gadget_driver *driver)
 	}
 	del_timer_sync(&dev->timer);
 
-	/* report disconnect; the driver is already quiesced */
-	if (driver)
-		driver->disconnect(&dev->gadget);
-
 	/* re-init driver-visible data structures */
 	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();
 	dev->pullup = 0;
@@ -1360,14 +1328,12 @@ static int pxa25x_stop(struct usb_gadget_driver *driver)
 	if (!IS_ERR_OR_NULL(dev->transceiver))
 		(void) otg_set_peripheral(dev->transceiver->otg, NULL);
 
-	driver->unbind(&dev->gadget);
 	dev->gadget.dev.driver = NULL;
 	dev->driver = NULL;
 
 	device_del (&dev->gadget.dev);
-
-	DMSG("unregistered gadget driver '%s'\n", driver->driver.name);
 	dump_state(dev);
+
 	return 0;
 }
 

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

@@ -126,6 +126,7 @@ struct pxa25x_udc {
 	struct dentry				*debugfs_udc;
 #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;
 }
 
-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 = {
 	.get_frame	= pxa_udc_get_frame,
@@ -1681,8 +1682,8 @@ static const struct usb_gadget_ops pxa_udc_ops = {
 	.pullup		= pxa_udc_pullup,
 	.vbus_session	= pxa_udc_vbus_session,
 	.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
  */
-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;
 
-	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 ... */
 	udc->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);
 	if (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)) {
 		retval = otg_set_peripheral(udc->transceiver->otg,
 						&udc->gadget);
 		if (retval) {
 			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);
 	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->gadget.dev.driver = NULL;
 	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++)
 		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
  */
-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);
 	udc_disable(udc);
 	dplus_pullup(udc, 0);
 
-	driver->unbind(&udc->gadget);
 	udc->driver = NULL;
 
 	device_del(&udc->gadget.dev);
-	dev_info(udc->dev, "unregistered gadget driver '%s'\n",
-		 driver->driver.name);
 
 	if (!IS_ERR_OR_NULL(udc->transceiver))
 		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;
 #endif
 };
+#define to_pxa(g)	(container_of((g), struct pxa_udc, 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;
 }
 
-static struct usb_gadget_ops r8a66597_gadget_ops = {
+static const struct usb_gadget_ops r8a66597_gadget_ops = {
 	.get_frame		= r8a66597_get_frame,
 	.udc_start		= r8a66597_start,
 	.udc_stop		= r8a66597_stop,

+ 29 - 15
drivers/usb/gadget/s3c-hsotg.c

@@ -32,6 +32,7 @@
 
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
+#include <linux/usb/phy.h>
 #include <linux/platform_data/s3c-hsotg.h>
 
 #include <mach/map.h>
@@ -133,7 +134,9 @@ struct s3c_hsotg_ep {
  * struct s3c_hsotg - driver state.
  * @dev: The parent device supplied to the probe function
  * @driver: USB gadget driver
- * @plat: The platform specific configuration data.
+ * @phy: The otg phy transceiver structure for phy control.
+ * @plat: The platform specific configuration data. This can be removed once
+ * all SoCs support usb transceiver.
  * @regs: The memory area mapped for accessing registers.
  * @irq: The IRQ number we are using
  * @supplies: Definition of USB power supplies
@@ -153,6 +156,7 @@ struct s3c_hsotg_ep {
 struct s3c_hsotg {
 	struct device		 *dev;
 	struct usb_gadget_driver *driver;
+	struct usb_phy		*phy;
 	struct s3c_hsotg_plat	 *plat;
 
 	spinlock_t              lock;
@@ -2854,7 +2858,10 @@ static void s3c_hsotg_phy_enable(struct s3c_hsotg *hsotg)
 	struct platform_device *pdev = to_platform_device(hsotg->dev);
 
 	dev_dbg(hsotg->dev, "pdev 0x%p\n", pdev);
-	if (hsotg->plat->phy_init)
+
+	if (hsotg->phy)
+		usb_phy_init(hsotg->phy);
+	else if (hsotg->plat->phy_init)
 		hsotg->plat->phy_init(pdev, hsotg->plat->phy_type);
 }
 
@@ -2869,7 +2876,9 @@ static void s3c_hsotg_phy_disable(struct s3c_hsotg *hsotg)
 {
 	struct platform_device *pdev = to_platform_device(hsotg->dev);
 
-	if (hsotg->plat->phy_exit)
+	if (hsotg->phy)
+		usb_phy_shutdown(hsotg->phy);
+	else if (hsotg->plat->phy_exit)
 		hsotg->plat->phy_exit(pdev, hsotg->plat->phy_type);
 }
 
@@ -3055,7 +3064,7 @@ static int s3c_hsotg_pullup(struct usb_gadget *gadget, int is_on)
 	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,
 	.udc_start		= s3c_hsotg_udc_start,
 	.udc_stop		= s3c_hsotg_udc_stop,
@@ -3492,6 +3501,7 @@ static void s3c_hsotg_release(struct device *dev)
 static int s3c_hsotg_probe(struct platform_device *pdev)
 {
 	struct s3c_hsotg_plat *plat = pdev->dev.platform_data;
+	struct usb_phy *phy;
 	struct device *dev = &pdev->dev;
 	struct s3c_hsotg_ep *eps;
 	struct s3c_hsotg *hsotg;
@@ -3500,20 +3510,27 @@ static int s3c_hsotg_probe(struct platform_device *pdev)
 	int ret;
 	int i;
 
-	plat = pdev->dev.platform_data;
-	if (!plat) {
-		dev_err(&pdev->dev, "no platform data defined\n");
-		return -EINVAL;
-	}
-
 	hsotg = devm_kzalloc(&pdev->dev, sizeof(struct s3c_hsotg), GFP_KERNEL);
 	if (!hsotg) {
 		dev_err(dev, "cannot get memory\n");
 		return -ENOMEM;
 	}
 
+	phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
+	if (IS_ERR_OR_NULL(phy)) {
+		/* Fallback for pdata */
+		plat = pdev->dev.platform_data;
+		if (!plat) {
+			dev_err(&pdev->dev, "no platform data or transceiver defined\n");
+			return -EPROBE_DEFER;
+		} else {
+			hsotg->plat = plat;
+		}
+	} else {
+		hsotg->phy = phy;
+	}
+
 	hsotg->dev = dev;
-	hsotg->plat = plat;
 
 	hsotg->clk = devm_clk_get(&pdev->dev, "otg");
 	if (IS_ERR(hsotg->clk)) {
@@ -3571,7 +3588,7 @@ static int s3c_hsotg_probe(struct platform_device *pdev)
 	for (i = 0; i < ARRAY_SIZE(hsotg->supplies); 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);
 	if (ret) {
 		dev_err(dev, "failed to request supplies: %d\n", ret);
@@ -3661,8 +3678,6 @@ err_ep_mem:
 	kfree(eps);
 err_supplies:
 	s3c_hsotg_phy_disable(hsotg);
-	regulator_bulk_free(ARRAY_SIZE(hsotg->supplies), hsotg->supplies);
-
 err_clk:
 	clk_disable_unprepare(hsotg->clk);
 
@@ -3687,7 +3702,6 @@ static int s3c_hsotg_remove(struct platform_device *pdev)
 	}
 
 	s3c_hsotg_phy_disable(hsotg);
-	regulator_bulk_free(ARRAY_SIZE(hsotg->supplies), hsotg->supplies);
 
 	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;
 	u32 csr;
 
-	csr = readl((u32)hsudc->regs + S3C_ESR);
+	csr = readl(hsudc->regs + S3C_ESR);
 	if (csr & S3C_ESR_STALL) {
 		writel(S3C_ESR_STALL, hsudc->regs + S3C_ESR);
 		return;
@@ -468,7 +468,7 @@ static void s3c_hsudc_epout_intr(struct s3c_hsudc *hsudc, u32 ep_idx)
 	struct s3c_hsudc_req *hsreq;
 	u32 csr;
 
-	csr = readl((u32)hsudc->regs + S3C_ESR);
+	csr = readl(hsudc->regs + S3C_ESR);
 	if (csr & S3C_ESR_STALL) {
 		writel(S3C_ESR_STALL, hsudc->regs + S3C_ESR);
 		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) {
 		offset = (ep_index(hsep)) ? S3C_ESR : S3C_EP0SR;
 		if (ep_is_in(hsep)) {
-			csr = readl((u32)hsudc->regs + offset);
+			csr = readl(hsudc->regs + offset);
 			if (!(csr & S3C_ESR_TX_SUCCESS) &&
 				(s3c_hsudc_write_fifo(hsep, hsreq) == 1))
 				hsreq = NULL;
 		} else {
-			csr = readl((u32)hsudc->regs + offset);
+			csr = readl(hsudc->regs + offset);
 			if ((csr & S3C_ESR_RX_SUCCESS)
 				   && (s3c_hsudc_read_fifo(hsep, hsreq) == 1))
 				hsreq = NULL;
@@ -1254,7 +1254,7 @@ static int s3c_hsudc_vbus_draw(struct usb_gadget *gadget, unsigned mA)
 	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,
 	.udc_start	= s3c_hsudc_start,
 	.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++)
 		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);
 	if (ret != 0) {
 		dev_err(dev, "failed to request supplies: %d\n", ret);
@@ -1366,7 +1366,6 @@ err_res:
 	if (!IS_ERR_OR_NULL(hsudc->transceiver))
 		usb_put_phy(hsudc->transceiver);
 
-	regulator_bulk_free(ARRAY_SIZE(hsudc->supplies), hsudc->supplies);
 err_supplies:
 	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;
 }
 
-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 = {
 	.get_frame		= s3c2410_udc_get_frame,
@@ -1549,8 +1550,8 @@ static const struct usb_gadget_ops s3c2410_ops = {
 	.pullup			= s3c2410_udc_pullup,
 	.vbus_session		= s3c2410_udc_vbus_session,
 	.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)
@@ -1664,33 +1665,14 @@ static void s3c2410_udc_enable(struct s3c2410_udc *dev)
 	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;
 
 	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 */
 	udc->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;
 	}
 
-	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 */
 	s3c2410_udc_enable(udc);
 
@@ -1722,24 +1695,10 @@ register_error:
 	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);
 	udc->driver = NULL;

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

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

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

@@ -36,10 +36,8 @@
  * 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_acm.c"
 #include "f_obex.c"
 #include "f_serial.c"
-#include "u_serial.c"
 
 /*-------------------------------------------------------------------------*/
 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");
 
 /*-------------------------------------------------------------------------*/
+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;
 	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;
 }
 
@@ -152,13 +155,70 @@ static struct usb_configuration serial_config_driver = {
 	.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)
 {
 	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
 	 * 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 */
-	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)
 		goto fail;
 
@@ -189,16 +257,31 @@ static int __init gs_bind(struct usb_composite_dev *cdev)
 	return 0;
 
 fail:
-	gserial_cleanup();
+	cur_line--;
+	while (cur_line >= 0)
+		gserial_free_line(tty_lines[cur_line--]);
 	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 = {
 	.name		= "g_serial",
 	.dev		= &device_desc,
 	.strings	= dev_strings,
 	.max_speed	= USB_SPEED_SUPER,
 	.bind		= gs_bind,
+	.unbind		= gs_unbind,
 };
 
 static int __init init(void)
@@ -234,6 +317,5 @@ module_init(init);
 static void __exit cleanup(void)
 {
 	usb_composite_unregister(&gserial_driver);
-	gserial_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 */
 #define MAX_COMMAND_SIZE	16
 
@@ -385,41 +373,6 @@ static struct usb_ss_ep_comp_descriptor fsg_ss_bulk_out_comp_desc = {
 	/*.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[] = {
 	(struct usb_descriptor_header *) &fsg_intf_desc,
 	(struct usb_descriptor_header *) &fsg_ss_bulk_in_desc,
@@ -429,20 +382,6 @@ static struct usb_descriptor_header *fsg_ss_function[] = {
 	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 struct usb_string		fsg_strings[] = {
 	{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/slab.h>
 #include <linux/export.h>
+#include <linux/module.h>
 
 #include "u_serial.h"
 
@@ -35,11 +36,12 @@
  * "serial port" functionality through the USB gadget stack.  Each such
  * 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.
  * 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 */
 };
 
-/* increase N_PORTS if you need more */
-#define N_PORTS		4
 static struct portmaster {
 	struct mutex	lock;			/* protect open/close */
 	struct gs_port	*port;
-} ports[N_PORTS];
-static unsigned	n_ports;
+} ports[MAX_U_SERIAL_PORTS];
 
 #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;
 }
+EXPORT_SYMBOL_GPL(gs_alloc_req);
 
 /*
  * gs_free_req
@@ -320,6 +320,7 @@ void gs_free_req(struct usb_ep *ep, struct usb_request *req)
 	kfree(req->buf);
 	usb_ep_free_request(ep, req);
 }
+EXPORT_SYMBOL_GPL(gs_free_req);
 
 /*
  * gs_send_packet
@@ -1030,10 +1031,19 @@ static int
 gs_port_alloc(unsigned port_num, struct usb_cdc_line_coding *coding)
 {
 	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);
-	if (port == NULL)
-		return -ENOMEM;
+	if (port == NULL) {
+		ret = -ENOMEM;
+		goto out;
+	}
 
 	tty_port_init(&port->port);
 	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;
 
 	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)
@@ -1164,55 +1074,77 @@ static int gs_closed(struct gs_port *port)
 	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;
 
-	if (!gs_tty_driver)
+	mutex_lock(&ports[port_num].lock);
+	if (WARN_ON(!ports[port_num].port)) {
+		mutex_unlock(&ports[port_num].lock);
 		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
@@ -1229,8 +1161,8 @@ void gserial_cleanup(void)
  *
  * Caller needs to have set up the endpoints and USB function in @dev
  * 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.
  * On success, ep->driver_data will be overwritten.
@@ -1241,11 +1173,18 @@ int gserial_connect(struct gserial *gser, u8 port_num)
 	unsigned long	flags;
 	int		status;
 
-	if (!gs_tty_driver || port_num >= n_ports)
+	if (port_num >= MAX_U_SERIAL_PORTS)
 		return -ENXIO;
 
-	/* we "know" gserial_cleanup() hasn't been called */
 	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 */
 	status = usb_ep_enable(gser->in);
@@ -1292,7 +1231,7 @@ fail_out:
 	gser->in->driver_data = NULL;
 	return status;
 }
-
+EXPORT_SYMBOL_GPL(gserial_connect);
 /**
  * gserial_disconnect - notify TTY I/O glue that USB link is inactive
  * @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);
 }
+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/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
  * 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);
 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 */
 int gserial_connect(struct gserial *, u8 port_num);

Some files were not shown because too many files changed in this diff