Эх сурвалжийг харах

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

Felipe writes:

usb: patches for v3.10 merge window

Here is the big Gadget & PHY pull request. Many of us have
been really busy lately getting multiple drivers to a better
position.

Since this pull request is so large, I will divide it in sections
so it's easier to grasp what's included.

- cleanups:
	. UDC drivers no longer touch gadget->dev, that's now udc-core
		responsibility
	. Many more UDC drivers converted to usb_gadget_map/unmap_request()
	. UDC drivers no longer initialize DMA-related fields from gadget's
		device structure
	. UDC drivers don't touch gadget.dev.driver directly
	. UDC drivers don't assign gadget.dev.release directly
	. Removal of some unused DMA_ADDR_INVALID
	. Introduction of CONFIG_USB_PHY
	. All phy drivers have been moved to drivers/usb/phy and renamed to
		a common naming scheme
	. Fix PHY layer so it never returns a NULL pointer, also fix all
		callers to avoid using IS_ERR_OR_NULL()
	. Sparse fixes all over the place
	. drivers/usb/otg/ has been deleted
	. Marvel drivers (mv_udc, ehci-mv, mv_otg and mv_u3d) improved clock
		usage

- new features:
	. UDC core now provides a generic way for tracking and reporting
		UDC's state (not attached, resuming, suspended, addressed,
		default, etc)
	. twl4030-usb learned that it shouldn't be enabled during init
	. Full DT support for DWC3 has been implemented
	. ab8500-usb learned about pinctrl framework
	. nop PHY learned about DeviceTree and regulators
	. DWC3 learned about suspend/resume
	. DWC3 can now be compiled in host-only and gadget-only (as well as
		DRD) configurations
	. UVC now enables streaming endpoint based on negotiated speed
	. isp1301 now implements the PHY API properly
	. configfs-based interface for gadget drivers which will lead to
		the removal of all code which just combines functions together
		to build functional gadget drivers.
	. f_serial and f_obex were converted to new configfs interface while
		maintaining old interface around.

- non-critical fixes:
	. UVC gadget driver got fixes for Endpoint usage and stream calculation
	. ab8500-usb fixed unbalanced clock and regulator API usage
	. twl4030-usb got a fix for when OMAP3 is booted with cable connected
	. fusb300_udc got a fix for DMA usage
	. UVC got fixes for two assertions of the USB Video Class Compliance
		specification revision 1.1
	. build warning issues caused by recent addition of __must_check to
		regulator API

These are all changes which deserve a mention, all other changes are related
to these one or minor spelling fixes and other similar tasks.

Signed-of-by: Felipe Balbi <balbi@ti.com>
Greg Kroah-Hartman 12 жил өмнө
parent
commit
64dc9e2e73
100 өөрчлөгдсөн 3196 нэмэгдсэн , 2310 устгасан
  1. 34 6
      Documentation/devicetree/bindings/usb/omap-usb.txt
  2. 69 7
      Documentation/devicetree/bindings/usb/samsung-usbphy.txt
  3. 34 0
      Documentation/devicetree/bindings/usb/usb-nop-xceiv.txt
  4. 0 6
      arch/arm/mach-mmp/aspenite.c
  5. 0 6
      arch/arm/mach-mmp/ttc_dkb.c
  6. 6 2
      arch/arm/mach-shmobile/board-armadillo800eva.c
  7. 6 2
      arch/arm/mach-shmobile/board-kzm9g.c
  8. 9 3
      arch/arm/mach-shmobile/board-mackerel.c
  9. 4 4
      arch/arm/mach-tegra/Kconfig
  10. 3 1
      arch/sh/boards/mach-ecovec24/setup.c
  11. 1 1
      drivers/Makefile
  12. 1 1
      drivers/power/Kconfig
  13. 7 7
      drivers/power/pda_power.c
  14. 0 2
      drivers/usb/Kconfig
  15. 1 3
      drivers/usb/Makefile
  16. 1 26
      drivers/usb/chipidea/udc.c
  17. 0 1
      drivers/usb/dwc3/Kconfig
  18. 182 19
      drivers/usb/dwc3/core.c
  19. 62 10
      drivers/usb/dwc3/core.h
  20. 31 21
      drivers/usb/dwc3/debugfs.c
  21. 63 35
      drivers/usb/dwc3/dwc3-exynos.c
  22. 119 126
      drivers/usb/dwc3/dwc3-omap.c
  23. 38 0
      drivers/usb/dwc3/dwc3-pci.c
  24. 21 12
      drivers/usb/dwc3/ep0.c
  25. 230 91
      drivers/usb/dwc3/gadget.c
  26. 11 7
      drivers/usb/gadget/Kconfig
  27. 9 4
      drivers/usb/gadget/Makefile
  28. 1 14
      drivers/usb/gadget/acm_ms.c
  29. 2 14
      drivers/usb/gadget/amd5536udc.c
  30. 0 1
      drivers/usb/gadget/amd5536udc.h
  31. 1 13
      drivers/usb/gadget/at91_udc.c
  32. 6 38
      drivers/usb/gadget/atmel_usba_udc.c
  33. 0 6
      drivers/usb/gadget/atmel_usba_udc.h
  34. 0 23
      drivers/usb/gadget/bcm63xx_udc.c
  35. 7 20
      drivers/usb/gadget/cdc2.c
  36. 1 0
      drivers/usb/gadget/composite.c
  37. 1003 0
      drivers/usb/gadget/configfs.c
  38. 1 18
      drivers/usb/gadget/dummy_hcd.c
  39. 10 10
      drivers/usb/gadget/ether.c
  40. 73 64
      drivers/usb/gadget/f_acm.c
  41. 3 1
      drivers/usb/gadget/f_ecm.c
  42. 2 1
      drivers/usb/gadget/f_eem.c
  43. 3 1
      drivers/usb/gadget/f_ncm.c
  44. 180 46
      drivers/usb/gadget/f_obex.c
  45. 2 1
      drivers/usb/gadget/f_rndis.c
  46. 130 44
      drivers/usb/gadget/f_serial.c
  47. 3 1
      drivers/usb/gadget/f_subset.c
  48. 129 133
      drivers/usb/gadget/f_uvc.c
  49. 6 6
      drivers/usb/gadget/f_uvc.h
  50. 2 16
      drivers/usb/gadget/fsl_qe_udc.c
  51. 17 66
      drivers/usb/gadget/fsl_udc_core.c
  52. 14 32
      drivers/usb/gadget/fusb300_udc.c
  53. 1 1
      drivers/usb/gadget/fusb300_udc.h
  54. 21 14
      drivers/usb/gadget/g_ffs.c
  55. 2 18
      drivers/usb/gadget/goku_udc.c
  56. 1 2
      drivers/usb/gadget/goku_udc.h
  57. 1 15
      drivers/usb/gadget/imx_udc.c
  58. 4 47
      drivers/usb/gadget/lpc32xx_udc.c
  59. 0 17
      drivers/usb/gadget/m66592-udc.c
  60. 9 20
      drivers/usb/gadget/multi.c
  61. 23 42
      drivers/usb/gadget/mv_u3d_core.c
  62. 1 2
      drivers/usb/gadget/mv_udc.h
  63. 28 89
      drivers/usb/gadget/mv_udc_core.c
  64. 7 6
      drivers/usb/gadget/ncm.c
  65. 6 19
      drivers/usb/gadget/net2272.c
  66. 6 19
      drivers/usb/gadget/net2280.c
  67. 62 33
      drivers/usb/gadget/nokia.c
  68. 4 17
      drivers/usb/gadget/omap_udc.c
  69. 6 15
      drivers/usb/gadget/pch_udc.c
  70. 0 16
      drivers/usb/gadget/pxa25x_udc.c
  71. 10 41
      drivers/usb/gadget/pxa27x_udc.c
  72. 1 13
      drivers/usb/gadget/r8a66597-udc.c
  73. 6 72
      drivers/usb/gadget/s3c-hsotg.c
  74. 0 16
      drivers/usb/gadget/s3c-hsudc.c
  75. 0 15
      drivers/usb/gadget/s3c2410_udc.c
  76. 7 52
      drivers/usb/gadget/serial.c
  77. 10 22
      drivers/usb/gadget/u_ether.c
  78. 16 11
      drivers/usb/gadget/u_ether.h
  79. 0 1
      drivers/usb/gadget/u_serial.h
  80. 80 10
      drivers/usb/gadget/udc-core.c
  81. 1 2
      drivers/usb/gadget/uvc.h
  82. 171 367
      drivers/usb/gadget/uvc_queue.c
  83. 13 19
      drivers/usb/gadget/uvc_queue.h
  84. 40 31
      drivers/usb/gadget/uvc_v4l2.c
  85. 20 11
      drivers/usb/gadget/uvc_video.c
  86. 1 1
      drivers/usb/host/Kconfig
  87. 1 1
      drivers/usb/host/ehci-msm.c
  88. 19 35
      drivers/usb/host/ehci-mv.c
  89. 1 1
      drivers/usb/host/ehci-s5p.c
  90. 3 9
      drivers/usb/host/ehci-tegra.c
  91. 1 1
      drivers/usb/host/ohci-exynos.c
  92. 3 3
      drivers/usb/musb/Kconfig
  93. 4 4
      drivers/usb/musb/am35x.c
  94. 3 3
      drivers/usb/musb/blackfin.c
  95. 3 14
      drivers/usb/musb/cppi_dma.c
  96. 4 4
      drivers/usb/musb/da8xx.c
  97. 2 2
      drivers/usb/musb/davinci.c
  98. 33 38
      drivers/usb/musb/musb_core.c
  99. 7 7
      drivers/usb/musb/musb_dsps.c
  100. 16 140
      drivers/usb/musb/musb_gadget.c

+ 34 - 6
Documentation/devicetree/bindings/usb/omap-usb.txt

@@ -8,10 +8,10 @@ OMAP MUSB GLUE
    and disconnect.
    and disconnect.
  - multipoint : Should be "1" indicating the musb controller supports
  - multipoint : Should be "1" indicating the musb controller supports
    multipoint. This is a MUSB configuration-specific setting.
    multipoint. This is a MUSB configuration-specific setting.
- - num_eps : Specifies the number of endpoints. This is also a
+ - num-eps : Specifies the number of endpoints. This is also a
    MUSB configuration-specific setting. Should be set to "16"
    MUSB configuration-specific setting. Should be set to "16"
- - ram_bits : Specifies the ram address size. Should be set to "12"
- - interface_type : This is a board specific setting to describe the type of
+ - ram-bits : Specifies the ram address size. Should be set to "12"
+ - interface-type : This is a board specific setting to describe the type of
    interface between the controller and the phy. It should be "0" or "1"
    interface between the controller and the phy. It should be "0" or "1"
    specifying ULPI and UTMI respectively.
    specifying ULPI and UTMI respectively.
  - mode : Should be "3" to represent OTG. "1" signifies HOST and "2"
  - mode : Should be "3" to represent OTG. "1" signifies HOST and "2"
@@ -29,18 +29,46 @@ usb_otg_hs: usb_otg_hs@4a0ab000 {
 	ti,hwmods = "usb_otg_hs";
 	ti,hwmods = "usb_otg_hs";
 	ti,has-mailbox;
 	ti,has-mailbox;
 	multipoint = <1>;
 	multipoint = <1>;
-	num_eps = <16>;
-	ram_bits = <12>;
+	num-eps = <16>;
+	ram-bits = <12>;
 	ctrl-module = <&omap_control_usb>;
 	ctrl-module = <&omap_control_usb>;
 };
 };
 
 
 Board specific device node entry
 Board specific device node entry
 &usb_otg_hs {
 &usb_otg_hs {
-	interface_type = <1>;
+	interface-type = <1>;
 	mode = <3>;
 	mode = <3>;
 	power = <50>;
 	power = <50>;
 };
 };
 
 
+OMAP DWC3 GLUE
+ - compatible : Should be "ti,dwc3"
+ - ti,hwmods : Should be "usb_otg_ss"
+ - reg : Address and length of the register set for the device.
+ - interrupts : The irq number of this device that is used to interrupt the
+   MPU
+ - #address-cells, #size-cells : Must be present if the device has sub-nodes
+ - utmi-mode : controls the source of UTMI/PIPE status for VBUS and OTG ID.
+   It should be set to "1" for HW mode and "2" for SW mode.
+ - ranges: the child address space are mapped 1:1 onto the parent address space
+
+Sub-nodes:
+The dwc3 core should be added as subnode to omap dwc3 glue.
+- dwc3 :
+   The binding details of dwc3 can be found in:
+   Documentation/devicetree/bindings/usb/dwc3.txt
+
+omap_dwc3 {
+	compatible = "ti,dwc3";
+	ti,hwmods = "usb_otg_ss";
+	reg = <0x4a020000 0x1ff>;
+	interrupts = <0 93 4>;
+	#address-cells = <1>;
+	#size-cells = <1>;
+	utmi-mode = <2>;
+	ranges;
+};
+
 OMAP CONTROL USB
 OMAP CONTROL USB
 
 
 Required properties:
 Required properties:

+ 69 - 7
Documentation/devicetree/bindings/usb/samsung-usbphy.txt

@@ -1,20 +1,25 @@
-* Samsung's usb phy transceiver
+SAMSUNG USB-PHY controllers
 
 
-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.
+** Samsung's usb 2.0 phy transceiver
+
+The Samsung's usb 2.0 phy transceiver is used for controlling
+usb 2.0 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
 TODO: Adding the PHY binding with controller(s) according to the under
 developement generic PHY driver.
 developement generic PHY driver.
 
 
 Required properties:
 Required properties:
 
 
 Exynos4210:
 Exynos4210:
-- compatible : should be "samsung,exynos4210-usbphy"
+- compatible : should be "samsung,exynos4210-usb2phy"
 - reg : base physical address of the phy registers and length of memory mapped
 - reg : base physical address of the phy registers and length of memory mapped
 	region.
 	region.
+- clocks: Clock IDs array as required by the controller.
+- clock-names: names of clock correseponding IDs clock property as requested
+	       by the controller driver.
 
 
 Exynos5250:
 Exynos5250:
-- compatible : should be "samsung,exynos5250-usbphy"
+- compatible : should be "samsung,exynos5250-usb2phy"
 - reg : base physical address of the phy registers and length of memory mapped
 - reg : base physical address of the phy registers and length of memory mapped
 	region.
 	region.
 
 
@@ -44,12 +49,69 @@ Example:
 	usbphy@125B0000 {
 	usbphy@125B0000 {
 		#address-cells = <1>;
 		#address-cells = <1>;
 		#size-cells = <1>;
 		#size-cells = <1>;
-		compatible = "samsung,exynos4210-usbphy";
+		compatible = "samsung,exynos4210-usb2phy";
 		reg = <0x125B0000 0x100>;
 		reg = <0x125B0000 0x100>;
 		ranges;
 		ranges;
 
 
+		clocks = <&clock 2>, <&clock 305>;
+		clock-names = "xusbxti", "otg";
+
 		usbphy-sys {
 		usbphy-sys {
 			/* USB device and host PHY_CONTROL registers */
 			/* USB device and host PHY_CONTROL registers */
 			reg = <0x10020704 0x8>;
 			reg = <0x10020704 0x8>;
 		};
 		};
 	};
 	};
+
+
+** Samsung's usb 3.0 phy transceiver
+
+Starting exynso5250, Samsung's SoC have usb 3.0 phy transceiver
+which is used for controlling usb 3.0 phy for dwc3-exynos usb 3.0
+controllers across Samsung SOCs.
+
+Required properties:
+
+Exynos5250:
+- compatible : should be "samsung,exynos5250-usb3phy"
+- reg : base physical address of the phy registers and length of memory mapped
+	region.
+- clocks: Clock IDs array as required by the controller.
+- clock-names: names of clocks correseponding to IDs in the clock property
+	       as requested by the controller driver.
+
+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:
+	usbphy@12100000 {
+		compatible = "samsung,exynos5250-usb3phy";
+		reg = <0x12100000 0x100>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		clocks = <&clock 1>, <&clock 286>;
+		clock-names = "ext_xtal", "usbdrd30";
+
+		usbphy-sys {
+			/* USB device and host PHY_CONTROL registers */
+			reg = <0x10040704 0x8>;
+		};
+	};

+ 34 - 0
Documentation/devicetree/bindings/usb/usb-nop-xceiv.txt

@@ -0,0 +1,34 @@
+USB NOP PHY
+
+Required properties:
+- compatible: should be usb-nop-xceiv
+
+Optional properties:
+- clocks: phandle to the PHY clock. Use as per Documentation/devicetree
+  /bindings/clock/clock-bindings.txt
+  This property is required if clock-frequency is specified.
+
+- clock-names: Should be "main_clk"
+
+- clock-frequency: the clock frequency (in Hz) that the PHY clock must
+  be configured to.
+
+- vcc-supply: phandle to the regulator that provides RESET to the PHY.
+
+- reset-supply: phandle to the regulator that provides power to the PHY.
+
+Example:
+
+	hsusb1_phy {
+		compatible = "usb-nop-xceiv";
+		clock-frequency = <19200000>;
+		clocks = <&osc 0>;
+		clock-names = "main_clk";
+		vcc-supply = <&hsusb1_vcc_regulator>;
+		reset-supply = <&hsusb1_reset_regulator>;
+	};
+
+hsusb1_phy is a NOP USB PHY device that gets its clock from an oscillator
+and expects that clock to be configured to 19.2MHz by the NOP PHY driver.
+hsusb1_vcc_regulator provides power to the PHY and hsusb1_reset_regulator
+controls RESET.

+ 0 - 6
arch/arm/mach-mmp/aspenite.c

@@ -223,13 +223,7 @@ static struct pxa27x_keypad_platform_data aspenite_keypad_info __initdata = {
 };
 };
 
 
 #if defined(CONFIG_USB_EHCI_MV)
 #if defined(CONFIG_USB_EHCI_MV)
-static char *pxa168_sph_clock_name[] = {
-	[0] = "PXA168-USBCLK",
-};
-
 static struct mv_usb_platform_data pxa168_sph_pdata = {
 static struct mv_usb_platform_data pxa168_sph_pdata = {
-	.clknum         = 1,
-	.clkname        = pxa168_sph_clock_name,
 	.mode           = MV_USB_MODE_HOST,
 	.mode           = MV_USB_MODE_HOST,
 	.phy_init	= pxa_usb_phy_init,
 	.phy_init	= pxa_usb_phy_init,
 	.phy_deinit	= pxa_usb_phy_deinit,
 	.phy_deinit	= pxa_usb_phy_deinit,

+ 0 - 6
arch/arm/mach-mmp/ttc_dkb.c

@@ -162,13 +162,7 @@ static struct i2c_board_info ttc_dkb_i2c_info[] = {
 #ifdef CONFIG_USB_SUPPORT
 #ifdef CONFIG_USB_SUPPORT
 #if defined(CONFIG_USB_MV_UDC) || defined(CONFIG_USB_EHCI_MV_U2O)
 #if defined(CONFIG_USB_MV_UDC) || defined(CONFIG_USB_EHCI_MV_U2O)
 
 
-static char *pxa910_usb_clock_name[] = {
-	[0] = "U2OCLK",
-};
-
 static struct mv_usb_platform_data ttc_usb_pdata = {
 static struct mv_usb_platform_data ttc_usb_pdata = {
-	.clknum		= 1,
-	.clkname	= pxa910_usb_clock_name,
 	.vbus		= NULL,
 	.vbus		= NULL,
 	.mode		= MV_USB_MODE_OTG,
 	.mode		= MV_USB_MODE_OTG,
 	.otg_force_a_bus_req = 1,
 	.otg_force_a_bus_req = 1,

+ 6 - 2
arch/arm/mach-shmobile/board-armadillo800eva.c

@@ -169,7 +169,7 @@ static int usbhsf_get_id(struct platform_device *pdev)
 	return USBHS_GADGET;
 	return USBHS_GADGET;
 }
 }
 
 
-static void usbhsf_power_ctrl(struct platform_device *pdev,
+static int usbhsf_power_ctrl(struct platform_device *pdev,
 			      void __iomem *base, int enable)
 			      void __iomem *base, int enable)
 {
 {
 	struct usbhsf_private *priv = usbhsf_get_priv(pdev);
 	struct usbhsf_private *priv = usbhsf_get_priv(pdev);
@@ -223,6 +223,8 @@ static void usbhsf_power_ctrl(struct platform_device *pdev,
 		clk_disable(priv->pci);		/* usb work around */
 		clk_disable(priv->pci);		/* usb work around */
 		clk_disable(priv->usb24);	/* usb work around */
 		clk_disable(priv->usb24);	/* usb work around */
 	}
 	}
+
+	return 0;
 }
 }
 
 
 static int usbhsf_get_vbus(struct platform_device *pdev)
 static int usbhsf_get_vbus(struct platform_device *pdev)
@@ -239,7 +241,7 @@ static irqreturn_t usbhsf_interrupt(int irq, void *data)
 	return IRQ_HANDLED;
 	return IRQ_HANDLED;
 }
 }
 
 
-static void usbhsf_hardware_exit(struct platform_device *pdev)
+static int usbhsf_hardware_exit(struct platform_device *pdev)
 {
 {
 	struct usbhsf_private *priv = usbhsf_get_priv(pdev);
 	struct usbhsf_private *priv = usbhsf_get_priv(pdev);
 
 
@@ -264,6 +266,8 @@ static void usbhsf_hardware_exit(struct platform_device *pdev)
 	priv->usbh_base	= NULL;
 	priv->usbh_base	= NULL;
 
 
 	free_irq(IRQ7, pdev);
 	free_irq(IRQ7, pdev);
+
+	return 0;
 }
 }
 
 
 static int usbhsf_hardware_init(struct platform_device *pdev)
 static int usbhsf_hardware_init(struct platform_device *pdev)

+ 6 - 2
arch/arm/mach-shmobile/board-kzm9g.c

@@ -155,12 +155,14 @@ static int usbhs_get_vbus(struct platform_device *pdev)
 	return !((1 << 7) & __raw_readw(priv->cr2));
 	return !((1 << 7) & __raw_readw(priv->cr2));
 }
 }
 
 
-static void usbhs_phy_reset(struct platform_device *pdev)
+static int usbhs_phy_reset(struct platform_device *pdev)
 {
 {
 	struct usbhs_private *priv = usbhs_get_priv(pdev);
 	struct usbhs_private *priv = usbhs_get_priv(pdev);
 
 
 	/* init phy */
 	/* init phy */
 	__raw_writew(0x8a0a, priv->cr2);
 	__raw_writew(0x8a0a, priv->cr2);
+
+	return 0;
 }
 }
 
 
 static int usbhs_get_id(struct platform_device *pdev)
 static int usbhs_get_id(struct platform_device *pdev)
@@ -202,7 +204,7 @@ static int usbhs_hardware_init(struct platform_device *pdev)
 	return 0;
 	return 0;
 }
 }
 
 
-static void usbhs_hardware_exit(struct platform_device *pdev)
+static int usbhs_hardware_exit(struct platform_device *pdev)
 {
 {
 	struct usbhs_private *priv = usbhs_get_priv(pdev);
 	struct usbhs_private *priv = usbhs_get_priv(pdev);
 
 
@@ -210,6 +212,8 @@ static void usbhs_hardware_exit(struct platform_device *pdev)
 	__raw_writew(USB_PHY_MODE | USB_PHY_INT_CLR, priv->phy);
 	__raw_writew(USB_PHY_MODE | USB_PHY_INT_CLR, priv->phy);
 
 
 	free_irq(IRQ15, pdev);
 	free_irq(IRQ15, pdev);
+
+	return 0;
 }
 }
 
 
 static u32 usbhs_pipe_cfg[] = {
 static u32 usbhs_pipe_cfg[] = {

+ 9 - 3
arch/arm/mach-shmobile/board-mackerel.c

@@ -596,12 +596,14 @@ static int usbhs_get_vbus(struct platform_device *pdev)
 	return usbhs_is_connected(usbhs_get_priv(pdev));
 	return usbhs_is_connected(usbhs_get_priv(pdev));
 }
 }
 
 
-static void usbhs_phy_reset(struct platform_device *pdev)
+static int usbhs_phy_reset(struct platform_device *pdev)
 {
 {
 	struct usbhs_private *priv = usbhs_get_priv(pdev);
 	struct usbhs_private *priv = usbhs_get_priv(pdev);
 
 
 	/* init phy */
 	/* init phy */
 	__raw_writew(0x8a0a, priv->usbcrcaddr);
 	__raw_writew(0x8a0a, priv->usbcrcaddr);
+
+	return 0;
 }
 }
 
 
 static int usbhs0_get_id(struct platform_device *pdev)
 static int usbhs0_get_id(struct platform_device *pdev)
@@ -628,11 +630,13 @@ static int usbhs0_hardware_init(struct platform_device *pdev)
 	return 0;
 	return 0;
 }
 }
 
 
-static void usbhs0_hardware_exit(struct platform_device *pdev)
+static int usbhs0_hardware_exit(struct platform_device *pdev)
 {
 {
 	struct usbhs_private *priv = usbhs_get_priv(pdev);
 	struct usbhs_private *priv = usbhs_get_priv(pdev);
 
 
 	cancel_delayed_work_sync(&priv->work);
 	cancel_delayed_work_sync(&priv->work);
+
+	return 0;
 }
 }
 
 
 static struct usbhs_private usbhs0_private = {
 static struct usbhs_private usbhs0_private = {
@@ -735,7 +739,7 @@ static int usbhs1_hardware_init(struct platform_device *pdev)
 	return 0;
 	return 0;
 }
 }
 
 
-static void usbhs1_hardware_exit(struct platform_device *pdev)
+static int usbhs1_hardware_exit(struct platform_device *pdev)
 {
 {
 	struct usbhs_private *priv = usbhs_get_priv(pdev);
 	struct usbhs_private *priv = usbhs_get_priv(pdev);
 
 
@@ -743,6 +747,8 @@ static void usbhs1_hardware_exit(struct platform_device *pdev)
 	__raw_writew(USB_PHY_MODE | USB_PHY_INT_CLR, priv->usbphyaddr);
 	__raw_writew(USB_PHY_MODE | USB_PHY_INT_CLR, priv->usbphyaddr);
 
 
 	free_irq(IRQ8, pdev);
 	free_irq(IRQ8, pdev);
+
+	return 0;
 }
 }
 
 
 static int usbhs1_get_id(struct platform_device *pdev)
 static int usbhs1_get_id(struct platform_device *pdev)

+ 4 - 4
arch/arm/mach-tegra/Kconfig

@@ -18,8 +18,8 @@ config ARCH_TEGRA_2x_SOC
 	select PL310_ERRATA_727915 if CACHE_L2X0
 	select PL310_ERRATA_727915 if CACHE_L2X0
 	select PL310_ERRATA_769419 if CACHE_L2X0
 	select PL310_ERRATA_769419 if CACHE_L2X0
 	select USB_ARCH_HAS_EHCI if USB_SUPPORT
 	select USB_ARCH_HAS_EHCI if USB_SUPPORT
-	select USB_ULPI if USB
-	select USB_ULPI_VIEWPORT if USB_SUPPORT
+	select USB_ULPI if USB_PHY
+	select USB_ULPI_VIEWPORT if USB_PHY
 	help
 	help
 	  Support for NVIDIA Tegra AP20 and T20 processors, based on the
 	  Support for NVIDIA Tegra AP20 and T20 processors, based on the
 	  ARM CortexA9MP CPU and the ARM PL310 L2 cache controller
 	  ARM CortexA9MP CPU and the ARM PL310 L2 cache controller
@@ -37,8 +37,8 @@ config ARCH_TEGRA_3x_SOC
 	select PINCTRL_TEGRA30
 	select PINCTRL_TEGRA30
 	select PL310_ERRATA_769419 if CACHE_L2X0
 	select PL310_ERRATA_769419 if CACHE_L2X0
 	select USB_ARCH_HAS_EHCI if USB_SUPPORT
 	select USB_ARCH_HAS_EHCI if USB_SUPPORT
-	select USB_ULPI if USB
-	select USB_ULPI_VIEWPORT if USB_SUPPORT
+	select USB_ULPI if USB_PHY
+	select USB_ULPI_VIEWPORT if USB_PHY
 	help
 	help
 	  Support for NVIDIA Tegra T30 processor family, based on the
 	  Support for NVIDIA Tegra T30 processor family, based on the
 	  ARM CortexA9MP CPU and the ARM PL310 L2 cache controller
 	  ARM CortexA9MP CPU and the ARM PL310 L2 cache controller

+ 3 - 1
arch/sh/boards/mach-ecovec24/setup.c

@@ -254,11 +254,13 @@ static int usbhs_get_id(struct platform_device *pdev)
 	return gpio_get_value(GPIO_PTB3);
 	return gpio_get_value(GPIO_PTB3);
 }
 }
 
 
-static void usbhs_phy_reset(struct platform_device *pdev)
+static int usbhs_phy_reset(struct platform_device *pdev)
 {
 {
 	/* enable vbus if HOST */
 	/* enable vbus if HOST */
 	if (!gpio_get_value(GPIO_PTB3))
 	if (!gpio_get_value(GPIO_PTB3))
 		gpio_set_value(GPIO_PTB5, 1);
 		gpio_set_value(GPIO_PTB5, 1);
+
+	return 0;
 }
 }
 
 
 static struct renesas_usbhs_platform_info usbhs_info = {
 static struct renesas_usbhs_platform_info usbhs_info = {

+ 1 - 1
drivers/Makefile

@@ -79,7 +79,7 @@ obj-$(CONFIG_ATA_OVER_ETH)	+= block/aoe/
 obj-$(CONFIG_PARIDE) 		+= block/paride/
 obj-$(CONFIG_PARIDE) 		+= block/paride/
 obj-$(CONFIG_TC)		+= tc/
 obj-$(CONFIG_TC)		+= tc/
 obj-$(CONFIG_UWB)		+= uwb/
 obj-$(CONFIG_UWB)		+= uwb/
-obj-$(CONFIG_USB_OTG_UTILS)	+= usb/
+obj-$(CONFIG_USB_PHY)		+= usb/
 obj-$(CONFIG_USB)		+= usb/
 obj-$(CONFIG_USB)		+= usb/
 obj-$(CONFIG_PCI)		+= usb/
 obj-$(CONFIG_PCI)		+= usb/
 obj-$(CONFIG_USB_GADGET)	+= usb/
 obj-$(CONFIG_USB_GADGET)	+= usb/

+ 1 - 1
drivers/power/Kconfig

@@ -254,7 +254,7 @@ config BATTERY_RX51
 
 
 config CHARGER_ISP1704
 config CHARGER_ISP1704
 	tristate "ISP1704 USB Charger Detection"
 	tristate "ISP1704 USB Charger Detection"
-	depends on USB_OTG_UTILS
+	depends on USB_PHY
 	help
 	help
 	  Say Y to enable support for USB Charger Detection with
 	  Say Y to enable support for USB Charger Detection with
 	  ISP1707/ISP1704 USB transceivers.
 	  ISP1707/ISP1704 USB transceivers.

+ 7 - 7
drivers/power/pda_power.c

@@ -35,7 +35,7 @@ static struct timer_list supply_timer;
 static struct timer_list polling_timer;
 static struct timer_list polling_timer;
 static int polling;
 static int polling;
 
 
-#ifdef CONFIG_USB_OTG_UTILS
+#if IS_ENABLED(CONFIG_USB_PHY)
 static struct usb_phy *transceiver;
 static struct usb_phy *transceiver;
 static struct notifier_block otg_nb;
 static struct notifier_block otg_nb;
 #endif
 #endif
@@ -218,7 +218,7 @@ static void polling_timer_func(unsigned long unused)
 		  jiffies + msecs_to_jiffies(pdata->polling_interval));
 		  jiffies + msecs_to_jiffies(pdata->polling_interval));
 }
 }
 
 
-#ifdef CONFIG_USB_OTG_UTILS
+#if IS_ENABLED(CONFIG_USB_PHY)
 static int otg_is_usb_online(void)
 static int otg_is_usb_online(void)
 {
 {
 	return (transceiver->last_event == USB_EVENT_VBUS ||
 	return (transceiver->last_event == USB_EVENT_VBUS ||
@@ -315,7 +315,7 @@ static int pda_power_probe(struct platform_device *pdev)
 		pda_psy_usb.num_supplicants = pdata->num_supplicants;
 		pda_psy_usb.num_supplicants = pdata->num_supplicants;
 	}
 	}
 
 
-#ifdef CONFIG_USB_OTG_UTILS
+#if IS_ENABLED(CONFIG_USB_PHY)
 	transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
 	transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
 	if (!IS_ERR_OR_NULL(transceiver)) {
 	if (!IS_ERR_OR_NULL(transceiver)) {
 		if (!pdata->is_usb_online)
 		if (!pdata->is_usb_online)
@@ -367,7 +367,7 @@ static int pda_power_probe(struct platform_device *pdev)
 		}
 		}
 	}
 	}
 
 
-#ifdef CONFIG_USB_OTG_UTILS
+#if IS_ENABLED(CONFIG_USB_PHY)
 	if (!IS_ERR_OR_NULL(transceiver) && pdata->use_otg_notifier) {
 	if (!IS_ERR_OR_NULL(transceiver) && pdata->use_otg_notifier) {
 		otg_nb.notifier_call = otg_handle_notification;
 		otg_nb.notifier_call = otg_handle_notification;
 		ret = usb_register_notifier(transceiver, &otg_nb);
 		ret = usb_register_notifier(transceiver, &otg_nb);
@@ -391,7 +391,7 @@ static int pda_power_probe(struct platform_device *pdev)
 
 
 	return 0;
 	return 0;
 
 
-#ifdef CONFIG_USB_OTG_UTILS
+#if IS_ENABLED(CONFIG_USB_PHY)
 otg_reg_notifier_failed:
 otg_reg_notifier_failed:
 	if (pdata->is_usb_online && usb_irq)
 	if (pdata->is_usb_online && usb_irq)
 		free_irq(usb_irq->start, &pda_psy_usb);
 		free_irq(usb_irq->start, &pda_psy_usb);
@@ -402,7 +402,7 @@ usb_irq_failed:
 usb_supply_failed:
 usb_supply_failed:
 	if (pdata->is_ac_online && ac_irq)
 	if (pdata->is_ac_online && ac_irq)
 		free_irq(ac_irq->start, &pda_psy_ac);
 		free_irq(ac_irq->start, &pda_psy_ac);
-#ifdef CONFIG_USB_OTG_UTILS
+#if IS_ENABLED(CONFIG_USB_PHY)
 	if (!IS_ERR_OR_NULL(transceiver))
 	if (!IS_ERR_OR_NULL(transceiver))
 		usb_put_phy(transceiver);
 		usb_put_phy(transceiver);
 #endif
 #endif
@@ -437,7 +437,7 @@ static int pda_power_remove(struct platform_device *pdev)
 		power_supply_unregister(&pda_psy_usb);
 		power_supply_unregister(&pda_psy_usb);
 	if (pdata->is_ac_online)
 	if (pdata->is_ac_online)
 		power_supply_unregister(&pda_psy_ac);
 		power_supply_unregister(&pda_psy_ac);
-#ifdef CONFIG_USB_OTG_UTILS
+#if IS_ENABLED(CONFIG_USB_PHY)
 	if (!IS_ERR_OR_NULL(transceiver))
 	if (!IS_ERR_OR_NULL(transceiver))
 		usb_put_phy(transceiver);
 		usb_put_phy(transceiver);
 #endif
 #endif

+ 0 - 2
drivers/usb/Kconfig

@@ -186,6 +186,4 @@ source "drivers/usb/atm/Kconfig"
 
 
 source "drivers/usb/gadget/Kconfig"
 source "drivers/usb/gadget/Kconfig"
 
 
-source "drivers/usb/otg/Kconfig"
-
 endif # USB_SUPPORT
 endif # USB_SUPPORT

+ 1 - 3
drivers/usb/Makefile

@@ -6,8 +6,6 @@
 
 
 obj-$(CONFIG_USB)		+= core/
 obj-$(CONFIG_USB)		+= core/
 
 
-obj-$(CONFIG_USB_OTG_UTILS)	+= otg/
-
 obj-$(CONFIG_USB_DWC3)		+= dwc3/
 obj-$(CONFIG_USB_DWC3)		+= dwc3/
 
 
 obj-$(CONFIG_USB_MON)		+= mon/
 obj-$(CONFIG_USB_MON)		+= mon/
@@ -46,7 +44,7 @@ obj-$(CONFIG_USB_MICROTEK)	+= image/
 obj-$(CONFIG_USB_SERIAL)	+= serial/
 obj-$(CONFIG_USB_SERIAL)	+= serial/
 
 
 obj-$(CONFIG_USB)		+= misc/
 obj-$(CONFIG_USB)		+= misc/
-obj-$(CONFIG_USB_OTG_UTILS)	+= phy/
+obj-$(CONFIG_USB_PHY)		+= phy/
 obj-$(CONFIG_EARLY_PRINTK_DBGP)	+= early/
 obj-$(CONFIG_EARLY_PRINTK_DBGP)	+= early/
 
 
 obj-$(CONFIG_USB_ATM)		+= atm/
 obj-$(CONFIG_USB_ATM)		+= atm/

+ 1 - 26
drivers/usb/chipidea/udc.c

@@ -1638,16 +1638,6 @@ static irqreturn_t udc_irq(struct ci13xxx *ci)
 	return retval;
 	return retval;
 }
 }
 
 
-/**
- * udc_release: driver release function
- * @dev: device
- *
- * Currently does nothing
- */
-static void udc_release(struct device *dev)
-{
-}
-
 /**
 /**
  * udc_start: initialize gadget role
  * udc_start: initialize gadget role
  * @ci: chipidea controller
  * @ci: chipidea controller
@@ -1667,12 +1657,6 @@ static int udc_start(struct ci13xxx *ci)
 
 
 	INIT_LIST_HEAD(&ci->gadget.ep_list);
 	INIT_LIST_HEAD(&ci->gadget.ep_list);
 
 
-	dev_set_name(&ci->gadget.dev, "gadget");
-	ci->gadget.dev.dma_mask = dev->dma_mask;
-	ci->gadget.dev.coherent_dma_mask = dev->coherent_dma_mask;
-	ci->gadget.dev.parent   = dev;
-	ci->gadget.dev.release  = udc_release;
-
 	/* alloc resources */
 	/* alloc resources */
 	ci->qh_pool = dma_pool_create("ci13xxx_qh", dev,
 	ci->qh_pool = dma_pool_create("ci13xxx_qh", dev,
 				       sizeof(struct ci13xxx_qh),
 				       sizeof(struct ci13xxx_qh),
@@ -1710,17 +1694,11 @@ static int udc_start(struct ci13xxx *ci)
 			goto put_transceiver;
 			goto put_transceiver;
 	}
 	}
 
 
-	retval = device_register(&ci->gadget.dev);
-	if (retval) {
-		put_device(&ci->gadget.dev);
-		goto put_transceiver;
-	}
-
 	if (!IS_ERR_OR_NULL(ci->transceiver)) {
 	if (!IS_ERR_OR_NULL(ci->transceiver)) {
 		retval = otg_set_peripheral(ci->transceiver->otg,
 		retval = otg_set_peripheral(ci->transceiver->otg,
 						&ci->gadget);
 						&ci->gadget);
 		if (retval)
 		if (retval)
-			goto unreg_device;
+			goto put_transceiver;
 	}
 	}
 
 
 	retval = usb_add_gadget_udc(dev, &ci->gadget);
 	retval = usb_add_gadget_udc(dev, &ci->gadget);
@@ -1740,8 +1718,6 @@ remove_trans:
 	}
 	}
 
 
 	dev_err(dev, "error = %i\n", retval);
 	dev_err(dev, "error = %i\n", retval);
-unreg_device:
-	device_unregister(&ci->gadget.dev);
 put_transceiver:
 put_transceiver:
 	if (!IS_ERR_OR_NULL(ci->transceiver) && ci->global_phy)
 	if (!IS_ERR_OR_NULL(ci->transceiver) && ci->global_phy)
 		usb_put_phy(ci->transceiver);
 		usb_put_phy(ci->transceiver);
@@ -1776,7 +1752,6 @@ static void udc_stop(struct ci13xxx *ci)
 		if (ci->global_phy)
 		if (ci->global_phy)
 			usb_put_phy(ci->transceiver);
 			usb_put_phy(ci->transceiver);
 	}
 	}
-	device_unregister(&ci->gadget.dev);
 	/* my kobject is dynamic, I swear! */
 	/* my kobject is dynamic, I swear! */
 	memset(&ci->gadget, 0, sizeof(ci->gadget));
 	memset(&ci->gadget, 0, sizeof(ci->gadget));
 }
 }

+ 0 - 1
drivers/usb/dwc3/Kconfig

@@ -1,7 +1,6 @@
 config USB_DWC3
 config USB_DWC3
 	tristate "DesignWare USB3 DRD Core Support"
 	tristate "DesignWare USB3 DRD Core Support"
 	depends on (USB || USB_GADGET) && GENERIC_HARDIRQS
 	depends on (USB || USB_GADGET) && GENERIC_HARDIRQS
-	select USB_OTG_UTILS
 	select USB_XHCI_PLATFORM if USB_SUPPORT && USB_XHCI_HCD
 	select USB_XHCI_PLATFORM if USB_SUPPORT && USB_XHCI_HCD
 	help
 	help
 	  Say Y or M here if your system has a Dual Role SuperSpeed
 	  Say Y or M here if your system has a Dual Role SuperSpeed

+ 182 - 19
drivers/usb/dwc3/core.c

@@ -140,7 +140,8 @@ static void dwc3_free_one_event_buffer(struct dwc3 *dwc,
  * Returns a pointer to the allocated event buffer structure on success
  * Returns a pointer to the allocated event buffer structure on success
  * otherwise ERR_PTR(errno).
  * otherwise ERR_PTR(errno).
  */
  */
-static struct dwc3_event_buffer *dwc3_alloc_one_event_buffer(struct dwc3 *dwc, unsigned length)
+static struct dwc3_event_buffer *dwc3_alloc_one_event_buffer(struct dwc3 *dwc,
+		unsigned length)
 {
 {
 	struct dwc3_event_buffer	*evt;
 	struct dwc3_event_buffer	*evt;
 
 
@@ -259,6 +260,17 @@ static void dwc3_event_buffers_cleanup(struct dwc3 *dwc)
 	}
 	}
 }
 }
 
 
+static void dwc3_core_num_eps(struct dwc3 *dwc)
+{
+	struct dwc3_hwparams	*parms = &dwc->hwparams;
+
+	dwc->num_in_eps = DWC3_NUM_IN_EPS(parms);
+	dwc->num_out_eps = DWC3_NUM_EPS(parms) - dwc->num_in_eps;
+
+	dev_vdbg(dwc->dev, "found %d IN and %d OUT endpoints\n",
+			dwc->num_in_eps, dwc->num_out_eps);
+}
+
 static void dwc3_cache_hwparams(struct dwc3 *dwc)
 static void dwc3_cache_hwparams(struct dwc3 *dwc)
 {
 {
 	struct dwc3_hwparams	*parms = &dwc->hwparams;
 	struct dwc3_hwparams	*parms = &dwc->hwparams;
@@ -335,13 +347,9 @@ static int dwc3_core_init(struct dwc3 *dwc)
 	if (dwc->revision < DWC3_REVISION_190A)
 	if (dwc->revision < DWC3_REVISION_190A)
 		reg |= DWC3_GCTL_U2RSTECN;
 		reg |= DWC3_GCTL_U2RSTECN;
 
 
-	dwc3_writel(dwc->regs, DWC3_GCTL, reg);
+	dwc3_core_num_eps(dwc);
 
 
-	ret = dwc3_event_buffers_setup(dwc);
-	if (ret) {
-		dev_err(dwc->dev, "failed to setup event buffers\n");
-		goto err0;
-	}
+	dwc3_writel(dwc->regs, DWC3_GCTL, reg);
 
 
 	return 0;
 	return 0;
 
 
@@ -351,8 +359,6 @@ err0:
 
 
 static void dwc3_core_exit(struct dwc3 *dwc)
 static void dwc3_core_exit(struct dwc3 *dwc)
 {
 {
-	dwc3_event_buffers_cleanup(dwc);
-
 	usb_phy_shutdown(dwc->usb2_phy);
 	usb_phy_shutdown(dwc->usb2_phy);
 	usb_phy_shutdown(dwc->usb3_phy);
 	usb_phy_shutdown(dwc->usb3_phy);
 }
 }
@@ -428,12 +434,32 @@ static int dwc3_probe(struct platform_device *pdev)
 		dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3);
 		dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3);
 	}
 	}
 
 
-	if (IS_ERR_OR_NULL(dwc->usb2_phy)) {
+	if (IS_ERR(dwc->usb2_phy)) {
+		ret = PTR_ERR(dwc->usb2_phy);
+
+		/*
+		 * if -ENXIO is returned, it means PHY layer wasn't
+		 * enabled, so it makes no sense to return -EPROBE_DEFER
+		 * in that case, since no PHY driver will ever probe.
+		 */
+		if (ret == -ENXIO)
+			return ret;
+
 		dev_err(dev, "no usb2 phy configured\n");
 		dev_err(dev, "no usb2 phy configured\n");
 		return -EPROBE_DEFER;
 		return -EPROBE_DEFER;
 	}
 	}
 
 
-	if (IS_ERR_OR_NULL(dwc->usb3_phy)) {
+	if (IS_ERR(dwc->usb3_phy)) {
+		ret = PTR_ERR(dwc->usb2_phy);
+
+		/*
+		 * if -ENXIO is returned, it means PHY layer wasn't
+		 * enabled, so it makes no sense to return -EPROBE_DEFER
+		 * in that case, since no PHY driver will ever probe.
+		 */
+		if (ret == -ENXIO)
+			return ret;
+
 		dev_err(dev, "no usb3 phy configured\n");
 		dev_err(dev, "no usb3 phy configured\n");
 		return -EPROBE_DEFER;
 		return -EPROBE_DEFER;
 	}
 	}
@@ -448,6 +474,10 @@ static int dwc3_probe(struct platform_device *pdev)
 	dwc->regs_size	= resource_size(res);
 	dwc->regs_size	= resource_size(res);
 	dwc->dev	= dev;
 	dwc->dev	= dev;
 
 
+	dev->dma_mask	= dev->parent->dma_mask;
+	dev->dma_parms	= dev->parent->dma_parms;
+	dma_set_coherent_mask(dev, dev->parent->coherent_dma_mask);
+
 	if (!strncmp("super", maximum_speed, 5))
 	if (!strncmp("super", maximum_speed, 5))
 		dwc->maximum_speed = DWC3_DCFG_SUPERSPEED;
 		dwc->maximum_speed = DWC3_DCFG_SUPERSPEED;
 	else if (!strncmp("high", maximum_speed, 4))
 	else if (!strncmp("high", maximum_speed, 4))
@@ -480,7 +510,18 @@ static int dwc3_probe(struct platform_device *pdev)
 		goto err0;
 		goto err0;
 	}
 	}
 
 
-	mode = DWC3_MODE(dwc->hwparams.hwparams0);
+	ret = dwc3_event_buffers_setup(dwc);
+	if (ret) {
+		dev_err(dwc->dev, "failed to setup event buffers\n");
+		goto err1;
+	}
+
+	if (IS_ENABLED(CONFIG_USB_DWC3_HOST))
+		mode = DWC3_MODE_HOST;
+	else if (IS_ENABLED(CONFIG_USB_DWC3_GADGET))
+		mode = DWC3_MODE_DEVICE;
+	else
+		mode = DWC3_MODE_DRD;
 
 
 	switch (mode) {
 	switch (mode) {
 	case DWC3_MODE_DEVICE:
 	case DWC3_MODE_DEVICE:
@@ -488,7 +529,7 @@ static int dwc3_probe(struct platform_device *pdev)
 		ret = dwc3_gadget_init(dwc);
 		ret = dwc3_gadget_init(dwc);
 		if (ret) {
 		if (ret) {
 			dev_err(dev, "failed to initialize gadget\n");
 			dev_err(dev, "failed to initialize gadget\n");
-			goto err1;
+			goto err2;
 		}
 		}
 		break;
 		break;
 	case DWC3_MODE_HOST:
 	case DWC3_MODE_HOST:
@@ -496,7 +537,7 @@ static int dwc3_probe(struct platform_device *pdev)
 		ret = dwc3_host_init(dwc);
 		ret = dwc3_host_init(dwc);
 		if (ret) {
 		if (ret) {
 			dev_err(dev, "failed to initialize host\n");
 			dev_err(dev, "failed to initialize host\n");
-			goto err1;
+			goto err2;
 		}
 		}
 		break;
 		break;
 	case DWC3_MODE_DRD:
 	case DWC3_MODE_DRD:
@@ -504,32 +545,32 @@ static int dwc3_probe(struct platform_device *pdev)
 		ret = dwc3_host_init(dwc);
 		ret = dwc3_host_init(dwc);
 		if (ret) {
 		if (ret) {
 			dev_err(dev, "failed to initialize host\n");
 			dev_err(dev, "failed to initialize host\n");
-			goto err1;
+			goto err2;
 		}
 		}
 
 
 		ret = dwc3_gadget_init(dwc);
 		ret = dwc3_gadget_init(dwc);
 		if (ret) {
 		if (ret) {
 			dev_err(dev, "failed to initialize gadget\n");
 			dev_err(dev, "failed to initialize gadget\n");
-			goto err1;
+			goto err2;
 		}
 		}
 		break;
 		break;
 	default:
 	default:
 		dev_err(dev, "Unsupported mode of operation %d\n", mode);
 		dev_err(dev, "Unsupported mode of operation %d\n", mode);
-		goto err1;
+		goto err2;
 	}
 	}
 	dwc->mode = mode;
 	dwc->mode = mode;
 
 
 	ret = dwc3_debugfs_init(dwc);
 	ret = dwc3_debugfs_init(dwc);
 	if (ret) {
 	if (ret) {
 		dev_err(dev, "failed to initialize debugfs\n");
 		dev_err(dev, "failed to initialize debugfs\n");
-		goto err2;
+		goto err3;
 	}
 	}
 
 
 	pm_runtime_allow(dev);
 	pm_runtime_allow(dev);
 
 
 	return 0;
 	return 0;
 
 
-err2:
+err3:
 	switch (mode) {
 	switch (mode) {
 	case DWC3_MODE_DEVICE:
 	case DWC3_MODE_DEVICE:
 		dwc3_gadget_exit(dwc);
 		dwc3_gadget_exit(dwc);
@@ -546,6 +587,9 @@ err2:
 		break;
 		break;
 	}
 	}
 
 
+err2:
+	dwc3_event_buffers_cleanup(dwc);
+
 err1:
 err1:
 	dwc3_core_exit(dwc);
 	dwc3_core_exit(dwc);
 
 
@@ -583,12 +627,130 @@ static int dwc3_remove(struct platform_device *pdev)
 		break;
 		break;
 	}
 	}
 
 
+	dwc3_event_buffers_cleanup(dwc);
 	dwc3_free_event_buffers(dwc);
 	dwc3_free_event_buffers(dwc);
 	dwc3_core_exit(dwc);
 	dwc3_core_exit(dwc);
 
 
 	return 0;
 	return 0;
 }
 }
 
 
+#ifdef CONFIG_PM_SLEEP
+static int dwc3_prepare(struct device *dev)
+{
+	struct dwc3	*dwc = dev_get_drvdata(dev);
+	unsigned long	flags;
+
+	spin_lock_irqsave(&dwc->lock, flags);
+
+	switch (dwc->mode) {
+	case DWC3_MODE_DEVICE:
+	case DWC3_MODE_DRD:
+		dwc3_gadget_prepare(dwc);
+		/* FALLTHROUGH */
+	case DWC3_MODE_HOST:
+	default:
+		dwc3_event_buffers_cleanup(dwc);
+		break;
+	}
+
+	spin_unlock_irqrestore(&dwc->lock, flags);
+
+	return 0;
+}
+
+static void dwc3_complete(struct device *dev)
+{
+	struct dwc3	*dwc = dev_get_drvdata(dev);
+	unsigned long	flags;
+
+	spin_lock_irqsave(&dwc->lock, flags);
+
+	switch (dwc->mode) {
+	case DWC3_MODE_DEVICE:
+	case DWC3_MODE_DRD:
+		dwc3_gadget_complete(dwc);
+		/* FALLTHROUGH */
+	case DWC3_MODE_HOST:
+	default:
+		dwc3_event_buffers_setup(dwc);
+		break;
+	}
+
+	spin_unlock_irqrestore(&dwc->lock, flags);
+}
+
+static int dwc3_suspend(struct device *dev)
+{
+	struct dwc3	*dwc = dev_get_drvdata(dev);
+	unsigned long	flags;
+
+	spin_lock_irqsave(&dwc->lock, flags);
+
+	switch (dwc->mode) {
+	case DWC3_MODE_DEVICE:
+	case DWC3_MODE_DRD:
+		dwc3_gadget_suspend(dwc);
+		/* FALLTHROUGH */
+	case DWC3_MODE_HOST:
+	default:
+		/* do nothing */
+		break;
+	}
+
+	dwc->gctl = dwc3_readl(dwc->regs, DWC3_GCTL);
+	spin_unlock_irqrestore(&dwc->lock, flags);
+
+	usb_phy_shutdown(dwc->usb3_phy);
+	usb_phy_shutdown(dwc->usb2_phy);
+
+	return 0;
+}
+
+static int dwc3_resume(struct device *dev)
+{
+	struct dwc3	*dwc = dev_get_drvdata(dev);
+	unsigned long	flags;
+
+	usb_phy_init(dwc->usb3_phy);
+	usb_phy_init(dwc->usb2_phy);
+	msleep(100);
+
+	spin_lock_irqsave(&dwc->lock, flags);
+
+	dwc3_writel(dwc->regs, DWC3_GCTL, dwc->gctl);
+
+	switch (dwc->mode) {
+	case DWC3_MODE_DEVICE:
+	case DWC3_MODE_DRD:
+		dwc3_gadget_resume(dwc);
+		/* FALLTHROUGH */
+	case DWC3_MODE_HOST:
+	default:
+		/* do nothing */
+		break;
+	}
+
+	spin_unlock_irqrestore(&dwc->lock, flags);
+
+	pm_runtime_disable(dev);
+	pm_runtime_set_active(dev);
+	pm_runtime_enable(dev);
+
+	return 0;
+}
+
+static const struct dev_pm_ops dwc3_dev_pm_ops = {
+	.prepare	= dwc3_prepare,
+	.complete	= dwc3_complete,
+
+	SET_SYSTEM_SLEEP_PM_OPS(dwc3_suspend, dwc3_resume)
+};
+
+#define DWC3_PM_OPS	&(dwc3_dev_pm_ops)
+#else
+#define DWC3_PM_OPS	NULL
+#endif
+
 #ifdef CONFIG_OF
 #ifdef CONFIG_OF
 static const struct of_device_id of_dwc3_match[] = {
 static const struct of_device_id of_dwc3_match[] = {
 	{
 	{
@@ -605,6 +767,7 @@ static struct platform_driver dwc3_driver = {
 	.driver		= {
 	.driver		= {
 		.name	= "dwc3",
 		.name	= "dwc3",
 		.of_match_table	= of_match_ptr(of_dwc3_match),
 		.of_match_table	= of_match_ptr(of_dwc3_match),
+		.pm	= DWC3_PM_OPS,
 	},
 	},
 };
 };
 
 

+ 62 - 10
drivers/usb/dwc3/core.h

@@ -154,8 +154,9 @@
 /* OTG Registers */
 /* OTG Registers */
 #define DWC3_OCFG		0xcc00
 #define DWC3_OCFG		0xcc00
 #define DWC3_OCTL		0xcc04
 #define DWC3_OCTL		0xcc04
-#define DWC3_OEVTEN		0xcc08
-#define DWC3_OSTS		0xcc0C
+#define DWC3_OEVT		0xcc08
+#define DWC3_OEVTEN		0xcc0C
+#define DWC3_OSTS		0xcc10
 
 
 /* Bit fields */
 /* Bit fields */
 
 
@@ -369,6 +370,9 @@ struct dwc3_trb;
  * @list: a list of event buffers
  * @list: a list of event buffers
  * @buf: _THE_ buffer
  * @buf: _THE_ buffer
  * @length: size of this buffer
  * @length: size of this buffer
+ * @lpos: event offset
+ * @count: cache of last read event count register
+ * @flags: flags related to this event buffer
  * @dma: dma_addr_t
  * @dma: dma_addr_t
  * @dwc: pointer to DWC controller
  * @dwc: pointer to DWC controller
  */
  */
@@ -376,6 +380,10 @@ struct dwc3_event_buffer {
 	void			*buf;
 	void			*buf;
 	unsigned		length;
 	unsigned		length;
 	unsigned int		lpos;
 	unsigned int		lpos;
+	unsigned int		count;
+	unsigned int		flags;
+
+#define DWC3_EVENT_PENDING	BIT(0)
 
 
 	dma_addr_t		dma;
 	dma_addr_t		dma;
 
 
@@ -487,12 +495,6 @@ enum dwc3_link_state {
 	DWC3_LINK_STATE_MASK		= 0x0f,
 	DWC3_LINK_STATE_MASK		= 0x0f,
 };
 };
 
 
-enum dwc3_device_state {
-	DWC3_DEFAULT_STATE,
-	DWC3_ADDRESS_STATE,
-	DWC3_CONFIGURED_STATE,
-};
-
 /* TRB Length, PCM and Status */
 /* TRB Length, PCM and Status */
 #define DWC3_TRB_SIZE_MASK	(0x00ffffff)
 #define DWC3_TRB_SIZE_MASK	(0x00ffffff)
 #define DWC3_TRB_SIZE_LENGTH(n)	((n) & DWC3_TRB_SIZE_MASK)
 #define DWC3_TRB_SIZE_LENGTH(n)	((n) & DWC3_TRB_SIZE_MASK)
@@ -574,6 +576,14 @@ struct dwc3_hwparams {
 /* HWPARAMS1 */
 /* HWPARAMS1 */
 #define DWC3_NUM_INT(n)		(((n) & (0x3f << 15)) >> 15)
 #define DWC3_NUM_INT(n)		(((n) & (0x3f << 15)) >> 15)
 
 
+/* HWPARAMS3 */
+#define DWC3_NUM_IN_EPS_MASK	(0x1f << 18)
+#define DWC3_NUM_EPS_MASK	(0x3f << 12)
+#define DWC3_NUM_EPS(p)		(((p)->hwparams3 &		\
+			(DWC3_NUM_EPS_MASK)) >> 12)
+#define DWC3_NUM_IN_EPS(p)	(((p)->hwparams3 &		\
+			(DWC3_NUM_IN_EPS_MASK)) >> 18)
+
 /* HWPARAMS7 */
 /* HWPARAMS7 */
 #define DWC3_RAM1_DEPTH(n)	((n) & 0xffff)
 #define DWC3_RAM1_DEPTH(n)	((n) & 0xffff)
 
 
@@ -618,7 +628,6 @@ struct dwc3_scratchpad_array {
  * @gadget_driver: pointer to the gadget driver
  * @gadget_driver: pointer to the gadget driver
  * @regs: base address for our registers
  * @regs: base address for our registers
  * @regs_size: address space size
  * @regs_size: address space size
- * @irq: IRQ number
  * @num_event_buffers: calculated number of event buffers
  * @num_event_buffers: calculated number of event buffers
  * @u1u2: only used on revisions <1.83a for workaround
  * @u1u2: only used on revisions <1.83a for workaround
  * @maximum_speed: maximum speed requested (mainly for testing purposes)
  * @maximum_speed: maximum speed requested (mainly for testing purposes)
@@ -626,6 +635,8 @@ struct dwc3_scratchpad_array {
  * @mode: mode of operation
  * @mode: mode of operation
  * @usb2_phy: pointer to USB2 PHY
  * @usb2_phy: pointer to USB2 PHY
  * @usb3_phy: pointer to USB3 PHY
  * @usb3_phy: pointer to USB3 PHY
+ * @dcfg: saved contents of DCFG register
+ * @gctl: saved contents of GCTL register
  * @is_selfpowered: true when we are selfpowered
  * @is_selfpowered: true when we are selfpowered
  * @three_stage_setup: set if we perform a three phase setup
  * @three_stage_setup: set if we perform a three phase setup
  * @ep0_bounced: true when we used bounce buffer
  * @ep0_bounced: true when we used bounce buffer
@@ -639,6 +650,8 @@ struct dwc3_scratchpad_array {
  * @u2pel: parameter from Set SEL request.
  * @u2pel: parameter from Set SEL request.
  * @u1sel: parameter from Set SEL request.
  * @u1sel: parameter from Set SEL request.
  * @u1pel: parameter from Set SEL request.
  * @u1pel: parameter from Set SEL request.
+ * @num_out_eps: number of out endpoints
+ * @num_in_eps: number of in endpoints
  * @ep0_next_event: hold the next expected event
  * @ep0_next_event: hold the next expected event
  * @ep0state: state of endpoint zero
  * @ep0state: state of endpoint zero
  * @link_state: link state
  * @link_state: link state
@@ -656,8 +669,10 @@ struct dwc3 {
 	dma_addr_t		ep0_trb_addr;
 	dma_addr_t		ep0_trb_addr;
 	dma_addr_t		ep0_bounce_addr;
 	dma_addr_t		ep0_bounce_addr;
 	struct dwc3_request	ep0_usb_req;
 	struct dwc3_request	ep0_usb_req;
+
 	/* device lock */
 	/* device lock */
 	spinlock_t		lock;
 	spinlock_t		lock;
+
 	struct device		*dev;
 	struct device		*dev;
 
 
 	struct platform_device	*xhci;
 	struct platform_device	*xhci;
@@ -675,6 +690,10 @@ struct dwc3 {
 	void __iomem		*regs;
 	void __iomem		*regs;
 	size_t			regs_size;
 	size_t			regs_size;
 
 
+	/* used for suspend/resume */
+	u32			dcfg;
+	u32			gctl;
+
 	u32			num_event_buffers;
 	u32			num_event_buffers;
 	u32			u1u2;
 	u32			u1u2;
 	u32			maximum_speed;
 	u32			maximum_speed;
@@ -694,6 +713,9 @@ struct dwc3 {
 #define DWC3_REVISION_202A	0x5533202a
 #define DWC3_REVISION_202A	0x5533202a
 #define DWC3_REVISION_210A	0x5533210a
 #define DWC3_REVISION_210A	0x5533210a
 #define DWC3_REVISION_220A	0x5533220a
 #define DWC3_REVISION_220A	0x5533220a
+#define DWC3_REVISION_230A	0x5533230a
+#define DWC3_REVISION_240A	0x5533240a
+#define DWC3_REVISION_250A	0x5533250a
 
 
 	unsigned		is_selfpowered:1;
 	unsigned		is_selfpowered:1;
 	unsigned		three_stage_setup:1;
 	unsigned		three_stage_setup:1;
@@ -704,11 +726,11 @@ struct dwc3 {
 	unsigned		delayed_status:1;
 	unsigned		delayed_status:1;
 	unsigned		needs_fifo_resize:1;
 	unsigned		needs_fifo_resize:1;
 	unsigned		resize_fifos:1;
 	unsigned		resize_fifos:1;
+	unsigned		pullups_connected:1;
 
 
 	enum dwc3_ep0_next	ep0_next_event;
 	enum dwc3_ep0_next	ep0_next_event;
 	enum dwc3_ep0_state	ep0state;
 	enum dwc3_ep0_state	ep0state;
 	enum dwc3_link_state	link_state;
 	enum dwc3_link_state	link_state;
-	enum dwc3_device_state	dev_state;
 
 
 	u16			isoch_delay;
 	u16			isoch_delay;
 	u16			u2sel;
 	u16			u2sel;
@@ -718,6 +740,9 @@ struct dwc3 {
 
 
 	u8			speed;
 	u8			speed;
 
 
+	u8			num_out_eps;
+	u8			num_in_eps;
+
 	void			*mem;
 	void			*mem;
 
 
 	struct dwc3_hwparams	hwparams;
 	struct dwc3_hwparams	hwparams;
@@ -884,4 +909,31 @@ static inline void dwc3_gadget_exit(struct dwc3 *dwc)
 { }
 { }
 #endif
 #endif
 
 
+/* power management interface */
+#if !IS_ENABLED(CONFIG_USB_DWC3_HOST)
+int dwc3_gadget_prepare(struct dwc3 *dwc);
+void dwc3_gadget_complete(struct dwc3 *dwc);
+int dwc3_gadget_suspend(struct dwc3 *dwc);
+int dwc3_gadget_resume(struct dwc3 *dwc);
+#else
+static inline int dwc3_gadget_prepare(struct dwc3 *dwc)
+{
+	return 0;
+}
+
+static inline void dwc3_gadget_complete(struct dwc3 *dwc)
+{
+}
+
+static inline int dwc3_gadget_suspend(struct dwc3 *dwc)
+{
+	return 0;
+}
+
+static inline int dwc3_gadget_resume(struct dwc3 *dwc)
+{
+	return 0;
+}
+#endif /* !IS_ENABLED(CONFIG_USB_DWC3_HOST) */
+
 #endif /* __DRIVERS_USB_DWC3_CORE_H */
 #endif /* __DRIVERS_USB_DWC3_CORE_H */

+ 31 - 21
drivers/usb/dwc3/debugfs.c

@@ -59,7 +59,7 @@
 	.offset	= DWC3_ ##nm - DWC3_GLOBALS_REGS_START,	\
 	.offset	= DWC3_ ##nm - DWC3_GLOBALS_REGS_START,	\
 }
 }
 
 
-static struct debugfs_reg32 dwc3_regs[] = {
+static const struct debugfs_reg32 dwc3_regs[] = {
 	dump_register(GSBUSCFG0),
 	dump_register(GSBUSCFG0),
 	dump_register(GSBUSCFG1),
 	dump_register(GSBUSCFG1),
 	dump_register(GTXTHRCFG),
 	dump_register(GTXTHRCFG),
@@ -372,6 +372,7 @@ static struct debugfs_reg32 dwc3_regs[] = {
 
 
 	dump_register(OCFG),
 	dump_register(OCFG),
 	dump_register(OCTL),
 	dump_register(OCTL),
+	dump_register(OEVT),
 	dump_register(OEVTEN),
 	dump_register(OEVTEN),
 	dump_register(OSTS),
 	dump_register(OSTS),
 };
 };
@@ -577,8 +578,14 @@ static int dwc3_link_state_show(struct seq_file *s, void *unused)
 	case DWC3_LINK_STATE_LPBK:
 	case DWC3_LINK_STATE_LPBK:
 		seq_printf(s, "Loopback\n");
 		seq_printf(s, "Loopback\n");
 		break;
 		break;
+	case DWC3_LINK_STATE_RESET:
+		seq_printf(s, "Reset\n");
+		break;
+	case DWC3_LINK_STATE_RESUME:
+		seq_printf(s, "Resume\n");
+		break;
 	default:
 	default:
-		seq_printf(s, "UNKNOWN %d\n", reg);
+		seq_printf(s, "UNKNOWN %d\n", state);
 	}
 	}
 
 
 	return 0;
 	return 0;
@@ -661,28 +668,31 @@ int dwc3_debugfs_init(struct dwc3 *dwc)
 		goto err1;
 		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) {
-		ret = -ENOMEM;
-		goto err1;
-	}
-
-	file = debugfs_create_file("testmode", S_IRUGO | S_IWUSR, root,
-			dwc, &dwc3_testmode_fops);
-	if (!file) {
-		ret = -ENOMEM;
-		goto err1;
+	if (IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE)) {
+		file = debugfs_create_file("mode", S_IRUGO | S_IWUSR, root,
+				dwc, &dwc3_mode_fops);
+		if (!file) {
+			ret = -ENOMEM;
+			goto err1;
+		}
 	}
 	}
 
 
-	file = debugfs_create_file("link_state", S_IRUGO | S_IWUSR, root,
-			dwc, &dwc3_link_state_fops);
-	if (!file) {
-		ret = -ENOMEM;
-		goto err1;
+	if (IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE) ||
+			IS_ENABLED(CONFIG_USB_DWC3_GADGET)) {
+		file = debugfs_create_file("testmode", S_IRUGO | S_IWUSR, root,
+				dwc, &dwc3_testmode_fops);
+		if (!file) {
+			ret = -ENOMEM;
+			goto err1;
+		}
+
+		file = debugfs_create_file("link_state", S_IRUGO | S_IWUSR, root,
+				dwc, &dwc3_link_state_fops);
+		if (!file) {
+			ret = -ENOMEM;
+			goto err1;
+		}
 	}
 	}
-#endif
 
 
 	return 0;
 	return 0;
 
 

+ 63 - 35
drivers/usb/dwc3/dwc3-exynos.c

@@ -22,9 +22,9 @@
 #include <linux/usb/otg.h>
 #include <linux/usb/otg.h>
 #include <linux/usb/nop-usb-xceiv.h>
 #include <linux/usb/nop-usb-xceiv.h>
 #include <linux/of.h>
 #include <linux/of.h>
+#include <linux/of_platform.h>
 
 
 struct dwc3_exynos {
 struct dwc3_exynos {
-	struct platform_device	*dwc3;
 	struct platform_device	*usb2_phy;
 	struct platform_device	*usb2_phy;
 	struct platform_device	*usb3_phy;
 	struct platform_device	*usb3_phy;
 	struct device		*dev;
 	struct device		*dev;
@@ -86,21 +86,30 @@ err1:
 	return ret;
 	return ret;
 }
 }
 
 
+static int dwc3_exynos_remove_child(struct device *dev, void *unused)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+
+	platform_device_unregister(pdev);
+
+	return 0;
+}
+
 static u64 dwc3_exynos_dma_mask = DMA_BIT_MASK(32);
 static u64 dwc3_exynos_dma_mask = DMA_BIT_MASK(32);
 
 
 static int dwc3_exynos_probe(struct platform_device *pdev)
 static int dwc3_exynos_probe(struct platform_device *pdev)
 {
 {
-	struct platform_device	*dwc3;
 	struct dwc3_exynos	*exynos;
 	struct dwc3_exynos	*exynos;
 	struct clk		*clk;
 	struct clk		*clk;
 	struct device		*dev = &pdev->dev;
 	struct device		*dev = &pdev->dev;
+	struct device_node	*node = dev->of_node;
 
 
 	int			ret = -ENOMEM;
 	int			ret = -ENOMEM;
 
 
 	exynos = devm_kzalloc(dev, sizeof(*exynos), GFP_KERNEL);
 	exynos = devm_kzalloc(dev, sizeof(*exynos), GFP_KERNEL);
 	if (!exynos) {
 	if (!exynos) {
 		dev_err(dev, "not enough memory\n");
 		dev_err(dev, "not enough memory\n");
-		return -ENOMEM;
+		goto err1;
 	}
 	}
 
 
 	/*
 	/*
@@ -108,21 +117,15 @@ static int dwc3_exynos_probe(struct platform_device *pdev)
 	 * Since shared usb code relies on it, set it here for now.
 	 * Since shared usb code relies on it, set it here for now.
 	 * Once we move to full device tree support this will vanish off.
 	 * Once we move to full device tree support this will vanish off.
 	 */
 	 */
-	if (!pdev->dev.dma_mask)
-		pdev->dev.dma_mask = &dwc3_exynos_dma_mask;
+	if (!dev->dma_mask)
+		dev->dma_mask = &dwc3_exynos_dma_mask;
 
 
 	platform_set_drvdata(pdev, exynos);
 	platform_set_drvdata(pdev, exynos);
 
 
 	ret = dwc3_exynos_register_phys(exynos);
 	ret = dwc3_exynos_register_phys(exynos);
 	if (ret) {
 	if (ret) {
 		dev_err(dev, "couldn't register PHYs\n");
 		dev_err(dev, "couldn't register PHYs\n");
-		return ret;
-	}
-
-	dwc3 = platform_device_alloc("dwc3", PLATFORM_DEVID_AUTO);
-	if (!dwc3) {
-		dev_err(dev, "couldn't allocate dwc3 device\n");
-		return -ENOMEM;
+		goto err1;
 	}
 	}
 
 
 	clk = devm_clk_get(dev, "usbdrd30");
 	clk = devm_clk_get(dev, "usbdrd30");
@@ -132,37 +135,28 @@ static int dwc3_exynos_probe(struct platform_device *pdev)
 		goto err1;
 		goto err1;
 	}
 	}
 
 
-	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;
-	exynos->dwc3	= dwc3;
 	exynos->dev	= dev;
 	exynos->dev	= dev;
 	exynos->clk	= clk;
 	exynos->clk	= clk;
 
 
-	clk_enable(exynos->clk);
-
-	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");
+	clk_prepare_enable(exynos->clk);
+
+	if (node) {
+		ret = of_platform_populate(node, NULL, NULL, dev);
+		if (ret) {
+			dev_err(dev, "failed to add dwc3 core\n");
+			goto err2;
+		}
+	} else {
+		dev_err(dev, "no device node, failed to add dwc3 core\n");
+		ret = -ENODEV;
 		goto err2;
 		goto err2;
 	}
 	}
 
 
 	return 0;
 	return 0;
 
 
 err2:
 err2:
-	clk_disable(clk);
+	clk_disable_unprepare(clk);
 err1:
 err1:
-	platform_device_put(dwc3);
-
 	return ret;
 	return ret;
 }
 }
 
 
@@ -170,11 +164,11 @@ static int dwc3_exynos_remove(struct platform_device *pdev)
 {
 {
 	struct dwc3_exynos	*exynos = platform_get_drvdata(pdev);
 	struct dwc3_exynos	*exynos = platform_get_drvdata(pdev);
 
 
-	platform_device_unregister(exynos->dwc3);
 	platform_device_unregister(exynos->usb2_phy);
 	platform_device_unregister(exynos->usb2_phy);
 	platform_device_unregister(exynos->usb3_phy);
 	platform_device_unregister(exynos->usb3_phy);
+	device_for_each_child(&pdev->dev, NULL, dwc3_exynos_remove_child);
 
 
-	clk_disable(exynos->clk);
+	clk_disable_unprepare(exynos->clk);
 
 
 	return 0;
 	return 0;
 }
 }
@@ -187,12 +181,46 @@ static const struct of_device_id exynos_dwc3_match[] = {
 MODULE_DEVICE_TABLE(of, exynos_dwc3_match);
 MODULE_DEVICE_TABLE(of, exynos_dwc3_match);
 #endif
 #endif
 
 
+#ifdef CONFIG_PM_SLEEP
+static int dwc3_exynos_suspend(struct device *dev)
+{
+	struct dwc3_exynos *exynos = dev_get_drvdata(dev);
+
+	clk_disable(exynos->clk);
+
+	return 0;
+}
+
+static int dwc3_exynos_resume(struct device *dev)
+{
+	struct dwc3_exynos *exynos = dev_get_drvdata(dev);
+
+	clk_enable(exynos->clk);
+
+	/* runtime set active to reflect active state. */
+	pm_runtime_disable(dev);
+	pm_runtime_set_active(dev);
+	pm_runtime_enable(dev);
+
+	return 0;
+}
+
+static const struct dev_pm_ops dwc3_exynos_dev_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(dwc3_exynos_suspend, dwc3_exynos_resume)
+};
+
+#define DEV_PM_OPS	(&dwc3_exynos_dev_pm_ops)
+#else
+#define DEV_PM_OPS	NULL
+#endif /* CONFIG_PM_SLEEP */
+
 static struct platform_driver dwc3_exynos_driver = {
 static struct platform_driver dwc3_exynos_driver = {
 	.probe		= dwc3_exynos_probe,
 	.probe		= dwc3_exynos_probe,
 	.remove		= dwc3_exynos_remove,
 	.remove		= dwc3_exynos_remove,
 	.driver		= {
 	.driver		= {
 		.name	= "exynos-dwc3",
 		.name	= "exynos-dwc3",
 		.of_match_table = of_match_ptr(exynos_dwc3_match),
 		.of_match_table = of_match_ptr(exynos_dwc3_match),
+		.pm	= DEV_PM_OPS,
 	},
 	},
 };
 };
 
 

+ 119 - 126
drivers/usb/dwc3/dwc3-omap.c

@@ -52,7 +52,6 @@
 #include <linux/of_platform.h>
 #include <linux/of_platform.h>
 
 
 #include <linux/usb/otg.h>
 #include <linux/usb/otg.h>
-#include <linux/usb/nop-usb-xceiv.h>
 
 
 /*
 /*
  * All these registers belong to OMAP's Wrapper around the
  * All these registers belong to OMAP's Wrapper around the
@@ -117,20 +116,17 @@ struct dwc3_omap {
 	/* device lock */
 	/* device lock */
 	spinlock_t		lock;
 	spinlock_t		lock;
 
 
-	struct platform_device	*usb2_phy;
-	struct platform_device	*usb3_phy;
 	struct device		*dev;
 	struct device		*dev;
 
 
 	int			irq;
 	int			irq;
 	void __iomem		*base;
 	void __iomem		*base;
 
 
-	void			*context;
-	u32			resource_size;
+	u32			utmi_otg_status;
 
 
 	u32			dma_status:1;
 	u32			dma_status:1;
 };
 };
 
 
-struct dwc3_omap		*_omap;
+static struct dwc3_omap		*_omap;
 
 
 static inline u32 dwc3_omap_readl(void __iomem *base, u32 offset)
 static inline u32 dwc3_omap_readl(void __iomem *base, u32 offset)
 {
 {
@@ -142,11 +138,14 @@ static inline void dwc3_omap_writel(void __iomem *base, u32 offset, u32 value)
 	writel(value, base + offset);
 	writel(value, base + offset);
 }
 }
 
 
-void dwc3_omap_mailbox(enum omap_dwc3_vbus_id_status status)
+int dwc3_omap_mailbox(enum omap_dwc3_vbus_id_status status)
 {
 {
 	u32			val;
 	u32			val;
 	struct dwc3_omap	*omap = _omap;
 	struct dwc3_omap	*omap = _omap;
 
 
+	if (!omap)
+		return -EPROBE_DEFER;
+
 	switch (status) {
 	switch (status) {
 	case OMAP_DWC3_ID_GROUND:
 	case OMAP_DWC3_ID_GROUND:
 		dev_dbg(omap->dev, "ID GND\n");
 		dev_dbg(omap->dev, "ID GND\n");
@@ -189,63 +188,9 @@ void dwc3_omap_mailbox(enum omap_dwc3_vbus_id_status status)
 		dev_dbg(omap->dev, "ID float\n");
 		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;
-	struct platform_device	*pdev;
-	int			ret;
-
-	memset(&pdata, 0x00, sizeof(pdata));
-
-	pdev = platform_device_alloc("nop_usb_xceiv", PLATFORM_DEVID_AUTO);
-	if (!pdev)
-		return -ENOMEM;
-
-	omap->usb2_phy = pdev;
-	pdata.type = USB_PHY_TYPE_USB2;
-
-	ret = platform_device_add_data(omap->usb2_phy, &pdata, sizeof(pdata));
-	if (ret)
-		goto err1;
-
-	pdev = platform_device_alloc("nop_usb_xceiv", PLATFORM_DEVID_AUTO);
-	if (!pdev) {
-		ret = -ENOMEM;
-		goto err1;
-	}
-
-	omap->usb3_phy = pdev;
-	pdata.type = USB_PHY_TYPE_USB3;
-
-	ret = platform_device_add_data(omap->usb3_phy, &pdata, sizeof(pdata));
-	if (ret)
-		goto err2;
-
-	ret = platform_device_add(omap->usb2_phy);
-	if (ret)
-		goto err2;
-
-	ret = platform_device_add(omap->usb3_phy);
-	if (ret)
-		goto err3;
-
 	return 0;
 	return 0;
-
-err3:
-	platform_device_del(omap->usb2_phy);
-
-err2:
-	platform_device_put(omap->usb3_phy);
-
-err1:
-	platform_device_put(omap->usb2_phy);
-
-	return ret;
 }
 }
+EXPORT_SYMBOL_GPL(dwc3_omap_mailbox);
 
 
 static irqreturn_t dwc3_omap_interrupt(int irq, void *_omap)
 static irqreturn_t dwc3_omap_interrupt(int irq, void *_omap)
 {
 {
@@ -307,24 +252,57 @@ static int dwc3_omap_remove_core(struct device *dev, void *c)
 	return 0;
 	return 0;
 }
 }
 
 
+static void dwc3_omap_enable_irqs(struct dwc3_omap *omap)
+{
+	u32			reg;
+
+	/* enable all IRQs */
+	reg = USBOTGSS_IRQO_COREIRQ_ST;
+	dwc3_omap_writel(omap->base, USBOTGSS_IRQENABLE_SET_0, reg);
+
+	reg = (USBOTGSS_IRQ1_OEVT |
+			USBOTGSS_IRQ1_DRVVBUS_RISE |
+			USBOTGSS_IRQ1_CHRGVBUS_RISE |
+			USBOTGSS_IRQ1_DISCHRGVBUS_RISE |
+			USBOTGSS_IRQ1_IDPULLUP_RISE |
+			USBOTGSS_IRQ1_DRVVBUS_FALL |
+			USBOTGSS_IRQ1_CHRGVBUS_FALL |
+			USBOTGSS_IRQ1_DISCHRGVBUS_FALL |
+			USBOTGSS_IRQ1_IDPULLUP_FALL);
+
+	dwc3_omap_writel(omap->base, USBOTGSS_IRQENABLE_SET_1, reg);
+}
+
+static void dwc3_omap_disable_irqs(struct dwc3_omap *omap)
+{
+	/* disable all IRQs */
+	dwc3_omap_writel(omap->base, USBOTGSS_IRQENABLE_SET_1, 0x00);
+	dwc3_omap_writel(omap->base, USBOTGSS_IRQENABLE_SET_0, 0x00);
+}
+
+static u64 dwc3_omap_dma_mask = DMA_BIT_MASK(32);
+
 static int dwc3_omap_probe(struct platform_device *pdev)
 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 device_node	*node = pdev->dev.of_node;
 
 
 	struct dwc3_omap	*omap;
 	struct dwc3_omap	*omap;
 	struct resource		*res;
 	struct resource		*res;
 	struct device		*dev = &pdev->dev;
 	struct device		*dev = &pdev->dev;
 
 
-	int			size;
 	int			ret = -ENOMEM;
 	int			ret = -ENOMEM;
 	int			irq;
 	int			irq;
 
 
-	const u32		*utmi_mode;
+	int			utmi_mode = 0;
+
 	u32			reg;
 	u32			reg;
 
 
 	void __iomem		*base;
 	void __iomem		*base;
-	void			*context;
+
+	if (!node) {
+		dev_err(dev, "device node not found\n");
+		return -EINVAL;
+	}
 
 
 	omap = devm_kzalloc(dev, sizeof(*omap), GFP_KERNEL);
 	omap = devm_kzalloc(dev, sizeof(*omap), GFP_KERNEL);
 	if (!omap) {
 	if (!omap) {
@@ -334,13 +312,13 @@ static int dwc3_omap_probe(struct platform_device *pdev)
 
 
 	platform_set_drvdata(pdev, omap);
 	platform_set_drvdata(pdev, omap);
 
 
-	irq = platform_get_irq(pdev, 1);
+	irq = platform_get_irq(pdev, 0);
 	if (irq < 0) {
 	if (irq < 0) {
 		dev_err(dev, "missing IRQ resource\n");
 		dev_err(dev, "missing IRQ resource\n");
 		return -EINVAL;
 		return -EINVAL;
 	}
 	}
 
 
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!res) {
 	if (!res) {
 		dev_err(dev, "missing memory base resource\n");
 		dev_err(dev, "missing memory base resource\n");
 		return -EINVAL;
 		return -EINVAL;
@@ -352,25 +330,12 @@ static int dwc3_omap_probe(struct platform_device *pdev)
 		return -ENOMEM;
 		return -ENOMEM;
 	}
 	}
 
 
-	ret = dwc3_omap_register_phys(omap);
-	if (ret) {
-		dev_err(dev, "couldn't register PHYs\n");
-		return ret;
-	}
-
-	context = devm_kzalloc(dev, resource_size(res), GFP_KERNEL);
-	if (!context) {
-		dev_err(dev, "couldn't allocate dwc3 context memory\n");
-		return -ENOMEM;
-	}
-
 	spin_lock_init(&omap->lock);
 	spin_lock_init(&omap->lock);
 
 
-	omap->resource_size = resource_size(res);
-	omap->context	= context;
 	omap->dev	= dev;
 	omap->dev	= dev;
 	omap->irq	= irq;
 	omap->irq	= irq;
 	omap->base	= base;
 	omap->base	= base;
+	dev->dma_mask	= &dwc3_omap_dma_mask;
 
 
 	/*
 	/*
 	 * REVISIT if we ever have two instances of the wrapper, we will be
 	 * REVISIT if we ever have two instances of the wrapper, we will be
@@ -387,25 +352,17 @@ static int dwc3_omap_probe(struct platform_device *pdev)
 
 
 	reg = dwc3_omap_readl(omap->base, USBOTGSS_UTMI_OTG_STATUS);
 	reg = dwc3_omap_readl(omap->base, USBOTGSS_UTMI_OTG_STATUS);
 
 
-	utmi_mode = of_get_property(node, "utmi-mode", &size);
-	if (utmi_mode && size == sizeof(*utmi_mode)) {
-		reg |= *utmi_mode;
-	} else {
-		if (!pdata) {
-			dev_dbg(dev, "missing platform data\n");
-		} else {
-			switch (pdata->utmi_mode) {
-			case DWC3_OMAP_UTMI_MODE_SW:
-				reg |= USBOTGSS_UTMI_OTG_STATUS_SW_MODE;
-				break;
-			case DWC3_OMAP_UTMI_MODE_HW:
-				reg &= ~USBOTGSS_UTMI_OTG_STATUS_SW_MODE;
-				break;
-			default:
-				dev_dbg(dev, "UNKNOWN utmi mode %d\n",
-						pdata->utmi_mode);
-			}
-		}
+	of_property_read_u32(node, "utmi-mode", &utmi_mode);
+
+	switch (utmi_mode) {
+	case DWC3_OMAP_UTMI_MODE_SW:
+		reg |= USBOTGSS_UTMI_OTG_STATUS_SW_MODE;
+		break;
+	case DWC3_OMAP_UTMI_MODE_HW:
+		reg &= ~USBOTGSS_UTMI_OTG_STATUS_SW_MODE;
+		break;
+	default:
+		dev_dbg(dev, "UNKNOWN utmi mode %d\n", utmi_mode);
 	}
 	}
 
 
 	dwc3_omap_writel(omap->base, USBOTGSS_UTMI_OTG_STATUS, reg);
 	dwc3_omap_writel(omap->base, USBOTGSS_UTMI_OTG_STATUS, reg);
@@ -422,29 +379,12 @@ static int dwc3_omap_probe(struct platform_device *pdev)
 		return ret;
 		return ret;
 	}
 	}
 
 
-	/* enable all IRQs */
-	reg = USBOTGSS_IRQO_COREIRQ_ST;
-	dwc3_omap_writel(omap->base, USBOTGSS_IRQENABLE_SET_0, reg);
+	dwc3_omap_enable_irqs(omap);
 
 
-	reg = (USBOTGSS_IRQ1_OEVT |
-			USBOTGSS_IRQ1_DRVVBUS_RISE |
-			USBOTGSS_IRQ1_CHRGVBUS_RISE |
-			USBOTGSS_IRQ1_DISCHRGVBUS_RISE |
-			USBOTGSS_IRQ1_IDPULLUP_RISE |
-			USBOTGSS_IRQ1_DRVVBUS_FALL |
-			USBOTGSS_IRQ1_CHRGVBUS_FALL |
-			USBOTGSS_IRQ1_DISCHRGVBUS_FALL |
-			USBOTGSS_IRQ1_IDPULLUP_FALL);
-
-	dwc3_omap_writel(omap->base, USBOTGSS_IRQENABLE_SET_1, reg);
-
-	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;
-		}
+	ret = of_platform_populate(node, NULL, NULL, dev);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to create dwc3 core\n");
+		return ret;
 	}
 	}
 
 
 	return 0;
 	return 0;
@@ -454,8 +394,7 @@ static int dwc3_omap_remove(struct platform_device *pdev)
 {
 {
 	struct dwc3_omap	*omap = platform_get_drvdata(pdev);
 	struct dwc3_omap	*omap = platform_get_drvdata(pdev);
 
 
-	platform_device_unregister(omap->usb2_phy);
-	platform_device_unregister(omap->usb3_phy);
+	dwc3_omap_disable_irqs(omap);
 	pm_runtime_put_sync(&pdev->dev);
 	pm_runtime_put_sync(&pdev->dev);
 	pm_runtime_disable(&pdev->dev);
 	pm_runtime_disable(&pdev->dev);
 	device_for_each_child(&pdev->dev, NULL, dwc3_omap_remove_core);
 	device_for_each_child(&pdev->dev, NULL, dwc3_omap_remove_core);
@@ -465,18 +404,72 @@ static int dwc3_omap_remove(struct platform_device *pdev)
 
 
 static const struct of_device_id of_dwc3_match[] = {
 static const struct of_device_id of_dwc3_match[] = {
 	{
 	{
-		"ti,dwc3",
+		.compatible =	"ti,dwc3"
 	},
 	},
 	{ },
 	{ },
 };
 };
 MODULE_DEVICE_TABLE(of, of_dwc3_match);
 MODULE_DEVICE_TABLE(of, of_dwc3_match);
 
 
+#ifdef CONFIG_PM_SLEEP
+static int dwc3_omap_prepare(struct device *dev)
+{
+	struct dwc3_omap	*omap = dev_get_drvdata(dev);
+
+	dwc3_omap_disable_irqs(omap);
+
+	return 0;
+}
+
+static void dwc3_omap_complete(struct device *dev)
+{
+	struct dwc3_omap	*omap = dev_get_drvdata(dev);
+
+	dwc3_omap_enable_irqs(omap);
+}
+
+static int dwc3_omap_suspend(struct device *dev)
+{
+	struct dwc3_omap	*omap = dev_get_drvdata(dev);
+
+	omap->utmi_otg_status = dwc3_omap_readl(omap->base,
+			USBOTGSS_UTMI_OTG_STATUS);
+
+	return 0;
+}
+
+static int dwc3_omap_resume(struct device *dev)
+{
+	struct dwc3_omap	*omap = dev_get_drvdata(dev);
+
+	dwc3_omap_writel(omap->base, USBOTGSS_UTMI_OTG_STATUS,
+			omap->utmi_otg_status);
+
+	pm_runtime_disable(dev);
+	pm_runtime_set_active(dev);
+	pm_runtime_enable(dev);
+
+	return 0;
+}
+
+static const struct dev_pm_ops dwc3_omap_dev_pm_ops = {
+	.prepare	= dwc3_omap_prepare,
+	.complete	= dwc3_omap_complete,
+
+	SET_SYSTEM_SLEEP_PM_OPS(dwc3_omap_suspend, dwc3_omap_resume)
+};
+
+#define DEV_PM_OPS	(&dwc3_omap_dev_pm_ops)
+#else
+#define DEV_PM_OPS	NULL
+#endif /* CONFIG_PM_SLEEP */
+
 static struct platform_driver dwc3_omap_driver = {
 static struct platform_driver dwc3_omap_driver = {
 	.probe		= dwc3_omap_probe,
 	.probe		= dwc3_omap_probe,
 	.remove		= dwc3_omap_remove,
 	.remove		= dwc3_omap_remove,
 	.driver		= {
 	.driver		= {
 		.name	= "omap-dwc3",
 		.name	= "omap-dwc3",
 		.of_match_table	= of_dwc3_match,
 		.of_match_table	= of_dwc3_match,
+		.pm	= DEV_PM_OPS,
 	},
 	},
 };
 };
 
 

+ 38 - 0
drivers/usb/dwc3/dwc3-pci.c

@@ -212,11 +212,49 @@ static DEFINE_PCI_DEVICE_TABLE(dwc3_pci_id_table) = {
 };
 };
 MODULE_DEVICE_TABLE(pci, dwc3_pci_id_table);
 MODULE_DEVICE_TABLE(pci, dwc3_pci_id_table);
 
 
+#ifdef CONFIG_PM
+static int dwc3_pci_suspend(struct device *dev)
+{
+	struct pci_dev	*pci = to_pci_dev(dev);
+
+	pci_disable_device(pci);
+
+	return 0;
+}
+
+static int dwc3_pci_resume(struct device *dev)
+{
+	struct pci_dev	*pci = to_pci_dev(dev);
+	int		ret;
+
+	ret = pci_enable_device(pci);
+	if (ret) {
+		dev_err(dev, "can't re-enable device --> %d\n", ret);
+		return ret;
+	}
+
+	pci_set_master(pci);
+
+	return 0;
+}
+
+static const struct dev_pm_ops dwc3_pci_dev_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(dwc3_pci_suspend, dwc3_pci_resume)
+};
+
+#define DEV_PM_OPS	(&dwc3_pci_dev_pm_ops)
+#else
+#define DEV_PM_OPS	NULL
+#endif /* CONFIG_PM */
+
 static struct pci_driver dwc3_pci_driver = {
 static struct pci_driver dwc3_pci_driver = {
 	.name		= "dwc3-pci",
 	.name		= "dwc3-pci",
 	.id_table	= dwc3_pci_id_table,
 	.id_table	= dwc3_pci_id_table,
 	.probe		= dwc3_pci_probe,
 	.probe		= dwc3_pci_probe,
 	.remove		= dwc3_pci_remove,
 	.remove		= dwc3_pci_remove,
+	.driver		= {
+		.pm	= DEV_PM_OPS,
+	},
 };
 };
 
 
 MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>");
 MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>");

+ 21 - 12
drivers/usb/dwc3/ep0.c

@@ -394,10 +394,13 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc,
 	u32			wIndex;
 	u32			wIndex;
 	u32			reg;
 	u32			reg;
 	int			ret;
 	int			ret;
+	enum usb_device_state	state;
 
 
 	wValue = le16_to_cpu(ctrl->wValue);
 	wValue = le16_to_cpu(ctrl->wValue);
 	wIndex = le16_to_cpu(ctrl->wIndex);
 	wIndex = le16_to_cpu(ctrl->wIndex);
 	recip = ctrl->bRequestType & USB_RECIP_MASK;
 	recip = ctrl->bRequestType & USB_RECIP_MASK;
+	state = dwc->gadget.state;
+
 	switch (recip) {
 	switch (recip) {
 	case USB_RECIP_DEVICE:
 	case USB_RECIP_DEVICE:
 
 
@@ -409,7 +412,7 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc,
 		 * default control pipe
 		 * default control pipe
 		 */
 		 */
 		case USB_DEVICE_U1_ENABLE:
 		case USB_DEVICE_U1_ENABLE:
-			if (dwc->dev_state != DWC3_CONFIGURED_STATE)
+			if (state != USB_STATE_CONFIGURED)
 				return -EINVAL;
 				return -EINVAL;
 			if (dwc->speed != DWC3_DSTS_SUPERSPEED)
 			if (dwc->speed != DWC3_DSTS_SUPERSPEED)
 				return -EINVAL;
 				return -EINVAL;
@@ -423,7 +426,7 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc,
 			break;
 			break;
 
 
 		case USB_DEVICE_U2_ENABLE:
 		case USB_DEVICE_U2_ENABLE:
-			if (dwc->dev_state != DWC3_CONFIGURED_STATE)
+			if (state != USB_STATE_CONFIGURED)
 				return -EINVAL;
 				return -EINVAL;
 			if (dwc->speed != DWC3_DSTS_SUPERSPEED)
 			if (dwc->speed != DWC3_DSTS_SUPERSPEED)
 				return -EINVAL;
 				return -EINVAL;
@@ -493,6 +496,7 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc,
 
 
 static int dwc3_ep0_set_address(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
 static int dwc3_ep0_set_address(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
 {
 {
+	enum usb_device_state state = dwc->gadget.state;
 	u32 addr;
 	u32 addr;
 	u32 reg;
 	u32 reg;
 
 
@@ -502,7 +506,7 @@ static int dwc3_ep0_set_address(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
 		return -EINVAL;
 		return -EINVAL;
 	}
 	}
 
 
-	if (dwc->dev_state == DWC3_CONFIGURED_STATE) {
+	if (state == USB_STATE_CONFIGURED) {
 		dev_dbg(dwc->dev, "trying to set address when configured\n");
 		dev_dbg(dwc->dev, "trying to set address when configured\n");
 		return -EINVAL;
 		return -EINVAL;
 	}
 	}
@@ -513,9 +517,9 @@ static int dwc3_ep0_set_address(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
 	dwc3_writel(dwc->regs, DWC3_DCFG, reg);
 	dwc3_writel(dwc->regs, DWC3_DCFG, reg);
 
 
 	if (addr)
 	if (addr)
-		dwc->dev_state = DWC3_ADDRESS_STATE;
+		usb_gadget_set_state(&dwc->gadget, USB_STATE_ADDRESS);
 	else
 	else
-		dwc->dev_state = DWC3_DEFAULT_STATE;
+		usb_gadget_set_state(&dwc->gadget, USB_STATE_DEFAULT);
 
 
 	return 0;
 	return 0;
 }
 }
@@ -532,6 +536,7 @@ static int dwc3_ep0_delegate_req(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
 
 
 static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
 static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
 {
 {
+	enum usb_device_state state = dwc->gadget.state;
 	u32 cfg;
 	u32 cfg;
 	int ret;
 	int ret;
 	u32 reg;
 	u32 reg;
@@ -539,16 +544,18 @@ static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
 	dwc->start_config_issued = false;
 	dwc->start_config_issued = false;
 	cfg = le16_to_cpu(ctrl->wValue);
 	cfg = le16_to_cpu(ctrl->wValue);
 
 
-	switch (dwc->dev_state) {
-	case DWC3_DEFAULT_STATE:
+	switch (state) {
+	case USB_STATE_DEFAULT:
 		return -EINVAL;
 		return -EINVAL;
 		break;
 		break;
 
 
-	case DWC3_ADDRESS_STATE:
+	case USB_STATE_ADDRESS:
 		ret = dwc3_ep0_delegate_req(dwc, ctrl);
 		ret = dwc3_ep0_delegate_req(dwc, ctrl);
 		/* if the cfg matches and the cfg is non zero */
 		/* if the cfg matches and the cfg is non zero */
 		if (cfg && (!ret || (ret == USB_GADGET_DELAYED_STATUS))) {
 		if (cfg && (!ret || (ret == USB_GADGET_DELAYED_STATUS))) {
-			dwc->dev_state = DWC3_CONFIGURED_STATE;
+			usb_gadget_set_state(&dwc->gadget,
+					USB_STATE_CONFIGURED);
+
 			/*
 			/*
 			 * Enable transition to U1/U2 state when
 			 * Enable transition to U1/U2 state when
 			 * nothing is pending from application.
 			 * nothing is pending from application.
@@ -562,10 +569,11 @@ static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
 		}
 		}
 		break;
 		break;
 
 
-	case DWC3_CONFIGURED_STATE:
+	case USB_STATE_CONFIGURED:
 		ret = dwc3_ep0_delegate_req(dwc, ctrl);
 		ret = dwc3_ep0_delegate_req(dwc, ctrl);
 		if (!cfg)
 		if (!cfg)
-			dwc->dev_state = DWC3_ADDRESS_STATE;
+			usb_gadget_set_state(&dwc->gadget,
+					USB_STATE_ADDRESS);
 		break;
 		break;
 	default:
 	default:
 		ret = -EINVAL;
 		ret = -EINVAL;
@@ -620,10 +628,11 @@ static void dwc3_ep0_set_sel_cmpl(struct usb_ep *ep, struct usb_request *req)
 static int dwc3_ep0_set_sel(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
 static int dwc3_ep0_set_sel(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
 {
 {
 	struct dwc3_ep	*dep;
 	struct dwc3_ep	*dep;
+	enum usb_device_state state = dwc->gadget.state;
 	u16		wLength;
 	u16		wLength;
 	u16		wValue;
 	u16		wValue;
 
 
-	if (dwc->dev_state == DWC3_DEFAULT_STATE)
+	if (state == USB_STATE_DEFAULT)
 		return -EINVAL;
 		return -EINVAL;
 
 
 	wValue = le16_to_cpu(ctrl->wValue);
 	wValue = le16_to_cpu(ctrl->wValue);

+ 230 - 91
drivers/usb/dwc3/gadget.c

@@ -1425,8 +1425,10 @@ static int dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on)
 		if (dwc->revision >= DWC3_REVISION_194A)
 		if (dwc->revision >= DWC3_REVISION_194A)
 			reg &= ~DWC3_DCTL_KEEP_CONNECT;
 			reg &= ~DWC3_DCTL_KEEP_CONNECT;
 		reg |= DWC3_DCTL_RUN_STOP;
 		reg |= DWC3_DCTL_RUN_STOP;
+		dwc->pullups_connected = true;
 	} else {
 	} else {
 		reg &= ~DWC3_DCTL_RUN_STOP;
 		reg &= ~DWC3_DCTL_RUN_STOP;
+		dwc->pullups_connected = false;
 	}
 	}
 
 
 	dwc3_writel(dwc->regs, DWC3_DCTL, reg);
 	dwc3_writel(dwc->regs, DWC3_DCTL, reg);
@@ -1469,6 +1471,33 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on)
 	return ret;
 	return ret;
 }
 }
 
 
+static void dwc3_gadget_enable_irq(struct dwc3 *dwc)
+{
+	u32			reg;
+
+	/* Enable all but Start and End of Frame IRQs */
+	reg = (DWC3_DEVTEN_VNDRDEVTSTRCVEDEN |
+			DWC3_DEVTEN_EVNTOVERFLOWEN |
+			DWC3_DEVTEN_CMDCMPLTEN |
+			DWC3_DEVTEN_ERRTICERREN |
+			DWC3_DEVTEN_WKUPEVTEN |
+			DWC3_DEVTEN_ULSTCNGEN |
+			DWC3_DEVTEN_CONNECTDONEEN |
+			DWC3_DEVTEN_USBRSTEN |
+			DWC3_DEVTEN_DISCONNEVTEN);
+
+	dwc3_writel(dwc->regs, DWC3_DEVTEN, reg);
+}
+
+static void dwc3_gadget_disable_irq(struct dwc3 *dwc)
+{
+	/* mask all interrupts */
+	dwc3_writel(dwc->regs, DWC3_DEVTEN, 0x00);
+}
+
+static irqreturn_t dwc3_interrupt(int irq, void *_dwc);
+static irqreturn_t dwc3_thread_interrupt(int irq, void *_dwc);
+
 static int dwc3_gadget_start(struct usb_gadget *g,
 static int dwc3_gadget_start(struct usb_gadget *g,
 		struct usb_gadget_driver *driver)
 		struct usb_gadget_driver *driver)
 {
 {
@@ -1476,6 +1505,7 @@ static int dwc3_gadget_start(struct usb_gadget *g,
 	struct dwc3_ep		*dep;
 	struct dwc3_ep		*dep;
 	unsigned long		flags;
 	unsigned long		flags;
 	int			ret = 0;
 	int			ret = 0;
+	int			irq;
 	u32			reg;
 	u32			reg;
 
 
 	spin_lock_irqsave(&dwc->lock, flags);
 	spin_lock_irqsave(&dwc->lock, flags);
@@ -1489,7 +1519,6 @@ static int dwc3_gadget_start(struct usb_gadget *g,
 	}
 	}
 
 
 	dwc->gadget_driver	= driver;
 	dwc->gadget_driver	= driver;
-	dwc->gadget.dev.driver	= &driver->driver;
 
 
 	reg = dwc3_readl(dwc->regs, DWC3_DCFG);
 	reg = dwc3_readl(dwc->regs, DWC3_DCFG);
 	reg &= ~(DWC3_DCFG_SPEED_MASK);
 	reg &= ~(DWC3_DCFG_SPEED_MASK);
@@ -1536,6 +1565,17 @@ static int dwc3_gadget_start(struct usb_gadget *g,
 	dwc->ep0state = EP0_SETUP_PHASE;
 	dwc->ep0state = EP0_SETUP_PHASE;
 	dwc3_ep0_out_start(dwc);
 	dwc3_ep0_out_start(dwc);
 
 
+	irq = platform_get_irq(to_platform_device(dwc->dev), 0);
+	ret = request_threaded_irq(irq, dwc3_interrupt, dwc3_thread_interrupt,
+			IRQF_SHARED | IRQF_ONESHOT, "dwc3", dwc);
+	if (ret) {
+		dev_err(dwc->dev, "failed to request irq #%d --> %d\n",
+				irq, ret);
+		goto err1;
+	}
+
+	dwc3_gadget_enable_irq(dwc);
+
 	spin_unlock_irqrestore(&dwc->lock, flags);
 	spin_unlock_irqrestore(&dwc->lock, flags);
 
 
 	return 0;
 	return 0;
@@ -1554,14 +1594,18 @@ static int dwc3_gadget_stop(struct usb_gadget *g,
 {
 {
 	struct dwc3		*dwc = gadget_to_dwc(g);
 	struct dwc3		*dwc = gadget_to_dwc(g);
 	unsigned long		flags;
 	unsigned long		flags;
+	int			irq;
 
 
 	spin_lock_irqsave(&dwc->lock, flags);
 	spin_lock_irqsave(&dwc->lock, flags);
 
 
+	dwc3_gadget_disable_irq(dwc);
+	irq = platform_get_irq(to_platform_device(dwc->dev), 0);
+	free_irq(irq, dwc);
+
 	__dwc3_gadget_ep_disable(dwc->eps[0]);
 	__dwc3_gadget_ep_disable(dwc->eps[0]);
 	__dwc3_gadget_ep_disable(dwc->eps[1]);
 	__dwc3_gadget_ep_disable(dwc->eps[1]);
 
 
 	dwc->gadget_driver	= NULL;
 	dwc->gadget_driver	= NULL;
-	dwc->gadget.dev.driver	= NULL;
 
 
 	spin_unlock_irqrestore(&dwc->lock, flags);
 	spin_unlock_irqrestore(&dwc->lock, flags);
 
 
@@ -1579,14 +1623,15 @@ static const struct usb_gadget_ops dwc3_gadget_ops = {
 
 
 /* -------------------------------------------------------------------------- */
 /* -------------------------------------------------------------------------- */
 
 
-static int dwc3_gadget_init_endpoints(struct dwc3 *dwc)
+static int dwc3_gadget_init_hw_endpoints(struct dwc3 *dwc,
+		u8 num, u32 direction)
 {
 {
 	struct dwc3_ep			*dep;
 	struct dwc3_ep			*dep;
-	u8				epnum;
+	u8				i;
 
 
-	INIT_LIST_HEAD(&dwc->gadget.ep_list);
+	for (i = 0; i < num; i++) {
+		u8 epnum = (i << 1) | (!!direction);
 
 
-	for (epnum = 0; epnum < DWC3_ENDPOINTS_NUM; epnum++) {
 		dep = kzalloc(sizeof(*dep), GFP_KERNEL);
 		dep = kzalloc(sizeof(*dep), GFP_KERNEL);
 		if (!dep) {
 		if (!dep) {
 			dev_err(dwc->dev, "can't allocate endpoint %d\n",
 			dev_err(dwc->dev, "can't allocate endpoint %d\n",
@@ -1600,6 +1645,7 @@ static int dwc3_gadget_init_endpoints(struct dwc3 *dwc)
 
 
 		snprintf(dep->name, sizeof(dep->name), "ep%d%s", epnum >> 1,
 		snprintf(dep->name, sizeof(dep->name), "ep%d%s", epnum >> 1,
 				(epnum & 1) ? "in" : "out");
 				(epnum & 1) ? "in" : "out");
+
 		dep->endpoint.name = dep->name;
 		dep->endpoint.name = dep->name;
 		dep->direction = (epnum & 1);
 		dep->direction = (epnum & 1);
 
 
@@ -1630,6 +1676,27 @@ static int dwc3_gadget_init_endpoints(struct dwc3 *dwc)
 	return 0;
 	return 0;
 }
 }
 
 
+static int dwc3_gadget_init_endpoints(struct dwc3 *dwc)
+{
+	int				ret;
+
+	INIT_LIST_HEAD(&dwc->gadget.ep_list);
+
+	ret = dwc3_gadget_init_hw_endpoints(dwc, dwc->num_out_eps, 0);
+	if (ret < 0) {
+		dev_vdbg(dwc->dev, "failed to allocate OUT endpoints\n");
+		return ret;
+	}
+
+	ret = dwc3_gadget_init_hw_endpoints(dwc, dwc->num_in_eps, 1);
+	if (ret < 0) {
+		dev_vdbg(dwc->dev, "failed to allocate IN endpoints\n");
+		return ret;
+	}
+
+	return 0;
+}
+
 static void dwc3_gadget_free_endpoints(struct dwc3 *dwc)
 static void dwc3_gadget_free_endpoints(struct dwc3 *dwc)
 {
 {
 	struct dwc3_ep			*dep;
 	struct dwc3_ep			*dep;
@@ -1637,6 +1704,9 @@ static void dwc3_gadget_free_endpoints(struct dwc3 *dwc)
 
 
 	for (epnum = 0; epnum < DWC3_ENDPOINTS_NUM; epnum++) {
 	for (epnum = 0; epnum < DWC3_ENDPOINTS_NUM; epnum++) {
 		dep = dwc->eps[epnum];
 		dep = dwc->eps[epnum];
+		if (!dep)
+			continue;
+
 		dwc3_free_trb_pool(dep);
 		dwc3_free_trb_pool(dep);
 
 
 		if (epnum != 0 && epnum != 1)
 		if (epnum != 0 && epnum != 1)
@@ -1646,12 +1716,8 @@ static void dwc3_gadget_free_endpoints(struct dwc3 *dwc)
 	}
 	}
 }
 }
 
 
-static void dwc3_gadget_release(struct device *dev)
-{
-	dev_dbg(dev, "%s\n", __func__);
-}
-
 /* -------------------------------------------------------------------------- */
 /* -------------------------------------------------------------------------- */
+
 static int __dwc3_cleanup_done_trbs(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,
 		struct dwc3_request *req, struct dwc3_trb *trb,
 		const struct dwc3_event_depevt *event, int status)
 		const struct dwc3_event_depevt *event, int status)
@@ -1975,6 +2041,9 @@ static void dwc3_stop_active_transfers(struct dwc3 *dwc)
 		struct dwc3_ep *dep;
 		struct dwc3_ep *dep;
 
 
 		dep = dwc->eps[epnum];
 		dep = dwc->eps[epnum];
+		if (!dep)
+			continue;
+
 		if (!(dep->flags & DWC3_EP_ENABLED))
 		if (!(dep->flags & DWC3_EP_ENABLED))
 			continue;
 			continue;
 
 
@@ -1992,6 +2061,8 @@ static void dwc3_clear_stall_all_ep(struct dwc3 *dwc)
 		int ret;
 		int ret;
 
 
 		dep = dwc->eps[epnum];
 		dep = dwc->eps[epnum];
+		if (!dep)
+			continue;
 
 
 		if (!(dep->flags & DWC3_EP_STALL))
 		if (!(dep->flags & DWC3_EP_STALL))
 			continue;
 			continue;
@@ -2091,7 +2162,7 @@ static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc)
 	}
 	}
 
 
 	/* after reset -> Default State */
 	/* after reset -> Default State */
-	dwc->dev_state = DWC3_DEFAULT_STATE;
+	usb_gadget_set_state(&dwc->gadget, USB_STATE_DEFAULT);
 
 
 	/* Recent versions support automatic phy suspend and don't need this */
 	/* Recent versions support automatic phy suspend and don't need this */
 	if (dwc->revision < DWC3_REVISION_194A) {
 	if (dwc->revision < DWC3_REVISION_194A) {
@@ -2277,6 +2348,34 @@ static void dwc3_gadget_linksts_change_interrupt(struct dwc3 *dwc,
 		unsigned int evtinfo)
 		unsigned int evtinfo)
 {
 {
 	enum dwc3_link_state	next = evtinfo & DWC3_LINK_STATE_MASK;
 	enum dwc3_link_state	next = evtinfo & DWC3_LINK_STATE_MASK;
+	unsigned int		pwropt;
+
+	/*
+	 * WORKAROUND: DWC3 < 2.50a have an issue when configured without
+	 * Hibernation mode enabled which would show up when device detects
+	 * host-initiated U3 exit.
+	 *
+	 * In that case, device will generate a Link State Change Interrupt
+	 * from U3 to RESUME which is only necessary if Hibernation is
+	 * configured in.
+	 *
+	 * There are no functional changes due to such spurious event and we
+	 * just need to ignore it.
+	 *
+	 * Refers to:
+	 *
+	 * STAR#9000570034 RTL: SS Resume event generated in non-Hibernation
+	 * operational mode
+	 */
+	pwropt = DWC3_GHWPARAMS1_EN_PWROPT(dwc->hwparams.hwparams1);
+	if ((dwc->revision < DWC3_REVISION_250A) &&
+			(pwropt != DWC3_GHWPARAMS1_EN_PWROPT_HIB)) {
+		if ((dwc->link_state == DWC3_LINK_STATE_U3) &&
+				(next == DWC3_LINK_STATE_RESUME)) {
+			dev_vdbg(dwc->dev, "ignoring transition U3 -> Resume\n");
+			return;
+		}
+	}
 
 
 	/*
 	/*
 	 * WORKAROUND: DWC3 Revisions <1.83a have an issue which, depending
 	 * WORKAROUND: DWC3 Revisions <1.83a have an issue which, depending
@@ -2387,40 +2486,73 @@ static void dwc3_process_event_entry(struct dwc3 *dwc,
 	}
 	}
 }
 }
 
 
+static irqreturn_t dwc3_thread_interrupt(int irq, void *_dwc)
+{
+	struct dwc3 *dwc = _dwc;
+	unsigned long flags;
+	irqreturn_t ret = IRQ_NONE;
+	int i;
+
+	spin_lock_irqsave(&dwc->lock, flags);
+
+	for (i = 0; i < dwc->num_event_buffers; i++) {
+		struct dwc3_event_buffer *evt;
+		int			left;
+
+		evt = dwc->ev_buffs[i];
+		left = evt->count;
+
+		if (!(evt->flags & DWC3_EVENT_PENDING))
+			continue;
+
+		while (left > 0) {
+			union dwc3_event event;
+
+			event.raw = *(u32 *) (evt->buf + evt->lpos);
+
+			dwc3_process_event_entry(dwc, &event);
+
+			/*
+			 * FIXME we wrap around correctly to the next entry as
+			 * almost all entries are 4 bytes in size. There is one
+			 * entry which has 12 bytes which is a regular entry
+			 * followed by 8 bytes data. ATM I don't know how
+			 * things are organized if we get next to the a
+			 * boundary so I worry about that once we try to handle
+			 * that.
+			 */
+			evt->lpos = (evt->lpos + 4) % DWC3_EVENT_BUFFERS_SIZE;
+			left -= 4;
+
+			dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(i), 4);
+		}
+
+		evt->count = 0;
+		evt->flags &= ~DWC3_EVENT_PENDING;
+		ret = IRQ_HANDLED;
+	}
+
+	spin_unlock_irqrestore(&dwc->lock, flags);
+
+	return ret;
+}
+
 static irqreturn_t dwc3_process_event_buf(struct dwc3 *dwc, u32 buf)
 static irqreturn_t dwc3_process_event_buf(struct dwc3 *dwc, u32 buf)
 {
 {
 	struct dwc3_event_buffer *evt;
 	struct dwc3_event_buffer *evt;
-	int left;
 	u32 count;
 	u32 count;
 
 
+	evt = dwc->ev_buffs[buf];
+
 	count = dwc3_readl(dwc->regs, DWC3_GEVNTCOUNT(buf));
 	count = dwc3_readl(dwc->regs, DWC3_GEVNTCOUNT(buf));
 	count &= DWC3_GEVNTCOUNT_MASK;
 	count &= DWC3_GEVNTCOUNT_MASK;
 	if (!count)
 	if (!count)
 		return IRQ_NONE;
 		return IRQ_NONE;
 
 
-	evt = dwc->ev_buffs[buf];
-	left = count;
-
-	while (left > 0) {
-		union dwc3_event event;
-
-		event.raw = *(u32 *) (evt->buf + evt->lpos);
+	evt->count = count;
+	evt->flags |= DWC3_EVENT_PENDING;
 
 
-		dwc3_process_event_entry(dwc, &event);
-		/*
-		 * XXX we wrap around correctly to the next entry as almost all
-		 * entries are 4 bytes in size. There is one entry which has 12
-		 * bytes which is a regular entry followed by 8 bytes data. ATM
-		 * I don't know how things are organized if were get next to the
-		 * a boundary so I worry about that once we try to handle that.
-		 */
-		evt->lpos = (evt->lpos + 4) % DWC3_EVENT_BUFFERS_SIZE;
-		left -= 4;
-
-		dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(buf), 4);
-	}
-
-	return IRQ_HANDLED;
+	return IRQ_WAKE_THREAD;
 }
 }
 
 
 static irqreturn_t dwc3_interrupt(int irq, void *_dwc)
 static irqreturn_t dwc3_interrupt(int irq, void *_dwc)
@@ -2435,7 +2567,7 @@ static irqreturn_t dwc3_interrupt(int irq, void *_dwc)
 		irqreturn_t status;
 		irqreturn_t status;
 
 
 		status = dwc3_process_event_buf(dwc, i);
 		status = dwc3_process_event_buf(dwc, i);
-		if (status == IRQ_HANDLED)
+		if (status == IRQ_WAKE_THREAD)
 			ret = status;
 			ret = status;
 	}
 	}
 
 
@@ -2454,7 +2586,6 @@ int dwc3_gadget_init(struct dwc3 *dwc)
 {
 {
 	u32					reg;
 	u32					reg;
 	int					ret;
 	int					ret;
-	int					irq;
 
 
 	dwc->ctrl_req = dma_alloc_coherent(dwc->dev, sizeof(*dwc->ctrl_req),
 	dwc->ctrl_req = dma_alloc_coherent(dwc->dev, sizeof(*dwc->ctrl_req),
 			&dwc->ctrl_req_addr, GFP_KERNEL);
 			&dwc->ctrl_req_addr, GFP_KERNEL);
@@ -2488,19 +2619,10 @@ int dwc3_gadget_init(struct dwc3 *dwc)
 		goto err3;
 		goto err3;
 	}
 	}
 
 
-	dev_set_name(&dwc->gadget.dev, "gadget");
-
 	dwc->gadget.ops			= &dwc3_gadget_ops;
 	dwc->gadget.ops			= &dwc3_gadget_ops;
 	dwc->gadget.max_speed		= USB_SPEED_SUPER;
 	dwc->gadget.max_speed		= USB_SPEED_SUPER;
 	dwc->gadget.speed		= USB_SPEED_UNKNOWN;
 	dwc->gadget.speed		= USB_SPEED_UNKNOWN;
-	dwc->gadget.dev.parent		= dwc->dev;
 	dwc->gadget.sg_supported	= true;
 	dwc->gadget.sg_supported	= true;
-
-	dma_set_coherent_mask(&dwc->gadget.dev, dwc->dev->coherent_dma_mask);
-
-	dwc->gadget.dev.dma_parms	= dwc->dev->dma_parms;
-	dwc->gadget.dev.dma_mask	= dwc->dev->dma_mask;
-	dwc->gadget.dev.release		= dwc3_gadget_release;
 	dwc->gadget.name		= "dwc3-gadget";
 	dwc->gadget.name		= "dwc3-gadget";
 
 
 	/*
 	/*
@@ -2512,60 +2634,24 @@ int dwc3_gadget_init(struct dwc3 *dwc)
 	if (ret)
 	if (ret)
 		goto err4;
 		goto err4;
 
 
-	irq = platform_get_irq(to_platform_device(dwc->dev), 0);
-
-	ret = request_irq(irq, dwc3_interrupt, IRQF_SHARED,
-			"dwc3", dwc);
-	if (ret) {
-		dev_err(dwc->dev, "failed to request irq #%d --> %d\n",
-				irq, ret);
-		goto err5;
-	}
-
 	reg = dwc3_readl(dwc->regs, DWC3_DCFG);
 	reg = dwc3_readl(dwc->regs, DWC3_DCFG);
 	reg |= DWC3_DCFG_LPM_CAP;
 	reg |= DWC3_DCFG_LPM_CAP;
 	dwc3_writel(dwc->regs, DWC3_DCFG, reg);
 	dwc3_writel(dwc->regs, DWC3_DCFG, reg);
 
 
-	/* Enable all but Start and End of Frame IRQs */
-	reg = (DWC3_DEVTEN_VNDRDEVTSTRCVEDEN |
-			DWC3_DEVTEN_EVNTOVERFLOWEN |
-			DWC3_DEVTEN_CMDCMPLTEN |
-			DWC3_DEVTEN_ERRTICERREN |
-			DWC3_DEVTEN_WKUPEVTEN |
-			DWC3_DEVTEN_ULSTCNGEN |
-			DWC3_DEVTEN_CONNECTDONEEN |
-			DWC3_DEVTEN_USBRSTEN |
-			DWC3_DEVTEN_DISCONNEVTEN);
-	dwc3_writel(dwc->regs, DWC3_DEVTEN, reg);
-
-	/* automatic phy suspend only on recent versions */
+	/* Enable USB2 LPM and automatic phy suspend only on recent versions */
 	if (dwc->revision >= DWC3_REVISION_194A) {
 	if (dwc->revision >= DWC3_REVISION_194A) {
 		dwc3_gadget_usb2_phy_suspend(dwc, false);
 		dwc3_gadget_usb2_phy_suspend(dwc, false);
 		dwc3_gadget_usb3_phy_suspend(dwc, false);
 		dwc3_gadget_usb3_phy_suspend(dwc, false);
 	}
 	}
 
 
-	ret = device_register(&dwc->gadget.dev);
-	if (ret) {
-		dev_err(dwc->dev, "failed to register gadget device\n");
-		put_device(&dwc->gadget.dev);
-		goto err6;
-	}
-
 	ret = usb_add_gadget_udc(dwc->dev, &dwc->gadget);
 	ret = usb_add_gadget_udc(dwc->dev, &dwc->gadget);
 	if (ret) {
 	if (ret) {
 		dev_err(dwc->dev, "failed to register udc\n");
 		dev_err(dwc->dev, "failed to register udc\n");
-		goto err7;
+		goto err5;
 	}
 	}
 
 
 	return 0;
 	return 0;
 
 
-err7:
-	device_unregister(&dwc->gadget.dev);
-
-err6:
-	dwc3_writel(dwc->regs, DWC3_DEVTEN, 0x00);
-	free_irq(irq, dwc);
-
 err5:
 err5:
 	dwc3_gadget_free_endpoints(dwc);
 	dwc3_gadget_free_endpoints(dwc);
 
 
@@ -2588,15 +2674,11 @@ err0:
 	return ret;
 	return ret;
 }
 }
 
 
+/* -------------------------------------------------------------------------- */
+
 void dwc3_gadget_exit(struct dwc3 *dwc)
 void dwc3_gadget_exit(struct dwc3 *dwc)
 {
 {
-	int			irq;
-
 	usb_del_gadget_udc(&dwc->gadget);
 	usb_del_gadget_udc(&dwc->gadget);
-	irq = platform_get_irq(to_platform_device(dwc->dev), 0);
-
-	dwc3_writel(dwc->regs, DWC3_DEVTEN, 0x00);
-	free_irq(irq, dwc);
 
 
 	dwc3_gadget_free_endpoints(dwc);
 	dwc3_gadget_free_endpoints(dwc);
 
 
@@ -2610,6 +2692,63 @@ void dwc3_gadget_exit(struct dwc3 *dwc)
 
 
 	dma_free_coherent(dwc->dev, sizeof(*dwc->ctrl_req),
 	dma_free_coherent(dwc->dev, sizeof(*dwc->ctrl_req),
 			dwc->ctrl_req, dwc->ctrl_req_addr);
 			dwc->ctrl_req, dwc->ctrl_req_addr);
+}
 
 
-	device_unregister(&dwc->gadget.dev);
+int dwc3_gadget_prepare(struct dwc3 *dwc)
+{
+	if (dwc->pullups_connected)
+		dwc3_gadget_disable_irq(dwc);
+
+	return 0;
+}
+
+void dwc3_gadget_complete(struct dwc3 *dwc)
+{
+	if (dwc->pullups_connected) {
+		dwc3_gadget_enable_irq(dwc);
+		dwc3_gadget_run_stop(dwc, true);
+	}
+}
+
+int dwc3_gadget_suspend(struct dwc3 *dwc)
+{
+	__dwc3_gadget_ep_disable(dwc->eps[0]);
+	__dwc3_gadget_ep_disable(dwc->eps[1]);
+
+	dwc->dcfg = dwc3_readl(dwc->regs, DWC3_DCFG);
+
+	return 0;
+}
+
+int dwc3_gadget_resume(struct dwc3 *dwc)
+{
+	struct dwc3_ep		*dep;
+	int			ret;
+
+	/* Start with SuperSpeed Default */
+	dwc3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(512);
+
+	dep = dwc->eps[0];
+	ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL, false);
+	if (ret)
+		goto err0;
+
+	dep = dwc->eps[1];
+	ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL, false);
+	if (ret)
+		goto err1;
+
+	/* begin to receive SETUP packets */
+	dwc->ep0state = EP0_SETUP_PHASE;
+	dwc3_ep0_out_start(dwc);
+
+	dwc3_writel(dwc->regs, DWC3_DCFG, dwc->dcfg);
+
+	return 0;
+
+err1:
+	__dwc3_gadget_ep_disable(dwc->eps[0]);
+
+err0:
+	return ret;
 }
 }

+ 11 - 7
drivers/usb/gadget/Kconfig

@@ -196,7 +196,6 @@ config USB_OMAP
 	tristate "OMAP USB Device Controller"
 	tristate "OMAP USB Device Controller"
 	depends on ARCH_OMAP1
 	depends on ARCH_OMAP1
 	select ISP1301_OMAP if MACH_OMAP_H2 || MACH_OMAP_H3 || MACH_OMAP_H4_OTG
 	select ISP1301_OMAP if MACH_OMAP_H2 || MACH_OMAP_H3 || MACH_OMAP_H4_OTG
-	select USB_OTG_UTILS if ARCH_OMAP
 	help
 	help
 	   Many Texas Instruments OMAP processors have flexible full
 	   Many Texas Instruments OMAP processors have flexible full
 	   speed USB device controllers, with support for up to 30
 	   speed USB device controllers, with support for up to 30
@@ -211,7 +210,6 @@ config USB_OMAP
 config USB_PXA25X
 config USB_PXA25X
 	tristate "PXA 25x or IXP 4xx"
 	tristate "PXA 25x or IXP 4xx"
 	depends on (ARCH_PXA && PXA25x) || ARCH_IXP4XX
 	depends on (ARCH_PXA && PXA25x) || ARCH_IXP4XX
-	select USB_OTG_UTILS
 	help
 	help
 	   Intel's PXA 25x series XScale ARM-5TE processors include
 	   Intel's PXA 25x series XScale ARM-5TE processors include
 	   an integrated full speed USB 1.1 device controller.  The
 	   an integrated full speed USB 1.1 device controller.  The
@@ -259,8 +257,6 @@ config USB_RENESAS_USBHS_UDC
 
 
 config USB_PXA27X
 config USB_PXA27X
 	tristate "PXA 27x"
 	tristate "PXA 27x"
-	depends on ARCH_PXA && (PXA27x || PXA3xx)
-	select USB_OTG_UTILS
 	help
 	help
 	   Intel's PXA 27x series XScale ARM v5TE processors include
 	   Intel's PXA 27x series XScale ARM v5TE processors include
 	   an integrated full speed USB 1.1 device controller.
 	   an integrated full speed USB 1.1 device controller.
@@ -329,9 +325,6 @@ config USB_MV_UDC
 
 
 config USB_MV_U3D
 config USB_MV_U3D
 	tristate "MARVELL PXA2128 USB 3.0 controller"
 	tristate "MARVELL PXA2128 USB 3.0 controller"
-	depends on CPU_MMP3
-	select USB_GADGET_DUALSPEED
-	select USB_GADGET_SUPERSPEED
 	help
 	help
 	  MARVELL PXA2128 Processor series include a super speed USB3.0 device
 	  MARVELL PXA2128 Processor series include a super speed USB3.0 device
 	  controller, which support super speed USB peripheral.
 	  controller, which support super speed USB peripheral.
@@ -501,6 +494,7 @@ endmenu
 # composite based drivers
 # composite based drivers
 config USB_LIBCOMPOSITE
 config USB_LIBCOMPOSITE
 	tristate
 	tristate
+	select CONFIGFS_FS
 	depends on USB_GADGET
 	depends on USB_GADGET
 
 
 config USB_F_ACM
 config USB_F_ACM
@@ -512,6 +506,12 @@ config USB_F_SS_LB
 config USB_U_SERIAL
 config USB_U_SERIAL
 	tristate
 	tristate
 
 
+config USB_F_SERIAL
+	tristate
+
+config USB_F_OBEX
+	tristate
+
 choice
 choice
 	tristate "USB Gadget Drivers"
 	tristate "USB Gadget Drivers"
 	default USB_ETH
 	default USB_ETH
@@ -766,6 +766,8 @@ config USB_G_SERIAL
 	depends on TTY
 	depends on TTY
 	select USB_U_SERIAL
 	select USB_U_SERIAL
 	select USB_F_ACM
 	select USB_F_ACM
+	select USB_F_SERIAL
+	select USB_F_OBEX
 	select USB_LIBCOMPOSITE
 	select USB_LIBCOMPOSITE
 	help
 	help
 	  The Serial Gadget talks to the Linux-USB generic serial driver.
 	  The Serial Gadget talks to the Linux-USB generic serial driver.
@@ -839,6 +841,7 @@ config USB_G_NOKIA
 	depends on PHONET
 	depends on PHONET
 	select USB_LIBCOMPOSITE
 	select USB_LIBCOMPOSITE
 	select USB_U_SERIAL
 	select USB_U_SERIAL
+	select USB_F_ACM
 	help
 	help
 	  The Nokia composite gadget provides support for acm, obex
 	  The Nokia composite gadget provides support for acm, obex
 	  and phonet in only one composite gadget driver.
 	  and phonet in only one composite gadget driver.
@@ -957,6 +960,7 @@ config USB_G_WEBCAM
 	tristate "USB Webcam Gadget"
 	tristate "USB Webcam Gadget"
 	depends on VIDEO_DEV
 	depends on VIDEO_DEV
 	select USB_LIBCOMPOSITE
 	select USB_LIBCOMPOSITE
+	select VIDEOBUF2_VMALLOC
 	help
 	help
 	  The Webcam Gadget acts as a composite USB Audio and Video Class
 	  The Webcam Gadget acts as a composite USB Audio and Video Class
 	  device. It provides a userspace API to process UVC control requests
 	  device. It provides a userspace API to process UVC control requests

+ 9 - 4
drivers/usb/gadget/Makefile

@@ -6,7 +6,7 @@ ccflags-$(CONFIG_USB_GADGET_DEBUG) := -DDEBUG
 obj-$(CONFIG_USB_GADGET)	+= udc-core.o
 obj-$(CONFIG_USB_GADGET)	+= udc-core.o
 obj-$(CONFIG_USB_LIBCOMPOSITE)	+= libcomposite.o
 obj-$(CONFIG_USB_LIBCOMPOSITE)	+= libcomposite.o
 libcomposite-y			:= usbstring.o config.o epautoconf.o
 libcomposite-y			:= usbstring.o config.o epautoconf.o
-libcomposite-y			+= composite.o functions.o
+libcomposite-y			+= composite.o functions.o configfs.o
 obj-$(CONFIG_USB_DUMMY_HCD)	+= dummy_hcd.o
 obj-$(CONFIG_USB_DUMMY_HCD)	+= dummy_hcd.o
 obj-$(CONFIG_USB_NET2272)	+= net2272.o
 obj-$(CONFIG_USB_NET2272)	+= net2272.o
 obj-$(CONFIG_USB_NET2280)	+= net2280.o
 obj-$(CONFIG_USB_NET2280)	+= net2280.o
@@ -36,10 +36,15 @@ obj-$(CONFIG_USB_FUSB300)	+= fusb300_udc.o
 obj-$(CONFIG_USB_MV_U3D)	+= mv_u3d_core.o
 obj-$(CONFIG_USB_MV_U3D)	+= mv_u3d_core.o
 
 
 # USB Functions
 # 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
+usb_f_acm-y			:= f_acm.o
+obj-$(CONFIG_USB_F_ACM)		+= usb_f_acm.o
+usb_f_ss_lb-y			:= f_loopback.o f_sourcesink.o
+obj-$(CONFIG_USB_F_SS_LB)	+= usb_f_ss_lb.o
 obj-$(CONFIG_USB_U_SERIAL)	+= u_serial.o
 obj-$(CONFIG_USB_U_SERIAL)	+= u_serial.o
+usb_f_serial-y			:= f_serial.o
+obj-$(CONFIG_USB_F_SERIAL)	+= usb_f_serial.o
+usb_f_obex-y			:= f_obex.o
+obj-$(CONFIG_USB_F_OBEX)	+= usb_f_obex.o
 
 
 #
 #
 # USB gadget drivers
 # USB gadget drivers

+ 1 - 14
drivers/usb/gadget/acm_ms.c

@@ -109,7 +109,6 @@ FSG_MODULE_PARAMETERS(/* no prefix */, fsg_mod_data);
 static struct fsg_common fsg_common;
 static struct fsg_common fsg_common;
 
 
 /*-------------------------------------------------------------------------*/
 /*-------------------------------------------------------------------------*/
-static unsigned char tty_line;
 static struct usb_function *f_acm;
 static struct usb_function *f_acm;
 static struct usb_function_instance *f_acm_inst;
 static struct usb_function_instance *f_acm_inst;
 /*
 /*
@@ -117,7 +116,6 @@ static struct usb_function_instance *f_acm_inst;
  */
  */
 static int __init acm_ms_do_config(struct usb_configuration *c)
 static int __init acm_ms_do_config(struct usb_configuration *c)
 {
 {
-	struct f_serial_opts *opts;
 	int	status;
 	int	status;
 
 
 	if (gadget_is_otg(c->cdev->gadget)) {
 	if (gadget_is_otg(c->cdev->gadget)) {
@@ -129,9 +127,6 @@ static int __init acm_ms_do_config(struct usb_configuration *c)
 	if (IS_ERR(f_acm_inst))
 	if (IS_ERR(f_acm_inst))
 		return PTR_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);
 	f_acm = usb_get_function(f_acm_inst);
 	if (IS_ERR(f_acm)) {
 	if (IS_ERR(f_acm)) {
 		status = PTR_ERR(f_acm);
 		status = PTR_ERR(f_acm);
@@ -171,16 +166,11 @@ static int __init acm_ms_bind(struct usb_composite_dev *cdev)
 	int			status;
 	int			status;
 	void			*retp;
 	void			*retp;
 
 
-	/* set up serial link layer */
-	status = gserial_alloc_line(&tty_line);
-	if (status < 0)
-		return status;
-
 	/* set up mass storage function */
 	/* set up mass storage function */
 	retp = fsg_common_from_params(&fsg_common, cdev, &fsg_mod_data);
 	retp = fsg_common_from_params(&fsg_common, cdev, &fsg_mod_data);
 	if (IS_ERR(retp)) {
 	if (IS_ERR(retp)) {
 		status = PTR_ERR(retp);
 		status = PTR_ERR(retp);
-		goto fail0;
+		return PTR_ERR(retp);
 	}
 	}
 
 
 	/*
 	/*
@@ -207,8 +197,6 @@ static int __init acm_ms_bind(struct usb_composite_dev *cdev)
 	/* error recovery */
 	/* error recovery */
 fail1:
 fail1:
 	fsg_common_put(&fsg_common);
 	fsg_common_put(&fsg_common);
-fail0:
-	gserial_free_line(tty_line);
 	return status;
 	return status;
 }
 }
 
 
@@ -216,7 +204,6 @@ static int __exit acm_ms_unbind(struct usb_composite_dev *cdev)
 {
 {
 	usb_put_function(f_acm);
 	usb_put_function(f_acm);
 	usb_put_function_instance(f_acm_inst);
 	usb_put_function_instance(f_acm_inst);
-	gserial_free_line(tty_line);
 	return 0;
 	return 0;
 }
 }
 
 

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

@@ -1922,7 +1922,6 @@ static int amd5536_udc_start(struct usb_gadget *g,
 
 
 	driver->driver.bus = NULL;
 	driver->driver.bus = NULL;
 	dev->driver = driver;
 	dev->driver = driver;
-	dev->gadget.dev.driver = &driver->driver;
 
 
 	/* Some gadget drivers use both ep0 directions.
 	/* Some gadget drivers use both ep0 directions.
 	 * NOTE: to gadget driver, ep0 is just one endpoint...
 	 * NOTE: to gadget driver, ep0 is just one endpoint...
@@ -1973,7 +1972,6 @@ static int amd5536_udc_stop(struct usb_gadget *g,
 	shutdown(dev, driver);
 	shutdown(dev, driver);
 	spin_unlock_irqrestore(&dev->lock, flags);
 	spin_unlock_irqrestore(&dev->lock, flags);
 
 
-	dev->gadget.dev.driver = NULL;
 	dev->driver = NULL;
 	dev->driver = NULL;
 
 
 	/* set SD */
 	/* set SD */
@@ -3080,7 +3078,6 @@ static void udc_pci_remove(struct pci_dev *pdev)
 	if (dev->active)
 	if (dev->active)
 		pci_disable_device(pdev);
 		pci_disable_device(pdev);
 
 
-	device_unregister(&dev->gadget.dev);
 	pci_set_drvdata(pdev, NULL);
 	pci_set_drvdata(pdev, NULL);
 
 
 	udc_remove(dev);
 	udc_remove(dev);
@@ -3245,8 +3242,6 @@ static int udc_pci_probe(
 	dev->phys_addr = resource;
 	dev->phys_addr = resource;
 	dev->irq = pdev->irq;
 	dev->irq = pdev->irq;
 	dev->pdev = pdev;
 	dev->pdev = pdev;
-	dev->gadget.dev.parent = &pdev->dev;
-	dev->gadget.dev.dma_mask = pdev->dev.dma_mask;
 
 
 	/* general probing */
 	/* general probing */
 	if (udc_probe(dev) == 0)
 	if (udc_probe(dev) == 0)
@@ -3273,7 +3268,6 @@ static int udc_probe(struct udc *dev)
 	dev->gadget.ops = &udc_ops;
 	dev->gadget.ops = &udc_ops;
 
 
 	dev_set_name(&dev->gadget.dev, "gadget");
 	dev_set_name(&dev->gadget.dev, "gadget");
-	dev->gadget.dev.release = gadget_release;
 	dev->gadget.name = name;
 	dev->gadget.name = name;
 	dev->gadget.max_speed = USB_SPEED_HIGH;
 	dev->gadget.max_speed = USB_SPEED_HIGH;
 
 
@@ -3297,17 +3291,11 @@ static int udc_probe(struct udc *dev)
 		"driver version: %s(for Geode5536 B1)\n", tmp);
 		"driver version: %s(for Geode5536 B1)\n", tmp);
 	udc = dev;
 	udc = dev;
 
 
-	retval = usb_add_gadget_udc(&udc->pdev->dev, &dev->gadget);
+	retval = usb_add_gadget_udc_release(&udc->pdev->dev, &dev->gadget,
+			gadget_release);
 	if (retval)
 	if (retval)
 		goto finished;
 		goto finished;
 
 
-	retval = device_register(&dev->gadget.dev);
-	if (retval) {
-		usb_del_gadget_udc(&dev->gadget);
-		put_device(&dev->gadget.dev);
-		goto finished;
-	}
-
 	/* timer init */
 	/* timer init */
 	init_timer(&udc_timer);
 	init_timer(&udc_timer);
 	udc_timer.function = udc_timer_function;
 	udc_timer.function = udc_timer_function;

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

@@ -472,7 +472,6 @@ struct udc_request {
 
 
 	/* flags */
 	/* flags */
 	unsigned			dma_going : 1,
 	unsigned			dma_going : 1,
-					dma_mapping : 1,
 					dma_done : 1;
 					dma_done : 1;
 	/* phys. address */
 	/* phys. address */
 	dma_addr_t			td_phys;
 	dma_addr_t			td_phys;

+ 1 - 13
drivers/usb/gadget/at91_udc.c

@@ -1631,7 +1631,6 @@ static int at91_start(struct usb_gadget *gadget,
 
 
 	udc = container_of(gadget, struct at91_udc, gadget);
 	udc = container_of(gadget, struct at91_udc, gadget);
 	udc->driver = driver;
 	udc->driver = driver;
-	udc->gadget.dev.driver = &driver->driver;
 	udc->gadget.dev.of_node = udc->pdev->dev.of_node;
 	udc->gadget.dev.of_node = udc->pdev->dev.of_node;
 	udc->enabled = 1;
 	udc->enabled = 1;
 	udc->selfpowered = 1;
 	udc->selfpowered = 1;
@@ -1652,7 +1651,6 @@ static int at91_stop(struct usb_gadget *gadget,
 	at91_udp_write(udc, AT91_UDP_IDR, ~0);
 	at91_udp_write(udc, AT91_UDP_IDR, ~0);
 	spin_unlock_irqrestore(&udc->lock, flags);
 	spin_unlock_irqrestore(&udc->lock, flags);
 
 
-	udc->gadget.dev.driver = NULL;
 	udc->driver = NULL;
 	udc->driver = NULL;
 
 
 	DBG("unbound from %s\n", driver->driver.name);
 	DBG("unbound from %s\n", driver->driver.name);
@@ -1780,13 +1778,7 @@ static int at91udc_probe(struct platform_device *pdev)
 		DBG("clocks missing\n");
 		DBG("clocks missing\n");
 		retval = -ENODEV;
 		retval = -ENODEV;
 		/* NOTE: we "know" here that refcounts on these are NOPs */
 		/* NOTE: we "know" here that refcounts on these are NOPs */
-		goto fail0b;
-	}
-
-	retval = device_register(&udc->gadget.dev);
-	if (retval < 0) {
-		put_device(&udc->gadget.dev);
-		goto fail0b;
+		goto fail1;
 	}
 	}
 
 
 	/* don't do anything until we have both gadget driver and VBUS */
 	/* don't do anything until we have both gadget driver and VBUS */
@@ -1857,8 +1849,6 @@ fail3:
 fail2:
 fail2:
 	free_irq(udc->udp_irq, udc);
 	free_irq(udc->udp_irq, udc);
 fail1:
 fail1:
-	device_unregister(&udc->gadget.dev);
-fail0b:
 	iounmap(udc->udp_baseaddr);
 	iounmap(udc->udp_baseaddr);
 fail0a:
 fail0a:
 	if (cpu_is_at91rm9200())
 	if (cpu_is_at91rm9200())
@@ -1892,8 +1882,6 @@ static int __exit at91udc_remove(struct platform_device *pdev)
 		gpio_free(udc->board.vbus_pin);
 		gpio_free(udc->board.vbus_pin);
 	}
 	}
 	free_irq(udc->udp_irq, udc);
 	free_irq(udc->udp_irq, udc);
-	device_unregister(&udc->gadget.dev);
-
 	iounmap(udc->udp_baseaddr);
 	iounmap(udc->udp_baseaddr);
 
 
 	if (cpu_is_at91rm9200())
 	if (cpu_is_at91rm9200())

+ 6 - 38
drivers/usb/gadget/atmel_usba_udc.c

@@ -489,13 +489,8 @@ request_complete(struct usba_ep *ep, struct usba_request *req, int status)
 	if (req->req.status == -EINPROGRESS)
 	if (req->req.status == -EINPROGRESS)
 		req->req.status = status;
 		req->req.status = status;
 
 
-	if (req->mapped) {
-		dma_unmap_single(
-			&udc->pdev->dev, req->req.dma, req->req.length,
-			ep->is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
-		req->req.dma = DMA_ADDR_INVALID;
-		req->mapped = 0;
-	}
+	if (req->using_dma)
+		usb_gadget_unmap_request(&udc->gadget, &req->req, ep->is_in);
 
 
 	DBG(DBG_GADGET | DBG_REQ,
 	DBG(DBG_GADGET | DBG_REQ,
 		"%s: req %p complete: status %d, actual %u\n",
 		"%s: req %p complete: status %d, actual %u\n",
@@ -684,7 +679,6 @@ usba_ep_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags)
 		return NULL;
 		return NULL;
 
 
 	INIT_LIST_HEAD(&req->queue);
 	INIT_LIST_HEAD(&req->queue);
-	req->req.dma = DMA_ADDR_INVALID;
 
 
 	return &req->req;
 	return &req->req;
 }
 }
@@ -717,20 +711,11 @@ static int queue_dma(struct usba_udc *udc, struct usba_ep *ep,
 		return -EINVAL;
 		return -EINVAL;
 	}
 	}
 
 
-	req->using_dma = 1;
-
-	if (req->req.dma == DMA_ADDR_INVALID) {
-		req->req.dma = dma_map_single(
-			&udc->pdev->dev, req->req.buf, req->req.length,
-			ep->is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
-		req->mapped = 1;
-	} else {
-		dma_sync_single_for_device(
-			&udc->pdev->dev, req->req.dma, req->req.length,
-			ep->is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
-		req->mapped = 0;
-	}
+	ret = usb_gadget_map_request(&udc->gadget, &req->req, ep->is_in);
+	if (ret)
+		return ret;
 
 
+	req->using_dma = 1;
 	req->ctrl = USBA_BF(DMA_BUF_LEN, req->req.length)
 	req->ctrl = USBA_BF(DMA_BUF_LEN, req->req.length)
 			| USBA_DMA_CH_EN | USBA_DMA_END_BUF_IE
 			| USBA_DMA_CH_EN | USBA_DMA_END_BUF_IE
 			| USBA_DMA_END_TR_EN | USBA_DMA_END_TR_IE;
 			| USBA_DMA_END_TR_EN | USBA_DMA_END_TR_IE;
@@ -1799,7 +1784,6 @@ static int atmel_usba_start(struct usb_gadget *gadget,
 
 
 	udc->devstatus = 1 << USB_DEVICE_SELF_POWERED;
 	udc->devstatus = 1 << USB_DEVICE_SELF_POWERED;
 	udc->driver = driver;
 	udc->driver = driver;
-	udc->gadget.dev.driver = &driver->driver;
 	spin_unlock_irqrestore(&udc->lock, flags);
 	spin_unlock_irqrestore(&udc->lock, flags);
 
 
 	clk_enable(udc->pclk);
 	clk_enable(udc->pclk);
@@ -1841,7 +1825,6 @@ static int atmel_usba_stop(struct usb_gadget *gadget,
 	toggle_bias(0);
 	toggle_bias(0);
 	usba_writel(udc, CTRL, USBA_DISABLE_MASK);
 	usba_writel(udc, CTRL, USBA_DISABLE_MASK);
 
 
-	udc->gadget.dev.driver = NULL;
 	udc->driver = NULL;
 	udc->driver = NULL;
 
 
 	clk_disable(udc->hclk);
 	clk_disable(udc->hclk);
@@ -1900,10 +1883,6 @@ static int __init usba_udc_probe(struct platform_device *pdev)
 	dev_info(&pdev->dev, "FIFO at 0x%08lx mapped at %p\n",
 	dev_info(&pdev->dev, "FIFO at 0x%08lx mapped at %p\n",
 		 (unsigned long)fifo->start, udc->fifo);
 		 (unsigned long)fifo->start, udc->fifo);
 
 
-	device_initialize(&udc->gadget.dev);
-	udc->gadget.dev.parent = &pdev->dev;
-	udc->gadget.dev.dma_mask = pdev->dev.dma_mask;
-
 	platform_set_drvdata(pdev, udc);
 	platform_set_drvdata(pdev, udc);
 
 
 	/* Make sure we start from a clean slate */
 	/* Make sure we start from a clean slate */
@@ -1962,12 +1941,6 @@ static int __init usba_udc_probe(struct platform_device *pdev)
 	}
 	}
 	udc->irq = irq;
 	udc->irq = irq;
 
 
-	ret = device_add(&udc->gadget.dev);
-	if (ret) {
-		dev_dbg(&pdev->dev, "Could not add gadget: %d\n", ret);
-		goto err_device_add;
-	}
-
 	if (gpio_is_valid(pdata->vbus_pin)) {
 	if (gpio_is_valid(pdata->vbus_pin)) {
 		if (!gpio_request(pdata->vbus_pin, "atmel_usba_udc")) {
 		if (!gpio_request(pdata->vbus_pin, "atmel_usba_udc")) {
 			udc->vbus_pin = pdata->vbus_pin;
 			udc->vbus_pin = pdata->vbus_pin;
@@ -2007,9 +1980,6 @@ err_add_udc:
 		gpio_free(udc->vbus_pin);
 		gpio_free(udc->vbus_pin);
 	}
 	}
 
 
-	device_unregister(&udc->gadget.dev);
-
-err_device_add:
 	free_irq(irq, udc);
 	free_irq(irq, udc);
 err_request_irq:
 err_request_irq:
 	kfree(usba_ep);
 	kfree(usba_ep);
@@ -2053,8 +2023,6 @@ static int __exit usba_udc_remove(struct platform_device *pdev)
 	clk_put(udc->hclk);
 	clk_put(udc->hclk);
 	clk_put(udc->pclk);
 	clk_put(udc->pclk);
 
 
-	device_unregister(&udc->gadget.dev);
-
 	return 0;
 	return 0;
 }
 }
 
 

+ 0 - 6
drivers/usb/gadget/atmel_usba_udc.h

@@ -216,12 +216,6 @@
 #define EP0_EPT_SIZE		USBA_EPT_SIZE_64
 #define EP0_EPT_SIZE		USBA_EPT_SIZE_64
 #define EP0_NR_BANKS		1
 #define EP0_NR_BANKS		1
 
 
-/*
- * REVISIT: Try to eliminate this value. Can we rely on req->mapped to
- * provide this information?
- */
-#define DMA_ADDR_INVALID (~(dma_addr_t)0)
-
 #define FIFO_IOMEM_ID	0
 #define FIFO_IOMEM_ID	0
 #define CTRL_IOMEM_ID	1
 #define CTRL_IOMEM_ID	1
 
 

+ 0 - 23
drivers/usb/gadget/bcm63xx_udc.c

@@ -1819,7 +1819,6 @@ static int bcm63xx_udc_start(struct usb_gadget *gadget,
 
 
 	udc->driver = driver;
 	udc->driver = driver;
 	driver->driver.bus = NULL;
 	driver->driver.bus = NULL;
-	udc->gadget.dev.driver = &driver->driver;
 	udc->gadget.dev.of_node = udc->dev->of_node;
 	udc->gadget.dev.of_node = udc->dev->of_node;
 
 
 	spin_unlock_irqrestore(&udc->lock, flags);
 	spin_unlock_irqrestore(&udc->lock, flags);
@@ -1841,7 +1840,6 @@ static int bcm63xx_udc_stop(struct usb_gadget *gadget,
 	spin_lock_irqsave(&udc->lock, flags);
 	spin_lock_irqsave(&udc->lock, flags);
 
 
 	udc->driver = NULL;
 	udc->driver = NULL;
-	udc->gadget.dev.driver = NULL;
 
 
 	/*
 	/*
 	 * If we switch the PHY too abruptly after dropping D+, the host
 	 * If we switch the PHY too abruptly after dropping D+, the host
@@ -2305,17 +2303,6 @@ static void bcm63xx_udc_cleanup_debugfs(struct bcm63xx_udc *udc)
  * Driver init/exit
  * Driver init/exit
  ***********************************************************************/
  ***********************************************************************/
 
 
-/**
- * bcm63xx_udc_gadget_release - Called from device_release().
- * @dev: Unused.
- *
- * We get a warning if this function doesn't exist, but it's empty because
- * we don't have to free any of the memory allocated with the devm_* APIs.
- */
-static void bcm63xx_udc_gadget_release(struct device *dev)
-{
-}
-
 /**
 /**
  * bcm63xx_udc_probe - Initialize a new instance of the UDC.
  * bcm63xx_udc_probe - Initialize a new instance of the UDC.
  * @pdev: Platform device struct from the bcm63xx BSP code.
  * @pdev: Platform device struct from the bcm63xx BSP code.
@@ -2368,13 +2355,9 @@ static int bcm63xx_udc_probe(struct platform_device *pdev)
 
 
 	spin_lock_init(&udc->lock);
 	spin_lock_init(&udc->lock);
 	INIT_WORK(&udc->ep0_wq, bcm63xx_ep0_process);
 	INIT_WORK(&udc->ep0_wq, bcm63xx_ep0_process);
-	dev_set_name(&udc->gadget.dev, "gadget");
 
 
 	udc->gadget.ops = &bcm63xx_udc_ops;
 	udc->gadget.ops = &bcm63xx_udc_ops;
 	udc->gadget.name = dev_name(dev);
 	udc->gadget.name = dev_name(dev);
-	udc->gadget.dev.parent = dev;
-	udc->gadget.dev.release = bcm63xx_udc_gadget_release;
-	udc->gadget.dev.dma_mask = dev->dma_mask;
 
 
 	if (!pd->use_fullspeed && !use_fullspeed)
 	if (!pd->use_fullspeed && !use_fullspeed)
 		udc->gadget.max_speed = USB_SPEED_HIGH;
 		udc->gadget.max_speed = USB_SPEED_HIGH;
@@ -2414,17 +2397,12 @@ static int bcm63xx_udc_probe(struct platform_device *pdev)
 		}
 		}
 	}
 	}
 
 
-	rc = device_register(&udc->gadget.dev);
-	if (rc)
-		goto out_uninit;
-
 	bcm63xx_udc_init_debugfs(udc);
 	bcm63xx_udc_init_debugfs(udc);
 	rc = usb_add_gadget_udc(dev, &udc->gadget);
 	rc = usb_add_gadget_udc(dev, &udc->gadget);
 	if (!rc)
 	if (!rc)
 		return 0;
 		return 0;
 
 
 	bcm63xx_udc_cleanup_debugfs(udc);
 	bcm63xx_udc_cleanup_debugfs(udc);
-	device_unregister(&udc->gadget.dev);
 out_uninit:
 out_uninit:
 	bcm63xx_uninit_udc_hw(udc);
 	bcm63xx_uninit_udc_hw(udc);
 	return rc;
 	return rc;
@@ -2440,7 +2418,6 @@ static int bcm63xx_udc_remove(struct platform_device *pdev)
 
 
 	bcm63xx_udc_cleanup_debugfs(udc);
 	bcm63xx_udc_cleanup_debugfs(udc);
 	usb_del_gadget_udc(&udc->gadget);
 	usb_del_gadget_udc(&udc->gadget);
-	device_unregister(&udc->gadget.dev);
 	BUG_ON(udc->driver);
 	BUG_ON(udc->driver);
 
 
 	platform_set_drvdata(pdev, NULL);
 	platform_set_drvdata(pdev, NULL);

+ 7 - 20
drivers/usb/gadget/cdc2.c

@@ -103,18 +103,16 @@ static struct usb_gadget_strings *dev_strings[] = {
 };
 };
 
 
 static u8 hostaddr[ETH_ALEN];
 static u8 hostaddr[ETH_ALEN];
-
+static struct eth_dev *the_dev;
 /*-------------------------------------------------------------------------*/
 /*-------------------------------------------------------------------------*/
 static struct usb_function *f_acm;
 static struct usb_function *f_acm;
 static struct usb_function_instance *fi_serial;
 static struct usb_function_instance *fi_serial;
 
 
-static unsigned char tty_line;
 /*
 /*
  * We _always_ have both CDC ECM and CDC ACM functions.
  * We _always_ have both CDC ECM and CDC ACM functions.
  */
  */
 static int __init cdc_do_config(struct usb_configuration *c)
 static int __init cdc_do_config(struct usb_configuration *c)
 {
 {
-	struct f_serial_opts *opts;
 	int	status;
 	int	status;
 
 
 	if (gadget_is_otg(c->cdev->gadget)) {
 	if (gadget_is_otg(c->cdev->gadget)) {
@@ -122,7 +120,7 @@ static int __init cdc_do_config(struct usb_configuration *c)
 		c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
 		c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
 	}
 	}
 
 
-	status = ecm_bind_config(c, hostaddr);
+	status = ecm_bind_config(c, hostaddr, the_dev);
 	if (status < 0)
 	if (status < 0)
 		return status;
 		return status;
 
 
@@ -130,9 +128,6 @@ static int __init cdc_do_config(struct usb_configuration *c)
 	if (IS_ERR(fi_serial))
 	if (IS_ERR(fi_serial))
 		return PTR_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);
 	f_acm = usb_get_function(fi_serial);
 	if (IS_ERR(f_acm))
 	if (IS_ERR(f_acm))
 		goto err_func_acm;
 		goto err_func_acm;
@@ -169,14 +164,9 @@ static int __init cdc_bind(struct usb_composite_dev *cdev)
 	}
 	}
 
 
 	/* set up network link layer */
 	/* set up network link layer */
-	status = gether_setup(cdev->gadget, hostaddr);
-	if (status < 0)
-		return status;
-
-	/* set up serial link layer */
-	status = gserial_alloc_line(&tty_line);
-	if (status < 0)
-		goto fail0;
+	the_dev = gether_setup(cdev->gadget, hostaddr);
+	if (IS_ERR(the_dev))
+		return PTR_ERR(the_dev);
 
 
 	/* Allocate string descriptor numbers ... note that string
 	/* Allocate string descriptor numbers ... note that string
 	 * contents can be overridden by the composite_dev glue.
 	 * contents can be overridden by the composite_dev glue.
@@ -200,9 +190,7 @@ static int __init cdc_bind(struct usb_composite_dev *cdev)
 	return 0;
 	return 0;
 
 
 fail1:
 fail1:
-	gserial_free_line(tty_line);
-fail0:
-	gether_cleanup();
+	gether_cleanup(the_dev);
 	return status;
 	return status;
 }
 }
 
 
@@ -210,8 +198,7 @@ static int __exit cdc_unbind(struct usb_composite_dev *cdev)
 {
 {
 	usb_put_function(f_acm);
 	usb_put_function(f_acm);
 	usb_put_function_instance(fi_serial);
 	usb_put_function_instance(fi_serial);
-	gserial_free_line(tty_line);
-	gether_cleanup();
+	gether_cleanup(the_dev);
 	return 0;
 	return 0;
 }
 }
 
 

+ 1 - 0
drivers/usb/gadget/composite.c

@@ -1637,6 +1637,7 @@ void composite_dev_cleanup(struct usb_composite_dev *cdev)
 		kfree(cdev->req->buf);
 		kfree(cdev->req->buf);
 		usb_ep_free_request(cdev->gadget->ep0, cdev->req);
 		usb_ep_free_request(cdev->gadget->ep0, cdev->req);
 	}
 	}
+	cdev->next_string_id = 0;
 	device_remove_file(&cdev->gadget->dev, &dev_attr_suspended);
 	device_remove_file(&cdev->gadget->dev, &dev_attr_suspended);
 }
 }
 
 

+ 1003 - 0
drivers/usb/gadget/configfs.c

@@ -0,0 +1,1003 @@
+#include <linux/configfs.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/device.h>
+#include <linux/usb/composite.h>
+#include <linux/usb/gadget_configfs.h>
+
+int check_user_usb_string(const char *name,
+		struct usb_gadget_strings *stringtab_dev)
+{
+	unsigned primary_lang;
+	unsigned sub_lang;
+	u16 num;
+	int ret;
+
+	ret = kstrtou16(name, 0, &num);
+	if (ret)
+		return ret;
+
+	primary_lang = num & 0x3ff;
+	sub_lang = num >> 10;
+
+	/* simple sanity check for valid langid */
+	switch (primary_lang) {
+	case 0:
+	case 0x62 ... 0xfe:
+	case 0x100 ... 0x3ff:
+		return -EINVAL;
+	}
+	if (!sub_lang)
+		return -EINVAL;
+
+	stringtab_dev->language = num;
+	return 0;
+}
+
+#define MAX_NAME_LEN	40
+#define MAX_USB_STRING_LANGS 2
+
+struct gadget_info {
+	struct config_group group;
+	struct config_group functions_group;
+	struct config_group configs_group;
+	struct config_group strings_group;
+	struct config_group *default_groups[4];
+
+	struct mutex lock;
+	struct usb_gadget_strings *gstrings[MAX_USB_STRING_LANGS + 1];
+	struct list_head string_list;
+	struct list_head available_func;
+
+	const char *udc_name;
+#ifdef CONFIG_USB_OTG
+	struct usb_otg_descriptor otg;
+#endif
+	struct usb_composite_driver composite;
+	struct usb_composite_dev cdev;
+};
+
+struct config_usb_cfg {
+	struct config_group group;
+	struct config_group strings_group;
+	struct config_group *default_groups[2];
+	struct list_head string_list;
+	struct usb_configuration c;
+	struct list_head func_list;
+	struct usb_gadget_strings *gstrings[MAX_USB_STRING_LANGS + 1];
+};
+
+struct gadget_strings {
+	struct usb_gadget_strings stringtab_dev;
+	struct usb_string strings[USB_GADGET_FIRST_AVAIL_IDX];
+	char *manufacturer;
+	char *product;
+	char *serialnumber;
+
+	struct config_group group;
+	struct list_head list;
+};
+
+struct gadget_config_name {
+	struct usb_gadget_strings stringtab_dev;
+	struct usb_string strings;
+	char *configuration;
+
+	struct config_group group;
+	struct list_head list;
+};
+
+static int usb_string_copy(const char *s, char **s_copy)
+{
+	int ret;
+	char *str;
+	char *copy = *s_copy;
+	ret = strlen(s);
+	if (ret > 126)
+		return -EOVERFLOW;
+
+	str = kstrdup(s, GFP_KERNEL);
+	if (!str)
+		return -ENOMEM;
+	if (str[ret - 1] == '\n')
+		str[ret - 1] = '\0';
+	kfree(copy);
+	*s_copy = str;
+	return 0;
+}
+
+CONFIGFS_ATTR_STRUCT(gadget_info);
+CONFIGFS_ATTR_STRUCT(config_usb_cfg);
+
+#define GI_DEVICE_DESC_ITEM_ATTR(name)	\
+	static struct gadget_info_attribute gadget_cdev_desc_##name = \
+		__CONFIGFS_ATTR(name,  S_IRUGO | S_IWUSR,		\
+				gadget_dev_desc_##name##_show,		\
+				gadget_dev_desc_##name##_store)
+
+#define GI_DEVICE_DESC_SIMPLE_R_u8(__name)	\
+	static ssize_t gadget_dev_desc_##__name##_show(struct gadget_info *gi, \
+			char *page)	\
+{	\
+	return sprintf(page, "0x%02x\n", gi->cdev.desc.__name);	\
+}
+
+#define GI_DEVICE_DESC_SIMPLE_R_u16(__name)	\
+	static ssize_t gadget_dev_desc_##__name##_show(struct gadget_info *gi, \
+			char *page)	\
+{	\
+	return sprintf(page, "0x%04x\n", le16_to_cpup(&gi->cdev.desc.__name)); \
+}
+
+
+#define GI_DEVICE_DESC_SIMPLE_W_u8(_name)		\
+	static ssize_t gadget_dev_desc_##_name##_store(struct gadget_info *gi, \
+		const char *page, size_t len)		\
+{							\
+	u8 val;						\
+	int ret;					\
+	ret = kstrtou8(page, 0, &val);			\
+	if (ret)					\
+		return ret;				\
+	gi->cdev.desc._name = val;			\
+	return len;					\
+}
+
+#define GI_DEVICE_DESC_SIMPLE_W_u16(_name)	\
+	static ssize_t gadget_dev_desc_##_name##_store(struct gadget_info *gi, \
+		const char *page, size_t len)		\
+{							\
+	u16 val;					\
+	int ret;					\
+	ret = kstrtou16(page, 0, &val);			\
+	if (ret)					\
+		return ret;				\
+	gi->cdev.desc._name = cpu_to_le16p(&val);	\
+	return len;					\
+}
+
+#define GI_DEVICE_DESC_SIMPLE_RW(_name, _type)	\
+	GI_DEVICE_DESC_SIMPLE_R_##_type(_name)	\
+	GI_DEVICE_DESC_SIMPLE_W_##_type(_name)
+
+GI_DEVICE_DESC_SIMPLE_R_u16(bcdUSB);
+GI_DEVICE_DESC_SIMPLE_RW(bDeviceClass, u8);
+GI_DEVICE_DESC_SIMPLE_RW(bDeviceSubClass, u8);
+GI_DEVICE_DESC_SIMPLE_RW(bDeviceProtocol, u8);
+GI_DEVICE_DESC_SIMPLE_RW(bMaxPacketSize0, u8);
+GI_DEVICE_DESC_SIMPLE_RW(idVendor, u16);
+GI_DEVICE_DESC_SIMPLE_RW(idProduct, u16);
+GI_DEVICE_DESC_SIMPLE_R_u16(bcdDevice);
+
+static ssize_t is_valid_bcd(u16 bcd_val)
+{
+	if ((bcd_val & 0xf) > 9)
+		return -EINVAL;
+	if (((bcd_val >> 4) & 0xf) > 9)
+		return -EINVAL;
+	if (((bcd_val >> 8) & 0xf) > 9)
+		return -EINVAL;
+	if (((bcd_val >> 12) & 0xf) > 9)
+		return -EINVAL;
+	return 0;
+}
+
+static ssize_t gadget_dev_desc_bcdDevice_store(struct gadget_info *gi,
+		const char *page, size_t len)
+{
+	u16 bcdDevice;
+	int ret;
+
+	ret = kstrtou16(page, 0, &bcdDevice);
+	if (ret)
+		return ret;
+	ret = is_valid_bcd(bcdDevice);
+	if (ret)
+		return ret;
+
+	gi->cdev.desc.bcdDevice = cpu_to_le16(bcdDevice);
+	return len;
+}
+
+static ssize_t gadget_dev_desc_bcdUSB_store(struct gadget_info *gi,
+		const char *page, size_t len)
+{
+	u16 bcdUSB;
+	int ret;
+
+	ret = kstrtou16(page, 0, &bcdUSB);
+	if (ret)
+		return ret;
+	ret = is_valid_bcd(bcdUSB);
+	if (ret)
+		return ret;
+
+	gi->cdev.desc.bcdUSB = cpu_to_le16(bcdUSB);
+	return len;
+}
+
+static ssize_t gadget_dev_desc_UDC_show(struct gadget_info *gi, char *page)
+{
+	return sprintf(page, "%s\n", gi->udc_name ?: "");
+}
+
+static int unregister_gadget(struct gadget_info *gi)
+{
+	int ret;
+
+	if (!gi->udc_name)
+		return -ENODEV;
+
+	ret = usb_gadget_unregister_driver(&gi->composite.gadget_driver);
+	if (ret)
+		return ret;
+	kfree(gi->udc_name);
+	gi->udc_name = NULL;
+	return 0;
+}
+
+static ssize_t gadget_dev_desc_UDC_store(struct gadget_info *gi,
+		const char *page, size_t len)
+{
+	char *name;
+	int ret;
+
+	name = kstrdup(page, GFP_KERNEL);
+	if (!name)
+		return -ENOMEM;
+	if (name[len - 1] == '\n')
+		name[len - 1] = '\0';
+
+	mutex_lock(&gi->lock);
+
+	if (!strlen(name)) {
+		ret = unregister_gadget(gi);
+		if (ret)
+			goto err;
+	} else {
+		if (gi->udc_name) {
+			ret = -EBUSY;
+			goto err;
+		}
+		ret = udc_attach_driver(name, &gi->composite.gadget_driver);
+		if (ret)
+			goto err;
+		gi->udc_name = name;
+	}
+	mutex_unlock(&gi->lock);
+	return len;
+err:
+	kfree(name);
+	mutex_unlock(&gi->lock);
+	return ret;
+}
+
+GI_DEVICE_DESC_ITEM_ATTR(bDeviceClass);
+GI_DEVICE_DESC_ITEM_ATTR(bDeviceSubClass);
+GI_DEVICE_DESC_ITEM_ATTR(bDeviceProtocol);
+GI_DEVICE_DESC_ITEM_ATTR(bMaxPacketSize0);
+GI_DEVICE_DESC_ITEM_ATTR(idVendor);
+GI_DEVICE_DESC_ITEM_ATTR(idProduct);
+GI_DEVICE_DESC_ITEM_ATTR(bcdDevice);
+GI_DEVICE_DESC_ITEM_ATTR(bcdUSB);
+GI_DEVICE_DESC_ITEM_ATTR(UDC);
+
+static struct configfs_attribute *gadget_root_attrs[] = {
+	&gadget_cdev_desc_bDeviceClass.attr,
+	&gadget_cdev_desc_bDeviceSubClass.attr,
+	&gadget_cdev_desc_bDeviceProtocol.attr,
+	&gadget_cdev_desc_bMaxPacketSize0.attr,
+	&gadget_cdev_desc_idVendor.attr,
+	&gadget_cdev_desc_idProduct.attr,
+	&gadget_cdev_desc_bcdDevice.attr,
+	&gadget_cdev_desc_bcdUSB.attr,
+	&gadget_cdev_desc_UDC.attr,
+	NULL,
+};
+
+static inline struct gadget_info *to_gadget_info(struct config_item *item)
+{
+	 return container_of(to_config_group(item), struct gadget_info, group);
+}
+
+static inline struct gadget_strings *to_gadget_strings(struct config_item *item)
+{
+	 return container_of(to_config_group(item), struct gadget_strings,
+			 group);
+}
+
+static inline struct gadget_config_name *to_gadget_config_name(
+		struct config_item *item)
+{
+	 return container_of(to_config_group(item), struct gadget_config_name,
+			 group);
+}
+
+static inline struct config_usb_cfg *to_config_usb_cfg(struct config_item *item)
+{
+	return container_of(to_config_group(item), struct config_usb_cfg,
+			group);
+}
+
+static inline struct usb_function_instance *to_usb_function_instance(
+		struct config_item *item)
+{
+	 return container_of(to_config_group(item),
+			 struct usb_function_instance, group);
+}
+
+static void gadget_info_attr_release(struct config_item *item)
+{
+	struct gadget_info *gi = to_gadget_info(item);
+
+	WARN_ON(!list_empty(&gi->cdev.configs));
+	WARN_ON(!list_empty(&gi->string_list));
+	WARN_ON(!list_empty(&gi->available_func));
+	kfree(gi->composite.gadget_driver.function);
+	kfree(gi);
+}
+
+CONFIGFS_ATTR_OPS(gadget_info);
+
+static struct configfs_item_operations gadget_root_item_ops = {
+	.release                = gadget_info_attr_release,
+	.show_attribute         = gadget_info_attr_show,
+	.store_attribute        = gadget_info_attr_store,
+};
+
+static void gadget_config_attr_release(struct config_item *item)
+{
+	struct config_usb_cfg *cfg = to_config_usb_cfg(item);
+
+	WARN_ON(!list_empty(&cfg->c.functions));
+	list_del(&cfg->c.list);
+	kfree(cfg->c.label);
+	kfree(cfg);
+}
+
+static int config_usb_cfg_link(
+	struct config_item *usb_cfg_ci,
+	struct config_item *usb_func_ci)
+{
+	struct config_usb_cfg *cfg = to_config_usb_cfg(usb_cfg_ci);
+	struct usb_composite_dev *cdev = cfg->c.cdev;
+	struct gadget_info *gi = container_of(cdev, struct gadget_info, cdev);
+
+	struct config_group *group = to_config_group(usb_func_ci);
+	struct usb_function_instance *fi = container_of(group,
+			struct usb_function_instance, group);
+	struct usb_function_instance *a_fi;
+	struct usb_function *f;
+	int ret;
+
+	mutex_lock(&gi->lock);
+	/*
+	 * Make sure this function is from within our _this_ gadget and not
+	 * from another gadget or a random directory.
+	 * Also a function instance can only be linked once.
+	 */
+	list_for_each_entry(a_fi, &gi->available_func, cfs_list) {
+		if (a_fi == fi)
+			break;
+	}
+	if (a_fi != fi) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	list_for_each_entry(f, &cfg->func_list, list) {
+		if (f->fi == fi) {
+			ret = -EEXIST;
+			goto out;
+		}
+	}
+
+	f = usb_get_function(fi);
+	if (IS_ERR(f)) {
+		ret = PTR_ERR(f);
+		goto out;
+	}
+
+	/* stash the function until we bind it to the gadget */
+	list_add_tail(&f->list, &cfg->func_list);
+	ret = 0;
+out:
+	mutex_unlock(&gi->lock);
+	return ret;
+}
+
+static int config_usb_cfg_unlink(
+	struct config_item *usb_cfg_ci,
+	struct config_item *usb_func_ci)
+{
+	struct config_usb_cfg *cfg = to_config_usb_cfg(usb_cfg_ci);
+	struct usb_composite_dev *cdev = cfg->c.cdev;
+	struct gadget_info *gi = container_of(cdev, struct gadget_info, cdev);
+
+	struct config_group *group = to_config_group(usb_func_ci);
+	struct usb_function_instance *fi = container_of(group,
+			struct usb_function_instance, group);
+	struct usb_function *f;
+
+	/*
+	 * ideally I would like to forbid to unlink functions while a gadget is
+	 * bound to an UDC. Since this isn't possible at the moment, we simply
+	 * force an unbind, the function is available here and then we can
+	 * remove the function.
+	 */
+	mutex_lock(&gi->lock);
+	if (gi->udc_name)
+		unregister_gadget(gi);
+	WARN_ON(gi->udc_name);
+
+	list_for_each_entry(f, &cfg->func_list, list) {
+		if (f->fi == fi) {
+			list_del(&f->list);
+			usb_put_function(f);
+			mutex_unlock(&gi->lock);
+			return 0;
+		}
+	}
+	mutex_unlock(&gi->lock);
+	__WARN_printf("Unable to locate function to unbind\n");
+	return 0;
+}
+
+CONFIGFS_ATTR_OPS(config_usb_cfg);
+
+static struct configfs_item_operations gadget_config_item_ops = {
+	.release                = gadget_config_attr_release,
+	.show_attribute         = config_usb_cfg_attr_show,
+	.store_attribute        = config_usb_cfg_attr_store,
+	.allow_link             = config_usb_cfg_link,
+	.drop_link              = config_usb_cfg_unlink,
+};
+
+
+static ssize_t gadget_config_desc_MaxPower_show(struct config_usb_cfg *cfg,
+		char *page)
+{
+	return sprintf(page, "%u\n", cfg->c.MaxPower);
+}
+
+static ssize_t gadget_config_desc_MaxPower_store(struct config_usb_cfg *cfg,
+		const char *page, size_t len)
+{
+	u16 val;
+	int ret;
+	ret = kstrtou16(page, 0, &val);
+	if (ret)
+		return ret;
+	if (DIV_ROUND_UP(val, 8) > 0xff)
+		return -ERANGE;
+	cfg->c.MaxPower = val;
+	return len;
+}
+
+static ssize_t gadget_config_desc_bmAttributes_show(struct config_usb_cfg *cfg,
+		char *page)
+{
+	return sprintf(page, "0x%02x\n", cfg->c.bmAttributes);
+}
+
+static ssize_t gadget_config_desc_bmAttributes_store(struct config_usb_cfg *cfg,
+		const char *page, size_t len)
+{
+	u8 val;
+	int ret;
+	ret = kstrtou8(page, 0, &val);
+	if (ret)
+		return ret;
+	if (!(val & USB_CONFIG_ATT_ONE))
+		return -EINVAL;
+	if (val & ~(USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER |
+				USB_CONFIG_ATT_WAKEUP))
+		return -EINVAL;
+	cfg->c.bmAttributes = val;
+	return len;
+}
+
+#define CFG_CONFIG_DESC_ITEM_ATTR(name)	\
+	static struct config_usb_cfg_attribute gadget_usb_cfg_##name = \
+		__CONFIGFS_ATTR(name,  S_IRUGO | S_IWUSR,		\
+				gadget_config_desc_##name##_show,	\
+				gadget_config_desc_##name##_store)
+
+CFG_CONFIG_DESC_ITEM_ATTR(MaxPower);
+CFG_CONFIG_DESC_ITEM_ATTR(bmAttributes);
+
+static struct configfs_attribute *gadget_config_attrs[] = {
+	&gadget_usb_cfg_MaxPower.attr,
+	&gadget_usb_cfg_bmAttributes.attr,
+	NULL,
+};
+
+static struct config_item_type gadget_config_type = {
+	.ct_item_ops	= &gadget_config_item_ops,
+	.ct_attrs	= gadget_config_attrs,
+	.ct_owner	= THIS_MODULE,
+};
+
+static struct config_item_type gadget_root_type = {
+	.ct_item_ops	= &gadget_root_item_ops,
+	.ct_attrs	= gadget_root_attrs,
+	.ct_owner	= THIS_MODULE,
+};
+
+static void composite_init_dev(struct usb_composite_dev *cdev)
+{
+	spin_lock_init(&cdev->lock);
+	INIT_LIST_HEAD(&cdev->configs);
+	INIT_LIST_HEAD(&cdev->gstrings);
+}
+
+static struct config_group *function_make(
+		struct config_group *group,
+		const char *name)
+{
+	struct gadget_info *gi;
+	struct usb_function_instance *fi;
+	char buf[MAX_NAME_LEN];
+	char *func_name;
+	char *instance_name;
+	int ret;
+
+	ret = snprintf(buf, MAX_NAME_LEN, "%s", name);
+	if (ret >= MAX_NAME_LEN)
+		return ERR_PTR(-ENAMETOOLONG);
+
+	func_name = buf;
+	instance_name = strchr(func_name, '.');
+	if (!instance_name) {
+		pr_err("Unable to locate . in FUNC.INSTANCE\n");
+		return ERR_PTR(-EINVAL);
+	}
+	*instance_name = '\0';
+	instance_name++;
+
+	fi = usb_get_function_instance(func_name);
+	if (IS_ERR(fi))
+		return ERR_PTR(PTR_ERR(fi));
+
+	ret = config_item_set_name(&fi->group.cg_item, name);
+	if (ret) {
+		usb_put_function_instance(fi);
+		return ERR_PTR(ret);
+	}
+
+	gi = container_of(group, struct gadget_info, functions_group);
+
+	mutex_lock(&gi->lock);
+	list_add_tail(&fi->cfs_list, &gi->available_func);
+	mutex_unlock(&gi->lock);
+	return &fi->group;
+}
+
+static void function_drop(
+		struct config_group *group,
+		struct config_item *item)
+{
+	struct usb_function_instance *fi = to_usb_function_instance(item);
+	struct gadget_info *gi;
+
+	gi = container_of(group, struct gadget_info, functions_group);
+
+	mutex_lock(&gi->lock);
+	list_del(&fi->cfs_list);
+	mutex_unlock(&gi->lock);
+	config_item_put(item);
+}
+
+static struct configfs_group_operations functions_ops = {
+	.make_group     = &function_make,
+	.drop_item      = &function_drop,
+};
+
+static struct config_item_type functions_type = {
+	.ct_group_ops   = &functions_ops,
+	.ct_owner       = THIS_MODULE,
+};
+
+CONFIGFS_ATTR_STRUCT(gadget_config_name);
+GS_STRINGS_RW(gadget_config_name, configuration);
+
+static struct configfs_attribute *gadget_config_name_langid_attrs[] = {
+	&gadget_config_name_configuration.attr,
+	NULL,
+};
+
+static void gadget_config_name_attr_release(struct config_item *item)
+{
+	struct gadget_config_name *cn = to_gadget_config_name(item);
+
+	kfree(cn->configuration);
+
+	list_del(&cn->list);
+	kfree(cn);
+}
+
+USB_CONFIG_STRING_RW_OPS(gadget_config_name);
+USB_CONFIG_STRINGS_LANG(gadget_config_name, config_usb_cfg);
+
+static struct config_group *config_desc_make(
+		struct config_group *group,
+		const char *name)
+{
+	struct gadget_info *gi;
+	struct config_usb_cfg *cfg;
+	char buf[MAX_NAME_LEN];
+	char *num_str;
+	u8 num;
+	int ret;
+
+	gi = container_of(group, struct gadget_info, configs_group);
+	ret = snprintf(buf, MAX_NAME_LEN, "%s", name);
+	if (ret >= MAX_NAME_LEN)
+		return ERR_PTR(-ENAMETOOLONG);
+
+	num_str = strchr(buf, '.');
+	if (!num_str) {
+		pr_err("Unable to locate . in name.bConfigurationValue\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	*num_str = '\0';
+	num_str++;
+
+	if (!strlen(buf))
+		return ERR_PTR(-EINVAL);
+
+	ret = kstrtou8(num_str, 0, &num);
+	if (ret)
+		return ERR_PTR(ret);
+
+	cfg = kzalloc(sizeof(*cfg), GFP_KERNEL);
+	if (!cfg)
+		return ERR_PTR(-ENOMEM);
+	cfg->c.label = kstrdup(buf, GFP_KERNEL);
+	if (!cfg->c.label) {
+		ret = -ENOMEM;
+		goto err;
+	}
+	cfg->c.bConfigurationValue = num;
+	cfg->c.MaxPower = CONFIG_USB_GADGET_VBUS_DRAW;
+	cfg->c.bmAttributes = USB_CONFIG_ATT_ONE;
+	INIT_LIST_HEAD(&cfg->string_list);
+	INIT_LIST_HEAD(&cfg->func_list);
+
+	cfg->group.default_groups = cfg->default_groups;
+	cfg->default_groups[0] = &cfg->strings_group;
+
+	config_group_init_type_name(&cfg->group, name,
+				&gadget_config_type);
+	config_group_init_type_name(&cfg->strings_group, "strings",
+			&gadget_config_name_strings_type);
+
+	ret = usb_add_config_only(&gi->cdev, &cfg->c);
+	if (ret)
+		goto err;
+
+	return &cfg->group;
+err:
+	kfree(cfg->c.label);
+	kfree(cfg);
+	return ERR_PTR(ret);
+}
+
+static void config_desc_drop(
+		struct config_group *group,
+		struct config_item *item)
+{
+	config_item_put(item);
+}
+
+static struct configfs_group_operations config_desc_ops = {
+	.make_group     = &config_desc_make,
+	.drop_item      = &config_desc_drop,
+};
+
+static struct config_item_type config_desc_type = {
+	.ct_group_ops   = &config_desc_ops,
+	.ct_owner       = THIS_MODULE,
+};
+
+CONFIGFS_ATTR_STRUCT(gadget_strings);
+GS_STRINGS_RW(gadget_strings, manufacturer);
+GS_STRINGS_RW(gadget_strings, product);
+GS_STRINGS_RW(gadget_strings, serialnumber);
+
+static struct configfs_attribute *gadget_strings_langid_attrs[] = {
+	&gadget_strings_manufacturer.attr,
+	&gadget_strings_product.attr,
+	&gadget_strings_serialnumber.attr,
+	NULL,
+};
+
+static void gadget_strings_attr_release(struct config_item *item)
+{
+	struct gadget_strings *gs = to_gadget_strings(item);
+
+	kfree(gs->manufacturer);
+	kfree(gs->product);
+	kfree(gs->serialnumber);
+
+	list_del(&gs->list);
+	kfree(gs);
+}
+
+USB_CONFIG_STRING_RW_OPS(gadget_strings);
+USB_CONFIG_STRINGS_LANG(gadget_strings, gadget_info);
+
+static int configfs_do_nothing(struct usb_composite_dev *cdev)
+{
+	__WARN();
+	return -EINVAL;
+}
+
+int composite_dev_prepare(struct usb_composite_driver *composite,
+		struct usb_composite_dev *dev);
+
+static void purge_configs_funcs(struct gadget_info *gi)
+{
+	struct usb_configuration	*c;
+
+	list_for_each_entry(c, &gi->cdev.configs, list) {
+		struct usb_function *f, *tmp;
+		struct config_usb_cfg *cfg;
+
+		cfg = container_of(c, struct config_usb_cfg, c);
+
+		list_for_each_entry_safe(f, tmp, &c->functions, list) {
+
+			list_move_tail(&f->list, &cfg->func_list);
+			if (f->unbind) {
+				dev_err(&gi->cdev.gadget->dev, "unbind function"
+						" '%s'/%p\n", f->name, f);
+				f->unbind(c, f);
+			}
+		}
+		c->next_interface_id = 0;
+		c->superspeed = 0;
+		c->highspeed = 0;
+		c->fullspeed = 0;
+	}
+}
+
+static int configfs_composite_bind(struct usb_gadget *gadget,
+		struct usb_gadget_driver *gdriver)
+{
+	struct usb_composite_driver     *composite = to_cdriver(gdriver);
+	struct gadget_info		*gi = container_of(composite,
+						struct gadget_info, composite);
+	struct usb_composite_dev	*cdev = &gi->cdev;
+	struct usb_configuration	*c;
+	struct usb_string		*s;
+	unsigned			i;
+	int				ret;
+
+	/* the gi->lock is hold by the caller */
+	cdev->gadget = gadget;
+	set_gadget_data(gadget, cdev);
+	ret = composite_dev_prepare(composite, cdev);
+	if (ret)
+		return ret;
+	/* and now the gadget bind */
+	ret = -EINVAL;
+
+	if (list_empty(&gi->cdev.configs)) {
+		pr_err("Need atleast one configuration in %s.\n",
+				gi->composite.name);
+		goto err_comp_cleanup;
+	}
+
+
+	list_for_each_entry(c, &gi->cdev.configs, list) {
+		struct config_usb_cfg *cfg;
+
+		cfg = container_of(c, struct config_usb_cfg, c);
+		if (list_empty(&cfg->func_list)) {
+			pr_err("Config %s/%d of %s needs atleast one function.\n",
+			      c->label, c->bConfigurationValue,
+			      gi->composite.name);
+			goto err_comp_cleanup;
+		}
+	}
+
+	/* init all strings */
+	if (!list_empty(&gi->string_list)) {
+		struct gadget_strings *gs;
+
+		i = 0;
+		list_for_each_entry(gs, &gi->string_list, list) {
+
+			gi->gstrings[i] = &gs->stringtab_dev;
+			gs->stringtab_dev.strings = gs->strings;
+			gs->strings[USB_GADGET_MANUFACTURER_IDX].s =
+				gs->manufacturer;
+			gs->strings[USB_GADGET_PRODUCT_IDX].s = gs->product;
+			gs->strings[USB_GADGET_SERIAL_IDX].s = gs->serialnumber;
+			i++;
+		}
+		gi->gstrings[i] = NULL;
+		s = usb_gstrings_attach(&gi->cdev, gi->gstrings,
+				USB_GADGET_FIRST_AVAIL_IDX);
+		if (IS_ERR(s))
+			goto err_comp_cleanup;
+
+		gi->cdev.desc.iManufacturer = s[USB_GADGET_MANUFACTURER_IDX].id;
+		gi->cdev.desc.iProduct = s[USB_GADGET_PRODUCT_IDX].id;
+		gi->cdev.desc.iSerialNumber = s[USB_GADGET_SERIAL_IDX].id;
+	}
+
+	/* Go through all configs, attach all functions */
+	list_for_each_entry(c, &gi->cdev.configs, list) {
+		struct config_usb_cfg *cfg;
+		struct usb_function *f;
+		struct usb_function *tmp;
+		struct gadget_config_name *cn;
+
+		cfg = container_of(c, struct config_usb_cfg, c);
+		if (!list_empty(&cfg->string_list)) {
+			i = 0;
+			list_for_each_entry(cn, &cfg->string_list, list) {
+				cfg->gstrings[i] = &cn->stringtab_dev;
+				cn->stringtab_dev.strings = &cn->strings;
+				cn->strings.s = cn->configuration;
+				i++;
+			}
+			cfg->gstrings[i] = NULL;
+			s = usb_gstrings_attach(&gi->cdev, cfg->gstrings, 1);
+			if (IS_ERR(s))
+				goto err_comp_cleanup;
+			c->iConfiguration = s[0].id;
+		}
+
+		list_for_each_entry_safe(f, tmp, &cfg->func_list, list) {
+			list_del(&f->list);
+			ret = usb_add_function(c, f);
+			if (ret)
+				goto err_purge_funcs;
+		}
+		usb_ep_autoconfig_reset(cdev->gadget);
+	}
+	usb_ep_autoconfig_reset(cdev->gadget);
+	return 0;
+
+err_purge_funcs:
+	purge_configs_funcs(gi);
+err_comp_cleanup:
+	composite_dev_cleanup(cdev);
+	return ret;
+}
+
+static void configfs_composite_unbind(struct usb_gadget *gadget)
+{
+	struct usb_composite_dev	*cdev;
+	struct gadget_info		*gi;
+
+	/* the gi->lock is hold by the caller */
+
+	cdev = get_gadget_data(gadget);
+	gi = container_of(cdev, struct gadget_info, cdev);
+
+	purge_configs_funcs(gi);
+	composite_dev_cleanup(cdev);
+	usb_ep_autoconfig_reset(cdev->gadget);
+	cdev->gadget = NULL;
+	set_gadget_data(gadget, NULL);
+}
+
+static const struct usb_gadget_driver configfs_driver_template = {
+	.bind           = configfs_composite_bind,
+	.unbind         = configfs_composite_unbind,
+
+	.setup          = composite_setup,
+	.disconnect     = composite_disconnect,
+
+	.max_speed	= USB_SPEED_SUPER,
+	.driver = {
+		.owner          = THIS_MODULE,
+		.name		= "configfs-gadget",
+	},
+};
+
+static struct config_group *gadgets_make(
+		struct config_group *group,
+		const char *name)
+{
+	struct gadget_info *gi;
+
+	gi = kzalloc(sizeof(*gi), GFP_KERNEL);
+	if (!gi)
+		return ERR_PTR(-ENOMEM);
+
+	gi->group.default_groups = gi->default_groups;
+	gi->group.default_groups[0] = &gi->functions_group;
+	gi->group.default_groups[1] = &gi->configs_group;
+	gi->group.default_groups[2] = &gi->strings_group;
+
+	config_group_init_type_name(&gi->functions_group, "functions",
+			&functions_type);
+	config_group_init_type_name(&gi->configs_group, "configs",
+			&config_desc_type);
+	config_group_init_type_name(&gi->strings_group, "strings",
+			&gadget_strings_strings_type);
+
+	gi->composite.bind = configfs_do_nothing;
+	gi->composite.unbind = configfs_do_nothing;
+	gi->composite.suspend = NULL;
+	gi->composite.resume = NULL;
+	gi->composite.max_speed = USB_SPEED_SUPER;
+
+	mutex_init(&gi->lock);
+	INIT_LIST_HEAD(&gi->string_list);
+	INIT_LIST_HEAD(&gi->available_func);
+
+	composite_init_dev(&gi->cdev);
+	gi->cdev.desc.bLength = USB_DT_DEVICE_SIZE;
+	gi->cdev.desc.bDescriptorType = USB_DT_DEVICE;
+	gi->cdev.desc.bcdDevice = cpu_to_le16(get_default_bcdDevice());
+
+	gi->composite.gadget_driver = configfs_driver_template;
+
+	gi->composite.gadget_driver.function = kstrdup(name, GFP_KERNEL);
+	gi->composite.name = gi->composite.gadget_driver.function;
+
+	if (!gi->composite.gadget_driver.function)
+		goto err;
+
+#ifdef CONFIG_USB_OTG
+	gi->otg.bLength = sizeof(struct usb_otg_descriptor);
+	gi->otg.bDescriptorType = USB_DT_OTG;
+	gi->otg.bmAttributes = USB_OTG_SRP | USB_OTG_HNP;
+#endif
+
+	config_group_init_type_name(&gi->group, name,
+				&gadget_root_type);
+	return &gi->group;
+err:
+	kfree(gi);
+	return ERR_PTR(-ENOMEM);
+}
+
+static void gadgets_drop(struct config_group *group, struct config_item *item)
+{
+	config_item_put(item);
+}
+
+static struct configfs_group_operations gadgets_ops = {
+	.make_group     = &gadgets_make,
+	.drop_item      = &gadgets_drop,
+};
+
+static struct config_item_type gadgets_type = {
+	.ct_group_ops   = &gadgets_ops,
+	.ct_owner       = THIS_MODULE,
+};
+
+static struct configfs_subsystem gadget_subsys = {
+	.su_group = {
+		.cg_item = {
+			.ci_namebuf = "usb_gadget",
+			.ci_type = &gadgets_type,
+		},
+	},
+	.su_mutex = __MUTEX_INITIALIZER(gadget_subsys.su_mutex),
+};
+
+static int __init gadget_cfs_init(void)
+{
+	int ret;
+
+	config_group_init(&gadget_subsys.su_group);
+
+	ret = configfs_register_subsystem(&gadget_subsys);
+	return ret;
+}
+module_init(gadget_cfs_init);
+
+static void __exit gadget_cfs_exit(void)
+{
+	configfs_unregister_subsystem(&gadget_subsys);
+}
+module_exit(gadget_cfs_exit);

+ 1 - 18
drivers/usb/gadget/dummy_hcd.c

@@ -912,7 +912,6 @@ static int dummy_udc_start(struct usb_gadget *g,
 	dum->devstatus = 0;
 	dum->devstatus = 0;
 
 
 	dum->driver = driver;
 	dum->driver = driver;
-	dum->gadget.dev.driver = &driver->driver;
 	dev_dbg(udc_dev(dum), "binding gadget driver '%s'\n",
 	dev_dbg(udc_dev(dum), "binding gadget driver '%s'\n",
 			driver->driver.name);
 			driver->driver.name);
 	return 0;
 	return 0;
@@ -927,7 +926,6 @@ static int dummy_udc_stop(struct usb_gadget *g,
 	dev_dbg(udc_dev(dum), "unregister gadget driver '%s'\n",
 	dev_dbg(udc_dev(dum), "unregister gadget driver '%s'\n",
 			driver->driver.name);
 			driver->driver.name);
 
 
-	dum->gadget.dev.driver = NULL;
 	dum->driver = NULL;
 	dum->driver = NULL;
 
 
 	return 0;
 	return 0;
@@ -937,11 +935,6 @@ static int dummy_udc_stop(struct usb_gadget *g,
 
 
 /* The gadget structure is stored inside the hcd structure and will be
 /* The gadget structure is stored inside the hcd structure and will be
  * released along with it. */
  * released along with it. */
-static void dummy_gadget_release(struct device *dev)
-{
-	return;
-}
-
 static void init_dummy_udc_hw(struct dummy *dum)
 static void init_dummy_udc_hw(struct dummy *dum)
 {
 {
 	int i;
 	int i;
@@ -984,15 +977,7 @@ static int dummy_udc_probe(struct platform_device *pdev)
 	dum->gadget.ops = &dummy_ops;
 	dum->gadget.ops = &dummy_ops;
 	dum->gadget.max_speed = USB_SPEED_SUPER;
 	dum->gadget.max_speed = USB_SPEED_SUPER;
 
 
-	dev_set_name(&dum->gadget.dev, "gadget");
 	dum->gadget.dev.parent = &pdev->dev;
 	dum->gadget.dev.parent = &pdev->dev;
-	dum->gadget.dev.release = dummy_gadget_release;
-	rc = device_register(&dum->gadget.dev);
-	if (rc < 0) {
-		put_device(&dum->gadget.dev);
-		return rc;
-	}
-
 	init_dummy_udc_hw(dum);
 	init_dummy_udc_hw(dum);
 
 
 	rc = usb_add_gadget_udc(&pdev->dev, &dum->gadget);
 	rc = usb_add_gadget_udc(&pdev->dev, &dum->gadget);
@@ -1008,7 +993,6 @@ static int dummy_udc_probe(struct platform_device *pdev)
 err_dev:
 err_dev:
 	usb_del_gadget_udc(&dum->gadget);
 	usb_del_gadget_udc(&dum->gadget);
 err_udc:
 err_udc:
-	device_unregister(&dum->gadget.dev);
 	return rc;
 	return rc;
 }
 }
 
 
@@ -1019,7 +1003,6 @@ static int dummy_udc_remove(struct platform_device *pdev)
 	usb_del_gadget_udc(&dum->gadget);
 	usb_del_gadget_udc(&dum->gadget);
 	platform_set_drvdata(pdev, NULL);
 	platform_set_drvdata(pdev, NULL);
 	device_remove_file(&dum->gadget.dev, &dev_attr_function);
 	device_remove_file(&dum->gadget.dev, &dev_attr_function);
-	device_unregister(&dum->gadget.dev);
 	return 0;
 	return 0;
 }
 }
 
 
@@ -1923,7 +1906,7 @@ done:
 }
 }
 
 
 /* usb 3.0 root hub device descriptor */
 /* usb 3.0 root hub device descriptor */
-struct {
+static struct {
 	struct usb_bos_descriptor bos;
 	struct usb_bos_descriptor bos;
 	struct usb_ss_cap_descriptor ss_cap;
 	struct usb_ss_cap_descriptor ss_cap;
 } __packed usb3_bos_desc = {
 } __packed usb3_bos_desc = {

+ 10 - 10
drivers/usb/gadget/ether.c

@@ -207,7 +207,7 @@ static struct usb_gadget_strings *dev_strings[] = {
 };
 };
 
 
 static u8 hostaddr[ETH_ALEN];
 static u8 hostaddr[ETH_ALEN];
-
+static struct eth_dev *the_dev;
 /*-------------------------------------------------------------------------*/
 /*-------------------------------------------------------------------------*/
 
 
 /*
 /*
@@ -224,7 +224,7 @@ static int __init rndis_do_config(struct usb_configuration *c)
 		c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
 		c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
 	}
 	}
 
 
-	return rndis_bind_config(c, hostaddr);
+	return rndis_bind_config(c, hostaddr, the_dev);
 }
 }
 
 
 static struct usb_configuration rndis_config_driver = {
 static struct usb_configuration rndis_config_driver = {
@@ -257,11 +257,11 @@ static int __init eth_do_config(struct usb_configuration *c)
 	}
 	}
 
 
 	if (use_eem)
 	if (use_eem)
-		return eem_bind_config(c);
+		return eem_bind_config(c, the_dev);
 	else if (can_support_ecm(c->cdev->gadget))
 	else if (can_support_ecm(c->cdev->gadget))
-		return ecm_bind_config(c, hostaddr);
+		return ecm_bind_config(c, hostaddr, the_dev);
 	else
 	else
-		return geth_bind_config(c, hostaddr);
+		return geth_bind_config(c, hostaddr, the_dev);
 }
 }
 
 
 static struct usb_configuration eth_config_driver = {
 static struct usb_configuration eth_config_driver = {
@@ -279,9 +279,9 @@ static int __init eth_bind(struct usb_composite_dev *cdev)
 	int			status;
 	int			status;
 
 
 	/* set up network link layer */
 	/* set up network link layer */
-	status = gether_setup(cdev->gadget, hostaddr);
-	if (status < 0)
-		return status;
+	the_dev = gether_setup(cdev->gadget, hostaddr);
+	if (IS_ERR(the_dev))
+		return PTR_ERR(the_dev);
 
 
 	/* set up main config label and device descriptor */
 	/* set up main config label and device descriptor */
 	if (use_eem) {
 	if (use_eem) {
@@ -338,13 +338,13 @@ static int __init eth_bind(struct usb_composite_dev *cdev)
 	return 0;
 	return 0;
 
 
 fail:
 fail:
-	gether_cleanup();
+	gether_cleanup(the_dev);
 	return status;
 	return status;
 }
 }
 
 
 static int __exit eth_unbind(struct usb_composite_dev *cdev)
 static int __exit eth_unbind(struct usb_composite_dev *cdev)
 {
 {
-	gether_cleanup();
+	gether_cleanup(the_dev);
 	return 0;
 	return 0;
 }
 }
 
 

+ 73 - 64
drivers/usb/gadget/f_acm.c

@@ -715,13 +715,31 @@ fail:
 	return status;
 	return status;
 }
 }
 
 
-static struct f_acm *acm_alloc_basic_func(void)
+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_acm	*acm;
+	struct f_serial_opts *opts;
+	struct f_acm *acm;
 
 
 	acm = kzalloc(sizeof(*acm), GFP_KERNEL);
 	acm = kzalloc(sizeof(*acm), GFP_KERNEL);
 	if (!acm)
 	if (!acm)
-		return NULL;
+		return ERR_PTR(-ENOMEM);
 
 
 	spin_lock_init(&acm->lock);
 	spin_lock_init(&acm->lock);
 
 
@@ -730,109 +748,100 @@ static struct f_acm *acm_alloc_basic_func(void)
 	acm->port.send_break = acm_send_break;
 	acm->port.send_break = acm_send_break;
 
 
 	acm->port.func.name = "acm";
 	acm->port.func.name = "acm";
+	acm->port.func.strings = acm_strings;
 	/* descriptors are per-instance copies */
 	/* descriptors are per-instance copies */
 	acm->port.func.bind = acm_bind;
 	acm->port.func.bind = acm_bind;
 	acm->port.func.set_alt = acm_set_alt;
 	acm->port.func.set_alt = acm_set_alt;
 	acm->port.func.setup = acm_setup;
 	acm->port.func.setup = acm_setup;
 	acm->port.func.disable = acm_disable;
 	acm->port.func.disable = acm_disable;
 
 
-	return acm;
+	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;
 }
 }
 
 
-#ifdef USB_FACM_INCLUDED
-static void
-acm_old_unbind(struct usb_configuration *c, struct usb_function *f)
+static inline struct f_serial_opts *to_f_serial_opts(struct config_item *item)
 {
 {
-	struct f_acm		*acm = func_to_acm(f);
-
-	usb_free_all_descriptors(f);
-	if (acm->notify_req)
-		gs_free_req(acm->notify, acm->notify_req);
-	kfree(acm);
+	return container_of(to_config_group(item), struct f_serial_opts,
+			func_inst.group);
 }
 }
 
 
-/**
- * acm_bind_config - add a CDC ACM function to a configuration
- * @c: the configuration to support the CDC ACM instance
- * @port_num: /dev/ttyGS* port this interface will use
- * Context: single threaded during gadget setup
- *
- * Returns zero on success, else negative errno.
- *
- */
-int acm_bind_config(struct usb_configuration *c, u8 port_num)
+CONFIGFS_ATTR_STRUCT(f_serial_opts);
+static ssize_t f_acm_attr_show(struct config_item *item,
+				 struct configfs_attribute *attr,
+				 char *page)
 {
 {
-	struct f_acm	*acm;
-	int		status;
-
-	/* allocate and initialize one new instance */
-	acm = acm_alloc_basic_func();
-	if (!acm)
-		return -ENOMEM;
-
-	acm->port_num = port_num;
-	acm->port.func.unbind = acm_old_unbind;
-
-	status = usb_add_function(c, &acm->port.func);
-	if (status)
-		kfree(acm);
-	return status;
+	struct f_serial_opts *opts = to_f_serial_opts(item);
+	struct f_serial_opts_attribute *f_serial_opts_attr =
+		container_of(attr, struct f_serial_opts_attribute, attr);
+	ssize_t ret = 0;
+
+	if (f_serial_opts_attr->show)
+		ret = f_serial_opts_attr->show(opts, page);
+	return ret;
 }
 }
 
 
-#else
-
-static void acm_unbind(struct usb_configuration *c, struct usb_function *f)
+static void acm_attr_release(struct config_item *item)
 {
 {
-	struct f_acm		*acm = func_to_acm(f);
+	struct f_serial_opts *opts = to_f_serial_opts(item);
 
 
-	acm_string_defs[0].id = 0;
-	usb_free_all_descriptors(f);
-	if (acm->notify_req)
-		gs_free_req(acm->notify, acm->notify_req);
+	usb_put_function_instance(&opts->func_inst);
 }
 }
 
 
-static void acm_free_func(struct usb_function *f)
-{
-	struct f_acm		*acm = func_to_acm(f);
+static struct configfs_item_operations acm_item_ops = {
+	.release                = acm_attr_release,
+	.show_attribute		= f_acm_attr_show,
+};
 
 
-	kfree(acm);
+static ssize_t f_acm_port_num_show(struct f_serial_opts *opts, char *page)
+{
+	return sprintf(page, "%u\n", opts->port_num);
 }
 }
 
 
-static struct usb_function *acm_alloc_func(struct usb_function_instance *fi)
-{
-	struct f_serial_opts *opts;
-	struct f_acm *acm;
+static struct f_serial_opts_attribute f_acm_port_num =
+	__CONFIGFS_ATTR_RO(port_num, f_acm_port_num_show);
 
 
-	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;
+static struct configfs_attribute *acm_attrs[] = {
+	&f_acm_port_num.attr,
+	NULL,
+};
 
 
-	return &acm->port.func;
-}
+static struct config_item_type acm_func_type = {
+	.ct_item_ops    = &acm_item_ops,
+	.ct_attrs	= acm_attrs,
+	.ct_owner       = THIS_MODULE,
+};
 
 
 static void acm_free_instance(struct usb_function_instance *fi)
 static void acm_free_instance(struct usb_function_instance *fi)
 {
 {
 	struct f_serial_opts *opts;
 	struct f_serial_opts *opts;
 
 
 	opts = container_of(fi, struct f_serial_opts, func_inst);
 	opts = container_of(fi, struct f_serial_opts, func_inst);
+	gserial_free_line(opts->port_num);
 	kfree(opts);
 	kfree(opts);
 }
 }
 
 
 static struct usb_function_instance *acm_alloc_instance(void)
 static struct usb_function_instance *acm_alloc_instance(void)
 {
 {
 	struct f_serial_opts *opts;
 	struct f_serial_opts *opts;
+	int ret;
 
 
 	opts = kzalloc(sizeof(*opts), GFP_KERNEL);
 	opts = kzalloc(sizeof(*opts), GFP_KERNEL);
 	if (!opts)
 	if (!opts)
 		return ERR_PTR(-ENOMEM);
 		return ERR_PTR(-ENOMEM);
 	opts->func_inst.free_func_inst = acm_free_instance;
 	opts->func_inst.free_func_inst = acm_free_instance;
+	ret = gserial_alloc_line(&opts->port_num);
+	if (ret) {
+		kfree(opts);
+		return ERR_PTR(ret);
+	}
+	config_group_init_type_name(&opts->func_inst.group, "",
+			&acm_func_type);
 	return &opts->func_inst;
 	return &opts->func_inst;
 }
 }
 DECLARE_USB_FUNCTION_INIT(acm, acm_alloc_instance, acm_alloc_func);
 DECLARE_USB_FUNCTION_INIT(acm, acm_alloc_instance, acm_alloc_func);
 MODULE_LICENSE("GPL");
 MODULE_LICENSE("GPL");
-#endif

+ 3 - 1
drivers/usb/gadget/f_ecm.c

@@ -824,7 +824,8 @@ ecm_unbind(struct usb_configuration *c, struct usb_function *f)
  * for calling @gether_cleanup() before module unload.
  * for calling @gether_cleanup() before module unload.
  */
  */
 int
 int
-ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
+ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
+		struct eth_dev *dev)
 {
 {
 	struct f_ecm	*ecm;
 	struct f_ecm	*ecm;
 	int		status;
 	int		status;
@@ -852,6 +853,7 @@ ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
 	snprintf(ecm->ethaddr, sizeof ecm->ethaddr, "%pm", ethaddr);
 	snprintf(ecm->ethaddr, sizeof ecm->ethaddr, "%pm", ethaddr);
 	ecm_string_defs[1].s = ecm->ethaddr;
 	ecm_string_defs[1].s = ecm->ethaddr;
 
 
+	ecm->port.ioport = dev;
 	ecm->port.cdc_filter = DEFAULT_FILTER;
 	ecm->port.cdc_filter = DEFAULT_FILTER;
 
 
 	ecm->port.func.name = "cdc_ethernet";
 	ecm->port.func.name = "cdc_ethernet";

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

@@ -528,7 +528,7 @@ error:
  * Caller must have called @gether_setup().  Caller is also responsible
  * Caller must have called @gether_setup().  Caller is also responsible
  * for calling @gether_cleanup() before module unload.
  * for calling @gether_cleanup() before module unload.
  */
  */
-int __init eem_bind_config(struct usb_configuration *c)
+int __init eem_bind_config(struct usb_configuration *c, struct eth_dev *dev)
 {
 {
 	struct f_eem	*eem;
 	struct f_eem	*eem;
 	int		status;
 	int		status;
@@ -549,6 +549,7 @@ int __init eem_bind_config(struct usb_configuration *c)
 	if (!eem)
 	if (!eem)
 		return -ENOMEM;
 		return -ENOMEM;
 
 
+	eem->port.ioport = dev;
 	eem->port.cdc_filter = DEFAULT_FILTER;
 	eem->port.cdc_filter = DEFAULT_FILTER;
 
 
 	eem->port.func.name = "cdc_eem";
 	eem->port.func.name = "cdc_eem";

+ 3 - 1
drivers/usb/gadget/f_ncm.c

@@ -1287,7 +1287,8 @@ ncm_unbind(struct usb_configuration *c, struct usb_function *f)
  * Caller must have called @gether_setup().  Caller is also responsible
  * Caller must have called @gether_setup().  Caller is also responsible
  * for calling @gether_cleanup() before module unload.
  * for calling @gether_cleanup() before module unload.
  */
  */
-int __init ncm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
+int __init ncm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
+		struct eth_dev *dev)
 {
 {
 	struct f_ncm	*ncm;
 	struct f_ncm	*ncm;
 	int		status;
 	int		status;
@@ -1321,6 +1322,7 @@ int __init ncm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
 
 
 	spin_lock_init(&ncm->lock);
 	spin_lock_init(&ncm->lock);
 	ncm_reset_values(ncm);
 	ncm_reset_values(ncm);
+	ncm->port.ioport = dev;
 	ncm->port.is_fixed = true;
 	ncm->port.is_fixed = true;
 
 
 	ncm->port.func.name = "cdc_network";
 	ncm->port.func.name = "cdc_network";

+ 180 - 46
drivers/usb/gadget/f_obex.c

@@ -72,7 +72,7 @@ static struct usb_gadget_strings *obex_strings[] = {
 
 
 /*-------------------------------------------------------------------------*/
 /*-------------------------------------------------------------------------*/
 
 
-static struct usb_interface_descriptor obex_control_intf __initdata = {
+static struct usb_interface_descriptor obex_control_intf = {
 	.bLength		= sizeof(obex_control_intf),
 	.bLength		= sizeof(obex_control_intf),
 	.bDescriptorType	= USB_DT_INTERFACE,
 	.bDescriptorType	= USB_DT_INTERFACE,
 	.bInterfaceNumber	= 0,
 	.bInterfaceNumber	= 0,
@@ -83,7 +83,7 @@ static struct usb_interface_descriptor obex_control_intf __initdata = {
 	.bInterfaceSubClass	= USB_CDC_SUBCLASS_OBEX,
 	.bInterfaceSubClass	= USB_CDC_SUBCLASS_OBEX,
 };
 };
 
 
-static struct usb_interface_descriptor obex_data_nop_intf __initdata = {
+static struct usb_interface_descriptor obex_data_nop_intf = {
 	.bLength		= sizeof(obex_data_nop_intf),
 	.bLength		= sizeof(obex_data_nop_intf),
 	.bDescriptorType	= USB_DT_INTERFACE,
 	.bDescriptorType	= USB_DT_INTERFACE,
 	.bInterfaceNumber	= 1,
 	.bInterfaceNumber	= 1,
@@ -93,7 +93,7 @@ static struct usb_interface_descriptor obex_data_nop_intf __initdata = {
 	.bInterfaceClass	= USB_CLASS_CDC_DATA,
 	.bInterfaceClass	= USB_CLASS_CDC_DATA,
 };
 };
 
 
-static struct usb_interface_descriptor obex_data_intf __initdata = {
+static struct usb_interface_descriptor obex_data_intf = {
 	.bLength		= sizeof(obex_data_intf),
 	.bLength		= sizeof(obex_data_intf),
 	.bDescriptorType	= USB_DT_INTERFACE,
 	.bDescriptorType	= USB_DT_INTERFACE,
 	.bInterfaceNumber	= 2,
 	.bInterfaceNumber	= 2,
@@ -103,14 +103,14 @@ static struct usb_interface_descriptor obex_data_intf __initdata = {
 	.bInterfaceClass	= USB_CLASS_CDC_DATA,
 	.bInterfaceClass	= USB_CLASS_CDC_DATA,
 };
 };
 
 
-static struct usb_cdc_header_desc obex_cdc_header_desc __initdata = {
+static struct usb_cdc_header_desc obex_cdc_header_desc = {
 	.bLength		= sizeof(obex_cdc_header_desc),
 	.bLength		= sizeof(obex_cdc_header_desc),
 	.bDescriptorType	= USB_DT_CS_INTERFACE,
 	.bDescriptorType	= USB_DT_CS_INTERFACE,
 	.bDescriptorSubType	= USB_CDC_HEADER_TYPE,
 	.bDescriptorSubType	= USB_CDC_HEADER_TYPE,
 	.bcdCDC			= cpu_to_le16(0x0120),
 	.bcdCDC			= cpu_to_le16(0x0120),
 };
 };
 
 
-static struct usb_cdc_union_desc obex_cdc_union_desc __initdata = {
+static struct usb_cdc_union_desc obex_cdc_union_desc = {
 	.bLength		= sizeof(obex_cdc_union_desc),
 	.bLength		= sizeof(obex_cdc_union_desc),
 	.bDescriptorType	= USB_DT_CS_INTERFACE,
 	.bDescriptorType	= USB_DT_CS_INTERFACE,
 	.bDescriptorSubType	= USB_CDC_UNION_TYPE,
 	.bDescriptorSubType	= USB_CDC_UNION_TYPE,
@@ -118,7 +118,7 @@ static struct usb_cdc_union_desc obex_cdc_union_desc __initdata = {
 	.bSlaveInterface0	= 2,
 	.bSlaveInterface0	= 2,
 };
 };
 
 
-static struct usb_cdc_obex_desc obex_desc __initdata = {
+static struct usb_cdc_obex_desc obex_desc = {
 	.bLength		= sizeof(obex_desc),
 	.bLength		= sizeof(obex_desc),
 	.bDescriptorType	= USB_DT_CS_INTERFACE,
 	.bDescriptorType	= USB_DT_CS_INTERFACE,
 	.bDescriptorSubType	= USB_CDC_OBEX_TYPE,
 	.bDescriptorSubType	= USB_CDC_OBEX_TYPE,
@@ -127,7 +127,7 @@ static struct usb_cdc_obex_desc obex_desc __initdata = {
 
 
 /* High-Speed Support */
 /* High-Speed Support */
 
 
-static struct usb_endpoint_descriptor obex_hs_ep_out_desc __initdata = {
+static struct usb_endpoint_descriptor obex_hs_ep_out_desc = {
 	.bLength		= USB_DT_ENDPOINT_SIZE,
 	.bLength		= USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType	= USB_DT_ENDPOINT,
 	.bDescriptorType	= USB_DT_ENDPOINT,
 
 
@@ -136,7 +136,7 @@ static struct usb_endpoint_descriptor obex_hs_ep_out_desc __initdata = {
 	.wMaxPacketSize		= cpu_to_le16(512),
 	.wMaxPacketSize		= cpu_to_le16(512),
 };
 };
 
 
-static struct usb_endpoint_descriptor obex_hs_ep_in_desc __initdata = {
+static struct usb_endpoint_descriptor obex_hs_ep_in_desc = {
 	.bLength		= USB_DT_ENDPOINT_SIZE,
 	.bLength		= USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType	= USB_DT_ENDPOINT,
 	.bDescriptorType	= USB_DT_ENDPOINT,
 
 
@@ -145,7 +145,7 @@ static struct usb_endpoint_descriptor obex_hs_ep_in_desc __initdata = {
 	.wMaxPacketSize		= cpu_to_le16(512),
 	.wMaxPacketSize		= cpu_to_le16(512),
 };
 };
 
 
-static struct usb_descriptor_header *hs_function[] __initdata = {
+static struct usb_descriptor_header *hs_function[] = {
 	(struct usb_descriptor_header *) &obex_control_intf,
 	(struct usb_descriptor_header *) &obex_control_intf,
 	(struct usb_descriptor_header *) &obex_cdc_header_desc,
 	(struct usb_descriptor_header *) &obex_cdc_header_desc,
 	(struct usb_descriptor_header *) &obex_desc,
 	(struct usb_descriptor_header *) &obex_desc,
@@ -160,7 +160,7 @@ static struct usb_descriptor_header *hs_function[] __initdata = {
 
 
 /* Full-Speed Support */
 /* Full-Speed Support */
 
 
-static struct usb_endpoint_descriptor obex_fs_ep_in_desc __initdata = {
+static struct usb_endpoint_descriptor obex_fs_ep_in_desc = {
 	.bLength		= USB_DT_ENDPOINT_SIZE,
 	.bLength		= USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType	= USB_DT_ENDPOINT,
 	.bDescriptorType	= USB_DT_ENDPOINT,
 
 
@@ -168,7 +168,7 @@ static struct usb_endpoint_descriptor obex_fs_ep_in_desc __initdata = {
 	.bmAttributes		= USB_ENDPOINT_XFER_BULK,
 	.bmAttributes		= USB_ENDPOINT_XFER_BULK,
 };
 };
 
 
-static struct usb_endpoint_descriptor obex_fs_ep_out_desc __initdata = {
+static struct usb_endpoint_descriptor obex_fs_ep_out_desc = {
 	.bLength		= USB_DT_ENDPOINT_SIZE,
 	.bLength		= USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType	= USB_DT_ENDPOINT,
 	.bDescriptorType	= USB_DT_ENDPOINT,
 
 
@@ -176,7 +176,7 @@ static struct usb_endpoint_descriptor obex_fs_ep_out_desc __initdata = {
 	.bmAttributes		= USB_ENDPOINT_XFER_BULK,
 	.bmAttributes		= USB_ENDPOINT_XFER_BULK,
 };
 };
 
 
-static struct usb_descriptor_header *fs_function[] __initdata = {
+static struct usb_descriptor_header *fs_function[] = {
 	(struct usb_descriptor_header *) &obex_control_intf,
 	(struct usb_descriptor_header *) &obex_control_intf,
 	(struct usb_descriptor_header *) &obex_cdc_header_desc,
 	(struct usb_descriptor_header *) &obex_cdc_header_desc,
 	(struct usb_descriptor_header *) &obex_desc,
 	(struct usb_descriptor_header *) &obex_desc,
@@ -290,14 +290,43 @@ static void obex_disconnect(struct gserial *g)
 
 
 /*-------------------------------------------------------------------------*/
 /*-------------------------------------------------------------------------*/
 
 
-static int __init
-obex_bind(struct usb_configuration *c, struct usb_function *f)
+/* Some controllers can't support CDC OBEX ... */
+static inline bool can_support_obex(struct usb_configuration *c)
+{
+	/* Since the first interface is a NOP, we can ignore the
+	 * issue of multi-interface support on most controllers.
+	 *
+	 * Altsettings are mandatory, however...
+	 */
+	if (!gadget_supports_altsettings(c->cdev->gadget))
+		return false;
+
+	/* everything else is *probably* fine ... */
+	return true;
+}
+
+static int obex_bind(struct usb_configuration *c, struct usb_function *f)
 {
 {
 	struct usb_composite_dev *cdev = c->cdev;
 	struct usb_composite_dev *cdev = c->cdev;
 	struct f_obex		*obex = func_to_obex(f);
 	struct f_obex		*obex = func_to_obex(f);
 	int			status;
 	int			status;
 	struct usb_ep		*ep;
 	struct usb_ep		*ep;
 
 
+	if (!can_support_obex(c))
+		return -EINVAL;
+
+	if (obex_string_defs[OBEX_CTRL_IDX].id == 0) {
+		status = usb_string_ids_tab(c->cdev, obex_string_defs);
+		if (status < 0)
+			return status;
+		obex_control_intf.iInterface =
+			obex_string_defs[OBEX_CTRL_IDX].id;
+
+		status = obex_string_defs[OBEX_DATA_IDX].id;
+		obex_data_nop_intf.iInterface = status;
+		obex_data_intf.iInterface = status;
+	}
+
 	/* allocate instance-specific interface IDs, and patch descriptors */
 	/* allocate instance-specific interface IDs, and patch descriptors */
 
 
 	status = usb_interface_id(c, f);
 	status = usb_interface_id(c, f);
@@ -376,29 +405,16 @@ fail:
 	return status;
 	return status;
 }
 }
 
 
+#ifdef USBF_OBEX_INCLUDED
+
 static void
 static void
-obex_unbind(struct usb_configuration *c, struct usb_function *f)
+obex_old_unbind(struct usb_configuration *c, struct usb_function *f)
 {
 {
 	obex_string_defs[OBEX_CTRL_IDX].id = 0;
 	obex_string_defs[OBEX_CTRL_IDX].id = 0;
 	usb_free_all_descriptors(f);
 	usb_free_all_descriptors(f);
 	kfree(func_to_obex(f));
 	kfree(func_to_obex(f));
 }
 }
 
 
-/* Some controllers can't support CDC OBEX ... */
-static inline bool can_support_obex(struct usb_configuration *c)
-{
-	/* Since the first interface is a NOP, we can ignore the
-	 * issue of multi-interface support on most controllers.
-	 *
-	 * Altsettings are mandatory, however...
-	 */
-	if (!gadget_supports_altsettings(c->cdev->gadget))
-		return false;
-
-	/* everything else is *probably* fine ... */
-	return true;
-}
-
 /**
 /**
  * obex_bind_config - add a CDC OBEX function to a configuration
  * obex_bind_config - add a CDC OBEX function to a configuration
  * @c: the configuration to support the CDC OBEX instance
  * @c: the configuration to support the CDC OBEX instance
@@ -412,21 +428,6 @@ int __init obex_bind_config(struct usb_configuration *c, u8 port_num)
 	struct f_obex	*obex;
 	struct f_obex	*obex;
 	int		status;
 	int		status;
 
 
-	if (!can_support_obex(c))
-		return -EINVAL;
-
-	if (obex_string_defs[OBEX_CTRL_IDX].id == 0) {
-		status = usb_string_ids_tab(c->cdev, obex_string_defs);
-		if (status < 0)
-			return status;
-		obex_control_intf.iInterface =
-			obex_string_defs[OBEX_CTRL_IDX].id;
-
-		status = obex_string_defs[OBEX_DATA_IDX].id;
-		obex_data_nop_intf.iInterface = status;
-		obex_data_intf.iInterface = status;
-	}
-
 	/* allocate and initialize one new instance */
 	/* allocate and initialize one new instance */
 	obex = kzalloc(sizeof *obex, GFP_KERNEL);
 	obex = kzalloc(sizeof *obex, GFP_KERNEL);
 	if (!obex)
 	if (!obex)
@@ -441,7 +442,7 @@ int __init obex_bind_config(struct usb_configuration *c, u8 port_num)
 	obex->port.func.strings = obex_strings;
 	obex->port.func.strings = obex_strings;
 	/* descriptors are per-instance copies */
 	/* descriptors are per-instance copies */
 	obex->port.func.bind = obex_bind;
 	obex->port.func.bind = obex_bind;
-	obex->port.func.unbind = obex_unbind;
+	obex->port.func.unbind = obex_old_unbind;
 	obex->port.func.set_alt = obex_set_alt;
 	obex->port.func.set_alt = obex_set_alt;
 	obex->port.func.get_alt = obex_get_alt;
 	obex->port.func.get_alt = obex_get_alt;
 	obex->port.func.disable = obex_disable;
 	obex->port.func.disable = obex_disable;
@@ -453,5 +454,138 @@ int __init obex_bind_config(struct usb_configuration *c, u8 port_num)
 	return status;
 	return status;
 }
 }
 
 
+#else
+
+static inline struct f_serial_opts *to_f_serial_opts(struct config_item *item)
+{
+	return container_of(to_config_group(item), struct f_serial_opts,
+			    func_inst.group);
+}
+
+CONFIGFS_ATTR_STRUCT(f_serial_opts);
+static ssize_t f_obex_attr_show(struct config_item *item,
+				struct configfs_attribute *attr,
+				char *page)
+{
+	struct f_serial_opts *opts = to_f_serial_opts(item);
+	struct f_serial_opts_attribute *f_serial_opts_attr =
+		container_of(attr, struct f_serial_opts_attribute, attr);
+	ssize_t ret = 0;
+
+	if (f_serial_opts_attr->show)
+		ret = f_serial_opts_attr->show(opts, page);
+
+	return ret;
+}
+
+static void obex_attr_release(struct config_item *item)
+{
+	struct f_serial_opts *opts = to_f_serial_opts(item);
+
+	usb_put_function_instance(&opts->func_inst);
+}
+
+static struct configfs_item_operations obex_item_ops = {
+	.release	= obex_attr_release,
+	.show_attribute = f_obex_attr_show,
+};
+
+static ssize_t f_obex_port_num_show(struct f_serial_opts *opts, char *page)
+{
+	return sprintf(page, "%u\n", opts->port_num);
+}
+
+static struct f_serial_opts_attribute f_obex_port_num =
+	__CONFIGFS_ATTR_RO(port_num, f_obex_port_num_show);
+
+static struct configfs_attribute *acm_attrs[] = {
+	&f_obex_port_num.attr,
+	NULL,
+};
+
+static struct config_item_type obex_func_type = {
+	.ct_item_ops	= &obex_item_ops,
+	.ct_attrs	= acm_attrs,
+	.ct_owner	= THIS_MODULE,
+};
+
+static void obex_free_inst(struct usb_function_instance *f)
+{
+	struct f_serial_opts *opts;
+
+	opts = container_of(f, struct f_serial_opts, func_inst);
+	gserial_free_line(opts->port_num);
+	kfree(opts);
+}
+
+static struct usb_function_instance *obex_alloc_inst(void)
+{
+	struct f_serial_opts *opts;
+	int ret;
+
+	opts = kzalloc(sizeof(*opts), GFP_KERNEL);
+	if (!opts)
+		return ERR_PTR(-ENOMEM);
+
+	opts->func_inst.free_func_inst = obex_free_inst;
+	ret = gserial_alloc_line(&opts->port_num);
+	if (ret) {
+		kfree(opts);
+		return ERR_PTR(ret);
+	}
+	config_group_init_type_name(&opts->func_inst.group, "",
+				    &obex_func_type);
+
+	return &opts->func_inst;
+}
+
+static void obex_free(struct usb_function *f)
+{
+	struct f_obex *obex;
+
+	obex = func_to_obex(f);
+	kfree(obex);
+}
+
+static void obex_unbind(struct usb_configuration *c, struct usb_function *f)
+{
+	obex_string_defs[OBEX_CTRL_IDX].id = 0;
+	usb_free_all_descriptors(f);
+}
+
+struct usb_function *obex_alloc(struct usb_function_instance *fi)
+{
+	struct f_obex	*obex;
+	struct f_serial_opts *opts;
+
+	/* allocate and initialize one new instance */
+	obex = kzalloc(sizeof(*obex), GFP_KERNEL);
+	if (!obex)
+		return ERR_PTR(-ENOMEM);
+
+	opts = container_of(fi, struct f_serial_opts, func_inst);
+
+	obex->port_num = opts->port_num;
+
+	obex->port.connect = obex_connect;
+	obex->port.disconnect = obex_disconnect;
+
+	obex->port.func.name = "obex";
+	obex->port.func.strings = obex_strings;
+	/* descriptors are per-instance copies */
+	obex->port.func.bind = obex_bind;
+	obex->port.func.unbind = obex_unbind;
+	obex->port.func.set_alt = obex_set_alt;
+	obex->port.func.get_alt = obex_get_alt;
+	obex->port.func.disable = obex_disable;
+	obex->port.func.free_func = obex_free;
+
+	return &obex->port.func;
+}
+
+DECLARE_USB_FUNCTION_INIT(obex, obex_alloc_inst, obex_alloc);
+
+#endif
+
 MODULE_AUTHOR("Felipe Balbi");
 MODULE_AUTHOR("Felipe Balbi");
 MODULE_LICENSE("GPL");
 MODULE_LICENSE("GPL");

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

@@ -813,7 +813,7 @@ static inline bool can_support_rndis(struct usb_configuration *c)
 
 
 int
 int
 rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
 rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
-				u32 vendorID, const char *manufacturer)
+		u32 vendorID, const char *manufacturer, struct eth_dev *dev)
 {
 {
 	struct f_rndis	*rndis;
 	struct f_rndis	*rndis;
 	int		status;
 	int		status;
@@ -846,6 +846,7 @@ rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
 	rndis->vendorID = vendorID;
 	rndis->vendorID = vendorID;
 	rndis->manufacturer = manufacturer;
 	rndis->manufacturer = manufacturer;
 
 
+	rndis->port.ioport = dev;
 	/* RNDIS activates when the host changes this filter */
 	/* RNDIS activates when the host changes this filter */
 	rndis->port.cdc_filter = 0;
 	rndis->port.cdc_filter = 0;
 
 

+ 130 - 44
drivers/usb/gadget/f_serial.c

@@ -12,6 +12,7 @@
 
 
 #include <linux/slab.h>
 #include <linux/slab.h>
 #include <linux/kernel.h>
 #include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/device.h>
 #include <linux/device.h>
 
 
 #include "u_serial.h"
 #include "u_serial.h"
@@ -42,7 +43,7 @@ static inline struct f_gser *func_to_gser(struct usb_function *f)
 
 
 /* interface descriptor: */
 /* interface descriptor: */
 
 
-static struct usb_interface_descriptor gser_interface_desc __initdata = {
+static struct usb_interface_descriptor gser_interface_desc = {
 	.bLength =		USB_DT_INTERFACE_SIZE,
 	.bLength =		USB_DT_INTERFACE_SIZE,
 	.bDescriptorType =	USB_DT_INTERFACE,
 	.bDescriptorType =	USB_DT_INTERFACE,
 	/* .bInterfaceNumber = DYNAMIC */
 	/* .bInterfaceNumber = DYNAMIC */
@@ -55,21 +56,21 @@ static struct usb_interface_descriptor gser_interface_desc __initdata = {
 
 
 /* full speed support: */
 /* full speed support: */
 
 
-static struct usb_endpoint_descriptor gser_fs_in_desc __initdata = {
+static struct usb_endpoint_descriptor gser_fs_in_desc = {
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType =	USB_DT_ENDPOINT,
 	.bDescriptorType =	USB_DT_ENDPOINT,
 	.bEndpointAddress =	USB_DIR_IN,
 	.bEndpointAddress =	USB_DIR_IN,
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
 };
 };
 
 
-static struct usb_endpoint_descriptor gser_fs_out_desc __initdata = {
+static struct usb_endpoint_descriptor gser_fs_out_desc = {
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType =	USB_DT_ENDPOINT,
 	.bDescriptorType =	USB_DT_ENDPOINT,
 	.bEndpointAddress =	USB_DIR_OUT,
 	.bEndpointAddress =	USB_DIR_OUT,
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
 };
 };
 
 
-static struct usb_descriptor_header *gser_fs_function[] __initdata = {
+static struct usb_descriptor_header *gser_fs_function[] = {
 	(struct usb_descriptor_header *) &gser_interface_desc,
 	(struct usb_descriptor_header *) &gser_interface_desc,
 	(struct usb_descriptor_header *) &gser_fs_in_desc,
 	(struct usb_descriptor_header *) &gser_fs_in_desc,
 	(struct usb_descriptor_header *) &gser_fs_out_desc,
 	(struct usb_descriptor_header *) &gser_fs_out_desc,
@@ -78,47 +79,47 @@ static struct usb_descriptor_header *gser_fs_function[] __initdata = {
 
 
 /* high speed support: */
 /* high speed support: */
 
 
-static struct usb_endpoint_descriptor gser_hs_in_desc __initdata = {
+static struct usb_endpoint_descriptor gser_hs_in_desc = {
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType =	USB_DT_ENDPOINT,
 	.bDescriptorType =	USB_DT_ENDPOINT,
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
 	.wMaxPacketSize =	cpu_to_le16(512),
 	.wMaxPacketSize =	cpu_to_le16(512),
 };
 };
 
 
-static struct usb_endpoint_descriptor gser_hs_out_desc __initdata = {
+static struct usb_endpoint_descriptor gser_hs_out_desc = {
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType =	USB_DT_ENDPOINT,
 	.bDescriptorType =	USB_DT_ENDPOINT,
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
 	.wMaxPacketSize =	cpu_to_le16(512),
 	.wMaxPacketSize =	cpu_to_le16(512),
 };
 };
 
 
-static struct usb_descriptor_header *gser_hs_function[] __initdata = {
+static struct usb_descriptor_header *gser_hs_function[] = {
 	(struct usb_descriptor_header *) &gser_interface_desc,
 	(struct usb_descriptor_header *) &gser_interface_desc,
 	(struct usb_descriptor_header *) &gser_hs_in_desc,
 	(struct usb_descriptor_header *) &gser_hs_in_desc,
 	(struct usb_descriptor_header *) &gser_hs_out_desc,
 	(struct usb_descriptor_header *) &gser_hs_out_desc,
 	NULL,
 	NULL,
 };
 };
 
 
-static struct usb_endpoint_descriptor gser_ss_in_desc __initdata = {
+static struct usb_endpoint_descriptor gser_ss_in_desc = {
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType =	USB_DT_ENDPOINT,
 	.bDescriptorType =	USB_DT_ENDPOINT,
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
 	.wMaxPacketSize =	cpu_to_le16(1024),
 	.wMaxPacketSize =	cpu_to_le16(1024),
 };
 };
 
 
-static struct usb_endpoint_descriptor gser_ss_out_desc __initdata = {
+static struct usb_endpoint_descriptor gser_ss_out_desc = {
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType =	USB_DT_ENDPOINT,
 	.bDescriptorType =	USB_DT_ENDPOINT,
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
 	.wMaxPacketSize =	cpu_to_le16(1024),
 	.wMaxPacketSize =	cpu_to_le16(1024),
 };
 };
 
 
-static struct usb_ss_ep_comp_descriptor gser_ss_bulk_comp_desc __initdata = {
+static struct usb_ss_ep_comp_descriptor gser_ss_bulk_comp_desc = {
 	.bLength =              sizeof gser_ss_bulk_comp_desc,
 	.bLength =              sizeof gser_ss_bulk_comp_desc,
 	.bDescriptorType =      USB_DT_SS_ENDPOINT_COMP,
 	.bDescriptorType =      USB_DT_SS_ENDPOINT_COMP,
 };
 };
 
 
-static struct usb_descriptor_header *gser_ss_function[] __initdata = {
+static struct usb_descriptor_header *gser_ss_function[] = {
 	(struct usb_descriptor_header *) &gser_interface_desc,
 	(struct usb_descriptor_header *) &gser_interface_desc,
 	(struct usb_descriptor_header *) &gser_ss_in_desc,
 	(struct usb_descriptor_header *) &gser_ss_in_desc,
 	(struct usb_descriptor_header *) &gser_ss_bulk_comp_desc,
 	(struct usb_descriptor_header *) &gser_ss_bulk_comp_desc,
@@ -183,14 +184,25 @@ static void gser_disable(struct usb_function *f)
 
 
 /* serial function driver setup/binding */
 /* serial function driver setup/binding */
 
 
-static int __init
-gser_bind(struct usb_configuration *c, struct usb_function *f)
+static int gser_bind(struct usb_configuration *c, struct usb_function *f)
 {
 {
 	struct usb_composite_dev *cdev = c->cdev;
 	struct usb_composite_dev *cdev = c->cdev;
 	struct f_gser		*gser = func_to_gser(f);
 	struct f_gser		*gser = func_to_gser(f);
 	int			status;
 	int			status;
 	struct usb_ep		*ep;
 	struct usb_ep		*ep;
 
 
+	/* REVISIT might want instance-specific strings to help
+	 * distinguish instances ...
+	 */
+
+	/* maybe allocate device-global string ID */
+	if (gser_string_defs[0].id == 0) {
+		status = usb_string_id(c->cdev);
+		if (status < 0)
+			return status;
+		gser_string_defs[0].id = status;
+	}
+
 	/* allocate instance-specific interface IDs */
 	/* allocate instance-specific interface IDs */
 	status = usb_interface_id(c, f);
 	status = usb_interface_id(c, f);
 	if (status < 0)
 	if (status < 0)
@@ -246,44 +258,115 @@ fail:
 	return status;
 	return status;
 }
 }
 
 
-static void
-gser_unbind(struct usb_configuration *c, struct usb_function *f)
+static inline struct f_serial_opts *to_f_serial_opts(struct config_item *item)
 {
 {
-	usb_free_all_descriptors(f);
-	kfree(func_to_gser(f));
+	return container_of(to_config_group(item), struct f_serial_opts,
+			    func_inst.group);
 }
 }
 
 
-/**
- * gser_bind_config - add a generic serial function to a configuration
- * @c: the configuration to support the serial instance
- * @port_num: /dev/ttyGS* port this interface will use
- * Context: single threaded during gadget setup
- *
- * Returns zero on success, else negative errno.
- */
-int __init gser_bind_config(struct usb_configuration *c, u8 port_num)
+CONFIGFS_ATTR_STRUCT(f_serial_opts);
+static ssize_t f_serial_attr_show(struct config_item *item,
+				  struct configfs_attribute *attr,
+				  char *page)
 {
 {
-	struct f_gser	*gser;
-	int		status;
+	struct f_serial_opts *opts = to_f_serial_opts(item);
+	struct f_serial_opts_attribute *f_serial_opts_attr =
+		container_of(attr, struct f_serial_opts_attribute, attr);
+	ssize_t ret = 0;
 
 
-	/* REVISIT might want instance-specific strings to help
-	 * distinguish instances ...
-	 */
+	if (f_serial_opts_attr->show)
+		ret = f_serial_opts_attr->show(opts, page);
 
 
-	/* maybe allocate device-global string ID */
-	if (gser_string_defs[0].id == 0) {
-		status = usb_string_id(c->cdev);
-		if (status < 0)
-			return status;
-		gser_string_defs[0].id = status;
+	return ret;
+}
+
+static void serial_attr_release(struct config_item *item)
+{
+	struct f_serial_opts *opts = to_f_serial_opts(item);
+
+	usb_put_function_instance(&opts->func_inst);
+}
+
+static struct configfs_item_operations serial_item_ops = {
+	.release	= serial_attr_release,
+	.show_attribute = f_serial_attr_show,
+};
+
+static ssize_t f_serial_port_num_show(struct f_serial_opts *opts, char *page)
+{
+	return sprintf(page, "%u\n", opts->port_num);
+}
+
+static struct f_serial_opts_attribute f_serial_port_num =
+	__CONFIGFS_ATTR_RO(port_num, f_serial_port_num_show);
+
+static struct configfs_attribute *acm_attrs[] = {
+	&f_serial_port_num.attr,
+	NULL,
+};
+
+static struct config_item_type serial_func_type = {
+	.ct_item_ops	= &serial_item_ops,
+	.ct_attrs	= acm_attrs,
+	.ct_owner	= THIS_MODULE,
+};
+
+static void gser_free_inst(struct usb_function_instance *f)
+{
+	struct f_serial_opts *opts;
+
+	opts = container_of(f, struct f_serial_opts, func_inst);
+	gserial_free_line(opts->port_num);
+	kfree(opts);
+}
+
+static struct usb_function_instance *gser_alloc_inst(void)
+{
+	struct f_serial_opts *opts;
+	int ret;
+
+	opts = kzalloc(sizeof(*opts), GFP_KERNEL);
+	if (!opts)
+		return ERR_PTR(-ENOMEM);
+
+	opts->func_inst.free_func_inst = gser_free_inst;
+	ret = gserial_alloc_line(&opts->port_num);
+	if (ret) {
+		kfree(opts);
+		return ERR_PTR(ret);
 	}
 	}
+	config_group_init_type_name(&opts->func_inst.group, "",
+				    &serial_func_type);
+
+	return &opts->func_inst;
+}
+
+static void gser_free(struct usb_function *f)
+{
+	struct f_gser *serial;
+
+	serial = func_to_gser(f);
+	kfree(serial);
+}
+
+static void gser_unbind(struct usb_configuration *c, struct usb_function *f)
+{
+	usb_free_all_descriptors(f);
+}
+
+struct usb_function *gser_alloc(struct usb_function_instance *fi)
+{
+	struct f_gser	*gser;
+	struct f_serial_opts *opts;
 
 
 	/* allocate and initialize one new instance */
 	/* allocate and initialize one new instance */
-	gser = kzalloc(sizeof *gser, GFP_KERNEL);
+	gser = kzalloc(sizeof(*gser), GFP_KERNEL);
 	if (!gser)
 	if (!gser)
-		return -ENOMEM;
+		return ERR_PTR(-ENOMEM);
 
 
-	gser->port_num = port_num;
+	opts = container_of(fi, struct f_serial_opts, func_inst);
+
+	gser->port_num = opts->port_num;
 
 
 	gser->port.func.name = "gser";
 	gser->port.func.name = "gser";
 	gser->port.func.strings = gser_strings;
 	gser->port.func.strings = gser_strings;
@@ -291,9 +374,12 @@ int __init gser_bind_config(struct usb_configuration *c, u8 port_num)
 	gser->port.func.unbind = gser_unbind;
 	gser->port.func.unbind = gser_unbind;
 	gser->port.func.set_alt = gser_set_alt;
 	gser->port.func.set_alt = gser_set_alt;
 	gser->port.func.disable = gser_disable;
 	gser->port.func.disable = gser_disable;
+	gser->port.func.free_func = gser_free;
 
 
-	status = usb_add_function(c, &gser->port.func);
-	if (status)
-		kfree(gser);
-	return status;
+	return &gser->port.func;
 }
 }
+
+DECLARE_USB_FUNCTION_INIT(gser, gser_alloc_inst, gser_alloc);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Al Borchers");
+MODULE_AUTHOR("David Brownell");

+ 3 - 1
drivers/usb/gadget/f_subset.c

@@ -380,7 +380,8 @@ geth_unbind(struct usb_configuration *c, struct usb_function *f)
  * Caller must have called @gether_setup().  Caller is also responsible
  * Caller must have called @gether_setup().  Caller is also responsible
  * for calling @gether_cleanup() before module unload.
  * for calling @gether_cleanup() before module unload.
  */
  */
-int geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
+int geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
+		struct eth_dev *dev)
 {
 {
 	struct f_gether	*geth;
 	struct f_gether	*geth;
 	int		status;
 	int		status;
@@ -406,6 +407,7 @@ int geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
 	snprintf(geth->ethaddr, sizeof geth->ethaddr, "%pm", ethaddr);
 	snprintf(geth->ethaddr, sizeof geth->ethaddr, "%pm", ethaddr);
 	geth_string_defs[1].s = geth->ethaddr;
 	geth_string_defs[1].s = geth->ethaddr;
 
 
+	geth->port.ioport = dev;
 	geth->port.cdc_filter = DEFAULT_FILTER;
 	geth->port.cdc_filter = DEFAULT_FILTER;
 
 
 	geth->port.func.name = "cdc_subset";
 	geth->port.func.name = "cdc_subset";

+ 129 - 133
drivers/usb/gadget/f_uvc.c

@@ -33,19 +33,15 @@ unsigned int uvc_gadget_trace_param;
 /*-------------------------------------------------------------------------*/
 /*-------------------------------------------------------------------------*/
 
 
 /* module parameters specific to the Video streaming endpoint */
 /* module parameters specific to the Video streaming endpoint */
-static unsigned streaming_interval = 1;
+static unsigned int streaming_interval = 1;
 module_param(streaming_interval, uint, S_IRUGO|S_IWUSR);
 module_param(streaming_interval, uint, S_IRUGO|S_IWUSR);
 MODULE_PARM_DESC(streaming_interval, "1 - 16");
 MODULE_PARM_DESC(streaming_interval, "1 - 16");
 
 
-static unsigned streaming_maxpacket = 1024;
+static unsigned int streaming_maxpacket = 1024;
 module_param(streaming_maxpacket, uint, S_IRUGO|S_IWUSR);
 module_param(streaming_maxpacket, uint, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(streaming_maxpacket, "0 - 1023 (fs), 0 - 1024 (hs/ss)");
+MODULE_PARM_DESC(streaming_maxpacket, "1 - 1023 (FS), 1 - 3072 (hs/ss)");
 
 
-static unsigned streaming_mult;
-module_param(streaming_mult, uint, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(streaming_mult, "0 - 2 (hs/ss only)");
-
-static unsigned streaming_maxburst;
+static unsigned int streaming_maxburst;
 module_param(streaming_maxburst, uint, S_IRUGO|S_IWUSR);
 module_param(streaming_maxburst, uint, S_IRUGO|S_IWUSR);
 MODULE_PARM_DESC(streaming_maxburst, "0 - 15 (ss only)");
 MODULE_PARM_DESC(streaming_maxburst, "0 - 15 (ss only)");
 
 
@@ -55,13 +51,11 @@ MODULE_PARM_DESC(streaming_maxburst, "0 - 15 (ss only)");
 
 
 /* string IDs are assigned dynamically */
 /* string IDs are assigned dynamically */
 
 
-#define UVC_STRING_ASSOCIATION_IDX		0
-#define UVC_STRING_CONTROL_IDX			1
-#define UVC_STRING_STREAMING_IDX		2
+#define UVC_STRING_CONTROL_IDX			0
+#define UVC_STRING_STREAMING_IDX		1
 
 
 static struct usb_string uvc_en_us_strings[] = {
 static struct usb_string uvc_en_us_strings[] = {
-	[UVC_STRING_ASSOCIATION_IDX].s = "UVC Camera",
-	[UVC_STRING_CONTROL_IDX].s = "Video Control",
+	[UVC_STRING_CONTROL_IDX].s = "UVC Camera",
 	[UVC_STRING_STREAMING_IDX].s = "Video Streaming",
 	[UVC_STRING_STREAMING_IDX].s = "Video Streaming",
 	{  }
 	{  }
 };
 };
@@ -79,7 +73,7 @@ static struct usb_gadget_strings *uvc_function_strings[] = {
 #define UVC_INTF_VIDEO_CONTROL			0
 #define UVC_INTF_VIDEO_CONTROL			0
 #define UVC_INTF_VIDEO_STREAMING		1
 #define UVC_INTF_VIDEO_STREAMING		1
 
 
-#define STATUS_BYTECOUNT			16	/* 16 bytes status */
+#define UVC_STATUS_MAX_PACKET_SIZE		16	/* 16 bytes status */
 
 
 static struct usb_interface_assoc_descriptor uvc_iad __initdata = {
 static struct usb_interface_assoc_descriptor uvc_iad __initdata = {
 	.bLength		= sizeof(uvc_iad),
 	.bLength		= sizeof(uvc_iad),
@@ -104,20 +98,29 @@ static struct usb_interface_descriptor uvc_control_intf __initdata = {
 	.iInterface		= 0,
 	.iInterface		= 0,
 };
 };
 
 
-static struct usb_endpoint_descriptor uvc_fs_control_ep __initdata = {
+static struct usb_endpoint_descriptor uvc_control_ep __initdata = {
 	.bLength		= USB_DT_ENDPOINT_SIZE,
 	.bLength		= USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType	= USB_DT_ENDPOINT,
 	.bDescriptorType	= USB_DT_ENDPOINT,
 	.bEndpointAddress	= USB_DIR_IN,
 	.bEndpointAddress	= USB_DIR_IN,
 	.bmAttributes		= USB_ENDPOINT_XFER_INT,
 	.bmAttributes		= USB_ENDPOINT_XFER_INT,
-	.wMaxPacketSize		= cpu_to_le16(STATUS_BYTECOUNT),
+	.wMaxPacketSize		= cpu_to_le16(UVC_STATUS_MAX_PACKET_SIZE),
 	.bInterval		= 8,
 	.bInterval		= 8,
 };
 };
 
 
+static struct usb_ss_ep_comp_descriptor uvc_ss_control_comp __initdata = {
+	.bLength		= sizeof(uvc_ss_control_comp),
+	.bDescriptorType	= USB_DT_SS_ENDPOINT_COMP,
+	/* The following 3 values can be tweaked if necessary. */
+	.bMaxBurst		= 0,
+	.bmAttributes		= 0,
+	.wBytesPerInterval	= cpu_to_le16(UVC_STATUS_MAX_PACKET_SIZE),
+};
+
 static struct uvc_control_endpoint_descriptor uvc_control_cs_ep __initdata = {
 static struct uvc_control_endpoint_descriptor uvc_control_cs_ep __initdata = {
 	.bLength		= UVC_DT_CONTROL_ENDPOINT_SIZE,
 	.bLength		= UVC_DT_CONTROL_ENDPOINT_SIZE,
 	.bDescriptorType	= USB_DT_CS_ENDPOINT,
 	.bDescriptorType	= USB_DT_CS_ENDPOINT,
 	.bDescriptorSubType	= UVC_EP_INTERRUPT,
 	.bDescriptorSubType	= UVC_EP_INTERRUPT,
-	.wMaxTransferSize	= cpu_to_le16(STATUS_BYTECOUNT),
+	.wMaxTransferSize	= cpu_to_le16(UVC_STATUS_MAX_PACKET_SIZE),
 };
 };
 
 
 static struct usb_interface_descriptor uvc_streaming_intf_alt0 __initdata = {
 static struct usb_interface_descriptor uvc_streaming_intf_alt0 __initdata = {
@@ -144,63 +147,53 @@ static struct usb_interface_descriptor uvc_streaming_intf_alt1 __initdata = {
 	.iInterface		= 0,
 	.iInterface		= 0,
 };
 };
 
 
-static struct usb_endpoint_descriptor uvc_fs_streaming_ep = {
+static struct usb_endpoint_descriptor uvc_fs_streaming_ep __initdata = {
 	.bLength		= USB_DT_ENDPOINT_SIZE,
 	.bLength		= USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType	= USB_DT_ENDPOINT,
 	.bDescriptorType	= USB_DT_ENDPOINT,
 	.bEndpointAddress	= USB_DIR_IN,
 	.bEndpointAddress	= USB_DIR_IN,
-	.bmAttributes		= USB_ENDPOINT_XFER_ISOC,
-	.wMaxPacketSize		= cpu_to_le16(512),
-	.bInterval		= 1,
+	.bmAttributes		= USB_ENDPOINT_SYNC_ASYNC
+				| USB_ENDPOINT_XFER_ISOC,
+	/* The wMaxPacketSize and bInterval values will be initialized from
+	 * module parameters.
+	 */
+	.wMaxPacketSize		= 0,
+	.bInterval		= 0,
 };
 };
 
 
-static struct usb_endpoint_descriptor uvc_hs_streaming_ep = {
+static struct usb_endpoint_descriptor uvc_hs_streaming_ep __initdata = {
 	.bLength		= USB_DT_ENDPOINT_SIZE,
 	.bLength		= USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType	= USB_DT_ENDPOINT,
 	.bDescriptorType	= USB_DT_ENDPOINT,
 	.bEndpointAddress	= USB_DIR_IN,
 	.bEndpointAddress	= USB_DIR_IN,
-	.bmAttributes		= USB_ENDPOINT_XFER_ISOC,
-	.wMaxPacketSize		= cpu_to_le16(1024),
-	.bInterval		= 1,
-};
-
-/* super speed support */
-static struct usb_endpoint_descriptor uvc_ss_control_ep __initdata = {
-	.bLength =		USB_DT_ENDPOINT_SIZE,
-	.bDescriptorType =	USB_DT_ENDPOINT,
-
-	.bEndpointAddress =	USB_DIR_IN,
-	.bmAttributes =		USB_ENDPOINT_XFER_INT,
-	.wMaxPacketSize =	cpu_to_le16(STATUS_BYTECOUNT),
-	.bInterval =		8,
-};
-
-static struct usb_ss_ep_comp_descriptor uvc_ss_control_comp __initdata = {
-	.bLength =		sizeof uvc_ss_control_comp,
-	.bDescriptorType =	USB_DT_SS_ENDPOINT_COMP,
-
-	/* the following 3 values can be tweaked if necessary */
-	/* .bMaxBurst =		0, */
-	/* .bmAttributes =	0, */
-	.wBytesPerInterval =	cpu_to_le16(STATUS_BYTECOUNT),
+	.bmAttributes		= USB_ENDPOINT_SYNC_ASYNC
+				| USB_ENDPOINT_XFER_ISOC,
+	/* The wMaxPacketSize and bInterval values will be initialized from
+	 * module parameters.
+	 */
+	.wMaxPacketSize		= 0,
+	.bInterval		= 0,
 };
 };
 
 
 static struct usb_endpoint_descriptor uvc_ss_streaming_ep __initdata = {
 static struct usb_endpoint_descriptor uvc_ss_streaming_ep __initdata = {
-	.bLength =		USB_DT_ENDPOINT_SIZE,
-	.bDescriptorType =	USB_DT_ENDPOINT,
+	.bLength		= USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType	= USB_DT_ENDPOINT,
 
 
-	.bEndpointAddress =	USB_DIR_IN,
-	.bmAttributes =		USB_ENDPOINT_XFER_ISOC,
-	.wMaxPacketSize =	cpu_to_le16(1024),
-	.bInterval =		4,
+	.bEndpointAddress	= USB_DIR_IN,
+	.bmAttributes		= USB_ENDPOINT_SYNC_ASYNC
+				| USB_ENDPOINT_XFER_ISOC,
+	/* The wMaxPacketSize and bInterval values will be initialized from
+	 * module parameters.
+	 */
+	.wMaxPacketSize		= 0,
+	.bInterval		= 0,
 };
 };
 
 
-static struct usb_ss_ep_comp_descriptor uvc_ss_streaming_comp = {
-	.bLength =		sizeof uvc_ss_streaming_comp,
-	.bDescriptorType =	USB_DT_SS_ENDPOINT_COMP,
-
-	/* the following 3 values can be tweaked if necessary */
-	.bMaxBurst =		0,
-	.bmAttributes =	0,
-	.wBytesPerInterval =	cpu_to_le16(1024),
+static struct usb_ss_ep_comp_descriptor uvc_ss_streaming_comp __initdata = {
+	.bLength		= sizeof(uvc_ss_streaming_comp),
+	.bDescriptorType	= USB_DT_SS_ENDPOINT_COMP,
+	/* The following 3 values can be tweaked if necessary. */
+	.bMaxBurst		= 0,
+	.bmAttributes		= 0,
+	.wBytesPerInterval	= cpu_to_le16(1024),
 };
 };
 
 
 static const struct usb_descriptor_header * const uvc_fs_streaming[] = {
 static const struct usb_descriptor_header * const uvc_fs_streaming[] = {
@@ -273,6 +266,13 @@ uvc_function_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
 	return 0;
 	return 0;
 }
 }
 
 
+void uvc_function_setup_continue(struct uvc_device *uvc)
+{
+	struct usb_composite_dev *cdev = uvc->func.config->cdev;
+
+	usb_composite_setup_continue(cdev);
+}
+
 static int
 static int
 uvc_function_get_alt(struct usb_function *f, unsigned interface)
 uvc_function_get_alt(struct usb_function *f, unsigned interface)
 {
 {
@@ -335,7 +335,7 @@ uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt)
 		v4l2_event_queue(uvc->vdev, &v4l2_event);
 		v4l2_event_queue(uvc->vdev, &v4l2_event);
 
 
 		uvc->state = UVC_STATE_CONNECTED;
 		uvc->state = UVC_STATE_CONNECTED;
-		break;
+		return 0;
 
 
 	case 1:
 	case 1:
 		if (uvc->state != UVC_STATE_CONNECTED)
 		if (uvc->state != UVC_STATE_CONNECTED)
@@ -352,15 +352,11 @@ uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt)
 		memset(&v4l2_event, 0, sizeof(v4l2_event));
 		memset(&v4l2_event, 0, sizeof(v4l2_event));
 		v4l2_event.type = UVC_EVENT_STREAMON;
 		v4l2_event.type = UVC_EVENT_STREAMON;
 		v4l2_event_queue(uvc->vdev, &v4l2_event);
 		v4l2_event_queue(uvc->vdev, &v4l2_event);
-
-		uvc->state = UVC_STATE_STREAMING;
-		break;
+		return USB_GADGET_DELAYED_STATUS;
 
 
 	default:
 	default:
 		return -EINVAL;
 		return -EINVAL;
 	}
 	}
-
-	return 0;
 }
 }
 
 
 static void
 static void
@@ -454,7 +450,6 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed)
 	const struct uvc_descriptor_header * const *uvc_streaming_cls;
 	const struct uvc_descriptor_header * const *uvc_streaming_cls;
 	const struct usb_descriptor_header * const *uvc_streaming_std;
 	const struct usb_descriptor_header * const *uvc_streaming_std;
 	const struct usb_descriptor_header * const *src;
 	const struct usb_descriptor_header * const *src;
-	static struct usb_endpoint_descriptor *uvc_control_ep;
 	struct usb_descriptor_header **dst;
 	struct usb_descriptor_header **dst;
 	struct usb_descriptor_header **hdr;
 	struct usb_descriptor_header **hdr;
 	unsigned int control_size;
 	unsigned int control_size;
@@ -468,14 +463,12 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed)
 		uvc_control_desc = uvc->desc.ss_control;
 		uvc_control_desc = uvc->desc.ss_control;
 		uvc_streaming_cls = uvc->desc.ss_streaming;
 		uvc_streaming_cls = uvc->desc.ss_streaming;
 		uvc_streaming_std = uvc_ss_streaming;
 		uvc_streaming_std = uvc_ss_streaming;
-		uvc_control_ep = &uvc_ss_control_ep;
 		break;
 		break;
 
 
 	case USB_SPEED_HIGH:
 	case USB_SPEED_HIGH:
 		uvc_control_desc = uvc->desc.fs_control;
 		uvc_control_desc = uvc->desc.fs_control;
 		uvc_streaming_cls = uvc->desc.hs_streaming;
 		uvc_streaming_cls = uvc->desc.hs_streaming;
 		uvc_streaming_std = uvc_hs_streaming;
 		uvc_streaming_std = uvc_hs_streaming;
-		uvc_control_ep = &uvc_fs_control_ep;
 		break;
 		break;
 
 
 	case USB_SPEED_FULL:
 	case USB_SPEED_FULL:
@@ -483,7 +476,6 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed)
 		uvc_control_desc = uvc->desc.fs_control;
 		uvc_control_desc = uvc->desc.fs_control;
 		uvc_streaming_cls = uvc->desc.fs_streaming;
 		uvc_streaming_cls = uvc->desc.fs_streaming;
 		uvc_streaming_std = uvc_fs_streaming;
 		uvc_streaming_std = uvc_fs_streaming;
-		uvc_control_ep = &uvc_fs_control_ep;
 		break;
 		break;
 	}
 	}
 
 
@@ -494,6 +486,7 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed)
 	 * Class-specific UVC control descriptors
 	 * Class-specific UVC control descriptors
 	 * uvc_control_ep
 	 * uvc_control_ep
 	 * uvc_control_cs_ep
 	 * uvc_control_cs_ep
+	 * uvc_ss_control_comp (for SS only)
 	 * uvc_streaming_intf_alt0
 	 * uvc_streaming_intf_alt0
 	 * Class-specific UVC streaming descriptors
 	 * Class-specific UVC streaming descriptors
 	 * uvc_{fs|hs}_streaming
 	 * uvc_{fs|hs}_streaming
@@ -503,7 +496,7 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed)
 	control_size = 0;
 	control_size = 0;
 	streaming_size = 0;
 	streaming_size = 0;
 	bytes = uvc_iad.bLength + uvc_control_intf.bLength
 	bytes = uvc_iad.bLength + uvc_control_intf.bLength
-	      + uvc_control_ep->bLength + uvc_control_cs_ep.bLength
+	      + uvc_control_ep.bLength + uvc_control_cs_ep.bLength
 	      + uvc_streaming_intf_alt0.bLength;
 	      + uvc_streaming_intf_alt0.bLength;
 
 
 	if (speed == USB_SPEED_SUPER) {
 	if (speed == USB_SPEED_SUPER) {
@@ -514,13 +507,13 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed)
 	}
 	}
 
 
 	for (src = (const struct usb_descriptor_header **)uvc_control_desc;
 	for (src = (const struct usb_descriptor_header **)uvc_control_desc;
-			*src; ++src) {
+	     *src; ++src) {
 		control_size += (*src)->bLength;
 		control_size += (*src)->bLength;
 		bytes += (*src)->bLength;
 		bytes += (*src)->bLength;
 		n_desc++;
 		n_desc++;
 	}
 	}
 	for (src = (const struct usb_descriptor_header **)uvc_streaming_cls;
 	for (src = (const struct usb_descriptor_header **)uvc_streaming_cls;
-			*src; ++src) {
+	     *src; ++src) {
 		streaming_size += (*src)->bLength;
 		streaming_size += (*src)->bLength;
 		bytes += (*src)->bLength;
 		bytes += (*src)->bLength;
 		n_desc++;
 		n_desc++;
@@ -549,7 +542,7 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed)
 	uvc_control_header->bInCollection = 1;
 	uvc_control_header->bInCollection = 1;
 	uvc_control_header->baInterfaceNr[0] = uvc->streaming_intf;
 	uvc_control_header->baInterfaceNr[0] = uvc->streaming_intf;
 
 
-	UVC_COPY_DESCRIPTOR(mem, dst, uvc_control_ep);
+	UVC_COPY_DESCRIPTOR(mem, dst, &uvc_control_ep);
 	if (speed == USB_SPEED_SUPER)
 	if (speed == USB_SPEED_SUPER)
 		UVC_COPY_DESCRIPTOR(mem, dst, &uvc_ss_control_comp);
 		UVC_COPY_DESCRIPTOR(mem, dst, &uvc_ss_control_comp);
 
 
@@ -560,8 +553,7 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed)
 	UVC_COPY_DESCRIPTORS(mem, dst,
 	UVC_COPY_DESCRIPTORS(mem, dst,
 		(const struct usb_descriptor_header**)uvc_streaming_cls);
 		(const struct usb_descriptor_header**)uvc_streaming_cls);
 	uvc_streaming_header->wTotalLength = cpu_to_le16(streaming_size);
 	uvc_streaming_header->wTotalLength = cpu_to_le16(streaming_size);
-	uvc_streaming_header->bEndpointAddress =
-		uvc_fs_streaming_ep.bEndpointAddress;
+	uvc_streaming_header->bEndpointAddress = uvc->video.ep->address;
 
 
 	UVC_COPY_DESCRIPTORS(mem, dst, uvc_streaming_std);
 	UVC_COPY_DESCRIPTORS(mem, dst, uvc_streaming_std);
 
 
@@ -581,7 +573,7 @@ uvc_function_unbind(struct usb_configuration *c, struct usb_function *f)
 	uvc->control_ep->driver_data = NULL;
 	uvc->control_ep->driver_data = NULL;
 	uvc->video.ep->driver_data = NULL;
 	uvc->video.ep->driver_data = NULL;
 
 
-	uvc_en_us_strings[UVC_STRING_ASSOCIATION_IDX].id = 0;
+	uvc_en_us_strings[UVC_STRING_CONTROL_IDX].id = 0;
 	usb_ep_free_request(cdev->gadget->ep0, uvc->control_req);
 	usb_ep_free_request(cdev->gadget->ep0, uvc->control_req);
 	kfree(uvc->control_buf);
 	kfree(uvc->control_buf);
 
 
@@ -595,31 +587,52 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f)
 {
 {
 	struct usb_composite_dev *cdev = c->cdev;
 	struct usb_composite_dev *cdev = c->cdev;
 	struct uvc_device *uvc = to_uvc(f);
 	struct uvc_device *uvc = to_uvc(f);
+	unsigned int max_packet_mult;
+	unsigned int max_packet_size;
 	struct usb_ep *ep;
 	struct usb_ep *ep;
 	int ret = -EINVAL;
 	int ret = -EINVAL;
 
 
 	INFO(cdev, "uvc_function_bind\n");
 	INFO(cdev, "uvc_function_bind\n");
 
 
-	/* sanity check the streaming endpoint module parameters */
-	if (streaming_interval < 1)
-		streaming_interval = 1;
-	if (streaming_interval > 16)
-		streaming_interval = 16;
-	if (streaming_mult > 2)
-		streaming_mult = 2;
-	if (streaming_maxburst > 15)
-		streaming_maxburst = 15;
-
-	/*
-	 * fill in the FS video streaming specific descriptors from the
-	 * module parameters
+	/* Sanity check the streaming endpoint module parameters.
 	 */
 	 */
-	uvc_fs_streaming_ep.wMaxPacketSize = streaming_maxpacket > 1023 ?
-						1023 : streaming_maxpacket;
+	streaming_interval = clamp(streaming_interval, 1U, 16U);
+	streaming_maxpacket = clamp(streaming_maxpacket, 1U, 3072U);
+	streaming_maxburst = min(streaming_maxburst, 15U);
+
+	/* Fill in the FS/HS/SS Video Streaming specific descriptors from the
+	 * module parameters.
+	 *
+	 * NOTE: We assume that the user knows what they are doing and won't
+	 * give parameters that their UDC doesn't support.
+	 */
+	if (streaming_maxpacket <= 1024) {
+		max_packet_mult = 1;
+		max_packet_size = streaming_maxpacket;
+	} else if (streaming_maxpacket <= 2048) {
+		max_packet_mult = 2;
+		max_packet_size = streaming_maxpacket / 2;
+	} else {
+		max_packet_mult = 3;
+		max_packet_size = streaming_maxpacket / 3;
+	}
+
+	uvc_fs_streaming_ep.wMaxPacketSize = min(streaming_maxpacket, 1023U);
 	uvc_fs_streaming_ep.bInterval = streaming_interval;
 	uvc_fs_streaming_ep.bInterval = streaming_interval;
 
 
+	uvc_hs_streaming_ep.wMaxPacketSize = max_packet_size;
+	uvc_hs_streaming_ep.wMaxPacketSize |= ((max_packet_mult - 1) << 11);
+	uvc_hs_streaming_ep.bInterval = streaming_interval;
+
+	uvc_ss_streaming_ep.wMaxPacketSize = max_packet_size;
+	uvc_ss_streaming_ep.bInterval = streaming_interval;
+	uvc_ss_streaming_comp.bmAttributes = max_packet_mult - 1;
+	uvc_ss_streaming_comp.bMaxBurst = streaming_maxburst;
+	uvc_ss_streaming_comp.wBytesPerInterval =
+		max_packet_size * max_packet_mult * streaming_maxburst;
+
 	/* Allocate endpoints. */
 	/* Allocate endpoints. */
-	ep = usb_ep_autoconfig(cdev->gadget, &uvc_fs_control_ep);
+	ep = usb_ep_autoconfig(cdev->gadget, &uvc_control_ep);
 	if (!ep) {
 	if (!ep) {
 		INFO(cdev, "Unable to allocate control EP\n");
 		INFO(cdev, "Unable to allocate control EP\n");
 		goto error;
 		goto error;
@@ -627,7 +640,14 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f)
 	uvc->control_ep = ep;
 	uvc->control_ep = ep;
 	ep->driver_data = uvc;
 	ep->driver_data = uvc;
 
 
-	ep = usb_ep_autoconfig(cdev->gadget, &uvc_fs_streaming_ep);
+	if (gadget_is_superspeed(c->cdev->gadget))
+		ep = usb_ep_autoconfig_ss(cdev->gadget, &uvc_ss_streaming_ep,
+					  &uvc_ss_streaming_comp);
+	else if (gadget_is_dualspeed(cdev->gadget))
+		ep = usb_ep_autoconfig(cdev->gadget, &uvc_hs_streaming_ep);
+	else
+		ep = usb_ep_autoconfig(cdev->gadget, &uvc_fs_streaming_ep);
+
 	if (!ep) {
 	if (!ep) {
 		INFO(cdev, "Unable to allocate streaming EP\n");
 		INFO(cdev, "Unable to allocate streaming EP\n");
 		goto error;
 		goto error;
@@ -635,6 +655,10 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f)
 	uvc->video.ep = ep;
 	uvc->video.ep = ep;
 	ep->driver_data = uvc;
 	ep->driver_data = uvc;
 
 
+	uvc_fs_streaming_ep.bEndpointAddress = uvc->video.ep->address;
+	uvc_hs_streaming_ep.bEndpointAddress = uvc->video.ep->address;
+	uvc_ss_streaming_ep.bEndpointAddress = uvc->video.ep->address;
+
 	/* Allocate interface IDs. */
 	/* Allocate interface IDs. */
 	if ((ret = usb_interface_id(c, f)) < 0)
 	if ((ret = usb_interface_id(c, f)) < 0)
 		goto error;
 		goto error;
@@ -648,37 +672,6 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f)
 	uvc_streaming_intf_alt1.bInterfaceNumber = ret;
 	uvc_streaming_intf_alt1.bInterfaceNumber = ret;
 	uvc->streaming_intf = ret;
 	uvc->streaming_intf = ret;
 
 
-	/* sanity check the streaming endpoint module parameters */
-	if (streaming_maxpacket > 1024)
-		streaming_maxpacket = 1024;
-	/*
-	 * Fill in the HS descriptors from the module parameters for the Video
-	 * Streaming endpoint.
-	 * NOTE: We assume that the user knows what they are doing and won't
-	 * give parameters that their UDC doesn't support.
-	 */
-	uvc_hs_streaming_ep.wMaxPacketSize = streaming_maxpacket;
-	uvc_hs_streaming_ep.wMaxPacketSize |= streaming_mult << 11;
-	uvc_hs_streaming_ep.bInterval = streaming_interval;
-	uvc_hs_streaming_ep.bEndpointAddress =
-		uvc_fs_streaming_ep.bEndpointAddress;
-
-	/*
-	 * Fill in the SS descriptors from the module parameters for the Video
-	 * Streaming endpoint.
-	 * NOTE: We assume that the user knows what they are doing and won't
-	 * give parameters that their UDC doesn't support.
-	 */
-	uvc_ss_streaming_ep.wMaxPacketSize = streaming_maxpacket;
-	uvc_ss_streaming_ep.bInterval = streaming_interval;
-	uvc_ss_streaming_comp.bmAttributes = streaming_mult;
-	uvc_ss_streaming_comp.bMaxBurst = streaming_maxburst;
-	uvc_ss_streaming_comp.wBytesPerInterval =
-		streaming_maxpacket * (streaming_mult + 1) *
-		(streaming_maxburst + 1);
-	uvc_ss_streaming_ep.bEndpointAddress =
-		uvc_fs_streaming_ep.bEndpointAddress;
-
 	/* Copy descriptors */
 	/* Copy descriptors */
 	f->fs_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_FULL);
 	f->fs_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_FULL);
 	if (gadget_is_dualspeed(cdev->gadget))
 	if (gadget_is_dualspeed(cdev->gadget))
@@ -775,23 +768,23 @@ uvc_bind_config(struct usb_configuration *c,
 
 
 	/* Validate the descriptors. */
 	/* Validate the descriptors. */
 	if (fs_control == NULL || fs_control[0] == NULL ||
 	if (fs_control == NULL || fs_control[0] == NULL ||
-		fs_control[0]->bDescriptorSubType != UVC_VC_HEADER)
+	    fs_control[0]->bDescriptorSubType != UVC_VC_HEADER)
 		goto error;
 		goto error;
 
 
 	if (ss_control == NULL || ss_control[0] == NULL ||
 	if (ss_control == NULL || ss_control[0] == NULL ||
-		ss_control[0]->bDescriptorSubType != UVC_VC_HEADER)
+	    ss_control[0]->bDescriptorSubType != UVC_VC_HEADER)
 		goto error;
 		goto error;
 
 
 	if (fs_streaming == NULL || fs_streaming[0] == NULL ||
 	if (fs_streaming == NULL || fs_streaming[0] == NULL ||
-		fs_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER)
+	    fs_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER)
 		goto error;
 		goto error;
 
 
 	if (hs_streaming == NULL || hs_streaming[0] == NULL ||
 	if (hs_streaming == NULL || hs_streaming[0] == NULL ||
-		hs_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER)
+	    hs_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER)
 		goto error;
 		goto error;
 
 
 	if (ss_streaming == NULL || ss_streaming[0] == NULL ||
 	if (ss_streaming == NULL || ss_streaming[0] == NULL ||
-		ss_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER)
+	    ss_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER)
 		goto error;
 		goto error;
 
 
 	uvc->desc.fs_control = fs_control;
 	uvc->desc.fs_control = fs_control;
@@ -800,13 +793,16 @@ uvc_bind_config(struct usb_configuration *c,
 	uvc->desc.hs_streaming = hs_streaming;
 	uvc->desc.hs_streaming = hs_streaming;
 	uvc->desc.ss_streaming = ss_streaming;
 	uvc->desc.ss_streaming = ss_streaming;
 
 
-	/* Allocate string descriptor numbers. */
-	if (uvc_en_us_strings[UVC_STRING_ASSOCIATION_IDX].id == 0) {
+	/* String descriptors are global, we only need to allocate string IDs
+	 * for the first UVC function. UVC functions beyond the first (if any)
+	 * will reuse the same IDs.
+	 */
+	if (uvc_en_us_strings[UVC_STRING_CONTROL_IDX].id == 0) {
 		ret = usb_string_ids_tab(c->cdev, uvc_en_us_strings);
 		ret = usb_string_ids_tab(c->cdev, uvc_en_us_strings);
 		if (ret)
 		if (ret)
 			goto error;
 			goto error;
 		uvc_iad.iFunction =
 		uvc_iad.iFunction =
-			uvc_en_us_strings[UVC_STRING_ASSOCIATION_IDX].id;
+			uvc_en_us_strings[UVC_STRING_CONTROL_IDX].id;
 		uvc_control_intf.iInterface =
 		uvc_control_intf.iInterface =
 			uvc_en_us_strings[UVC_STRING_CONTROL_IDX].id;
 			uvc_en_us_strings[UVC_STRING_CONTROL_IDX].id;
 		ret = uvc_en_us_strings[UVC_STRING_STREAMING_IDX].id;
 		ret = uvc_en_us_strings[UVC_STRING_STREAMING_IDX].id;

+ 6 - 6
drivers/usb/gadget/f_uvc.h

@@ -16,12 +16,12 @@
 #include <linux/usb/composite.h>
 #include <linux/usb/composite.h>
 #include <linux/usb/video.h>
 #include <linux/usb/video.h>
 
 
-extern int uvc_bind_config(struct usb_configuration *c,
-		   const struct uvc_descriptor_header * const *fs_control,
-		   const struct uvc_descriptor_header * const *hs_control,
-		   const struct uvc_descriptor_header * const *fs_streaming,
-		   const struct uvc_descriptor_header * const *hs_streaming,
-		   const struct uvc_descriptor_header * const *ss_streaming);
+int uvc_bind_config(struct usb_configuration *c,
+		    const struct uvc_descriptor_header * const *fs_control,
+		    const struct uvc_descriptor_header * const *hs_control,
+		    const struct uvc_descriptor_header * const *fs_streaming,
+		    const struct uvc_descriptor_header * const *hs_streaming,
+		    const struct uvc_descriptor_header * const *ss_streaming);
 
 
 #endif /* _F_UVC_H_ */
 #endif /* _F_UVC_H_ */
 
 

+ 2 - 16
drivers/usb/gadget/fsl_qe_udc.c

@@ -2296,7 +2296,6 @@ static int fsl_qe_start(struct usb_gadget *gadget,
 	driver->driver.bus = NULL;
 	driver->driver.bus = NULL;
 	/* hook up the driver */
 	/* hook up the driver */
 	udc->driver = driver;
 	udc->driver = driver;
-	udc->gadget.dev.driver = &driver->driver;
 	udc->gadget.speed = driver->max_speed;
 	udc->gadget.speed = driver->max_speed;
 
 
 	/* Enable IRQ reg and Set usbcmd reg EN bit */
 	/* Enable IRQ reg and Set usbcmd reg EN bit */
@@ -2338,7 +2337,6 @@ static int fsl_qe_stop(struct usb_gadget *gadget,
 		nuke(loop_ep, -ESHUTDOWN);
 		nuke(loop_ep, -ESHUTDOWN);
 	spin_unlock_irqrestore(&udc->lock, flags);
 	spin_unlock_irqrestore(&udc->lock, flags);
 
 
-	udc->gadget.dev.driver = NULL;
 	udc->driver = NULL;
 	udc->driver = NULL;
 
 
 	dev_info(udc->dev, "unregistered gadget driver '%s'\r\n",
 	dev_info(udc->dev, "unregistered gadget driver '%s'\r\n",
@@ -2523,12 +2521,6 @@ static int qe_udc_probe(struct platform_device *ofdev)
 
 
 	/* name: Identifies the controller hardware type. */
 	/* name: Identifies the controller hardware type. */
 	udc->gadget.name = driver_name;
 	udc->gadget.name = driver_name;
-
-	device_initialize(&udc->gadget.dev);
-
-	dev_set_name(&udc->gadget.dev, "gadget");
-
-	udc->gadget.dev.release = qe_udc_release;
 	udc->gadget.dev.parent = &ofdev->dev;
 	udc->gadget.dev.parent = &ofdev->dev;
 
 
 	/* initialize qe_ep struct */
 	/* initialize qe_ep struct */
@@ -2592,22 +2584,17 @@ static int qe_udc_probe(struct platform_device *ofdev)
 		goto err5;
 		goto err5;
 	}
 	}
 
 
-	ret = device_add(&udc->gadget.dev);
+	ret = usb_add_gadget_udc_release(&ofdev->dev, &udc->gadget,
+			qe_udc_release);
 	if (ret)
 	if (ret)
 		goto err6;
 		goto err6;
 
 
-	ret = usb_add_gadget_udc(&ofdev->dev, &udc->gadget);
-	if (ret)
-		goto err7;
-
 	dev_set_drvdata(&ofdev->dev, udc);
 	dev_set_drvdata(&ofdev->dev, udc);
 	dev_info(udc->dev,
 	dev_info(udc->dev,
 			"%s USB controller initialized as device\n",
 			"%s USB controller initialized as device\n",
 			(udc->soc_type == PORT_QE) ? "QE" : "CPM");
 			(udc->soc_type == PORT_QE) ? "QE" : "CPM");
 	return 0;
 	return 0;
 
 
-err7:
-	device_unregister(&udc->gadget.dev);
 err6:
 err6:
 	free_irq(udc->usb_irq, udc);
 	free_irq(udc->usb_irq, udc);
 err5:
 err5:
@@ -2702,7 +2689,6 @@ static int qe_udc_remove(struct platform_device *ofdev)
 
 
 	iounmap(udc->usb_regs);
 	iounmap(udc->usb_regs);
 
 
-	device_unregister(&udc->gadget.dev);
 	/* wait for release() of gadget.dev to free udc */
 	/* wait for release() of gadget.dev to free udc */
 	wait_for_completion(&done);
 	wait_for_completion(&done);
 
 

+ 17 - 66
drivers/usb/gadget/fsl_udc_core.c

@@ -185,20 +185,7 @@ static void done(struct fsl_ep *ep, struct fsl_req *req, int status)
 		dma_pool_free(udc->td_pool, curr_td, curr_td->td_dma);
 		dma_pool_free(udc->td_pool, curr_td, curr_td->td_dma);
 	}
 	}
 
 
-	if (req->mapped) {
-		dma_unmap_single(ep->udc->gadget.dev.parent,
-			req->req.dma, req->req.length,
-			ep_is_in(ep)
-				? DMA_TO_DEVICE
-				: DMA_FROM_DEVICE);
-		req->req.dma = DMA_ADDR_INVALID;
-		req->mapped = 0;
-	} else
-		dma_sync_single_for_cpu(ep->udc->gadget.dev.parent,
-			req->req.dma, req->req.length,
-			ep_is_in(ep)
-				? DMA_TO_DEVICE
-				: DMA_FROM_DEVICE);
+	usb_gadget_unmap_request(&ep->udc->gadget, &req->req, ep_is_in(ep));
 
 
 	if (status && (status != -ESHUTDOWN))
 	if (status && (status != -ESHUTDOWN))
 		VDBG("complete %s req %p stat %d len %u/%u",
 		VDBG("complete %s req %p stat %d len %u/%u",
@@ -888,6 +875,7 @@ fsl_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
 	struct fsl_req *req = container_of(_req, struct fsl_req, req);
 	struct fsl_req *req = container_of(_req, struct fsl_req, req);
 	struct fsl_udc *udc;
 	struct fsl_udc *udc;
 	unsigned long flags;
 	unsigned long flags;
+	int ret;
 
 
 	/* catch various bogus parameters */
 	/* catch various bogus parameters */
 	if (!_req || !req->req.complete || !req->req.buf
 	if (!_req || !req->req.complete || !req->req.buf
@@ -910,22 +898,9 @@ fsl_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
 
 
 	req->ep = ep;
 	req->ep = ep;
 
 
-	/* map virtual address to hardware */
-	if (req->req.dma == DMA_ADDR_INVALID) {
-		req->req.dma = dma_map_single(ep->udc->gadget.dev.parent,
-					req->req.buf,
-					req->req.length, ep_is_in(ep)
-						? DMA_TO_DEVICE
-						: DMA_FROM_DEVICE);
-		req->mapped = 1;
-	} else {
-		dma_sync_single_for_device(ep->udc->gadget.dev.parent,
-					req->req.dma, req->req.length,
-					ep_is_in(ep)
-						? DMA_TO_DEVICE
-						: DMA_FROM_DEVICE);
-		req->mapped = 0;
-	}
+	ret = usb_gadget_map_request(&ep->udc->gadget, &req->req, ep_is_in(ep));
+	if (ret)
+		return ret;
 
 
 	req->req.status = -EINPROGRESS;
 	req->req.status = -EINPROGRESS;
 	req->req.actual = 0;
 	req->req.actual = 0;
@@ -1290,6 +1265,7 @@ static int ep0_prime_status(struct fsl_udc *udc, int direction)
 {
 {
 	struct fsl_req *req = udc->status_req;
 	struct fsl_req *req = udc->status_req;
 	struct fsl_ep *ep;
 	struct fsl_ep *ep;
+	int ret;
 
 
 	if (direction == EP_DIR_IN)
 	if (direction == EP_DIR_IN)
 		udc->ep0_dir = USB_DIR_IN;
 		udc->ep0_dir = USB_DIR_IN;
@@ -1307,10 +1283,9 @@ static int ep0_prime_status(struct fsl_udc *udc, int direction)
 	req->req.complete = NULL;
 	req->req.complete = NULL;
 	req->dtd_count = 0;
 	req->dtd_count = 0;
 
 
-	req->req.dma = dma_map_single(ep->udc->gadget.dev.parent,
-			req->req.buf, req->req.length,
-			ep_is_in(ep) ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
-	req->mapped = 1;
+	ret = usb_gadget_map_request(&ep->udc->gadget, &req->req, ep_is_in(ep));
+	if (ret)
+		return ret;
 
 
 	if (fsl_req_to_dtd(req, GFP_ATOMIC) == 0)
 	if (fsl_req_to_dtd(req, GFP_ATOMIC) == 0)
 		fsl_queue_td(ep, req);
 		fsl_queue_td(ep, req);
@@ -1353,6 +1328,7 @@ static void ch9getstatus(struct fsl_udc *udc, u8 request_type, u16 value,
 	u16 tmp = 0;		/* Status, cpu endian */
 	u16 tmp = 0;		/* Status, cpu endian */
 	struct fsl_req *req;
 	struct fsl_req *req;
 	struct fsl_ep *ep;
 	struct fsl_ep *ep;
+	int ret;
 
 
 	ep = &udc->eps[0];
 	ep = &udc->eps[0];
 
 
@@ -1390,10 +1366,9 @@ static void ch9getstatus(struct fsl_udc *udc, u8 request_type, u16 value,
 	req->req.complete = NULL;
 	req->req.complete = NULL;
 	req->dtd_count = 0;
 	req->dtd_count = 0;
 
 
-	req->req.dma = dma_map_single(ep->udc->gadget.dev.parent,
-				req->req.buf, req->req.length,
-				ep_is_in(ep) ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
-	req->mapped = 1;
+	ret = usb_gadget_map_request(&ep->udc->gadget, &req->req, ep_is_in(ep));
+	if (ret)
+		goto stall;
 
 
 	/* prime the data phase */
 	/* prime the data phase */
 	if ((fsl_req_to_dtd(req, GFP_ATOMIC) == 0))
 	if ((fsl_req_to_dtd(req, GFP_ATOMIC) == 0))
@@ -1964,7 +1939,6 @@ static int fsl_udc_start(struct usb_gadget *g,
 	driver->driver.bus = NULL;
 	driver->driver.bus = NULL;
 	/* hook up the driver */
 	/* hook up the driver */
 	udc_controller->driver = driver;
 	udc_controller->driver = driver;
-	udc_controller->gadget.dev.driver = &driver->driver;
 	spin_unlock_irqrestore(&udc_controller->lock, flags);
 	spin_unlock_irqrestore(&udc_controller->lock, flags);
 
 
 	if (!IS_ERR_OR_NULL(udc_controller->transceiver)) {
 	if (!IS_ERR_OR_NULL(udc_controller->transceiver)) {
@@ -1980,7 +1954,6 @@ static int fsl_udc_start(struct usb_gadget *g,
 			if (retval < 0) {
 			if (retval < 0) {
 				ERR("can't bind to transceiver\n");
 				ERR("can't bind to transceiver\n");
 				driver->unbind(&udc_controller->gadget);
 				driver->unbind(&udc_controller->gadget);
-				udc_controller->gadget.dev.driver = 0;
 				udc_controller->driver = 0;
 				udc_controller->driver = 0;
 				return retval;
 				return retval;
 			}
 			}
@@ -2023,7 +1996,6 @@ static int fsl_udc_stop(struct usb_gadget *g,
 		nuke(loop_ep, -ESHUTDOWN);
 		nuke(loop_ep, -ESHUTDOWN);
 	spin_unlock_irqrestore(&udc_controller->lock, flags);
 	spin_unlock_irqrestore(&udc_controller->lock, flags);
 
 
-	udc_controller->gadget.dev.driver = NULL;
 	udc_controller->driver = NULL;
 	udc_controller->driver = NULL;
 
 
 	return 0;
 	return 0;
@@ -2521,12 +2493,7 @@ static int __init fsl_udc_probe(struct platform_device *pdev)
 
 
 	/* Setup gadget.dev and register with kernel */
 	/* Setup gadget.dev and register with kernel */
 	dev_set_name(&udc_controller->gadget.dev, "gadget");
 	dev_set_name(&udc_controller->gadget.dev, "gadget");
-	udc_controller->gadget.dev.release = fsl_udc_release;
-	udc_controller->gadget.dev.parent = &pdev->dev;
 	udc_controller->gadget.dev.of_node = pdev->dev.of_node;
 	udc_controller->gadget.dev.of_node = pdev->dev.of_node;
-	ret = device_register(&udc_controller->gadget.dev);
-	if (ret < 0)
-		goto err_free_irq;
 
 
 	if (!IS_ERR_OR_NULL(udc_controller->transceiver))
 	if (!IS_ERR_OR_NULL(udc_controller->transceiver))
 		udc_controller->gadget.is_otg = 1;
 		udc_controller->gadget.is_otg = 1;
@@ -2559,10 +2526,11 @@ static int __init fsl_udc_probe(struct platform_device *pdev)
 			DTD_ALIGNMENT, UDC_DMA_BOUNDARY);
 			DTD_ALIGNMENT, UDC_DMA_BOUNDARY);
 	if (udc_controller->td_pool == NULL) {
 	if (udc_controller->td_pool == NULL) {
 		ret = -ENOMEM;
 		ret = -ENOMEM;
-		goto err_unregister;
+		goto err_free_irq;
 	}
 	}
 
 
-	ret = usb_add_gadget_udc(&pdev->dev, &udc_controller->gadget);
+	ret = usb_add_gadget_udc_release(&pdev->dev, &udc_controller->gadget,
+			fsl_udc_release);
 	if (ret)
 	if (ret)
 		goto err_del_udc;
 		goto err_del_udc;
 
 
@@ -2571,8 +2539,6 @@ static int __init fsl_udc_probe(struct platform_device *pdev)
 
 
 err_del_udc:
 err_del_udc:
 	dma_pool_destroy(udc_controller->td_pool);
 	dma_pool_destroy(udc_controller->td_pool);
-err_unregister:
-	device_unregister(&udc_controller->gadget.dev);
 err_free_irq:
 err_free_irq:
 	free_irq(udc_controller->irq, udc_controller);
 	free_irq(udc_controller->irq, udc_controller);
 err_iounmap:
 err_iounmap:
@@ -2622,7 +2588,6 @@ static int __exit fsl_udc_remove(struct platform_device *pdev)
 	if (pdata->operating_mode == FSL_USB2_DR_DEVICE)
 	if (pdata->operating_mode == FSL_USB2_DR_DEVICE)
 		release_mem_region(res->start, resource_size(res));
 		release_mem_region(res->start, resource_size(res));
 
 
-	device_unregister(&udc_controller->gadget.dev);
 	/* free udc --wait for the release() finished */
 	/* free udc --wait for the release() finished */
 	wait_for_completion(&done);
 	wait_for_completion(&done);
 
 
@@ -2747,21 +2712,7 @@ static struct platform_driver udc_driver = {
 	},
 	},
 };
 };
 
 
-static int __init udc_init(void)
-{
-	printk(KERN_INFO "%s (%s)\n", driver_desc, DRIVER_VERSION);
-	return platform_driver_probe(&udc_driver, fsl_udc_probe);
-}
-
-module_init(udc_init);
-
-static void __exit udc_exit(void)
-{
-	platform_driver_unregister(&udc_driver);
-	printk(KERN_WARNING "%s unregistered\n", driver_desc);
-}
-
-module_exit(udc_exit);
+module_platform_driver_probe(udc_driver, fsl_udc_probe);
 
 
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_AUTHOR(DRIVER_AUTHOR);

+ 14 - 32
drivers/usb/gadget/fusb300_udc.c

@@ -394,7 +394,7 @@ static void fusb300_clear_epnstall(struct fusb300 *fusb300, u8 ep)
 
 
 	if (reg & FUSB300_EPSET0_STL) {
 	if (reg & FUSB300_EPSET0_STL) {
 		printk(KERN_DEBUG "EP%d stall... Clear!!\n", ep);
 		printk(KERN_DEBUG "EP%d stall... Clear!!\n", ep);
-		reg &= ~FUSB300_EPSET0_STL;
+		reg |= FUSB300_EPSET0_STL_CLR;
 		iowrite32(reg, fusb300->reg + FUSB300_OFFSET_EPSET0(ep));
 		iowrite32(reg, fusb300->reg + FUSB300_OFFSET_EPSET0(ep));
 	}
 	}
 }
 }
@@ -930,33 +930,33 @@ static void fusb300_wait_idma_finished(struct fusb300_ep *ep)
 
 
 	fusb300_clear_int(ep->fusb300, FUSB300_OFFSET_IGR0,
 	fusb300_clear_int(ep->fusb300, FUSB300_OFFSET_IGR0,
 		FUSB300_IGR0_EPn_PRD_INT(ep->epnum));
 		FUSB300_IGR0_EPn_PRD_INT(ep->epnum));
+	return;
+
 IDMA_RESET:
 IDMA_RESET:
-	fusb300_clear_int(ep->fusb300, FUSB300_OFFSET_IGER0,
-		FUSB300_IGER0_EEPn_PRD_INT(ep->epnum));
+	reg = ioread32(ep->fusb300->reg + FUSB300_OFFSET_IGER0);
+	reg &= ~FUSB300_IGER0_EEPn_PRD_INT(ep->epnum);
+	iowrite32(reg, ep->fusb300->reg + FUSB300_OFFSET_IGER0);
 }
 }
 
 
-static void  fusb300_set_idma(struct fusb300_ep *ep,
+static void fusb300_set_idma(struct fusb300_ep *ep,
 			struct fusb300_request *req)
 			struct fusb300_request *req)
 {
 {
-	dma_addr_t d;
-
-	d = dma_map_single(NULL, req->req.buf, req->req.length, DMA_TO_DEVICE);
+	int ret;
 
 
-	if (dma_mapping_error(NULL, d)) {
-		printk(KERN_DEBUG "dma_mapping_error\n");
+	ret = usb_gadget_map_request(&ep->fusb300->gadget,
+			&req->req, DMA_TO_DEVICE);
+	if (ret)
 		return;
 		return;
-	}
-
-	dma_sync_single_for_device(NULL, d, req->req.length, DMA_TO_DEVICE);
 
 
 	fusb300_enable_bit(ep->fusb300, FUSB300_OFFSET_IGER0,
 	fusb300_enable_bit(ep->fusb300, FUSB300_OFFSET_IGER0,
 		FUSB300_IGER0_EEPn_PRD_INT(ep->epnum));
 		FUSB300_IGER0_EEPn_PRD_INT(ep->epnum));
 
 
-	fusb300_fill_idma_prdtbl(ep, d, req->req.length);
+	fusb300_fill_idma_prdtbl(ep, req->req.dma, req->req.length);
 	/* check idma is done */
 	/* check idma is done */
 	fusb300_wait_idma_finished(ep);
 	fusb300_wait_idma_finished(ep);
 
 
-	dma_unmap_single(NULL, d, req->req.length, DMA_TO_DEVICE);
+	usb_gadget_unmap_request(&ep->fusb300->gadget,
+			&req->req, DMA_TO_DEVICE);
 }
 }
 
 
 static void in_ep_fifo_handler(struct fusb300_ep *ep)
 static void in_ep_fifo_handler(struct fusb300_ep *ep)
@@ -1316,7 +1316,6 @@ static int fusb300_udc_start(struct usb_gadget *g,
 	/* hook up the driver */
 	/* hook up the driver */
 	driver->driver.bus = NULL;
 	driver->driver.bus = NULL;
 	fusb300->driver = driver;
 	fusb300->driver = driver;
-	fusb300->gadget.dev.driver = &driver->driver;
 
 
 	return 0;
 	return 0;
 }
 }
@@ -1327,7 +1326,6 @@ static int fusb300_udc_stop(struct usb_gadget *g,
 	struct fusb300 *fusb300 = to_fusb300(g);
 	struct fusb300 *fusb300 = to_fusb300(g);
 
 
 	driver->unbind(&fusb300->gadget);
 	driver->unbind(&fusb300->gadget);
-	fusb300->gadget.dev.driver = NULL;
 
 
 	init_controller(fusb300);
 	init_controller(fusb300);
 	fusb300->driver = NULL;
 	fusb300->driver = NULL;
@@ -1422,14 +1420,7 @@ static int __init fusb300_probe(struct platform_device *pdev)
 
 
 	fusb300->gadget.ops = &fusb300_gadget_ops;
 	fusb300->gadget.ops = &fusb300_gadget_ops;
 
 
-	device_initialize(&fusb300->gadget.dev);
-
-	dev_set_name(&fusb300->gadget.dev, "gadget");
-
 	fusb300->gadget.max_speed = USB_SPEED_HIGH;
 	fusb300->gadget.max_speed = USB_SPEED_HIGH;
-	fusb300->gadget.dev.parent = &pdev->dev;
-	fusb300->gadget.dev.dma_mask = pdev->dev.dma_mask;
-	fusb300->gadget.dev.release = pdev->dev.release;
 	fusb300->gadget.name = udc_name;
 	fusb300->gadget.name = udc_name;
 	fusb300->reg = reg;
 	fusb300->reg = reg;
 
 
@@ -1478,19 +1469,10 @@ static int __init fusb300_probe(struct platform_device *pdev)
 	if (ret)
 	if (ret)
 		goto err_add_udc;
 		goto err_add_udc;
 
 
-	ret = device_add(&fusb300->gadget.dev);
-	if (ret) {
-		pr_err("device_add error (%d)\n", ret);
-		goto err_add_device;
-	}
-
 	dev_info(&pdev->dev, "version %s\n", DRIVER_VERSION);
 	dev_info(&pdev->dev, "version %s\n", DRIVER_VERSION);
 
 
 	return 0;
 	return 0;
 
 
-err_add_device:
-	usb_del_gadget_udc(&fusb300->gadget);
-
 err_add_udc:
 err_add_udc:
 	fusb300_free_request(&fusb300->ep[0]->ep, fusb300->ep0_req);
 	fusb300_free_request(&fusb300->ep[0]->ep, fusb300->ep0_req);
 
 

+ 1 - 1
drivers/usb/gadget/fusb300_udc.h

@@ -111,8 +111,8 @@
 /*
 /*
  * * EPn Setting 0 (EPn_SET0, offset = 020H+(n-1)*30H, n=1~15 )
  * * EPn Setting 0 (EPn_SET0, offset = 020H+(n-1)*30H, n=1~15 )
  * */
  * */
+#define FUSB300_EPSET0_STL_CLR		(1 << 3)
 #define FUSB300_EPSET0_CLRSEQNUM	(1 << 2)
 #define FUSB300_EPSET0_CLRSEQNUM	(1 << 2)
-#define FUSB300_EPSET0_EPn_TX0BYTE	(1 << 1)
 #define FUSB300_EPSET0_STL		(1 << 0)
 #define FUSB300_EPSET0_STL		(1 << 0)
 
 
 /*
 /*

+ 21 - 14
drivers/usb/gadget/g_ffs.c

@@ -13,7 +13,6 @@
 #define pr_fmt(fmt) "g_ffs: " fmt
 #define pr_fmt(fmt) "g_ffs: " fmt
 
 
 #include <linux/module.h>
 #include <linux/module.h>
-
 /*
 /*
  * kbuild is not very cooperative with respect to linking separately
  * kbuild is not very cooperative with respect to linking separately
  * compiled library objects into one module.  So for now we won't use
  * compiled library objects into one module.  So for now we won't use
@@ -38,13 +37,16 @@
 #  include "u_ether.c"
 #  include "u_ether.c"
 
 
 static u8 gfs_hostaddr[ETH_ALEN];
 static u8 gfs_hostaddr[ETH_ALEN];
+static struct eth_dev *the_dev;
 #  ifdef CONFIG_USB_FUNCTIONFS_ETH
 #  ifdef CONFIG_USB_FUNCTIONFS_ETH
-static int eth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]);
+static int eth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
+		struct eth_dev *dev);
 #  endif
 #  endif
 #else
 #else
-#  define gether_cleanup() do { } while (0)
-#  define gether_setup(gadget, hostaddr)   ((int)0)
+#  define the_dev	NULL
+#  define gether_cleanup(dev) do { } while (0)
 #  define gfs_hostaddr NULL
 #  define gfs_hostaddr NULL
+struct eth_dev;
 #endif
 #endif
 
 
 #include "f_fs.c"
 #include "f_fs.c"
@@ -137,7 +139,8 @@ static struct usb_gadget_strings *gfs_dev_strings[] = {
 
 
 struct gfs_configuration {
 struct gfs_configuration {
 	struct usb_configuration c;
 	struct usb_configuration c;
-	int (*eth)(struct usb_configuration *c, u8 *ethaddr);
+	int (*eth)(struct usb_configuration *c, u8 *ethaddr,
+			struct eth_dev *dev);
 } gfs_configurations[] = {
 } gfs_configurations[] = {
 #ifdef CONFIG_USB_FUNCTIONFS_RNDIS
 #ifdef CONFIG_USB_FUNCTIONFS_RNDIS
 	{
 	{
@@ -346,10 +349,13 @@ static int gfs_bind(struct usb_composite_dev *cdev)
 
 
 	if (missing_funcs)
 	if (missing_funcs)
 		return -ENODEV;
 		return -ENODEV;
-
-	ret = gether_setup(cdev->gadget, gfs_hostaddr);
-	if (unlikely(ret < 0))
+#if defined CONFIG_USB_FUNCTIONFS_ETH || defined CONFIG_USB_FUNCTIONFS_RNDIS
+	the_dev = gether_setup(cdev->gadget, gfs_hostaddr);
+#endif
+	if (IS_ERR(the_dev)) {
+		ret = PTR_ERR(the_dev);
 		goto error_quick;
 		goto error_quick;
+	}
 	gfs_ether_setup = true;
 	gfs_ether_setup = true;
 
 
 	ret = usb_string_ids_tab(cdev, gfs_strings);
 	ret = usb_string_ids_tab(cdev, gfs_strings);
@@ -386,7 +392,7 @@ error_unbind:
 	for (i = 0; i < func_num; i++)
 	for (i = 0; i < func_num; i++)
 		functionfs_unbind(ffs_tab[i].ffs_data);
 		functionfs_unbind(ffs_tab[i].ffs_data);
 error:
 error:
-	gether_cleanup();
+	gether_cleanup(the_dev);
 error_quick:
 error_quick:
 	gfs_ether_setup = false;
 	gfs_ether_setup = false;
 	return ret;
 	return ret;
@@ -410,7 +416,7 @@ static int gfs_unbind(struct usb_composite_dev *cdev)
 	 * do...?
 	 * do...?
 	 */
 	 */
 	if (gfs_ether_setup)
 	if (gfs_ether_setup)
-		gether_cleanup();
+		gether_cleanup(the_dev);
 	gfs_ether_setup = false;
 	gfs_ether_setup = false;
 
 
 	for (i = func_num; i--; )
 	for (i = func_num; i--; )
@@ -440,7 +446,7 @@ static int gfs_do_config(struct usb_configuration *c)
 	}
 	}
 
 
 	if (gc->eth) {
 	if (gc->eth) {
-		ret = gc->eth(c, gfs_hostaddr);
+		ret = gc->eth(c, gfs_hostaddr, the_dev);
 		if (unlikely(ret < 0))
 		if (unlikely(ret < 0))
 			return ret;
 			return ret;
 	}
 	}
@@ -469,11 +475,12 @@ static int gfs_do_config(struct usb_configuration *c)
 
 
 #ifdef CONFIG_USB_FUNCTIONFS_ETH
 #ifdef CONFIG_USB_FUNCTIONFS_ETH
 
 
-static int eth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
+static int eth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
+		struct eth_dev *dev)
 {
 {
 	return can_support_ecm(c->cdev->gadget)
 	return can_support_ecm(c->cdev->gadget)
-		? ecm_bind_config(c, ethaddr)
-		: geth_bind_config(c, ethaddr);
+		? ecm_bind_config(c, ethaddr, dev)
+		: geth_bind_config(c, ethaddr, dev);
 }
 }
 
 
 #endif
 #endif

+ 2 - 18
drivers/usb/gadget/goku_udc.c

@@ -51,8 +51,6 @@
 #define	DRIVER_DESC		"TC86C001 USB Device Controller"
 #define	DRIVER_DESC		"TC86C001 USB Device Controller"
 #define	DRIVER_VERSION		"30-Oct 2003"
 #define	DRIVER_VERSION		"30-Oct 2003"
 
 
-#define	DMA_ADDR_INVALID	(~(dma_addr_t)0)
-
 static const char driver_name [] = "goku_udc";
 static const char driver_name [] = "goku_udc";
 static const char driver_desc [] = DRIVER_DESC;
 static const char driver_desc [] = DRIVER_DESC;
 
 
@@ -275,7 +273,6 @@ goku_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags)
 	if (!req)
 	if (!req)
 		return NULL;
 		return NULL;
 
 
-	req->req.dma = DMA_ADDR_INVALID;
 	INIT_LIST_HEAD(&req->queue);
 	INIT_LIST_HEAD(&req->queue);
 	return &req->req;
 	return &req->req;
 }
 }
@@ -1354,7 +1351,6 @@ static int goku_udc_start(struct usb_gadget *g,
 	/* hook up the driver */
 	/* hook up the driver */
 	driver->driver.bus = NULL;
 	driver->driver.bus = NULL;
 	dev->driver = driver;
 	dev->driver = driver;
-	dev->gadget.dev.driver = &driver->driver;
 
 
 	/*
 	/*
 	 * then enable host detection and ep0; and we're ready
 	 * then enable host detection and ep0; and we're ready
@@ -1394,7 +1390,6 @@ static int goku_udc_stop(struct usb_gadget *g,
 	dev->driver = NULL;
 	dev->driver = NULL;
 	stop_activity(dev, driver);
 	stop_activity(dev, driver);
 	spin_unlock_irqrestore(&dev->lock, flags);
 	spin_unlock_irqrestore(&dev->lock, flags);
-	dev->gadget.dev.driver = NULL;
 
 
 	return 0;
 	return 0;
 }
 }
@@ -1716,8 +1711,6 @@ static void goku_remove(struct pci_dev *pdev)
 				pci_resource_len (pdev, 0));
 				pci_resource_len (pdev, 0));
 	if (dev->enabled)
 	if (dev->enabled)
 		pci_disable_device(pdev);
 		pci_disable_device(pdev);
-	if (dev->registered)
-		device_unregister(&dev->gadget.dev);
 
 
 	pci_set_drvdata(pdev, NULL);
 	pci_set_drvdata(pdev, NULL);
 	dev->regs = NULL;
 	dev->regs = NULL;
@@ -1756,10 +1749,6 @@ static int goku_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 	dev->gadget.max_speed = USB_SPEED_FULL;
 	dev->gadget.max_speed = USB_SPEED_FULL;
 
 
 	/* the "gadget" abstracts/virtualizes the controller */
 	/* the "gadget" abstracts/virtualizes the controller */
-	dev_set_name(&dev->gadget.dev, "gadget");
-	dev->gadget.dev.parent = &pdev->dev;
-	dev->gadget.dev.dma_mask = pdev->dev.dma_mask;
-	dev->gadget.dev.release = gadget_release;
 	dev->gadget.name = driver_name;
 	dev->gadget.name = driver_name;
 
 
 	/* now all the pci goodies ... */
 	/* now all the pci goodies ... */
@@ -1810,13 +1799,8 @@ static int goku_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 	create_proc_read_entry(proc_node_name, 0, NULL, udc_proc_read, dev);
 	create_proc_read_entry(proc_node_name, 0, NULL, udc_proc_read, dev);
 #endif
 #endif
 
 
-	retval = device_register(&dev->gadget.dev);
-	if (retval) {
-		put_device(&dev->gadget.dev);
-		goto err;
-	}
-	dev->registered = 1;
-	retval = usb_add_gadget_udc(&pdev->dev, &dev->gadget);
+	retval = usb_add_gadget_udc_release(&pdev->dev, &dev->gadget,
+			gadget_release);
 	if (retval)
 	if (retval)
 		goto err;
 		goto err;
 
 

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

@@ -250,8 +250,7 @@ struct goku_udc {
 					got_region:1,
 					got_region:1,
 					req_config:1,
 					req_config:1,
 					configured:1,
 					configured:1,
-					enabled:1,
-					registered:1;
+					enabled:1;
 
 
 	/* pci state used to access those endpoints */
 	/* pci state used to access those endpoints */
 	struct pci_dev			*pdev;
 	struct pci_dev			*pdev;

+ 1 - 15
drivers/usb/gadget/imx_udc.c

@@ -1338,7 +1338,6 @@ static int imx_udc_start(struct usb_gadget *gadget,
 	imx_usb = container_of(gadget, struct imx_udc_struct, gadget);
 	imx_usb = container_of(gadget, struct imx_udc_struct, gadget);
 	/* first hook up the driver ... */
 	/* first hook up the driver ... */
 	imx_usb->driver = driver;
 	imx_usb->driver = driver;
-	imx_usb->gadget.dev.driver = &driver->driver;
 
 
 	D_INI(imx_usb->dev, "<%s> registered gadget driver '%s'\n",
 	D_INI(imx_usb->dev, "<%s> registered gadget driver '%s'\n",
 		__func__, driver->driver.name);
 		__func__, driver->driver.name);
@@ -1358,7 +1357,6 @@ static int imx_udc_stop(struct usb_gadget *gadget,
 	imx_udc_disable(imx_usb);
 	imx_udc_disable(imx_usb);
 	del_timer(&imx_usb->timer);
 	del_timer(&imx_usb->timer);
 
 
-	imx_usb->gadget.dev.driver = NULL;
 	imx_usb->driver = NULL;
 	imx_usb->driver = NULL;
 
 
 	D_INI(imx_usb->dev, "<%s> unregistered gadget driver '%s'\n",
 	D_INI(imx_usb->dev, "<%s> unregistered gadget driver '%s'\n",
@@ -1461,15 +1459,6 @@ static int __init imx_udc_probe(struct platform_device *pdev)
 	imx_usb->clk = clk;
 	imx_usb->clk = clk;
 	imx_usb->dev = &pdev->dev;
 	imx_usb->dev = &pdev->dev;
 
 
-	device_initialize(&imx_usb->gadget.dev);
-
-	imx_usb->gadget.dev.parent = &pdev->dev;
-	imx_usb->gadget.dev.dma_mask = pdev->dev.dma_mask;
-
-	ret = device_add(&imx_usb->gadget.dev);
-	if (retval)
-		goto fail4;
-
 	platform_set_drvdata(pdev, imx_usb);
 	platform_set_drvdata(pdev, imx_usb);
 
 
 	usb_init_data(imx_usb);
 	usb_init_data(imx_usb);
@@ -1481,11 +1470,9 @@ static int __init imx_udc_probe(struct platform_device *pdev)
 
 
 	ret = usb_add_gadget_udc(&pdev->dev, &imx_usb->gadget);
 	ret = usb_add_gadget_udc(&pdev->dev, &imx_usb->gadget);
 	if (ret)
 	if (ret)
-		goto fail5;
+		goto fail4;
 
 
 	return 0;
 	return 0;
-fail5:
-	device_unregister(&imx_usb->gadget.dev);
 fail4:
 fail4:
 	for (i = 0; i < IMX_USB_NB_EP + 1; i++)
 	for (i = 0; i < IMX_USB_NB_EP + 1; i++)
 		free_irq(imx_usb->usbd_int[i], imx_usb);
 		free_irq(imx_usb->usbd_int[i], imx_usb);
@@ -1509,7 +1496,6 @@ static int __exit imx_udc_remove(struct platform_device *pdev)
 	int i;
 	int i;
 
 
 	usb_del_gadget_udc(&imx_usb->gadget);
 	usb_del_gadget_udc(&imx_usb->gadget);
-	device_unregister(&imx_usb->gadget.dev);
 	imx_udc_disable(imx_usb);
 	imx_udc_disable(imx_usb);
 	del_timer(&imx_usb->timer);
 	del_timer(&imx_usb->timer);
 
 

+ 4 - 47
drivers/usb/gadget/lpc32xx_udc.c

@@ -1469,23 +1469,7 @@ static void done(struct lpc32xx_ep *ep, struct lpc32xx_request *req, int status)
 		status = req->req.status;
 		status = req->req.status;
 
 
 	if (ep->lep) {
 	if (ep->lep) {
-		enum dma_data_direction direction;
-
-		if (ep->is_in)
-			direction = DMA_TO_DEVICE;
-		else
-			direction = DMA_FROM_DEVICE;
-
-		if (req->mapped) {
-			dma_unmap_single(ep->udc->gadget.dev.parent,
-					req->req.dma, req->req.length,
-					direction);
-			req->req.dma = 0;
-			req->mapped = 0;
-		} else
-			dma_sync_single_for_cpu(ep->udc->gadget.dev.parent,
-						req->req.dma, req->req.length,
-						direction);
+		usb_gadget_unmap_request(&udc->gadget, &req->req, ep->is_in);
 
 
 		/* Free DDs */
 		/* Free DDs */
 		udc_dd_free(udc, req->dd_desc_ptr);
 		udc_dd_free(udc, req->dd_desc_ptr);
@@ -1841,26 +1825,11 @@ static int lpc32xx_ep_queue(struct usb_ep *_ep,
 	}
 	}
 
 
 	if (ep->lep) {
 	if (ep->lep) {
-		enum dma_data_direction direction;
 		struct lpc32xx_usbd_dd_gad *dd;
 		struct lpc32xx_usbd_dd_gad *dd;
 
 
-		/* Map DMA pointer */
-		if (ep->is_in)
-			direction = DMA_TO_DEVICE;
-		else
-			direction = DMA_FROM_DEVICE;
-
-		if (req->req.dma == 0) {
-			req->req.dma = dma_map_single(
-				ep->udc->gadget.dev.parent,
-				req->req.buf, req->req.length, direction);
-			req->mapped = 1;
-		} else {
-			dma_sync_single_for_device(
-				ep->udc->gadget.dev.parent, req->req.dma,
-				req->req.length, direction);
-			req->mapped = 0;
-		}
+		status = usb_gadget_map_request(&udc->gadget, _req, ep->is_in);
+		if (status)
+			return status;
 
 
 		/* For the request, build a list of DDs */
 		/* For the request, build a list of DDs */
 		dd = udc_dd_alloc(udc);
 		dd = udc_dd_alloc(udc);
@@ -2977,7 +2946,6 @@ static int lpc32xx_start(struct usb_gadget *gadget,
 	}
 	}
 
 
 	udc->driver = driver;
 	udc->driver = driver;
-	udc->gadget.dev.driver = &driver->driver;
 	udc->gadget.dev.of_node = udc->dev->of_node;
 	udc->gadget.dev.of_node = udc->dev->of_node;
 	udc->enabled = 1;
 	udc->enabled = 1;
 	udc->selfpowered = 1;
 	udc->selfpowered = 1;
@@ -3026,7 +2994,6 @@ static int lpc32xx_stop(struct usb_gadget *gadget,
 	}
 	}
 
 
 	udc->enabled = 0;
 	udc->enabled = 0;
-	udc->gadget.dev.driver = NULL;
 	udc->driver = NULL;
 	udc->driver = NULL;
 
 
 	return 0;
 	return 0;
@@ -3248,12 +3215,6 @@ static int __init lpc32xx_udc_probe(struct platform_device *pdev)
 	udc_disable(udc);
 	udc_disable(udc);
 	udc_reinit(udc);
 	udc_reinit(udc);
 
 
-	retval = device_register(&udc->gadget.dev);
-	if (retval < 0) {
-		dev_err(udc->dev, "Device registration failure\n");
-		goto dev_register_fail;
-	}
-
 	/* Request IRQs - low and high priority USB device IRQs are routed to
 	/* Request IRQs - low and high priority USB device IRQs are routed to
 	 * the same handler, while the DMA interrupt is routed elsewhere */
 	 * the same handler, while the DMA interrupt is routed elsewhere */
 	retval = request_irq(udc->udp_irq[IRQ_USB_LP], lpc32xx_usb_lp_irq,
 	retval = request_irq(udc->udp_irq[IRQ_USB_LP], lpc32xx_usb_lp_irq,
@@ -3320,8 +3281,6 @@ irq_dev_fail:
 irq_hp_fail:
 irq_hp_fail:
 	free_irq(udc->udp_irq[IRQ_USB_LP], udc);
 	free_irq(udc->udp_irq[IRQ_USB_LP], udc);
 irq_lp_fail:
 irq_lp_fail:
-	device_unregister(&udc->gadget.dev);
-dev_register_fail:
 	dma_pool_destroy(udc->dd_cache);
 	dma_pool_destroy(udc->dd_cache);
 dma_alloc_fail:
 dma_alloc_fail:
 	dma_free_coherent(&pdev->dev, UDCA_BUFF_SIZE,
 	dma_free_coherent(&pdev->dev, UDCA_BUFF_SIZE,
@@ -3376,8 +3335,6 @@ static int lpc32xx_udc_remove(struct platform_device *pdev)
 	free_irq(udc->udp_irq[IRQ_USB_HP], udc);
 	free_irq(udc->udp_irq[IRQ_USB_HP], udc);
 	free_irq(udc->udp_irq[IRQ_USB_LP], udc);
 	free_irq(udc->udp_irq[IRQ_USB_LP], udc);
 
 
-	device_unregister(&udc->gadget.dev);
-
 	clk_disable(udc->usb_otg_clk);
 	clk_disable(udc->usb_otg_clk);
 	clk_put(udc->usb_otg_clk);
 	clk_put(udc->usb_otg_clk);
 	clk_disable(udc->usb_slv_clk);
 	clk_disable(udc->usb_slv_clk);

+ 0 - 17
drivers/usb/gadget/m66592-udc.c

@@ -1471,7 +1471,6 @@ static int m66592_udc_start(struct usb_gadget *g,
 	/* hook up the driver */
 	/* hook up the driver */
 	driver->driver.bus = NULL;
 	driver->driver.bus = NULL;
 	m66592->driver = driver;
 	m66592->driver = driver;
-	m66592->gadget.dev.driver = &driver->driver;
 
 
 	m66592_bset(m66592, M66592_VBSE | M66592_URST, M66592_INTENB0);
 	m66592_bset(m66592, M66592_VBSE | M66592_URST, M66592_INTENB0);
 	if (m66592_read(m66592, M66592_INTSTS0) & M66592_VBSTS) {
 	if (m66592_read(m66592, M66592_INTSTS0) & M66592_VBSTS) {
@@ -1494,7 +1493,6 @@ static int m66592_udc_stop(struct usb_gadget *g,
 	m66592_bclr(m66592, M66592_VBSE | M66592_URST, M66592_INTENB0);
 	m66592_bclr(m66592, M66592_VBSE | M66592_URST, M66592_INTENB0);
 
 
 	driver->unbind(&m66592->gadget);
 	driver->unbind(&m66592->gadget);
-	m66592->gadget.dev.driver = NULL;
 
 
 	init_controller(m66592);
 	init_controller(m66592);
 	disable_controller(m66592);
 	disable_controller(m66592);
@@ -1538,7 +1536,6 @@ static int __exit m66592_remove(struct platform_device *pdev)
 	struct m66592		*m66592 = dev_get_drvdata(&pdev->dev);
 	struct m66592		*m66592 = dev_get_drvdata(&pdev->dev);
 
 
 	usb_del_gadget_udc(&m66592->gadget);
 	usb_del_gadget_udc(&m66592->gadget);
-	device_del(&m66592->gadget.dev);
 
 
 	del_timer_sync(&m66592->timer);
 	del_timer_sync(&m66592->timer);
 	iounmap(m66592->reg);
 	iounmap(m66592->reg);
@@ -1608,12 +1605,7 @@ static int __init m66592_probe(struct platform_device *pdev)
 	dev_set_drvdata(&pdev->dev, m66592);
 	dev_set_drvdata(&pdev->dev, m66592);
 
 
 	m66592->gadget.ops = &m66592_gadget_ops;
 	m66592->gadget.ops = &m66592_gadget_ops;
-	device_initialize(&m66592->gadget.dev);
-	dev_set_name(&m66592->gadget.dev, "gadget");
 	m66592->gadget.max_speed = USB_SPEED_HIGH;
 	m66592->gadget.max_speed = USB_SPEED_HIGH;
-	m66592->gadget.dev.parent = &pdev->dev;
-	m66592->gadget.dev.dma_mask = pdev->dev.dma_mask;
-	m66592->gadget.dev.release = pdev->dev.release;
 	m66592->gadget.name = udc_name;
 	m66592->gadget.name = udc_name;
 
 
 	init_timer(&m66592->timer);
 	init_timer(&m66592->timer);
@@ -1674,12 +1666,6 @@ static int __init m66592_probe(struct platform_device *pdev)
 
 
 	init_controller(m66592);
 	init_controller(m66592);
 
 
-	ret = device_add(&m66592->gadget.dev);
-	if (ret) {
-		pr_err("device_add error (%d)\n", ret);
-		goto err_device_add;
-	}
-
 	ret = usb_add_gadget_udc(&pdev->dev, &m66592->gadget);
 	ret = usb_add_gadget_udc(&pdev->dev, &m66592->gadget);
 	if (ret)
 	if (ret)
 		goto err_add_udc;
 		goto err_add_udc;
@@ -1688,9 +1674,6 @@ static int __init m66592_probe(struct platform_device *pdev)
 	return 0;
 	return 0;
 
 
 err_add_udc:
 err_add_udc:
-	device_del(&m66592->gadget.dev);
-
-err_device_add:
 	m66592_free_request(&m66592->ep[0].ep, m66592->ep0_req);
 	m66592_free_request(&m66592->ep[0].ep, m66592->ep0_req);
 
 
 clean_up3:
 clean_up3:

+ 9 - 20
drivers/usb/gadget/multi.c

@@ -135,8 +135,8 @@ static struct fsg_common fsg_common;
 
 
 static u8 hostaddr[ETH_ALEN];
 static u8 hostaddr[ETH_ALEN];
 
 
-static unsigned char tty_line;
 static struct usb_function_instance *fi_acm;
 static struct usb_function_instance *fi_acm;
+static struct eth_dev *the_dev;
 
 
 /********** RNDIS **********/
 /********** RNDIS **********/
 
 
@@ -152,7 +152,7 @@ static __init int rndis_do_config(struct usb_configuration *c)
 		c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
 		c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
 	}
 	}
 
 
-	ret = rndis_bind_config(c, hostaddr);
+	ret = rndis_bind_config(c, hostaddr, the_dev);
 	if (ret < 0)
 	if (ret < 0)
 		return ret;
 		return ret;
 
 
@@ -214,7 +214,7 @@ static __init int cdc_do_config(struct usb_configuration *c)
 		c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
 		c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
 	}
 	}
 
 
-	ret = ecm_bind_config(c, hostaddr);
+	ret = ecm_bind_config(c, hostaddr, the_dev);
 	if (ret < 0)
 	if (ret < 0)
 		return ret;
 		return ret;
 
 
@@ -269,7 +269,6 @@ static int cdc_config_register(struct usb_composite_dev *cdev)
 static int __ref multi_bind(struct usb_composite_dev *cdev)
 static int __ref multi_bind(struct usb_composite_dev *cdev)
 {
 {
 	struct usb_gadget *gadget = cdev->gadget;
 	struct usb_gadget *gadget = cdev->gadget;
-	struct f_serial_opts *opts;
 	int status;
 	int status;
 
 
 	if (!can_support_ecm(cdev->gadget)) {
 	if (!can_support_ecm(cdev->gadget)) {
@@ -279,24 +278,17 @@ static int __ref multi_bind(struct usb_composite_dev *cdev)
 	}
 	}
 
 
 	/* set up network link layer */
 	/* set up network link layer */
-	status = gether_setup(cdev->gadget, hostaddr);
-	if (status < 0)
-		return status;
+	the_dev = gether_setup(cdev->gadget, hostaddr);
+	if (IS_ERR(the_dev))
+		return PTR_ERR(the_dev);
 
 
 	/* set up serial link layer */
 	/* set up serial link layer */
-	status = gserial_alloc_line(&tty_line);
-	if (status < 0)
-		goto fail0;
-
 	fi_acm = usb_get_function_instance("acm");
 	fi_acm = usb_get_function_instance("acm");
 	if (IS_ERR(fi_acm)) {
 	if (IS_ERR(fi_acm)) {
 		status = PTR_ERR(fi_acm);
 		status = PTR_ERR(fi_acm);
-		goto fail0dot5;
+		goto fail0;
 	}
 	}
 
 
-	opts = container_of(fi_acm, struct f_serial_opts, func_inst);
-	opts->port_num = tty_line;
-
 	/* set up mass storage function */
 	/* set up mass storage function */
 	{
 	{
 		void *retp;
 		void *retp;
@@ -334,10 +326,8 @@ fail2:
 	fsg_common_put(&fsg_common);
 	fsg_common_put(&fsg_common);
 fail1:
 fail1:
 	usb_put_function_instance(fi_acm);
 	usb_put_function_instance(fi_acm);
-fail0dot5:
-	gserial_free_line(tty_line);
 fail0:
 fail0:
-	gether_cleanup();
+	gether_cleanup(the_dev);
 	return status;
 	return status;
 }
 }
 
 
@@ -350,8 +340,7 @@ static int __exit multi_unbind(struct usb_composite_dev *cdev)
 	usb_put_function(f_acm_rndis);
 	usb_put_function(f_acm_rndis);
 #endif
 #endif
 	usb_put_function_instance(fi_acm);
 	usb_put_function_instance(fi_acm);
-	gserial_free_line(tty_line);
-	gether_cleanup();
+	gether_cleanup(the_dev);
 	return 0;
 	return 0;
 }
 }
 
 

+ 23 - 42
drivers/usb/gadget/mv_u3d_core.c

@@ -30,9 +30,6 @@
 #include <linux/platform_device.h>
 #include <linux/platform_device.h>
 #include <linux/platform_data/mv_usb.h>
 #include <linux/platform_data/mv_usb.h>
 #include <linux/clk.h>
 #include <linux/clk.h>
-#include <asm/system.h>
-#include <asm/unaligned.h>
-#include <asm/byteorder.h>
 
 
 #include "mv_u3d.h"
 #include "mv_u3d.h"
 
 
@@ -125,7 +122,7 @@ static int mv_u3d_process_ep_req(struct mv_u3d *u3d, int index,
 	struct mv_u3d_trb	*curr_trb;
 	struct mv_u3d_trb	*curr_trb;
 	dma_addr_t cur_deq_lo;
 	dma_addr_t cur_deq_lo;
 	struct mv_u3d_ep_context	*curr_ep_context;
 	struct mv_u3d_ep_context	*curr_ep_context;
-	int trb_complete, actual, remaining_length;
+	int trb_complete, actual, remaining_length = 0;
 	int direction, ep_num;
 	int direction, ep_num;
 	int retval = 0;
 	int retval = 0;
 	u32 tmp, status, length;
 	u32 tmp, status, length;
@@ -189,6 +186,8 @@ static int mv_u3d_process_ep_req(struct mv_u3d *u3d, int index,
  */
  */
 static
 static
 void mv_u3d_done(struct mv_u3d_ep *ep, struct mv_u3d_req *req, int status)
 void mv_u3d_done(struct mv_u3d_ep *ep, struct mv_u3d_req *req, int status)
+	__releases(&ep->udc->lock)
+	__acquires(&ep->udc->lock)
 {
 {
 	struct mv_u3d *u3d = (struct mv_u3d *)ep->u3d;
 	struct mv_u3d *u3d = (struct mv_u3d *)ep->u3d;
 
 
@@ -812,19 +811,19 @@ mv_u3d_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
 		return 0;
 		return 0;
 	}
 	}
 
 
-	dev_dbg(u3d->dev, "%s: %s, req: 0x%x\n",
-			__func__, _ep->name, (u32)req);
+	dev_dbg(u3d->dev, "%s: %s, req: 0x%p\n",
+			__func__, _ep->name, req);
 
 
 	/* catch various bogus parameters */
 	/* catch various bogus parameters */
 	if (!req->req.complete || !req->req.buf
 	if (!req->req.complete || !req->req.buf
 			|| !list_empty(&req->queue)) {
 			|| !list_empty(&req->queue)) {
 		dev_err(u3d->dev,
 		dev_err(u3d->dev,
-			"%s, bad params, _req: 0x%x,"
-			"req->req.complete: 0x%x, req->req.buf: 0x%x,"
+			"%s, bad params, _req: 0x%p,"
+			"req->req.complete: 0x%p, req->req.buf: 0x%p,"
 			"list_empty: 0x%x\n",
 			"list_empty: 0x%x\n",
-			__func__, (u32)_req,
-			(u32)req->req.complete, (u32)req->req.buf,
-			(u32)list_empty(&req->queue));
+			__func__, _req,
+			req->req.complete, req->req.buf,
+			list_empty(&req->queue));
 		return -EINVAL;
 		return -EINVAL;
 	}
 	}
 	if (unlikely(!ep->ep.desc)) {
 	if (unlikely(!ep->ep.desc)) {
@@ -905,7 +904,7 @@ static int mv_u3d_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)
 					struct mv_u3d_req, queue);
 					struct mv_u3d_req, queue);
 
 
 			/* Point first TRB of next request to the EP context. */
 			/* Point first TRB of next request to the EP context. */
-			iowrite32((u32) next_req->trb_head,
+			iowrite32((unsigned long) next_req->trb_head,
 					&ep_context->trb_addr_lo);
 					&ep_context->trb_addr_lo);
 		} else {
 		} else {
 			struct mv_u3d_ep_context *ep_context;
 			struct mv_u3d_ep_context *ep_context;
@@ -1264,7 +1263,6 @@ static int mv_u3d_start(struct usb_gadget *g,
 	/* hook up the driver ... */
 	/* hook up the driver ... */
 	driver->driver.bus = NULL;
 	driver->driver.bus = NULL;
 	u3d->driver = driver;
 	u3d->driver = driver;
-	u3d->gadget.dev.driver = &driver->driver;
 
 
 	u3d->ep0_dir = USB_DIR_OUT;
 	u3d->ep0_dir = USB_DIR_OUT;
 
 
@@ -1302,7 +1300,6 @@ static int mv_u3d_stop(struct usb_gadget *g,
 
 
 	spin_unlock_irqrestore(&u3d->lock, flags);
 	spin_unlock_irqrestore(&u3d->lock, flags);
 
 
-	u3d->gadget.dev.driver = NULL;
 	u3d->driver = NULL;
 	u3d->driver = NULL;
 
 
 	return 0;
 	return 0;
@@ -1525,6 +1522,8 @@ static int mv_u3d_is_set_configuration(struct usb_ctrlrequest *setup)
 
 
 static void mv_u3d_handle_setup_packet(struct mv_u3d *u3d, u8 ep_num,
 static void mv_u3d_handle_setup_packet(struct mv_u3d *u3d, u8 ep_num,
 	struct usb_ctrlrequest *setup)
 	struct usb_ctrlrequest *setup)
+	__releases(&u3c->lock)
+	__acquires(&u3c->lock)
 {
 {
 	bool delegate = false;
 	bool delegate = false;
 
 
@@ -1758,11 +1757,6 @@ static irqreturn_t mv_u3d_irq(int irq, void *dev)
 	return IRQ_HANDLED;
 	return IRQ_HANDLED;
 }
 }
 
 
-static void mv_u3d_gadget_release(struct device *dev)
-{
-	dev_dbg(dev, "%s\n", __func__);
-}
-
 static int mv_u3d_remove(struct platform_device *dev)
 static int mv_u3d_remove(struct platform_device *dev)
 {
 {
 	struct mv_u3d *u3d = platform_get_drvdata(dev);
 	struct mv_u3d *u3d = platform_get_drvdata(dev);
@@ -1792,8 +1786,6 @@ static int mv_u3d_remove(struct platform_device *dev)
 
 
 	clk_put(u3d->clk);
 	clk_put(u3d->clk);
 
 
-	device_unregister(&u3d->gadget.dev);
-
 	platform_set_drvdata(dev, NULL);
 	platform_set_drvdata(dev, NULL);
 
 
 	kfree(u3d);
 	kfree(u3d);
@@ -1829,7 +1821,7 @@ static int mv_u3d_probe(struct platform_device *dev)
 	u3d->dev = &dev->dev;
 	u3d->dev = &dev->dev;
 	u3d->vbus = pdata->vbus;
 	u3d->vbus = pdata->vbus;
 
 
-	u3d->clk = clk_get(&dev->dev, pdata->clkname[0]);
+	u3d->clk = clk_get(&dev->dev, NULL);
 	if (IS_ERR(u3d->clk)) {
 	if (IS_ERR(u3d->clk)) {
 		retval = PTR_ERR(u3d->clk);
 		retval = PTR_ERR(u3d->clk);
 		goto err_get_clk;
 		goto err_get_clk;
@@ -1849,8 +1841,9 @@ static int mv_u3d_probe(struct platform_device *dev)
 		retval = -EBUSY;
 		retval = -EBUSY;
 		goto err_map_cap_regs;
 		goto err_map_cap_regs;
 	} else {
 	} else {
-		dev_dbg(&dev->dev, "cap_regs address: 0x%x/0x%x\n",
-			(unsigned int)r->start, (unsigned int)u3d->cap_regs);
+		dev_dbg(&dev->dev, "cap_regs address: 0x%lx/0x%lx\n",
+			(unsigned long) r->start,
+			(unsigned long) u3d->cap_regs);
 	}
 	}
 
 
 	/* we will access controller register, so enable the u3d controller */
 	/* we will access controller register, so enable the u3d controller */
@@ -1864,10 +1857,10 @@ static int mv_u3d_probe(struct platform_device *dev)
 		}
 		}
 	}
 	}
 
 
-	u3d->op_regs = (struct mv_u3d_op_regs __iomem *)((u32)u3d->cap_regs
+	u3d->op_regs = (struct mv_u3d_op_regs __iomem *)(u3d->cap_regs
 		+ MV_U3D_USB3_OP_REGS_OFFSET);
 		+ MV_U3D_USB3_OP_REGS_OFFSET);
 
 
-	u3d->vuc_regs = (struct mv_u3d_vuc_regs __iomem *)((u32)u3d->cap_regs
+	u3d->vuc_regs = (struct mv_u3d_vuc_regs __iomem *)(u3d->cap_regs
 		+ ioread32(&u3d->cap_regs->vuoff));
 		+ ioread32(&u3d->cap_regs->vuoff));
 
 
 	u3d->max_eps = 16;
 	u3d->max_eps = 16;
@@ -1957,16 +1950,8 @@ static int mv_u3d_probe(struct platform_device *dev)
 	u3d->gadget.speed = USB_SPEED_UNKNOWN;	/* speed */
 	u3d->gadget.speed = USB_SPEED_UNKNOWN;	/* speed */
 
 
 	/* the "gadget" abstracts/virtualizes the controller */
 	/* the "gadget" abstracts/virtualizes the controller */
-	dev_set_name(&u3d->gadget.dev, "gadget");
-	u3d->gadget.dev.parent = &dev->dev;
-	u3d->gadget.dev.dma_mask = dev->dev.dma_mask;
-	u3d->gadget.dev.release = mv_u3d_gadget_release;
 	u3d->gadget.name = driver_name;		/* gadget name */
 	u3d->gadget.name = driver_name;		/* gadget name */
 
 
-	retval = device_register(&u3d->gadget.dev);
-	if (retval)
-		goto err_register_gadget_device;
-
 	mv_u3d_eps_init(u3d);
 	mv_u3d_eps_init(u3d);
 
 
 	/* external vbus detection */
 	/* external vbus detection */
@@ -1991,8 +1976,6 @@ static int mv_u3d_probe(struct platform_device *dev)
 	return 0;
 	return 0;
 
 
 err_unregister:
 err_unregister:
-	device_unregister(&u3d->gadget.dev);
-err_register_gadget_device:
 	free_irq(u3d->irq, &dev->dev);
 	free_irq(u3d->irq, &dev->dev);
 err_request_irq:
 err_request_irq:
 err_get_irq:
 err_get_irq:
@@ -2021,7 +2004,7 @@ err_pdata:
 	return retval;
 	return retval;
 }
 }
 
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 static int mv_u3d_suspend(struct device *dev)
 static int mv_u3d_suspend(struct device *dev)
 {
 {
 	struct mv_u3d *u3d = dev_get_drvdata(dev);
 	struct mv_u3d *u3d = dev_get_drvdata(dev);
@@ -2064,10 +2047,10 @@ static int mv_u3d_resume(struct device *dev)
 
 
 	return 0;
 	return 0;
 }
 }
-
-SIMPLE_DEV_PM_OPS(mv_u3d_pm_ops, mv_u3d_suspend, mv_u3d_resume);
 #endif
 #endif
 
 
+static SIMPLE_DEV_PM_OPS(mv_u3d_pm_ops, mv_u3d_suspend, mv_u3d_resume);
+
 static void mv_u3d_shutdown(struct platform_device *dev)
 static void mv_u3d_shutdown(struct platform_device *dev)
 {
 {
 	struct mv_u3d *u3d = dev_get_drvdata(&dev->dev);
 	struct mv_u3d *u3d = dev_get_drvdata(&dev->dev);
@@ -2080,14 +2063,12 @@ static void mv_u3d_shutdown(struct platform_device *dev)
 
 
 static struct platform_driver mv_u3d_driver = {
 static struct platform_driver mv_u3d_driver = {
 	.probe		= mv_u3d_probe,
 	.probe		= mv_u3d_probe,
-	.remove		= __exit_p(mv_u3d_remove),
+	.remove		= mv_u3d_remove,
 	.shutdown	= mv_u3d_shutdown,
 	.shutdown	= mv_u3d_shutdown,
 	.driver		= {
 	.driver		= {
 		.owner	= THIS_MODULE,
 		.owner	= THIS_MODULE,
 		.name	= "mv-u3d",
 		.name	= "mv-u3d",
-#ifdef CONFIG_PM
 		.pm	= &mv_u3d_pm_ops,
 		.pm	= &mv_u3d_pm_ops,
-#endif
 	},
 	},
 };
 };
 
 

+ 1 - 2
drivers/usb/gadget/mv_udc.h

@@ -222,8 +222,7 @@ struct mv_udc {
 	struct mv_usb_platform_data     *pdata;
 	struct mv_usb_platform_data     *pdata;
 
 
 	/* some SOC has mutiple clock sources for USB*/
 	/* some SOC has mutiple clock sources for USB*/
-	unsigned int    clknum;
-	struct clk      *clk[0];
+	struct clk      *clk;
 };
 };
 
 
 /* endpoint data structure */
 /* endpoint data structure */

+ 28 - 89
drivers/usb/gadget/mv_udc_core.c

@@ -212,6 +212,8 @@ static int process_ep_req(struct mv_udc *udc, int index,
  * request is still in progress.
  * request is still in progress.
  */
  */
 static void done(struct mv_ep *ep, struct mv_req *req, int status)
 static void done(struct mv_ep *ep, struct mv_req *req, int status)
+	__releases(&ep->udc->lock)
+	__acquires(&ep->udc->lock)
 {
 {
 	struct mv_udc *udc = NULL;
 	struct mv_udc *udc = NULL;
 	unsigned char stopped = ep->stopped;
 	unsigned char stopped = ep->stopped;
@@ -237,18 +239,7 @@ static void done(struct mv_ep *ep, struct mv_req *req, int status)
 		dma_pool_free(udc->dtd_pool, curr_td, curr_td->td_dma);
 		dma_pool_free(udc->dtd_pool, curr_td, curr_td->td_dma);
 	}
 	}
 
 
-	if (req->mapped) {
-		dma_unmap_single(ep->udc->gadget.dev.parent,
-			req->req.dma, req->req.length,
-			((ep_dir(ep) == EP_DIR_IN) ?
-				DMA_TO_DEVICE : DMA_FROM_DEVICE));
-		req->req.dma = DMA_ADDR_INVALID;
-		req->mapped = 0;
-	} else
-		dma_sync_single_for_cpu(ep->udc->gadget.dev.parent,
-			req->req.dma, req->req.length,
-			((ep_dir(ep) == EP_DIR_IN) ?
-				DMA_TO_DEVICE : DMA_FROM_DEVICE));
+	usb_gadget_unmap_request(&udc->gadget, &req->req, ep_dir(ep));
 
 
 	if (status && (status != -ESHUTDOWN))
 	if (status && (status != -ESHUTDOWN))
 		dev_info(&udc->dev->dev, "complete %s req %p stat %d len %u/%u",
 		dev_info(&udc->dev->dev, "complete %s req %p stat %d len %u/%u",
@@ -732,21 +723,9 @@ mv_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
 	req->ep = ep;
 	req->ep = ep;
 
 
 	/* map virtual address to hardware */
 	/* map virtual address to hardware */
-	if (req->req.dma == DMA_ADDR_INVALID) {
-		req->req.dma = dma_map_single(ep->udc->gadget.dev.parent,
-					req->req.buf,
-					req->req.length, ep_dir(ep)
-						? DMA_TO_DEVICE
-						: DMA_FROM_DEVICE);
-		req->mapped = 1;
-	} else {
-		dma_sync_single_for_device(ep->udc->gadget.dev.parent,
-					req->req.dma, req->req.length,
-					ep_dir(ep)
-						? DMA_TO_DEVICE
-						: DMA_FROM_DEVICE);
-		req->mapped = 0;
-	}
+	retval = usb_gadget_map_request(&udc->gadget, _req, ep_dir(ep));
+	if (retval)
+		return retval;
 
 
 	req->req.status = -EINPROGRESS;
 	req->req.status = -EINPROGRESS;
 	req->req.actual = 0;
 	req->req.actual = 0;
@@ -780,18 +759,7 @@ mv_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
 	return 0;
 	return 0;
 
 
 err_unmap_dma:
 err_unmap_dma:
-	if (req->mapped) {
-		dma_unmap_single(ep->udc->gadget.dev.parent,
-				req->req.dma, req->req.length,
-				((ep_dir(ep) == EP_DIR_IN) ?
-				DMA_TO_DEVICE : DMA_FROM_DEVICE));
-		req->req.dma = DMA_ADDR_INVALID;
-		req->mapped = 0;
-	} else
-		dma_sync_single_for_cpu(ep->udc->gadget.dev.parent,
-				req->req.dma, req->req.length,
-				((ep_dir(ep) == EP_DIR_IN) ?
-				DMA_TO_DEVICE : DMA_FROM_DEVICE));
+	usb_gadget_unmap_request(&udc->gadget, _req, ep_dir(ep));
 
 
 	return retval;
 	return retval;
 }
 }
@@ -1006,18 +974,12 @@ static struct usb_ep_ops mv_ep_ops = {
 
 
 static void udc_clock_enable(struct mv_udc *udc)
 static void udc_clock_enable(struct mv_udc *udc)
 {
 {
-	unsigned int i;
-
-	for (i = 0; i < udc->clknum; i++)
-		clk_prepare_enable(udc->clk[i]);
+	clk_prepare_enable(udc->clk);
 }
 }
 
 
 static void udc_clock_disable(struct mv_udc *udc)
 static void udc_clock_disable(struct mv_udc *udc)
 {
 {
-	unsigned int i;
-
-	for (i = 0; i < udc->clknum; i++)
-		clk_disable_unprepare(udc->clk[i]);
+	clk_disable_unprepare(udc->clk);
 }
 }
 
 
 static void udc_stop(struct mv_udc *udc)
 static void udc_stop(struct mv_udc *udc)
@@ -1386,7 +1348,6 @@ static int mv_udc_start(struct usb_gadget *gadget,
 	/* hook up the driver ... */
 	/* hook up the driver ... */
 	driver->driver.bus = NULL;
 	driver->driver.bus = NULL;
 	udc->driver = driver;
 	udc->driver = driver;
-	udc->gadget.dev.driver = &driver->driver;
 
 
 	udc->usb_state = USB_STATE_ATTACHED;
 	udc->usb_state = USB_STATE_ATTACHED;
 	udc->ep0_state = WAIT_FOR_SETUP;
 	udc->ep0_state = WAIT_FOR_SETUP;
@@ -1401,7 +1362,6 @@ static int mv_udc_start(struct usb_gadget *gadget,
 			dev_err(&udc->dev->dev,
 			dev_err(&udc->dev->dev,
 				"unable to register peripheral to otg\n");
 				"unable to register peripheral to otg\n");
 			udc->driver = NULL;
 			udc->driver = NULL;
-			udc->gadget.dev.driver = NULL;
 			return retval;
 			return retval;
 		}
 		}
 	}
 	}
@@ -1437,7 +1397,6 @@ static int mv_udc_stop(struct usb_gadget *gadget,
 	spin_unlock_irqrestore(&udc->lock, flags);
 	spin_unlock_irqrestore(&udc->lock, flags);
 
 
 	/* unbind gadget driver */
 	/* unbind gadget driver */
-	udc->gadget.dev.driver = NULL;
 	udc->driver = NULL;
 	udc->driver = NULL;
 
 
 	return 0;
 	return 0;
@@ -1528,14 +1487,7 @@ udc_prime_status(struct mv_udc *udc, u8 direction, u16 status, bool empty)
 
 
 	return 0;
 	return 0;
 out:
 out:
-	if (req->mapped) {
-		dma_unmap_single(ep->udc->gadget.dev.parent,
-				req->req.dma, req->req.length,
-				((ep_dir(ep) == EP_DIR_IN) ?
-				DMA_TO_DEVICE : DMA_FROM_DEVICE));
-		req->req.dma = DMA_ADDR_INVALID;
-		req->mapped = 0;
-	}
+	usb_gadget_unmap_request(&udc->gadget, &req->req, ep_dir(ep));
 
 
 	return retval;
 	return retval;
 }
 }
@@ -1695,6 +1647,8 @@ out:
 
 
 static void handle_setup_packet(struct mv_udc *udc, u8 ep_num,
 static void handle_setup_packet(struct mv_udc *udc, u8 ep_num,
 	struct usb_ctrlrequest *setup)
 	struct usb_ctrlrequest *setup)
+	__releases(&ep->udc->lock)
+	__acquires(&ep->udc->lock)
 {
 {
 	bool delegate = false;
 	bool delegate = false;
 
 
@@ -1891,7 +1845,7 @@ static void irq_process_tr_complete(struct mv_udc *udc)
 	}
 	}
 }
 }
 
 
-void irq_process_reset(struct mv_udc *udc)
+static void irq_process_reset(struct mv_udc *udc)
 {
 {
 	u32 tmp;
 	u32 tmp;
 	unsigned int loops;
 	unsigned int loops;
@@ -2138,8 +2092,6 @@ static int mv_udc_remove(struct platform_device *pdev)
 
 
 	mv_udc_disable(udc);
 	mv_udc_disable(udc);
 
 
-	device_unregister(&udc->gadget.dev);
-
 	/* free dev, wait for the release() finished */
 	/* free dev, wait for the release() finished */
 	wait_for_completion(udc->done);
 	wait_for_completion(udc->done);
 
 
@@ -2151,7 +2103,6 @@ static int mv_udc_probe(struct platform_device *pdev)
 	struct mv_usb_platform_data *pdata = pdev->dev.platform_data;
 	struct mv_usb_platform_data *pdata = pdev->dev.platform_data;
 	struct mv_udc *udc;
 	struct mv_udc *udc;
 	int retval = 0;
 	int retval = 0;
-	int clk_i = 0;
 	struct resource *r;
 	struct resource *r;
 	size_t size;
 	size_t size;
 
 
@@ -2160,8 +2111,7 @@ static int mv_udc_probe(struct platform_device *pdev)
 		return -ENODEV;
 		return -ENODEV;
 	}
 	}
 
 
-	size = sizeof(*udc) + sizeof(struct clk *) * pdata->clknum;
-	udc = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
+	udc = devm_kzalloc(&pdev->dev, sizeof(*udc), GFP_KERNEL);
 	if (udc == NULL) {
 	if (udc == NULL) {
 		dev_err(&pdev->dev, "failed to allocate memory for udc\n");
 		dev_err(&pdev->dev, "failed to allocate memory for udc\n");
 		return -ENOMEM;
 		return -ENOMEM;
@@ -2173,26 +2123,24 @@ static int mv_udc_probe(struct platform_device *pdev)
 
 
 	udc->dev = pdev;
 	udc->dev = pdev;
 
 
-#ifdef CONFIG_USB_OTG_UTILS
 	if (pdata->mode == MV_USB_MODE_OTG) {
 	if (pdata->mode == MV_USB_MODE_OTG) {
 		udc->transceiver = devm_usb_get_phy(&pdev->dev,
 		udc->transceiver = devm_usb_get_phy(&pdev->dev,
 					USB_PHY_TYPE_USB2);
 					USB_PHY_TYPE_USB2);
-		if (IS_ERR_OR_NULL(udc->transceiver)) {
+		if (IS_ERR(udc->transceiver)) {
+			retval = PTR_ERR(udc->transceiver);
+
+			if (retval == -ENXIO)
+				return retval;
+
 			udc->transceiver = NULL;
 			udc->transceiver = NULL;
-			return -ENODEV;
+			return -EPROBE_DEFER;
 		}
 		}
 	}
 	}
-#endif
 
 
-	udc->clknum = pdata->clknum;
-	for (clk_i = 0; clk_i < udc->clknum; 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]);
-			return retval;
-		}
-	}
+	/* udc only have one sysclk. */
+	udc->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(udc->clk))
+		return PTR_ERR(udc->clk);
 
 
 	r = platform_get_resource_byname(udc->dev, IORESOURCE_MEM, "capregs");
 	r = platform_get_resource_byname(udc->dev, IORESOURCE_MEM, "capregs");
 	if (r == NULL) {
 	if (r == NULL) {
@@ -2311,16 +2259,8 @@ static int mv_udc_probe(struct platform_device *pdev)
 	udc->gadget.max_speed = USB_SPEED_HIGH;	/* support dual speed */
 	udc->gadget.max_speed = USB_SPEED_HIGH;	/* support dual speed */
 
 
 	/* the "gadget" abstracts/virtualizes the controller */
 	/* the "gadget" abstracts/virtualizes the controller */
-	dev_set_name(&udc->gadget.dev, "gadget");
-	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 */
 	udc->gadget.name = driver_name;		/* gadget name */
 
 
-	retval = device_register(&udc->gadget.dev);
-	if (retval)
-		goto err_destroy_dma;
-
 	eps_init(udc);
 	eps_init(udc);
 
 
 	/* VBUS detect: we can disable/enable clock on demand.*/
 	/* VBUS detect: we can disable/enable clock on demand.*/
@@ -2342,7 +2282,7 @@ static int mv_udc_probe(struct platform_device *pdev)
 		if (!udc->qwork) {
 		if (!udc->qwork) {
 			dev_err(&pdev->dev, "cannot create workqueue\n");
 			dev_err(&pdev->dev, "cannot create workqueue\n");
 			retval = -ENOMEM;
 			retval = -ENOMEM;
-			goto err_unregister;
+			goto err_destroy_dma;
 		}
 		}
 
 
 		INIT_WORK(&udc->vbus_work, mv_udc_vbus_work);
 		INIT_WORK(&udc->vbus_work, mv_udc_vbus_work);
@@ -2358,7 +2298,8 @@ static int mv_udc_probe(struct platform_device *pdev)
 	else
 	else
 		udc->vbus_active = 1;
 		udc->vbus_active = 1;
 
 
-	retval = usb_add_gadget_udc(&pdev->dev, &udc->gadget);
+	retval = usb_add_gadget_udc_release(&pdev->dev, &udc->gadget,
+			gadget_release);
 	if (retval)
 	if (retval)
 		goto err_create_workqueue;
 		goto err_create_workqueue;
 
 
@@ -2370,8 +2311,6 @@ static int mv_udc_probe(struct platform_device *pdev)
 
 
 err_create_workqueue:
 err_create_workqueue:
 	destroy_workqueue(udc->qwork);
 	destroy_workqueue(udc->qwork);
-err_unregister:
-	device_unregister(&udc->gadget.dev);
 err_destroy_dma:
 err_destroy_dma:
 	dma_pool_destroy(udc->dtd_pool);
 	dma_pool_destroy(udc->dtd_pool);
 err_free_dma:
 err_free_dma:

+ 7 - 6
drivers/usb/gadget/ncm.c

@@ -111,6 +111,7 @@ static struct usb_gadget_strings *dev_strings[] = {
 	NULL,
 	NULL,
 };
 };
 
 
+struct eth_dev *the_dev;
 static u8 hostaddr[ETH_ALEN];
 static u8 hostaddr[ETH_ALEN];
 
 
 /*-------------------------------------------------------------------------*/
 /*-------------------------------------------------------------------------*/
@@ -124,7 +125,7 @@ static int __init ncm_do_config(struct usb_configuration *c)
 		c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
 		c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
 	}
 	}
 
 
-	return ncm_bind_config(c, hostaddr);
+	return ncm_bind_config(c, hostaddr, the_dev);
 }
 }
 
 
 static struct usb_configuration ncm_config_driver = {
 static struct usb_configuration ncm_config_driver = {
@@ -143,9 +144,9 @@ static int __init gncm_bind(struct usb_composite_dev *cdev)
 	int			status;
 	int			status;
 
 
 	/* set up network link layer */
 	/* set up network link layer */
-	status = gether_setup(cdev->gadget, hostaddr);
-	if (status < 0)
-		return status;
+	the_dev = gether_setup(cdev->gadget, hostaddr);
+	if (IS_ERR(the_dev))
+		return PTR_ERR(the_dev);
 
 
 	/* Allocate string descriptor numbers ... note that string
 	/* Allocate string descriptor numbers ... note that string
 	 * contents can be overridden by the composite_dev glue.
 	 * contents can be overridden by the composite_dev glue.
@@ -168,13 +169,13 @@ static int __init gncm_bind(struct usb_composite_dev *cdev)
 	return 0;
 	return 0;
 
 
 fail:
 fail:
-	gether_cleanup();
+	gether_cleanup(the_dev);
 	return status;
 	return status;
 }
 }
 
 
 static int __exit gncm_unbind(struct usb_composite_dev *cdev)
 static int __exit gncm_unbind(struct usb_composite_dev *cdev)
 {
 {
-	gether_cleanup();
+	gether_cleanup(the_dev);
 	return 0;
 	return 0;
 }
 }
 
 

+ 6 - 19
drivers/usb/gadget/net2272.c

@@ -58,7 +58,6 @@ static const char * const ep_name[] = {
 	"ep-a", "ep-b", "ep-c",
 	"ep-a", "ep-b", "ep-c",
 };
 };
 
 
-#define DMA_ADDR_INVALID	(~(dma_addr_t)0)
 #ifdef CONFIG_USB_NET2272_DMA
 #ifdef CONFIG_USB_NET2272_DMA
 /*
 /*
  * use_dma: the NET2272 can use an external DMA controller.
  * use_dma: the NET2272 can use an external DMA controller.
@@ -341,7 +340,6 @@ net2272_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags)
 	if (!req)
 	if (!req)
 		return NULL;
 		return NULL;
 
 
-	req->req.dma = DMA_ADDR_INVALID;
 	INIT_LIST_HEAD(&req->queue);
 	INIT_LIST_HEAD(&req->queue);
 
 
 	return &req->req;
 	return &req->req;
@@ -913,7 +911,7 @@ net2272_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
 			}
 			}
 		}
 		}
 	}
 	}
-	if (likely(req != 0))
+	if (likely(req))
 		list_add_tail(&req->queue, &ep->queue);
 		list_add_tail(&req->queue, &ep->queue);
 
 
 	if (likely(!list_empty(&ep->queue)))
 	if (likely(!list_empty(&ep->queue)))
@@ -1467,7 +1465,6 @@ static int net2272_start(struct usb_gadget *_gadget,
 	dev->softconnect = 1;
 	dev->softconnect = 1;
 	driver->driver.bus = NULL;
 	driver->driver.bus = NULL;
 	dev->driver = driver;
 	dev->driver = driver;
-	dev->gadget.dev.driver = &driver->driver;
 
 
 	/* ... then enable host detection and ep0; and we're ready
 	/* ... then enable host detection and ep0; and we're ready
 	 * for set_configuration as well as eventual disconnect.
 	 * for set_configuration as well as eventual disconnect.
@@ -1517,7 +1514,6 @@ static int net2272_stop(struct usb_gadget *_gadget,
 	stop_activity(dev, driver);
 	stop_activity(dev, driver);
 	spin_unlock_irqrestore(&dev->lock, flags);
 	spin_unlock_irqrestore(&dev->lock, flags);
 
 
-	dev->gadget.dev.driver = NULL;
 	dev->driver = NULL;
 	dev->driver = NULL;
 
 
 	dev_dbg(dev->dev, "unregistered driver '%s'\n", driver->driver.name);
 	dev_dbg(dev->dev, "unregistered driver '%s'\n", driver->driver.name);
@@ -1549,7 +1545,7 @@ net2272_handle_dma(struct net2272_ep *ep)
 	      | (ep->dev->dma_eot_polarity << EOT_POLARITY)
 	      | (ep->dev->dma_eot_polarity << EOT_POLARITY)
 	      | (ep->dev->dma_dack_polarity << DACK_POLARITY)
 	      | (ep->dev->dma_dack_polarity << DACK_POLARITY)
 	      | (ep->dev->dma_dreq_polarity << DREQ_POLARITY)
 	      | (ep->dev->dma_dreq_polarity << DREQ_POLARITY)
-	      | ((ep->dma >> 1) << DMA_ENDPOINT_SELECT));
+	      | (ep->dma << DMA_ENDPOINT_SELECT));
 
 
 	ep->dev->dma_busy = 0;
 	ep->dev->dma_busy = 0;
 
 
@@ -1622,7 +1618,7 @@ net2272_handle_ep(struct net2272_ep *ep)
 	ep->irqs++;
 	ep->irqs++;
 
 
 	dev_vdbg(ep->dev->dev, "%s ack ep_stat0 %02x, ep_stat1 %02x, req %p\n",
 	dev_vdbg(ep->dev->dev, "%s ack ep_stat0 %02x, ep_stat1 %02x, req %p\n",
-		ep->ep.name, stat0, stat1, req ? &req->req : 0);
+		ep->ep.name, stat0, stat1, req ? &req->req : NULL);
 
 
 	net2272_ep_write(ep, EP_STAT0, stat0 &
 	net2272_ep_write(ep, EP_STAT0, stat0 &
 		~((1 << NAK_OUT_PACKETS)
 		~((1 << NAK_OUT_PACKETS)
@@ -2216,7 +2212,6 @@ net2272_remove(struct net2272 *dev)
 	free_irq(dev->irq, dev);
 	free_irq(dev->irq, dev);
 	iounmap(dev->base_addr);
 	iounmap(dev->base_addr);
 
 
-	device_unregister(&dev->gadget.dev);
 	device_remove_file(dev->dev, &dev_attr_registers);
 	device_remove_file(dev->dev, &dev_attr_registers);
 
 
 	dev_info(dev->dev, "unbind\n");
 	dev_info(dev->dev, "unbind\n");
@@ -2243,10 +2238,6 @@ static struct net2272 *net2272_probe_init(struct device *dev, unsigned int irq)
 	ret->gadget.max_speed = USB_SPEED_HIGH;
 	ret->gadget.max_speed = USB_SPEED_HIGH;
 
 
 	/* the "gadget" abstracts/virtualizes the controller */
 	/* the "gadget" abstracts/virtualizes the controller */
-	dev_set_name(&ret->gadget.dev, "gadget");
-	ret->gadget.dev.parent = dev;
-	ret->gadget.dev.dma_mask = dev->dma_mask;
-	ret->gadget.dev.release = net2272_gadget_release;
 	ret->gadget.name = driver_name;
 	ret->gadget.name = driver_name;
 
 
 	return ret;
 	return ret;
@@ -2282,14 +2273,12 @@ net2272_probe_fin(struct net2272 *dev, unsigned int irqflags)
 		dma_mode_string());
 		dma_mode_string());
 	dev_info(dev->dev, "version: %s\n", driver_vers);
 	dev_info(dev->dev, "version: %s\n", driver_vers);
 
 
-	ret = device_register(&dev->gadget.dev);
-	if (ret)
-		goto err_irq;
 	ret = device_create_file(dev->dev, &dev_attr_registers);
 	ret = device_create_file(dev->dev, &dev_attr_registers);
 	if (ret)
 	if (ret)
-		goto err_dev_reg;
+		goto err_irq;
 
 
-	ret = usb_add_gadget_udc(dev->dev, &dev->gadget);
+	ret = usb_add_gadget_udc_release(dev->dev, &dev->gadget,
+			net2272_gadget_release);
 	if (ret)
 	if (ret)
 		goto err_add_udc;
 		goto err_add_udc;
 
 
@@ -2297,8 +2286,6 @@ net2272_probe_fin(struct net2272 *dev, unsigned int irqflags)
 
 
 err_add_udc:
 err_add_udc:
 	device_remove_file(dev->dev, &dev_attr_registers);
 	device_remove_file(dev->dev, &dev_attr_registers);
- err_dev_reg:
-	device_unregister(&dev->gadget.dev);
  err_irq:
  err_irq:
 	free_irq(dev->irq, dev);
 	free_irq(dev->irq, dev);
  err:
  err:

+ 6 - 19
drivers/usb/gadget/net2280.c

@@ -65,7 +65,6 @@
 #define	DRIVER_DESC		"PLX NET228x USB Peripheral Controller"
 #define	DRIVER_DESC		"PLX NET228x USB Peripheral Controller"
 #define	DRIVER_VERSION		"2005 Sept 27"
 #define	DRIVER_VERSION		"2005 Sept 27"
 
 
-#define	DMA_ADDR_INVALID	(~(dma_addr_t)0)
 #define	EP_DONTUSE		13	/* nonzero */
 #define	EP_DONTUSE		13	/* nonzero */
 
 
 #define USE_RDK_LEDS		/* GPIO pins control three LEDs */
 #define USE_RDK_LEDS		/* GPIO pins control three LEDs */
@@ -406,7 +405,6 @@ net2280_alloc_request (struct usb_ep *_ep, gfp_t gfp_flags)
 	if (!req)
 	if (!req)
 		return NULL;
 		return NULL;
 
 
-	req->req.dma = DMA_ADDR_INVALID;
 	INIT_LIST_HEAD (&req->queue);
 	INIT_LIST_HEAD (&req->queue);
 
 
 	/* this dma descriptor may be swapped with the previous dummy */
 	/* this dma descriptor may be swapped with the previous dummy */
@@ -420,7 +418,6 @@ net2280_alloc_request (struct usb_ep *_ep, gfp_t gfp_flags)
 			return NULL;
 			return NULL;
 		}
 		}
 		td->dmacount = 0;	/* not VALID */
 		td->dmacount = 0;	/* not VALID */
-		td->dmaaddr = cpu_to_le32 (DMA_ADDR_INVALID);
 		td->dmadesc = td->dmaaddr;
 		td->dmadesc = td->dmaaddr;
 		req->td = td;
 		req->td = td;
 	}
 	}
@@ -1896,7 +1893,6 @@ static int net2280_start(struct usb_gadget *_gadget,
 	dev->softconnect = 1;
 	dev->softconnect = 1;
 	driver->driver.bus = NULL;
 	driver->driver.bus = NULL;
 	dev->driver = driver;
 	dev->driver = driver;
-	dev->gadget.dev.driver = &driver->driver;
 
 
 	retval = device_create_file (&dev->pdev->dev, &dev_attr_function);
 	retval = device_create_file (&dev->pdev->dev, &dev_attr_function);
 	if (retval) goto err_unbind;
 	if (retval) goto err_unbind;
@@ -1924,7 +1920,6 @@ static int net2280_start(struct usb_gadget *_gadget,
 err_func:
 err_func:
 	device_remove_file (&dev->pdev->dev, &dev_attr_function);
 	device_remove_file (&dev->pdev->dev, &dev_attr_function);
 err_unbind:
 err_unbind:
-	dev->gadget.dev.driver = NULL;
 	dev->driver = NULL;
 	dev->driver = NULL;
 	return retval;
 	return retval;
 }
 }
@@ -1967,7 +1962,6 @@ static int net2280_stop(struct usb_gadget *_gadget,
 	stop_activity (dev, driver);
 	stop_activity (dev, driver);
 	spin_unlock_irqrestore (&dev->lock, flags);
 	spin_unlock_irqrestore (&dev->lock, flags);
 
 
-	dev->gadget.dev.driver = NULL;
 	dev->driver = NULL;
 	dev->driver = NULL;
 
 
 	net2280_led_active (dev, 0);
 	net2280_led_active (dev, 0);
@@ -2072,7 +2066,7 @@ static void handle_ep_small (struct net2280_ep *ep)
 		return;
 		return;
 
 
 	/* manual DMA queue advance after short OUT */
 	/* manual DMA queue advance after short OUT */
-	if (likely (ep->dma != 0)) {
+	if (likely (ep->dma)) {
 		if (t & (1 << SHORT_PACKET_TRANSFERRED_INTERRUPT)) {
 		if (t & (1 << SHORT_PACKET_TRANSFERRED_INTERRUPT)) {
 			u32	count;
 			u32	count;
 			int	stopped = ep->stopped;
 			int	stopped = ep->stopped;
@@ -2330,7 +2324,7 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat)
 			/* hw handles device and interface status */
 			/* hw handles device and interface status */
 			if (u.r.bRequestType != (USB_DIR_IN|USB_RECIP_ENDPOINT))
 			if (u.r.bRequestType != (USB_DIR_IN|USB_RECIP_ENDPOINT))
 				goto delegate;
 				goto delegate;
-			if ((e = get_ep_by_addr (dev, w_index)) == 0
+			if ((e = get_ep_by_addr (dev, w_index)) == NULL
 					|| w_length > 2)
 					|| w_length > 2)
 				goto do_stall;
 				goto do_stall;
 
 
@@ -2358,7 +2352,7 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat)
 			if (w_value != USB_ENDPOINT_HALT
 			if (w_value != USB_ENDPOINT_HALT
 					|| w_length != 0)
 					|| w_length != 0)
 				goto do_stall;
 				goto do_stall;
-			if ((e = get_ep_by_addr (dev, w_index)) == 0)
+			if ((e = get_ep_by_addr (dev, w_index)) == NULL)
 				goto do_stall;
 				goto do_stall;
 			if (e->wedged) {
 			if (e->wedged) {
 				VDEBUG(dev, "%s wedged, halt not cleared\n",
 				VDEBUG(dev, "%s wedged, halt not cleared\n",
@@ -2380,7 +2374,7 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat)
 			if (w_value != USB_ENDPOINT_HALT
 			if (w_value != USB_ENDPOINT_HALT
 					|| w_length != 0)
 					|| w_length != 0)
 				goto do_stall;
 				goto do_stall;
-			if ((e = get_ep_by_addr (dev, w_index)) == 0)
+			if ((e = get_ep_by_addr (dev, w_index)) == NULL)
 				goto do_stall;
 				goto do_stall;
 			if (e->ep.name == ep0name)
 			if (e->ep.name == ep0name)
 				goto do_stall;
 				goto do_stall;
@@ -2685,7 +2679,6 @@ static void net2280_remove (struct pci_dev *pdev)
 				pci_resource_len (pdev, 0));
 				pci_resource_len (pdev, 0));
 	if (dev->enabled)
 	if (dev->enabled)
 		pci_disable_device (pdev);
 		pci_disable_device (pdev);
-	device_unregister (&dev->gadget.dev);
 	device_remove_file (&pdev->dev, &dev_attr_registers);
 	device_remove_file (&pdev->dev, &dev_attr_registers);
 	pci_set_drvdata (pdev, NULL);
 	pci_set_drvdata (pdev, NULL);
 
 
@@ -2717,10 +2710,6 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id)
 	dev->gadget.max_speed = USB_SPEED_HIGH;
 	dev->gadget.max_speed = USB_SPEED_HIGH;
 
 
 	/* the "gadget" abstracts/virtualizes the controller */
 	/* the "gadget" abstracts/virtualizes the controller */
-	dev_set_name(&dev->gadget.dev, "gadget");
-	dev->gadget.dev.parent = &pdev->dev;
-	dev->gadget.dev.dma_mask = pdev->dev.dma_mask;
-	dev->gadget.dev.release = gadget_release;
 	dev->gadget.name = driver_name;
 	dev->gadget.name = driver_name;
 
 
 	/* now all the pci goodies ... */
 	/* now all the pci goodies ... */
@@ -2802,7 +2791,6 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id)
 			goto done;
 			goto done;
 		}
 		}
 		td->dmacount = 0;	/* not VALID */
 		td->dmacount = 0;	/* not VALID */
-		td->dmaaddr = cpu_to_le32 (DMA_ADDR_INVALID);
 		td->dmadesc = td->dmaaddr;
 		td->dmadesc = td->dmaaddr;
 		dev->ep [i].dummy = td;
 		dev->ep [i].dummy = td;
 	}
 	}
@@ -2829,12 +2817,11 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id)
 			use_dma
 			use_dma
 				? (use_dma_chaining ? "chaining" : "enabled")
 				? (use_dma_chaining ? "chaining" : "enabled")
 				: "disabled");
 				: "disabled");
-	retval = device_register (&dev->gadget.dev);
-	if (retval) goto done;
 	retval = device_create_file (&pdev->dev, &dev_attr_registers);
 	retval = device_create_file (&pdev->dev, &dev_attr_registers);
 	if (retval) goto done;
 	if (retval) goto done;
 
 
-	retval = usb_add_gadget_udc(&pdev->dev, &dev->gadget);
+	retval = usb_add_gadget_udc_release(&pdev->dev, &dev->gadget,
+			gadget_release);
 	if (retval)
 	if (retval)
 		goto done;
 		goto done;
 	return 0;
 	return 0;

+ 62 - 33
drivers/usb/gadget/nokia.c

@@ -37,11 +37,9 @@
  * the runtime footprint, and giving us at least some parts of what
  * the runtime footprint, and giving us at least some parts of what
  * a "gcc --combine ... part1.c part2.c part3.c ... " build would.
  * a "gcc --combine ... part1.c part2.c part3.c ... " build would.
  */
  */
-#define USB_FACM_INCLUDED
-#include "f_acm.c"
+#define USBF_OBEX_INCLUDED
 #include "f_ecm.c"
 #include "f_ecm.c"
 #include "f_obex.c"
 #include "f_obex.c"
-#include "f_serial.c"
 #include "f_phonet.c"
 #include "f_phonet.c"
 #include "u_ether.c"
 #include "u_ether.c"
 
 
@@ -98,20 +96,40 @@ MODULE_AUTHOR("Felipe Balbi");
 MODULE_LICENSE("GPL");
 MODULE_LICENSE("GPL");
 
 
 /*-------------------------------------------------------------------------*/
 /*-------------------------------------------------------------------------*/
-
+static struct usb_function *f_acm_cfg1;
+static struct usb_function *f_acm_cfg2;
 static u8 hostaddr[ETH_ALEN];
 static u8 hostaddr[ETH_ALEN];
+static struct eth_dev *the_dev;
 
 
 enum {
 enum {
 	TTY_PORT_OBEX0,
 	TTY_PORT_OBEX0,
 	TTY_PORT_OBEX1,
 	TTY_PORT_OBEX1,
-	TTY_PORT_ACM,
 	TTY_PORTS_MAX,
 	TTY_PORTS_MAX,
 };
 };
 
 
 static unsigned char tty_lines[TTY_PORTS_MAX];
 static unsigned char tty_lines[TTY_PORTS_MAX];
 
 
+static struct usb_configuration nokia_config_500ma_driver = {
+	.label		= "Bus Powered",
+	.bConfigurationValue = 1,
+	/* .iConfiguration = DYNAMIC */
+	.bmAttributes	= USB_CONFIG_ATT_ONE,
+	.MaxPower	= 500,
+};
+
+static struct usb_configuration nokia_config_100ma_driver = {
+	.label		= "Self Powered",
+	.bConfigurationValue = 2,
+	/* .iConfiguration = DYNAMIC */
+	.bmAttributes	= USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
+	.MaxPower	= 100,
+};
+
+static struct usb_function_instance *fi_acm;
+
 static int __init nokia_bind_config(struct usb_configuration *c)
 static int __init nokia_bind_config(struct usb_configuration *c)
 {
 {
+	struct usb_function *f_acm;
 	int status = 0;
 	int status = 0;
 
 
 	status = phonet_bind_config(c);
 	status = phonet_bind_config(c);
@@ -126,33 +144,32 @@ static int __init nokia_bind_config(struct usb_configuration *c)
 	if (status)
 	if (status)
 		printk(KERN_DEBUG "could not bind obex config %d\n", 0);
 		printk(KERN_DEBUG "could not bind obex config %d\n", 0);
 
 
-	status = acm_bind_config(c, tty_lines[TTY_PORT_ACM]);
-	if (status)
-		printk(KERN_DEBUG "could not bind acm config\n");
+	f_acm = usb_get_function(fi_acm);
+	if (IS_ERR(f_acm))
+		return PTR_ERR(f_acm);
 
 
-	status = ecm_bind_config(c, hostaddr);
+	status = usb_add_function(c, f_acm);
 	if (status)
 	if (status)
-		printk(KERN_DEBUG "could not bind ecm config\n");
+		goto err_conf;
+
+	status = ecm_bind_config(c, hostaddr, the_dev);
+	if (status) {
+		pr_debug("could not bind ecm config %d\n", status);
+		goto err_ecm;
+	}
+	if (c == &nokia_config_500ma_driver)
+		f_acm_cfg1 = f_acm;
+	else
+		f_acm_cfg2 = f_acm;
 
 
 	return status;
 	return status;
+err_ecm:
+	usb_remove_function(c, f_acm);
+err_conf:
+	usb_put_function(f_acm);
+	return status;
 }
 }
 
 
-static struct usb_configuration nokia_config_500ma_driver = {
-	.label		= "Bus Powered",
-	.bConfigurationValue = 1,
-	/* .iConfiguration = DYNAMIC */
-	.bmAttributes	= USB_CONFIG_ATT_ONE,
-	.MaxPower	= 500,
-};
-
-static struct usb_configuration nokia_config_100ma_driver = {
-	.label		= "Self Powered",
-	.bConfigurationValue = 2,
-	/* .iConfiguration = DYNAMIC */
-	.bmAttributes	= USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
-	.MaxPower	= 100,
-};
-
 static int __init nokia_bind(struct usb_composite_dev *cdev)
 static int __init nokia_bind(struct usb_composite_dev *cdev)
 {
 {
 	struct usb_gadget	*gadget = cdev->gadget;
 	struct usb_gadget	*gadget = cdev->gadget;
@@ -169,9 +186,11 @@ static int __init nokia_bind(struct usb_composite_dev *cdev)
 			goto err_ether;
 			goto err_ether;
 	}
 	}
 
 
-	status = gether_setup(cdev->gadget, hostaddr);
-	if (status < 0)
+	the_dev = gether_setup(cdev->gadget, hostaddr);
+	if (IS_ERR(the_dev)) {
+		status = PTR_ERR(the_dev);
 		goto err_ether;
 		goto err_ether;
+	}
 
 
 	status = usb_string_ids_tab(cdev, strings_dev);
 	status = usb_string_ids_tab(cdev, strings_dev);
 	if (status < 0)
 	if (status < 0)
@@ -185,24 +204,32 @@ static int __init nokia_bind(struct usb_composite_dev *cdev)
 	if (!gadget_supports_altsettings(gadget))
 	if (!gadget_supports_altsettings(gadget))
 		goto err_usb;
 		goto err_usb;
 
 
+	fi_acm = usb_get_function_instance("acm");
+	if (IS_ERR(fi_acm))
+		goto err_usb;
+
 	/* finally register the configuration */
 	/* finally register the configuration */
 	status = usb_add_config(cdev, &nokia_config_500ma_driver,
 	status = usb_add_config(cdev, &nokia_config_500ma_driver,
 			nokia_bind_config);
 			nokia_bind_config);
 	if (status < 0)
 	if (status < 0)
-		goto err_usb;
+		goto err_acm_inst;
 
 
 	status = usb_add_config(cdev, &nokia_config_100ma_driver,
 	status = usb_add_config(cdev, &nokia_config_100ma_driver,
 			nokia_bind_config);
 			nokia_bind_config);
 	if (status < 0)
 	if (status < 0)
-		goto err_usb;
+		goto err_put_cfg1;
 
 
 	usb_composite_overwrite_options(cdev, &coverwrite);
 	usb_composite_overwrite_options(cdev, &coverwrite);
 	dev_info(&gadget->dev, "%s\n", NOKIA_LONG_NAME);
 	dev_info(&gadget->dev, "%s\n", NOKIA_LONG_NAME);
 
 
 	return 0;
 	return 0;
 
 
+err_put_cfg1:
+	usb_put_function(f_acm_cfg1);
+err_acm_inst:
+	usb_put_function_instance(fi_acm);
 err_usb:
 err_usb:
-	gether_cleanup();
+	gether_cleanup(the_dev);
 err_ether:
 err_ether:
 	cur_line--;
 	cur_line--;
 	while (cur_line >= 0)
 	while (cur_line >= 0)
@@ -217,12 +244,15 @@ static int __exit nokia_unbind(struct usb_composite_dev *cdev)
 {
 {
 	int i;
 	int i;
 
 
+	usb_put_function(f_acm_cfg1);
+	usb_put_function(f_acm_cfg2);
+	usb_put_function_instance(fi_acm);
 	gphonet_cleanup();
 	gphonet_cleanup();
 
 
 	for (i = 0; i < TTY_PORTS_MAX; i++)
 	for (i = 0; i < TTY_PORTS_MAX; i++)
 		gserial_free_line(tty_lines[i]);
 		gserial_free_line(tty_lines[i]);
 
 
-	gether_cleanup();
+	gether_cleanup(the_dev);
 
 
 	return 0;
 	return 0;
 }
 }
@@ -247,4 +277,3 @@ static void __exit nokia_cleanup(void)
 	usb_composite_unregister(&nokia_driver);
 	usb_composite_unregister(&nokia_driver);
 }
 }
 module_exit(nokia_cleanup);
 module_exit(nokia_cleanup);
-

+ 4 - 17
drivers/usb/gadget/omap_udc.c

@@ -2067,7 +2067,6 @@ static int omap_udc_start(struct usb_gadget *g,
 	/* hook up the driver */
 	/* hook up the driver */
 	driver->driver.bus = NULL;
 	driver->driver.bus = NULL;
 	udc->driver = driver;
 	udc->driver = driver;
-	udc->gadget.dev.driver = &driver->driver;
 	spin_unlock_irqrestore(&udc->lock, flags);
 	spin_unlock_irqrestore(&udc->lock, flags);
 
 
 	if (udc->dc_clk != NULL)
 	if (udc->dc_clk != NULL)
@@ -2083,7 +2082,6 @@ static int omap_udc_start(struct usb_gadget *g,
 			ERR("can't bind to transceiver\n");
 			ERR("can't bind to transceiver\n");
 			if (driver->unbind) {
 			if (driver->unbind) {
 				driver->unbind(&udc->gadget);
 				driver->unbind(&udc->gadget);
-				udc->gadget.dev.driver = NULL;
 				udc->driver = NULL;
 				udc->driver = NULL;
 			}
 			}
 			goto done;
 			goto done;
@@ -2129,7 +2127,6 @@ static int omap_udc_stop(struct usb_gadget *g,
 	udc_quiesce(udc);
 	udc_quiesce(udc);
 	spin_unlock_irqrestore(&udc->lock, flags);
 	spin_unlock_irqrestore(&udc->lock, flags);
 
 
-	udc->gadget.dev.driver = NULL;
 	udc->driver = NULL;
 	udc->driver = NULL;
 
 
 	if (udc->dc_clk != NULL)
 	if (udc->dc_clk != NULL)
@@ -2631,14 +2628,6 @@ omap_udc_setup(struct platform_device *odev, struct usb_phy *xceiv)
 	udc->gadget.speed = USB_SPEED_UNKNOWN;
 	udc->gadget.speed = USB_SPEED_UNKNOWN;
 	udc->gadget.max_speed = USB_SPEED_FULL;
 	udc->gadget.max_speed = USB_SPEED_FULL;
 	udc->gadget.name = driver_name;
 	udc->gadget.name = driver_name;
-
-	device_initialize(&udc->gadget.dev);
-	dev_set_name(&udc->gadget.dev, "gadget");
-	udc->gadget.dev.release = omap_udc_release;
-	udc->gadget.dev.parent = &odev->dev;
-	if (use_dma)
-		udc->gadget.dev.dma_mask = odev->dev.dma_mask;
-
 	udc->transceiver = xceiv;
 	udc->transceiver = xceiv;
 
 
 	/* ep0 is special; put it right after the SETUP buffer */
 	/* ep0 is special; put it right after the SETUP buffer */
@@ -2912,14 +2901,13 @@ bad_on_1710:
 	}
 	}
 
 
 	create_proc_file();
 	create_proc_file();
-	status = device_add(&udc->gadget.dev);
+	status = usb_add_gadget_udc_release(&pdev->dev, &udc->gadget,
+			omap_udc_release);
 	if (status)
 	if (status)
 		goto cleanup4;
 		goto cleanup4;
 
 
-	status = usb_add_gadget_udc(&pdev->dev, &udc->gadget);
-	if (!status)
-		return status;
-	/* If fail, fall through */
+	return 0;
+
 cleanup4:
 cleanup4:
 	remove_proc_file();
 	remove_proc_file();
 
 
@@ -2990,7 +2978,6 @@ static int omap_udc_remove(struct platform_device *pdev)
 	release_mem_region(pdev->resource[0].start,
 	release_mem_region(pdev->resource[0].start,
 			pdev->resource[0].end - pdev->resource[0].start + 1);
 			pdev->resource[0].end - pdev->resource[0].start + 1);
 
 
-	device_unregister(&udc->gadget.dev);
 	wait_for_completion(&done);
 	wait_for_completion(&done);
 
 
 	return 0;
 	return 0;

+ 6 - 15
drivers/usb/gadget/pch_udc.c

@@ -358,7 +358,6 @@ struct pch_udc_dev {
 			prot_stall:1,
 			prot_stall:1,
 			irq_registered:1,
 			irq_registered:1,
 			mem_region:1,
 			mem_region:1,
-			registered:1,
 			suspended:1,
 			suspended:1,
 			connected:1,
 			connected:1,
 			vbus_session:1,
 			vbus_session:1,
@@ -1441,6 +1440,8 @@ static void pch_vbus_gpio_free(struct pch_udc_dev *dev)
  */
  */
 static void complete_req(struct pch_udc_ep *ep, struct pch_udc_request *req,
 static void complete_req(struct pch_udc_ep *ep, struct pch_udc_request *req,
 								 int status)
 								 int status)
+	__releases(&dev->lock)
+	__acquires(&dev->lock)
 {
 {
 	struct pch_udc_dev	*dev;
 	struct pch_udc_dev	*dev;
 	unsigned halted = ep->halted;
 	unsigned halted = ep->halted;
@@ -2382,6 +2383,8 @@ static void pch_udc_svc_control_in(struct pch_udc_dev *dev)
  * @dev:	Reference to the device structure
  * @dev:	Reference to the device structure
  */
  */
 static void pch_udc_svc_control_out(struct pch_udc_dev *dev)
 static void pch_udc_svc_control_out(struct pch_udc_dev *dev)
+	__releases(&dev->lock)
+	__acquires(&dev->lock)
 {
 {
 	u32	stat;
 	u32	stat;
 	int setup_supported;
 	int setup_supported;
@@ -2989,7 +2992,6 @@ static int pch_udc_start(struct usb_gadget *g,
 
 
 	driver->driver.bus = NULL;
 	driver->driver.bus = NULL;
 	dev->driver = driver;
 	dev->driver = driver;
-	dev->gadget.dev.driver = &driver->driver;
 
 
 	/* get ready for ep0 traffic */
 	/* get ready for ep0 traffic */
 	pch_udc_setup_ep0(dev);
 	pch_udc_setup_ep0(dev);
@@ -3010,7 +3012,6 @@ static int pch_udc_stop(struct usb_gadget *g,
 	pch_udc_disable_interrupts(dev, UDC_DEVINT_MSK);
 	pch_udc_disable_interrupts(dev, UDC_DEVINT_MSK);
 
 
 	/* Assures that there are no pending requests with this driver */
 	/* Assures that there are no pending requests with this driver */
-	dev->gadget.dev.driver = NULL;
 	dev->driver = NULL;
 	dev->driver = NULL;
 	dev->connected = 0;
 	dev->connected = 0;
 
 
@@ -3078,8 +3079,6 @@ static void pch_udc_remove(struct pci_dev *pdev)
 				   pci_resource_len(pdev, PCH_UDC_PCI_BAR));
 				   pci_resource_len(pdev, PCH_UDC_PCI_BAR));
 	if (dev->active)
 	if (dev->active)
 		pci_disable_device(pdev);
 		pci_disable_device(pdev);
-	if (dev->registered)
-		device_unregister(&dev->gadget.dev);
 	kfree(dev);
 	kfree(dev);
 	pci_set_drvdata(pdev, NULL);
 	pci_set_drvdata(pdev, NULL);
 }
 }
@@ -3196,21 +3195,13 @@ static int pch_udc_probe(struct pci_dev *pdev,
 	if (retval)
 	if (retval)
 		goto finished;
 		goto finished;
 
 
-	dev_set_name(&dev->gadget.dev, "gadget");
-	dev->gadget.dev.parent = &pdev->dev;
-	dev->gadget.dev.dma_mask = pdev->dev.dma_mask;
-	dev->gadget.dev.release = gadget_release;
 	dev->gadget.name = KBUILD_MODNAME;
 	dev->gadget.name = KBUILD_MODNAME;
 	dev->gadget.max_speed = USB_SPEED_HIGH;
 	dev->gadget.max_speed = USB_SPEED_HIGH;
 
 
-	retval = device_register(&dev->gadget.dev);
-	if (retval)
-		goto finished;
-	dev->registered = 1;
-
 	/* Put the device in disconnected state till a driver is bound */
 	/* Put the device in disconnected state till a driver is bound */
 	pch_udc_set_disconnect(dev);
 	pch_udc_set_disconnect(dev);
-	retval = usb_add_gadget_udc(&pdev->dev, &dev->gadget);
+	retval = usb_add_gadget_udc_release(&pdev->dev, &dev->gadget,
+			gadget_release);
 	if (retval)
 	if (retval)
 		goto finished;
 		goto finished;
 	return 0;
 	return 0;

+ 0 - 16
drivers/usb/gadget/pxa25x_udc.c

@@ -1263,7 +1263,6 @@ static int pxa25x_udc_start(struct usb_gadget *g,
 
 
 	/* first hook up the driver ... */
 	/* first hook up the driver ... */
 	dev->driver = driver;
 	dev->driver = driver;
-	dev->gadget.dev.driver = &driver->driver;
 	dev->pullup = 1;
 	dev->pullup = 1;
 
 
 	/* ... then enable host detection and ep0; and we're ready
 	/* ... then enable host detection and ep0; and we're ready
@@ -1325,7 +1324,6 @@ static int pxa25x_udc_stop(struct usb_gadget*g,
 	if (!IS_ERR_OR_NULL(dev->transceiver))
 	if (!IS_ERR_OR_NULL(dev->transceiver))
 		(void) otg_set_peripheral(dev->transceiver->otg, NULL);
 		(void) otg_set_peripheral(dev->transceiver->otg, NULL);
 
 
-	dev->gadget.dev.driver = NULL;
 	dev->driver = NULL;
 	dev->driver = NULL;
 
 
 	dump_state(dev);
 	dump_state(dev);
@@ -2138,17 +2136,6 @@ static int __init pxa25x_udc_probe(struct platform_device *pdev)
 	dev->timer.function = udc_watchdog;
 	dev->timer.function = udc_watchdog;
 	dev->timer.data = (unsigned long) dev;
 	dev->timer.data = (unsigned long) dev;
 
 
-	device_initialize(&dev->gadget.dev);
-	dev->gadget.dev.parent = &pdev->dev;
-	dev->gadget.dev.dma_mask = pdev->dev.dma_mask;
-
-	retval = device_add(&dev->gadget.dev);
-	if (retval) {
-		dev->driver = NULL;
-		dev->gadget.dev.driver = NULL;
-		goto err_device_add;
-	}
-
 	the_controller = dev;
 	the_controller = dev;
 	platform_set_drvdata(pdev, dev);
 	platform_set_drvdata(pdev, dev);
 
 
@@ -2199,8 +2186,6 @@ lubbock_fail0:
 	free_irq(irq, dev);
 	free_irq(irq, dev);
 #endif
 #endif
  err_irq1:
  err_irq1:
-	device_unregister(&dev->gadget.dev);
- err_device_add:
 	if (gpio_is_valid(dev->mach->gpio_pullup))
 	if (gpio_is_valid(dev->mach->gpio_pullup))
 		gpio_free(dev->mach->gpio_pullup);
 		gpio_free(dev->mach->gpio_pullup);
  err_gpio_pullup:
  err_gpio_pullup:
@@ -2226,7 +2211,6 @@ static int __exit pxa25x_udc_remove(struct platform_device *pdev)
 		return -EBUSY;
 		return -EBUSY;
 
 
 	usb_del_gadget_udc(&dev->gadget);
 	usb_del_gadget_udc(&dev->gadget);
-	device_unregister(&dev->gadget.dev);
 	dev->pullup = 0;
 	dev->pullup = 0;
 	pullup(dev);
 	pullup(dev);
 
 

+ 10 - 41
drivers/usb/gadget/pxa27x_udc.c

@@ -24,14 +24,12 @@
 #include <linux/gpio.h>
 #include <linux/gpio.h>
 #include <linux/slab.h>
 #include <linux/slab.h>
 #include <linux/prefetch.h>
 #include <linux/prefetch.h>
-
-#include <asm/byteorder.h>
-#include <mach/hardware.h>
+#include <linux/byteorder/generic.h>
+#include <linux/platform_data/pxa2xx_udc.h>
 
 
 #include <linux/usb.h>
 #include <linux/usb.h>
 #include <linux/usb/ch9.h>
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
 #include <linux/usb/gadget.h>
-#include <mach/udc.h>
 
 
 #include "pxa27x_udc.h"
 #include "pxa27x_udc.h"
 
 
@@ -611,7 +609,7 @@ static void inc_ep_stats_bytes(struct pxa_ep *ep, int count, int is_in)
  *
  *
  * Find the physical pxa27x ep, and setup its UDCCR
  * Find the physical pxa27x ep, and setup its UDCCR
  */
  */
-static __init void pxa_ep_setup(struct pxa_ep *ep)
+static void pxa_ep_setup(struct pxa_ep *ep)
 {
 {
 	u32 new_udccr;
 	u32 new_udccr;
 
 
@@ -633,7 +631,7 @@ static __init void pxa_ep_setup(struct pxa_ep *ep)
  *
  *
  * Setup all pxa physical endpoints, except ep0
  * Setup all pxa physical endpoints, except ep0
  */
  */
-static __init void pxa_eps_setup(struct pxa_udc *dev)
+static void pxa_eps_setup(struct pxa_udc *dev)
 {
 {
 	unsigned int i;
 	unsigned int i;
 
 
@@ -1718,7 +1716,7 @@ static void udc_disable(struct pxa_udc *udc)
  * Initializes gadget endpoint list, endpoints locks. No action is taken
  * Initializes gadget endpoint list, endpoints locks. No action is taken
  * on the hardware.
  * on the hardware.
  */
  */
-static __init void udc_init_data(struct pxa_udc *dev)
+static void udc_init_data(struct pxa_udc *dev)
 {
 {
 	int i;
 	int i;
 	struct pxa_ep *ep;
 	struct pxa_ep *ep;
@@ -1811,7 +1809,6 @@ static int pxa27x_udc_start(struct usb_gadget *g,
 
 
 	/* first hook up the driver ... */
 	/* first hook up the driver ... */
 	udc->driver = driver;
 	udc->driver = driver;
-	udc->gadget.dev.driver = &driver->driver;
 	dplus_pullup(udc, 1);
 	dplus_pullup(udc, 1);
 
 
 	if (!IS_ERR_OR_NULL(udc->transceiver)) {
 	if (!IS_ERR_OR_NULL(udc->transceiver)) {
@@ -1829,7 +1826,6 @@ static int pxa27x_udc_start(struct usb_gadget *g,
 
 
 fail:
 fail:
 	udc->driver = NULL;
 	udc->driver = NULL;
-	udc->gadget.dev.driver = NULL;
 	return retval;
 	return retval;
 }
 }
 
 
@@ -1871,7 +1867,6 @@ static int pxa27x_udc_stop(struct usb_gadget *g,
 
 
 	udc->driver = NULL;
 	udc->driver = NULL;
 
 
-
 	if (!IS_ERR_OR_NULL(udc->transceiver))
 	if (!IS_ERR_OR_NULL(udc->transceiver))
 		return otg_set_peripheral(udc->transceiver->otg, NULL);
 		return otg_set_peripheral(udc->transceiver->otg, NULL);
 	return 0;
 	return 0;
@@ -2413,7 +2408,7 @@ static struct pxa_udc memory = {
  * Perform basic init : allocates udc clock, creates sysfs files, requests
  * Perform basic init : allocates udc clock, creates sysfs files, requests
  * irq.
  * irq.
  */
  */
-static int __init pxa_udc_probe(struct platform_device *pdev)
+static int pxa_udc_probe(struct platform_device *pdev)
 {
 {
 	struct resource *regs;
 	struct resource *regs;
 	struct pxa_udc *udc = &memory;
 	struct pxa_udc *udc = &memory;
@@ -2456,9 +2451,6 @@ static int __init pxa_udc_probe(struct platform_device *pdev)
 		goto err_map;
 		goto err_map;
 	}
 	}
 
 
-	device_initialize(&udc->gadget.dev);
-	udc->gadget.dev.parent = &pdev->dev;
-	udc->gadget.dev.dma_mask = NULL;
 	udc->vbus_sensed = 0;
 	udc->vbus_sensed = 0;
 
 
 	the_controller = udc;
 	the_controller = udc;
@@ -2475,12 +2467,6 @@ static int __init pxa_udc_probe(struct platform_device *pdev)
 		goto err_irq;
 		goto err_irq;
 	}
 	}
 
 
-	retval = device_add(&udc->gadget.dev);
-	if (retval) {
-		dev_err(udc->dev, "device_add error %d\n", retval);
-		goto err_dev_add;
-	}
-
 	retval = usb_add_gadget_udc(&pdev->dev, &udc->gadget);
 	retval = usb_add_gadget_udc(&pdev->dev, &udc->gadget);
 	if (retval)
 	if (retval)
 		goto err_add_udc;
 		goto err_add_udc;
@@ -2490,8 +2476,6 @@ static int __init pxa_udc_probe(struct platform_device *pdev)
 	return 0;
 	return 0;
 
 
 err_add_udc:
 err_add_udc:
-	device_unregister(&udc->gadget.dev);
-err_dev_add:
 	free_irq(udc->irq, udc);
 	free_irq(udc->irq, udc);
 err_irq:
 err_irq:
 	iounmap(udc->regs);
 	iounmap(udc->regs);
@@ -2506,13 +2490,12 @@ err_clk:
  * pxa_udc_remove - removes the udc device driver
  * pxa_udc_remove - removes the udc device driver
  * @_dev: platform device
  * @_dev: platform device
  */
  */
-static int __exit pxa_udc_remove(struct platform_device *_dev)
+static int pxa_udc_remove(struct platform_device *_dev)
 {
 {
 	struct pxa_udc *udc = platform_get_drvdata(_dev);
 	struct pxa_udc *udc = platform_get_drvdata(_dev);
 	int gpio = udc->mach->gpio_pullup;
 	int gpio = udc->mach->gpio_pullup;
 
 
 	usb_del_gadget_udc(&udc->gadget);
 	usb_del_gadget_udc(&udc->gadget);
-	device_del(&udc->gadget.dev);
 	usb_gadget_unregister_driver(udc->driver);
 	usb_gadget_unregister_driver(udc->driver);
 	free_irq(udc->irq, udc);
 	free_irq(udc->irq, udc);
 	pxa_cleanup_debugfs(udc);
 	pxa_cleanup_debugfs(udc);
@@ -2625,7 +2608,8 @@ static struct platform_driver udc_driver = {
 		.name	= "pxa27x-udc",
 		.name	= "pxa27x-udc",
 		.owner	= THIS_MODULE,
 		.owner	= THIS_MODULE,
 	},
 	},
-	.remove		= __exit_p(pxa_udc_remove),
+	.probe		= pxa_udc_probe,
+	.remove		= pxa_udc_remove,
 	.shutdown	= pxa_udc_shutdown,
 	.shutdown	= pxa_udc_shutdown,
 #ifdef CONFIG_PM
 #ifdef CONFIG_PM
 	.suspend	= pxa_udc_suspend,
 	.suspend	= pxa_udc_suspend,
@@ -2633,22 +2617,7 @@ static struct platform_driver udc_driver = {
 #endif
 #endif
 };
 };
 
 
-static int __init udc_init(void)
-{
-	if (!cpu_is_pxa27x() && !cpu_is_pxa3xx())
-		return -ENODEV;
-
-	printk(KERN_INFO "%s: version %s\n", driver_name, DRIVER_VERSION);
-	return platform_driver_probe(&udc_driver, pxa_udc_probe);
-}
-module_init(udc_init);
-
-
-static void __exit udc_exit(void)
-{
-	platform_driver_unregister(&udc_driver);
-}
-module_exit(udc_exit);
+module_platform_driver(udc_driver);
 
 
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_AUTHOR("Robert Jarzmik");
 MODULE_AUTHOR("Robert Jarzmik");

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

@@ -1837,7 +1837,6 @@ static int __exit r8a66597_remove(struct platform_device *pdev)
 		clk_put(r8a66597->clk);
 		clk_put(r8a66597->clk);
 	}
 	}
 
 
-	device_unregister(&r8a66597->gadget.dev);
 	kfree(r8a66597);
 	kfree(r8a66597);
 	return 0;
 	return 0;
 }
 }
@@ -1915,17 +1914,8 @@ static int __init r8a66597_probe(struct platform_device *pdev)
 	r8a66597->irq_sense_low = irq_trigger == IRQF_TRIGGER_LOW;
 	r8a66597->irq_sense_low = irq_trigger == IRQF_TRIGGER_LOW;
 
 
 	r8a66597->gadget.ops = &r8a66597_gadget_ops;
 	r8a66597->gadget.ops = &r8a66597_gadget_ops;
-	dev_set_name(&r8a66597->gadget.dev, "gadget");
 	r8a66597->gadget.max_speed = USB_SPEED_HIGH;
 	r8a66597->gadget.max_speed = USB_SPEED_HIGH;
-	r8a66597->gadget.dev.parent = &pdev->dev;
-	r8a66597->gadget.dev.dma_mask = pdev->dev.dma_mask;
-	r8a66597->gadget.dev.release = pdev->dev.release;
 	r8a66597->gadget.name = udc_name;
 	r8a66597->gadget.name = udc_name;
-	ret = device_register(&r8a66597->gadget.dev);
-	if (ret < 0) {
-		dev_err(&pdev->dev, "device_register failed\n");
-		goto clean_up;
-	}
 
 
 	init_timer(&r8a66597->timer);
 	init_timer(&r8a66597->timer);
 	r8a66597->timer.function = r8a66597_timer;
 	r8a66597->timer.function = r8a66597_timer;
@@ -1939,7 +1929,7 @@ static int __init r8a66597_probe(struct platform_device *pdev)
 			dev_err(&pdev->dev, "cannot get clock \"%s\"\n",
 			dev_err(&pdev->dev, "cannot get clock \"%s\"\n",
 				clk_name);
 				clk_name);
 			ret = PTR_ERR(r8a66597->clk);
 			ret = PTR_ERR(r8a66597->clk);
-			goto clean_up_dev;
+			goto clean_up;
 		}
 		}
 		clk_enable(r8a66597->clk);
 		clk_enable(r8a66597->clk);
 	}
 	}
@@ -2007,8 +1997,6 @@ clean_up2:
 		clk_disable(r8a66597->clk);
 		clk_disable(r8a66597->clk);
 		clk_put(r8a66597->clk);
 		clk_put(r8a66597->clk);
 	}
 	}
-clean_up_dev:
-	device_unregister(&r8a66597->gadget.dev);
 clean_up:
 clean_up:
 	if (r8a66597) {
 	if (r8a66597) {
 		if (r8a66597->sudmac_reg)
 		if (r8a66597->sudmac_reg)

+ 6 - 72
drivers/usb/gadget/s3c-hsotg.c

@@ -39,8 +39,6 @@
 
 
 #include "s3c-hsotg.h"
 #include "s3c-hsotg.h"
 
 
-#define DMA_ADDR_INVALID (~((dma_addr_t)0))
-
 static const char * const s3c_hsotg_supply_names[] = {
 static const char * const s3c_hsotg_supply_names[] = {
 	"vusb_d",		/* digital USB supply, 1.2V */
 	"vusb_d",		/* digital USB supply, 1.2V */
 	"vusb_a",		/* analog USB supply, 1.1V */
 	"vusb_a",		/* analog USB supply, 1.1V */
@@ -405,7 +403,6 @@ static struct usb_request *s3c_hsotg_ep_alloc_request(struct usb_ep *ep,
 
 
 	INIT_LIST_HEAD(&req->queue);
 	INIT_LIST_HEAD(&req->queue);
 
 
-	req->req.dma = DMA_ADDR_INVALID;
 	return &req->req;
 	return &req->req;
 }
 }
 
 
@@ -435,24 +432,12 @@ static void s3c_hsotg_unmap_dma(struct s3c_hsotg *hsotg,
 				struct s3c_hsotg_req *hs_req)
 				struct s3c_hsotg_req *hs_req)
 {
 {
 	struct usb_request *req = &hs_req->req;
 	struct usb_request *req = &hs_req->req;
-	enum dma_data_direction dir;
-
-	dir = hs_ep->dir_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
 
 
 	/* ignore this if we're not moving any data */
 	/* ignore this if we're not moving any data */
 	if (hs_req->req.length == 0)
 	if (hs_req->req.length == 0)
 		return;
 		return;
 
 
-	if (hs_req->mapped) {
-		/* we mapped this, so unmap and remove the dma */
-
-		dma_unmap_single(hsotg->dev, req->dma, req->length, dir);
-
-		req->dma = DMA_ADDR_INVALID;
-		hs_req->mapped = 0;
-	} else {
-		dma_sync_single_for_cpu(hsotg->dev, req->dma, req->length, dir);
-	}
+	usb_gadget_unmap_request(&hsotg->gadget, hs_req, hs_ep->dir_in);
 }
 }
 
 
 /**
 /**
@@ -852,37 +837,16 @@ static int s3c_hsotg_map_dma(struct s3c_hsotg *hsotg,
 			     struct s3c_hsotg_ep *hs_ep,
 			     struct s3c_hsotg_ep *hs_ep,
 			     struct usb_request *req)
 			     struct usb_request *req)
 {
 {
-	enum dma_data_direction dir;
 	struct s3c_hsotg_req *hs_req = our_req(req);
 	struct s3c_hsotg_req *hs_req = our_req(req);
-
-	dir = hs_ep->dir_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+	int ret;
 
 
 	/* if the length is zero, ignore the DMA data */
 	/* if the length is zero, ignore the DMA data */
 	if (hs_req->req.length == 0)
 	if (hs_req->req.length == 0)
 		return 0;
 		return 0;
 
 
-	if (req->dma == DMA_ADDR_INVALID) {
-		dma_addr_t dma;
-
-		dma = dma_map_single(hsotg->dev, req->buf, req->length, dir);
-
-		if (unlikely(dma_mapping_error(hsotg->dev, dma)))
-			goto dma_error;
-
-		if (dma & 3) {
-			dev_err(hsotg->dev, "%s: unaligned dma buffer\n",
-				__func__);
-
-			dma_unmap_single(hsotg->dev, dma, req->length, dir);
-			return -EINVAL;
-		}
-
-		hs_req->mapped = 1;
-		req->dma = dma;
-	} else {
-		dma_sync_single_for_cpu(hsotg->dev, req->dma, req->length, dir);
-		hs_req->mapped = 0;
-	}
+	ret = usb_gadget_map_request(&hsotg->gadget, req, hs_ep->dir_in);
+	if (ret)
+		goto dma_error;
 
 
 	return 0;
 	return 0;
 
 
@@ -2961,9 +2925,7 @@ static int s3c_hsotg_udc_start(struct usb_gadget *gadget,
 
 
 	driver->driver.bus = NULL;
 	driver->driver.bus = NULL;
 	hsotg->driver = driver;
 	hsotg->driver = driver;
-	hsotg->gadget.dev.driver = &driver->driver;
 	hsotg->gadget.dev.of_node = hsotg->dev->of_node;
 	hsotg->gadget.dev.of_node = hsotg->dev->of_node;
-	hsotg->gadget.dev.dma_mask = hsotg->dev->dma_mask;
 	hsotg->gadget.speed = USB_SPEED_UNKNOWN;
 	hsotg->gadget.speed = USB_SPEED_UNKNOWN;
 
 
 	ret = regulator_bulk_enable(ARRAY_SIZE(hsotg->supplies),
 	ret = regulator_bulk_enable(ARRAY_SIZE(hsotg->supplies),
@@ -2979,7 +2941,6 @@ static int s3c_hsotg_udc_start(struct usb_gadget *gadget,
 
 
 err:
 err:
 	hsotg->driver = NULL;
 	hsotg->driver = NULL;
-	hsotg->gadget.dev.driver = NULL;
 	return ret;
 	return ret;
 }
 }
 
 
@@ -3014,7 +2975,6 @@ static int s3c_hsotg_udc_stop(struct usb_gadget *gadget,
 
 
 	hsotg->driver = NULL;
 	hsotg->driver = NULL;
 	hsotg->gadget.speed = USB_SPEED_UNKNOWN;
 	hsotg->gadget.speed = USB_SPEED_UNKNOWN;
-	hsotg->gadget.dev.driver = NULL;
 
 
 	spin_unlock_irqrestore(&hsotg->lock, flags);
 	spin_unlock_irqrestore(&hsotg->lock, flags);
 
 
@@ -3483,16 +3443,6 @@ static void s3c_hsotg_delete_debug(struct s3c_hsotg *hsotg)
 	debugfs_remove(hsotg->debug_root);
 	debugfs_remove(hsotg->debug_root);
 }
 }
 
 
-/**
- * s3c_hsotg_release - release callback for hsotg device
- * @dev: Device to for which release is called
- *
- * Nothing to do as the resource is allocated using devm_ API.
- */
-static void s3c_hsotg_release(struct device *dev)
-{
-}
-
 /**
 /**
  * s3c_hsotg_probe - probe function for hsotg driver
  * s3c_hsotg_probe - probe function for hsotg driver
  * @pdev: The platform information for the driver
  * @pdev: The platform information for the driver
@@ -3517,7 +3467,7 @@ static int s3c_hsotg_probe(struct platform_device *pdev)
 	}
 	}
 
 
 	phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
 	phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
-	if (IS_ERR_OR_NULL(phy)) {
+	if (IS_ERR(phy)) {
 		/* Fallback for pdata */
 		/* Fallback for pdata */
 		plat = pdev->dev.platform_data;
 		plat = pdev->dev.platform_data;
 		if (!plat) {
 		if (!plat) {
@@ -3567,18 +3517,10 @@ static int s3c_hsotg_probe(struct platform_device *pdev)
 
 
 	dev_info(dev, "regs %p, irq %d\n", hsotg->regs, hsotg->irq);
 	dev_info(dev, "regs %p, irq %d\n", hsotg->regs, hsotg->irq);
 
 
-	device_initialize(&hsotg->gadget.dev);
-
-	dev_set_name(&hsotg->gadget.dev, "gadget");
-
 	hsotg->gadget.max_speed = USB_SPEED_HIGH;
 	hsotg->gadget.max_speed = USB_SPEED_HIGH;
 	hsotg->gadget.ops = &s3c_hsotg_gadget_ops;
 	hsotg->gadget.ops = &s3c_hsotg_gadget_ops;
 	hsotg->gadget.name = dev_name(dev);
 	hsotg->gadget.name = dev_name(dev);
 
 
-	hsotg->gadget.dev.parent = dev;
-	hsotg->gadget.dev.dma_mask = dev->dma_mask;
-	hsotg->gadget.dev.release = s3c_hsotg_release;
-
 	/* reset the system */
 	/* reset the system */
 
 
 	clk_prepare_enable(hsotg->clk);
 	clk_prepare_enable(hsotg->clk);
@@ -3658,12 +3600,6 @@ static int s3c_hsotg_probe(struct platform_device *pdev)
 
 
 	s3c_hsotg_phy_disable(hsotg);
 	s3c_hsotg_phy_disable(hsotg);
 
 
-	ret = device_add(&hsotg->gadget.dev);
-	if (ret) {
-		put_device(&hsotg->gadget.dev);
-		goto err_ep_mem;
-	}
-
 	ret = usb_add_gadget_udc(&pdev->dev, &hsotg->gadget);
 	ret = usb_add_gadget_udc(&pdev->dev, &hsotg->gadget);
 	if (ret)
 	if (ret)
 		goto err_ep_mem;
 		goto err_ep_mem;
@@ -3702,10 +3638,8 @@ static int s3c_hsotg_remove(struct platform_device *pdev)
 	}
 	}
 
 
 	s3c_hsotg_phy_disable(hsotg);
 	s3c_hsotg_phy_disable(hsotg);
-
 	clk_disable_unprepare(hsotg->clk);
 	clk_disable_unprepare(hsotg->clk);
 
 
-	device_unregister(&hsotg->gadget.dev);
 	return 0;
 	return 0;
 }
 }
 
 

+ 0 - 16
drivers/usb/gadget/s3c-hsudc.c

@@ -283,7 +283,6 @@ static void s3c_hsudc_nuke_ep(struct s3c_hsudc_ep *hsep, int status)
 /**
 /**
  * s3c_hsudc_stop_activity - Stop activity on all endpoints.
  * s3c_hsudc_stop_activity - Stop activity on all endpoints.
  * @hsudc: Device controller for which EP activity is to be stopped.
  * @hsudc: Device controller for which EP activity is to be stopped.
- * @driver: Reference to the gadget driver which is currently active.
  *
  *
  * All the endpoints are stopped and any pending transfer requests if any on
  * All the endpoints are stopped and any pending transfer requests if any on
  * the endpoint are terminated.
  * the endpoint are terminated.
@@ -1154,7 +1153,6 @@ static int s3c_hsudc_start(struct usb_gadget *gadget,
 		return -EBUSY;
 		return -EBUSY;
 
 
 	hsudc->driver = driver;
 	hsudc->driver = driver;
-	hsudc->gadget.dev.driver = &driver->driver;
 
 
 	ret = regulator_bulk_enable(ARRAY_SIZE(hsudc->supplies),
 	ret = regulator_bulk_enable(ARRAY_SIZE(hsudc->supplies),
 				    hsudc->supplies);
 				    hsudc->supplies);
@@ -1190,7 +1188,6 @@ err_otg:
 	regulator_bulk_disable(ARRAY_SIZE(hsudc->supplies), hsudc->supplies);
 	regulator_bulk_disable(ARRAY_SIZE(hsudc->supplies), hsudc->supplies);
 err_supplies:
 err_supplies:
 	hsudc->driver = NULL;
 	hsudc->driver = NULL;
-	hsudc->gadget.dev.driver = NULL;
 	return ret;
 	return ret;
 }
 }
 
 
@@ -1208,7 +1205,6 @@ static int s3c_hsudc_stop(struct usb_gadget *gadget,
 
 
 	spin_lock_irqsave(&hsudc->lock, flags);
 	spin_lock_irqsave(&hsudc->lock, flags);
 	hsudc->driver = NULL;
 	hsudc->driver = NULL;
-	hsudc->gadget.dev.driver = NULL;
 	hsudc->gadget.speed = USB_SPEED_UNKNOWN;
 	hsudc->gadget.speed = USB_SPEED_UNKNOWN;
 	s3c_hsudc_uninit_phy();
 	s3c_hsudc_uninit_phy();
 
 
@@ -1303,15 +1299,10 @@ static int s3c_hsudc_probe(struct platform_device *pdev)
 
 
 	spin_lock_init(&hsudc->lock);
 	spin_lock_init(&hsudc->lock);
 
 
-	dev_set_name(&hsudc->gadget.dev, "gadget");
-
 	hsudc->gadget.max_speed = USB_SPEED_HIGH;
 	hsudc->gadget.max_speed = USB_SPEED_HIGH;
 	hsudc->gadget.ops = &s3c_hsudc_gadget_ops;
 	hsudc->gadget.ops = &s3c_hsudc_gadget_ops;
 	hsudc->gadget.name = dev_name(dev);
 	hsudc->gadget.name = dev_name(dev);
-	hsudc->gadget.dev.parent = dev;
-	hsudc->gadget.dev.dma_mask = dev->dma_mask;
 	hsudc->gadget.ep0 = &hsudc->ep[0].ep;
 	hsudc->gadget.ep0 = &hsudc->ep[0].ep;
-
 	hsudc->gadget.is_otg = 0;
 	hsudc->gadget.is_otg = 0;
 	hsudc->gadget.is_a_peripheral = 0;
 	hsudc->gadget.is_a_peripheral = 0;
 	hsudc->gadget.speed = USB_SPEED_UNKNOWN;
 	hsudc->gadget.speed = USB_SPEED_UNKNOWN;
@@ -1345,12 +1336,6 @@ static int s3c_hsudc_probe(struct platform_device *pdev)
 	disable_irq(hsudc->irq);
 	disable_irq(hsudc->irq);
 	local_irq_enable();
 	local_irq_enable();
 
 
-	ret = device_register(&hsudc->gadget.dev);
-	if (ret) {
-		put_device(&hsudc->gadget.dev);
-		goto err_add_device;
-	}
-
 	ret = usb_add_gadget_udc(&pdev->dev, &hsudc->gadget);
 	ret = usb_add_gadget_udc(&pdev->dev, &hsudc->gadget);
 	if (ret)
 	if (ret)
 		goto err_add_udc;
 		goto err_add_udc;
@@ -1359,7 +1344,6 @@ static int s3c_hsudc_probe(struct platform_device *pdev)
 
 
 	return 0;
 	return 0;
 err_add_udc:
 err_add_udc:
-	device_unregister(&hsudc->gadget.dev);
 err_add_device:
 err_add_device:
 	clk_disable(hsudc->uclk);
 	clk_disable(hsudc->uclk);
 err_res:
 err_res:

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

@@ -1674,7 +1674,6 @@ static int s3c2410_udc_start(struct usb_gadget *g,
 
 
 	/* Hook the driver */
 	/* Hook the driver */
 	udc->driver = driver;
 	udc->driver = driver;
-	udc->gadget.dev.driver = &driver->driver;
 
 
 	/* Enable udc */
 	/* Enable udc */
 	s3c2410_udc_enable(udc);
 	s3c2410_udc_enable(udc);
@@ -1824,17 +1823,6 @@ static int s3c2410_udc_probe(struct platform_device *pdev)
 		goto err_mem;
 		goto err_mem;
 	}
 	}
 
 
-	device_initialize(&udc->gadget.dev);
-	udc->gadget.dev.parent = &pdev->dev;
-	udc->gadget.dev.dma_mask = pdev->dev.dma_mask;
-
-	/* Bind the driver */
-	retval = device_add(&udc->gadget.dev);
-	if (retval) {
-		dev_err(&udc->gadget.dev, "Error in device_add() : %d\n", retval);
-		goto err_device_add;
-	}
-
 	the_controller = udc;
 	the_controller = udc;
 	platform_set_drvdata(pdev, udc);
 	platform_set_drvdata(pdev, udc);
 
 
@@ -1923,8 +1911,6 @@ err_gpio_claim:
 err_int:
 err_int:
 	free_irq(IRQ_USBD, udc);
 	free_irq(IRQ_USBD, udc);
 err_map:
 err_map:
-	device_unregister(&udc->gadget.dev);
-err_device_add:
 	iounmap(base_addr);
 	iounmap(base_addr);
 err_mem:
 err_mem:
 	release_mem_region(rsrc_start, rsrc_len);
 	release_mem_region(rsrc_start, rsrc_len);
@@ -1946,7 +1932,6 @@ static int s3c2410_udc_remove(struct platform_device *pdev)
 		return -EBUSY;
 		return -EBUSY;
 
 
 	usb_del_gadget_udc(&udc->gadget);
 	usb_del_gadget_udc(&udc->gadget);
-	device_unregister(&udc->gadget.dev);
 	debugfs_remove(udc->regs_info);
 	debugfs_remove(udc->regs_info);
 
 
 	if (udc_info && !udc_info->udc_command &&
 	if (udc_info && !udc_info->udc_command &&

+ 7 - 52
drivers/usb/gadget/serial.c

@@ -12,6 +12,7 @@
 
 
 #include <linux/kernel.h>
 #include <linux/kernel.h>
 #include <linux/device.h>
 #include <linux/device.h>
+#include <linux/module.h>
 #include <linux/tty.h>
 #include <linux/tty.h>
 #include <linux/tty_flip.h>
 #include <linux/tty_flip.h>
 
 
@@ -27,18 +28,6 @@
 #define GS_LONG_NAME			"Gadget Serial"
 #define GS_LONG_NAME			"Gadget Serial"
 #define GS_VERSION_NAME			GS_LONG_NAME " " GS_VERSION_STR
 #define GS_VERSION_NAME			GS_LONG_NAME " " GS_VERSION_STR
 
 
-/*-------------------------------------------------------------------------*/
-
-/*
- * Kbuild is not very cooperative with respect to linking separately
- * compiled library objects into one module.  So for now we won't use
- * separate compilation ... ensuring init/exit sections work to shrink
- * the runtime footprint, and giving us at least some parts of what
- * a "gcc --combine ... part1.c part2.c part3.c ... " build would.
- */
-#include "f_obex.c"
-#include "f_serial.c"
-
 /*-------------------------------------------------------------------------*/
 /*-------------------------------------------------------------------------*/
 USB_GADGET_COMPOSITE_OPTIONS();
 USB_GADGET_COMPOSITE_OPTIONS();
 
 
@@ -126,27 +115,6 @@ module_param(n_ports, uint, 0);
 MODULE_PARM_DESC(n_ports, "number of ports to create, default=1");
 MODULE_PARM_DESC(n_ports, "number of ports to create, default=1");
 
 
 /*-------------------------------------------------------------------------*/
 /*-------------------------------------------------------------------------*/
-static unsigned char tty_lines[MAX_U_SERIAL_PORTS];
-
-static int __init serial_bind_obex_config(struct usb_configuration *c)
-{
-	unsigned i;
-	int status = 0;
-
-	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;
-}
 
 
 static struct usb_configuration serial_config_driver = {
 static struct usb_configuration serial_config_driver = {
 	/* .label = f(use_acm) */
 	/* .label = f(use_acm) */
@@ -169,15 +137,12 @@ static int serial_register_ports(struct usb_composite_dev *cdev,
 		goto out;
 		goto out;
 
 
 	for (i = 0; i < n_ports; i++) {
 	for (i = 0; i < n_ports; i++) {
-		struct f_serial_opts *opts;
 
 
 		fi_serial[i] = usb_get_function_instance(f_name);
 		fi_serial[i] = usb_get_function_instance(f_name);
 		if (IS_ERR(fi_serial[i])) {
 		if (IS_ERR(fi_serial[i])) {
 			ret = PTR_ERR(fi_serial[i]);
 			ret = PTR_ERR(fi_serial[i]);
 			goto fail;
 			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]);
 		f_serial[i] = usb_get_function(fi_serial[i]);
 		if (IS_ERR(f_serial[i])) {
 		if (IS_ERR(f_serial[i])) {
@@ -212,13 +177,6 @@ out:
 static int __init gs_bind(struct usb_composite_dev *cdev)
 static int __init gs_bind(struct usb_composite_dev *cdev)
 {
 {
 	int			status;
 	int			status;
-	int			cur_line;
-
-	for (cur_line = 0; cur_line < n_ports; cur_line++) {
-		status = gserial_alloc_line(&tty_lines[cur_line]);
-		if (status)
-			goto fail;
-	}
 
 
 	/* Allocate string descriptor numbers ... note that string
 	/* Allocate string descriptor numbers ... note that string
 	 * contents can be overridden by the composite_dev glue.
 	 * contents can be overridden by the composite_dev glue.
@@ -243,11 +201,12 @@ static int __init gs_bind(struct usb_composite_dev *cdev)
 				"acm");
 				"acm");
 		usb_ep_autoconfig_reset(cdev->gadget);
 		usb_ep_autoconfig_reset(cdev->gadget);
 	} else if (use_obex)
 	} 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);
+		status = serial_register_ports(cdev, &serial_config_driver,
+				"obex");
+	else {
+		status = serial_register_ports(cdev, &serial_config_driver,
+				"gser");
+	}
 	if (status < 0)
 	if (status < 0)
 		goto fail;
 		goto fail;
 
 
@@ -257,9 +216,6 @@ static int __init gs_bind(struct usb_composite_dev *cdev)
 	return 0;
 	return 0;
 
 
 fail:
 fail:
-	cur_line--;
-	while (cur_line >= 0)
-		gserial_free_line(tty_lines[cur_line--]);
 	return status;
 	return status;
 }
 }
 
 
@@ -270,7 +226,6 @@ static int gs_unbind(struct usb_composite_dev *cdev)
 	for (i = 0; i < n_ports; i++) {
 	for (i = 0; i < n_ports; i++) {
 		usb_put_function(f_serial[i]);
 		usb_put_function(f_serial[i]);
 		usb_put_function_instance(fi_serial[i]);
 		usb_put_function_instance(fi_serial[i]);
-		gserial_free_line(tty_lines[i]);
 	}
 	}
 	return 0;
 	return 0;
 }
 }

+ 10 - 22
drivers/usb/gadget/u_ether.c

@@ -50,7 +50,6 @@
 
 
 struct eth_dev {
 struct eth_dev {
 	/* lock is held while accessing port_usb
 	/* lock is held while accessing port_usb
-	 * or updating its backlink port_usb->ioport
 	 */
 	 */
 	spinlock_t		lock;
 	spinlock_t		lock;
 	struct gether		*port_usb;
 	struct gether		*port_usb;
@@ -729,8 +728,6 @@ static int get_ether_addr(const char *str, u8 *dev_addr)
 	return 1;
 	return 1;
 }
 }
 
 
-static struct eth_dev *the_dev;
-
 static const struct net_device_ops eth_netdev_ops = {
 static const struct net_device_ops eth_netdev_ops = {
 	.ndo_open		= eth_open,
 	.ndo_open		= eth_open,
 	.ndo_stop		= eth_stop,
 	.ndo_stop		= eth_stop,
@@ -758,19 +755,16 @@ static struct device_type gadget_type = {
  *
  *
  * Returns negative errno, or zero on success
  * Returns negative errno, or zero on success
  */
  */
-int gether_setup_name(struct usb_gadget *g, u8 ethaddr[ETH_ALEN],
+struct eth_dev *gether_setup_name(struct usb_gadget *g, u8 ethaddr[ETH_ALEN],
 		const char *netname)
 		const char *netname)
 {
 {
 	struct eth_dev		*dev;
 	struct eth_dev		*dev;
 	struct net_device	*net;
 	struct net_device	*net;
 	int			status;
 	int			status;
 
 
-	if (the_dev)
-		return -EBUSY;
-
 	net = alloc_etherdev(sizeof *dev);
 	net = alloc_etherdev(sizeof *dev);
 	if (!net)
 	if (!net)
-		return -ENOMEM;
+		return ERR_PTR(-ENOMEM);
 
 
 	dev = netdev_priv(net);
 	dev = netdev_priv(net);
 	spin_lock_init(&dev->lock);
 	spin_lock_init(&dev->lock);
@@ -807,12 +801,11 @@ int gether_setup_name(struct usb_gadget *g, u8 ethaddr[ETH_ALEN],
 	if (status < 0) {
 	if (status < 0) {
 		dev_dbg(&g->dev, "register_netdev failed, %d\n", status);
 		dev_dbg(&g->dev, "register_netdev failed, %d\n", status);
 		free_netdev(net);
 		free_netdev(net);
+		dev = ERR_PTR(status);
 	} else {
 	} else {
 		INFO(dev, "MAC %pM\n", net->dev_addr);
 		INFO(dev, "MAC %pM\n", net->dev_addr);
 		INFO(dev, "HOST MAC %pM\n", dev->host_mac);
 		INFO(dev, "HOST MAC %pM\n", dev->host_mac);
 
 
-		the_dev = dev;
-
 		/* two kinds of host-initiated state changes:
 		/* two kinds of host-initiated state changes:
 		 *  - iff DATA transfer is active, carrier is "on"
 		 *  - iff DATA transfer is active, carrier is "on"
 		 *  - tx queueing enabled if open *and* carrier is "on"
 		 *  - tx queueing enabled if open *and* carrier is "on"
@@ -820,7 +813,7 @@ int gether_setup_name(struct usb_gadget *g, u8 ethaddr[ETH_ALEN],
 		netif_carrier_off(net);
 		netif_carrier_off(net);
 	}
 	}
 
 
-	return status;
+	return dev;
 }
 }
 
 
 /**
 /**
@@ -829,19 +822,16 @@ int gether_setup_name(struct usb_gadget *g, u8 ethaddr[ETH_ALEN],
  *
  *
  * This is called to free all resources allocated by @gether_setup().
  * This is called to free all resources allocated by @gether_setup().
  */
  */
-void gether_cleanup(void)
+void gether_cleanup(struct eth_dev *dev)
 {
 {
-	if (!the_dev)
+	if (!dev)
 		return;
 		return;
 
 
-	unregister_netdev(the_dev->net);
-	flush_work(&the_dev->work);
-	free_netdev(the_dev->net);
-
-	the_dev = NULL;
+	unregister_netdev(dev->net);
+	flush_work(&dev->work);
+	free_netdev(dev->net);
 }
 }
 
 
-
 /**
 /**
  * gether_connect - notify network layer that USB link is active
  * gether_connect - notify network layer that USB link is active
  * @link: the USB link, set up with endpoints, descriptors matching
  * @link: the USB link, set up with endpoints, descriptors matching
@@ -860,7 +850,7 @@ void gether_cleanup(void)
  */
  */
 struct net_device *gether_connect(struct gether *link)
 struct net_device *gether_connect(struct gether *link)
 {
 {
-	struct eth_dev		*dev = the_dev;
+	struct eth_dev		*dev = link->ioport;
 	int			result = 0;
 	int			result = 0;
 
 
 	if (!dev)
 	if (!dev)
@@ -895,7 +885,6 @@ struct net_device *gether_connect(struct gether *link)
 
 
 		spin_lock(&dev->lock);
 		spin_lock(&dev->lock);
 		dev->port_usb = link;
 		dev->port_usb = link;
-		link->ioport = dev;
 		if (netif_running(dev->net)) {
 		if (netif_running(dev->net)) {
 			if (link->open)
 			if (link->open)
 				link->open(link);
 				link->open(link);
@@ -989,6 +978,5 @@ void gether_disconnect(struct gether *link)
 
 
 	spin_lock(&dev->lock);
 	spin_lock(&dev->lock);
 	dev->port_usb = NULL;
 	dev->port_usb = NULL;
-	link->ioport = NULL;
 	spin_unlock(&dev->lock);
 	spin_unlock(&dev->lock);
 }
 }

+ 16 - 11
drivers/usb/gadget/u_ether.h

@@ -21,6 +21,7 @@
 
 
 #include "gadget_chips.h"
 #include "gadget_chips.h"
 
 
+struct eth_dev;
 
 
 /*
 /*
  * This represents the USB side of an "ethernet" link, managed by a USB
  * This represents the USB side of an "ethernet" link, managed by a USB
@@ -70,7 +71,7 @@ struct gether {
 			|USB_CDC_PACKET_TYPE_DIRECTED)
 			|USB_CDC_PACKET_TYPE_DIRECTED)
 
 
 /* variant of gether_setup that allows customizing network device name */
 /* variant of gether_setup that allows customizing network device name */
-int gether_setup_name(struct usb_gadget *g, u8 ethaddr[ETH_ALEN],
+struct eth_dev *gether_setup_name(struct usb_gadget *g, u8 ethaddr[ETH_ALEN],
 		const char *netname);
 		const char *netname);
 
 
 /* netdev setup/teardown as directed by the gadget driver */
 /* netdev setup/teardown as directed by the gadget driver */
@@ -86,12 +87,13 @@ int gether_setup_name(struct usb_gadget *g, u8 ethaddr[ETH_ALEN],
  *
  *
  * Returns negative errno, or zero on success
  * Returns negative errno, or zero on success
  */
  */
-static inline int gether_setup(struct usb_gadget *g, u8 ethaddr[ETH_ALEN])
+static inline struct eth_dev *gether_setup(struct usb_gadget *g,
+		u8 ethaddr[ETH_ALEN])
 {
 {
 	return gether_setup_name(g, ethaddr, "usb");
 	return gether_setup_name(g, ethaddr, "usb");
 }
 }
 
 
-void gether_cleanup(void);
+void gether_cleanup(struct eth_dev *dev);
 
 
 /* connect/disconnect is handled by individual functions */
 /* connect/disconnect is handled by individual functions */
 struct net_device *gether_connect(struct gether *);
 struct net_device *gether_connect(struct gether *);
@@ -111,21 +113,24 @@ static inline bool can_support_ecm(struct usb_gadget *gadget)
 }
 }
 
 
 /* each configuration may bind one instance of an ethernet link */
 /* each configuration may bind one instance of an ethernet link */
-int geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]);
-int ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]);
-int ncm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]);
-int eem_bind_config(struct usb_configuration *c);
+int geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
+		struct eth_dev *dev);
+int ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
+		struct eth_dev *dev);
+int ncm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
+		struct eth_dev *dev);
+int eem_bind_config(struct usb_configuration *c, struct eth_dev *dev);
 
 
 #ifdef USB_ETH_RNDIS
 #ifdef USB_ETH_RNDIS
 
 
 int rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
 int rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
-				u32 vendorID, const char *manufacturer);
+		u32 vendorID, const char *manufacturer, struct eth_dev *dev);
 
 
 #else
 #else
 
 
 static inline int
 static inline int
 rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
 rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
-				u32 vendorID, const char *manufacturer)
+		u32 vendorID, const char *manufacturer, struct eth_dev *dev)
 {
 {
 	return 0;
 	return 0;
 }
 }
@@ -145,9 +150,9 @@ rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
  * for calling @gether_cleanup() before module unload.
  * for calling @gether_cleanup() before module unload.
  */
  */
 static inline int rndis_bind_config(struct usb_configuration *c,
 static inline int rndis_bind_config(struct usb_configuration *c,
-				    u8 ethaddr[ETH_ALEN])
+		u8 ethaddr[ETH_ALEN], struct eth_dev *dev)
 {
 {
-	return rndis_bind_config_vendor(c, ethaddr, 0, NULL);
+	return rndis_bind_config_vendor(c, ethaddr, 0, NULL, dev);
 }
 }
 
 
 
 

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

@@ -65,7 +65,6 @@ int gserial_connect(struct gserial *, u8 port_num);
 void gserial_disconnect(struct gserial *);
 void gserial_disconnect(struct gserial *);
 
 
 /* functions are bound to configurations by a config or gadget driver */
 /* functions are bound to configurations by a config or gadget driver */
-int acm_bind_config(struct usb_configuration *c, u8 port_num);
 int gser_bind_config(struct usb_configuration *c, u8 port_num);
 int gser_bind_config(struct usb_configuration *c, u8 port_num);
 int obex_bind_config(struct usb_configuration *c, u8 port_num);
 int obex_bind_config(struct usb_configuration *c, u8 port_num);
 
 

+ 80 - 10
drivers/usb/gadget/udc-core.c

@@ -101,6 +101,16 @@ EXPORT_SYMBOL_GPL(usb_gadget_unmap_request);
 
 
 /* ------------------------------------------------------------------------- */
 /* ------------------------------------------------------------------------- */
 
 
+void usb_gadget_set_state(struct usb_gadget *gadget,
+		enum usb_device_state state)
+{
+	gadget->state = state;
+	sysfs_notify(&gadget->dev.kobj, NULL, "status");
+}
+EXPORT_SYMBOL_GPL(usb_gadget_set_state);
+
+/* ------------------------------------------------------------------------- */
+
 /**
 /**
  * usb_gadget_udc_start - tells usb device controller to start up
  * usb_gadget_udc_start - tells usb device controller to start up
  * @gadget: The gadget we want to get started
  * @gadget: The gadget we want to get started
@@ -156,15 +166,23 @@ static void usb_udc_release(struct device *dev)
 }
 }
 
 
 static const struct attribute_group *usb_udc_attr_groups[];
 static const struct attribute_group *usb_udc_attr_groups[];
+
+static void usb_udc_nop_release(struct device *dev)
+{
+	dev_vdbg(dev, "%s\n", __func__);
+}
+
 /**
 /**
- * usb_add_gadget_udc - adds a new gadget to the udc class driver list
- * @parent: the parent device to this udc. Usually the controller
- * driver's device.
- * @gadget: the gadget to be added to the list
+ * usb_add_gadget_udc_release - adds a new gadget to the udc class driver list
+ * @parent: the parent device to this udc. Usually the controller driver's
+ * device.
+ * @gadget: the gadget to be added to the list.
+ * @release: a gadget release function.
  *
  *
  * Returns zero on success, negative errno otherwise.
  * Returns zero on success, negative errno otherwise.
  */
  */
-int usb_add_gadget_udc(struct device *parent, struct usb_gadget *gadget)
+int usb_add_gadget_udc_release(struct device *parent, struct usb_gadget *gadget,
+		void (*release)(struct device *dev))
 {
 {
 	struct usb_udc		*udc;
 	struct usb_udc		*udc;
 	int			ret = -ENOMEM;
 	int			ret = -ENOMEM;
@@ -173,6 +191,22 @@ int usb_add_gadget_udc(struct device *parent, struct usb_gadget *gadget)
 	if (!udc)
 	if (!udc)
 		goto err1;
 		goto err1;
 
 
+	dev_set_name(&gadget->dev, "gadget");
+	gadget->dev.parent = parent;
+
+	dma_set_coherent_mask(&gadget->dev, parent->coherent_dma_mask);
+	gadget->dev.dma_parms = parent->dma_parms;
+	gadget->dev.dma_mask = parent->dma_mask;
+
+	if (release)
+		gadget->dev.release = release;
+	else
+		gadget->dev.release = usb_udc_nop_release;
+
+	ret = device_register(&gadget->dev);
+	if (ret)
+		goto err2;
+
 	device_initialize(&udc->dev);
 	device_initialize(&udc->dev);
 	udc->dev.release = usb_udc_release;
 	udc->dev.release = usb_udc_release;
 	udc->dev.class = udc_class;
 	udc->dev.class = udc_class;
@@ -180,7 +214,7 @@ int usb_add_gadget_udc(struct device *parent, struct usb_gadget *gadget)
 	udc->dev.parent = parent;
 	udc->dev.parent = parent;
 	ret = dev_set_name(&udc->dev, "%s", kobject_name(&parent->kobj));
 	ret = dev_set_name(&udc->dev, "%s", kobject_name(&parent->kobj));
 	if (ret)
 	if (ret)
-		goto err2;
+		goto err3;
 
 
 	udc->gadget = gadget;
 	udc->gadget = gadget;
 
 
@@ -189,21 +223,42 @@ int usb_add_gadget_udc(struct device *parent, struct usb_gadget *gadget)
 
 
 	ret = device_add(&udc->dev);
 	ret = device_add(&udc->dev);
 	if (ret)
 	if (ret)
-		goto err3;
+		goto err4;
+
+	usb_gadget_set_state(gadget, USB_STATE_NOTATTACHED);
 
 
 	mutex_unlock(&udc_lock);
 	mutex_unlock(&udc_lock);
 
 
 	return 0;
 	return 0;
-err3:
+
+err4:
 	list_del(&udc->list);
 	list_del(&udc->list);
 	mutex_unlock(&udc_lock);
 	mutex_unlock(&udc_lock);
 
 
-err2:
+err3:
 	put_device(&udc->dev);
 	put_device(&udc->dev);
 
 
+err2:
+	put_device(&gadget->dev);
+	kfree(udc);
+
 err1:
 err1:
 	return ret;
 	return ret;
 }
 }
+EXPORT_SYMBOL_GPL(usb_add_gadget_udc_release);
+
+/**
+ * usb_add_gadget_udc - adds a new gadget to the udc class driver list
+ * @parent: the parent device to this udc. Usually the controller
+ * driver's device.
+ * @gadget: the gadget to be added to the list
+ *
+ * Returns zero on success, negative errno otherwise.
+ */
+int usb_add_gadget_udc(struct device *parent, struct usb_gadget *gadget)
+{
+	return usb_add_gadget_udc_release(parent, gadget, NULL);
+}
 EXPORT_SYMBOL_GPL(usb_add_gadget_udc);
 EXPORT_SYMBOL_GPL(usb_add_gadget_udc);
 
 
 static void usb_gadget_remove_driver(struct usb_udc *udc)
 static void usb_gadget_remove_driver(struct usb_udc *udc)
@@ -220,6 +275,7 @@ static void usb_gadget_remove_driver(struct usb_udc *udc)
 
 
 	udc->driver = NULL;
 	udc->driver = NULL;
 	udc->dev.driver = NULL;
 	udc->dev.driver = NULL;
+	udc->gadget->dev.driver = NULL;
 }
 }
 
 
 /**
 /**
@@ -254,6 +310,7 @@ found:
 
 
 	kobject_uevent(&udc->dev.kobj, KOBJ_REMOVE);
 	kobject_uevent(&udc->dev.kobj, KOBJ_REMOVE);
 	device_unregister(&udc->dev);
 	device_unregister(&udc->dev);
+	device_unregister(&gadget->dev);
 }
 }
 EXPORT_SYMBOL_GPL(usb_del_gadget_udc);
 EXPORT_SYMBOL_GPL(usb_del_gadget_udc);
 
 
@@ -268,6 +325,7 @@ static int udc_bind_to_driver(struct usb_udc *udc, struct usb_gadget_driver *dri
 
 
 	udc->driver = driver;
 	udc->driver = driver;
 	udc->dev.driver = &driver->driver;
 	udc->dev.driver = &driver->driver;
+	udc->gadget->dev.driver = &driver->driver;
 
 
 	ret = driver->bind(udc->gadget, driver);
 	ret = driver->bind(udc->gadget, driver);
 	if (ret)
 	if (ret)
@@ -286,6 +344,7 @@ err1:
 			udc->driver->function, ret);
 			udc->driver->function, ret);
 	udc->driver = NULL;
 	udc->driver = NULL;
 	udc->dev.driver = NULL;
 	udc->dev.driver = NULL;
+	udc->gadget->dev.driver = NULL;
 	return ret;
 	return ret;
 }
 }
 
 
@@ -395,6 +454,16 @@ static ssize_t usb_udc_softconn_store(struct device *dev,
 }
 }
 static DEVICE_ATTR(soft_connect, S_IWUSR, NULL, usb_udc_softconn_store);
 static DEVICE_ATTR(soft_connect, S_IWUSR, NULL, usb_udc_softconn_store);
 
 
+static ssize_t usb_gadget_state_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct usb_udc		*udc = container_of(dev, struct usb_udc, dev);
+	struct usb_gadget	*gadget = udc->gadget;
+
+	return sprintf(buf, "%s\n", usb_state_string(gadget->state));
+}
+static DEVICE_ATTR(state, S_IRUGO, usb_gadget_state_show, NULL);
+
 #define USB_UDC_SPEED_ATTR(name, param)					\
 #define USB_UDC_SPEED_ATTR(name, param)					\
 ssize_t usb_udc_##param##_show(struct device *dev,			\
 ssize_t usb_udc_##param##_show(struct device *dev,			\
 		struct device_attribute *attr, char *buf)		\
 		struct device_attribute *attr, char *buf)		\
@@ -403,7 +472,7 @@ ssize_t usb_udc_##param##_show(struct device *dev,			\
 	return snprintf(buf, PAGE_SIZE, "%s\n",				\
 	return snprintf(buf, PAGE_SIZE, "%s\n",				\
 			usb_speed_string(udc->gadget->param));		\
 			usb_speed_string(udc->gadget->param));		\
 }									\
 }									\
-static DEVICE_ATTR(name, S_IRUSR, usb_udc_##param##_show, NULL)
+static DEVICE_ATTR(name, S_IRUGO, usb_udc_##param##_show, NULL)
 
 
 static USB_UDC_SPEED_ATTR(current_speed, speed);
 static USB_UDC_SPEED_ATTR(current_speed, speed);
 static USB_UDC_SPEED_ATTR(maximum_speed, max_speed);
 static USB_UDC_SPEED_ATTR(maximum_speed, max_speed);
@@ -428,6 +497,7 @@ static USB_UDC_ATTR(a_alt_hnp_support);
 static struct attribute *usb_udc_attrs[] = {
 static struct attribute *usb_udc_attrs[] = {
 	&dev_attr_srp.attr,
 	&dev_attr_srp.attr,
 	&dev_attr_soft_connect.attr,
 	&dev_attr_soft_connect.attr,
+	&dev_attr_state.attr,
 	&dev_attr_current_speed.attr,
 	&dev_attr_current_speed.attr,
 	&dev_attr_maximum_speed.attr,
 	&dev_attr_maximum_speed.attr,
 
 

+ 1 - 2
drivers/usb/gadget/uvc.h

@@ -98,8 +98,6 @@ extern unsigned int uvc_gadget_trace_param;
 #define DRIVER_VERSION				"0.1.0"
 #define DRIVER_VERSION				"0.1.0"
 #define DRIVER_VERSION_NUMBER			KERNEL_VERSION(0, 1, 0)
 #define DRIVER_VERSION_NUMBER			KERNEL_VERSION(0, 1, 0)
 
 
-#define DMA_ADDR_INVALID			(~(dma_addr_t)0)
-
 #define UVC_NUM_REQUESTS			4
 #define UVC_NUM_REQUESTS			4
 #define UVC_MAX_REQUEST_SIZE			64
 #define UVC_MAX_REQUEST_SIZE			64
 #define UVC_MAX_EVENTS				4
 #define UVC_MAX_EVENTS				4
@@ -190,6 +188,7 @@ struct uvc_file_handle
  * Functions
  * Functions
  */
  */
 
 
+extern void uvc_function_setup_continue(struct uvc_device *uvc);
 extern void uvc_endpoint_stream(struct uvc_device *dev);
 extern void uvc_endpoint_stream(struct uvc_device *dev);
 
 
 extern void uvc_function_connect(struct uvc_device *uvc);
 extern void uvc_function_connect(struct uvc_device *uvc);

+ 171 - 367
drivers/usb/gadget/uvc_queue.c

@@ -10,6 +10,7 @@
  *	(at your option) any later version.
  *	(at your option) any later version.
  */
  */
 
 
+#include <linux/atomic.h>
 #include <linux/kernel.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/mm.h>
 #include <linux/list.h>
 #include <linux/list.h>
@@ -18,7 +19,8 @@
 #include <linux/videodev2.h>
 #include <linux/videodev2.h>
 #include <linux/vmalloc.h>
 #include <linux/vmalloc.h>
 #include <linux/wait.h>
 #include <linux/wait.h>
-#include <linux/atomic.h>
+
+#include <media/videobuf2-vmalloc.h>
 
 
 #include "uvc.h"
 #include "uvc.h"
 
 
@@ -28,330 +30,175 @@
  * Video queues is initialized by uvc_queue_init(). The function performs
  * Video queues is initialized by uvc_queue_init(). The function performs
  * basic initialization of the uvc_video_queue struct and never fails.
  * basic initialization of the uvc_video_queue struct and never fails.
  *
  *
- * Video buffer allocation and freeing are performed by uvc_alloc_buffers and
- * uvc_free_buffers respectively. The former acquires the video queue lock,
- * while the later must be called with the lock held (so that allocation can
- * free previously allocated buffers). Trying to free buffers that are mapped
- * to user space will return -EBUSY.
- *
- * Video buffers are managed using two queues. However, unlike most USB video
- * drivers that use an in queue and an out queue, we use a main queue to hold
- * all queued buffers (both 'empty' and 'done' buffers), and an irq queue to
- * hold empty buffers. This design (copied from video-buf) minimizes locking
- * in interrupt, as only one queue is shared between interrupt and user
- * contexts.
- *
- * Use cases
- * ---------
- *
- * Unless stated otherwise, all operations that modify the irq buffers queue
- * are protected by the irq spinlock.
- *
- * 1. The user queues the buffers, starts streaming and dequeues a buffer.
- *
- *    The buffers are added to the main and irq queues. Both operations are
- *    protected by the queue lock, and the later is protected by the irq
- *    spinlock as well.
- *
- *    The completion handler fetches a buffer from the irq queue and fills it
- *    with video data. If no buffer is available (irq queue empty), the handler
- *    returns immediately.
- *
- *    When the buffer is full, the completion handler removes it from the irq
- *    queue, marks it as ready (UVC_BUF_STATE_DONE) and wakes its wait queue.
- *    At that point, any process waiting on the buffer will be woken up. If a
- *    process tries to dequeue a buffer after it has been marked ready, the
- *    dequeing will succeed immediately.
- *
- * 2. Buffers are queued, user is waiting on a buffer and the device gets
- *    disconnected.
- *
- *    When the device is disconnected, the kernel calls the completion handler
- *    with an appropriate status code. The handler marks all buffers in the
- *    irq queue as being erroneous (UVC_BUF_STATE_ERROR) and wakes them up so
- *    that any process waiting on a buffer gets woken up.
- *
- *    Waking up up the first buffer on the irq list is not enough, as the
- *    process waiting on the buffer might restart the dequeue operation
- *    immediately.
- *
+ * Video buffers are managed by videobuf2. The driver uses a mutex to protect
+ * the videobuf2 queue operations by serializing calls to videobuf2 and a
+ * spinlock to protect the IRQ queue that holds the buffers to be processed by
+ * the driver.
  */
  */
 
 
-static void
-uvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type)
-{
-	mutex_init(&queue->mutex);
-	spin_lock_init(&queue->irqlock);
-	INIT_LIST_HEAD(&queue->mainqueue);
-	INIT_LIST_HEAD(&queue->irqqueue);
-	queue->type = type;
-}
-
-/*
- * Free the video buffers.
- *
- * This function must be called with the queue lock held.
+/* -----------------------------------------------------------------------------
+ * videobuf2 queue operations
  */
  */
-static int uvc_free_buffers(struct uvc_video_queue *queue)
+
+static int uvc_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+			   unsigned int *nbuffers, unsigned int *nplanes,
+			   unsigned int sizes[], void *alloc_ctxs[])
 {
 {
-	unsigned int i;
+	struct uvc_video_queue *queue = vb2_get_drv_priv(vq);
+	struct uvc_video *video = container_of(queue, struct uvc_video, queue);
 
 
-	for (i = 0; i < queue->count; ++i) {
-		if (queue->buffer[i].vma_use_count != 0)
-			return -EBUSY;
-	}
+	if (*nbuffers > UVC_MAX_VIDEO_BUFFERS)
+		*nbuffers = UVC_MAX_VIDEO_BUFFERS;
 
 
-	if (queue->count) {
-		vfree(queue->mem);
-		queue->count = 0;
-	}
+	*nplanes = 1;
+
+	sizes[0] = video->imagesize;
 
 
 	return 0;
 	return 0;
 }
 }
 
 
-/*
- * Allocate the video buffers.
- *
- * Pages are reserved to make sure they will not be swapped, as they will be
- * filled in the URB completion handler.
- *
- * Buffers will be individually mapped, so they must all be page aligned.
- */
-static int
-uvc_alloc_buffers(struct uvc_video_queue *queue, unsigned int nbuffers,
-		  unsigned int buflength)
+static int uvc_buffer_prepare(struct vb2_buffer *vb)
 {
 {
-	unsigned int bufsize = PAGE_ALIGN(buflength);
-	unsigned int i;
-	void *mem = NULL;
-	int ret;
+	struct uvc_video_queue *queue = vb2_get_drv_priv(vb->vb2_queue);
+	struct uvc_buffer *buf = container_of(vb, struct uvc_buffer, buf);
 
 
-	if (nbuffers > UVC_MAX_VIDEO_BUFFERS)
-		nbuffers = UVC_MAX_VIDEO_BUFFERS;
+	if (vb->v4l2_buf.type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
+	    vb2_get_plane_payload(vb, 0) > vb2_plane_size(vb, 0)) {
+		uvc_trace(UVC_TRACE_CAPTURE, "[E] Bytes used out of bounds.\n");
+		return -EINVAL;
+	}
 
 
-	mutex_lock(&queue->mutex);
+	if (unlikely(queue->flags & UVC_QUEUE_DISCONNECTED))
+		return -ENODEV;
 
 
-	if ((ret = uvc_free_buffers(queue)) < 0)
-		goto done;
+	buf->state = UVC_BUF_STATE_QUEUED;
+	buf->mem = vb2_plane_vaddr(vb, 0);
+	buf->length = vb2_plane_size(vb, 0);
+	if (vb->v4l2_buf.type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		buf->bytesused = 0;
+	else
+		buf->bytesused = vb2_get_plane_payload(vb, 0);
 
 
-	/* Bail out if no buffers should be allocated. */
-	if (nbuffers == 0)
-		goto done;
+	return 0;
+}
 
 
-	/* Decrement the number of buffers until allocation succeeds. */
-	for (; nbuffers > 0; --nbuffers) {
-		mem = vmalloc_32(nbuffers * bufsize);
-		if (mem != NULL)
-			break;
-	}
+static void uvc_buffer_queue(struct vb2_buffer *vb)
+{
+	struct uvc_video_queue *queue = vb2_get_drv_priv(vb->vb2_queue);
+	struct uvc_buffer *buf = container_of(vb, struct uvc_buffer, buf);
+	unsigned long flags;
 
 
-	if (mem == NULL) {
-		ret = -ENOMEM;
-		goto done;
-	}
+	spin_lock_irqsave(&queue->irqlock, flags);
 
 
-	for (i = 0; i < nbuffers; ++i) {
-		memset(&queue->buffer[i], 0, sizeof queue->buffer[i]);
-		queue->buffer[i].buf.index = i;
-		queue->buffer[i].buf.m.offset = i * bufsize;
-		queue->buffer[i].buf.length = buflength;
-		queue->buffer[i].buf.type = queue->type;
-		queue->buffer[i].buf.sequence = 0;
-		queue->buffer[i].buf.field = V4L2_FIELD_NONE;
-		queue->buffer[i].buf.memory = V4L2_MEMORY_MMAP;
-		queue->buffer[i].buf.flags = 0;
-		init_waitqueue_head(&queue->buffer[i].wait);
+	if (likely(!(queue->flags & UVC_QUEUE_DISCONNECTED))) {
+		list_add_tail(&buf->queue, &queue->irqqueue);
+	} else {
+		/* If the device is disconnected return the buffer to userspace
+		 * directly. The next QBUF call will fail with -ENODEV.
+		 */
+		buf->state = UVC_BUF_STATE_ERROR;
+		vb2_buffer_done(&buf->buf, VB2_BUF_STATE_ERROR);
 	}
 	}
 
 
-	queue->mem = mem;
-	queue->count = nbuffers;
-	queue->buf_size = bufsize;
-	ret = nbuffers;
-
-done:
-	mutex_unlock(&queue->mutex);
-	return ret;
+	spin_unlock_irqrestore(&queue->irqlock, flags);
 }
 }
 
 
-static void __uvc_query_buffer(struct uvc_buffer *buf,
-		struct v4l2_buffer *v4l2_buf)
-{
-	memcpy(v4l2_buf, &buf->buf, sizeof *v4l2_buf);
-
-	if (buf->vma_use_count)
-		v4l2_buf->flags |= V4L2_BUF_FLAG_MAPPED;
-
-	switch (buf->state) {
-	case UVC_BUF_STATE_ERROR:
-	case UVC_BUF_STATE_DONE:
-		v4l2_buf->flags |= V4L2_BUF_FLAG_DONE;
-		break;
-	case UVC_BUF_STATE_QUEUED:
-	case UVC_BUF_STATE_ACTIVE:
-		v4l2_buf->flags |= V4L2_BUF_FLAG_QUEUED;
-		break;
-	case UVC_BUF_STATE_IDLE:
-	default:
-		break;
-	}
-}
+static struct vb2_ops uvc_queue_qops = {
+	.queue_setup = uvc_queue_setup,
+	.buf_prepare = uvc_buffer_prepare,
+	.buf_queue = uvc_buffer_queue,
+};
 
 
-static int
-uvc_query_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *v4l2_buf)
+static int uvc_queue_init(struct uvc_video_queue *queue,
+			  enum v4l2_buf_type type)
 {
 {
-	int ret = 0;
+	int ret;
 
 
-	mutex_lock(&queue->mutex);
-	if (v4l2_buf->index >= queue->count) {
-		ret = -EINVAL;
-		goto done;
-	}
+	queue->queue.type = type;
+	queue->queue.io_modes = VB2_MMAP | VB2_USERPTR;
+	queue->queue.drv_priv = queue;
+	queue->queue.buf_struct_size = sizeof(struct uvc_buffer);
+	queue->queue.ops = &uvc_queue_qops;
+	queue->queue.mem_ops = &vb2_vmalloc_memops;
+	ret = vb2_queue_init(&queue->queue);
+	if (ret)
+		return ret;
+
+	mutex_init(&queue->mutex);
+	spin_lock_init(&queue->irqlock);
+	INIT_LIST_HEAD(&queue->irqqueue);
+	queue->flags = 0;
 
 
-	__uvc_query_buffer(&queue->buffer[v4l2_buf->index], v4l2_buf);
+	return 0;
+}
 
 
-done:
+/*
+ * Free the video buffers.
+ */
+static void uvc_free_buffers(struct uvc_video_queue *queue)
+{
+	mutex_lock(&queue->mutex);
+	vb2_queue_release(&queue->queue);
 	mutex_unlock(&queue->mutex);
 	mutex_unlock(&queue->mutex);
-	return ret;
 }
 }
 
 
 /*
 /*
- * Queue a video buffer. Attempting to queue a buffer that has already been
- * queued will return -EINVAL.
+ * Allocate the video buffers.
  */
  */
-static int
-uvc_queue_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *v4l2_buf)
+static int uvc_alloc_buffers(struct uvc_video_queue *queue,
+			     struct v4l2_requestbuffers *rb)
 {
 {
-	struct uvc_buffer *buf;
-	unsigned long flags;
-	int ret = 0;
+	int ret;
 
 
-	uvc_trace(UVC_TRACE_CAPTURE, "Queuing buffer %u.\n", v4l2_buf->index);
+	mutex_lock(&queue->mutex);
+	ret = vb2_reqbufs(&queue->queue, rb);
+	mutex_unlock(&queue->mutex);
 
 
-	if (v4l2_buf->type != queue->type ||
-	    v4l2_buf->memory != V4L2_MEMORY_MMAP) {
-		uvc_trace(UVC_TRACE_CAPTURE, "[E] Invalid buffer type (%u) "
-			"and/or memory (%u).\n", v4l2_buf->type,
-			v4l2_buf->memory);
-		return -EINVAL;
-	}
+	return ret ? ret : rb->count;
+}
 
 
-	mutex_lock(&queue->mutex);
-	if (v4l2_buf->index >= queue->count) {
-		uvc_trace(UVC_TRACE_CAPTURE, "[E] Out of range index.\n");
-		ret = -EINVAL;
-		goto done;
-	}
+static int uvc_query_buffer(struct uvc_video_queue *queue,
+			    struct v4l2_buffer *buf)
+{
+	int ret;
 
 
-	buf = &queue->buffer[v4l2_buf->index];
-	if (buf->state != UVC_BUF_STATE_IDLE) {
-		uvc_trace(UVC_TRACE_CAPTURE, "[E] Invalid buffer state "
-			"(%u).\n", buf->state);
-		ret = -EINVAL;
-		goto done;
-	}
+	mutex_lock(&queue->mutex);
+	ret = vb2_querybuf(&queue->queue, buf);
+	mutex_unlock(&queue->mutex);
 
 
-	if (v4l2_buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
-	    v4l2_buf->bytesused > buf->buf.length) {
-		uvc_trace(UVC_TRACE_CAPTURE, "[E] Bytes used out of bounds.\n");
-		ret = -EINVAL;
-		goto done;
-	}
+	return ret;
+}
 
 
-	if (v4l2_buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
-		buf->buf.bytesused = 0;
-	else
-		buf->buf.bytesused = v4l2_buf->bytesused;
+static int uvc_queue_buffer(struct uvc_video_queue *queue,
+			    struct v4l2_buffer *buf)
+{
+	unsigned long flags;
+	int ret;
 
 
+	mutex_lock(&queue->mutex);
+	ret = vb2_qbuf(&queue->queue, buf);
 	spin_lock_irqsave(&queue->irqlock, flags);
 	spin_lock_irqsave(&queue->irqlock, flags);
-	if (queue->flags & UVC_QUEUE_DISCONNECTED) {
-		spin_unlock_irqrestore(&queue->irqlock, flags);
-		ret = -ENODEV;
-		goto done;
-	}
-	buf->state = UVC_BUF_STATE_QUEUED;
-
 	ret = (queue->flags & UVC_QUEUE_PAUSED) != 0;
 	ret = (queue->flags & UVC_QUEUE_PAUSED) != 0;
 	queue->flags &= ~UVC_QUEUE_PAUSED;
 	queue->flags &= ~UVC_QUEUE_PAUSED;
-
-	list_add_tail(&buf->stream, &queue->mainqueue);
-	list_add_tail(&buf->queue, &queue->irqqueue);
 	spin_unlock_irqrestore(&queue->irqlock, flags);
 	spin_unlock_irqrestore(&queue->irqlock, flags);
-
-done:
 	mutex_unlock(&queue->mutex);
 	mutex_unlock(&queue->mutex);
-	return ret;
-}
 
 
-static int uvc_queue_waiton(struct uvc_buffer *buf, int nonblocking)
-{
-	if (nonblocking) {
-		return (buf->state != UVC_BUF_STATE_QUEUED &&
-			buf->state != UVC_BUF_STATE_ACTIVE)
-			? 0 : -EAGAIN;
-	}
-
-	return wait_event_interruptible(buf->wait,
-		buf->state != UVC_BUF_STATE_QUEUED &&
-		buf->state != UVC_BUF_STATE_ACTIVE);
+	return ret;
 }
 }
 
 
 /*
 /*
  * Dequeue a video buffer. If nonblocking is false, block until a buffer is
  * Dequeue a video buffer. If nonblocking is false, block until a buffer is
  * available.
  * available.
  */
  */
-static int
-uvc_dequeue_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *v4l2_buf,
-		   int nonblocking)
+static int uvc_dequeue_buffer(struct uvc_video_queue *queue,
+			      struct v4l2_buffer *buf, int nonblocking)
 {
 {
-	struct uvc_buffer *buf;
-	int ret = 0;
-
-	if (v4l2_buf->type != queue->type ||
-	    v4l2_buf->memory != V4L2_MEMORY_MMAP) {
-		uvc_trace(UVC_TRACE_CAPTURE, "[E] Invalid buffer type (%u) "
-			"and/or memory (%u).\n", v4l2_buf->type,
-			v4l2_buf->memory);
-		return -EINVAL;
-	}
+	int ret;
 
 
 	mutex_lock(&queue->mutex);
 	mutex_lock(&queue->mutex);
-	if (list_empty(&queue->mainqueue)) {
-		uvc_trace(UVC_TRACE_CAPTURE, "[E] Empty buffer queue.\n");
-		ret = -EINVAL;
-		goto done;
-	}
-
-	buf = list_first_entry(&queue->mainqueue, struct uvc_buffer, stream);
-	if ((ret = uvc_queue_waiton(buf, nonblocking)) < 0)
-		goto done;
-
-	uvc_trace(UVC_TRACE_CAPTURE, "Dequeuing buffer %u (%u, %u bytes).\n",
-		buf->buf.index, buf->state, buf->buf.bytesused);
-
-	switch (buf->state) {
-	case UVC_BUF_STATE_ERROR:
-		uvc_trace(UVC_TRACE_CAPTURE, "[W] Corrupted data "
-			"(transmission error).\n");
-		ret = -EIO;
-	case UVC_BUF_STATE_DONE:
-		buf->state = UVC_BUF_STATE_IDLE;
-		break;
-
-	case UVC_BUF_STATE_IDLE:
-	case UVC_BUF_STATE_QUEUED:
-	case UVC_BUF_STATE_ACTIVE:
-	default:
-		uvc_trace(UVC_TRACE_CAPTURE, "[E] Invalid buffer state %u "
-			"(driver bug?).\n", buf->state);
-		ret = -EINVAL;
-		goto done;
-	}
-
-	list_del(&buf->stream);
-	__uvc_query_buffer(buf, v4l2_buf);
-
-done:
+	ret = vb2_dqbuf(&queue->queue, buf, nonblocking);
 	mutex_unlock(&queue->mutex);
 	mutex_unlock(&queue->mutex);
+
 	return ret;
 	return ret;
 }
 }
 
 
@@ -361,105 +208,47 @@ done:
  * This function implements video queue polling and is intended to be used by
  * This function implements video queue polling and is intended to be used by
  * the device poll handler.
  * the device poll handler.
  */
  */
-static unsigned int
-uvc_queue_poll(struct uvc_video_queue *queue, struct file *file,
-	       poll_table *wait)
+static unsigned int uvc_queue_poll(struct uvc_video_queue *queue,
+				   struct file *file, poll_table *wait)
 {
 {
-	struct uvc_buffer *buf;
-	unsigned int mask = 0;
+	unsigned int ret;
 
 
 	mutex_lock(&queue->mutex);
 	mutex_lock(&queue->mutex);
-	if (list_empty(&queue->mainqueue))
-		goto done;
-
-	buf = list_first_entry(&queue->mainqueue, struct uvc_buffer, stream);
-
-	poll_wait(file, &buf->wait, wait);
-	if (buf->state == UVC_BUF_STATE_DONE ||
-	    buf->state == UVC_BUF_STATE_ERROR)
-		mask |= POLLOUT | POLLWRNORM;
-
-done:
+	ret = vb2_poll(&queue->queue, file, wait);
 	mutex_unlock(&queue->mutex);
 	mutex_unlock(&queue->mutex);
-	return mask;
-}
 
 
-/*
- * VMA operations.
- */
-static void uvc_vm_open(struct vm_area_struct *vma)
-{
-	struct uvc_buffer *buffer = vma->vm_private_data;
-	buffer->vma_use_count++;
+	return ret;
 }
 }
 
 
-static void uvc_vm_close(struct vm_area_struct *vma)
+static int uvc_queue_mmap(struct uvc_video_queue *queue,
+			  struct vm_area_struct *vma)
 {
 {
-	struct uvc_buffer *buffer = vma->vm_private_data;
-	buffer->vma_use_count--;
-}
+	int ret;
 
 
-static struct vm_operations_struct uvc_vm_ops = {
-	.open		= uvc_vm_open,
-	.close		= uvc_vm_close,
-};
+	mutex_lock(&queue->mutex);
+	ret = vb2_mmap(&queue->queue, vma);
+	mutex_unlock(&queue->mutex);
+
+	return ret;
+}
 
 
+#ifndef CONFIG_MMU
 /*
 /*
- * Memory-map a buffer.
+ * Get unmapped area.
  *
  *
- * This function implements video buffer memory mapping and is intended to be
- * used by the device mmap handler.
+ * NO-MMU arch need this function to make mmap() work correctly.
  */
  */
-static int
-uvc_queue_mmap(struct uvc_video_queue *queue, struct vm_area_struct *vma)
+static unsigned long uvc_queue_get_unmapped_area(struct uvc_video_queue *queue,
+		unsigned long pgoff)
 {
 {
-	struct uvc_buffer *uninitialized_var(buffer);
-	struct page *page;
-	unsigned long addr, start, size;
-	unsigned int i;
-	int ret = 0;
-
-	start = vma->vm_start;
-	size = vma->vm_end - vma->vm_start;
+	unsigned long ret;
 
 
 	mutex_lock(&queue->mutex);
 	mutex_lock(&queue->mutex);
-
-	for (i = 0; i < queue->count; ++i) {
-		buffer = &queue->buffer[i];
-		if ((buffer->buf.m.offset >> PAGE_SHIFT) == vma->vm_pgoff)
-			break;
-	}
-
-	if (i == queue->count || size != queue->buf_size) {
-		ret = -EINVAL;
-		goto done;
-	}
-
-	/*
-	 * VM_IO marks the area as being an mmaped region for I/O to a
-	 * device. It also prevents the region from being core dumped.
-	 */
-	vma->vm_flags |= VM_IO;
-
-	addr = (unsigned long)queue->mem + buffer->buf.m.offset;
-	while (size > 0) {
-		page = vmalloc_to_page((void *)addr);
-		if ((ret = vm_insert_page(vma, start, page)) < 0)
-			goto done;
-
-		start += PAGE_SIZE;
-		addr += PAGE_SIZE;
-		size -= PAGE_SIZE;
-	}
-
-	vma->vm_ops = &uvc_vm_ops;
-	vma->vm_private_data = buffer;
-	uvc_vm_open(vma);
-
-done:
+	ret = vb2_get_unmapped_area(&queue->queue, 0, 0, pgoff, 0);
 	mutex_unlock(&queue->mutex);
 	mutex_unlock(&queue->mutex);
 	return ret;
 	return ret;
 }
 }
+#endif
 
 
 /*
 /*
  * Cancel the video buffers queue.
  * Cancel the video buffers queue.
@@ -484,7 +273,7 @@ static void uvc_queue_cancel(struct uvc_video_queue *queue, int disconnect)
 				       queue);
 				       queue);
 		list_del(&buf->queue);
 		list_del(&buf->queue);
 		buf->state = UVC_BUF_STATE_ERROR;
 		buf->state = UVC_BUF_STATE_ERROR;
-		wake_up(&buf->wait);
+		vb2_buffer_done(&buf->buf, VB2_BUF_STATE_ERROR);
 	}
 	}
 	/* This must be protected by the irqlock spinlock to avoid race
 	/* This must be protected by the irqlock spinlock to avoid race
 	 * conditions between uvc_queue_buffer and the disconnection event that
 	 * conditions between uvc_queue_buffer and the disconnection event that
@@ -516,26 +305,33 @@ static void uvc_queue_cancel(struct uvc_video_queue *queue, int disconnect)
  */
  */
 static int uvc_queue_enable(struct uvc_video_queue *queue, int enable)
 static int uvc_queue_enable(struct uvc_video_queue *queue, int enable)
 {
 {
-	unsigned int i;
+	unsigned long flags;
 	int ret = 0;
 	int ret = 0;
 
 
 	mutex_lock(&queue->mutex);
 	mutex_lock(&queue->mutex);
 	if (enable) {
 	if (enable) {
-		if (uvc_queue_streaming(queue)) {
-			ret = -EBUSY;
+		ret = vb2_streamon(&queue->queue, queue->queue.type);
+		if (ret < 0)
 			goto done;
 			goto done;
-		}
+
 		queue->sequence = 0;
 		queue->sequence = 0;
-		queue->flags |= UVC_QUEUE_STREAMING;
 		queue->buf_used = 0;
 		queue->buf_used = 0;
 	} else {
 	} else {
-		uvc_queue_cancel(queue, 0);
-		INIT_LIST_HEAD(&queue->mainqueue);
+		ret = vb2_streamoff(&queue->queue, queue->queue.type);
+		if (ret < 0)
+			goto done;
 
 
-		for (i = 0; i < queue->count; ++i)
-			queue->buffer[i].state = UVC_BUF_STATE_IDLE;
+		spin_lock_irqsave(&queue->irqlock, flags);
+		INIT_LIST_HEAD(&queue->irqqueue);
 
 
-		queue->flags &= ~UVC_QUEUE_STREAMING;
+		/*
+		 * FIXME: We need to clear the DISCONNECTED flag to ensure that
+		 * applications will be able to queue buffers for the next
+		 * streaming run. However, clearing it here doesn't guarantee
+		 * that the device will be reconnected in the meantime.
+		 */
+		queue->flags &= ~UVC_QUEUE_DISCONNECTED;
+		spin_unlock_irqrestore(&queue->irqlock, flags);
 	}
 	}
 
 
 done:
 done:
@@ -544,15 +340,15 @@ done:
 }
 }
 
 
 /* called with &queue_irqlock held.. */
 /* called with &queue_irqlock held.. */
-static struct uvc_buffer *
-uvc_queue_next_buffer(struct uvc_video_queue *queue, struct uvc_buffer *buf)
+static struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue,
+						struct uvc_buffer *buf)
 {
 {
 	struct uvc_buffer *nextbuf;
 	struct uvc_buffer *nextbuf;
 
 
 	if ((queue->flags & UVC_QUEUE_DROP_INCOMPLETE) &&
 	if ((queue->flags & UVC_QUEUE_DROP_INCOMPLETE) &&
-	    buf->buf.length != buf->buf.bytesused) {
+	     buf->length != buf->bytesused) {
 		buf->state = UVC_BUF_STATE_QUEUED;
 		buf->state = UVC_BUF_STATE_QUEUED;
-		buf->buf.bytesused = 0;
+		vb2_set_plane_payload(&buf->buf, 0, 0);
 		return buf;
 		return buf;
 	}
 	}
 
 
@@ -563,10 +359,18 @@ uvc_queue_next_buffer(struct uvc_video_queue *queue, struct uvc_buffer *buf)
 	else
 	else
 		nextbuf = NULL;
 		nextbuf = NULL;
 
 
-	buf->buf.sequence = queue->sequence++;
-	do_gettimeofday(&buf->buf.timestamp);
+	/*
+	 * FIXME: with videobuf2, the sequence number or timestamp fields
+	 * are valid only for video capture devices and the UVC gadget usually
+	 * is a video output device. Keeping these until the specs are clear on
+	 * this aspect.
+	 */
+	buf->buf.v4l2_buf.sequence = queue->sequence++;
+	do_gettimeofday(&buf->buf.v4l2_buf.timestamp);
+
+	vb2_set_plane_payload(&buf->buf, 0, buf->bytesused);
+	vb2_buffer_done(&buf->buf, VB2_BUF_STATE_DONE);
 
 
-	wake_up(&buf->wait);
 	return nextbuf;
 	return nextbuf;
 }
 }
 
 

+ 13 - 19
drivers/usb/gadget/uvc_queue.h

@@ -6,6 +6,7 @@
 #include <linux/kernel.h>
 #include <linux/kernel.h>
 #include <linux/poll.h>
 #include <linux/poll.h>
 #include <linux/videodev2.h>
 #include <linux/videodev2.h>
+#include <media/videobuf2-core.h>
 
 
 /* Maximum frame size in bytes, for sanity checking. */
 /* Maximum frame size in bytes, for sanity checking. */
 #define UVC_MAX_FRAME_SIZE	(16*1024*1024)
 #define UVC_MAX_FRAME_SIZE	(16*1024*1024)
@@ -25,42 +26,35 @@ enum uvc_buffer_state {
 };
 };
 
 
 struct uvc_buffer {
 struct uvc_buffer {
-	unsigned long vma_use_count;
-	struct list_head stream;
-
-	/* Touched by interrupt handler. */
-	struct v4l2_buffer buf;
+	struct vb2_buffer buf;
 	struct list_head queue;
 	struct list_head queue;
-	wait_queue_head_t wait;
+
 	enum uvc_buffer_state state;
 	enum uvc_buffer_state state;
+	void *mem;
+	unsigned int length;
+	unsigned int bytesused;
 };
 };
 
 
-#define UVC_QUEUE_STREAMING		(1 << 0)
-#define UVC_QUEUE_DISCONNECTED		(1 << 1)
-#define UVC_QUEUE_DROP_INCOMPLETE	(1 << 2)
-#define UVC_QUEUE_PAUSED		(1 << 3)
+#define UVC_QUEUE_DISCONNECTED		(1 << 0)
+#define UVC_QUEUE_DROP_INCOMPLETE	(1 << 1)
+#define UVC_QUEUE_PAUSED		(1 << 2)
 
 
 struct uvc_video_queue {
 struct uvc_video_queue {
-	enum v4l2_buf_type type;
+	struct vb2_queue queue;
+	struct mutex mutex;	/* Protects queue */
 
 
-	void *mem;
 	unsigned int flags;
 	unsigned int flags;
 	__u32 sequence;
 	__u32 sequence;
 
 
-	unsigned int count;
-	unsigned int buf_size;
 	unsigned int buf_used;
 	unsigned int buf_used;
-	struct uvc_buffer buffer[UVC_MAX_VIDEO_BUFFERS];
-	struct mutex mutex;	/* protects buffers and mainqueue */
-	spinlock_t irqlock;	/* protects irqqueue */
 
 
-	struct list_head mainqueue;
+	spinlock_t irqlock;	/* Protects flags and irqqueue */
 	struct list_head irqqueue;
 	struct list_head irqqueue;
 };
 };
 
 
 static inline int uvc_queue_streaming(struct uvc_video_queue *queue)
 static inline int uvc_queue_streaming(struct uvc_video_queue *queue)
 {
 {
-	return queue->flags & UVC_QUEUE_STREAMING;
+	return vb2_is_streaming(&queue->queue);
 }
 }
 
 
 #endif /* __KERNEL__ */
 #endif /* __KERNEL__ */

+ 40 - 31
drivers/usb/gadget/uvc_v4l2.c

@@ -41,9 +41,8 @@ uvc_send_response(struct uvc_device *uvc, struct uvc_request_data *data)
 
 
 	req->length = min_t(unsigned int, uvc->event_length, data->length);
 	req->length = min_t(unsigned int, uvc->event_length, data->length);
 	req->zero = data->length < uvc->event_length;
 	req->zero = data->length < uvc->event_length;
-	req->dma = DMA_ADDR_INVALID;
 
 
-	memcpy(req->buf, data->data, data->length);
+	memcpy(req->buf, data->data, req->length);
 
 
 	return usb_ep_queue(cdev->gadget->ep0, req, GFP_KERNEL);
 	return usb_ep_queue(cdev->gadget->ep0, req, GFP_KERNEL);
 }
 }
@@ -148,16 +147,13 @@ uvc_v4l2_release(struct file *file)
 	uvc_function_disconnect(uvc);
 	uvc_function_disconnect(uvc);
 
 
 	uvc_video_enable(video, 0);
 	uvc_video_enable(video, 0);
-	mutex_lock(&video->queue.mutex);
-	if (uvc_free_buffers(&video->queue) < 0)
-		printk(KERN_ERR "uvc_v4l2_release: Unable to free "
-				"buffers.\n");
-	mutex_unlock(&video->queue.mutex);
+	uvc_free_buffers(&video->queue);
 
 
 	file->private_data = NULL;
 	file->private_data = NULL;
 	v4l2_fh_del(&handle->vfh);
 	v4l2_fh_del(&handle->vfh);
 	v4l2_fh_exit(&handle->vfh);
 	v4l2_fh_exit(&handle->vfh);
 	kfree(handle);
 	kfree(handle);
+
 	return 0;
 	return 0;
 }
 }
 
 
@@ -178,9 +174,9 @@ uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
 		struct v4l2_capability *cap = arg;
 		struct v4l2_capability *cap = arg;
 
 
 		memset(cap, 0, sizeof *cap);
 		memset(cap, 0, sizeof *cap);
-		strncpy(cap->driver, "g_uvc", sizeof(cap->driver));
-		strncpy(cap->card, cdev->gadget->name, sizeof(cap->card));
-		strncpy(cap->bus_info, dev_name(&cdev->gadget->dev),
+		strlcpy(cap->driver, "g_uvc", sizeof(cap->driver));
+		strlcpy(cap->card, cdev->gadget->name, sizeof(cap->card));
+		strlcpy(cap->bus_info, dev_name(&cdev->gadget->dev),
 			sizeof cap->bus_info);
 			sizeof cap->bus_info);
 		cap->version = DRIVER_VERSION_NUMBER;
 		cap->version = DRIVER_VERSION_NUMBER;
 		cap->capabilities = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING;
 		cap->capabilities = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING;
@@ -192,7 +188,7 @@ uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
 	{
 	{
 		struct v4l2_format *fmt = arg;
 		struct v4l2_format *fmt = arg;
 
 
-		if (fmt->type != video->queue.type)
+		if (fmt->type != video->queue.queue.type)
 			return -EINVAL;
 			return -EINVAL;
 
 
 		return uvc_v4l2_get_format(video, fmt);
 		return uvc_v4l2_get_format(video, fmt);
@@ -202,7 +198,7 @@ uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
 	{
 	{
 		struct v4l2_format *fmt = arg;
 		struct v4l2_format *fmt = arg;
 
 
-		if (fmt->type != video->queue.type)
+		if (fmt->type != video->queue.queue.type)
 			return -EINVAL;
 			return -EINVAL;
 
 
 		return uvc_v4l2_set_format(video, fmt);
 		return uvc_v4l2_set_format(video, fmt);
@@ -213,16 +209,13 @@ uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
 	{
 	{
 		struct v4l2_requestbuffers *rb = arg;
 		struct v4l2_requestbuffers *rb = arg;
 
 
-		if (rb->type != video->queue.type ||
-		    rb->memory != V4L2_MEMORY_MMAP)
+		if (rb->type != video->queue.queue.type)
 			return -EINVAL;
 			return -EINVAL;
 
 
-		ret = uvc_alloc_buffers(&video->queue, rb->count,
-					video->imagesize);
+		ret = uvc_alloc_buffers(&video->queue, rb);
 		if (ret < 0)
 		if (ret < 0)
 			return ret;
 			return ret;
 
 
-		rb->count = ret;
 		ret = 0;
 		ret = 0;
 		break;
 		break;
 	}
 	}
@@ -231,9 +224,6 @@ uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
 	{
 	{
 		struct v4l2_buffer *buf = arg;
 		struct v4l2_buffer *buf = arg;
 
 
-		if (buf->type != video->queue.type)
-			return -EINVAL;
-
 		return uvc_query_buffer(&video->queue, buf);
 		return uvc_query_buffer(&video->queue, buf);
 	}
 	}
 
 
@@ -251,24 +241,36 @@ uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
 	{
 	{
 		int *type = arg;
 		int *type = arg;
 
 
-		if (*type != video->queue.type)
+		if (*type != video->queue.queue.type)
 			return -EINVAL;
 			return -EINVAL;
 
 
-		return uvc_video_enable(video, 1);
+		/* Enable UVC video. */
+		ret = uvc_video_enable(video, 1);
+		if (ret < 0)
+			return ret;
+
+		/*
+		 * Complete the alternate setting selection setup phase now that
+		 * userspace is ready to provide video frames.
+		 */
+		uvc_function_setup_continue(uvc);
+		uvc->state = UVC_STATE_STREAMING;
+
+		return 0;
 	}
 	}
 
 
 	case VIDIOC_STREAMOFF:
 	case VIDIOC_STREAMOFF:
 	{
 	{
 		int *type = arg;
 		int *type = arg;
 
 
-		if (*type != video->queue.type)
+		if (*type != video->queue.queue.type)
 			return -EINVAL;
 			return -EINVAL;
 
 
 		return uvc_video_enable(video, 0);
 		return uvc_video_enable(video, 0);
 	}
 	}
 
 
 	/* Events */
 	/* Events */
-        case VIDIOC_DQEVENT:
+	case VIDIOC_DQEVENT:
 	{
 	{
 		struct v4l2_event *event = arg;
 		struct v4l2_event *event = arg;
 
 
@@ -333,17 +335,21 @@ uvc_v4l2_poll(struct file *file, poll_table *wait)
 {
 {
 	struct video_device *vdev = video_devdata(file);
 	struct video_device *vdev = video_devdata(file);
 	struct uvc_device *uvc = video_get_drvdata(vdev);
 	struct uvc_device *uvc = video_get_drvdata(vdev);
-	struct uvc_file_handle *handle = to_uvc_file_handle(file->private_data);
-	unsigned int mask = 0;
 
 
-	poll_wait(file, &handle->vfh.wait, wait);
-	if (v4l2_event_pending(&handle->vfh))
-		mask |= POLLPRI;
+	return uvc_queue_poll(&uvc->video.queue, file, wait);
+}
 
 
-	mask |= uvc_queue_poll(&uvc->video.queue, file, wait);
+#ifndef CONFIG_MMU
+static unsigned long uvc_v4l2_get_unmapped_area(struct file *file,
+		unsigned long addr, unsigned long len, unsigned long pgoff,
+		unsigned long flags)
+{
+	struct video_device *vdev = video_devdata(file);
+	struct uvc_device *uvc = video_get_drvdata(vdev);
 
 
-	return mask;
+	return uvc_queue_get_unmapped_area(&uvc->video.queue, pgoff);
 }
 }
+#endif
 
 
 static struct v4l2_file_operations uvc_v4l2_fops = {
 static struct v4l2_file_operations uvc_v4l2_fops = {
 	.owner		= THIS_MODULE,
 	.owner		= THIS_MODULE,
@@ -352,5 +358,8 @@ static struct v4l2_file_operations uvc_v4l2_fops = {
 	.ioctl		= uvc_v4l2_ioctl,
 	.ioctl		= uvc_v4l2_ioctl,
 	.mmap		= uvc_v4l2_mmap,
 	.mmap		= uvc_v4l2_mmap,
 	.poll		= uvc_v4l2_poll,
 	.poll		= uvc_v4l2_poll,
+#ifndef CONFIG_MMU
+	.get_unmapped_area = uvc_v4l2_get_unmapped_area,
+#endif
 };
 };
 
 

+ 20 - 11
drivers/usb/gadget/uvc_video.c

@@ -32,7 +32,7 @@ uvc_video_encode_header(struct uvc_video *video, struct uvc_buffer *buf,
 	data[0] = 2;
 	data[0] = 2;
 	data[1] = UVC_STREAM_EOH | video->fid;
 	data[1] = UVC_STREAM_EOH | video->fid;
 
 
-	if (buf->buf.bytesused - video->queue.buf_used <= len - 2)
+	if (buf->bytesused - video->queue.buf_used <= len - 2)
 		data[1] |= UVC_STREAM_EOF;
 		data[1] |= UVC_STREAM_EOF;
 
 
 	return 2;
 	return 2;
@@ -47,8 +47,8 @@ uvc_video_encode_data(struct uvc_video *video, struct uvc_buffer *buf,
 	void *mem;
 	void *mem;
 
 
 	/* Copy video data to the USB buffer. */
 	/* Copy video data to the USB buffer. */
-	mem = queue->mem + buf->buf.m.offset + queue->buf_used;
-	nbytes = min((unsigned int)len, buf->buf.bytesused - queue->buf_used);
+	mem = buf->mem + queue->buf_used;
+	nbytes = min((unsigned int)len, buf->bytesused - queue->buf_used);
 
 
 	memcpy(data, mem, nbytes);
 	memcpy(data, mem, nbytes);
 	queue->buf_used += nbytes;
 	queue->buf_used += nbytes;
@@ -82,7 +82,7 @@ uvc_video_encode_bulk(struct usb_request *req, struct uvc_video *video,
 	req->length = video->req_size - len;
 	req->length = video->req_size - len;
 	req->zero = video->payload_size == video->max_payload_size;
 	req->zero = video->payload_size == video->max_payload_size;
 
 
-	if (buf->buf.bytesused == video->queue.buf_used) {
+	if (buf->bytesused == video->queue.buf_used) {
 		video->queue.buf_used = 0;
 		video->queue.buf_used = 0;
 		buf->state = UVC_BUF_STATE_DONE;
 		buf->state = UVC_BUF_STATE_DONE;
 		uvc_queue_next_buffer(&video->queue, buf);
 		uvc_queue_next_buffer(&video->queue, buf);
@@ -92,7 +92,7 @@ uvc_video_encode_bulk(struct usb_request *req, struct uvc_video *video,
 	}
 	}
 
 
 	if (video->payload_size == video->max_payload_size ||
 	if (video->payload_size == video->max_payload_size ||
-	    buf->buf.bytesused == video->queue.buf_used)
+	    buf->bytesused == video->queue.buf_used)
 		video->payload_size = 0;
 		video->payload_size = 0;
 }
 }
 
 
@@ -115,7 +115,7 @@ uvc_video_encode_isoc(struct usb_request *req, struct uvc_video *video,
 
 
 	req->length = video->req_size - len;
 	req->length = video->req_size - len;
 
 
-	if (buf->buf.bytesused == video->queue.buf_used) {
+	if (buf->bytesused == video->queue.buf_used) {
 		video->queue.buf_used = 0;
 		video->queue.buf_used = 0;
 		buf->state = UVC_BUF_STATE_DONE;
 		buf->state = UVC_BUF_STATE_DONE;
 		uvc_queue_next_buffer(&video->queue, buf);
 		uvc_queue_next_buffer(&video->queue, buf);
@@ -161,6 +161,7 @@ static void
 uvc_video_complete(struct usb_ep *ep, struct usb_request *req)
 uvc_video_complete(struct usb_ep *ep, struct usb_request *req)
 {
 {
 	struct uvc_video *video = req->context;
 	struct uvc_video *video = req->context;
+	struct uvc_video_queue *queue = &video->queue;
 	struct uvc_buffer *buf;
 	struct uvc_buffer *buf;
 	unsigned long flags;
 	unsigned long flags;
 	int ret;
 	int ret;
@@ -169,13 +170,15 @@ uvc_video_complete(struct usb_ep *ep, struct usb_request *req)
 	case 0:
 	case 0:
 		break;
 		break;
 
 
-	case -ESHUTDOWN:
+	case -ESHUTDOWN:	/* disconnect from host. */
 		printk(KERN_INFO "VS request cancelled.\n");
 		printk(KERN_INFO "VS request cancelled.\n");
+		uvc_queue_cancel(queue, 1);
 		goto requeue;
 		goto requeue;
 
 
 	default:
 	default:
 		printk(KERN_INFO "VS request completed with status %d.\n",
 		printk(KERN_INFO "VS request completed with status %d.\n",
 			req->status);
 			req->status);
+		uvc_queue_cancel(queue, 0);
 		goto requeue;
 		goto requeue;
 	}
 	}
 
 
@@ -229,13 +232,18 @@ uvc_video_free_requests(struct uvc_video *video)
 static int
 static int
 uvc_video_alloc_requests(struct uvc_video *video)
 uvc_video_alloc_requests(struct uvc_video *video)
 {
 {
+	unsigned int req_size;
 	unsigned int i;
 	unsigned int i;
 	int ret = -ENOMEM;
 	int ret = -ENOMEM;
 
 
 	BUG_ON(video->req_size);
 	BUG_ON(video->req_size);
 
 
+	req_size = video->ep->maxpacket
+		 * max_t(unsigned int, video->ep->maxburst, 1)
+		 * (video->ep->mult + 1);
+
 	for (i = 0; i < UVC_NUM_REQUESTS; ++i) {
 	for (i = 0; i < UVC_NUM_REQUESTS; ++i) {
-		video->req_buffer[i] = kmalloc(video->ep->maxpacket, GFP_KERNEL);
+		video->req_buffer[i] = kmalloc(req_size, GFP_KERNEL);
 		if (video->req_buffer[i] == NULL)
 		if (video->req_buffer[i] == NULL)
 			goto error;
 			goto error;
 
 
@@ -245,14 +253,14 @@ uvc_video_alloc_requests(struct uvc_video *video)
 
 
 		video->req[i]->buf = video->req_buffer[i];
 		video->req[i]->buf = video->req_buffer[i];
 		video->req[i]->length = 0;
 		video->req[i]->length = 0;
-		video->req[i]->dma = DMA_ADDR_INVALID;
 		video->req[i]->complete = uvc_video_complete;
 		video->req[i]->complete = uvc_video_complete;
 		video->req[i]->context = video;
 		video->req[i]->context = video;
 
 
 		list_add_tail(&video->req[i]->list, &video->req_free);
 		list_add_tail(&video->req[i]->list, &video->req_free);
 	}
 	}
 
 
-	video->req_size = video->ep->maxpacket;
+	video->req_size = req_size;
+
 	return 0;
 	return 0;
 
 
 error:
 error:
@@ -309,7 +317,8 @@ uvc_video_pump(struct uvc_video *video)
 		video->encode(req, video, buf);
 		video->encode(req, video, buf);
 
 
 		/* Queue the USB request */
 		/* Queue the USB request */
-		if ((ret = usb_ep_queue(video->ep, req, GFP_KERNEL)) < 0) {
+		ret = usb_ep_queue(video->ep, req, GFP_ATOMIC);
+		if (ret < 0) {
 			printk(KERN_INFO "Failed to queue request (%d)\n", ret);
 			printk(KERN_INFO "Failed to queue request (%d)\n", ret);
 			usb_ep_set_halt(video->ep);
 			usb_ep_set_halt(video->ep);
 			spin_unlock_irqrestore(&video->queue.irqlock, flags);
 			spin_unlock_irqrestore(&video->queue.irqlock, flags);

+ 1 - 1
drivers/usb/host/Kconfig

@@ -180,6 +180,7 @@ config USB_EHCI_TEGRA
        boolean "NVIDIA Tegra HCD support"
        boolean "NVIDIA Tegra HCD support"
        depends on USB_EHCI_HCD && ARCH_TEGRA
        depends on USB_EHCI_HCD && ARCH_TEGRA
        select USB_EHCI_ROOT_HUB_TT
        select USB_EHCI_ROOT_HUB_TT
+       select USB_PHY
        help
        help
          This driver enables support for the internal USB Host Controllers
          This driver enables support for the internal USB Host Controllers
          found in NVIDIA Tegra SoCs. The controllers are EHCI compliant.
          found in NVIDIA Tegra SoCs. The controllers are EHCI compliant.
@@ -301,7 +302,6 @@ config USB_OHCI_HCD
 	tristate "OHCI HCD support"
 	tristate "OHCI HCD support"
 	depends on USB && USB_ARCH_HAS_OHCI
 	depends on USB && USB_ARCH_HAS_OHCI
 	select ISP1301_OMAP if MACH_OMAP_H2 || MACH_OMAP_H3
 	select ISP1301_OMAP if MACH_OMAP_H2 || MACH_OMAP_H3
-	select USB_OTG_UTILS if ARCH_OMAP
 	depends on USB_ISP1301 || !ARCH_LPC32XX
 	depends on USB_ISP1301 || !ARCH_LPC32XX
 	---help---
 	---help---
 	  The Open Host Controller Interface (OHCI) is a standard for accessing
 	  The Open Host Controller Interface (OHCI) is a standard for accessing

+ 1 - 1
drivers/usb/host/ehci-msm.c

@@ -145,7 +145,7 @@ static int ehci_msm_probe(struct platform_device *pdev)
 	 * management.
 	 * management.
 	 */
 	 */
 	phy = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2);
 	phy = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2);
-	if (IS_ERR_OR_NULL(phy)) {
+	if (IS_ERR(phy)) {
 		dev_err(&pdev->dev, "unable to find transceiver\n");
 		dev_err(&pdev->dev, "unable to find transceiver\n");
 		ret = -ENODEV;
 		ret = -ENODEV;
 		goto put_hcd;
 		goto put_hcd;

+ 19 - 35
drivers/usb/host/ehci-mv.c

@@ -33,25 +33,17 @@ struct ehci_hcd_mv {
 
 
 	struct mv_usb_platform_data *pdata;
 	struct mv_usb_platform_data *pdata;
 
 
-	/* clock source and total clock number */
-	unsigned int clknum;
-	struct clk *clk[0];
+	struct clk *clk;
 };
 };
 
 
 static void ehci_clock_enable(struct ehci_hcd_mv *ehci_mv)
 static void ehci_clock_enable(struct ehci_hcd_mv *ehci_mv)
 {
 {
-	unsigned int i;
-
-	for (i = 0; i < ehci_mv->clknum; i++)
-		clk_prepare_enable(ehci_mv->clk[i]);
+	clk_prepare_enable(ehci_mv->clk);
 }
 }
 
 
 static void ehci_clock_disable(struct ehci_hcd_mv *ehci_mv)
 static void ehci_clock_disable(struct ehci_hcd_mv *ehci_mv)
 {
 {
-	unsigned int i;
-
-	for (i = 0; i < ehci_mv->clknum; i++)
-		clk_disable_unprepare(ehci_mv->clk[i]);
+	clk_disable_unprepare(ehci_mv->clk);
 }
 }
 
 
 static int mv_ehci_enable(struct ehci_hcd_mv *ehci_mv)
 static int mv_ehci_enable(struct ehci_hcd_mv *ehci_mv)
@@ -144,9 +136,8 @@ static int mv_ehci_probe(struct platform_device *pdev)
 	struct ehci_hcd *ehci;
 	struct ehci_hcd *ehci;
 	struct ehci_hcd_mv *ehci_mv;
 	struct ehci_hcd_mv *ehci_mv;
 	struct resource *r;
 	struct resource *r;
-	int clk_i, retval = -ENODEV;
+	int retval = -ENODEV;
 	u32 offset;
 	u32 offset;
-	size_t size;
 
 
 	if (!pdata) {
 	if (!pdata) {
 		dev_err(&pdev->dev, "missing platform_data\n");
 		dev_err(&pdev->dev, "missing platform_data\n");
@@ -160,8 +151,7 @@ static int mv_ehci_probe(struct platform_device *pdev)
 	if (!hcd)
 	if (!hcd)
 		return -ENOMEM;
 		return -ENOMEM;
 
 
-	size = sizeof(*ehci_mv) + sizeof(struct clk *) * pdata->clknum;
-	ehci_mv = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
+	ehci_mv = devm_kzalloc(&pdev->dev, sizeof(*ehci_mv), GFP_KERNEL);
 	if (ehci_mv == NULL) {
 	if (ehci_mv == NULL) {
 		dev_err(&pdev->dev, "cannot allocate ehci_hcd_mv\n");
 		dev_err(&pdev->dev, "cannot allocate ehci_hcd_mv\n");
 		retval = -ENOMEM;
 		retval = -ENOMEM;
@@ -172,16 +162,11 @@ static int mv_ehci_probe(struct platform_device *pdev)
 	ehci_mv->pdata = pdata;
 	ehci_mv->pdata = pdata;
 	ehci_mv->hcd = hcd;
 	ehci_mv->hcd = hcd;
 
 
-	ehci_mv->clknum = pdata->clknum;
-	for (clk_i = 0; clk_i < ehci_mv->clknum; clk_i++) {
-		ehci_mv->clk[clk_i] =
-		    devm_clk_get(&pdev->dev, pdata->clkname[clk_i]);
-		if (IS_ERR(ehci_mv->clk[clk_i])) {
-			dev_err(&pdev->dev, "error get clck \"%s\"\n",
-				pdata->clkname[clk_i]);
-			retval = PTR_ERR(ehci_mv->clk[clk_i]);
-			goto err_clear_drvdata;
-		}
+	ehci_mv->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(ehci_mv->clk)) {
+		dev_err(&pdev->dev, "error getting clock\n");
+		retval = PTR_ERR(ehci_mv->clk);
+		goto err_clear_drvdata;
 	}
 	}
 
 
 	r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phyregs");
 	r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phyregs");
@@ -240,12 +225,16 @@ static int mv_ehci_probe(struct platform_device *pdev)
 
 
 	ehci_mv->mode = pdata->mode;
 	ehci_mv->mode = pdata->mode;
 	if (ehci_mv->mode == MV_USB_MODE_OTG) {
 	if (ehci_mv->mode == MV_USB_MODE_OTG) {
-#ifdef CONFIG_USB_OTG_UTILS
 		ehci_mv->otg = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2);
 		ehci_mv->otg = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2);
-		if (IS_ERR_OR_NULL(ehci_mv->otg)) {
-			dev_err(&pdev->dev,
-				"unable to find transceiver\n");
-			retval = -ENODEV;
+		if (IS_ERR(ehci_mv->otg)) {
+			retval = PTR_ERR(ehci_mv->otg);
+
+			if (retval == -ENXIO)
+				dev_info(&pdev->dev, "MV_USB_MODE_OTG "
+						"must have CONFIG_USB_PHY enabled\n");
+			else
+				dev_err(&pdev->dev,
+						"unable to find transceiver\n");
 			goto err_disable_clk;
 			goto err_disable_clk;
 		}
 		}
 
 
@@ -258,11 +247,6 @@ static int mv_ehci_probe(struct platform_device *pdev)
 		}
 		}
 		/* otg will enable clock before use as host */
 		/* otg will enable clock before use as host */
 		mv_ehci_disable(ehci_mv);
 		mv_ehci_disable(ehci_mv);
-#else
-		dev_info(&pdev->dev, "MV_USB_MODE_OTG "
-			 "must have CONFIG_USB_OTG_UTILS enabled\n");
-		goto err_disable_clk;
-#endif
 	} else {
 	} else {
 		if (pdata->set_vbus)
 		if (pdata->set_vbus)
 			pdata->set_vbus(1);
 			pdata->set_vbus(1);

+ 1 - 1
drivers/usb/host/ehci-s5p.c

@@ -140,7 +140,7 @@ static int s5p_ehci_probe(struct platform_device *pdev)
 		return -ENOMEM;
 		return -ENOMEM;
 
 
 	phy = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2);
 	phy = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2);
-	if (IS_ERR_OR_NULL(phy)) {
+	if (IS_ERR(phy)) {
 		/* Fallback to pdata */
 		/* Fallback to pdata */
 		if (!pdata) {
 		if (!pdata) {
 			dev_warn(&pdev->dev, "no platform data or transceiver defined\n");
 			dev_warn(&pdev->dev, "no platform data or transceiver defined\n");

+ 3 - 9
drivers/usb/host/ehci-tegra.c

@@ -773,16 +773,14 @@ static int tegra_ehci_probe(struct platform_device *pdev)
 		goto fail_phy;
 		goto fail_phy;
 	}
 	}
 
 
-#ifdef CONFIG_USB_OTG_UTILS
 	if (pdata->operating_mode == TEGRA_USB_OTG) {
 	if (pdata->operating_mode == TEGRA_USB_OTG) {
 		tegra->transceiver =
 		tegra->transceiver =
 			devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2);
 			devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2);
-		if (!IS_ERR_OR_NULL(tegra->transceiver))
+		if (!IS_ERR(tegra->transceiver))
 			otg_set_host(tegra->transceiver->otg, &hcd->self);
 			otg_set_host(tegra->transceiver->otg, &hcd->self);
 	} else {
 	} else {
 		tegra->transceiver = ERR_PTR(-ENODEV);
 		tegra->transceiver = ERR_PTR(-ENODEV);
 	}
 	}
-#endif
 
 
 	err = usb_add_hcd(hcd, irq, IRQF_SHARED);
 	err = usb_add_hcd(hcd, irq, IRQF_SHARED);
 	if (err) {
 	if (err) {
@@ -801,10 +799,8 @@ static int tegra_ehci_probe(struct platform_device *pdev)
 	return err;
 	return err;
 
 
 fail:
 fail:
-#ifdef CONFIG_USB_OTG_UTILS
-	if (!IS_ERR_OR_NULL(tegra->transceiver))
+	if (!IS_ERR(tegra->transceiver))
 		otg_set_host(tegra->transceiver->otg, NULL);
 		otg_set_host(tegra->transceiver->otg, NULL);
-#endif
 fail_phy:
 fail_phy:
 	usb_phy_shutdown(hcd->phy);
 	usb_phy_shutdown(hcd->phy);
 fail_io:
 fail_io:
@@ -823,10 +819,8 @@ static int tegra_ehci_remove(struct platform_device *pdev)
 	pm_runtime_disable(&pdev->dev);
 	pm_runtime_disable(&pdev->dev);
 	pm_runtime_put_noidle(&pdev->dev);
 	pm_runtime_put_noidle(&pdev->dev);
 
 
-#ifdef CONFIG_USB_OTG_UTILS
-	if (!IS_ERR_OR_NULL(tegra->transceiver))
+	if (!IS_ERR(tegra->transceiver))
 		otg_set_host(tegra->transceiver->otg, NULL);
 		otg_set_host(tegra->transceiver->otg, NULL);
-#endif
 
 
 	usb_phy_shutdown(hcd->phy);
 	usb_phy_shutdown(hcd->phy);
 	usb_remove_hcd(hcd);
 	usb_remove_hcd(hcd);

+ 1 - 1
drivers/usb/host/ohci-exynos.c

@@ -128,7 +128,7 @@ static int exynos_ohci_probe(struct platform_device *pdev)
 		return -ENOMEM;
 		return -ENOMEM;
 
 
 	phy = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2);
 	phy = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2);
-	if (IS_ERR_OR_NULL(phy)) {
+	if (IS_ERR(phy)) {
 		/* Fallback to pdata */
 		/* Fallback to pdata */
 		if (!pdata) {
 		if (!pdata) {
 			dev_warn(&pdev->dev, "no platform data or transceiver defined\n");
 			dev_warn(&pdev->dev, "no platform data or transceiver defined\n");

+ 3 - 3
drivers/usb/musb/Kconfig

@@ -7,7 +7,6 @@
 config USB_MUSB_HDRC
 config USB_MUSB_HDRC
 	tristate 'Inventra Highspeed Dual Role Controller (TI, ADI, ...)'
 	tristate 'Inventra Highspeed Dual Role Controller (TI, ADI, ...)'
 	depends on USB && USB_GADGET
 	depends on USB && USB_GADGET
-	select USB_OTG_UTILS
 	help
 	help
 	  Say Y here if your system has a dual role high speed USB
 	  Say Y here if your system has a dual role high speed USB
 	  controller based on the Mentor Graphics silicon IP.  Then
 	  controller based on the Mentor Graphics silicon IP.  Then
@@ -34,10 +33,12 @@ choice
 config USB_MUSB_DAVINCI
 config USB_MUSB_DAVINCI
 	tristate "DaVinci"
 	tristate "DaVinci"
 	depends on ARCH_DAVINCI_DMx
 	depends on ARCH_DAVINCI_DMx
+	depends on BROKEN
 
 
 config USB_MUSB_DA8XX
 config USB_MUSB_DA8XX
 	tristate "DA8xx/OMAP-L1x"
 	tristate "DA8xx/OMAP-L1x"
 	depends on ARCH_DAVINCI_DA8XX
 	depends on ARCH_DAVINCI_DA8XX
+	depends on BROKEN
 
 
 config USB_MUSB_TUSB6010
 config USB_MUSB_TUSB6010
 	tristate "TUSB6010"
 	tristate "TUSB6010"
@@ -53,7 +54,6 @@ config USB_MUSB_AM35X
 
 
 config USB_MUSB_DSPS
 config USB_MUSB_DSPS
 	tristate "TI DSPS platforms"
 	tristate "TI DSPS platforms"
-	depends on SOC_TI81XX || SOC_AM33XX
 
 
 config USB_MUSB_BLACKFIN
 config USB_MUSB_BLACKFIN
 	tristate "Blackfin"
 	tristate "Blackfin"
@@ -61,12 +61,12 @@ config USB_MUSB_BLACKFIN
 
 
 config USB_MUSB_UX500
 config USB_MUSB_UX500
 	tristate "U8500 and U5500"
 	tristate "U8500 and U5500"
-	depends on (ARCH_U8500 && AB8500_USB)
 
 
 endchoice
 endchoice
 
 
 choice
 choice
 	prompt 'MUSB DMA mode'
 	prompt 'MUSB DMA mode'
+	default MUSB_PIO_ONLY if ARCH_MULTIPLATFORM
 	default USB_UX500_DMA if USB_MUSB_UX500
 	default USB_UX500_DMA if USB_MUSB_UX500
 	default USB_INVENTRA_DMA if USB_MUSB_OMAP2PLUS || USB_MUSB_BLACKFIN
 	default USB_INVENTRA_DMA if USB_MUSB_OMAP2PLUS || USB_MUSB_BLACKFIN
 	default USB_TI_CPPI_DMA if USB_MUSB_DAVINCI
 	default USB_TI_CPPI_DMA if USB_MUSB_DAVINCI

+ 4 - 4
drivers/usb/musb/am35x.c

@@ -149,7 +149,7 @@ static void otg_timer(unsigned long _musb)
 	 */
 	 */
 	devctl = musb_readb(mregs, MUSB_DEVCTL);
 	devctl = musb_readb(mregs, MUSB_DEVCTL);
 	dev_dbg(musb->controller, "Poll devctl %02x (%s)\n", devctl,
 	dev_dbg(musb->controller, "Poll devctl %02x (%s)\n", devctl,
-		otg_state_string(musb->xceiv->state));
+		usb_otg_state_string(musb->xceiv->state));
 
 
 	spin_lock_irqsave(&musb->lock, flags);
 	spin_lock_irqsave(&musb->lock, flags);
 	switch (musb->xceiv->state) {
 	switch (musb->xceiv->state) {
@@ -195,7 +195,7 @@ static void am35x_musb_try_idle(struct musb *musb, unsigned long timeout)
 	if (musb->is_active || (musb->a_wait_bcon == 0 &&
 	if (musb->is_active || (musb->a_wait_bcon == 0 &&
 				musb->xceiv->state == OTG_STATE_A_WAIT_BCON)) {
 				musb->xceiv->state == OTG_STATE_A_WAIT_BCON)) {
 		dev_dbg(musb->controller, "%s active, deleting timer\n",
 		dev_dbg(musb->controller, "%s active, deleting timer\n",
-			otg_state_string(musb->xceiv->state));
+			usb_otg_state_string(musb->xceiv->state));
 		del_timer(&otg_workaround);
 		del_timer(&otg_workaround);
 		last_timer = jiffies;
 		last_timer = jiffies;
 		return;
 		return;
@@ -208,7 +208,7 @@ static void am35x_musb_try_idle(struct musb *musb, unsigned long timeout)
 	last_timer = timeout;
 	last_timer = timeout;
 
 
 	dev_dbg(musb->controller, "%s inactive, starting idle timer for %u ms\n",
 	dev_dbg(musb->controller, "%s inactive, starting idle timer for %u ms\n",
-		otg_state_string(musb->xceiv->state),
+		usb_otg_state_string(musb->xceiv->state),
 		jiffies_to_msecs(timeout - jiffies));
 		jiffies_to_msecs(timeout - jiffies));
 	mod_timer(&otg_workaround, timeout);
 	mod_timer(&otg_workaround, timeout);
 }
 }
@@ -298,7 +298,7 @@ static irqreturn_t am35x_musb_interrupt(int irq, void *hci)
 		/* NOTE: this must complete power-on within 100 ms. */
 		/* NOTE: this must complete power-on within 100 ms. */
 		dev_dbg(musb->controller, "VBUS %s (%s)%s, devctl %02x\n",
 		dev_dbg(musb->controller, "VBUS %s (%s)%s, devctl %02x\n",
 				drvvbus ? "on" : "off",
 				drvvbus ? "on" : "off",
-				otg_state_string(musb->xceiv->state),
+				usb_otg_state_string(musb->xceiv->state),
 				err ? " ERROR" : "",
 				err ? " ERROR" : "",
 				devctl);
 				devctl);
 		ret = IRQ_HANDLED;
 		ret = IRQ_HANDLED;

+ 3 - 3
drivers/usb/musb/blackfin.c

@@ -280,13 +280,13 @@ static void musb_conn_timer_handler(unsigned long _musb)
 		break;
 		break;
 	default:
 	default:
 		dev_dbg(musb->controller, "%s state not handled\n",
 		dev_dbg(musb->controller, "%s state not handled\n",
-			otg_state_string(musb->xceiv->state));
+			usb_otg_state_string(musb->xceiv->state));
 		break;
 		break;
 	}
 	}
 	spin_unlock_irqrestore(&musb->lock, flags);
 	spin_unlock_irqrestore(&musb->lock, flags);
 
 
 	dev_dbg(musb->controller, "state is %s\n",
 	dev_dbg(musb->controller, "state is %s\n",
-		otg_state_string(musb->xceiv->state));
+		usb_otg_state_string(musb->xceiv->state));
 }
 }
 
 
 static void bfin_musb_enable(struct musb *musb)
 static void bfin_musb_enable(struct musb *musb)
@@ -307,7 +307,7 @@ static void bfin_musb_set_vbus(struct musb *musb, int is_on)
 
 
 	dev_dbg(musb->controller, "VBUS %s, devctl %02x "
 	dev_dbg(musb->controller, "VBUS %s, devctl %02x "
 		/* otg %3x conf %08x prcm %08x */ "\n",
 		/* otg %3x conf %08x prcm %08x */ "\n",
-		otg_state_string(musb->xceiv->state),
+		usb_otg_state_string(musb->xceiv->state),
 		musb_readb(musb->mregs, MUSB_DEVCTL));
 		musb_readb(musb->mregs, MUSB_DEVCTL));
 }
 }
 
 

+ 3 - 14
drivers/usb/musb/cppi_dma.c

@@ -435,7 +435,6 @@ cppi_rndis_update(struct cppi_channel *c, int is_rx,
 	}
 	}
 }
 }
 
 
-#ifdef CONFIG_USB_MUSB_DEBUG
 static void cppi_dump_rxbd(const char *tag, struct cppi_descriptor *bd)
 static void cppi_dump_rxbd(const char *tag, struct cppi_descriptor *bd)
 {
 {
 	pr_debug("RXBD/%s %08x: "
 	pr_debug("RXBD/%s %08x: "
@@ -444,21 +443,16 @@ static void cppi_dump_rxbd(const char *tag, struct cppi_descriptor *bd)
 			bd->hw_next, bd->hw_bufp, bd->hw_off_len,
 			bd->hw_next, bd->hw_bufp, bd->hw_off_len,
 			bd->hw_options);
 			bd->hw_options);
 }
 }
-#endif
 
 
 static void cppi_dump_rxq(int level, const char *tag, struct cppi_channel *rx)
 static void cppi_dump_rxq(int level, const char *tag, struct cppi_channel *rx)
 {
 {
-#ifdef CONFIG_USB_MUSB_DEBUG
 	struct cppi_descriptor	*bd;
 	struct cppi_descriptor	*bd;
 
 
-	if (!_dbg_level(level))
-		return;
 	cppi_dump_rx(level, rx, tag);
 	cppi_dump_rx(level, rx, tag);
 	if (rx->last_processed)
 	if (rx->last_processed)
 		cppi_dump_rxbd("last", rx->last_processed);
 		cppi_dump_rxbd("last", rx->last_processed);
 	for (bd = rx->head; bd; bd = bd->next)
 	for (bd = rx->head; bd; bd = bd->next)
 		cppi_dump_rxbd("active", bd);
 		cppi_dump_rxbd("active", bd);
-#endif
 }
 }
 
 
 
 
@@ -784,6 +778,7 @@ cppi_next_rx_segment(struct musb *musb, struct cppi_channel *rx, int onepacket)
 	void __iomem		*tibase = musb->ctrl_base;
 	void __iomem		*tibase = musb->ctrl_base;
 	int			is_rndis = 0;
 	int			is_rndis = 0;
 	struct cppi_rx_stateram	__iomem *rx_ram = rx->state_ram;
 	struct cppi_rx_stateram	__iomem *rx_ram = rx->state_ram;
+	struct cppi_descriptor	*d;
 
 
 	if (onepacket) {
 	if (onepacket) {
 		/* almost every USB driver, host or peripheral side */
 		/* almost every USB driver, host or peripheral side */
@@ -897,14 +892,8 @@ cppi_next_rx_segment(struct musb *musb, struct cppi_channel *rx, int onepacket)
 	bd->hw_options |= CPPI_SOP_SET;
 	bd->hw_options |= CPPI_SOP_SET;
 	tail->hw_options |= CPPI_EOP_SET;
 	tail->hw_options |= CPPI_EOP_SET;
 
 
-#ifdef CONFIG_USB_MUSB_DEBUG
-	if (_dbg_level(5)) {
-		struct cppi_descriptor	*d;
-
-		for (d = rx->head; d; d = d->next)
-			cppi_dump_rxbd("S", d);
-	}
-#endif
+	for (d = rx->head; d; d = d->next)
+		cppi_dump_rxbd("S", d);
 
 
 	/* in case the preceding transfer left some state... */
 	/* in case the preceding transfer left some state... */
 	tail = rx->last_processed;
 	tail = rx->last_processed;

+ 4 - 4
drivers/usb/musb/da8xx.c

@@ -198,7 +198,7 @@ static void otg_timer(unsigned long _musb)
 	 */
 	 */
 	devctl = musb_readb(mregs, MUSB_DEVCTL);
 	devctl = musb_readb(mregs, MUSB_DEVCTL);
 	dev_dbg(musb->controller, "Poll devctl %02x (%s)\n", devctl,
 	dev_dbg(musb->controller, "Poll devctl %02x (%s)\n", devctl,
-		otg_state_string(musb->xceiv->state));
+		usb_otg_state_string(musb->xceiv->state));
 
 
 	spin_lock_irqsave(&musb->lock, flags);
 	spin_lock_irqsave(&musb->lock, flags);
 	switch (musb->xceiv->state) {
 	switch (musb->xceiv->state) {
@@ -267,7 +267,7 @@ static void da8xx_musb_try_idle(struct musb *musb, unsigned long timeout)
 	if (musb->is_active || (musb->a_wait_bcon == 0 &&
 	if (musb->is_active || (musb->a_wait_bcon == 0 &&
 				musb->xceiv->state == OTG_STATE_A_WAIT_BCON)) {
 				musb->xceiv->state == OTG_STATE_A_WAIT_BCON)) {
 		dev_dbg(musb->controller, "%s active, deleting timer\n",
 		dev_dbg(musb->controller, "%s active, deleting timer\n",
-			otg_state_string(musb->xceiv->state));
+			usb_otg_state_string(musb->xceiv->state));
 		del_timer(&otg_workaround);
 		del_timer(&otg_workaround);
 		last_timer = jiffies;
 		last_timer = jiffies;
 		return;
 		return;
@@ -280,7 +280,7 @@ static void da8xx_musb_try_idle(struct musb *musb, unsigned long timeout)
 	last_timer = timeout;
 	last_timer = timeout;
 
 
 	dev_dbg(musb->controller, "%s inactive, starting idle timer for %u ms\n",
 	dev_dbg(musb->controller, "%s inactive, starting idle timer for %u ms\n",
-		otg_state_string(musb->xceiv->state),
+		usb_otg_state_string(musb->xceiv->state),
 		jiffies_to_msecs(timeout - jiffies));
 		jiffies_to_msecs(timeout - jiffies));
 	mod_timer(&otg_workaround, timeout);
 	mod_timer(&otg_workaround, timeout);
 }
 }
@@ -360,7 +360,7 @@ static irqreturn_t da8xx_musb_interrupt(int irq, void *hci)
 
 
 		dev_dbg(musb->controller, "VBUS %s (%s)%s, devctl %02x\n",
 		dev_dbg(musb->controller, "VBUS %s (%s)%s, devctl %02x\n",
 				drvvbus ? "on" : "off",
 				drvvbus ? "on" : "off",
-				otg_state_string(musb->xceiv->state),
+				usb_otg_state_string(musb->xceiv->state),
 				err ? " ERROR" : "",
 				err ? " ERROR" : "",
 				devctl);
 				devctl);
 		ret = IRQ_HANDLED;
 		ret = IRQ_HANDLED;

+ 2 - 2
drivers/usb/musb/davinci.c

@@ -215,7 +215,7 @@ static void otg_timer(unsigned long _musb)
 	 */
 	 */
 	devctl = musb_readb(mregs, MUSB_DEVCTL);
 	devctl = musb_readb(mregs, MUSB_DEVCTL);
 	dev_dbg(musb->controller, "poll devctl %02x (%s)\n", devctl,
 	dev_dbg(musb->controller, "poll devctl %02x (%s)\n", devctl,
-		otg_state_string(musb->xceiv->state));
+		usb_otg_state_string(musb->xceiv->state));
 
 
 	spin_lock_irqsave(&musb->lock, flags);
 	spin_lock_irqsave(&musb->lock, flags);
 	switch (musb->xceiv->state) {
 	switch (musb->xceiv->state) {
@@ -349,7 +349,7 @@ static irqreturn_t davinci_musb_interrupt(int irq, void *__hci)
 		davinci_musb_source_power(musb, drvvbus, 0);
 		davinci_musb_source_power(musb, drvvbus, 0);
 		dev_dbg(musb->controller, "VBUS %s (%s)%s, devctl %02x\n",
 		dev_dbg(musb->controller, "VBUS %s (%s)%s, devctl %02x\n",
 				drvvbus ? "on" : "off",
 				drvvbus ? "on" : "off",
-				otg_state_string(musb->xceiv->state),
+				usb_otg_state_string(musb->xceiv->state),
 				err ? " ERROR" : "",
 				err ? " ERROR" : "",
 				devctl);
 				devctl);
 		retval = IRQ_HANDLED;
 		retval = IRQ_HANDLED;

+ 33 - 38
drivers/usb/musb/musb_core.c

@@ -372,13 +372,13 @@ static void musb_otg_timer_func(unsigned long data)
 	case OTG_STATE_A_SUSPEND:
 	case OTG_STATE_A_SUSPEND:
 	case OTG_STATE_A_WAIT_BCON:
 	case OTG_STATE_A_WAIT_BCON:
 		dev_dbg(musb->controller, "HNP: %s timeout\n",
 		dev_dbg(musb->controller, "HNP: %s timeout\n",
-			otg_state_string(musb->xceiv->state));
+			usb_otg_state_string(musb->xceiv->state));
 		musb_platform_set_vbus(musb, 0);
 		musb_platform_set_vbus(musb, 0);
 		musb->xceiv->state = OTG_STATE_A_WAIT_VFALL;
 		musb->xceiv->state = OTG_STATE_A_WAIT_VFALL;
 		break;
 		break;
 	default:
 	default:
 		dev_dbg(musb->controller, "HNP: Unhandled mode %s\n",
 		dev_dbg(musb->controller, "HNP: Unhandled mode %s\n",
-			otg_state_string(musb->xceiv->state));
+			usb_otg_state_string(musb->xceiv->state));
 	}
 	}
 	musb->ignore_disconnect = 0;
 	musb->ignore_disconnect = 0;
 	spin_unlock_irqrestore(&musb->lock, flags);
 	spin_unlock_irqrestore(&musb->lock, flags);
@@ -393,13 +393,14 @@ void musb_hnp_stop(struct musb *musb)
 	void __iomem	*mbase = musb->mregs;
 	void __iomem	*mbase = musb->mregs;
 	u8	reg;
 	u8	reg;
 
 
-	dev_dbg(musb->controller, "HNP: stop from %s\n", otg_state_string(musb->xceiv->state));
+	dev_dbg(musb->controller, "HNP: stop from %s\n",
+			usb_otg_state_string(musb->xceiv->state));
 
 
 	switch (musb->xceiv->state) {
 	switch (musb->xceiv->state) {
 	case OTG_STATE_A_PERIPHERAL:
 	case OTG_STATE_A_PERIPHERAL:
 		musb_g_disconnect(musb);
 		musb_g_disconnect(musb);
 		dev_dbg(musb->controller, "HNP: back to %s\n",
 		dev_dbg(musb->controller, "HNP: back to %s\n",
-			otg_state_string(musb->xceiv->state));
+			usb_otg_state_string(musb->xceiv->state));
 		break;
 		break;
 	case OTG_STATE_B_HOST:
 	case OTG_STATE_B_HOST:
 		dev_dbg(musb->controller, "HNP: Disabling HR\n");
 		dev_dbg(musb->controller, "HNP: Disabling HR\n");
@@ -413,7 +414,7 @@ void musb_hnp_stop(struct musb *musb)
 		break;
 		break;
 	default:
 	default:
 		dev_dbg(musb->controller, "HNP: Stopping in unknown state %s\n",
 		dev_dbg(musb->controller, "HNP: Stopping in unknown state %s\n",
-			otg_state_string(musb->xceiv->state));
+			usb_otg_state_string(musb->xceiv->state));
 	}
 	}
 
 
 	/*
 	/*
@@ -451,7 +452,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
 	 */
 	 */
 	if (int_usb & MUSB_INTR_RESUME) {
 	if (int_usb & MUSB_INTR_RESUME) {
 		handled = IRQ_HANDLED;
 		handled = IRQ_HANDLED;
-		dev_dbg(musb->controller, "RESUME (%s)\n", otg_state_string(musb->xceiv->state));
+		dev_dbg(musb->controller, "RESUME (%s)\n", usb_otg_state_string(musb->xceiv->state));
 
 
 		if (devctl & MUSB_DEVCTL_HM) {
 		if (devctl & MUSB_DEVCTL_HM) {
 			void __iomem *mbase = musb->mregs;
 			void __iomem *mbase = musb->mregs;
@@ -493,7 +494,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
 			default:
 			default:
 				WARNING("bogus %s RESUME (%s)\n",
 				WARNING("bogus %s RESUME (%s)\n",
 					"host",
 					"host",
-					otg_state_string(musb->xceiv->state));
+					usb_otg_state_string(musb->xceiv->state));
 			}
 			}
 		} else {
 		} else {
 			switch (musb->xceiv->state) {
 			switch (musb->xceiv->state) {
@@ -522,7 +523,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
 			default:
 			default:
 				WARNING("bogus %s RESUME (%s)\n",
 				WARNING("bogus %s RESUME (%s)\n",
 					"peripheral",
 					"peripheral",
-					otg_state_string(musb->xceiv->state));
+					usb_otg_state_string(musb->xceiv->state));
 			}
 			}
 		}
 		}
 	}
 	}
@@ -538,7 +539,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
 		}
 		}
 
 
 		dev_dbg(musb->controller, "SESSION_REQUEST (%s)\n",
 		dev_dbg(musb->controller, "SESSION_REQUEST (%s)\n",
-			otg_state_string(musb->xceiv->state));
+			usb_otg_state_string(musb->xceiv->state));
 
 
 		/* IRQ arrives from ID pin sense or (later, if VBUS power
 		/* IRQ arrives from ID pin sense or (later, if VBUS power
 		 * is removed) SRP.  responses are time critical:
 		 * is removed) SRP.  responses are time critical:
@@ -602,8 +603,9 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
 			break;
 			break;
 		}
 		}
 
 
-		dev_dbg(musb->controller, "VBUS_ERROR in %s (%02x, %s), retry #%d, port1 %08x\n",
-				otg_state_string(musb->xceiv->state),
+		dev_printk(ignore ? KERN_DEBUG : KERN_ERR, musb->controller,
+				"VBUS_ERROR in %s (%02x, %s), retry #%d, port1 %08x\n",
+				usb_otg_state_string(musb->xceiv->state),
 				devctl,
 				devctl,
 				({ char *s;
 				({ char *s;
 				switch (devctl & MUSB_DEVCTL_VBUS) {
 				switch (devctl & MUSB_DEVCTL_VBUS) {
@@ -628,7 +630,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
 
 
 	if (int_usb & MUSB_INTR_SUSPEND) {
 	if (int_usb & MUSB_INTR_SUSPEND) {
 		dev_dbg(musb->controller, "SUSPEND (%s) devctl %02x\n",
 		dev_dbg(musb->controller, "SUSPEND (%s) devctl %02x\n",
-			otg_state_string(musb->xceiv->state), devctl);
+			usb_otg_state_string(musb->xceiv->state), devctl);
 		handled = IRQ_HANDLED;
 		handled = IRQ_HANDLED;
 
 
 		switch (musb->xceiv->state) {
 		switch (musb->xceiv->state) {
@@ -745,12 +747,12 @@ b_host:
 			usb_hcd_resume_root_hub(hcd);
 			usb_hcd_resume_root_hub(hcd);
 
 
 		dev_dbg(musb->controller, "CONNECT (%s) devctl %02x\n",
 		dev_dbg(musb->controller, "CONNECT (%s) devctl %02x\n",
-				otg_state_string(musb->xceiv->state), devctl);
+				usb_otg_state_string(musb->xceiv->state), devctl);
 	}
 	}
 
 
 	if ((int_usb & MUSB_INTR_DISCONNECT) && !musb->ignore_disconnect) {
 	if ((int_usb & MUSB_INTR_DISCONNECT) && !musb->ignore_disconnect) {
 		dev_dbg(musb->controller, "DISCONNECT (%s) as %s, devctl %02x\n",
 		dev_dbg(musb->controller, "DISCONNECT (%s) as %s, devctl %02x\n",
-				otg_state_string(musb->xceiv->state),
+				usb_otg_state_string(musb->xceiv->state),
 				MUSB_MODE(musb), devctl);
 				MUSB_MODE(musb), devctl);
 		handled = IRQ_HANDLED;
 		handled = IRQ_HANDLED;
 
 
@@ -787,7 +789,7 @@ b_host:
 			break;
 			break;
 		default:
 		default:
 			WARNING("unhandled DISCONNECT transition (%s)\n",
 			WARNING("unhandled DISCONNECT transition (%s)\n",
-				otg_state_string(musb->xceiv->state));
+				usb_otg_state_string(musb->xceiv->state));
 			break;
 			break;
 		}
 		}
 	}
 	}
@@ -813,7 +815,7 @@ b_host:
 			}
 			}
 		} else {
 		} else {
 			dev_dbg(musb->controller, "BUS RESET as %s\n",
 			dev_dbg(musb->controller, "BUS RESET as %s\n",
-				otg_state_string(musb->xceiv->state));
+				usb_otg_state_string(musb->xceiv->state));
 			switch (musb->xceiv->state) {
 			switch (musb->xceiv->state) {
 			case OTG_STATE_A_SUSPEND:
 			case OTG_STATE_A_SUSPEND:
 				/* We need to ignore disconnect on suspend
 				/* We need to ignore disconnect on suspend
@@ -826,7 +828,7 @@ b_host:
 			case OTG_STATE_A_WAIT_BCON:	/* OPT TD.4.7-900ms */
 			case OTG_STATE_A_WAIT_BCON:	/* OPT TD.4.7-900ms */
 				/* never use invalid T(a_wait_bcon) */
 				/* never use invalid T(a_wait_bcon) */
 				dev_dbg(musb->controller, "HNP: in %s, %d msec timeout\n",
 				dev_dbg(musb->controller, "HNP: in %s, %d msec timeout\n",
-					otg_state_string(musb->xceiv->state),
+					usb_otg_state_string(musb->xceiv->state),
 					TA_WAIT_BCON(musb));
 					TA_WAIT_BCON(musb));
 				mod_timer(&musb->otg_timer, jiffies
 				mod_timer(&musb->otg_timer, jiffies
 					+ msecs_to_jiffies(TA_WAIT_BCON(musb)));
 					+ msecs_to_jiffies(TA_WAIT_BCON(musb)));
@@ -838,7 +840,7 @@ b_host:
 				break;
 				break;
 			case OTG_STATE_B_WAIT_ACON:
 			case OTG_STATE_B_WAIT_ACON:
 				dev_dbg(musb->controller, "HNP: RESET (%s), to b_peripheral\n",
 				dev_dbg(musb->controller, "HNP: RESET (%s), to b_peripheral\n",
-					otg_state_string(musb->xceiv->state));
+					usb_otg_state_string(musb->xceiv->state));
 				musb->xceiv->state = OTG_STATE_B_PERIPHERAL;
 				musb->xceiv->state = OTG_STATE_B_PERIPHERAL;
 				musb_g_reset(musb);
 				musb_g_reset(musb);
 				break;
 				break;
@@ -850,7 +852,7 @@ b_host:
 				break;
 				break;
 			default:
 			default:
 				dev_dbg(musb->controller, "Unhandled BUS RESET as %s\n",
 				dev_dbg(musb->controller, "Unhandled BUS RESET as %s\n",
-					otg_state_string(musb->xceiv->state));
+					usb_otg_state_string(musb->xceiv->state));
 			}
 			}
 		}
 		}
 	}
 	}
@@ -1632,7 +1634,7 @@ musb_mode_show(struct device *dev, struct device_attribute *attr, char *buf)
 	int ret = -EINVAL;
 	int ret = -EINVAL;
 
 
 	spin_lock_irqsave(&musb->lock, flags);
 	spin_lock_irqsave(&musb->lock, flags);
-	ret = sprintf(buf, "%s\n", otg_state_string(musb->xceiv->state));
+	ret = sprintf(buf, "%s\n", usb_otg_state_string(musb->xceiv->state));
 	spin_unlock_irqrestore(&musb->lock, flags);
 	spin_unlock_irqrestore(&musb->lock, flags);
 
 
 	return ret;
 	return ret;
@@ -1951,9 +1953,13 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
 		musb_write_ulpi_buscontrol(musb->mregs, busctl);
 		musb_write_ulpi_buscontrol(musb->mregs, busctl);
 	}
 	}
 
 
-	MUSB_DEV_MODE(musb);
-	musb->xceiv->otg->default_a = 0;
-	musb->xceiv->state = OTG_STATE_B_IDLE;
+	if (musb->xceiv->otg->default_a) {
+		MUSB_HST_MODE(musb);
+		musb->xceiv->state = OTG_STATE_A_IDLE;
+	} else {
+		MUSB_DEV_MODE(musb);
+		musb->xceiv->state = OTG_STATE_B_IDLE;
+	}
 
 
 	status = musb_gadget_setup(musb);
 	status = musb_gadget_setup(musb);
 
 
@@ -2008,7 +2014,6 @@ static int musb_probe(struct platform_device *pdev)
 {
 {
 	struct device	*dev = &pdev->dev;
 	struct device	*dev = &pdev->dev;
 	int		irq = platform_get_irq_byname(pdev, "mc");
 	int		irq = platform_get_irq_byname(pdev, "mc");
-	int		status;
 	struct resource	*iomem;
 	struct resource	*iomem;
 	void __iomem	*base;
 	void __iomem	*base;
 
 
@@ -2016,24 +2021,17 @@ static int musb_probe(struct platform_device *pdev)
 	if (!iomem || irq <= 0)
 	if (!iomem || irq <= 0)
 		return -ENODEV;
 		return -ENODEV;
 
 
-	base = ioremap(iomem->start, resource_size(iomem));
-	if (!base) {
-		dev_err(dev, "ioremap failed\n");
-		return -ENOMEM;
-	}
+	base = devm_ioremap_resource(dev, iomem);
+	if (IS_ERR(base))
+		return PTR_ERR(base);
 
 
-	status = musb_init_controller(dev, irq, base);
-	if (status < 0)
-		iounmap(base);
-
-	return status;
+	return musb_init_controller(dev, irq, base);
 }
 }
 
 
 static int musb_remove(struct platform_device *pdev)
 static int musb_remove(struct platform_device *pdev)
 {
 {
 	struct device	*dev = &pdev->dev;
 	struct device	*dev = &pdev->dev;
 	struct musb	*musb = dev_to_musb(dev);
 	struct musb	*musb = dev_to_musb(dev);
-	void __iomem	*ctrl_base = musb->ctrl_base;
 
 
 	/* this gets called on rmmod.
 	/* this gets called on rmmod.
 	 *  - Host mode: host may still be active
 	 *  - Host mode: host may still be active
@@ -2044,7 +2042,6 @@ static int musb_remove(struct platform_device *pdev)
 	musb_shutdown(pdev);
 	musb_shutdown(pdev);
 
 
 	musb_free(musb);
 	musb_free(musb);
-	iounmap(ctrl_base);
 	device_init_wakeup(dev, 0);
 	device_init_wakeup(dev, 0);
 #ifndef CONFIG_MUSB_PIO_ONLY
 #ifndef CONFIG_MUSB_PIO_ONLY
 	dma_set_mask(dev, *dev->parent->dma_mask);
 	dma_set_mask(dev, *dev->parent->dma_mask);
@@ -2293,8 +2290,6 @@ static int __init musb_init(void)
 	if (usb_disabled())
 	if (usb_disabled())
 		return 0;
 		return 0;
 
 
-	pr_info("%s: version " MUSB_VERSION ", ?dma?, otg (peripheral+host)\n",
-		musb_driver_name);
 	return platform_driver_register(&musb_driver);
 	return platform_driver_register(&musb_driver);
 }
 }
 module_init(musb_init);
 module_init(musb_init);

+ 7 - 7
drivers/usb/musb/musb_dsps.c

@@ -38,6 +38,7 @@
 #include <linux/module.h>
 #include <linux/module.h>
 #include <linux/usb/nop-usb-xceiv.h>
 #include <linux/usb/nop-usb-xceiv.h>
 #include <linux/platform_data/usb-omap.h>
 #include <linux/platform_data/usb-omap.h>
+#include <linux/sizes.h>
 
 
 #include <linux/of.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
 #include <linux/of_device.h>
@@ -224,7 +225,7 @@ static void otg_timer(unsigned long _musb)
 	 */
 	 */
 	devctl = dsps_readb(mregs, MUSB_DEVCTL);
 	devctl = dsps_readb(mregs, MUSB_DEVCTL);
 	dev_dbg(musb->controller, "Poll devctl %02x (%s)\n", devctl,
 	dev_dbg(musb->controller, "Poll devctl %02x (%s)\n", devctl,
-				otg_state_string(musb->xceiv->state));
+				usb_otg_state_string(musb->xceiv->state));
 
 
 	spin_lock_irqsave(&musb->lock, flags);
 	spin_lock_irqsave(&musb->lock, flags);
 	switch (musb->xceiv->state) {
 	switch (musb->xceiv->state) {
@@ -273,7 +274,7 @@ static void dsps_musb_try_idle(struct musb *musb, unsigned long timeout)
 	if (musb->is_active || (musb->a_wait_bcon == 0 &&
 	if (musb->is_active || (musb->a_wait_bcon == 0 &&
 				musb->xceiv->state == OTG_STATE_A_WAIT_BCON)) {
 				musb->xceiv->state == OTG_STATE_A_WAIT_BCON)) {
 		dev_dbg(musb->controller, "%s active, deleting timer\n",
 		dev_dbg(musb->controller, "%s active, deleting timer\n",
-				otg_state_string(musb->xceiv->state));
+				usb_otg_state_string(musb->xceiv->state));
 		del_timer(&glue->timer[pdev->id]);
 		del_timer(&glue->timer[pdev->id]);
 		glue->last_timer[pdev->id] = jiffies;
 		glue->last_timer[pdev->id] = jiffies;
 		return;
 		return;
@@ -288,7 +289,7 @@ static void dsps_musb_try_idle(struct musb *musb, unsigned long timeout)
 	glue->last_timer[pdev->id] = timeout;
 	glue->last_timer[pdev->id] = timeout;
 
 
 	dev_dbg(musb->controller, "%s inactive, starting idle timer for %u ms\n",
 	dev_dbg(musb->controller, "%s inactive, starting idle timer for %u ms\n",
-		otg_state_string(musb->xceiv->state),
+		usb_otg_state_string(musb->xceiv->state),
 			jiffies_to_msecs(timeout - jiffies));
 			jiffies_to_msecs(timeout - jiffies));
 	mod_timer(&glue->timer[pdev->id], timeout);
 	mod_timer(&glue->timer[pdev->id], timeout);
 }
 }
@@ -334,7 +335,7 @@ static irqreturn_t dsps_interrupt(int irq, void *hci)
 	 * value but DEVCTL.BDEVICE is invalid without DEVCTL.SESSION set.
 	 * value but DEVCTL.BDEVICE is invalid without DEVCTL.SESSION set.
 	 * Also, DRVVBUS pulses for SRP (but not at 5V) ...
 	 * Also, DRVVBUS pulses for SRP (but not at 5V) ...
 	 */
 	 */
-	if (usbintr & MUSB_INTR_BABBLE)
+	if (is_host_active(musb) && usbintr & MUSB_INTR_BABBLE)
 		pr_info("CAUTION: musb: Babble Interrupt Occurred\n");
 		pr_info("CAUTION: musb: Babble Interrupt Occurred\n");
 
 
 	if (usbintr & ((1 << wrp->drvvbus) << wrp->usb_shift)) {
 	if (usbintr & ((1 << wrp->drvvbus) << wrp->usb_shift)) {
@@ -377,7 +378,7 @@ static irqreturn_t dsps_interrupt(int irq, void *hci)
 		/* NOTE: this must complete power-on within 100 ms. */
 		/* NOTE: this must complete power-on within 100 ms. */
 		dev_dbg(musb->controller, "VBUS %s (%s)%s, devctl %02x\n",
 		dev_dbg(musb->controller, "VBUS %s (%s)%s, devctl %02x\n",
 				drvvbus ? "on" : "off",
 				drvvbus ? "on" : "off",
-				otg_state_string(musb->xceiv->state),
+				usb_otg_state_string(musb->xceiv->state),
 				err ? " ERROR" : "",
 				err ? " ERROR" : "",
 				devctl);
 				devctl);
 		ret = IRQ_HANDLED;
 		ret = IRQ_HANDLED;
@@ -596,14 +597,13 @@ err0:
 
 
 static int dsps_probe(struct platform_device *pdev)
 static int dsps_probe(struct platform_device *pdev)
 {
 {
-	struct device_node *np = pdev->dev.of_node;
 	const struct of_device_id *match;
 	const struct of_device_id *match;
 	const struct dsps_musb_wrapper *wrp;
 	const struct dsps_musb_wrapper *wrp;
 	struct dsps_glue *glue;
 	struct dsps_glue *glue;
 	struct resource *iomem;
 	struct resource *iomem;
 	int ret, i;
 	int ret, i;
 
 
-	match = of_match_node(musb_dsps_of_match, np);
+	match = of_match_node(musb_dsps_of_match, pdev->dev.of_node);
 	if (!match) {
 	if (!match) {
 		dev_err(&pdev->dev, "fail to get matching of_match struct\n");
 		dev_err(&pdev->dev, "fail to get matching of_match struct\n");
 		ret = -EINVAL;
 		ret = -EINVAL;

+ 16 - 140
drivers/usb/musb/musb_gadget.c

@@ -46,48 +46,6 @@
 #include "musb_core.h"
 #include "musb_core.h"
 
 
 
 
-/* MUSB PERIPHERAL status 3-mar-2006:
- *
- * - EP0 seems solid.  It passes both USBCV and usbtest control cases.
- *   Minor glitches:
- *
- *     + remote wakeup to Linux hosts work, but saw USBCV failures;
- *       in one test run (operator error?)
- *     + endpoint halt tests -- in both usbtest and usbcv -- seem
- *       to break when dma is enabled ... is something wrongly
- *       clearing SENDSTALL?
- *
- * - Mass storage behaved ok when last tested.  Network traffic patterns
- *   (with lots of short transfers etc) need retesting; they turn up the
- *   worst cases of the DMA, since short packets are typical but are not
- *   required.
- *
- * - TX/IN
- *     + both pio and dma behave in with network and g_zero tests
- *     + no cppi throughput issues other than no-hw-queueing
- *     + failed with FLAT_REG (DaVinci)
- *     + seems to behave with double buffering, PIO -and- CPPI
- *     + with gadgetfs + AIO, requests got lost?
- *
- * - RX/OUT
- *     + both pio and dma behave in with network and g_zero tests
- *     + dma is slow in typical case (short_not_ok is clear)
- *     + double buffering ok with PIO
- *     + double buffering *FAILS* with CPPI, wrong data bytes sometimes
- *     + request lossage observed with gadgetfs
- *
- * - ISO not tested ... might work, but only weakly isochronous
- *
- * - Gadget driver disabling of softconnect during bind() is ignored; so
- *   drivers can't hold off host requests until userspace is ready.
- *   (Workaround:  they can turn it off later.)
- *
- * - PORTABILITY (assumes PIO works):
- *     + DaVinci, basically works with cppi dma
- *     + OMAP 2430, ditto with mentor dma
- *     + TUSB 6010, platform-specific dma in the works
- */
-
 /* ----------------------------------------------------------------------- */
 /* ----------------------------------------------------------------------- */
 
 
 #define is_buffer_mapped(req) (is_dma_capable() && \
 #define is_buffer_mapped(req) (is_dma_capable() && \
@@ -280,41 +238,6 @@ static inline int max_ep_writesize(struct musb *musb, struct musb_ep *ep)
 		return ep->packet_sz;
 		return ep->packet_sz;
 }
 }
 
 
-
-#ifdef CONFIG_USB_INVENTRA_DMA
-
-/* Peripheral tx (IN) using Mentor DMA works as follows:
-	Only mode 0 is used for transfers <= wPktSize,
-	mode 1 is used for larger transfers,
-
-	One of the following happens:
-	- Host sends IN token which causes an endpoint interrupt
-		-> TxAvail
-			-> if DMA is currently busy, exit.
-			-> if queue is non-empty, txstate().
-
-	- Request is queued by the gadget driver.
-		-> if queue was previously empty, txstate()
-
-	txstate()
-		-> start
-		  /\	-> setup DMA
-		  |     (data is transferred to the FIFO, then sent out when
-		  |	IN token(s) are recd from Host.
-		  |		-> DMA interrupt on completion
-		  |		   calls TxAvail.
-		  |		      -> stop DMA, ~DMAENAB,
-		  |		      -> set TxPktRdy for last short pkt or zlp
-		  |		      -> Complete Request
-		  |		      -> Continue next request (call txstate)
-		  |___________________________________|
-
- * Non-Mentor DMA engines can of course work differently, such as by
- * upleveling from irq-per-packet to irq-per-buffer.
- */
-
-#endif
-
 /*
 /*
  * An endpoint is transmitting data. This can be called either from
  * An endpoint is transmitting data. This can be called either from
  * the IRQ routine or from ep.queue() to kickstart a request on an
  * the IRQ routine or from ep.queue() to kickstart a request on an
@@ -621,37 +544,6 @@ void musb_g_tx(struct musb *musb, u8 epnum)
 
 
 /* ------------------------------------------------------------ */
 /* ------------------------------------------------------------ */
 
 
-#ifdef CONFIG_USB_INVENTRA_DMA
-
-/* Peripheral rx (OUT) using Mentor DMA works as follows:
-	- Only mode 0 is used.
-
-	- Request is queued by the gadget class driver.
-		-> if queue was previously empty, rxstate()
-
-	- Host sends OUT token which causes an endpoint interrupt
-	  /\      -> RxReady
-	  |	      -> if request queued, call rxstate
-	  |		/\	-> setup DMA
-	  |		|	     -> DMA interrupt on completion
-	  |		|		-> RxReady
-	  |		|		      -> stop DMA
-	  |		|		      -> ack the read
-	  |		|		      -> if data recd = max expected
-	  |		|				by the request, or host
-	  |		|				sent a short packet,
-	  |		|				complete the request,
-	  |		|				and start the next one.
-	  |		|_____________________________________|
-	  |					 else just wait for the host
-	  |					    to send the next OUT token.
-	  |__________________________________________________|
-
- * Non-Mentor DMA engines can of course work differently.
- */
-
-#endif
-
 /*
 /*
  * Context: controller locked, IRQs blocked, endpoint selected
  * Context: controller locked, IRQs blocked, endpoint selected
  */
  */
@@ -740,7 +632,7 @@ static void rxstate(struct musb *musb, struct musb_request *req)
 				struct dma_controller	*c;
 				struct dma_controller	*c;
 				struct dma_channel	*channel;
 				struct dma_channel	*channel;
 				int			use_dma = 0;
 				int			use_dma = 0;
-				int transfer_size;
+				unsigned int transfer_size;
 
 
 				c = musb->dma_controller;
 				c = musb->dma_controller;
 				channel = musb_ep->dma;
 				channel = musb_ep->dma;
@@ -782,10 +674,11 @@ static void rxstate(struct musb *musb, struct musb_request *req)
 						csr | MUSB_RXCSR_DMAMODE);
 						csr | MUSB_RXCSR_DMAMODE);
 					musb_writew(epio, MUSB_RXCSR, csr);
 					musb_writew(epio, MUSB_RXCSR, csr);
 
 
-					transfer_size = min(request->length - request->actual,
+					transfer_size = min_t(unsigned int,
+							request->length -
+							request->actual,
 							channel->max_len);
 							channel->max_len);
 					musb_ep->dma->desired_mode = 1;
 					musb_ep->dma->desired_mode = 1;
-
 				} else {
 				} else {
 					if (!musb_ep->hb_mult &&
 					if (!musb_ep->hb_mult &&
 						musb_ep->hw_ep->rx_double_buffered)
 						musb_ep->hw_ep->rx_double_buffered)
@@ -815,7 +708,7 @@ static void rxstate(struct musb *musb, struct musb_request *req)
 
 
 				struct dma_controller *c;
 				struct dma_controller *c;
 				struct dma_channel *channel;
 				struct dma_channel *channel;
-				int transfer_size = 0;
+				unsigned int transfer_size = 0;
 
 
 				c = musb->dma_controller;
 				c = musb->dma_controller;
 				channel = musb_ep->dma;
 				channel = musb_ep->dma;
@@ -824,11 +717,13 @@ static void rxstate(struct musb *musb, struct musb_request *req)
 				if (fifo_count < musb_ep->packet_sz)
 				if (fifo_count < musb_ep->packet_sz)
 					transfer_size = fifo_count;
 					transfer_size = fifo_count;
 				else if (request->short_not_ok)
 				else if (request->short_not_ok)
-					transfer_size =	min(request->length -
+					transfer_size =	min_t(unsigned int,
+							request->length -
 							request->actual,
 							request->actual,
 							channel->max_len);
 							channel->max_len);
 				else
 				else
-					transfer_size = min(request->length -
+					transfer_size = min_t(unsigned int,
+							request->length -
 							request->actual,
 							request->actual,
 							(unsigned)fifo_count);
 							(unsigned)fifo_count);
 
 
@@ -1681,7 +1576,7 @@ static int musb_gadget_wakeup(struct usb_gadget *gadget)
 		goto done;
 		goto done;
 	default:
 	default:
 		dev_dbg(musb->controller, "Unhandled wake: %s\n",
 		dev_dbg(musb->controller, "Unhandled wake: %s\n",
-			otg_state_string(musb->xceiv->state));
+			usb_otg_state_string(musb->xceiv->state));
 		goto done;
 		goto done;
 	}
 	}
 
 
@@ -1801,13 +1696,6 @@ static const struct usb_gadget_ops musb_gadget_operations = {
  * all peripheral ports are external...
  * all peripheral ports are external...
  */
  */
 
 
-static void musb_gadget_release(struct device *dev)
-{
-	/* kref_put(WHAT) */
-	dev_dbg(dev, "%s\n", __func__);
-}
-
-
 static void
 static void
 init_peripheral_ep(struct musb *musb, struct musb_ep *ep, u8 epnum, int is_in)
 init_peripheral_ep(struct musb *musb, struct musb_ep *ep, u8 epnum, int is_in)
 {
 {
@@ -1892,12 +1780,7 @@ int musb_gadget_setup(struct musb *musb)
 	musb->g.speed = USB_SPEED_UNKNOWN;
 	musb->g.speed = USB_SPEED_UNKNOWN;
 
 
 	/* this "gadget" abstracts/virtualizes the controller */
 	/* this "gadget" abstracts/virtualizes the controller */
-	dev_set_name(&musb->g.dev, "gadget");
-	musb->g.dev.parent = musb->controller;
-	musb->g.dev.dma_mask = musb->controller->dma_mask;
-	musb->g.dev.release = musb_gadget_release;
 	musb->g.name = musb_driver_name;
 	musb->g.name = musb_driver_name;
-
 	musb->g.is_otg = 1;
 	musb->g.is_otg = 1;
 
 
 	musb_g_init_endpoints(musb);
 	musb_g_init_endpoints(musb);
@@ -1905,11 +1788,6 @@ int musb_gadget_setup(struct musb *musb)
 	musb->is_active = 0;
 	musb->is_active = 0;
 	musb_platform_try_idle(musb, 0);
 	musb_platform_try_idle(musb, 0);
 
 
-	status = device_register(&musb->g.dev);
-	if (status != 0) {
-		put_device(&musb->g.dev);
-		return status;
-	}
 	status = usb_add_gadget_udc(musb->controller, &musb->g);
 	status = usb_add_gadget_udc(musb->controller, &musb->g);
 	if (status)
 	if (status)
 		goto err;
 		goto err;
@@ -1924,8 +1802,6 @@ err:
 void musb_gadget_cleanup(struct musb *musb)
 void musb_gadget_cleanup(struct musb *musb)
 {
 {
 	usb_del_gadget_udc(&musb->g);
 	usb_del_gadget_udc(&musb->g);
-	if (musb->g.dev.parent)
-		device_unregister(&musb->g.dev);
 }
 }
 
 
 /*
 /*
@@ -1977,9 +1853,8 @@ static int musb_gadget_start(struct usb_gadget *g,
 		goto err;
 		goto err;
 	}
 	}
 
 
-	if ((musb->xceiv->last_event == USB_EVENT_ID)
-				&& otg->set_vbus)
-		otg_set_vbus(otg, 1);
+	if (musb->xceiv->last_event == USB_EVENT_ID)
+		musb_platform_set_vbus(musb, 1);
 
 
 	hcd->self.uses_pio_for_control = 1;
 	hcd->self.uses_pio_for_control = 1;
 
 
@@ -2063,6 +1938,7 @@ static int musb_gadget_stop(struct usb_gadget *g,
 	dev_dbg(musb->controller, "unregistering driver %s\n", driver->function);
 	dev_dbg(musb->controller, "unregistering driver %s\n", driver->function);
 
 
 	musb->is_active = 0;
 	musb->is_active = 0;
+	musb->gadget_driver = NULL;
 	musb_platform_try_idle(musb, 0);
 	musb_platform_try_idle(musb, 0);
 	spin_unlock_irqrestore(&musb->lock, flags);
 	spin_unlock_irqrestore(&musb->lock, flags);
 
 
@@ -2099,7 +1975,7 @@ void musb_g_resume(struct musb *musb)
 		break;
 		break;
 	default:
 	default:
 		WARNING("unhandled RESUME transition (%s)\n",
 		WARNING("unhandled RESUME transition (%s)\n",
-				otg_state_string(musb->xceiv->state));
+				usb_otg_state_string(musb->xceiv->state));
 	}
 	}
 }
 }
 
 
@@ -2129,7 +2005,7 @@ void musb_g_suspend(struct musb *musb)
 		 * A_PERIPHERAL may need care too
 		 * A_PERIPHERAL may need care too
 		 */
 		 */
 		WARNING("unhandled SUSPEND transition (%s)\n",
 		WARNING("unhandled SUSPEND transition (%s)\n",
-				otg_state_string(musb->xceiv->state));
+				usb_otg_state_string(musb->xceiv->state));
 	}
 	}
 }
 }
 
 
@@ -2163,7 +2039,7 @@ void musb_g_disconnect(struct musb *musb)
 	switch (musb->xceiv->state) {
 	switch (musb->xceiv->state) {
 	default:
 	default:
 		dev_dbg(musb->controller, "Unhandled disconnect %s, setting a_idle\n",
 		dev_dbg(musb->controller, "Unhandled disconnect %s, setting a_idle\n",
-			otg_state_string(musb->xceiv->state));
+			usb_otg_state_string(musb->xceiv->state));
 		musb->xceiv->state = OTG_STATE_A_IDLE;
 		musb->xceiv->state = OTG_STATE_A_IDLE;
 		MUSB_HST_MODE(musb);
 		MUSB_HST_MODE(musb);
 		break;
 		break;

Энэ ялгаанд хэт олон файл өөрчлөгдсөн тул зарим файлыг харуулаагүй болно