浏览代码

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

Felipe writes:

usb: patches for v3.17 merge window

Surprisingly enough, while a big set of patches, the majority is
composed of cleanups (using devm_*, fixing sparse errors, moving
code around, adding const, etc).

The highlights are addition of new support for PLX USB338x devices,
and support for USB 2.0-only configurations of the DWC3 IP core.

Signed-of-by: Felipe Balbi <balbi@ti.com>
Greg Kroah-Hartman 11 年之前
父节点
当前提交
61fe2d75f1
共有 100 个文件被更改,包括 1932 次插入4588 次删除
  1. 5 5
      Documentation/DocBook/gadget.tmpl
  2. 32 19
      drivers/usb/dwc3/core.c
  3. 13 0
      drivers/usb/dwc3/core.h
  4. 86 86
      drivers/usb/dwc3/dwc3-omap.c
  5. 3 4
      drivers/usb/dwc3/gadget.c
  6. 2 822
      drivers/usb/gadget/Kconfig
  7. 4 97
      drivers/usb/gadget/Makefile
  8. 1 0
      drivers/usb/gadget/composite.c
  9. 1 3
      drivers/usb/gadget/configfs.c
  10. 34 0
      drivers/usb/gadget/function/Makefile
  11. 0 0
      drivers/usb/gadget/function/f_acm.c
  12. 0 0
      drivers/usb/gadget/function/f_ecm.c
  13. 10 12
      drivers/usb/gadget/function/f_eem.c
  14. 339 13
      drivers/usb/gadget/function/f_fs.c
  15. 0 0
      drivers/usb/gadget/function/f_hid.c
  16. 0 0
      drivers/usb/gadget/function/f_loopback.c
  17. 0 0
      drivers/usb/gadget/function/f_mass_storage.c
  18. 0 0
      drivers/usb/gadget/function/f_mass_storage.h
  19. 0 0
      drivers/usb/gadget/function/f_midi.c
  20. 332 148
      drivers/usb/gadget/function/f_ncm.c
  21. 0 0
      drivers/usb/gadget/function/f_obex.c
  22. 0 0
      drivers/usb/gadget/function/f_phonet.c
  23. 4 0
      drivers/usb/gadget/function/f_rndis.c
  24. 0 0
      drivers/usb/gadget/function/f_serial.c
  25. 0 0
      drivers/usb/gadget/function/f_sourcesink.c
  26. 0 0
      drivers/usb/gadget/function/f_subset.c
  27. 0 0
      drivers/usb/gadget/function/f_uac1.c
  28. 22 2
      drivers/usb/gadget/function/f_uac2.c
  29. 0 0
      drivers/usb/gadget/function/f_uvc.c
  30. 0 0
      drivers/usb/gadget/function/f_uvc.h
  31. 0 0
      drivers/usb/gadget/function/g_zero.h
  32. 0 0
      drivers/usb/gadget/function/ndis.h
  33. 0 0
      drivers/usb/gadget/function/rndis.c
  34. 0 0
      drivers/usb/gadget/function/rndis.h
  35. 0 0
      drivers/usb/gadget/function/storage_common.c
  36. 0 0
      drivers/usb/gadget/function/storage_common.h
  37. 0 0
      drivers/usb/gadget/function/u_ecm.h
  38. 0 0
      drivers/usb/gadget/function/u_eem.h
  39. 13 6
      drivers/usb/gadget/function/u_ether.c
  40. 2 0
      drivers/usb/gadget/function/u_ether.h
  41. 0 0
      drivers/usb/gadget/function/u_ether_configfs.h
  42. 7 0
      drivers/usb/gadget/function/u_fs.h
  43. 0 0
      drivers/usb/gadget/function/u_gether.h
  44. 0 0
      drivers/usb/gadget/function/u_ncm.h
  45. 0 0
      drivers/usb/gadget/function/u_phonet.h
  46. 0 0
      drivers/usb/gadget/function/u_rndis.h
  47. 0 0
      drivers/usb/gadget/function/u_serial.c
  48. 0 0
      drivers/usb/gadget/function/u_serial.h
  49. 0 0
      drivers/usb/gadget/function/u_uac1.c
  50. 0 0
      drivers/usb/gadget/function/u_uac1.h
  51. 0 0
      drivers/usb/gadget/function/uvc.h
  52. 0 0
      drivers/usb/gadget/function/uvc_queue.c
  53. 0 0
      drivers/usb/gadget/function/uvc_queue.h
  54. 0 0
      drivers/usb/gadget/function/uvc_v4l2.c
  55. 0 0
      drivers/usb/gadget/function/uvc_video.c
  56. 475 0
      drivers/usb/gadget/legacy/Kconfig
  57. 44 0
      drivers/usb/gadget/legacy/Makefile
  58. 2 12
      drivers/usb/gadget/legacy/acm_ms.c
  59. 1 11
      drivers/usb/gadget/legacy/audio.c
  60. 2 12
      drivers/usb/gadget/legacy/cdc2.c
  61. 0 0
      drivers/usb/gadget/legacy/dbgp.c
  62. 2 12
      drivers/usb/gadget/legacy/ether.c
  63. 1 1
      drivers/usb/gadget/legacy/g_ffs.c
  64. 1 12
      drivers/usb/gadget/legacy/gmidi.c
  65. 0 0
      drivers/usb/gadget/legacy/hid.c
  66. 0 0
      drivers/usb/gadget/legacy/inode.c
  67. 0 0
      drivers/usb/gadget/legacy/mass_storage.c
  68. 1 12
      drivers/usb/gadget/legacy/multi.c
  69. 2 12
      drivers/usb/gadget/legacy/ncm.c
  70. 1 11
      drivers/usb/gadget/legacy/nokia.c
  71. 0 0
      drivers/usb/gadget/legacy/printer.c
  72. 0 0
      drivers/usb/gadget/legacy/serial.c
  73. 0 0
      drivers/usb/gadget/legacy/tcm_usb_gadget.c
  74. 0 0
      drivers/usb/gadget/legacy/tcm_usb_gadget.h
  75. 1 14
      drivers/usb/gadget/legacy/webcam.c
  76. 2 12
      drivers/usb/gadget/legacy/zero.c
  77. 0 2905
      drivers/usb/gadget/net2280.c
  78. 0 308
      drivers/usb/gadget/net2280.h
  79. 46 13
      drivers/usb/gadget/u_os_desc.h
  80. 385 0
      drivers/usb/gadget/udc/Kconfig
  81. 31 0
      drivers/usb/gadget/udc/Makefile
  82. 0 0
      drivers/usb/gadget/udc/amd5536udc.c
  83. 0 0
      drivers/usb/gadget/udc/amd5536udc.h
  84. 0 0
      drivers/usb/gadget/udc/at91_udc.c
  85. 0 0
      drivers/usb/gadget/udc/at91_udc.h
  86. 1 1
      drivers/usb/gadget/udc/atmel_usba_udc.c
  87. 0 0
      drivers/usb/gadget/udc/atmel_usba_udc.h
  88. 0 0
      drivers/usb/gadget/udc/bcm63xx_udc.c
  89. 0 0
      drivers/usb/gadget/udc/dummy_hcd.c
  90. 0 0
      drivers/usb/gadget/udc/fotg210-udc.c
  91. 0 0
      drivers/usb/gadget/udc/fotg210.h
  92. 2 0
      drivers/usb/gadget/udc/fsl_mxc_udc.c
  93. 7 12
      drivers/usb/gadget/udc/fsl_qe_udc.c
  94. 0 0
      drivers/usb/gadget/udc/fsl_qe_udc.h
  95. 11 8
      drivers/usb/gadget/udc/fsl_udc_core.c
  96. 3 0
      drivers/usb/gadget/udc/fsl_usb2_udc.h
  97. 1 3
      drivers/usb/gadget/udc/fusb300_udc.c
  98. 0 0
      drivers/usb/gadget/udc/fusb300_udc.h
  99. 0 0
      drivers/usb/gadget/udc/gadget_chips.h
  100. 0 0
      drivers/usb/gadget/udc/goku_udc.c

+ 5 - 5
Documentation/DocBook/gadget.tmpl

@@ -556,11 +556,11 @@ been converted to this framework.
 Near-term plans include converting all of them, except for "gadgetfs".
 </para>
 
-!Edrivers/usb/gadget/f_acm.c
-!Edrivers/usb/gadget/f_ecm.c
-!Edrivers/usb/gadget/f_subset.c
-!Edrivers/usb/gadget/f_obex.c
-!Edrivers/usb/gadget/f_serial.c
+!Edrivers/usb/gadget/function/f_acm.c
+!Edrivers/usb/gadget/function/f_ecm.c
+!Edrivers/usb/gadget/function/f_subset.c
+!Edrivers/usb/gadget/function/f_obex.c
+!Edrivers/usb/gadget/function/f_serial.c
 
 </sect1>
 

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

@@ -386,6 +386,13 @@ static int dwc3_core_init(struct dwc3 *dwc)
 	}
 	dwc->revision = reg;
 
+	/* Handle USB2.0-only core configuration */
+	if (DWC3_GHWPARAMS3_SSPHY_IFC(dwc->hwparams.hwparams3) ==
+			DWC3_GHWPARAMS3_SSPHY_IFC_DIS) {
+		if (dwc->maximum_speed == USB_SPEED_SUPER)
+			dwc->maximum_speed = USB_SPEED_HIGH;
+	}
+
 	/* issue device SoftReset too */
 	timeout = jiffies + msecs_to_jiffies(500);
 	dwc3_writel(dwc->regs, DWC3_DCTL, DWC3_DCTL_CSFTRST);
@@ -656,6 +663,31 @@ static int dwc3_probe(struct platform_device *pdev)
 		return -ENODEV;
 	}
 
+	dwc->xhci_resources[0].start = res->start;
+	dwc->xhci_resources[0].end = dwc->xhci_resources[0].start +
+					DWC3_XHCI_REGS_END;
+	dwc->xhci_resources[0].flags = res->flags;
+	dwc->xhci_resources[0].name = res->name;
+
+	res->start += DWC3_GLOBALS_REGS_START;
+
+	/*
+	 * Request memory region but exclude xHCI regs,
+	 * since it will be requested by the xhci-plat driver.
+	 */
+	regs = devm_ioremap_resource(dev, res);
+	if (IS_ERR(regs))
+		return PTR_ERR(regs);
+
+	dwc->regs	= regs;
+	dwc->regs_size	= resource_size(res);
+	/*
+	 * restore res->start back to its original value so that,
+	 * in case the probe is deferred, we don't end up getting error in
+	 * request the memory region the next time probe is called.
+	 */
+	res->start -= DWC3_GLOBALS_REGS_START;
+
 	if (node) {
 		dwc->maximum_speed = of_usb_get_maximum_speed(node);
 
@@ -676,28 +708,9 @@ static int dwc3_probe(struct platform_device *pdev)
 	if (ret)
 		return ret;
 
-	dwc->xhci_resources[0].start = res->start;
-	dwc->xhci_resources[0].end = dwc->xhci_resources[0].start +
-					DWC3_XHCI_REGS_END;
-	dwc->xhci_resources[0].flags = res->flags;
-	dwc->xhci_resources[0].name = res->name;
-
-	res->start += DWC3_GLOBALS_REGS_START;
-
-	/*
-	 * Request memory region but exclude xHCI regs,
-	 * since it will be requested by the xhci-plat driver.
-	 */
-	regs = devm_ioremap_resource(dev, res);
-	if (IS_ERR(regs))
-		return PTR_ERR(regs);
-
 	spin_lock_init(&dwc->lock);
 	platform_set_drvdata(pdev, dwc);
 
-	dwc->regs	= regs;
-	dwc->regs_size	= resource_size(res);
-
 	dev->dma_mask	= dev->parent->dma_mask;
 	dev->dma_parms	= dev->parent->dma_parms;
 	dma_set_coherent_mask(dev, dev->parent->coherent_dma_mask);

+ 13 - 0
drivers/usb/dwc3/core.h

@@ -191,6 +191,19 @@
 #define DWC3_GHWPARAMS1_PWROPT(n)	((n) << 24)
 #define DWC3_GHWPARAMS1_PWROPT_MASK	DWC3_GHWPARAMS1_PWROPT(3)
 
+/* Global HWPARAMS3 Register */
+#define DWC3_GHWPARAMS3_SSPHY_IFC(n)		((n) & 3)
+#define DWC3_GHWPARAMS3_SSPHY_IFC_DIS		0
+#define DWC3_GHWPARAMS3_SSPHY_IFC_ENA		1
+#define DWC3_GHWPARAMS3_HSPHY_IFC(n)		(((n) & (3 << 2)) >> 2)
+#define DWC3_GHWPARAMS3_HSPHY_IFC_DIS		0
+#define DWC3_GHWPARAMS3_HSPHY_IFC_UTMI		1
+#define DWC3_GHWPARAMS3_HSPHY_IFC_ULPI		2
+#define DWC3_GHWPARAMS3_HSPHY_IFC_UTMI_ULPI	3
+#define DWC3_GHWPARAMS3_FSPHY_IFC(n)		(((n) & (3 << 4)) >> 4)
+#define DWC3_GHWPARAMS3_FSPHY_IFC_DIS		0
+#define DWC3_GHWPARAMS3_FSPHY_IFC_ENA		1
+
 /* Global HWPARAMS4 Register */
 #define DWC3_GHWPARAMS4_HIBER_SCRATCHBUFS(n)	(((n) & (0x0f << 13)) >> 13)
 #define DWC3_MAX_HIBER_SCRATCHBUFS		15

+ 86 - 86
drivers/usb/dwc3/dwc3-omap.c

@@ -77,10 +77,6 @@
 #define USBOTGSS_DEV_EBC_EN			0x0110
 #define USBOTGSS_DEBUG_OFFSET			0x0600
 
-/* REVISION REGISTER */
-#define USBOTGSS_REVISION_XMAJOR(reg)		((reg >> 8) & 0x7)
-#define USBOTGSS_REVISION_XMAJOR1		1
-#define USBOTGSS_REVISION_XMAJOR2		2
 /* SYSCONFIG REGISTER */
 #define USBOTGSS_SYSCONFIG_DMADISABLE		(1 << 16)
 
@@ -129,7 +125,6 @@ struct dwc3_omap {
 	u32			irq_eoi_offset;
 	u32			debug_offset;
 	u32			irq0_offset;
-	u32			revision;
 
 	u32			dma_status:1;
 
@@ -383,6 +378,87 @@ static int dwc3_omap_vbus_notifier(struct notifier_block *nb,
 	return NOTIFY_DONE;
 }
 
+static void dwc3_omap_map_offset(struct dwc3_omap *omap)
+{
+	struct device_node	*node = omap->dev->of_node;
+
+	/*
+	 * Differentiate between OMAP5 and AM437x.
+	 *
+	 * For OMAP5(ES2.0) and AM437x wrapper revision is same, even
+	 * though there are changes in wrapper register offsets.
+	 *
+	 * Using dt compatible to differentiate AM437x.
+	 */
+	if (of_device_is_compatible(node, "ti,am437x-dwc3")) {
+		omap->irq_eoi_offset = USBOTGSS_EOI_OFFSET;
+		omap->irq0_offset = USBOTGSS_IRQ0_OFFSET;
+		omap->irqmisc_offset = USBOTGSS_IRQMISC_OFFSET;
+		omap->utmi_otg_offset = USBOTGSS_UTMI_OTG_OFFSET;
+		omap->debug_offset = USBOTGSS_DEBUG_OFFSET;
+	}
+}
+
+static void dwc3_omap_set_utmi_mode(struct dwc3_omap *omap)
+{
+	u32			reg;
+	struct device_node	*node = omap->dev->of_node;
+	int			utmi_mode = 0;
+
+	reg = dwc3_omap_read_utmi_status(omap);
+
+	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(omap->dev, "UNKNOWN utmi mode %d\n", utmi_mode);
+	}
+
+	dwc3_omap_write_utmi_status(omap, reg);
+}
+
+static int dwc3_omap_extcon_register(struct dwc3_omap *omap)
+{
+	u32			ret;
+	struct device_node	*node = omap->dev->of_node;
+	struct extcon_dev	*edev;
+
+	if (of_property_read_bool(node, "extcon")) {
+		edev = extcon_get_edev_by_phandle(omap->dev, 0);
+		if (IS_ERR(edev)) {
+			dev_vdbg(omap->dev, "couldn't get extcon device\n");
+			return -EPROBE_DEFER;
+		}
+
+		omap->vbus_nb.notifier_call = dwc3_omap_vbus_notifier;
+		ret = extcon_register_interest(&omap->extcon_vbus_dev,
+					       edev->name, "USB",
+					       &omap->vbus_nb);
+		if (ret < 0)
+			dev_vdbg(omap->dev, "failed to register notifier for USB\n");
+
+		omap->id_nb.notifier_call = dwc3_omap_id_notifier;
+		ret = extcon_register_interest(&omap->extcon_id_dev,
+					       edev->name, "USB-HOST",
+					       &omap->id_nb);
+		if (ret < 0)
+			dev_vdbg(omap->dev, "failed to register notifier for USB-HOST\n");
+
+		if (extcon_get_cable_state(edev, "USB") == true)
+			dwc3_omap_set_mailbox(omap, OMAP_DWC3_VBUS_VALID);
+		if (extcon_get_cable_state(edev, "USB-HOST") == true)
+			dwc3_omap_set_mailbox(omap, OMAP_DWC3_ID_GROUND);
+	}
+
+	return 0;
+}
+
 static int dwc3_omap_probe(struct platform_device *pdev)
 {
 	struct device_node	*node = pdev->dev.of_node;
@@ -390,15 +466,11 @@ static int dwc3_omap_probe(struct platform_device *pdev)
 	struct dwc3_omap	*omap;
 	struct resource		*res;
 	struct device		*dev = &pdev->dev;
-	struct extcon_dev	*edev;
 	struct regulator	*vbus_reg = NULL;
 
 	int			ret;
 	int			irq;
 
-	int			utmi_mode = 0;
-	int			x_major;
-
 	u32			reg;
 
 	void __iomem		*base;
@@ -448,58 +520,8 @@ static int dwc3_omap_probe(struct platform_device *pdev)
 		goto err0;
 	}
 
-	reg = dwc3_omap_readl(omap->base, USBOTGSS_REVISION);
-	omap->revision = reg;
-	x_major = USBOTGSS_REVISION_XMAJOR(reg);
-
-	/* Differentiate between OMAP5 and AM437x */
-	switch (x_major) {
-	case USBOTGSS_REVISION_XMAJOR1:
-	case USBOTGSS_REVISION_XMAJOR2:
-		omap->irq_eoi_offset = 0;
-		omap->irq0_offset = 0;
-		omap->irqmisc_offset = 0;
-		omap->utmi_otg_offset = 0;
-		omap->debug_offset = 0;
-		break;
-	default:
-		/* Default to the latest revision */
-		omap->irq_eoi_offset = USBOTGSS_EOI_OFFSET;
-		omap->irq0_offset = USBOTGSS_IRQ0_OFFSET;
-		omap->irqmisc_offset = USBOTGSS_IRQMISC_OFFSET;
-		omap->utmi_otg_offset = USBOTGSS_UTMI_OTG_OFFSET;
-		omap->debug_offset = USBOTGSS_DEBUG_OFFSET;
-		break;
-	}
-
-	/* For OMAP5(ES2.0) and AM437x x_major is 2 even though there are
-	 * changes in wrapper registers, Using dt compatible for aegis
-	 */
-
-	if (of_device_is_compatible(node, "ti,am437x-dwc3")) {
-		omap->irq_eoi_offset = USBOTGSS_EOI_OFFSET;
-		omap->irq0_offset = USBOTGSS_IRQ0_OFFSET;
-		omap->irqmisc_offset = USBOTGSS_IRQMISC_OFFSET;
-		omap->utmi_otg_offset = USBOTGSS_UTMI_OTG_OFFSET;
-		omap->debug_offset = USBOTGSS_DEBUG_OFFSET;
-	}
-
-	reg = dwc3_omap_read_utmi_status(omap);
-
-	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_write_utmi_status(omap, reg);
+	dwc3_omap_map_offset(omap);
+	dwc3_omap_set_utmi_mode(omap);
 
 	/* check the DMA Status */
 	reg = dwc3_omap_readl(omap->base, USBOTGSS_SYSCONFIG);
@@ -515,31 +537,9 @@ static int dwc3_omap_probe(struct platform_device *pdev)
 
 	dwc3_omap_enable_irqs(omap);
 
-	if (of_property_read_bool(node, "extcon")) {
-		edev = extcon_get_edev_by_phandle(dev, 0);
-		if (IS_ERR(edev)) {
-			dev_vdbg(dev, "couldn't get extcon device\n");
-			ret = -EPROBE_DEFER;
-			goto err2;
-		}
-
-		omap->vbus_nb.notifier_call = dwc3_omap_vbus_notifier;
-		ret = extcon_register_interest(&omap->extcon_vbus_dev,
-			edev->name, "USB", &omap->vbus_nb);
-		if (ret < 0)
-			dev_vdbg(dev, "failed to register notifier for USB\n");
-		omap->id_nb.notifier_call = dwc3_omap_id_notifier;
-		ret = extcon_register_interest(&omap->extcon_id_dev, edev->name,
-					 "USB-HOST", &omap->id_nb);
-		if (ret < 0)
-			dev_vdbg(dev,
-				"failed to register notifier for USB-HOST\n");
-
-		if (extcon_get_cable_state(edev, "USB") == true)
-			dwc3_omap_set_mailbox(omap, OMAP_DWC3_VBUS_VALID);
-		if (extcon_get_cable_state(edev, "USB-HOST") == true)
-			dwc3_omap_set_mailbox(omap, OMAP_DWC3_ID_GROUND);
-	}
+	ret = dwc3_omap_extcon_register(omap);
+	if (ret < 0)
+		goto err2;
 
 	ret = of_platform_populate(node, NULL, NULL, dev);
 	if (ret) {

+ 3 - 4
drivers/usb/dwc3/gadget.c

@@ -1971,8 +1971,7 @@ static int dwc3_cleanup_done_reqs(struct dwc3 *dwc, struct dwc3_ep *dep,
 }
 
 static void dwc3_endpoint_transfer_complete(struct dwc3 *dwc,
-		struct dwc3_ep *dep, const struct dwc3_event_depevt *event,
-		int start_new)
+		struct dwc3_ep *dep, const struct dwc3_event_depevt *event)
 {
 	unsigned		status = 0;
 	int			clean_busy;
@@ -2039,7 +2038,7 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc,
 			return;
 		}
 
-		dwc3_endpoint_transfer_complete(dwc, dep, event, 1);
+		dwc3_endpoint_transfer_complete(dwc, dep, event);
 		break;
 	case DWC3_DEPEVT_XFERINPROGRESS:
 		if (!usb_endpoint_xfer_isoc(dep->endpoint.desc)) {
@@ -2048,7 +2047,7 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc,
 			return;
 		}
 
-		dwc3_endpoint_transfer_complete(dwc, dep, event, 0);
+		dwc3_endpoint_transfer_complete(dwc, dep, event);
 		break;
 	case DWC3_DEPEVT_XFERNOTREADY:
 		if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) {

+ 2 - 822
drivers/usb/gadget/Kconfig

@@ -127,368 +127,7 @@ config USB_GADGET_STORAGE_NUM_BUFFERS
 	   a module parameter as well.
 	   If unsure, say 2.
 
-#
-# USB Peripheral Controller Support
-#
-# The order here is alphabetical, except that integrated controllers go
-# before discrete ones so they will be the initial/default value:
-#   - integrated/SOC controllers first
-#   - licensed IP used in both SOC and discrete versions
-#   - discrete ones (including all PCI-only controllers)
-#   - debug/dummy gadget+hcd is last.
-#
-menu "USB Peripheral Controller"
-
-#
-# Integrated controllers
-#
-
-config USB_AT91
-	tristate "Atmel AT91 USB Device Port"
-	depends on ARCH_AT91
-	help
-	   Many Atmel AT91 processors (such as the AT91RM2000) have a
-	   full speed USB Device Port with support for five configurable
-	   endpoints (plus endpoint zero).
-
-	   Say "y" to link the driver statically, or "m" to build a
-	   dynamically linked module called "at91_udc" and force all
-	   gadget drivers to also be dynamically linked.
-
-config USB_LPC32XX
-	tristate "LPC32XX USB Peripheral Controller"
-	depends on ARCH_LPC32XX && I2C
-	select USB_ISP1301
-	help
-	   This option selects the USB device controller in the LPC32xx SoC.
-
-	   Say "y" to link the driver statically, or "m" to build a
-	   dynamically linked module called "lpc32xx_udc" and force all
-	   gadget drivers to also be dynamically linked.
-
-config USB_ATMEL_USBA
-	tristate "Atmel USBA"
-	depends on AVR32 || ARCH_AT91
-	help
-	  USBA is the integrated high-speed USB Device controller on
-	  the AT32AP700x, some AT91SAM9 and AT91CAP9 processors from Atmel.
-
-config USB_BCM63XX_UDC
-	tristate "Broadcom BCM63xx Peripheral Controller"
-	depends on BCM63XX
-	help
-	   Many Broadcom BCM63xx chipsets (such as the BCM6328) have a
-	   high speed USB Device Port with support for four fixed endpoints
-	   (plus endpoint zero).
-
-	   Say "y" to link the driver statically, or "m" to build a
-	   dynamically linked module called "bcm63xx_udc".
-
-config USB_FSL_USB2
-	tristate "Freescale Highspeed USB DR Peripheral Controller"
-	depends on FSL_SOC || ARCH_MXC
-	select USB_FSL_MPH_DR_OF if OF
-	help
-	   Some of Freescale PowerPC and i.MX processors have a High Speed
-	   Dual-Role(DR) USB controller, which supports device mode.
-
-	   The number of programmable endpoints is different through
-	   SOC revisions.
-
-	   Say "y" to link the driver statically, or "m" to build a
-	   dynamically linked module called "fsl_usb2_udc" and force
-	   all gadget drivers to also be dynamically linked.
-
-config USB_FUSB300
-	tristate "Faraday FUSB300 USB Peripheral Controller"
-	depends on !PHYS_ADDR_T_64BIT && HAS_DMA
-	help
-	   Faraday usb device controller FUSB300 driver
-
-config USB_FOTG210_UDC
-	depends on HAS_DMA
-	tristate "Faraday FOTG210 USB Peripheral Controller"
-	help
-	   Faraday USB2.0 OTG controller which can be configured as
-	   high speed or full speed USB device. This driver supppors
-	   Bulk Transfer so far.
-
-	   Say "y" to link the driver statically, or "m" to build a
-	   dynamically linked module called "fotg210_udc".
-
-config USB_GR_UDC
-       tristate "Aeroflex Gaisler GRUSBDC USB Peripheral Controller Driver"
-       depends on HAS_DMA
-       help
-          Select this to support Aeroflex Gaisler GRUSBDC cores from the GRLIB
-	  VHDL IP core library.
-
-config USB_OMAP
-	tristate "OMAP USB Device Controller"
-	depends on ARCH_OMAP1
-	depends on ISP1301_OMAP || !(MACH_OMAP_H2 || MACH_OMAP_H3)
-	help
-	   Many Texas Instruments OMAP processors have flexible full
-	   speed USB device controllers, with support for up to 30
-	   endpoints (plus endpoint zero).  This driver supports the
-	   controller in the OMAP 1611, and should work with controllers
-	   in other OMAP processors too, given minor tweaks.
-
-	   Say "y" to link the driver statically, or "m" to build a
-	   dynamically linked module called "omap_udc" and force all
-	   gadget drivers to also be dynamically linked.
-
-config USB_PXA25X
-	tristate "PXA 25x or IXP 4xx"
-	depends on (ARCH_PXA && PXA25x) || ARCH_IXP4XX
-	help
-	   Intel's PXA 25x series XScale ARM-5TE processors include
-	   an integrated full speed USB 1.1 device controller.  The
-	   controller in the IXP 4xx series is register-compatible.
-
-	   It has fifteen fixed-function endpoints, as well as endpoint
-	   zero (for control transfers).
-
-	   Say "y" to link the driver statically, or "m" to build a
-	   dynamically linked module called "pxa25x_udc" and force all
-	   gadget drivers to also be dynamically linked.
-
-# if there's only one gadget driver, using only two bulk endpoints,
-# don't waste memory for the other endpoints
-config USB_PXA25X_SMALL
-	depends on USB_PXA25X
-	bool
-	default n if USB_ETH_RNDIS
-	default y if USB_ZERO
-	default y if USB_ETH
-	default y if USB_G_SERIAL
-
-config USB_R8A66597
-	tristate "Renesas R8A66597 USB Peripheral Controller"
-	depends on HAS_DMA
-	help
-	   R8A66597 is a discrete USB host and peripheral controller chip that
-	   supports both full and high speed USB 2.0 data transfers.
-	   It has nine configurable endpoints, and endpoint zero.
-
-	   Say "y" to link the driver statically, or "m" to build a
-	   dynamically linked module called "r8a66597_udc" and force all
-	   gadget drivers to also be dynamically linked.
-
-config USB_RENESAS_USBHS_UDC
-	tristate 'Renesas USBHS controller'
-	depends on USB_RENESAS_USBHS
-	help
-	   Renesas USBHS is a discrete USB host and peripheral controller chip
-	   that supports both full and high speed USB 2.0 data transfers.
-	   It has nine or more configurable endpoints, and endpoint zero.
-
-	   Say "y" to link the driver statically, or "m" to build a
-	   dynamically linked module called "renesas_usbhs" and force all
-	   gadget drivers to also be dynamically linked.
-
-config USB_PXA27X
-	tristate "PXA 27x"
-	help
-	   Intel's PXA 27x series XScale ARM v5TE processors include
-	   an integrated full speed USB 1.1 device controller.
-
-	   It has up to 23 endpoints, as well as endpoint zero (for
-	   control transfers).
-
-	   Say "y" to link the driver statically, or "m" to build a
-	   dynamically linked module called "pxa27x_udc" and force all
-	   gadget drivers to also be dynamically linked.
-
-config USB_S3C2410
-	tristate "S3C2410 USB Device Controller"
-	depends on ARCH_S3C24XX
-	help
-	  Samsung's S3C2410 is an ARM-4 processor with an integrated
-	  full speed USB 1.1 device controller.  It has 4 configurable
-	  endpoints, as well as endpoint zero (for control transfers).
-
-	  This driver has been tested on the S3C2410, S3C2412, and
-	  S3C2440 processors.
-
-config USB_S3C2410_DEBUG
-	boolean "S3C2410 udc debug messages"
-	depends on USB_S3C2410
-
-config USB_S3C_HSUDC
-	tristate "S3C2416, S3C2443 and S3C2450 USB Device Controller"
-	depends on ARCH_S3C24XX
-	help
-	  Samsung's S3C2416, S3C2443 and S3C2450 is an ARM9 based SoC
-	  integrated with dual speed USB 2.0 device controller. It has
-	  8 endpoints, as well as endpoint zero.
-
-	  This driver has been tested on S3C2416 and S3C2450 processors.
-
-config USB_MV_UDC
-	tristate "Marvell USB2.0 Device Controller"
-	depends on HAS_DMA
-	help
-	  Marvell Socs (including PXA and MMP series) include a high speed
-	  USB2.0 OTG controller, which can be configured as high speed or
-	  full speed USB peripheral.
-
-config USB_MV_U3D
-	depends on HAS_DMA
-	tristate "MARVELL PXA2128 USB 3.0 controller"
-	help
-	  MARVELL PXA2128 Processor series include a super speed USB3.0 device
-	  controller, which support super speed USB peripheral.
-
-#
-# Controllers available in both integrated and discrete versions
-#
-
-config USB_M66592
-	tristate "Renesas M66592 USB Peripheral Controller"
-	help
-	   M66592 is a discrete USB peripheral controller chip that
-	   supports both full and high speed USB 2.0 data transfers.
-	   It has seven configurable endpoints, and endpoint zero.
-
-	   Say "y" to link the driver statically, or "m" to build a
-	   dynamically linked module called "m66592_udc" and force all
-	   gadget drivers to also be dynamically linked.
-
-#
-# Controllers available only in discrete form (and all PCI controllers)
-#
-
-config USB_AMD5536UDC
-	tristate "AMD5536 UDC"
-	depends on PCI
-	help
-	   The AMD5536 UDC is part of the AMD Geode CS5536, an x86 southbridge.
-	   It is a USB Highspeed DMA capable USB device controller. Beside ep0
-	   it provides 4 IN and 4 OUT endpoints (bulk or interrupt type).
-	   The UDC port supports OTG operation, and may be used as a host port
-	   if it's not being used to implement peripheral or OTG roles.
-
-	   Say "y" to link the driver statically, or "m" to build a
-	   dynamically linked module called "amd5536udc" and force all
-	   gadget drivers to also be dynamically linked.
-
-config USB_FSL_QE
-	tristate "Freescale QE/CPM USB Device Controller"
-	depends on FSL_SOC && (QUICC_ENGINE || CPM)
-	help
-	   Some of Freescale PowerPC processors have a Full Speed
-	   QE/CPM2 USB controller, which support device mode with 4
-	   programmable endpoints. This driver supports the
-	   controller in the MPC8360 and MPC8272, and should work with
-	   controllers having QE or CPM2, given minor tweaks.
-
-	   Set CONFIG_USB_GADGET to "m" to build this driver as a
-	   dynamically linked module called "fsl_qe_udc".
-
-config USB_NET2272
-	tristate "PLX NET2272"
-	help
-	  PLX NET2272 is a USB peripheral controller which supports
-	  both full and high speed USB 2.0 data transfers.
-
-	  It has three configurable endpoints, as well as endpoint zero
-	  (for control transfer).
-	  Say "y" to link the driver statically, or "m" to build a
-	  dynamically linked module called "net2272" and force all
-	  gadget drivers to also be dynamically linked.
-
-config USB_NET2272_DMA
-	boolean "Support external DMA controller"
-	depends on USB_NET2272 && HAS_DMA
-	help
-	  The NET2272 part can optionally support an external DMA
-	  controller, but your board has to have support in the
-	  driver itself.
-
-	  If unsure, say "N" here.  The driver works fine in PIO mode.
-
-config USB_NET2280
-	tristate "NetChip 228x"
-	depends on PCI
-	help
-	   NetChip 2280 / 2282 is a PCI based USB peripheral controller which
-	   supports both full and high speed USB 2.0 data transfers.
-
-	   It has six configurable endpoints, as well as endpoint zero
-	   (for control transfers) and several endpoints with dedicated
-	   functions.
-
-	   Say "y" to link the driver statically, or "m" to build a
-	   dynamically linked module called "net2280" and force all
-	   gadget drivers to also be dynamically linked.
-
-config USB_GOKU
-	tristate "Toshiba TC86C001 'Goku-S'"
-	depends on PCI
-	help
-	   The Toshiba TC86C001 is a PCI device which includes controllers
-	   for full speed USB devices, IDE, I2C, SIO, plus a USB host (OHCI).
-
-	   The device controller has three configurable (bulk or interrupt)
-	   endpoints, plus endpoint zero (for control transfers).
-
-	   Say "y" to link the driver statically, or "m" to build a
-	   dynamically linked module called "goku_udc" and to force all
-	   gadget drivers to also be dynamically linked.
-
-config USB_EG20T
-	tristate "Intel EG20T PCH/LAPIS Semiconductor IOH(ML7213/ML7831) UDC"
-	depends on PCI
-	help
-	  This is a USB device driver for EG20T PCH.
-	  EG20T PCH is the platform controller hub that is used in Intel's
-	  general embedded platform. EG20T PCH has USB device interface.
-	  Using this interface, it is able to access system devices connected
-	  to USB device.
-	  This driver enables USB device function.
-	  USB device is a USB peripheral controller which
-	  supports both full and high speed USB 2.0 data transfers.
-	  This driver supports both control transfer and bulk transfer modes.
-	  This driver dose not support interrupt transfer or isochronous
-	  transfer modes.
-
-	  This driver also can be used for LAPIS Semiconductor's ML7213 which is
-	  for IVI(In-Vehicle Infotainment) use.
-	  ML7831 is for general purpose use.
-	  ML7213/ML7831 is companion chip for Intel Atom E6xx series.
-	  ML7213/ML7831 is completely compatible for Intel EG20T PCH.
-
-#
-# LAST -- dummy/emulated controller
-#
-
-config USB_DUMMY_HCD
-	tristate "Dummy HCD (DEVELOPMENT)"
-	depends on USB=y || (USB=m && USB_GADGET=m)
-	help
-	  This host controller driver emulates USB, looping all data transfer
-	  requests back to a USB "gadget driver" in the same host.  The host
-	  side is the master; the gadget side is the slave.  Gadget drivers
-	  can be high, full, or low speed; and they have access to endpoints
-	  like those from NET2280, PXA2xx, or SA1100 hardware.
-
-	  This may help in some stages of creating a driver to embed in a
-	  Linux device, since it lets you debug several parts of the gadget
-	  driver without its hardware or drivers being involved.
-
-	  Since such a gadget side driver needs to interoperate with a host
-	  side Linux-USB device driver, this may help to debug both sides
-	  of a USB protocol stack.
-
-	  Say "y" to link the driver statically, or "m" to build a
-	  dynamically linked module called "dummy_hcd" and force all
-	  gadget drivers to also be dynamically linked.
-
-# NOTE:  Please keep dummy_hcd LAST so that "real hardware" appears
-# first and will be selected by default.
-
-endmenu
+source "drivers/usb/gadget/udc/Kconfig"
 
 #
 # USB Gadget Drivers
@@ -714,466 +353,7 @@ config USB_CONFIGFS_F_FS
 	  implemented in kernel space (for instance Ethernet, serial or
 	  mass storage) and other are implemented in user space.
 
-config USB_ZERO
-	tristate "Gadget Zero (DEVELOPMENT)"
-	select USB_LIBCOMPOSITE
-	select USB_F_SS_LB
-	help
-	  Gadget Zero is a two-configuration device.  It either sinks and
-	  sources bulk data; or it loops back a configurable number of
-	  transfers.  It also implements control requests, for "chapter 9"
-	  conformance.  The driver needs only two bulk-capable endpoints, so
-	  it can work on top of most device-side usb controllers.  It's
-	  useful for testing, and is also a working example showing how
-	  USB "gadget drivers" can be written.
-
-	  Make this be the first driver you try using on top of any new
-	  USB peripheral controller driver.  Then you can use host-side
-	  test software, like the "usbtest" driver, to put your hardware
-	  and its driver through a basic set of functional tests.
-
-	  Gadget Zero also works with the host-side "usb-skeleton" driver,
-	  and with many kinds of host-side test software.  You may need
-	  to tweak product and vendor IDs before host software knows about
-	  this device, and arrange to select an appropriate configuration.
-
-	  Say "y" to link the driver statically, or "m" to build a
-	  dynamically linked module called "g_zero".
-
-config USB_ZERO_HNPTEST
-	boolean "HNP Test Device"
-	depends on USB_ZERO && USB_OTG
-	help
-	  You can configure this device to enumerate using the device
-	  identifiers of the USB-OTG test device.  That means that when
-	  this gadget connects to another OTG device, with this one using
-	  the "B-Peripheral" role, that device will use HNP to let this
-	  one serve as the USB host instead (in the "B-Host" role).
-
-config USB_AUDIO
-	tristate "Audio Gadget"
-	depends on SND
-	select USB_LIBCOMPOSITE
-	select SND_PCM
-	help
-	  This Gadget Audio driver is compatible with USB Audio Class
-	  specification 2.0. It implements 1 AudioControl interface,
-	  1 AudioStreaming Interface each for USB-OUT and USB-IN.
-	  Number of channels, sample rate and sample size can be
-	  specified as module parameters.
-	  This driver doesn't expect any real Audio codec to be present
-	  on the device - the audio streams are simply sinked to and
-	  sourced from a virtual ALSA sound card created. The user-space
-	  application may choose to do whatever it wants with the data
-	  received from the USB Host and choose to provide whatever it
-	  wants as audio data to the USB Host.
-
-	  Say "y" to link the driver statically, or "m" to build a
-	  dynamically linked module called "g_audio".
-
-config GADGET_UAC1
-	bool "UAC 1.0 (Legacy)"
-	depends on USB_AUDIO
-	help
-	  If you instead want older UAC Spec-1.0 driver that also has audio
-	  paths hardwired to the Audio codec chip on-board and doesn't work
-	  without one.
-
-config USB_ETH
-	tristate "Ethernet Gadget (with CDC Ethernet support)"
-	depends on NET
-	select USB_LIBCOMPOSITE
-	select USB_U_ETHER
-	select USB_F_ECM
-	select USB_F_SUBSET
-	select CRC32
-	help
-	  This driver implements Ethernet style communication, in one of
-	  several ways:
-	  
-	   - The "Communication Device Class" (CDC) Ethernet Control Model.
-	     That protocol is often avoided with pure Ethernet adapters, in
-	     favor of simpler vendor-specific hardware, but is widely
-	     supported by firmware for smart network devices.
-
-	   - On hardware can't implement that protocol, a simple CDC subset
-	     is used, placing fewer demands on USB.
-
-	   - CDC Ethernet Emulation Model (EEM) is a newer standard that has
-	     a simpler interface that can be used by more USB hardware.
-
-	  RNDIS support is an additional option, more demanding than than
-	  subset.
-
-	  Within the USB device, this gadget driver exposes a network device
-	  "usbX", where X depends on what other networking devices you have.
-	  Treat it like a two-node Ethernet link:  host, and gadget.
-
-	  The Linux-USB host-side "usbnet" driver interoperates with this
-	  driver, so that deep I/O queues can be supported.  On 2.4 kernels,
-	  use "CDCEther" instead, if you're using the CDC option. That CDC
-	  mode should also interoperate with standard CDC Ethernet class
-	  drivers on other host operating systems.
-
-	  Say "y" to link the driver statically, or "m" to build a
-	  dynamically linked module called "g_ether".
-
-config USB_ETH_RNDIS
-	bool "RNDIS support"
-	depends on USB_ETH
-	select USB_LIBCOMPOSITE
-	select USB_F_RNDIS
-	default y
-	help
-	   Microsoft Windows XP bundles the "Remote NDIS" (RNDIS) protocol,
-	   and Microsoft provides redistributable binary RNDIS drivers for
-	   older versions of Windows.
-
-	   If you say "y" here, the Ethernet gadget driver will try to provide
-	   a second device configuration, supporting RNDIS to talk to such
-	   Microsoft USB hosts.
-	   
-	   To make MS-Windows work with this, use Documentation/usb/linux.inf
-	   as the "driver info file".  For versions of MS-Windows older than
-	   XP, you'll need to download drivers from Microsoft's website; a URL
-	   is given in comments found in that info file.
-
-config USB_ETH_EEM
-       bool "Ethernet Emulation Model (EEM) support"
-       depends on USB_ETH
-	select USB_LIBCOMPOSITE
-	select USB_F_EEM
-       default n
-       help
-         CDC EEM is a newer USB standard that is somewhat simpler than CDC ECM
-         and therefore can be supported by more hardware.  Technically ECM and
-         EEM are designed for different applications.  The ECM model extends
-         the network interface to the target (e.g. a USB cable modem), and the
-         EEM model is for mobile devices to communicate with hosts using
-         ethernet over USB.  For Linux gadgets, however, the interface with
-         the host is the same (a usbX device), so the differences are minimal.
-
-         If you say "y" here, the Ethernet gadget driver will use the EEM
-         protocol rather than ECM.  If unsure, say "n".
-
-config USB_G_NCM
-	tristate "Network Control Model (NCM) support"
-	depends on NET
-	select USB_LIBCOMPOSITE
-	select USB_U_ETHER
-	select USB_F_NCM
-	select CRC32
-	help
-	  This driver implements USB CDC NCM subclass standard. NCM is
-	  an advanced protocol for Ethernet encapsulation, allows grouping
-	  of several ethernet frames into one USB transfer and different
-	  alignment possibilities.
-
-	  Say "y" to link the driver statically, or "m" to build a
-	  dynamically linked module called "g_ncm".
-
-config USB_GADGETFS
-	tristate "Gadget Filesystem"
-	help
-	  This driver provides a filesystem based API that lets user mode
-	  programs implement a single-configuration USB device, including
-	  endpoint I/O and control requests that don't relate to enumeration.
-	  All endpoints, transfer speeds, and transfer types supported by
-	  the hardware are available, through read() and write() calls.
-
-	  Say "y" to link the driver statically, or "m" to build a
-	  dynamically linked module called "gadgetfs".
-
-config USB_FUNCTIONFS
-	tristate "Function Filesystem"
-	select USB_LIBCOMPOSITE
-	select USB_F_FS
-	select USB_FUNCTIONFS_GENERIC if !(USB_FUNCTIONFS_ETH || USB_FUNCTIONFS_RNDIS)
-	help
-	  The Function Filesystem (FunctionFS) lets one create USB
-	  composite functions in user space in the same way GadgetFS
-	  lets one create USB gadgets in user space.  This allows creation
-	  of composite gadgets such that some of the functions are
-	  implemented in kernel space (for instance Ethernet, serial or
-	  mass storage) and other are implemented in user space.
-
-	  If you say "y" or "m" here you will be able what kind of
-	  configurations the gadget will provide.
-
-	  Say "y" to link the driver statically, or "m" to build
-	  a dynamically linked module called "g_ffs".
-
-config USB_FUNCTIONFS_ETH
-	bool "Include configuration with CDC ECM (Ethernet)"
-	depends on USB_FUNCTIONFS && NET
-	select USB_U_ETHER
-	select USB_F_ECM
-	select USB_F_SUBSET
-	help
-	  Include a configuration with CDC ECM function (Ethernet) and the
-	  Function Filesystem.
-
-config USB_FUNCTIONFS_RNDIS
-	bool "Include configuration with RNDIS (Ethernet)"
-	depends on USB_FUNCTIONFS && NET
-	select USB_U_ETHER
-	select USB_F_RNDIS
-	help
-	  Include a configuration with RNDIS function (Ethernet) and the Filesystem.
-
-config USB_FUNCTIONFS_GENERIC
-	bool "Include 'pure' configuration"
-	depends on USB_FUNCTIONFS
-	help
-	  Include a configuration with the Function Filesystem alone with
-	  no Ethernet interface.
-
-config USB_MASS_STORAGE
-	tristate "Mass Storage Gadget"
-	depends on BLOCK
-	select USB_LIBCOMPOSITE
-	select USB_F_MASS_STORAGE
-	help
-	  The Mass Storage Gadget acts as a USB Mass Storage disk drive.
-	  As its storage repository it can use a regular file or a block
-	  device (in much the same way as the "loop" device driver),
-	  specified as a module parameter or sysfs option.
-
-	  This driver is a replacement for now removed File-backed
-	  Storage Gadget (g_file_storage).
-
-	  Say "y" to link the driver statically, or "m" to build
-	  a dynamically linked module called "g_mass_storage".
-
-config USB_GADGET_TARGET
-	tristate "USB Gadget Target Fabric Module"
-	depends on TARGET_CORE
-	select USB_LIBCOMPOSITE
-	help
-	  This fabric is an USB gadget. Two USB protocols are supported that is
-	  BBB or BOT (Bulk Only Transport) and UAS (USB Attached SCSI). BOT is
-	  advertised on alternative interface 0 (primary) and UAS is on
-	  alternative interface 1. Both protocols can work on USB2.0 and USB3.0.
-	  UAS utilizes the USB 3.0 feature called streams support.
-
-config USB_G_SERIAL
-	tristate "Serial Gadget (with CDC ACM and CDC OBEX support)"
-	depends on TTY
-	select USB_U_SERIAL
-	select USB_F_ACM
-	select USB_F_SERIAL
-	select USB_F_OBEX
-	select USB_LIBCOMPOSITE
-	help
-	  The Serial Gadget talks to the Linux-USB generic serial driver.
-	  This driver supports a CDC-ACM module option, which can be used
-	  to interoperate with MS-Windows hosts or with the Linux-USB
-	  "cdc-acm" driver.
-
-	  This driver also supports a CDC-OBEX option.  You will need a
-	  user space OBEX server talking to /dev/ttyGS*, since the kernel
-	  itself doesn't implement the OBEX protocol.
-
-	  Say "y" to link the driver statically, or "m" to build a
-	  dynamically linked module called "g_serial".
-
-	  For more information, see Documentation/usb/gadget_serial.txt
-	  which includes instructions and a "driver info file" needed to
-	  make MS-Windows work with CDC ACM.
-
-config USB_MIDI_GADGET
-	tristate "MIDI Gadget"
-	depends on SND
-	select USB_LIBCOMPOSITE
-	select SND_RAWMIDI
-	help
-	  The MIDI Gadget acts as a USB Audio device, with one MIDI
-	  input and one MIDI output. These MIDI jacks appear as
-	  a sound "card" in the ALSA sound system. Other MIDI
-	  connections can then be made on the gadget system, using
-	  ALSA's aconnect utility etc.
-
-	  Say "y" to link the driver statically, or "m" to build a
-	  dynamically linked module called "g_midi".
-
-config USB_G_PRINTER
-	tristate "Printer Gadget"
-	select USB_LIBCOMPOSITE
-	help
-	  The Printer Gadget channels data between the USB host and a
-	  userspace program driving the print engine. The user space
-	  program reads and writes the device file /dev/g_printer to
-	  receive or send printer data. It can use ioctl calls to
-	  the device file to get or set printer status.
-
-	  Say "y" to link the driver statically, or "m" to build a
-	  dynamically linked module called "g_printer".
-
-	  For more information, see Documentation/usb/gadget_printer.txt
-	  which includes sample code for accessing the device file.
-
-if TTY
-
-config USB_CDC_COMPOSITE
-	tristate "CDC Composite Device (Ethernet and ACM)"
-	depends on NET
-	select USB_LIBCOMPOSITE
-	select USB_U_SERIAL
-	select USB_U_ETHER
-	select USB_F_ACM
-	select USB_F_ECM
-	help
-	  This driver provides two functions in one configuration:
-	  a CDC Ethernet (ECM) link, and a CDC ACM (serial port) link.
-
-	  This driver requires four bulk and two interrupt endpoints,
-	  plus the ability to handle altsettings.  Not all peripheral
-	  controllers are that capable.
-
-	  Say "y" to link the driver statically, or "m" to build a
-	  dynamically linked module.
-
-config USB_G_NOKIA
-	tristate "Nokia composite gadget"
-	depends on PHONET
-	select USB_LIBCOMPOSITE
-	select USB_U_SERIAL
-	select USB_U_ETHER
-	select USB_F_ACM
-	select USB_F_OBEX
-	select USB_F_PHONET
-	select USB_F_ECM
-	help
-	  The Nokia composite gadget provides support for acm, obex
-	  and phonet in only one composite gadget driver.
-
-	  It's only really useful for N900 hardware. If you're building
-	  a kernel for N900, say Y or M here. If unsure, say N.
-
-config USB_G_ACM_MS
-	tristate "CDC Composite Device (ACM and mass storage)"
-	depends on BLOCK
-	select USB_LIBCOMPOSITE
-	select USB_U_SERIAL
-	select USB_F_ACM
-	select USB_F_MASS_STORAGE
-	help
-	  This driver provides two functions in one configuration:
-	  a mass storage, and a CDC ACM (serial port) link.
-
-	  Say "y" to link the driver statically, or "m" to build a
-	  dynamically linked module called "g_acm_ms".
-
-config USB_G_MULTI
-	tristate "Multifunction Composite Gadget"
-	depends on BLOCK && NET
-	select USB_G_MULTI_CDC if !USB_G_MULTI_RNDIS
-	select USB_LIBCOMPOSITE
-	select USB_U_SERIAL
-	select USB_U_ETHER
-	select USB_F_ACM
-	select USB_F_MASS_STORAGE
-	help
-	  The Multifunction Composite Gadget provides Ethernet (RNDIS
-	  and/or CDC Ethernet), mass storage and ACM serial link
-	  interfaces.
-
-	  You will be asked to choose which of the two configurations is
-	  to be available in the gadget.  At least one configuration must
-	  be chosen to make the gadget usable.  Selecting more than one
-	  configuration will prevent Windows from automatically detecting
-	  the gadget as a composite gadget, so an INF file will be needed to
-	  use the gadget.
-
-	  Say "y" to link the driver statically, or "m" to build a
-	  dynamically linked module called "g_multi".
-
-config USB_G_MULTI_RNDIS
-	bool "RNDIS + CDC Serial + Storage configuration"
-	depends on USB_G_MULTI
-	select USB_F_RNDIS
-	default y
-	help
-	  This option enables a configuration with RNDIS, CDC Serial and
-	  Mass Storage functions available in the Multifunction Composite
-	  Gadget.  This is the configuration dedicated for Windows since RNDIS
-	  is Microsoft's protocol.
-
-	  If unsure, say "y".
-
-config USB_G_MULTI_CDC
-	bool "CDC Ethernet + CDC Serial + Storage configuration"
-	depends on USB_G_MULTI
-	default n
-	select USB_F_ECM
-	help
-	  This option enables a configuration with CDC Ethernet (ECM), CDC
-	  Serial and Mass Storage functions available in the Multifunction
-	  Composite Gadget.
-
-	  If unsure, say "y".
-
-endif # TTY
-
-config USB_G_HID
-	tristate "HID Gadget"
-	select USB_LIBCOMPOSITE
-	help
-	  The HID gadget driver provides generic emulation of USB
-	  Human Interface Devices (HID).
-
-	  For more information, see Documentation/usb/gadget_hid.txt which
-	  includes sample code for accessing the device files.
-
-	  Say "y" to link the driver statically, or "m" to build a
-	  dynamically linked module called "g_hid".
-
-# Standalone / single function gadgets
-config USB_G_DBGP
-	tristate "EHCI Debug Device Gadget"
-	depends on TTY
-	select USB_LIBCOMPOSITE
-	help
-	  This gadget emulates an EHCI Debug device. This is useful when you want
-	  to interact with an EHCI Debug Port.
-
-	  Say "y" to link the driver statically, or "m" to build a
-	  dynamically linked module called "g_dbgp".
-
-if USB_G_DBGP
-choice
-	prompt "EHCI Debug Device mode"
-	default USB_G_DBGP_SERIAL
-
-config USB_G_DBGP_PRINTK
-	depends on USB_G_DBGP
-	bool "printk"
-	help
-	  Directly printk() received data. No interaction.
-
-config USB_G_DBGP_SERIAL
-	depends on USB_G_DBGP
-	select USB_U_SERIAL
-	bool "serial"
-	help
-	  Userland can interact using /dev/ttyGSxxx.
-endchoice
-endif
-
-# put drivers that need isochronous transfer support (for audio
-# or video class gadget drivers), or specific hardware, here.
-config USB_G_WEBCAM
-	tristate "USB Webcam Gadget"
-	depends on VIDEO_DEV
-	select USB_LIBCOMPOSITE
-	select VIDEOBUF2_VMALLOC
-	help
-	  The Webcam Gadget acts as a composite USB Audio and Video Class
-	  device. It provides a userspace API to process UVC control requests
-	  and stream video data to the host.
-
-	  Say "y" to link the driver statically, or "m" to build a
-	  dynamically linked module called "g_webcam".
+source "drivers/usb/gadget/legacy/Kconfig"
 
 endchoice
 

+ 4 - 97
drivers/usb/gadget/Makefile

@@ -1,105 +1,12 @@
 #
 # USB peripheral controller drivers
 #
-ccflags-$(CONFIG_USB_GADGET_DEBUG)	:= -DDEBUG
-ccflags-$(CONFIG_USB_GADGET_VERBOSE)	+= -DVERBOSE_DEBUG
+subdir-ccflags-$(CONFIG_USB_GADGET_DEBUG)	:= -DDEBUG
+subdir-ccflags-$(CONFIG_USB_GADGET_VERBOSE)	+= -DVERBOSE_DEBUG
+ccflags-y				+= -I$(PWD)/drivers/usb/gadget/udc
 
-obj-$(CONFIG_USB_GADGET)	+= udc-core.o
 obj-$(CONFIG_USB_LIBCOMPOSITE)	+= libcomposite.o
 libcomposite-y			:= usbstring.o config.o epautoconf.o
 libcomposite-y			+= composite.o functions.o configfs.o u_f.o
-obj-$(CONFIG_USB_DUMMY_HCD)	+= dummy_hcd.o
-obj-$(CONFIG_USB_NET2272)	+= net2272.o
-obj-$(CONFIG_USB_NET2280)	+= net2280.o
-obj-$(CONFIG_USB_AMD5536UDC)	+= amd5536udc.o
-obj-$(CONFIG_USB_PXA25X)	+= pxa25x_udc.o
-obj-$(CONFIG_USB_PXA27X)	+= pxa27x_udc.o
-obj-$(CONFIG_USB_GOKU)		+= goku_udc.o
-obj-$(CONFIG_USB_OMAP)		+= omap_udc.o
-obj-$(CONFIG_USB_S3C2410)	+= s3c2410_udc.o
-obj-$(CONFIG_USB_AT91)		+= at91_udc.o
-obj-$(CONFIG_USB_ATMEL_USBA)	+= atmel_usba_udc.o
-obj-$(CONFIG_USB_BCM63XX_UDC)	+= bcm63xx_udc.o
-obj-$(CONFIG_USB_FSL_USB2)	+= fsl_usb2_udc.o
-fsl_usb2_udc-y			:= fsl_udc_core.o
-fsl_usb2_udc-$(CONFIG_ARCH_MXC)	+= fsl_mxc_udc.o
-obj-$(CONFIG_USB_M66592)	+= m66592-udc.o
-obj-$(CONFIG_USB_R8A66597)	+= r8a66597-udc.o
-obj-$(CONFIG_USB_FSL_QE)	+= fsl_qe_udc.o
-obj-$(CONFIG_USB_S3C_HSUDC)	+= s3c-hsudc.o
-obj-$(CONFIG_USB_LPC32XX)	+= lpc32xx_udc.o
-obj-$(CONFIG_USB_EG20T)		+= pch_udc.o
-obj-$(CONFIG_USB_MV_UDC)	+= mv_udc.o
-mv_udc-y			:= mv_udc_core.o
-obj-$(CONFIG_USB_FUSB300)	+= fusb300_udc.o
-obj-$(CONFIG_USB_FOTG210_UDC)	+= fotg210-udc.o
-obj-$(CONFIG_USB_MV_U3D)	+= mv_u3d_core.o
-obj-$(CONFIG_USB_GR_UDC)	+= gr_udc.o
 
-# USB Functions
-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
-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
-obj-$(CONFIG_USB_U_ETHER)	+= u_ether.o
-usb_f_ncm-y			:= f_ncm.o
-obj-$(CONFIG_USB_F_NCM)		+= usb_f_ncm.o
-usb_f_ecm-y			:= f_ecm.o
-obj-$(CONFIG_USB_F_ECM)		+= usb_f_ecm.o
-usb_f_phonet-y			:= f_phonet.o
-obj-$(CONFIG_USB_F_PHONET)	+= usb_f_phonet.o
-usb_f_eem-y			:= f_eem.o
-obj-$(CONFIG_USB_F_EEM)		+= usb_f_eem.o
-usb_f_ecm_subset-y		:= f_subset.o
-obj-$(CONFIG_USB_F_SUBSET)	+= usb_f_ecm_subset.o
-usb_f_rndis-y			:= f_rndis.o rndis.o
-obj-$(CONFIG_USB_F_RNDIS)	+= usb_f_rndis.o
-usb_f_mass_storage-y		:= f_mass_storage.o storage_common.o
-obj-$(CONFIG_USB_F_MASS_STORAGE)+= usb_f_mass_storage.o
-usb_f_fs-y			:= f_fs.o
-obj-$(CONFIG_USB_F_FS)		+= usb_f_fs.o
-
-#
-# USB gadget drivers
-#
-g_zero-y			:= zero.o
-g_audio-y			:= audio.o
-g_ether-y			:= ether.o
-g_serial-y			:= serial.o
-g_midi-y			:= gmidi.o
-gadgetfs-y			:= inode.o
-g_mass_storage-y		:= mass_storage.o
-g_printer-y			:= printer.o
-g_cdc-y				:= cdc2.o
-g_multi-y			:= multi.o
-g_hid-y				:= hid.o
-g_dbgp-y			:= dbgp.o
-g_nokia-y			:= nokia.o
-g_webcam-y			:= webcam.o
-g_ncm-y				:= ncm.o
-g_acm_ms-y			:= acm_ms.o
-g_tcm_usb_gadget-y		:= tcm_usb_gadget.o
-
-obj-$(CONFIG_USB_ZERO)		+= g_zero.o
-obj-$(CONFIG_USB_AUDIO)		+= g_audio.o
-obj-$(CONFIG_USB_ETH)		+= g_ether.o
-obj-$(CONFIG_USB_GADGETFS)	+= gadgetfs.o
-obj-$(CONFIG_USB_FUNCTIONFS)	+= g_ffs.o
-obj-$(CONFIG_USB_MASS_STORAGE)	+= g_mass_storage.o
-obj-$(CONFIG_USB_G_SERIAL)	+= g_serial.o
-obj-$(CONFIG_USB_G_PRINTER)	+= g_printer.o
-obj-$(CONFIG_USB_MIDI_GADGET)	+= g_midi.o
-obj-$(CONFIG_USB_CDC_COMPOSITE) += g_cdc.o
-obj-$(CONFIG_USB_G_HID)		+= g_hid.o
-obj-$(CONFIG_USB_G_DBGP)	+= g_dbgp.o
-obj-$(CONFIG_USB_G_MULTI)	+= g_multi.o
-obj-$(CONFIG_USB_G_NOKIA)	+= g_nokia.o
-obj-$(CONFIG_USB_G_WEBCAM)	+= g_webcam.o
-obj-$(CONFIG_USB_G_NCM)		+= g_ncm.o
-obj-$(CONFIG_USB_G_ACM_MS)	+= g_acm_ms.o
-obj-$(CONFIG_USB_GADGET_TARGET)	+= tcm_usb_gadget.o
+obj-$(CONFIG_USB_GADGET)	+= udc/ function/ legacy/

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

@@ -1956,6 +1956,7 @@ void composite_dev_cleanup(struct usb_composite_dev *cdev)
 	}
 	if (cdev->req) {
 		kfree(cdev->req->buf);
+		usb_ep_dequeue(cdev->gadget->ep0, cdev->req);
 		usb_ep_free_request(cdev->gadget->ep0, cdev->req);
 	}
 	cdev->next_string_id = 0;

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

@@ -1021,12 +1021,10 @@ static ssize_t ext_prop_data_store(struct usb_os_desc_ext_prop *ext_prop,
 
 	if (page[len - 1] == '\n' || page[len - 1] == '\0')
 		--len;
-	new_data = kzalloc(len, GFP_KERNEL);
+	new_data = kmemdup(page, len, GFP_KERNEL);
 	if (!new_data)
 		return -ENOMEM;
 
-	memcpy(new_data, page, len);
-
 	if (desc->opts_mutex)
 		mutex_lock(desc->opts_mutex);
 	kfree(ext_prop->data);

+ 34 - 0
drivers/usb/gadget/function/Makefile

@@ -0,0 +1,34 @@
+#
+# USB peripheral controller drivers
+#
+
+ccflags-y			:= -I$(PWD)/drivers/usb/gadget/
+ccflags-y			+= -I$(PWD)/drivers/usb/gadget/udc/
+
+# USB Functions
+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
+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
+obj-$(CONFIG_USB_U_ETHER)	+= u_ether.o
+usb_f_ncm-y			:= f_ncm.o
+obj-$(CONFIG_USB_F_NCM)		+= usb_f_ncm.o
+usb_f_ecm-y			:= f_ecm.o
+obj-$(CONFIG_USB_F_ECM)		+= usb_f_ecm.o
+usb_f_phonet-y			:= f_phonet.o
+obj-$(CONFIG_USB_F_PHONET)	+= usb_f_phonet.o
+usb_f_eem-y			:= f_eem.o
+obj-$(CONFIG_USB_F_EEM)		+= usb_f_eem.o
+usb_f_ecm_subset-y		:= f_subset.o
+obj-$(CONFIG_USB_F_SUBSET)	+= usb_f_ecm_subset.o
+usb_f_rndis-y			:= f_rndis.o rndis.o
+obj-$(CONFIG_USB_F_RNDIS)	+= usb_f_rndis.o
+usb_f_mass_storage-y		:= f_mass_storage.o storage_common.o
+obj-$(CONFIG_USB_F_MASS_STORAGE)+= usb_f_mass_storage.o
+usb_f_fs-y			:= f_fs.o
+obj-$(CONFIG_USB_F_FS)		+= usb_f_fs.o

+ 0 - 0
drivers/usb/gadget/f_acm.c → drivers/usb/gadget/function/f_acm.c


+ 0 - 0
drivers/usb/gadget/f_ecm.c → drivers/usb/gadget/function/f_ecm.c


+ 10 - 12
drivers/usb/gadget/f_eem.c → drivers/usb/gadget/function/f_eem.c

@@ -355,20 +355,18 @@ static struct sk_buff *eem_wrap(struct gether *port, struct sk_buff *skb)
 	int		padlen = 0;
 	u16		len = skb->len;
 
-	if (!skb_cloned(skb)) {
-		int headroom = skb_headroom(skb);
-		int tailroom = skb_tailroom(skb);
+	int headroom = skb_headroom(skb);
+	int tailroom = skb_tailroom(skb);
 
-		/* When (len + EEM_HLEN + ETH_FCS_LEN) % in->maxpacket) is 0,
-		 * stick two bytes of zero-length EEM packet on the end.
-		 */
-		if (((len + EEM_HLEN + ETH_FCS_LEN) % in->maxpacket) == 0)
-			padlen += 2;
+	/* When (len + EEM_HLEN + ETH_FCS_LEN) % in->maxpacket) is 0,
+	 * stick two bytes of zero-length EEM packet on the end.
+	 */
+	if (((len + EEM_HLEN + ETH_FCS_LEN) % in->maxpacket) == 0)
+		padlen += 2;
 
-		if ((tailroom >= (ETH_FCS_LEN + padlen)) &&
-				(headroom >= EEM_HLEN))
-			goto done;
-	}
+	if ((tailroom >= (ETH_FCS_LEN + padlen)) &&
+			(headroom >= EEM_HLEN) && !skb_cloned(skb))
+		goto done;
 
 	skb2 = skb_copy_expand(skb, EEM_HLEN, ETH_FCS_LEN + padlen, GFP_ATOMIC);
 	dev_kfree_skb_any(skb);

+ 339 - 13
drivers/usb/gadget/f_fs.c → drivers/usb/gadget/function/f_fs.c

@@ -34,6 +34,7 @@
 
 #include "u_fs.h"
 #include "u_f.h"
+#include "u_os_desc.h"
 #include "configfs.h"
 
 #define FUNCTIONFS_MAGIC	0xa647361 /* Chosen by a honest dice roll ;) */
@@ -1646,13 +1647,22 @@ enum ffs_entity_type {
 	FFS_DESCRIPTOR, FFS_INTERFACE, FFS_STRING, FFS_ENDPOINT
 };
 
+enum ffs_os_desc_type {
+	FFS_OS_DESC, FFS_OS_DESC_EXT_COMPAT, FFS_OS_DESC_EXT_PROP
+};
+
 typedef int (*ffs_entity_callback)(enum ffs_entity_type entity,
 				   u8 *valuep,
 				   struct usb_descriptor_header *desc,
 				   void *priv);
 
-static int __must_check ffs_do_desc(char *data, unsigned len,
-				    ffs_entity_callback entity, void *priv)
+typedef int (*ffs_os_desc_callback)(enum ffs_os_desc_type entity,
+				    struct usb_os_desc_header *h, void *data,
+				    unsigned len, void *priv);
+
+static int __must_check ffs_do_single_desc(char *data, unsigned len,
+					   ffs_entity_callback entity,
+					   void *priv)
 {
 	struct usb_descriptor_header *_ds = (void *)data;
 	u8 length;
@@ -1804,7 +1814,7 @@ static int __must_check ffs_do_descs(unsigned count, char *data, unsigned len,
 		if (!data)
 			return _len - len;
 
-		ret = ffs_do_desc(data, len, entity, priv);
+		ret = ffs_do_single_desc(data, len, entity, priv);
 		if (unlikely(ret < 0)) {
 			pr_debug("%s returns %d\n", __func__, ret);
 			return ret;
@@ -1857,11 +1867,191 @@ static int __ffs_data_do_entity(enum ffs_entity_type type,
 	return 0;
 }
 
+static int __ffs_do_os_desc_header(enum ffs_os_desc_type *next_type,
+				   struct usb_os_desc_header *desc)
+{
+	u16 bcd_version = le16_to_cpu(desc->bcdVersion);
+	u16 w_index = le16_to_cpu(desc->wIndex);
+
+	if (bcd_version != 1) {
+		pr_vdebug("unsupported os descriptors version: %d",
+			  bcd_version);
+		return -EINVAL;
+	}
+	switch (w_index) {
+	case 0x4:
+		*next_type = FFS_OS_DESC_EXT_COMPAT;
+		break;
+	case 0x5:
+		*next_type = FFS_OS_DESC_EXT_PROP;
+		break;
+	default:
+		pr_vdebug("unsupported os descriptor type: %d", w_index);
+		return -EINVAL;
+	}
+
+	return sizeof(*desc);
+}
+
+/*
+ * Process all extended compatibility/extended property descriptors
+ * of a feature descriptor
+ */
+static int __must_check ffs_do_single_os_desc(char *data, unsigned len,
+					      enum ffs_os_desc_type type,
+					      u16 feature_count,
+					      ffs_os_desc_callback entity,
+					      void *priv,
+					      struct usb_os_desc_header *h)
+{
+	int ret;
+	const unsigned _len = len;
+
+	ENTER();
+
+	/* loop over all ext compat/ext prop descriptors */
+	while (feature_count--) {
+		ret = entity(type, h, data, len, priv);
+		if (unlikely(ret < 0)) {
+			pr_debug("bad OS descriptor, type: %d\n", type);
+			return ret;
+		}
+		data += ret;
+		len -= ret;
+	}
+	return _len - len;
+}
+
+/* Process a number of complete Feature Descriptors (Ext Compat or Ext Prop) */
+static int __must_check ffs_do_os_descs(unsigned count,
+					char *data, unsigned len,
+					ffs_os_desc_callback entity, void *priv)
+{
+	const unsigned _len = len;
+	unsigned long num = 0;
+
+	ENTER();
+
+	for (num = 0; num < count; ++num) {
+		int ret;
+		enum ffs_os_desc_type type;
+		u16 feature_count;
+		struct usb_os_desc_header *desc = (void *)data;
+
+		if (len < sizeof(*desc))
+			return -EINVAL;
+
+		/*
+		 * Record "descriptor" entity.
+		 * Process dwLength, bcdVersion, wIndex, get b/wCount.
+		 * Move the data pointer to the beginning of extended
+		 * compatibilities proper or extended properties proper
+		 * portions of the data
+		 */
+		if (le32_to_cpu(desc->dwLength) > len)
+			return -EINVAL;
+
+		ret = __ffs_do_os_desc_header(&type, desc);
+		if (unlikely(ret < 0)) {
+			pr_debug("entity OS_DESCRIPTOR(%02lx); ret = %d\n",
+				 num, ret);
+			return ret;
+		}
+		/*
+		 * 16-bit hex "?? 00" Little Endian looks like 8-bit hex "??"
+		 */
+		feature_count = le16_to_cpu(desc->wCount);
+		if (type == FFS_OS_DESC_EXT_COMPAT &&
+		    (feature_count > 255 || desc->Reserved))
+				return -EINVAL;
+		len -= ret;
+		data += ret;
+
+		/*
+		 * Process all function/property descriptors
+		 * of this Feature Descriptor
+		 */
+		ret = ffs_do_single_os_desc(data, len, type,
+					    feature_count, entity, priv, desc);
+		if (unlikely(ret < 0)) {
+			pr_debug("%s returns %d\n", __func__, ret);
+			return ret;
+		}
+
+		len -= ret;
+		data += ret;
+	}
+	return _len - len;
+}
+
+/**
+ * Validate contents of the buffer from userspace related to OS descriptors.
+ */
+static int __ffs_data_do_os_desc(enum ffs_os_desc_type type,
+				 struct usb_os_desc_header *h, void *data,
+				 unsigned len, void *priv)
+{
+	struct ffs_data *ffs = priv;
+	u8 length;
+
+	ENTER();
+
+	switch (type) {
+	case FFS_OS_DESC_EXT_COMPAT: {
+		struct usb_ext_compat_desc *d = data;
+		int i;
+
+		if (len < sizeof(*d) ||
+		    d->bFirstInterfaceNumber >= ffs->interfaces_count ||
+		    d->Reserved1)
+			return -EINVAL;
+		for (i = 0; i < ARRAY_SIZE(d->Reserved2); ++i)
+			if (d->Reserved2[i])
+				return -EINVAL;
+
+		length = sizeof(struct usb_ext_compat_desc);
+	}
+		break;
+	case FFS_OS_DESC_EXT_PROP: {
+		struct usb_ext_prop_desc *d = data;
+		u32 type, pdl;
+		u16 pnl;
+
+		if (len < sizeof(*d) || h->interface >= ffs->interfaces_count)
+			return -EINVAL;
+		length = le32_to_cpu(d->dwSize);
+		type = le32_to_cpu(d->dwPropertyDataType);
+		if (type < USB_EXT_PROP_UNICODE ||
+		    type > USB_EXT_PROP_UNICODE_MULTI) {
+			pr_vdebug("unsupported os descriptor property type: %d",
+				  type);
+			return -EINVAL;
+		}
+		pnl = le16_to_cpu(d->wPropertyNameLength);
+		pdl = le32_to_cpu(*(u32 *)((u8 *)data + 10 + pnl));
+		if (length != 14 + pnl + pdl) {
+			pr_vdebug("invalid os descriptor length: %d pnl:%d pdl:%d (descriptor %d)\n",
+				  length, pnl, pdl, type);
+			return -EINVAL;
+		}
+		++ffs->ms_os_descs_ext_prop_count;
+		/* property name reported to the host as "WCHAR"s */
+		ffs->ms_os_descs_ext_prop_name_len += pnl * 2;
+		ffs->ms_os_descs_ext_prop_data_len += pdl;
+	}
+		break;
+	default:
+		pr_vdebug("unknown descriptor: %d\n", type);
+		return -EINVAL;
+	}
+	return length;
+}
+
 static int __ffs_data_got_descs(struct ffs_data *ffs,
 				char *const _data, size_t len)
 {
 	char *data = _data, *raw_descs;
-	unsigned counts[3], flags;
+	unsigned os_descs_count = 0, counts[3], flags;
 	int ret = -EINVAL, i;
 
 	ENTER();
@@ -1879,7 +2069,8 @@ static int __ffs_data_got_descs(struct ffs_data *ffs,
 		flags = get_unaligned_le32(data + 8);
 		if (flags & ~(FUNCTIONFS_HAS_FS_DESC |
 			      FUNCTIONFS_HAS_HS_DESC |
-			      FUNCTIONFS_HAS_SS_DESC)) {
+			      FUNCTIONFS_HAS_SS_DESC |
+			      FUNCTIONFS_HAS_MS_OS_DESC)) {
 			ret = -ENOSYS;
 			goto error;
 		}
@@ -1902,6 +2093,11 @@ static int __ffs_data_got_descs(struct ffs_data *ffs,
 			len  -= 4;
 		}
 	}
+	if (flags & (1 << i)) {
+		os_descs_count = get_unaligned_le32(data);
+		data += 4;
+		len -= 4;
+	};
 
 	/* Read descriptors */
 	raw_descs = data;
@@ -1915,6 +2111,14 @@ static int __ffs_data_got_descs(struct ffs_data *ffs,
 		data += ret;
 		len  -= ret;
 	}
+	if (os_descs_count) {
+		ret = ffs_do_os_descs(os_descs_count, data, len,
+				      __ffs_data_do_os_desc, ffs);
+		if (ret < 0)
+			goto error;
+		data += ret;
+		len -= ret;
+	}
 
 	if (raw_descs == data || len) {
 		ret = -EINVAL;
@@ -1927,6 +2131,7 @@ static int __ffs_data_got_descs(struct ffs_data *ffs,
 	ffs->fs_descs_count	= counts[0];
 	ffs->hs_descs_count	= counts[1];
 	ffs->ss_descs_count	= counts[2];
+	ffs->ms_os_descs_count	= os_descs_count;
 
 	return 0;
 
@@ -2268,6 +2473,85 @@ static int __ffs_func_bind_do_nums(enum ffs_entity_type type, u8 *valuep,
 	return 0;
 }
 
+static int __ffs_func_bind_do_os_desc(enum ffs_os_desc_type type,
+				      struct usb_os_desc_header *h, void *data,
+				      unsigned len, void *priv)
+{
+	struct ffs_function *func = priv;
+	u8 length = 0;
+
+	switch (type) {
+	case FFS_OS_DESC_EXT_COMPAT: {
+		struct usb_ext_compat_desc *desc = data;
+		struct usb_os_desc_table *t;
+
+		t = &func->function.os_desc_table[desc->bFirstInterfaceNumber];
+		t->if_id = func->interfaces_nums[desc->bFirstInterfaceNumber];
+		memcpy(t->os_desc->ext_compat_id, &desc->CompatibleID,
+		       ARRAY_SIZE(desc->CompatibleID) +
+		       ARRAY_SIZE(desc->SubCompatibleID));
+		length = sizeof(*desc);
+	}
+		break;
+	case FFS_OS_DESC_EXT_PROP: {
+		struct usb_ext_prop_desc *desc = data;
+		struct usb_os_desc_table *t;
+		struct usb_os_desc_ext_prop *ext_prop;
+		char *ext_prop_name;
+		char *ext_prop_data;
+
+		t = &func->function.os_desc_table[h->interface];
+		t->if_id = func->interfaces_nums[h->interface];
+
+		ext_prop = func->ffs->ms_os_descs_ext_prop_avail;
+		func->ffs->ms_os_descs_ext_prop_avail += sizeof(*ext_prop);
+
+		ext_prop->type = le32_to_cpu(desc->dwPropertyDataType);
+		ext_prop->name_len = le16_to_cpu(desc->wPropertyNameLength);
+		ext_prop->data_len = le32_to_cpu(*(u32 *)
+			usb_ext_prop_data_len_ptr(data, ext_prop->name_len));
+		length = ext_prop->name_len + ext_prop->data_len + 14;
+
+		ext_prop_name = func->ffs->ms_os_descs_ext_prop_name_avail;
+		func->ffs->ms_os_descs_ext_prop_name_avail +=
+			ext_prop->name_len;
+
+		ext_prop_data = func->ffs->ms_os_descs_ext_prop_data_avail;
+		func->ffs->ms_os_descs_ext_prop_data_avail +=
+			ext_prop->data_len;
+		memcpy(ext_prop_data,
+		       usb_ext_prop_data_ptr(data, ext_prop->name_len),
+		       ext_prop->data_len);
+		/* unicode data reported to the host as "WCHAR"s */
+		switch (ext_prop->type) {
+		case USB_EXT_PROP_UNICODE:
+		case USB_EXT_PROP_UNICODE_ENV:
+		case USB_EXT_PROP_UNICODE_LINK:
+		case USB_EXT_PROP_UNICODE_MULTI:
+			ext_prop->data_len *= 2;
+			break;
+		}
+		ext_prop->data = ext_prop_data;
+
+		memcpy(ext_prop_name, usb_ext_prop_name_ptr(data),
+		       ext_prop->name_len);
+		/* property name reported to the host as "WCHAR"s */
+		ext_prop->name_len *= 2;
+		ext_prop->name = ext_prop_name;
+
+		t->os_desc->ext_prop_len +=
+			ext_prop->name_len + ext_prop->data_len + 14;
+		++t->os_desc->ext_prop_count;
+		list_add_tail(&ext_prop->entry, &t->os_desc->ext_prop);
+	}
+		break;
+	default:
+		pr_vdebug("unknown descriptor: %d\n", type);
+	}
+
+	return length;
+}
+
 static inline struct f_fs_opts *ffs_do_functionfs_bind(struct usb_function *f,
 						struct usb_configuration *c)
 {
@@ -2329,7 +2613,7 @@ static int _ffs_func_bind(struct usb_configuration *c,
 	const int super = gadget_is_superspeed(func->gadget) &&
 		func->ffs->ss_descs_count;
 
-	int fs_len, hs_len, ret;
+	int fs_len, hs_len, ss_len, ret, i;
 
 	/* Make it a single chunk, less management later on */
 	vla_group(d);
@@ -2341,6 +2625,18 @@ static int _ffs_func_bind(struct usb_configuration *c,
 	vla_item_with_sz(d, struct usb_descriptor_header *, ss_descs,
 		super ? ffs->ss_descs_count + 1 : 0);
 	vla_item_with_sz(d, short, inums, ffs->interfaces_count);
+	vla_item_with_sz(d, struct usb_os_desc_table, os_desc_table,
+			 c->cdev->use_os_string ? ffs->interfaces_count : 0);
+	vla_item_with_sz(d, char[16], ext_compat,
+			 c->cdev->use_os_string ? ffs->interfaces_count : 0);
+	vla_item_with_sz(d, struct usb_os_desc, os_desc,
+			 c->cdev->use_os_string ? ffs->interfaces_count : 0);
+	vla_item_with_sz(d, struct usb_os_desc_ext_prop, ext_prop,
+			 ffs->ms_os_descs_ext_prop_count);
+	vla_item_with_sz(d, char, ext_prop_name,
+			 ffs->ms_os_descs_ext_prop_name_len);
+	vla_item_with_sz(d, char, ext_prop_data,
+			 ffs->ms_os_descs_ext_prop_data_len);
 	vla_item_with_sz(d, char, raw_descs, ffs->raw_descs_length);
 	char *vlabuf;
 
@@ -2351,12 +2647,16 @@ static int _ffs_func_bind(struct usb_configuration *c,
 		return -ENOTSUPP;
 
 	/* Allocate a single chunk, less management later on */
-	vlabuf = kmalloc(vla_group_size(d), GFP_KERNEL);
+	vlabuf = kzalloc(vla_group_size(d), GFP_KERNEL);
 	if (unlikely(!vlabuf))
 		return -ENOMEM;
 
-	/* Zero */
-	memset(vla_ptr(vlabuf, d, eps), 0, d_eps__sz);
+	ffs->ms_os_descs_ext_prop_avail = vla_ptr(vlabuf, d, ext_prop);
+	ffs->ms_os_descs_ext_prop_name_avail =
+		vla_ptr(vlabuf, d, ext_prop_name);
+	ffs->ms_os_descs_ext_prop_data_avail =
+		vla_ptr(vlabuf, d, ext_prop_data);
+
 	/* Copy descriptors  */
 	memcpy(vla_ptr(vlabuf, d, raw_descs), ffs->raw_descs,
 	       ffs->raw_descs_length);
@@ -2410,12 +2710,16 @@ static int _ffs_func_bind(struct usb_configuration *c,
 
 	if (likely(super)) {
 		func->function.ss_descriptors = vla_ptr(vlabuf, d, ss_descs);
-		ret = ffs_do_descs(ffs->ss_descs_count,
+		ss_len = ffs_do_descs(ffs->ss_descs_count,
 				vla_ptr(vlabuf, d, raw_descs) + fs_len + hs_len,
 				d_raw_descs__sz - fs_len - hs_len,
 				__ffs_func_bind_do_descs, func);
-		if (unlikely(ret < 0))
+		if (unlikely(ss_len < 0)) {
+			ret = ss_len;
 			goto error;
+		}
+	} else {
+		ss_len = 0;
 	}
 
 	/*
@@ -2431,6 +2735,28 @@ static int _ffs_func_bind(struct usb_configuration *c,
 	if (unlikely(ret < 0))
 		goto error;
 
+	func->function.os_desc_table = vla_ptr(vlabuf, d, os_desc_table);
+	if (c->cdev->use_os_string)
+		for (i = 0; i < ffs->interfaces_count; ++i) {
+			struct usb_os_desc *desc;
+
+			desc = func->function.os_desc_table[i].os_desc =
+				vla_ptr(vlabuf, d, os_desc) +
+				i * sizeof(struct usb_os_desc);
+			desc->ext_compat_id =
+				vla_ptr(vlabuf, d, ext_compat) + i * 16;
+			INIT_LIST_HEAD(&desc->ext_prop);
+		}
+	ret = ffs_do_os_descs(ffs->ms_os_descs_count,
+			      vla_ptr(vlabuf, d, raw_descs) +
+			      fs_len + hs_len + ss_len,
+			      d_raw_descs__sz - fs_len - hs_len - ss_len,
+			      __ffs_func_bind_do_os_desc, func);
+	if (unlikely(ret < 0))
+		goto error;
+	func->function.os_desc_n =
+		c->cdev->use_os_string ? ffs->interfaces_count : 0;
+
 	/* And we're done */
 	ffs_event_add(ffs, FUNCTIONFS_BIND);
 	return 0;
@@ -2901,12 +3227,12 @@ static void *ffs_acquire_dev(const char *dev_name)
 
 	ffs_dev = _ffs_find_dev(dev_name);
 	if (!ffs_dev)
-		ffs_dev = ERR_PTR(-ENODEV);
+		ffs_dev = ERR_PTR(-ENOENT);
 	else if (ffs_dev->mounted)
 		ffs_dev = ERR_PTR(-EBUSY);
 	else if (ffs_dev->ffs_acquire_dev_callback &&
 	    ffs_dev->ffs_acquire_dev_callback(ffs_dev))
-		ffs_dev = ERR_PTR(-ENODEV);
+		ffs_dev = ERR_PTR(-ENOENT);
 	else
 		ffs_dev->mounted = true;
 

+ 0 - 0
drivers/usb/gadget/f_hid.c → drivers/usb/gadget/function/f_hid.c


+ 0 - 0
drivers/usb/gadget/f_loopback.c → drivers/usb/gadget/function/f_loopback.c


+ 0 - 0
drivers/usb/gadget/f_mass_storage.c → drivers/usb/gadget/function/f_mass_storage.c


+ 0 - 0
drivers/usb/gadget/f_mass_storage.h → drivers/usb/gadget/function/f_mass_storage.h


+ 0 - 0
drivers/usb/gadget/f_midi.c → drivers/usb/gadget/function/f_midi.c


+ 332 - 148
drivers/usb/gadget/f_ncm.c → drivers/usb/gadget/function/f_ncm.c

@@ -68,6 +68,18 @@ struct f_ncm {
 	 * callback and ethernet open/close
 	 */
 	spinlock_t			lock;
+
+	struct net_device		*netdev;
+
+	/* For multi-frame NDP TX */
+	struct sk_buff			*skb_tx_data;
+	struct sk_buff			*skb_tx_ndp;
+	u16				ndp_dgram_count;
+	bool				timer_force_tx;
+	struct tasklet_struct		tx_tasklet;
+	struct hrtimer			task_timer;
+
+	bool				timer_stopping;
 };
 
 static inline struct f_ncm *func_to_ncm(struct usb_function *f)
@@ -92,15 +104,20 @@ static inline unsigned ncm_bitrate(struct usb_gadget *g)
  * If the host can group frames, allow it to do that, 16K is selected,
  * because it's used by default by the current linux host driver
  */
-#define NTB_DEFAULT_IN_SIZE	USB_CDC_NCM_NTB_MIN_IN_SIZE
+#define NTB_DEFAULT_IN_SIZE	16384
 #define NTB_OUT_SIZE		16384
 
-/*
- * skbs of size less than that will not be aligned
- * to NCM's dwNtbInMaxSize to save bus bandwidth
+/* Allocation for storing the NDP, 32 should suffice for a
+ * 16k packet. This allows a maximum of 32 * 507 Byte packets to
+ * be transmitted in a single 16kB skb, though when sending full size
+ * packets this limit will be plenty.
+ * Smaller packets are not likely to be trying to maximize the
+ * throughput and will be mstly sending smaller infrequent frames.
  */
+#define TX_MAX_NUM_DPE		32
 
-#define	MAX_TX_NONFIXED		(512 * 3)
+/* Delay for the transmit to wait before sending an unfilled NTB frame. */
+#define TX_TIMEOUT_NSECS	300000
 
 #define FORMATS_SUPPORTED	(USB_CDC_NCM_NTB16_SUPPORTED |	\
 				 USB_CDC_NCM_NTB32_SUPPORTED)
@@ -355,14 +372,15 @@ struct ndp_parser_opts {
 	u32		ndp_sign;
 	unsigned	nth_size;
 	unsigned	ndp_size;
+	unsigned	dpe_size;
 	unsigned	ndplen_align;
 	/* sizes in u16 units */
 	unsigned	dgram_item_len; /* index or length */
 	unsigned	block_length;
-	unsigned	fp_index;
+	unsigned	ndp_index;
 	unsigned	reserved1;
 	unsigned	reserved2;
-	unsigned	next_fp_index;
+	unsigned	next_ndp_index;
 };
 
 #define INIT_NDP16_OPTS {					\
@@ -370,13 +388,14 @@ struct ndp_parser_opts {
 		.ndp_sign = USB_CDC_NCM_NDP16_NOCRC_SIGN,	\
 		.nth_size = sizeof(struct usb_cdc_ncm_nth16),	\
 		.ndp_size = sizeof(struct usb_cdc_ncm_ndp16),	\
+		.dpe_size = sizeof(struct usb_cdc_ncm_dpe16),	\
 		.ndplen_align = 4,				\
 		.dgram_item_len = 1,				\
 		.block_length = 1,				\
-		.fp_index = 1,					\
+		.ndp_index = 1,					\
 		.reserved1 = 0,					\
 		.reserved2 = 0,					\
-		.next_fp_index = 1,				\
+		.next_ndp_index = 1,				\
 	}
 
 
@@ -385,13 +404,14 @@ struct ndp_parser_opts {
 		.ndp_sign = USB_CDC_NCM_NDP32_NOCRC_SIGN,	\
 		.nth_size = sizeof(struct usb_cdc_ncm_nth32),	\
 		.ndp_size = sizeof(struct usb_cdc_ncm_ndp32),	\
+		.dpe_size = sizeof(struct usb_cdc_ncm_dpe32),	\
 		.ndplen_align = 8,				\
 		.dgram_item_len = 2,				\
 		.block_length = 2,				\
-		.fp_index = 2,					\
+		.ndp_index = 2,					\
 		.reserved1 = 1,					\
 		.reserved2 = 2,					\
-		.next_fp_index = 2,				\
+		.next_ndp_index = 2,				\
 	}
 
 static const struct ndp_parser_opts ndp16_opts = INIT_NDP16_OPTS;
@@ -803,6 +823,8 @@ static int ncm_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
 
 		if (ncm->port.in_ep->driver_data) {
 			DBG(cdev, "reset ncm\n");
+			ncm->timer_stopping = true;
+			ncm->netdev = NULL;
 			gether_disconnect(&ncm->port);
 			ncm_reset_values(ncm);
 		}
@@ -839,6 +861,8 @@ static int ncm_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
 			net = gether_connect(&ncm->port);
 			if (IS_ERR(net))
 				return PTR_ERR(net);
+			ncm->netdev = net;
+			ncm->timer_stopping = false;
 		}
 
 		spin_lock(&ncm->lock);
@@ -865,95 +889,232 @@ static int ncm_get_alt(struct usb_function *f, unsigned intf)
 	return ncm->port.in_ep->driver_data ? 1 : 0;
 }
 
+static struct sk_buff *package_for_tx(struct f_ncm *ncm)
+{
+	__le16		*ntb_iter;
+	struct sk_buff	*skb2 = NULL;
+	unsigned	ndp_pad;
+	unsigned	ndp_index;
+	unsigned	new_len;
+
+	const struct ndp_parser_opts *opts = ncm->parser_opts;
+	const int ndp_align = le16_to_cpu(ntb_parameters.wNdpInAlignment);
+	const int dgram_idx_len = 2 * 2 * opts->dgram_item_len;
+
+	/* Stop the timer */
+	hrtimer_try_to_cancel(&ncm->task_timer);
+
+	ndp_pad = ALIGN(ncm->skb_tx_data->len, ndp_align) -
+			ncm->skb_tx_data->len;
+	ndp_index = ncm->skb_tx_data->len + ndp_pad;
+	new_len = ndp_index + dgram_idx_len + ncm->skb_tx_ndp->len;
+
+	/* Set the final BlockLength and wNdpIndex */
+	ntb_iter = (void *) ncm->skb_tx_data->data;
+	/* Increment pointer to BlockLength */
+	ntb_iter += 2 + 1 + 1;
+	put_ncm(&ntb_iter, opts->block_length, new_len);
+	put_ncm(&ntb_iter, opts->ndp_index, ndp_index);
+
+	/* Set the final NDP wLength */
+	new_len = opts->ndp_size +
+			(ncm->ndp_dgram_count * dgram_idx_len);
+	ncm->ndp_dgram_count = 0;
+	/* Increment from start to wLength */
+	ntb_iter = (void *) ncm->skb_tx_ndp->data;
+	ntb_iter += 2;
+	put_unaligned_le16(new_len, ntb_iter);
+
+	/* Merge the skbs */
+	swap(skb2, ncm->skb_tx_data);
+	if (ncm->skb_tx_data) {
+		dev_kfree_skb_any(ncm->skb_tx_data);
+		ncm->skb_tx_data = NULL;
+	}
+
+	/* Insert NDP alignment. */
+	ntb_iter = (void *) skb_put(skb2, ndp_pad);
+	memset(ntb_iter, 0, ndp_pad);
+
+	/* Copy NTB across. */
+	ntb_iter = (void *) skb_put(skb2, ncm->skb_tx_ndp->len);
+	memcpy(ntb_iter, ncm->skb_tx_ndp->data, ncm->skb_tx_ndp->len);
+	dev_kfree_skb_any(ncm->skb_tx_ndp);
+	ncm->skb_tx_ndp = NULL;
+
+	/* Insert zero'd datagram. */
+	ntb_iter = (void *) skb_put(skb2, dgram_idx_len);
+	memset(ntb_iter, 0, dgram_idx_len);
+
+	return skb2;
+}
+
 static struct sk_buff *ncm_wrap_ntb(struct gether *port,
 				    struct sk_buff *skb)
 {
 	struct f_ncm	*ncm = func_to_ncm(&port->func);
-	struct sk_buff	*skb2;
+	struct sk_buff	*skb2 = NULL;
 	int		ncb_len = 0;
-	__le16		*tmp;
-	int		div;
-	int		rem;
-	int		pad;
-	int		ndp_align;
-	int		ndp_pad;
+	__le16		*ntb_data;
+	__le16		*ntb_ndp;
+	int		dgram_pad;
+
 	unsigned	max_size = ncm->port.fixed_in_len;
 	const struct ndp_parser_opts *opts = ncm->parser_opts;
-	unsigned	crc_len = ncm->is_crc ? sizeof(uint32_t) : 0;
-
-	div = le16_to_cpu(ntb_parameters.wNdpInDivisor);
-	rem = le16_to_cpu(ntb_parameters.wNdpInPayloadRemainder);
-	ndp_align = le16_to_cpu(ntb_parameters.wNdpInAlignment);
+	const int ndp_align = le16_to_cpu(ntb_parameters.wNdpInAlignment);
+	const int div = le16_to_cpu(ntb_parameters.wNdpInDivisor);
+	const int rem = le16_to_cpu(ntb_parameters.wNdpInPayloadRemainder);
+	const int dgram_idx_len = 2 * 2 * opts->dgram_item_len;
 
-	ncb_len += opts->nth_size;
-	ndp_pad = ALIGN(ncb_len, ndp_align) - ncb_len;
-	ncb_len += ndp_pad;
-	ncb_len += opts->ndp_size;
-	ncb_len += 2 * 2 * opts->dgram_item_len; /* Datagram entry */
-	ncb_len += 2 * 2 * opts->dgram_item_len; /* Zero datagram entry */
-	pad = ALIGN(ncb_len, div) + rem - ncb_len;
-	ncb_len += pad;
-
-	if (ncb_len + skb->len + crc_len > max_size) {
-		dev_kfree_skb_any(skb);
+	if (!skb && !ncm->skb_tx_data)
 		return NULL;
-	}
 
-	skb2 = skb_copy_expand(skb, ncb_len,
-			       max_size - skb->len - ncb_len - crc_len,
-			       GFP_ATOMIC);
-	dev_kfree_skb_any(skb);
-	if (!skb2)
-		return NULL;
+	if (skb) {
+		/* Add the CRC if required up front */
+		if (ncm->is_crc) {
+			uint32_t	crc;
+			__le16		*crc_pos;
+
+			crc = ~crc32_le(~0,
+					skb->data,
+					skb->len);
+			crc_pos = (void *) skb_put(skb, sizeof(uint32_t));
+			put_unaligned_le32(crc, crc_pos);
+		}
 
-	skb = skb2;
+		/* If the new skb is too big for the current NCM NTB then
+		 * set the current stored skb to be sent now and clear it
+		 * ready for new data.
+		 * NOTE: Assume maximum align for speed of calculation.
+		 */
+		if (ncm->skb_tx_data
+		    && (ncm->ndp_dgram_count >= TX_MAX_NUM_DPE
+		    || (ncm->skb_tx_data->len +
+		    div + rem + skb->len +
+		    ncm->skb_tx_ndp->len + ndp_align + (2 * dgram_idx_len))
+		    > max_size)) {
+			skb2 = package_for_tx(ncm);
+			if (!skb2)
+				goto err;
+		}
 
-	tmp = (void *) skb_push(skb, ncb_len);
-	memset(tmp, 0, ncb_len);
+		if (!ncm->skb_tx_data) {
+			ncb_len = opts->nth_size;
+			dgram_pad = ALIGN(ncb_len, div) + rem - ncb_len;
+			ncb_len += dgram_pad;
 
-	put_unaligned_le32(opts->nth_sign, tmp); /* dwSignature */
-	tmp += 2;
-	/* wHeaderLength */
-	put_unaligned_le16(opts->nth_size, tmp++);
-	tmp++; /* skip wSequence */
-	put_ncm(&tmp, opts->block_length, skb->len); /* (d)wBlockLength */
-	/* (d)wFpIndex */
-	/* the first pointer is right after the NTH + align */
-	put_ncm(&tmp, opts->fp_index, opts->nth_size + ndp_pad);
+			/* Create a new skb for the NTH and datagrams. */
+			ncm->skb_tx_data = alloc_skb(max_size, GFP_ATOMIC);
+			if (!ncm->skb_tx_data)
+				goto err;
 
-	tmp = (void *)tmp + ndp_pad;
+			ntb_data = (void *) skb_put(ncm->skb_tx_data, ncb_len);
+			memset(ntb_data, 0, ncb_len);
+			/* dwSignature */
+			put_unaligned_le32(opts->nth_sign, ntb_data);
+			ntb_data += 2;
+			/* wHeaderLength */
+			put_unaligned_le16(opts->nth_size, ntb_data++);
+
+			/* Allocate an skb for storing the NDP,
+			 * TX_MAX_NUM_DPE should easily suffice for a
+			 * 16k packet.
+			 */
+			ncm->skb_tx_ndp = alloc_skb((int)(opts->ndp_size
+						    + opts->dpe_size
+						    * TX_MAX_NUM_DPE),
+						    GFP_ATOMIC);
+			if (!ncm->skb_tx_ndp)
+				goto err;
+			ntb_ndp = (void *) skb_put(ncm->skb_tx_ndp,
+						    opts->ndp_size);
+			memset(ntb_ndp, 0, ncb_len);
+			/* dwSignature */
+			put_unaligned_le32(ncm->ndp_sign, ntb_ndp);
+			ntb_ndp += 2;
 
-	/* NDP */
-	put_unaligned_le32(ncm->ndp_sign, tmp); /* dwSignature */
-	tmp += 2;
-	/* wLength */
-	put_unaligned_le16(ncb_len - opts->nth_size - pad, tmp++);
+			/* There is always a zeroed entry */
+			ncm->ndp_dgram_count = 1;
 
-	tmp += opts->reserved1;
-	tmp += opts->next_fp_index; /* skip reserved (d)wNextFpIndex */
-	tmp += opts->reserved2;
+			/* Note: we skip opts->next_ndp_index */
+		}
 
-	if (ncm->is_crc) {
-		uint32_t crc;
+		/* Delay the timer. */
+		hrtimer_start(&ncm->task_timer,
+			      ktime_set(0, TX_TIMEOUT_NSECS),
+			      HRTIMER_MODE_REL);
+
+		/* Add the datagram position entries */
+		ntb_ndp = (void *) skb_put(ncm->skb_tx_ndp, dgram_idx_len);
+		memset(ntb_ndp, 0, dgram_idx_len);
+
+		ncb_len = ncm->skb_tx_data->len;
+		dgram_pad = ALIGN(ncb_len, div) + rem - ncb_len;
+		ncb_len += dgram_pad;
+
+		/* (d)wDatagramIndex */
+		put_ncm(&ntb_ndp, opts->dgram_item_len, ncb_len);
+		/* (d)wDatagramLength */
+		put_ncm(&ntb_ndp, opts->dgram_item_len, skb->len);
+		ncm->ndp_dgram_count++;
+
+		/* Add the new data to the skb */
+		ntb_data = (void *) skb_put(ncm->skb_tx_data, dgram_pad);
+		memset(ntb_data, 0, dgram_pad);
+		ntb_data = (void *) skb_put(ncm->skb_tx_data, skb->len);
+		memcpy(ntb_data, skb->data, skb->len);
+		dev_kfree_skb_any(skb);
+		skb = NULL;
 
-		crc = ~crc32_le(~0,
-				skb->data + ncb_len,
-				skb->len - ncb_len);
-		put_unaligned_le32(crc, skb->data + skb->len);
-		skb_put(skb, crc_len);
+	} else if (ncm->skb_tx_data && ncm->timer_force_tx) {
+		/* If the tx was requested because of a timeout then send */
+		skb2 = package_for_tx(ncm);
+		if (!skb2)
+			goto err;
 	}
 
-	/* (d)wDatagramIndex[0] */
-	put_ncm(&tmp, opts->dgram_item_len, ncb_len);
-	/* (d)wDatagramLength[0] */
-	put_ncm(&tmp, opts->dgram_item_len, skb->len - ncb_len);
-	/* (d)wDatagramIndex[1] and  (d)wDatagramLength[1] already zeroed */
+	return skb2;
 
-	if (skb->len > MAX_TX_NONFIXED)
-		memset(skb_put(skb, max_size - skb->len),
-		       0, max_size - skb->len);
+err:
+	ncm->netdev->stats.tx_dropped++;
+
+	if (skb)
+		dev_kfree_skb_any(skb);
+	if (ncm->skb_tx_data)
+		dev_kfree_skb_any(ncm->skb_tx_data);
+	if (ncm->skb_tx_ndp)
+		dev_kfree_skb_any(ncm->skb_tx_ndp);
 
-	return skb;
+	return NULL;
+}
+
+/*
+ * This transmits the NTB if there are frames waiting.
+ */
+static void ncm_tx_tasklet(unsigned long data)
+{
+	struct f_ncm	*ncm = (void *)data;
+
+	if (ncm->timer_stopping)
+		return;
+
+	/* Only send if data is available. */
+	if (ncm->skb_tx_data) {
+		ncm->timer_force_tx = true;
+		ncm->netdev->netdev_ops->ndo_start_xmit(NULL, ncm->netdev);
+		ncm->timer_force_tx = false;
+	}
+}
+
+/*
+ * The transmit should only be run if no skb data has been sent
+ * for a certain duration.
+ */
+static enum hrtimer_restart ncm_tx_timeout(struct hrtimer *data)
+{
+	struct f_ncm *ncm = container_of(data, struct f_ncm, task_timer);
+	tasklet_schedule(&ncm->tx_tasklet);
+	return HRTIMER_NORESTART;
 }
 
 static int ncm_unwrap_ntb(struct gether *port,
@@ -963,6 +1124,7 @@ static int ncm_unwrap_ntb(struct gether *port,
 	struct f_ncm	*ncm = func_to_ncm(&port->func);
 	__le16		*tmp = (void *) skb->data;
 	unsigned	index, index2;
+	int		ndp_index;
 	unsigned	dg_len, dg_len2;
 	unsigned	ndp_len;
 	struct sk_buff	*skb2;
@@ -995,91 +1157,101 @@ static int ncm_unwrap_ntb(struct gether *port,
 		goto err;
 	}
 
-	index = get_ncm(&tmp, opts->fp_index);
-	/* NCM 3.2 */
-	if (((index % 4) != 0) && (index < opts->nth_size)) {
-		INFO(port->func.config->cdev, "Bad index: %x\n",
-			index);
-		goto err;
-	}
-
-	/* walk through NDP */
-	tmp = ((void *)skb->data) + index;
-	if (get_unaligned_le32(tmp) != ncm->ndp_sign) {
-		INFO(port->func.config->cdev, "Wrong NDP SIGN\n");
-		goto err;
-	}
-	tmp += 2;
-
-	ndp_len = get_unaligned_le16(tmp++);
-	/*
-	 * NCM 3.3.1
-	 * entry is 2 items
-	 * item size is 16/32 bits, opts->dgram_item_len * 2 bytes
-	 * minimal: struct usb_cdc_ncm_ndpX + normal entry + zero entry
-	 */
-	if ((ndp_len < opts->ndp_size + 2 * 2 * (opts->dgram_item_len * 2))
-	    || (ndp_len % opts->ndplen_align != 0)) {
-		INFO(port->func.config->cdev, "Bad NDP length: %x\n", ndp_len);
-		goto err;
-	}
-	tmp += opts->reserved1;
-	tmp += opts->next_fp_index; /* skip reserved (d)wNextFpIndex */
-	tmp += opts->reserved2;
-
-	ndp_len -= opts->ndp_size;
-	index2 = get_ncm(&tmp, opts->dgram_item_len);
-	dg_len2 = get_ncm(&tmp, opts->dgram_item_len);
-	dgram_counter = 0;
+	ndp_index = get_ncm(&tmp, opts->ndp_index);
 
+	/* Run through all the NDP's in the NTB */
 	do {
-		index = index2;
-		dg_len = dg_len2;
-		if (dg_len < 14 + crc_len) { /* ethernet header + crc */
-			INFO(port->func.config->cdev, "Bad dgram length: %x\n",
-			     dg_len);
+		/* NCM 3.2 */
+		if (((ndp_index % 4) != 0) &&
+				(ndp_index < opts->nth_size)) {
+			INFO(port->func.config->cdev, "Bad index: %#X\n",
+			     ndp_index);
 			goto err;
 		}
-		if (ncm->is_crc) {
-			uint32_t crc, crc2;
-
-			crc = get_unaligned_le32(skb->data +
-						 index + dg_len - crc_len);
-			crc2 = ~crc32_le(~0,
-					 skb->data + index,
-					 dg_len - crc_len);
-			if (crc != crc2) {
-				INFO(port->func.config->cdev, "Bad CRC\n");
-				goto err;
-			}
+
+		/* walk through NDP */
+		tmp = (void *)(skb->data + ndp_index);
+		if (get_unaligned_le32(tmp) != ncm->ndp_sign) {
+			INFO(port->func.config->cdev, "Wrong NDP SIGN\n");
+			goto err;
 		}
+		tmp += 2;
 
+		ndp_len = get_unaligned_le16(tmp++);
+		/*
+		 * NCM 3.3.1
+		 * entry is 2 items
+		 * item size is 16/32 bits, opts->dgram_item_len * 2 bytes
+		 * minimal: struct usb_cdc_ncm_ndpX + normal entry + zero entry
+		 * Each entry is a dgram index and a dgram length.
+		 */
+		if ((ndp_len < opts->ndp_size
+				+ 2 * 2 * (opts->dgram_item_len * 2))
+				|| (ndp_len % opts->ndplen_align != 0)) {
+			INFO(port->func.config->cdev, "Bad NDP length: %#X\n",
+			     ndp_len);
+			goto err;
+		}
+		tmp += opts->reserved1;
+		/* Check for another NDP (d)wNextNdpIndex */
+		ndp_index = get_ncm(&tmp, opts->next_ndp_index);
+		tmp += opts->reserved2;
+
+		ndp_len -= opts->ndp_size;
 		index2 = get_ncm(&tmp, opts->dgram_item_len);
 		dg_len2 = get_ncm(&tmp, opts->dgram_item_len);
+		dgram_counter = 0;
+
+		do {
+			index = index2;
+			dg_len = dg_len2;
+			if (dg_len < 14 + crc_len) { /* ethernet hdr + crc */
+				INFO(port->func.config->cdev,
+				     "Bad dgram length: %#X\n", dg_len);
+				goto err;
+			}
+			if (ncm->is_crc) {
+				uint32_t crc, crc2;
+
+				crc = get_unaligned_le32(skb->data +
+							 index + dg_len -
+							 crc_len);
+				crc2 = ~crc32_le(~0,
+						 skb->data + index,
+						 dg_len - crc_len);
+				if (crc != crc2) {
+					INFO(port->func.config->cdev,
+					     "Bad CRC\n");
+					goto err;
+				}
+			}
+
+			index2 = get_ncm(&tmp, opts->dgram_item_len);
+			dg_len2 = get_ncm(&tmp, opts->dgram_item_len);
 
-		if (index2 == 0 || dg_len2 == 0) {
-			skb2 = skb;
-		} else {
-			skb2 = skb_clone(skb, GFP_ATOMIC);
+			/*
+			 * Copy the data into a new skb.
+			 * This ensures the truesize is correct
+			 */
+			skb2 = netdev_alloc_skb_ip_align(ncm->netdev,
+							 dg_len - crc_len);
 			if (skb2 == NULL)
 				goto err;
-		}
+			memcpy(skb_put(skb2, dg_len - crc_len),
+			       skb->data + index, dg_len - crc_len);
 
-		if (!skb_pull(skb2, index)) {
-			ret = -EOVERFLOW;
-			goto err;
-		}
+			skb_queue_tail(list, skb2);
 
-		skb_trim(skb2, dg_len - crc_len);
-		skb_queue_tail(list, skb2);
+			ndp_len -= 2 * (opts->dgram_item_len * 2);
 
-		ndp_len -= 2 * (opts->dgram_item_len * 2);
+			dgram_counter++;
 
-		dgram_counter++;
+			if (index2 == 0 || dg_len2 == 0)
+				break;
+		} while (ndp_len > 2 * (opts->dgram_item_len * 2));
+	} while (ndp_index);
 
-		if (index2 == 0 || dg_len2 == 0)
-			break;
-	} while (ndp_len > 2 * (opts->dgram_item_len * 2)); /* zero entry */
+	dev_kfree_skb_any(skb);
 
 	VDBG(port->func.config->cdev,
 	     "Parsed NTB with %d frames\n", dgram_counter);
@@ -1097,8 +1269,11 @@ static void ncm_disable(struct usb_function *f)
 
 	DBG(cdev, "ncm deactivated\n");
 
-	if (ncm->port.in_ep->driver_data)
+	if (ncm->port.in_ep->driver_data) {
+		ncm->timer_stopping = true;
+		ncm->netdev = NULL;
 		gether_disconnect(&ncm->port);
+	}
 
 	if (ncm->notify->driver_data) {
 		usb_ep_disable(ncm->notify);
@@ -1267,6 +1442,10 @@ static int ncm_bind(struct usb_configuration *c, struct usb_function *f)
 	ncm->port.open = ncm_open;
 	ncm->port.close = ncm_close;
 
+	tasklet_init(&ncm->tx_tasklet, ncm_tx_tasklet, (unsigned long) ncm);
+	hrtimer_init(&ncm->task_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+	ncm->task_timer.function = ncm_tx_timeout;
+
 	DBG(cdev, "CDC Network: %s speed IN/%s OUT/%s NOTIFY/%s\n",
 			gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
 			ncm->port.in_ep->name, ncm->port.out_ep->name,
@@ -1380,6 +1559,10 @@ static void ncm_unbind(struct usb_configuration *c, struct usb_function *f)
 
 	DBG(c->cdev, "ncm unbind\n");
 
+	hrtimer_cancel(&ncm->task_timer);
+	tasklet_kill(&ncm->tx_tasklet);
+
+	ncm_string_defs[0].id = 0;
 	usb_free_all_descriptors(f);
 
 	kfree(ncm->notify_req->buf);
@@ -1416,6 +1599,7 @@ static struct usb_function *ncm_alloc(struct usb_function_instance *fi)
 	ncm->port.ioport = netdev_priv(opts->net);
 	mutex_unlock(&opts->lock);
 	ncm->port.is_fixed = true;
+	ncm->port.supports_multi_frame = true;
 
 	ncm->port.func.name = "cdc_network";
 	/* descriptors are per-instance copies */

+ 0 - 0
drivers/usb/gadget/f_obex.c → drivers/usb/gadget/function/f_obex.c


+ 0 - 0
drivers/usb/gadget/f_phonet.c → drivers/usb/gadget/function/f_phonet.c


+ 4 - 0
drivers/usb/gadget/f_rndis.c → drivers/usb/gadget/function/f_rndis.c

@@ -727,6 +727,10 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f)
 	rndis_control_intf.bInterfaceNumber = status;
 	rndis_union_desc.bMasterInterface0 = status;
 
+	if (cdev->use_os_string)
+		f->os_desc_table[0].if_id =
+			rndis_iad_descriptor.bFirstInterface;
+
 	status = usb_interface_id(c, f);
 	if (status < 0)
 		goto fail;

+ 0 - 0
drivers/usb/gadget/f_serial.c → drivers/usb/gadget/function/f_serial.c


+ 0 - 0
drivers/usb/gadget/f_sourcesink.c → drivers/usb/gadget/function/f_sourcesink.c


+ 0 - 0
drivers/usb/gadget/f_subset.c → drivers/usb/gadget/function/f_subset.c


+ 0 - 0
drivers/usb/gadget/f_uac1.c → drivers/usb/gadget/function/f_uac1.c


+ 22 - 2
drivers/usb/gadget/f_uac2.c → drivers/usb/gadget/function/f_uac2.c

@@ -348,14 +348,34 @@ static int uac2_pcm_open(struct snd_pcm_substream *substream)
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
 		spin_lock_init(&uac2->p_prm.lock);
 		runtime->hw.rate_min = p_srate;
-		runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE; /* ! p_ssize ! */
+		switch (p_ssize) {
+		case 3:
+			runtime->hw.formats = SNDRV_PCM_FMTBIT_S24_3LE;
+			break;
+		case 4:
+			runtime->hw.formats = SNDRV_PCM_FMTBIT_S32_LE;
+			break;
+		default:
+			runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE;
+			break;
+		}
 		runtime->hw.channels_min = num_channels(p_chmask);
 		runtime->hw.period_bytes_min = 2 * uac2->p_prm.max_psize
 						/ runtime->hw.periods_min;
 	} else {
 		spin_lock_init(&uac2->c_prm.lock);
 		runtime->hw.rate_min = c_srate;
-		runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE; /* ! c_ssize ! */
+		switch (c_ssize) {
+		case 3:
+			runtime->hw.formats = SNDRV_PCM_FMTBIT_S24_3LE;
+			break;
+		case 4:
+			runtime->hw.formats = SNDRV_PCM_FMTBIT_S32_LE;
+			break;
+		default:
+			runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE;
+			break;
+		}
 		runtime->hw.channels_min = num_channels(c_chmask);
 		runtime->hw.period_bytes_min = 2 * uac2->c_prm.max_psize
 						/ runtime->hw.periods_min;

+ 0 - 0
drivers/usb/gadget/f_uvc.c → drivers/usb/gadget/function/f_uvc.c


+ 0 - 0
drivers/usb/gadget/f_uvc.h → drivers/usb/gadget/function/f_uvc.h


+ 0 - 0
drivers/usb/gadget/g_zero.h → drivers/usb/gadget/function/g_zero.h


+ 0 - 0
drivers/usb/gadget/ndis.h → drivers/usb/gadget/function/ndis.h


+ 0 - 0
drivers/usb/gadget/rndis.c → drivers/usb/gadget/function/rndis.c


+ 0 - 0
drivers/usb/gadget/rndis.h → drivers/usb/gadget/function/rndis.h


+ 0 - 0
drivers/usb/gadget/storage_common.c → drivers/usb/gadget/function/storage_common.c


+ 0 - 0
drivers/usb/gadget/storage_common.h → drivers/usb/gadget/function/storage_common.h


+ 0 - 0
drivers/usb/gadget/u_ecm.h → drivers/usb/gadget/function/u_ecm.h


+ 0 - 0
drivers/usb/gadget/u_eem.h → drivers/usb/gadget/function/u_eem.h


+ 13 - 6
drivers/usb/gadget/u_ether.c → drivers/usb/gadget/function/u_ether.c

@@ -483,7 +483,7 @@ static netdev_tx_t eth_start_xmit(struct sk_buff *skb,
 					struct net_device *net)
 {
 	struct eth_dev		*dev = netdev_priv(net);
-	int			length = skb->len;
+	int			length = 0;
 	int			retval;
 	struct usb_request	*req = NULL;
 	unsigned long		flags;
@@ -500,13 +500,13 @@ static netdev_tx_t eth_start_xmit(struct sk_buff *skb,
 	}
 	spin_unlock_irqrestore(&dev->lock, flags);
 
-	if (!in) {
+	if (skb && !in) {
 		dev_kfree_skb_any(skb);
 		return NETDEV_TX_OK;
 	}
 
 	/* apply outgoing CDC or RNDIS filters */
-	if (!is_promisc(cdc_filter)) {
+	if (skb && !is_promisc(cdc_filter)) {
 		u8		*dest = skb->data;
 
 		if (is_multicast_ether_addr(dest)) {
@@ -557,11 +557,17 @@ static netdev_tx_t eth_start_xmit(struct sk_buff *skb,
 		if (dev->port_usb)
 			skb = dev->wrap(dev->port_usb, skb);
 		spin_unlock_irqrestore(&dev->lock, flags);
-		if (!skb)
+		if (!skb) {
+			/* Multi frame CDC protocols may store the frame for
+			 * later which is not a dropped frame.
+			 */
+			if (dev->port_usb->supports_multi_frame)
+				goto multiframe;
 			goto drop;
-
-		length = skb->len;
+		}
 	}
+
+	length = skb->len;
 	req->buf = skb->data;
 	req->context = skb;
 	req->complete = tx_complete;
@@ -604,6 +610,7 @@ static netdev_tx_t eth_start_xmit(struct sk_buff *skb,
 		dev_kfree_skb_any(skb);
 drop:
 		dev->net->stats.tx_dropped++;
+multiframe:
 		spin_lock_irqsave(&dev->req_lock, flags);
 		if (list_empty(&dev->tx_reqs))
 			netif_start_queue(net);

+ 2 - 0
drivers/usb/gadget/u_ether.h → drivers/usb/gadget/function/u_ether.h

@@ -18,6 +18,7 @@
 #include <linux/if_ether.h>
 #include <linux/usb/composite.h>
 #include <linux/usb/cdc.h>
+#include <linux/netdevice.h>
 
 #include "gadget_chips.h"
 
@@ -74,6 +75,7 @@ struct gether {
 	bool				is_fixed;
 	u32				fixed_out_len;
 	u32				fixed_in_len;
+	bool				supports_multi_frame;
 	struct sk_buff			*(*wrap)(struct gether *port,
 						struct sk_buff *skb);
 	int				(*unwrap)(struct gether *port,

+ 0 - 0
drivers/usb/gadget/u_ether_configfs.h → drivers/usb/gadget/function/u_ether_configfs.h


+ 7 - 0
drivers/usb/gadget/u_fs.h → drivers/usb/gadget/function/u_fs.h

@@ -216,6 +216,13 @@ struct ffs_data {
 	unsigned			fs_descs_count;
 	unsigned			hs_descs_count;
 	unsigned			ss_descs_count;
+	unsigned			ms_os_descs_count;
+	unsigned			ms_os_descs_ext_prop_count;
+	unsigned			ms_os_descs_ext_prop_name_len;
+	unsigned			ms_os_descs_ext_prop_data_len;
+	void				*ms_os_descs_ext_prop_avail;
+	void				*ms_os_descs_ext_prop_name_avail;
+	void				*ms_os_descs_ext_prop_data_avail;
 
 	unsigned short			strings_count;
 	unsigned short			interfaces_count;

+ 0 - 0
drivers/usb/gadget/u_gether.h → drivers/usb/gadget/function/u_gether.h


+ 0 - 0
drivers/usb/gadget/u_ncm.h → drivers/usb/gadget/function/u_ncm.h


+ 0 - 0
drivers/usb/gadget/u_phonet.h → drivers/usb/gadget/function/u_phonet.h


+ 0 - 0
drivers/usb/gadget/u_rndis.h → drivers/usb/gadget/function/u_rndis.h


+ 0 - 0
drivers/usb/gadget/u_serial.c → drivers/usb/gadget/function/u_serial.c


+ 0 - 0
drivers/usb/gadget/u_serial.h → drivers/usb/gadget/function/u_serial.h


+ 0 - 0
drivers/usb/gadget/u_uac1.c → drivers/usb/gadget/function/u_uac1.c


+ 0 - 0
drivers/usb/gadget/u_uac1.h → drivers/usb/gadget/function/u_uac1.h


+ 0 - 0
drivers/usb/gadget/uvc.h → drivers/usb/gadget/function/uvc.h


+ 0 - 0
drivers/usb/gadget/uvc_queue.c → drivers/usb/gadget/function/uvc_queue.c


+ 0 - 0
drivers/usb/gadget/uvc_queue.h → drivers/usb/gadget/function/uvc_queue.h


+ 0 - 0
drivers/usb/gadget/uvc_v4l2.c → drivers/usb/gadget/function/uvc_v4l2.c


+ 0 - 0
drivers/usb/gadget/uvc_video.c → drivers/usb/gadget/function/uvc_video.c


+ 475 - 0
drivers/usb/gadget/legacy/Kconfig

@@ -0,0 +1,475 @@
+#
+# USB Gadget support on a system involves
+#    (a) a peripheral controller, and
+#    (b) the gadget driver using it.
+#
+# NOTE:  Gadget support ** DOES NOT ** depend on host-side CONFIG_USB !!
+#
+#  - Host systems (like PCs) need CONFIG_USB (with "A" jacks).
+#  - Peripherals (like PDAs) need CONFIG_USB_GADGET (with "B" jacks).
+#  - Some systems have both kinds of controllers.
+#
+# With help from a special transceiver and a "Mini-AB" jack, systems with
+# both kinds of controller can also support "USB On-the-Go" (CONFIG_USB_OTG).
+#
+
+config USB_ZERO
+	tristate "Gadget Zero (DEVELOPMENT)"
+	select USB_LIBCOMPOSITE
+	select USB_F_SS_LB
+	help
+	  Gadget Zero is a two-configuration device.  It either sinks and
+	  sources bulk data; or it loops back a configurable number of
+	  transfers.  It also implements control requests, for "chapter 9"
+	  conformance.  The driver needs only two bulk-capable endpoints, so
+	  it can work on top of most device-side usb controllers.  It's
+	  useful for testing, and is also a working example showing how
+	  USB "gadget drivers" can be written.
+
+	  Make this be the first driver you try using on top of any new
+	  USB peripheral controller driver.  Then you can use host-side
+	  test software, like the "usbtest" driver, to put your hardware
+	  and its driver through a basic set of functional tests.
+
+	  Gadget Zero also works with the host-side "usb-skeleton" driver,
+	  and with many kinds of host-side test software.  You may need
+	  to tweak product and vendor IDs before host software knows about
+	  this device, and arrange to select an appropriate configuration.
+
+	  Say "y" to link the driver statically, or "m" to build a
+	  dynamically linked module called "g_zero".
+
+config USB_ZERO_HNPTEST
+	boolean "HNP Test Device"
+	depends on USB_ZERO && USB_OTG
+	help
+	  You can configure this device to enumerate using the device
+	  identifiers of the USB-OTG test device.  That means that when
+	  this gadget connects to another OTG device, with this one using
+	  the "B-Peripheral" role, that device will use HNP to let this
+	  one serve as the USB host instead (in the "B-Host" role).
+
+config USB_AUDIO
+	tristate "Audio Gadget"
+	depends on SND
+	select USB_LIBCOMPOSITE
+	select SND_PCM
+	help
+	  This Gadget Audio driver is compatible with USB Audio Class
+	  specification 2.0. It implements 1 AudioControl interface,
+	  1 AudioStreaming Interface each for USB-OUT and USB-IN.
+	  Number of channels, sample rate and sample size can be
+	  specified as module parameters.
+	  This driver doesn't expect any real Audio codec to be present
+	  on the device - the audio streams are simply sinked to and
+	  sourced from a virtual ALSA sound card created. The user-space
+	  application may choose to do whatever it wants with the data
+	  received from the USB Host and choose to provide whatever it
+	  wants as audio data to the USB Host.
+
+	  Say "y" to link the driver statically, or "m" to build a
+	  dynamically linked module called "g_audio".
+
+config GADGET_UAC1
+	bool "UAC 1.0 (Legacy)"
+	depends on USB_AUDIO
+	help
+	  If you instead want older UAC Spec-1.0 driver that also has audio
+	  paths hardwired to the Audio codec chip on-board and doesn't work
+	  without one.
+
+config USB_ETH
+	tristate "Ethernet Gadget (with CDC Ethernet support)"
+	depends on NET
+	select USB_LIBCOMPOSITE
+	select USB_U_ETHER
+	select USB_F_ECM
+	select USB_F_SUBSET
+	select CRC32
+	help
+	  This driver implements Ethernet style communication, in one of
+	  several ways:
+
+	   - The "Communication Device Class" (CDC) Ethernet Control Model.
+	     That protocol is often avoided with pure Ethernet adapters, in
+	     favor of simpler vendor-specific hardware, but is widely
+	     supported by firmware for smart network devices.
+
+	   - On hardware can't implement that protocol, a simple CDC subset
+	     is used, placing fewer demands on USB.
+
+	   - CDC Ethernet Emulation Model (EEM) is a newer standard that has
+	     a simpler interface that can be used by more USB hardware.
+
+	  RNDIS support is an additional option, more demanding than than
+	  subset.
+
+	  Within the USB device, this gadget driver exposes a network device
+	  "usbX", where X depends on what other networking devices you have.
+	  Treat it like a two-node Ethernet link:  host, and gadget.
+
+	  The Linux-USB host-side "usbnet" driver interoperates with this
+	  driver, so that deep I/O queues can be supported.  On 2.4 kernels,
+	  use "CDCEther" instead, if you're using the CDC option. That CDC
+	  mode should also interoperate with standard CDC Ethernet class
+	  drivers on other host operating systems.
+
+	  Say "y" to link the driver statically, or "m" to build a
+	  dynamically linked module called "g_ether".
+
+config USB_ETH_RNDIS
+	bool "RNDIS support"
+	depends on USB_ETH
+	select USB_LIBCOMPOSITE
+	select USB_F_RNDIS
+	default y
+	help
+	   Microsoft Windows XP bundles the "Remote NDIS" (RNDIS) protocol,
+	   and Microsoft provides redistributable binary RNDIS drivers for
+	   older versions of Windows.
+
+	   If you say "y" here, the Ethernet gadget driver will try to provide
+	   a second device configuration, supporting RNDIS to talk to such
+	   Microsoft USB hosts.
+
+	   To make MS-Windows work with this, use Documentation/usb/linux.inf
+	   as the "driver info file".  For versions of MS-Windows older than
+	   XP, you'll need to download drivers from Microsoft's website; a URL
+	   is given in comments found in that info file.
+
+config USB_ETH_EEM
+       bool "Ethernet Emulation Model (EEM) support"
+       depends on USB_ETH
+	select USB_LIBCOMPOSITE
+	select USB_F_EEM
+       default n
+       help
+         CDC EEM is a newer USB standard that is somewhat simpler than CDC ECM
+         and therefore can be supported by more hardware.  Technically ECM and
+         EEM are designed for different applications.  The ECM model extends
+         the network interface to the target (e.g. a USB cable modem), and the
+         EEM model is for mobile devices to communicate with hosts using
+         ethernet over USB.  For Linux gadgets, however, the interface with
+         the host is the same (a usbX device), so the differences are minimal.
+
+         If you say "y" here, the Ethernet gadget driver will use the EEM
+         protocol rather than ECM.  If unsure, say "n".
+
+config USB_G_NCM
+	tristate "Network Control Model (NCM) support"
+	depends on NET
+	select USB_LIBCOMPOSITE
+	select USB_U_ETHER
+	select USB_F_NCM
+	select CRC32
+	help
+	  This driver implements USB CDC NCM subclass standard. NCM is
+	  an advanced protocol for Ethernet encapsulation, allows grouping
+	  of several ethernet frames into one USB transfer and different
+	  alignment possibilities.
+
+	  Say "y" to link the driver statically, or "m" to build a
+	  dynamically linked module called "g_ncm".
+
+config USB_GADGETFS
+	tristate "Gadget Filesystem"
+	help
+	  This driver provides a filesystem based API that lets user mode
+	  programs implement a single-configuration USB device, including
+	  endpoint I/O and control requests that don't relate to enumeration.
+	  All endpoints, transfer speeds, and transfer types supported by
+	  the hardware are available, through read() and write() calls.
+
+	  Say "y" to link the driver statically, or "m" to build a
+	  dynamically linked module called "gadgetfs".
+
+config USB_FUNCTIONFS
+	tristate "Function Filesystem"
+	select USB_LIBCOMPOSITE
+	select USB_F_FS
+	select USB_FUNCTIONFS_GENERIC if !(USB_FUNCTIONFS_ETH || USB_FUNCTIONFS_RNDIS)
+	help
+	  The Function Filesystem (FunctionFS) lets one create USB
+	  composite functions in user space in the same way GadgetFS
+	  lets one create USB gadgets in user space.  This allows creation
+	  of composite gadgets such that some of the functions are
+	  implemented in kernel space (for instance Ethernet, serial or
+	  mass storage) and other are implemented in user space.
+
+	  If you say "y" or "m" here you will be able what kind of
+	  configurations the gadget will provide.
+
+	  Say "y" to link the driver statically, or "m" to build
+	  a dynamically linked module called "g_ffs".
+
+config USB_FUNCTIONFS_ETH
+	bool "Include configuration with CDC ECM (Ethernet)"
+	depends on USB_FUNCTIONFS && NET
+	select USB_U_ETHER
+	select USB_F_ECM
+	select USB_F_SUBSET
+	help
+	  Include a configuration with CDC ECM function (Ethernet) and the
+	  Function Filesystem.
+
+config USB_FUNCTIONFS_RNDIS
+	bool "Include configuration with RNDIS (Ethernet)"
+	depends on USB_FUNCTIONFS && NET
+	select USB_U_ETHER
+	select USB_F_RNDIS
+	help
+	  Include a configuration with RNDIS function (Ethernet) and the Filesystem.
+
+config USB_FUNCTIONFS_GENERIC
+	bool "Include 'pure' configuration"
+	depends on USB_FUNCTIONFS
+	help
+	  Include a configuration with the Function Filesystem alone with
+	  no Ethernet interface.
+
+config USB_MASS_STORAGE
+	tristate "Mass Storage Gadget"
+	depends on BLOCK
+	select USB_LIBCOMPOSITE
+	select USB_F_MASS_STORAGE
+	help
+	  The Mass Storage Gadget acts as a USB Mass Storage disk drive.
+	  As its storage repository it can use a regular file or a block
+	  device (in much the same way as the "loop" device driver),
+	  specified as a module parameter or sysfs option.
+
+	  This driver is a replacement for now removed File-backed
+	  Storage Gadget (g_file_storage).
+
+	  Say "y" to link the driver statically, or "m" to build
+	  a dynamically linked module called "g_mass_storage".
+
+config USB_GADGET_TARGET
+	tristate "USB Gadget Target Fabric Module"
+	depends on TARGET_CORE
+	select USB_LIBCOMPOSITE
+	help
+	  This fabric is an USB gadget. Two USB protocols are supported that is
+	  BBB or BOT (Bulk Only Transport) and UAS (USB Attached SCSI). BOT is
+	  advertised on alternative interface 0 (primary) and UAS is on
+	  alternative interface 1. Both protocols can work on USB2.0 and USB3.0.
+	  UAS utilizes the USB 3.0 feature called streams support.
+
+config USB_G_SERIAL
+	tristate "Serial Gadget (with CDC ACM and CDC OBEX support)"
+	depends on TTY
+	select USB_U_SERIAL
+	select USB_F_ACM
+	select USB_F_SERIAL
+	select USB_F_OBEX
+	select USB_LIBCOMPOSITE
+	help
+	  The Serial Gadget talks to the Linux-USB generic serial driver.
+	  This driver supports a CDC-ACM module option, which can be used
+	  to interoperate with MS-Windows hosts or with the Linux-USB
+	  "cdc-acm" driver.
+
+	  This driver also supports a CDC-OBEX option.  You will need a
+	  user space OBEX server talking to /dev/ttyGS*, since the kernel
+	  itself doesn't implement the OBEX protocol.
+
+	  Say "y" to link the driver statically, or "m" to build a
+	  dynamically linked module called "g_serial".
+
+	  For more information, see Documentation/usb/gadget_serial.txt
+	  which includes instructions and a "driver info file" needed to
+	  make MS-Windows work with CDC ACM.
+
+config USB_MIDI_GADGET
+	tristate "MIDI Gadget"
+	depends on SND
+	select USB_LIBCOMPOSITE
+	select SND_RAWMIDI
+	help
+	  The MIDI Gadget acts as a USB Audio device, with one MIDI
+	  input and one MIDI output. These MIDI jacks appear as
+	  a sound "card" in the ALSA sound system. Other MIDI
+	  connections can then be made on the gadget system, using
+	  ALSA's aconnect utility etc.
+
+	  Say "y" to link the driver statically, or "m" to build a
+	  dynamically linked module called "g_midi".
+
+config USB_G_PRINTER
+	tristate "Printer Gadget"
+	select USB_LIBCOMPOSITE
+	help
+	  The Printer Gadget channels data between the USB host and a
+	  userspace program driving the print engine. The user space
+	  program reads and writes the device file /dev/g_printer to
+	  receive or send printer data. It can use ioctl calls to
+	  the device file to get or set printer status.
+
+	  Say "y" to link the driver statically, or "m" to build a
+	  dynamically linked module called "g_printer".
+
+	  For more information, see Documentation/usb/gadget_printer.txt
+	  which includes sample code for accessing the device file.
+
+if TTY
+
+config USB_CDC_COMPOSITE
+	tristate "CDC Composite Device (Ethernet and ACM)"
+	depends on NET
+	select USB_LIBCOMPOSITE
+	select USB_U_SERIAL
+	select USB_U_ETHER
+	select USB_F_ACM
+	select USB_F_ECM
+	help
+	  This driver provides two functions in one configuration:
+	  a CDC Ethernet (ECM) link, and a CDC ACM (serial port) link.
+
+	  This driver requires four bulk and two interrupt endpoints,
+	  plus the ability to handle altsettings.  Not all peripheral
+	  controllers are that capable.
+
+	  Say "y" to link the driver statically, or "m" to build a
+	  dynamically linked module.
+
+config USB_G_NOKIA
+	tristate "Nokia composite gadget"
+	depends on PHONET
+	select USB_LIBCOMPOSITE
+	select USB_U_SERIAL
+	select USB_U_ETHER
+	select USB_F_ACM
+	select USB_F_OBEX
+	select USB_F_PHONET
+	select USB_F_ECM
+	help
+	  The Nokia composite gadget provides support for acm, obex
+	  and phonet in only one composite gadget driver.
+
+	  It's only really useful for N900 hardware. If you're building
+	  a kernel for N900, say Y or M here. If unsure, say N.
+
+config USB_G_ACM_MS
+	tristate "CDC Composite Device (ACM and mass storage)"
+	depends on BLOCK
+	select USB_LIBCOMPOSITE
+	select USB_U_SERIAL
+	select USB_F_ACM
+	select USB_F_MASS_STORAGE
+	help
+	  This driver provides two functions in one configuration:
+	  a mass storage, and a CDC ACM (serial port) link.
+
+	  Say "y" to link the driver statically, or "m" to build a
+	  dynamically linked module called "g_acm_ms".
+
+config USB_G_MULTI
+	tristate "Multifunction Composite Gadget"
+	depends on BLOCK && NET
+	select USB_G_MULTI_CDC if !USB_G_MULTI_RNDIS
+	select USB_LIBCOMPOSITE
+	select USB_U_SERIAL
+	select USB_U_ETHER
+	select USB_F_ACM
+	select USB_F_MASS_STORAGE
+	help
+	  The Multifunction Composite Gadget provides Ethernet (RNDIS
+	  and/or CDC Ethernet), mass storage and ACM serial link
+	  interfaces.
+
+	  You will be asked to choose which of the two configurations is
+	  to be available in the gadget.  At least one configuration must
+	  be chosen to make the gadget usable.  Selecting more than one
+	  configuration will prevent Windows from automatically detecting
+	  the gadget as a composite gadget, so an INF file will be needed to
+	  use the gadget.
+
+	  Say "y" to link the driver statically, or "m" to build a
+	  dynamically linked module called "g_multi".
+
+config USB_G_MULTI_RNDIS
+	bool "RNDIS + CDC Serial + Storage configuration"
+	depends on USB_G_MULTI
+	select USB_F_RNDIS
+	default y
+	help
+	  This option enables a configuration with RNDIS, CDC Serial and
+	  Mass Storage functions available in the Multifunction Composite
+	  Gadget.  This is the configuration dedicated for Windows since RNDIS
+	  is Microsoft's protocol.
+
+	  If unsure, say "y".
+
+config USB_G_MULTI_CDC
+	bool "CDC Ethernet + CDC Serial + Storage configuration"
+	depends on USB_G_MULTI
+	default n
+	select USB_F_ECM
+	help
+	  This option enables a configuration with CDC Ethernet (ECM), CDC
+	  Serial and Mass Storage functions available in the Multifunction
+	  Composite Gadget.
+
+	  If unsure, say "y".
+
+endif # TTY
+
+config USB_G_HID
+	tristate "HID Gadget"
+	select USB_LIBCOMPOSITE
+	help
+	  The HID gadget driver provides generic emulation of USB
+	  Human Interface Devices (HID).
+
+	  For more information, see Documentation/usb/gadget_hid.txt which
+	  includes sample code for accessing the device files.
+
+	  Say "y" to link the driver statically, or "m" to build a
+	  dynamically linked module called "g_hid".
+
+# Standalone / single function gadgets
+config USB_G_DBGP
+	tristate "EHCI Debug Device Gadget"
+	depends on TTY
+	select USB_LIBCOMPOSITE
+	help
+	  This gadget emulates an EHCI Debug device. This is useful when you want
+	  to interact with an EHCI Debug Port.
+
+	  Say "y" to link the driver statically, or "m" to build a
+	  dynamically linked module called "g_dbgp".
+
+if USB_G_DBGP
+choice
+	prompt "EHCI Debug Device mode"
+	default USB_G_DBGP_SERIAL
+
+config USB_G_DBGP_PRINTK
+	depends on USB_G_DBGP
+	bool "printk"
+	help
+	  Directly printk() received data. No interaction.
+
+config USB_G_DBGP_SERIAL
+	depends on USB_G_DBGP
+	select USB_U_SERIAL
+	bool "serial"
+	help
+	  Userland can interact using /dev/ttyGSxxx.
+endchoice
+endif
+
+# put drivers that need isochronous transfer support (for audio
+# or video class gadget drivers), or specific hardware, here.
+config USB_G_WEBCAM
+	tristate "USB Webcam Gadget"
+	depends on VIDEO_DEV
+	select USB_LIBCOMPOSITE
+	select VIDEOBUF2_VMALLOC
+	help
+	  The Webcam Gadget acts as a composite USB Audio and Video Class
+	  device. It provides a userspace API to process UVC control requests
+	  and stream video data to the host.
+
+	  Say "y" to link the driver statically, or "m" to build a
+	  dynamically linked module called "g_webcam".

+ 44 - 0
drivers/usb/gadget/legacy/Makefile

@@ -0,0 +1,44 @@
+#
+# USB gadget drivers
+#
+
+ccflags-y			:= -I$(PWD)/drivers/usb/gadget/
+ccflags-y			+= -I$(PWD)/drivers/usb/gadget/udc/
+ccflags-y			+= -I$(PWD)/drivers/usb/gadget/function/
+
+g_zero-y			:= zero.o
+g_audio-y			:= audio.o
+g_ether-y			:= ether.o
+g_serial-y			:= serial.o
+g_midi-y			:= gmidi.o
+gadgetfs-y			:= inode.o
+g_mass_storage-y		:= mass_storage.o
+g_printer-y			:= printer.o
+g_cdc-y				:= cdc2.o
+g_multi-y			:= multi.o
+g_hid-y				:= hid.o
+g_dbgp-y			:= dbgp.o
+g_nokia-y			:= nokia.o
+g_webcam-y			:= webcam.o
+g_ncm-y				:= ncm.o
+g_acm_ms-y			:= acm_ms.o
+g_tcm_usb_gadget-y		:= tcm_usb_gadget.o
+
+obj-$(CONFIG_USB_ZERO)		+= g_zero.o
+obj-$(CONFIG_USB_AUDIO)		+= g_audio.o
+obj-$(CONFIG_USB_ETH)		+= g_ether.o
+obj-$(CONFIG_USB_GADGETFS)	+= gadgetfs.o
+obj-$(CONFIG_USB_FUNCTIONFS)	+= g_ffs.o
+obj-$(CONFIG_USB_MASS_STORAGE)	+= g_mass_storage.o
+obj-$(CONFIG_USB_G_SERIAL)	+= g_serial.o
+obj-$(CONFIG_USB_G_PRINTER)	+= g_printer.o
+obj-$(CONFIG_USB_MIDI_GADGET)	+= g_midi.o
+obj-$(CONFIG_USB_CDC_COMPOSITE) += g_cdc.o
+obj-$(CONFIG_USB_G_HID)		+= g_hid.o
+obj-$(CONFIG_USB_G_DBGP)	+= g_dbgp.o
+obj-$(CONFIG_USB_G_MULTI)	+= g_multi.o
+obj-$(CONFIG_USB_G_NOKIA)	+= g_nokia.o
+obj-$(CONFIG_USB_G_WEBCAM)	+= g_webcam.o
+obj-$(CONFIG_USB_G_NCM)		+= g_ncm.o
+obj-$(CONFIG_USB_G_ACM_MS)	+= g_acm_ms.o
+obj-$(CONFIG_USB_GADGET_TARGET)	+= tcm_usb_gadget.o

+ 2 - 12
drivers/usb/gadget/acm_ms.c → drivers/usb/gadget/legacy/acm_ms.c

@@ -267,18 +267,8 @@ static __refdata struct usb_composite_driver acm_ms_driver = {
 	.unbind		= __exit_p(acm_ms_unbind),
 };
 
+module_usb_composite_driver(acm_ms_driver);
+
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_AUTHOR("Klaus Schwarzkopf <schwarzkopf@sensortherm.de>");
 MODULE_LICENSE("GPL v2");
-
-static int __init init(void)
-{
-	return usb_composite_probe(&acm_ms_driver);
-}
-module_init(init);
-
-static void __exit cleanup(void)
-{
-	usb_composite_unregister(&acm_ms_driver);
-}
-module_exit(cleanup);

+ 1 - 11
drivers/usb/gadget/audio.c → drivers/usb/gadget/legacy/audio.c

@@ -172,17 +172,7 @@ static __refdata struct usb_composite_driver audio_driver = {
 	.unbind		= __exit_p(audio_unbind),
 };
 
-static int __init init(void)
-{
-	return usb_composite_probe(&audio_driver);
-}
-module_init(init);
-
-static void __exit cleanup(void)
-{
-	usb_composite_unregister(&audio_driver);
-}
-module_exit(cleanup);
+module_usb_composite_driver(audio_driver);
 
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_AUTHOR("Bryan Wu <cooloney@kernel.org>");

+ 2 - 12
drivers/usb/gadget/cdc2.c → drivers/usb/gadget/legacy/cdc2.c

@@ -231,18 +231,8 @@ static __refdata struct usb_composite_driver cdc_driver = {
 	.unbind		= __exit_p(cdc_unbind),
 };
 
+module_usb_composite_driver(cdc_driver);
+
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_AUTHOR("David Brownell");
 MODULE_LICENSE("GPL");
-
-static int __init init(void)
-{
-	return usb_composite_probe(&cdc_driver);
-}
-module_init(init);
-
-static void __exit cleanup(void)
-{
-	usb_composite_unregister(&cdc_driver);
-}
-module_exit(cleanup);

+ 0 - 0
drivers/usb/gadget/dbgp.c → drivers/usb/gadget/legacy/dbgp.c


+ 2 - 12
drivers/usb/gadget/ether.c → drivers/usb/gadget/legacy/ether.c

@@ -475,18 +475,8 @@ static __refdata struct usb_composite_driver eth_driver = {
 	.unbind		= __exit_p(eth_unbind),
 };
 
+module_usb_composite_driver(eth_driver);
+
 MODULE_DESCRIPTION(PREFIX DRIVER_DESC);
 MODULE_AUTHOR("David Brownell, Benedikt Spanger");
 MODULE_LICENSE("GPL");
-
-static int __init init(void)
-{
-	return usb_composite_probe(&eth_driver);
-}
-module_init(init);
-
-static void __exit cleanup(void)
-{
-	usb_composite_unregister(&eth_driver);
-}
-module_exit(cleanup);

+ 1 - 1
drivers/usb/gadget/g_ffs.c → drivers/usb/gadget/legacy/g_ffs.c

@@ -276,7 +276,7 @@ module_exit(gfs_exit);
 static void *functionfs_acquire_dev(struct ffs_dev *dev)
 {
 	if (!try_module_get(THIS_MODULE))
-		return ERR_PTR(-ENODEV);
+		return ERR_PTR(-ENOENT);
 	
 	return 0;
 }

+ 1 - 12
drivers/usb/gadget/gmidi.c → drivers/usb/gadget/legacy/gmidi.c

@@ -163,15 +163,4 @@ static __refdata struct usb_composite_driver midi_driver = {
 	.unbind		= __exit_p(midi_unbind),
 };
 
-static int __init midi_init(void)
-{
-	return usb_composite_probe(&midi_driver);
-}
-module_init(midi_init);
-
-static void __exit midi_cleanup(void)
-{
-	usb_composite_unregister(&midi_driver);
-}
-module_exit(midi_cleanup);
-
+module_usb_composite_driver(midi_driver);

+ 0 - 0
drivers/usb/gadget/hid.c → drivers/usb/gadget/legacy/hid.c


+ 0 - 0
drivers/usb/gadget/inode.c → drivers/usb/gadget/legacy/inode.c


+ 0 - 0
drivers/usb/gadget/mass_storage.c → drivers/usb/gadget/legacy/mass_storage.c


+ 1 - 12
drivers/usb/gadget/multi.c → drivers/usb/gadget/legacy/multi.c

@@ -507,15 +507,4 @@ static __refdata struct usb_composite_driver multi_driver = {
 	.needs_serial	= 1,
 };
 
-
-static int __init multi_init(void)
-{
-	return usb_composite_probe(&multi_driver);
-}
-module_init(multi_init);
-
-static void __exit multi_exit(void)
-{
-	usb_composite_unregister(&multi_driver);
-}
-module_exit(multi_exit);
+module_usb_composite_driver(multi_driver);

+ 2 - 12
drivers/usb/gadget/ncm.c → drivers/usb/gadget/legacy/ncm.c

@@ -204,18 +204,8 @@ static __refdata struct usb_composite_driver ncm_driver = {
 	.unbind		= __exit_p(gncm_unbind),
 };
 
+module_usb_composite_driver(ncm_driver);
+
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_AUTHOR("Yauheni Kaliuta");
 MODULE_LICENSE("GPL");
-
-static int __init init(void)
-{
-	return usb_composite_probe(&ncm_driver);
-}
-module_init(init);
-
-static void __exit cleanup(void)
-{
-	usb_composite_unregister(&ncm_driver);
-}
-module_exit(cleanup);

+ 1 - 11
drivers/usb/gadget/nokia.c → drivers/usb/gadget/legacy/nokia.c

@@ -347,14 +347,4 @@ static __refdata struct usb_composite_driver nokia_driver = {
 	.unbind		= __exit_p(nokia_unbind),
 };
 
-static int __init nokia_init(void)
-{
-	return usb_composite_probe(&nokia_driver);
-}
-module_init(nokia_init);
-
-static void __exit nokia_cleanup(void)
-{
-	usb_composite_unregister(&nokia_driver);
-}
-module_exit(nokia_cleanup);
+module_usb_composite_driver(nokia_driver);

+ 0 - 0
drivers/usb/gadget/printer.c → drivers/usb/gadget/legacy/printer.c


+ 0 - 0
drivers/usb/gadget/serial.c → drivers/usb/gadget/legacy/serial.c


+ 0 - 0
drivers/usb/gadget/tcm_usb_gadget.c → drivers/usb/gadget/legacy/tcm_usb_gadget.c


+ 0 - 0
drivers/usb/gadget/tcm_usb_gadget.h → drivers/usb/gadget/legacy/tcm_usb_gadget.h


+ 1 - 14
drivers/usb/gadget/webcam.c → drivers/usb/gadget/legacy/webcam.c

@@ -390,20 +390,7 @@ static __refdata struct usb_composite_driver webcam_driver = {
 	.unbind		= webcam_unbind,
 };
 
-static int __init
-webcam_init(void)
-{
-	return usb_composite_probe(&webcam_driver);
-}
-
-static void __exit
-webcam_cleanup(void)
-{
-	usb_composite_unregister(&webcam_driver);
-}
-
-module_init(webcam_init);
-module_exit(webcam_cleanup);
+module_usb_composite_driver(webcam_driver);
 
 MODULE_AUTHOR("Laurent Pinchart");
 MODULE_DESCRIPTION("Webcam Video Gadget");

+ 2 - 12
drivers/usb/gadget/zero.c → drivers/usb/gadget/legacy/zero.c

@@ -411,17 +411,7 @@ static __refdata struct usb_composite_driver zero_driver = {
 	.resume		= zero_resume,
 };
 
+module_usb_composite_driver(zero_driver);
+
 MODULE_AUTHOR("David Brownell");
 MODULE_LICENSE("GPL");
-
-static int __init init(void)
-{
-	return usb_composite_probe(&zero_driver);
-}
-module_init(init);
-
-static void __exit cleanup(void)
-{
-	usb_composite_unregister(&zero_driver);
-}
-module_exit(cleanup);

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

@@ -1,2905 +0,0 @@
-/*
- * Driver for the PLX NET2280 USB device controller.
- * Specs and errata are available from <http://www.plxtech.com>.
- *
- * PLX Technology Inc. (formerly NetChip Technology) supported the
- * development of this driver.
- *
- *
- * CODE STATUS HIGHLIGHTS
- *
- * This driver should work well with most "gadget" drivers, including
- * the Mass Storage, Serial, and Ethernet/RNDIS gadget drivers
- * as well as Gadget Zero and Gadgetfs.
- *
- * DMA is enabled by default.  Drivers using transfer queues might use
- * DMA chaining to remove IRQ latencies between transfers.  (Except when
- * short OUT transfers happen.)  Drivers can use the req->no_interrupt
- * hint to completely eliminate some IRQs, if a later IRQ is guaranteed
- * and DMA chaining is enabled.
- *
- * Note that almost all the errata workarounds here are only needed for
- * rev1 chips.  Rev1a silicon (0110) fixes almost all of them.
- */
-
-/*
- * Copyright (C) 2003 David Brownell
- * Copyright (C) 2003-2005 PLX Technology, Inc.
- *
- * Modified Seth Levy 2005 PLX Technology, Inc. to provide compatibility
- *	with 2282 chip
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#undef	DEBUG		/* messages on error and most fault paths */
-#undef	VERBOSE		/* extra debug messages (success too) */
-
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/dma-mapping.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/ioport.h>
-#include <linux/slab.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/timer.h>
-#include <linux/list.h>
-#include <linux/interrupt.h>
-#include <linux/moduleparam.h>
-#include <linux/device.h>
-#include <linux/usb/ch9.h>
-#include <linux/usb/gadget.h>
-#include <linux/prefetch.h>
-
-#include <asm/byteorder.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/unaligned.h>
-
-
-#define	DRIVER_DESC		"PLX NET228x USB Peripheral Controller"
-#define	DRIVER_VERSION		"2005 Sept 27"
-
-#define	EP_DONTUSE		13	/* nonzero */
-
-#define USE_RDK_LEDS		/* GPIO pins control three LEDs */
-
-
-static const char driver_name [] = "net2280";
-static const char driver_desc [] = DRIVER_DESC;
-
-static const char ep0name [] = "ep0";
-static const char *const ep_name [] = {
-	ep0name,
-	"ep-a", "ep-b", "ep-c", "ep-d",
-	"ep-e", "ep-f",
-};
-
-/* use_dma -- general goodness, fewer interrupts, less cpu load (vs PIO)
- * use_dma_chaining -- dma descriptor queueing gives even more irq reduction
- *
- * The net2280 DMA engines are not tightly integrated with their FIFOs;
- * not all cases are (yet) handled well in this driver or the silicon.
- * Some gadget drivers work better with the dma support here than others.
- * These two parameters let you use PIO or more aggressive DMA.
- */
-static bool use_dma = 1;
-static bool use_dma_chaining = 0;
-
-/* "modprobe net2280 use_dma=n" etc */
-module_param (use_dma, bool, S_IRUGO);
-module_param (use_dma_chaining, bool, S_IRUGO);
-
-
-/* mode 0 == ep-{a,b,c,d} 1K fifo each
- * mode 1 == ep-{a,b} 2K fifo each, ep-{c,d} unavailable
- * mode 2 == ep-a 2K fifo, ep-{b,c} 1K each, ep-d unavailable
- */
-static ushort fifo_mode = 0;
-
-/* "modprobe net2280 fifo_mode=1" etc */
-module_param (fifo_mode, ushort, 0644);
-
-/* enable_suspend -- When enabled, the driver will respond to
- * USB suspend requests by powering down the NET2280.  Otherwise,
- * USB suspend requests will be ignored.  This is acceptable for
- * self-powered devices
- */
-static bool enable_suspend = 0;
-
-/* "modprobe net2280 enable_suspend=1" etc */
-module_param (enable_suspend, bool, S_IRUGO);
-
-/* force full-speed operation */
-static bool full_speed;
-module_param(full_speed, bool, 0444);
-MODULE_PARM_DESC(full_speed, "force full-speed mode -- for testing only!");
-
-#define	DIR_STRING(bAddress) (((bAddress) & USB_DIR_IN) ? "in" : "out")
-
-#if defined(CONFIG_USB_GADGET_DEBUG_FILES) || defined (DEBUG)
-static char *type_string (u8 bmAttributes)
-{
-	switch ((bmAttributes) & USB_ENDPOINT_XFERTYPE_MASK) {
-	case USB_ENDPOINT_XFER_BULK:	return "bulk";
-	case USB_ENDPOINT_XFER_ISOC:	return "iso";
-	case USB_ENDPOINT_XFER_INT:	return "intr";
-	}
-	return "control";
-}
-#endif
-
-#include "net2280.h"
-
-#define valid_bit	cpu_to_le32 (1 << VALID_BIT)
-#define dma_done_ie	cpu_to_le32 (1 << DMA_DONE_INTERRUPT_ENABLE)
-
-/*-------------------------------------------------------------------------*/
-
-static int
-net2280_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
-{
-	struct net2280		*dev;
-	struct net2280_ep	*ep;
-	u32			max, tmp;
-	unsigned long		flags;
-
-	ep = container_of (_ep, struct net2280_ep, ep);
-	if (!_ep || !desc || ep->desc || _ep->name == ep0name
-			|| desc->bDescriptorType != USB_DT_ENDPOINT)
-		return -EINVAL;
-	dev = ep->dev;
-	if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)
-		return -ESHUTDOWN;
-
-	/* erratum 0119 workaround ties up an endpoint number */
-	if ((desc->bEndpointAddress & 0x0f) == EP_DONTUSE)
-		return -EDOM;
-
-	/* sanity check ep-e/ep-f since their fifos are small */
-	max = usb_endpoint_maxp (desc) & 0x1fff;
-	if (ep->num > 4 && max > 64)
-		return -ERANGE;
-
-	spin_lock_irqsave (&dev->lock, flags);
-	_ep->maxpacket = max & 0x7ff;
-	ep->desc = desc;
-
-	/* ep_reset() has already been called */
-	ep->stopped = 0;
-	ep->wedged = 0;
-	ep->out_overflow = 0;
-
-	/* set speed-dependent max packet; may kick in high bandwidth */
-	set_idx_reg (dev->regs, REG_EP_MAXPKT (dev, ep->num), max);
-
-	/* FIFO lines can't go to different packets.  PIO is ok, so
-	 * use it instead of troublesome (non-bulk) multi-packet DMA.
-	 */
-	if (ep->dma && (max % 4) != 0 && use_dma_chaining) {
-		DEBUG (ep->dev, "%s, no dma for maxpacket %d\n",
-			ep->ep.name, ep->ep.maxpacket);
-		ep->dma = NULL;
-	}
-
-	/* set type, direction, address; reset fifo counters */
-	writel ((1 << FIFO_FLUSH), &ep->regs->ep_stat);
-	tmp = (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK);
-	if (tmp == USB_ENDPOINT_XFER_INT) {
-		/* erratum 0105 workaround prevents hs NYET */
-		if (dev->chiprev == 0100
-				&& dev->gadget.speed == USB_SPEED_HIGH
-				&& !(desc->bEndpointAddress & USB_DIR_IN))
-			writel ((1 << CLEAR_NAK_OUT_PACKETS_MODE),
-				&ep->regs->ep_rsp);
-	} else if (tmp == USB_ENDPOINT_XFER_BULK) {
-		/* catch some particularly blatant driver bugs */
-		if ((dev->gadget.speed == USB_SPEED_HIGH
-					&& max != 512)
-				|| (dev->gadget.speed == USB_SPEED_FULL
-					&& max > 64)) {
-			spin_unlock_irqrestore (&dev->lock, flags);
-			return -ERANGE;
-		}
-	}
-	ep->is_iso = (tmp == USB_ENDPOINT_XFER_ISOC) ? 1 : 0;
-	tmp <<= ENDPOINT_TYPE;
-	tmp |= desc->bEndpointAddress;
-	tmp |= (4 << ENDPOINT_BYTE_COUNT);	/* default full fifo lines */
-	tmp |= 1 << ENDPOINT_ENABLE;
-	wmb ();
-
-	/* for OUT transfers, block the rx fifo until a read is posted */
-	ep->is_in = (tmp & USB_DIR_IN) != 0;
-	if (!ep->is_in)
-		writel ((1 << SET_NAK_OUT_PACKETS), &ep->regs->ep_rsp);
-	else if (dev->pdev->device != 0x2280) {
-		/* Added for 2282, Don't use nak packets on an in endpoint,
-		 * this was ignored on 2280
-		 */
-		writel ((1 << CLEAR_NAK_OUT_PACKETS)
-			| (1 << CLEAR_NAK_OUT_PACKETS_MODE), &ep->regs->ep_rsp);
-	}
-
-	writel (tmp, &ep->regs->ep_cfg);
-
-	/* enable irqs */
-	if (!ep->dma) {				/* pio, per-packet */
-		tmp = (1 << ep->num) | readl (&dev->regs->pciirqenb0);
-		writel (tmp, &dev->regs->pciirqenb0);
-
-		tmp = (1 << DATA_PACKET_RECEIVED_INTERRUPT_ENABLE)
-			| (1 << DATA_PACKET_TRANSMITTED_INTERRUPT_ENABLE);
-		if (dev->pdev->device == 0x2280)
-			tmp |= readl (&ep->regs->ep_irqenb);
-		writel (tmp, &ep->regs->ep_irqenb);
-	} else {				/* dma, per-request */
-		tmp = (1 << (8 + ep->num));	/* completion */
-		tmp |= readl (&dev->regs->pciirqenb1);
-		writel (tmp, &dev->regs->pciirqenb1);
-
-		/* for short OUT transfers, dma completions can't
-		 * advance the queue; do it pio-style, by hand.
-		 * NOTE erratum 0112 workaround #2
-		 */
-		if ((desc->bEndpointAddress & USB_DIR_IN) == 0) {
-			tmp = (1 << SHORT_PACKET_TRANSFERRED_INTERRUPT_ENABLE);
-			writel (tmp, &ep->regs->ep_irqenb);
-
-			tmp = (1 << ep->num) | readl (&dev->regs->pciirqenb0);
-			writel (tmp, &dev->regs->pciirqenb0);
-		}
-	}
-
-	tmp = desc->bEndpointAddress;
-	DEBUG (dev, "enabled %s (ep%d%s-%s) %s max %04x\n",
-		_ep->name, tmp & 0x0f, DIR_STRING (tmp),
-		type_string (desc->bmAttributes),
-		ep->dma ? "dma" : "pio", max);
-
-	/* pci writes may still be posted */
-	spin_unlock_irqrestore (&dev->lock, flags);
-	return 0;
-}
-
-static int handshake (u32 __iomem *ptr, u32 mask, u32 done, int usec)
-{
-	u32	result;
-
-	do {
-		result = readl (ptr);
-		if (result == ~(u32)0)		/* "device unplugged" */
-			return -ENODEV;
-		result &= mask;
-		if (result == done)
-			return 0;
-		udelay (1);
-		usec--;
-	} while (usec > 0);
-	return -ETIMEDOUT;
-}
-
-static const struct usb_ep_ops net2280_ep_ops;
-
-static void ep_reset (struct net2280_regs __iomem *regs, struct net2280_ep *ep)
-{
-	u32		tmp;
-
-	ep->desc = NULL;
-	INIT_LIST_HEAD (&ep->queue);
-
-	usb_ep_set_maxpacket_limit(&ep->ep, ~0);
-	ep->ep.ops = &net2280_ep_ops;
-
-	/* disable the dma, irqs, endpoint... */
-	if (ep->dma) {
-		writel (0, &ep->dma->dmactl);
-		writel (  (1 << DMA_SCATTER_GATHER_DONE_INTERRUPT)
-			| (1 << DMA_TRANSACTION_DONE_INTERRUPT)
-			| (1 << DMA_ABORT)
-			, &ep->dma->dmastat);
-
-		tmp = readl (&regs->pciirqenb0);
-		tmp &= ~(1 << ep->num);
-		writel (tmp, &regs->pciirqenb0);
-	} else {
-		tmp = readl (&regs->pciirqenb1);
-		tmp &= ~(1 << (8 + ep->num));	/* completion */
-		writel (tmp, &regs->pciirqenb1);
-	}
-	writel (0, &ep->regs->ep_irqenb);
-
-	/* init to our chosen defaults, notably so that we NAK OUT
-	 * packets until the driver queues a read (+note erratum 0112)
-	 */
-	if (!ep->is_in || ep->dev->pdev->device == 0x2280) {
-		tmp = (1 << SET_NAK_OUT_PACKETS_MODE)
-		| (1 << SET_NAK_OUT_PACKETS)
-		| (1 << CLEAR_EP_HIDE_STATUS_PHASE)
-		| (1 << CLEAR_INTERRUPT_MODE);
-	} else {
-		/* added for 2282 */
-		tmp = (1 << CLEAR_NAK_OUT_PACKETS_MODE)
-		| (1 << CLEAR_NAK_OUT_PACKETS)
-		| (1 << CLEAR_EP_HIDE_STATUS_PHASE)
-		| (1 << CLEAR_INTERRUPT_MODE);
-	}
-
-	if (ep->num != 0) {
-		tmp |= (1 << CLEAR_ENDPOINT_TOGGLE)
-			| (1 << CLEAR_ENDPOINT_HALT);
-	}
-	writel (tmp, &ep->regs->ep_rsp);
-
-	/* scrub most status bits, and flush any fifo state */
-	if (ep->dev->pdev->device == 0x2280)
-		tmp = (1 << FIFO_OVERFLOW)
-			| (1 << FIFO_UNDERFLOW);
-	else
-		tmp = 0;
-
-	writel (tmp | (1 << TIMEOUT)
-		| (1 << USB_STALL_SENT)
-		| (1 << USB_IN_NAK_SENT)
-		| (1 << USB_IN_ACK_RCVD)
-		| (1 << USB_OUT_PING_NAK_SENT)
-		| (1 << USB_OUT_ACK_SENT)
-		| (1 << FIFO_FLUSH)
-		| (1 << SHORT_PACKET_OUT_DONE_INTERRUPT)
-		| (1 << SHORT_PACKET_TRANSFERRED_INTERRUPT)
-		| (1 << DATA_PACKET_RECEIVED_INTERRUPT)
-		| (1 << DATA_PACKET_TRANSMITTED_INTERRUPT)
-		| (1 << DATA_OUT_PING_TOKEN_INTERRUPT)
-		| (1 << DATA_IN_TOKEN_INTERRUPT)
-		, &ep->regs->ep_stat);
-
-	/* fifo size is handled separately */
-}
-
-static void nuke (struct net2280_ep *);
-
-static int net2280_disable (struct usb_ep *_ep)
-{
-	struct net2280_ep	*ep;
-	unsigned long		flags;
-
-	ep = container_of (_ep, struct net2280_ep, ep);
-	if (!_ep || !ep->desc || _ep->name == ep0name)
-		return -EINVAL;
-
-	spin_lock_irqsave (&ep->dev->lock, flags);
-	nuke (ep);
-	ep_reset (ep->dev->regs, ep);
-
-	VDEBUG (ep->dev, "disabled %s %s\n",
-			ep->dma ? "dma" : "pio", _ep->name);
-
-	/* synch memory views with the device */
-	(void) readl (&ep->regs->ep_cfg);
-
-	if (use_dma && !ep->dma && ep->num >= 1 && ep->num <= 4)
-		ep->dma = &ep->dev->dma [ep->num - 1];
-
-	spin_unlock_irqrestore (&ep->dev->lock, flags);
-	return 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static struct usb_request *
-net2280_alloc_request (struct usb_ep *_ep, gfp_t gfp_flags)
-{
-	struct net2280_ep	*ep;
-	struct net2280_request	*req;
-
-	if (!_ep)
-		return NULL;
-	ep = container_of (_ep, struct net2280_ep, ep);
-
-	req = kzalloc(sizeof(*req), gfp_flags);
-	if (!req)
-		return NULL;
-
-	INIT_LIST_HEAD (&req->queue);
-
-	/* this dma descriptor may be swapped with the previous dummy */
-	if (ep->dma) {
-		struct net2280_dma	*td;
-
-		td = pci_pool_alloc (ep->dev->requests, gfp_flags,
-				&req->td_dma);
-		if (!td) {
-			kfree (req);
-			return NULL;
-		}
-		td->dmacount = 0;	/* not VALID */
-		td->dmadesc = td->dmaaddr;
-		req->td = td;
-	}
-	return &req->req;
-}
-
-static void
-net2280_free_request (struct usb_ep *_ep, struct usb_request *_req)
-{
-	struct net2280_ep	*ep;
-	struct net2280_request	*req;
-
-	ep = container_of (_ep, struct net2280_ep, ep);
-	if (!_ep || !_req)
-		return;
-
-	req = container_of (_req, struct net2280_request, req);
-	WARN_ON (!list_empty (&req->queue));
-	if (req->td)
-		pci_pool_free (ep->dev->requests, req->td, req->td_dma);
-	kfree (req);
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* load a packet into the fifo we use for usb IN transfers.
- * works for all endpoints.
- *
- * NOTE: pio with ep-a..ep-d could stuff multiple packets into the fifo
- * at a time, but this code is simpler because it knows it only writes
- * one packet.  ep-a..ep-d should use dma instead.
- */
-static void
-write_fifo (struct net2280_ep *ep, struct usb_request *req)
-{
-	struct net2280_ep_regs	__iomem *regs = ep->regs;
-	u8			*buf;
-	u32			tmp;
-	unsigned		count, total;
-
-	/* INVARIANT:  fifo is currently empty. (testable) */
-
-	if (req) {
-		buf = req->buf + req->actual;
-		prefetch (buf);
-		total = req->length - req->actual;
-	} else {
-		total = 0;
-		buf = NULL;
-	}
-
-	/* write just one packet at a time */
-	count = ep->ep.maxpacket;
-	if (count > total)	/* min() cannot be used on a bitfield */
-		count = total;
-
-	VDEBUG (ep->dev, "write %s fifo (IN) %d bytes%s req %p\n",
-			ep->ep.name, count,
-			(count != ep->ep.maxpacket) ? " (short)" : "",
-			req);
-	while (count >= 4) {
-		/* NOTE be careful if you try to align these. fifo lines
-		 * should normally be full (4 bytes) and successive partial
-		 * lines are ok only in certain cases.
-		 */
-		tmp = get_unaligned ((u32 *)buf);
-		cpu_to_le32s (&tmp);
-		writel (tmp, &regs->ep_data);
-		buf += 4;
-		count -= 4;
-	}
-
-	/* last fifo entry is "short" unless we wrote a full packet.
-	 * also explicitly validate last word in (periodic) transfers
-	 * when maxpacket is not a multiple of 4 bytes.
-	 */
-	if (count || total < ep->ep.maxpacket) {
-		tmp = count ? get_unaligned ((u32 *)buf) : count;
-		cpu_to_le32s (&tmp);
-		set_fifo_bytecount (ep, count & 0x03);
-		writel (tmp, &regs->ep_data);
-	}
-
-	/* pci writes may still be posted */
-}
-
-/* work around erratum 0106: PCI and USB race over the OUT fifo.
- * caller guarantees chiprev 0100, out endpoint is NAKing, and
- * there's no real data in the fifo.
- *
- * NOTE:  also used in cases where that erratum doesn't apply:
- * where the host wrote "too much" data to us.
- */
-static void out_flush (struct net2280_ep *ep)
-{
-	u32	__iomem *statp;
-	u32	tmp;
-
-	ASSERT_OUT_NAKING (ep);
-
-	statp = &ep->regs->ep_stat;
-	writel (  (1 << DATA_OUT_PING_TOKEN_INTERRUPT)
-		| (1 << DATA_PACKET_RECEIVED_INTERRUPT)
-		, statp);
-	writel ((1 << FIFO_FLUSH), statp);
-	mb ();
-	tmp = readl (statp);
-	if (tmp & (1 << DATA_OUT_PING_TOKEN_INTERRUPT)
-			/* high speed did bulk NYET; fifo isn't filling */
-			&& ep->dev->gadget.speed == USB_SPEED_FULL) {
-		unsigned	usec;
-
-		usec = 50;		/* 64 byte bulk/interrupt */
-		handshake (statp, (1 << USB_OUT_PING_NAK_SENT),
-				(1 << USB_OUT_PING_NAK_SENT), usec);
-		/* NAK done; now CLEAR_NAK_OUT_PACKETS is safe */
-	}
-}
-
-/* unload packet(s) from the fifo we use for usb OUT transfers.
- * returns true iff the request completed, because of short packet
- * or the request buffer having filled with full packets.
- *
- * for ep-a..ep-d this will read multiple packets out when they
- * have been accepted.
- */
-static int
-read_fifo (struct net2280_ep *ep, struct net2280_request *req)
-{
-	struct net2280_ep_regs	__iomem *regs = ep->regs;
-	u8			*buf = req->req.buf + req->req.actual;
-	unsigned		count, tmp, is_short;
-	unsigned		cleanup = 0, prevent = 0;
-
-	/* erratum 0106 ... packets coming in during fifo reads might
-	 * be incompletely rejected.  not all cases have workarounds.
-	 */
-	if (ep->dev->chiprev == 0x0100
-			&& ep->dev->gadget.speed == USB_SPEED_FULL) {
-		udelay (1);
-		tmp = readl (&ep->regs->ep_stat);
-		if ((tmp & (1 << NAK_OUT_PACKETS)))
-			cleanup = 1;
-		else if ((tmp & (1 << FIFO_FULL))) {
-			start_out_naking (ep);
-			prevent = 1;
-		}
-		/* else: hope we don't see the problem */
-	}
-
-	/* never overflow the rx buffer. the fifo reads packets until
-	 * it sees a short one; we might not be ready for them all.
-	 */
-	prefetchw (buf);
-	count = readl (&regs->ep_avail);
-	if (unlikely (count == 0)) {
-		udelay (1);
-		tmp = readl (&ep->regs->ep_stat);
-		count = readl (&regs->ep_avail);
-		/* handled that data already? */
-		if (count == 0 && (tmp & (1 << NAK_OUT_PACKETS)) == 0)
-			return 0;
-	}
-
-	tmp = req->req.length - req->req.actual;
-	if (count > tmp) {
-		/* as with DMA, data overflow gets flushed */
-		if ((tmp % ep->ep.maxpacket) != 0) {
-			ERROR (ep->dev,
-				"%s out fifo %d bytes, expected %d\n",
-				ep->ep.name, count, tmp);
-			req->req.status = -EOVERFLOW;
-			cleanup = 1;
-			/* NAK_OUT_PACKETS will be set, so flushing is safe;
-			 * the next read will start with the next packet
-			 */
-		} /* else it's a ZLP, no worries */
-		count = tmp;
-	}
-	req->req.actual += count;
-
-	is_short = (count == 0) || ((count % ep->ep.maxpacket) != 0);
-
-	VDEBUG (ep->dev, "read %s fifo (OUT) %d bytes%s%s%s req %p %d/%d\n",
-			ep->ep.name, count, is_short ? " (short)" : "",
-			cleanup ? " flush" : "", prevent ? " nak" : "",
-			req, req->req.actual, req->req.length);
-
-	while (count >= 4) {
-		tmp = readl (&regs->ep_data);
-		cpu_to_le32s (&tmp);
-		put_unaligned (tmp, (u32 *)buf);
-		buf += 4;
-		count -= 4;
-	}
-	if (count) {
-		tmp = readl (&regs->ep_data);
-		/* LE conversion is implicit here: */
-		do {
-			*buf++ = (u8) tmp;
-			tmp >>= 8;
-		} while (--count);
-	}
-	if (cleanup)
-		out_flush (ep);
-	if (prevent) {
-		writel ((1 << CLEAR_NAK_OUT_PACKETS), &ep->regs->ep_rsp);
-		(void) readl (&ep->regs->ep_rsp);
-	}
-
-	return is_short || ((req->req.actual == req->req.length)
-				&& !req->req.zero);
-}
-
-/* fill out dma descriptor to match a given request */
-static void
-fill_dma_desc (struct net2280_ep *ep, struct net2280_request *req, int valid)
-{
-	struct net2280_dma	*td = req->td;
-	u32			dmacount = req->req.length;
-
-	/* don't let DMA continue after a short OUT packet,
-	 * so overruns can't affect the next transfer.
-	 * in case of overruns on max-size packets, we can't
-	 * stop the fifo from filling but we can flush it.
-	 */
-	if (ep->is_in)
-		dmacount |= (1 << DMA_DIRECTION);
-	if ((!ep->is_in && (dmacount % ep->ep.maxpacket) != 0)
-			|| ep->dev->pdev->device != 0x2280)
-		dmacount |= (1 << END_OF_CHAIN);
-
-	req->valid = valid;
-	if (valid)
-		dmacount |= (1 << VALID_BIT);
-	if (likely(!req->req.no_interrupt || !use_dma_chaining))
-		dmacount |= (1 << DMA_DONE_INTERRUPT_ENABLE);
-
-	/* td->dmadesc = previously set by caller */
-	td->dmaaddr = cpu_to_le32 (req->req.dma);
-
-	/* 2280 may be polling VALID_BIT through ep->dma->dmadesc */
-	wmb ();
-	td->dmacount = cpu_to_le32(dmacount);
-}
-
-static const u32 dmactl_default =
-		  (1 << DMA_SCATTER_GATHER_DONE_INTERRUPT)
-		| (1 << DMA_CLEAR_COUNT_ENABLE)
-		/* erratum 0116 workaround part 1 (use POLLING) */
-		| (POLL_100_USEC << DESCRIPTOR_POLLING_RATE)
-		| (1 << DMA_VALID_BIT_POLLING_ENABLE)
-		| (1 << DMA_VALID_BIT_ENABLE)
-		| (1 << DMA_SCATTER_GATHER_ENABLE)
-		/* erratum 0116 workaround part 2 (no AUTOSTART) */
-		| (1 << DMA_ENABLE);
-
-static inline void spin_stop_dma (struct net2280_dma_regs __iomem *dma)
-{
-	handshake (&dma->dmactl, (1 << DMA_ENABLE), 0, 50);
-}
-
-static inline void stop_dma (struct net2280_dma_regs __iomem *dma)
-{
-	writel (readl (&dma->dmactl) & ~(1 << DMA_ENABLE), &dma->dmactl);
-	spin_stop_dma (dma);
-}
-
-static void start_queue (struct net2280_ep *ep, u32 dmactl, u32 td_dma)
-{
-	struct net2280_dma_regs	__iomem *dma = ep->dma;
-	unsigned int tmp = (1 << VALID_BIT) | (ep->is_in << DMA_DIRECTION);
-
-	if (ep->dev->pdev->device != 0x2280)
-		tmp |= (1 << END_OF_CHAIN);
-
-	writel (tmp, &dma->dmacount);
-	writel (readl (&dma->dmastat), &dma->dmastat);
-
-	writel (td_dma, &dma->dmadesc);
-	writel (dmactl, &dma->dmactl);
-
-	/* erratum 0116 workaround part 3:  pci arbiter away from net2280 */
-	(void) readl (&ep->dev->pci->pcimstctl);
-
-	writel ((1 << DMA_START), &dma->dmastat);
-
-	if (!ep->is_in)
-		stop_out_naking (ep);
-}
-
-static void start_dma (struct net2280_ep *ep, struct net2280_request *req)
-{
-	u32			tmp;
-	struct net2280_dma_regs	__iomem *dma = ep->dma;
-
-	/* FIXME can't use DMA for ZLPs */
-
-	/* on this path we "know" there's no dma active (yet) */
-	WARN_ON (readl (&dma->dmactl) & (1 << DMA_ENABLE));
-	writel (0, &ep->dma->dmactl);
-
-	/* previous OUT packet might have been short */
-	if (!ep->is_in && ((tmp = readl (&ep->regs->ep_stat))
-				& (1 << NAK_OUT_PACKETS)) != 0) {
-		writel ((1 << SHORT_PACKET_TRANSFERRED_INTERRUPT),
-			&ep->regs->ep_stat);
-
-		tmp = readl (&ep->regs->ep_avail);
-		if (tmp) {
-			writel (readl (&dma->dmastat), &dma->dmastat);
-
-			/* transfer all/some fifo data */
-			writel (req->req.dma, &dma->dmaaddr);
-			tmp = min (tmp, req->req.length);
-
-			/* dma irq, faking scatterlist status */
-			req->td->dmacount = cpu_to_le32 (req->req.length - tmp);
-			writel ((1 << DMA_DONE_INTERRUPT_ENABLE)
-				| tmp, &dma->dmacount);
-			req->td->dmadesc = 0;
-			req->valid = 1;
-
-			writel ((1 << DMA_ENABLE), &dma->dmactl);
-			writel ((1 << DMA_START), &dma->dmastat);
-			return;
-		}
-	}
-
-	tmp = dmactl_default;
-
-	/* force packet boundaries between dma requests, but prevent the
-	 * controller from automagically writing a last "short" packet
-	 * (zero length) unless the driver explicitly said to do that.
-	 */
-	if (ep->is_in) {
-		if (likely ((req->req.length % ep->ep.maxpacket) != 0
-				|| req->req.zero)) {
-			tmp |= (1 << DMA_FIFO_VALIDATE);
-			ep->in_fifo_validate = 1;
-		} else
-			ep->in_fifo_validate = 0;
-	}
-
-	/* init req->td, pointing to the current dummy */
-	req->td->dmadesc = cpu_to_le32 (ep->td_dma);
-	fill_dma_desc (ep, req, 1);
-
-	if (!use_dma_chaining)
-		req->td->dmacount |= cpu_to_le32 (1 << END_OF_CHAIN);
-
-	start_queue (ep, tmp, req->td_dma);
-}
-
-static inline void
-queue_dma (struct net2280_ep *ep, struct net2280_request *req, int valid)
-{
-	struct net2280_dma	*end;
-	dma_addr_t		tmp;
-
-	/* swap new dummy for old, link; fill and maybe activate */
-	end = ep->dummy;
-	ep->dummy = req->td;
-	req->td = end;
-
-	tmp = ep->td_dma;
-	ep->td_dma = req->td_dma;
-	req->td_dma = tmp;
-
-	end->dmadesc = cpu_to_le32 (ep->td_dma);
-
-	fill_dma_desc (ep, req, valid);
-}
-
-static void
-done (struct net2280_ep *ep, struct net2280_request *req, int status)
-{
-	struct net2280		*dev;
-	unsigned		stopped = ep->stopped;
-
-	list_del_init (&req->queue);
-
-	if (req->req.status == -EINPROGRESS)
-		req->req.status = status;
-	else
-		status = req->req.status;
-
-	dev = ep->dev;
-	if (ep->dma)
-		usb_gadget_unmap_request(&dev->gadget, &req->req, ep->is_in);
-
-	if (status && status != -ESHUTDOWN)
-		VDEBUG (dev, "complete %s req %p stat %d len %u/%u\n",
-			ep->ep.name, &req->req, status,
-			req->req.actual, req->req.length);
-
-	/* don't modify queue heads during completion callback */
-	ep->stopped = 1;
-	spin_unlock (&dev->lock);
-	req->req.complete (&ep->ep, &req->req);
-	spin_lock (&dev->lock);
-	ep->stopped = stopped;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static int
-net2280_queue (struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
-{
-	struct net2280_request	*req;
-	struct net2280_ep	*ep;
-	struct net2280		*dev;
-	unsigned long		flags;
-
-	/* we always require a cpu-view buffer, so that we can
-	 * always use pio (as fallback or whatever).
-	 */
-	req = container_of (_req, struct net2280_request, req);
-	if (!_req || !_req->complete || !_req->buf
-			|| !list_empty (&req->queue))
-		return -EINVAL;
-	if (_req->length > (~0 & DMA_BYTE_COUNT_MASK))
-		return -EDOM;
-	ep = container_of (_ep, struct net2280_ep, ep);
-	if (!_ep || (!ep->desc && ep->num != 0))
-		return -EINVAL;
-	dev = ep->dev;
-	if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)
-		return -ESHUTDOWN;
-
-	/* FIXME implement PIO fallback for ZLPs with DMA */
-	if (ep->dma && _req->length == 0)
-		return -EOPNOTSUPP;
-
-	/* set up dma mapping in case the caller didn't */
-	if (ep->dma) {
-		int ret;
-
-		ret = usb_gadget_map_request(&dev->gadget, _req,
-				ep->is_in);
-		if (ret)
-			return ret;
-	}
-
-#if 0
-	VDEBUG (dev, "%s queue req %p, len %d buf %p\n",
-			_ep->name, _req, _req->length, _req->buf);
-#endif
-
-	spin_lock_irqsave (&dev->lock, flags);
-
-	_req->status = -EINPROGRESS;
-	_req->actual = 0;
-
-	/* kickstart this i/o queue? */
-	if (list_empty (&ep->queue) && !ep->stopped) {
-		/* use DMA if the endpoint supports it, else pio */
-		if (ep->dma)
-			start_dma (ep, req);
-		else {
-			/* maybe there's no control data, just status ack */
-			if (ep->num == 0 && _req->length == 0) {
-				allow_status (ep);
-				done (ep, req, 0);
-				VDEBUG (dev, "%s status ack\n", ep->ep.name);
-				goto done;
-			}
-
-			/* PIO ... stuff the fifo, or unblock it.  */
-			if (ep->is_in)
-				write_fifo (ep, _req);
-			else if (list_empty (&ep->queue)) {
-				u32	s;
-
-				/* OUT FIFO might have packet(s) buffered */
-				s = readl (&ep->regs->ep_stat);
-				if ((s & (1 << FIFO_EMPTY)) == 0) {
-					/* note:  _req->short_not_ok is
-					 * ignored here since PIO _always_
-					 * stops queue advance here, and
-					 * _req->status doesn't change for
-					 * short reads (only _req->actual)
-					 */
-					if (read_fifo (ep, req)) {
-						done (ep, req, 0);
-						if (ep->num == 0)
-							allow_status (ep);
-						/* don't queue it */
-						req = NULL;
-					} else
-						s = readl (&ep->regs->ep_stat);
-				}
-
-				/* don't NAK, let the fifo fill */
-				if (req && (s & (1 << NAK_OUT_PACKETS)))
-					writel ((1 << CLEAR_NAK_OUT_PACKETS),
-							&ep->regs->ep_rsp);
-			}
-		}
-
-	} else if (ep->dma) {
-		int	valid = 1;
-
-		if (ep->is_in) {
-			int	expect;
-
-			/* preventing magic zlps is per-engine state, not
-			 * per-transfer; irq logic must recover hiccups.
-			 */
-			expect = likely (req->req.zero
-				|| (req->req.length % ep->ep.maxpacket) != 0);
-			if (expect != ep->in_fifo_validate)
-				valid = 0;
-		}
-		queue_dma (ep, req, valid);
-
-	} /* else the irq handler advances the queue. */
-
-	ep->responded = 1;
-	if (req)
-		list_add_tail (&req->queue, &ep->queue);
-done:
-	spin_unlock_irqrestore (&dev->lock, flags);
-
-	/* pci writes may still be posted */
-	return 0;
-}
-
-static inline void
-dma_done (
-	struct net2280_ep *ep,
-	struct net2280_request *req,
-	u32 dmacount,
-	int status
-)
-{
-	req->req.actual = req->req.length - (DMA_BYTE_COUNT_MASK & dmacount);
-	done (ep, req, status);
-}
-
-static void restart_dma (struct net2280_ep *ep);
-
-static void scan_dma_completions (struct net2280_ep *ep)
-{
-	/* only look at descriptors that were "naturally" retired,
-	 * so fifo and list head state won't matter
-	 */
-	while (!list_empty (&ep->queue)) {
-		struct net2280_request	*req;
-		u32			tmp;
-
-		req = list_entry (ep->queue.next,
-				struct net2280_request, queue);
-		if (!req->valid)
-			break;
-		rmb ();
-		tmp = le32_to_cpup (&req->td->dmacount);
-		if ((tmp & (1 << VALID_BIT)) != 0)
-			break;
-
-		/* SHORT_PACKET_TRANSFERRED_INTERRUPT handles "usb-short"
-		 * cases where DMA must be aborted; this code handles
-		 * all non-abort DMA completions.
-		 */
-		if (unlikely (req->td->dmadesc == 0)) {
-			/* paranoia */
-			tmp = readl (&ep->dma->dmacount);
-			if (tmp & DMA_BYTE_COUNT_MASK)
-				break;
-			/* single transfer mode */
-			dma_done (ep, req, tmp, 0);
-			break;
-		} else if (!ep->is_in
-				&& (req->req.length % ep->ep.maxpacket) != 0) {
-			tmp = readl (&ep->regs->ep_stat);
-
-			/* AVOID TROUBLE HERE by not issuing short reads from
-			 * your gadget driver.  That helps avoids errata 0121,
-			 * 0122, and 0124; not all cases trigger the warning.
-			 */
-			if ((tmp & (1 << NAK_OUT_PACKETS)) == 0) {
-				WARNING (ep->dev, "%s lost packet sync!\n",
-						ep->ep.name);
-				req->req.status = -EOVERFLOW;
-			} else if ((tmp = readl (&ep->regs->ep_avail)) != 0) {
-				/* fifo gets flushed later */
-				ep->out_overflow = 1;
-				DEBUG (ep->dev, "%s dma, discard %d len %d\n",
-						ep->ep.name, tmp,
-						req->req.length);
-				req->req.status = -EOVERFLOW;
-			}
-		}
-		dma_done (ep, req, tmp, 0);
-	}
-}
-
-static void restart_dma (struct net2280_ep *ep)
-{
-	struct net2280_request	*req;
-	u32			dmactl = dmactl_default;
-
-	if (ep->stopped)
-		return;
-	req = list_entry (ep->queue.next, struct net2280_request, queue);
-
-	if (!use_dma_chaining) {
-		start_dma (ep, req);
-		return;
-	}
-
-	/* the 2280 will be processing the queue unless queue hiccups after
-	 * the previous transfer:
-	 *  IN:   wanted automagic zlp, head doesn't (or vice versa)
-	 *        DMA_FIFO_VALIDATE doesn't init from dma descriptors.
-	 *  OUT:  was "usb-short", we must restart.
-	 */
-	if (ep->is_in && !req->valid) {
-		struct net2280_request	*entry, *prev = NULL;
-		int			reqmode, done = 0;
-
-		DEBUG (ep->dev, "%s dma hiccup td %p\n", ep->ep.name, req->td);
-		ep->in_fifo_validate = likely (req->req.zero
-			|| (req->req.length % ep->ep.maxpacket) != 0);
-		if (ep->in_fifo_validate)
-			dmactl |= (1 << DMA_FIFO_VALIDATE);
-		list_for_each_entry (entry, &ep->queue, queue) {
-			__le32		dmacount;
-
-			if (entry == req)
-				continue;
-			dmacount = entry->td->dmacount;
-			if (!done) {
-				reqmode = likely (entry->req.zero
-					|| (entry->req.length
-						% ep->ep.maxpacket) != 0);
-				if (reqmode == ep->in_fifo_validate) {
-					entry->valid = 1;
-					dmacount |= valid_bit;
-					entry->td->dmacount = dmacount;
-					prev = entry;
-					continue;
-				} else {
-					/* force a hiccup */
-					prev->td->dmacount |= dma_done_ie;
-					done = 1;
-				}
-			}
-
-			/* walk the rest of the queue so unlinks behave */
-			entry->valid = 0;
-			dmacount &= ~valid_bit;
-			entry->td->dmacount = dmacount;
-			prev = entry;
-		}
-	}
-
-	writel (0, &ep->dma->dmactl);
-	start_queue (ep, dmactl, req->td_dma);
-}
-
-static void abort_dma (struct net2280_ep *ep)
-{
-	/* abort the current transfer */
-	if (likely (!list_empty (&ep->queue))) {
-		/* FIXME work around errata 0121, 0122, 0124 */
-		writel ((1 << DMA_ABORT), &ep->dma->dmastat);
-		spin_stop_dma (ep->dma);
-	} else
-		stop_dma (ep->dma);
-	scan_dma_completions (ep);
-}
-
-/* dequeue ALL requests */
-static void nuke (struct net2280_ep *ep)
-{
-	struct net2280_request	*req;
-
-	/* called with spinlock held */
-	ep->stopped = 1;
-	if (ep->dma)
-		abort_dma (ep);
-	while (!list_empty (&ep->queue)) {
-		req = list_entry (ep->queue.next,
-				struct net2280_request,
-				queue);
-		done (ep, req, -ESHUTDOWN);
-	}
-}
-
-/* dequeue JUST ONE request */
-static int net2280_dequeue (struct usb_ep *_ep, struct usb_request *_req)
-{
-	struct net2280_ep	*ep;
-	struct net2280_request	*req;
-	unsigned long		flags;
-	u32			dmactl;
-	int			stopped;
-
-	ep = container_of (_ep, struct net2280_ep, ep);
-	if (!_ep || (!ep->desc && ep->num != 0) || !_req)
-		return -EINVAL;
-
-	spin_lock_irqsave (&ep->dev->lock, flags);
-	stopped = ep->stopped;
-
-	/* quiesce dma while we patch the queue */
-	dmactl = 0;
-	ep->stopped = 1;
-	if (ep->dma) {
-		dmactl = readl (&ep->dma->dmactl);
-		/* WARNING erratum 0127 may kick in ... */
-		stop_dma (ep->dma);
-		scan_dma_completions (ep);
-	}
-
-	/* make sure it's still queued on this endpoint */
-	list_for_each_entry (req, &ep->queue, queue) {
-		if (&req->req == _req)
-			break;
-	}
-	if (&req->req != _req) {
-		spin_unlock_irqrestore (&ep->dev->lock, flags);
-		return -EINVAL;
-	}
-
-	/* queue head may be partially complete. */
-	if (ep->queue.next == &req->queue) {
-		if (ep->dma) {
-			DEBUG (ep->dev, "unlink (%s) dma\n", _ep->name);
-			_req->status = -ECONNRESET;
-			abort_dma (ep);
-			if (likely (ep->queue.next == &req->queue)) {
-				// NOTE: misreports single-transfer mode
-				req->td->dmacount = 0;	/* invalidate */
-				dma_done (ep, req,
-					readl (&ep->dma->dmacount),
-					-ECONNRESET);
-			}
-		} else {
-			DEBUG (ep->dev, "unlink (%s) pio\n", _ep->name);
-			done (ep, req, -ECONNRESET);
-		}
-		req = NULL;
-
-	/* patch up hardware chaining data */
-	} else if (ep->dma && use_dma_chaining) {
-		if (req->queue.prev == ep->queue.next) {
-			writel (le32_to_cpu (req->td->dmadesc),
-				&ep->dma->dmadesc);
-			if (req->td->dmacount & dma_done_ie)
-				writel (readl (&ep->dma->dmacount)
-						| le32_to_cpu(dma_done_ie),
-					&ep->dma->dmacount);
-		} else {
-			struct net2280_request	*prev;
-
-			prev = list_entry (req->queue.prev,
-				struct net2280_request, queue);
-			prev->td->dmadesc = req->td->dmadesc;
-			if (req->td->dmacount & dma_done_ie)
-				prev->td->dmacount |= dma_done_ie;
-		}
-	}
-
-	if (req)
-		done (ep, req, -ECONNRESET);
-	ep->stopped = stopped;
-
-	if (ep->dma) {
-		/* turn off dma on inactive queues */
-		if (list_empty (&ep->queue))
-			stop_dma (ep->dma);
-		else if (!ep->stopped) {
-			/* resume current request, or start new one */
-			if (req)
-				writel (dmactl, &ep->dma->dmactl);
-			else
-				start_dma (ep, list_entry (ep->queue.next,
-					struct net2280_request, queue));
-		}
-	}
-
-	spin_unlock_irqrestore (&ep->dev->lock, flags);
-	return 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static int net2280_fifo_status (struct usb_ep *_ep);
-
-static int
-net2280_set_halt_and_wedge(struct usb_ep *_ep, int value, int wedged)
-{
-	struct net2280_ep	*ep;
-	unsigned long		flags;
-	int			retval = 0;
-
-	ep = container_of (_ep, struct net2280_ep, ep);
-	if (!_ep || (!ep->desc && ep->num != 0))
-		return -EINVAL;
-	if (!ep->dev->driver || ep->dev->gadget.speed == USB_SPEED_UNKNOWN)
-		return -ESHUTDOWN;
-	if (ep->desc /* not ep0 */ && (ep->desc->bmAttributes & 0x03)
-						== USB_ENDPOINT_XFER_ISOC)
-		return -EINVAL;
-
-	spin_lock_irqsave (&ep->dev->lock, flags);
-	if (!list_empty (&ep->queue))
-		retval = -EAGAIN;
-	else if (ep->is_in && value && net2280_fifo_status (_ep) != 0)
-		retval = -EAGAIN;
-	else {
-		VDEBUG (ep->dev, "%s %s %s\n", _ep->name,
-				value ? "set" : "clear",
-				wedged ? "wedge" : "halt");
-		/* set/clear, then synch memory views with the device */
-		if (value) {
-			if (ep->num == 0)
-				ep->dev->protocol_stall = 1;
-			else
-				set_halt (ep);
-			if (wedged)
-				ep->wedged = 1;
-		} else {
-			clear_halt (ep);
-			ep->wedged = 0;
-		}
-		(void) readl (&ep->regs->ep_rsp);
-	}
-	spin_unlock_irqrestore (&ep->dev->lock, flags);
-
-	return retval;
-}
-
-static int
-net2280_set_halt(struct usb_ep *_ep, int value)
-{
-	return net2280_set_halt_and_wedge(_ep, value, 0);
-}
-
-static int
-net2280_set_wedge(struct usb_ep *_ep)
-{
-	if (!_ep || _ep->name == ep0name)
-		return -EINVAL;
-	return net2280_set_halt_and_wedge(_ep, 1, 1);
-}
-
-static int
-net2280_fifo_status (struct usb_ep *_ep)
-{
-	struct net2280_ep	*ep;
-	u32			avail;
-
-	ep = container_of (_ep, struct net2280_ep, ep);
-	if (!_ep || (!ep->desc && ep->num != 0))
-		return -ENODEV;
-	if (!ep->dev->driver || ep->dev->gadget.speed == USB_SPEED_UNKNOWN)
-		return -ESHUTDOWN;
-
-	avail = readl (&ep->regs->ep_avail) & ((1 << 12) - 1);
-	if (avail > ep->fifo_size)
-		return -EOVERFLOW;
-	if (ep->is_in)
-		avail = ep->fifo_size - avail;
-	return avail;
-}
-
-static void
-net2280_fifo_flush (struct usb_ep *_ep)
-{
-	struct net2280_ep	*ep;
-
-	ep = container_of (_ep, struct net2280_ep, ep);
-	if (!_ep || (!ep->desc && ep->num != 0))
-		return;
-	if (!ep->dev->driver || ep->dev->gadget.speed == USB_SPEED_UNKNOWN)
-		return;
-
-	writel ((1 << FIFO_FLUSH), &ep->regs->ep_stat);
-	(void) readl (&ep->regs->ep_rsp);
-}
-
-static const struct usb_ep_ops net2280_ep_ops = {
-	.enable		= net2280_enable,
-	.disable	= net2280_disable,
-
-	.alloc_request	= net2280_alloc_request,
-	.free_request	= net2280_free_request,
-
-	.queue		= net2280_queue,
-	.dequeue	= net2280_dequeue,
-
-	.set_halt	= net2280_set_halt,
-	.set_wedge	= net2280_set_wedge,
-	.fifo_status	= net2280_fifo_status,
-	.fifo_flush	= net2280_fifo_flush,
-};
-
-/*-------------------------------------------------------------------------*/
-
-static int net2280_get_frame (struct usb_gadget *_gadget)
-{
-	struct net2280		*dev;
-	unsigned long		flags;
-	u16			retval;
-
-	if (!_gadget)
-		return -ENODEV;
-	dev = container_of (_gadget, struct net2280, gadget);
-	spin_lock_irqsave (&dev->lock, flags);
-	retval = get_idx_reg (dev->regs, REG_FRAME) & 0x03ff;
-	spin_unlock_irqrestore (&dev->lock, flags);
-	return retval;
-}
-
-static int net2280_wakeup (struct usb_gadget *_gadget)
-{
-	struct net2280		*dev;
-	u32			tmp;
-	unsigned long		flags;
-
-	if (!_gadget)
-		return 0;
-	dev = container_of (_gadget, struct net2280, gadget);
-
-	spin_lock_irqsave (&dev->lock, flags);
-	tmp = readl (&dev->usb->usbctl);
-	if (tmp & (1 << DEVICE_REMOTE_WAKEUP_ENABLE))
-		writel (1 << GENERATE_RESUME, &dev->usb->usbstat);
-	spin_unlock_irqrestore (&dev->lock, flags);
-
-	/* pci writes may still be posted */
-	return 0;
-}
-
-static int net2280_set_selfpowered (struct usb_gadget *_gadget, int value)
-{
-	struct net2280		*dev;
-	u32			tmp;
-	unsigned long		flags;
-
-	if (!_gadget)
-		return 0;
-	dev = container_of (_gadget, struct net2280, gadget);
-
-	spin_lock_irqsave (&dev->lock, flags);
-	tmp = readl (&dev->usb->usbctl);
-	if (value)
-		tmp |= (1 << SELF_POWERED_STATUS);
-	else
-		tmp &= ~(1 << SELF_POWERED_STATUS);
-	writel (tmp, &dev->usb->usbctl);
-	spin_unlock_irqrestore (&dev->lock, flags);
-
-	return 0;
-}
-
-static int net2280_pullup(struct usb_gadget *_gadget, int is_on)
-{
-	struct net2280  *dev;
-	u32             tmp;
-	unsigned long   flags;
-
-	if (!_gadget)
-		return -ENODEV;
-	dev = container_of (_gadget, struct net2280, gadget);
-
-	spin_lock_irqsave (&dev->lock, flags);
-	tmp = readl (&dev->usb->usbctl);
-	dev->softconnect = (is_on != 0);
-	if (is_on)
-		tmp |= (1 << USB_DETECT_ENABLE);
-	else
-		tmp &= ~(1 << USB_DETECT_ENABLE);
-	writel (tmp, &dev->usb->usbctl);
-	spin_unlock_irqrestore (&dev->lock, flags);
-
-	return 0;
-}
-
-static int net2280_start(struct usb_gadget *_gadget,
-		struct usb_gadget_driver *driver);
-static int net2280_stop(struct usb_gadget *_gadget,
-		struct usb_gadget_driver *driver);
-
-static const struct usb_gadget_ops net2280_ops = {
-	.get_frame	= net2280_get_frame,
-	.wakeup		= net2280_wakeup,
-	.set_selfpowered = net2280_set_selfpowered,
-	.pullup		= net2280_pullup,
-	.udc_start	= net2280_start,
-	.udc_stop	= net2280_stop,
-};
-
-/*-------------------------------------------------------------------------*/
-
-#ifdef	CONFIG_USB_GADGET_DEBUG_FILES
-
-/* FIXME move these into procfs, and use seq_file.
- * Sysfs _still_ doesn't behave for arbitrarily sized files,
- * and also doesn't help products using this with 2.4 kernels.
- */
-
-/* "function" sysfs attribute */
-static ssize_t function_show(struct device *_dev, struct device_attribute *attr,
-			     char *buf)
-{
-	struct net2280	*dev = dev_get_drvdata (_dev);
-
-	if (!dev->driver
-			|| !dev->driver->function
-			|| strlen (dev->driver->function) > PAGE_SIZE)
-		return 0;
-	return scnprintf (buf, PAGE_SIZE, "%s\n", dev->driver->function);
-}
-static DEVICE_ATTR_RO(function);
-
-static ssize_t registers_show(struct device *_dev,
-			      struct device_attribute *attr, char *buf)
-{
-	struct net2280		*dev;
-	char			*next;
-	unsigned		size, t;
-	unsigned long		flags;
-	int			i;
-	u32			t1, t2;
-	const char		*s;
-
-	dev = dev_get_drvdata (_dev);
-	next = buf;
-	size = PAGE_SIZE;
-	spin_lock_irqsave (&dev->lock, flags);
-
-	if (dev->driver)
-		s = dev->driver->driver.name;
-	else
-		s = "(none)";
-
-	/* Main Control Registers */
-	t = scnprintf (next, size, "%s version " DRIVER_VERSION
-			", chiprev %04x, dma %s\n\n"
-			"devinit %03x fifoctl %08x gadget '%s'\n"
-			"pci irqenb0 %02x irqenb1 %08x "
-			"irqstat0 %04x irqstat1 %08x\n",
-			driver_name, dev->chiprev,
-			use_dma
-				? (use_dma_chaining ? "chaining" : "enabled")
-				: "disabled",
-			readl (&dev->regs->devinit),
-			readl (&dev->regs->fifoctl),
-			s,
-			readl (&dev->regs->pciirqenb0),
-			readl (&dev->regs->pciirqenb1),
-			readl (&dev->regs->irqstat0),
-			readl (&dev->regs->irqstat1));
-	size -= t;
-	next += t;
-
-	/* USB Control Registers */
-	t1 = readl (&dev->usb->usbctl);
-	t2 = readl (&dev->usb->usbstat);
-	if (t1 & (1 << VBUS_PIN)) {
-		if (t2 & (1 << HIGH_SPEED))
-			s = "high speed";
-		else if (dev->gadget.speed == USB_SPEED_UNKNOWN)
-			s = "powered";
-		else
-			s = "full speed";
-		/* full speed bit (6) not working?? */
-	} else
-			s = "not attached";
-	t = scnprintf (next, size,
-			"stdrsp %08x usbctl %08x usbstat %08x "
-				"addr 0x%02x (%s)\n",
-			readl (&dev->usb->stdrsp), t1, t2,
-			readl (&dev->usb->ouraddr), s);
-	size -= t;
-	next += t;
-
-	/* PCI Master Control Registers */
-
-	/* DMA Control Registers */
-
-	/* Configurable EP Control Registers */
-	for (i = 0; i < 7; i++) {
-		struct net2280_ep	*ep;
-
-		ep = &dev->ep [i];
-		if (i && !ep->desc)
-			continue;
-
-		t1 = readl (&ep->regs->ep_cfg);
-		t2 = readl (&ep->regs->ep_rsp) & 0xff;
-		t = scnprintf (next, size,
-				"\n%s\tcfg %05x rsp (%02x) %s%s%s%s%s%s%s%s"
-					"irqenb %02x\n",
-				ep->ep.name, t1, t2,
-				(t2 & (1 << CLEAR_NAK_OUT_PACKETS))
-					? "NAK " : "",
-				(t2 & (1 << CLEAR_EP_HIDE_STATUS_PHASE))
-					? "hide " : "",
-				(t2 & (1 << CLEAR_EP_FORCE_CRC_ERROR))
-					? "CRC " : "",
-				(t2 & (1 << CLEAR_INTERRUPT_MODE))
-					? "interrupt " : "",
-				(t2 & (1<<CLEAR_CONTROL_STATUS_PHASE_HANDSHAKE))
-					? "status " : "",
-				(t2 & (1 << CLEAR_NAK_OUT_PACKETS_MODE))
-					? "NAKmode " : "",
-				(t2 & (1 << CLEAR_ENDPOINT_TOGGLE))
-					? "DATA1 " : "DATA0 ",
-				(t2 & (1 << CLEAR_ENDPOINT_HALT))
-					? "HALT " : "",
-				readl (&ep->regs->ep_irqenb));
-		size -= t;
-		next += t;
-
-		t = scnprintf (next, size,
-				"\tstat %08x avail %04x "
-				"(ep%d%s-%s)%s\n",
-				readl (&ep->regs->ep_stat),
-				readl (&ep->regs->ep_avail),
-				t1 & 0x0f, DIR_STRING (t1),
-				type_string (t1 >> 8),
-				ep->stopped ? "*" : "");
-		size -= t;
-		next += t;
-
-		if (!ep->dma)
-			continue;
-
-		t = scnprintf (next, size,
-				"  dma\tctl %08x stat %08x count %08x\n"
-				"\taddr %08x desc %08x\n",
-				readl (&ep->dma->dmactl),
-				readl (&ep->dma->dmastat),
-				readl (&ep->dma->dmacount),
-				readl (&ep->dma->dmaaddr),
-				readl (&ep->dma->dmadesc));
-		size -= t;
-		next += t;
-
-	}
-
-	/* Indexed Registers */
-		// none yet
-
-	/* Statistics */
-	t = scnprintf (next, size, "\nirqs:  ");
-	size -= t;
-	next += t;
-	for (i = 0; i < 7; i++) {
-		struct net2280_ep	*ep;
-
-		ep = &dev->ep [i];
-		if (i && !ep->irqs)
-			continue;
-		t = scnprintf (next, size, " %s/%lu", ep->ep.name, ep->irqs);
-		size -= t;
-		next += t;
-
-	}
-	t = scnprintf (next, size, "\n");
-	size -= t;
-	next += t;
-
-	spin_unlock_irqrestore (&dev->lock, flags);
-
-	return PAGE_SIZE - size;
-}
-static DEVICE_ATTR_RO(registers);
-
-static ssize_t queues_show(struct device *_dev, struct device_attribute *attr,
-			   char *buf)
-{
-	struct net2280		*dev;
-	char			*next;
-	unsigned		size;
-	unsigned long		flags;
-	int			i;
-
-	dev = dev_get_drvdata (_dev);
-	next = buf;
-	size = PAGE_SIZE;
-	spin_lock_irqsave (&dev->lock, flags);
-
-	for (i = 0; i < 7; i++) {
-		struct net2280_ep		*ep = &dev->ep [i];
-		struct net2280_request		*req;
-		int				t;
-
-		if (i != 0) {
-			const struct usb_endpoint_descriptor	*d;
-
-			d = ep->desc;
-			if (!d)
-				continue;
-			t = d->bEndpointAddress;
-			t = scnprintf (next, size,
-				"\n%s (ep%d%s-%s) max %04x %s fifo %d\n",
-				ep->ep.name, t & USB_ENDPOINT_NUMBER_MASK,
-				(t & USB_DIR_IN) ? "in" : "out",
-				({ char *val;
-				 switch (d->bmAttributes & 0x03) {
-				 case USB_ENDPOINT_XFER_BULK:
-					val = "bulk"; break;
-				 case USB_ENDPOINT_XFER_INT:
-					val = "intr"; break;
-				 default:
-					val = "iso"; break;
-				 } val; }),
-				usb_endpoint_maxp (d) & 0x1fff,
-				ep->dma ? "dma" : "pio", ep->fifo_size
-				);
-		} else /* ep0 should only have one transfer queued */
-			t = scnprintf (next, size, "ep0 max 64 pio %s\n",
-					ep->is_in ? "in" : "out");
-		if (t <= 0 || t > size)
-			goto done;
-		size -= t;
-		next += t;
-
-		if (list_empty (&ep->queue)) {
-			t = scnprintf (next, size, "\t(nothing queued)\n");
-			if (t <= 0 || t > size)
-				goto done;
-			size -= t;
-			next += t;
-			continue;
-		}
-		list_for_each_entry (req, &ep->queue, queue) {
-			if (ep->dma && req->td_dma == readl (&ep->dma->dmadesc))
-				t = scnprintf (next, size,
-					"\treq %p len %d/%d "
-					"buf %p (dmacount %08x)\n",
-					&req->req, req->req.actual,
-					req->req.length, req->req.buf,
-					readl (&ep->dma->dmacount));
-			else
-				t = scnprintf (next, size,
-					"\treq %p len %d/%d buf %p\n",
-					&req->req, req->req.actual,
-					req->req.length, req->req.buf);
-			if (t <= 0 || t > size)
-				goto done;
-			size -= t;
-			next += t;
-
-			if (ep->dma) {
-				struct net2280_dma	*td;
-
-				td = req->td;
-				t = scnprintf (next, size, "\t    td %08x "
-					" count %08x buf %08x desc %08x\n",
-					(u32) req->td_dma,
-					le32_to_cpu (td->dmacount),
-					le32_to_cpu (td->dmaaddr),
-					le32_to_cpu (td->dmadesc));
-				if (t <= 0 || t > size)
-					goto done;
-				size -= t;
-				next += t;
-			}
-		}
-	}
-
-done:
-	spin_unlock_irqrestore (&dev->lock, flags);
-	return PAGE_SIZE - size;
-}
-static DEVICE_ATTR_RO(queues);
-
-
-#else
-
-#define device_create_file(a,b)	(0)
-#define device_remove_file(a,b)	do { } while (0)
-
-#endif
-
-/*-------------------------------------------------------------------------*/
-
-/* another driver-specific mode might be a request type doing dma
- * to/from another device fifo instead of to/from memory.
- */
-
-static void set_fifo_mode (struct net2280 *dev, int mode)
-{
-	/* keeping high bits preserves BAR2 */
-	writel ((0xffff << PCI_BASE2_RANGE) | mode, &dev->regs->fifoctl);
-
-	/* always ep-{a,b,e,f} ... maybe not ep-c or ep-d */
-	INIT_LIST_HEAD (&dev->gadget.ep_list);
-	list_add_tail (&dev->ep [1].ep.ep_list, &dev->gadget.ep_list);
-	list_add_tail (&dev->ep [2].ep.ep_list, &dev->gadget.ep_list);
-	switch (mode) {
-	case 0:
-		list_add_tail (&dev->ep [3].ep.ep_list, &dev->gadget.ep_list);
-		list_add_tail (&dev->ep [4].ep.ep_list, &dev->gadget.ep_list);
-		dev->ep [1].fifo_size = dev->ep [2].fifo_size = 1024;
-		break;
-	case 1:
-		dev->ep [1].fifo_size = dev->ep [2].fifo_size = 2048;
-		break;
-	case 2:
-		list_add_tail (&dev->ep [3].ep.ep_list, &dev->gadget.ep_list);
-		dev->ep [1].fifo_size = 2048;
-		dev->ep [2].fifo_size = 1024;
-		break;
-	}
-	/* fifo sizes for ep0, ep-c, ep-d, ep-e, and ep-f never change */
-	list_add_tail (&dev->ep [5].ep.ep_list, &dev->gadget.ep_list);
-	list_add_tail (&dev->ep [6].ep.ep_list, &dev->gadget.ep_list);
-}
-
-/* keeping it simple:
- * - one bus driver, initted first;
- * - one function driver, initted second
- *
- * most of the work to support multiple net2280 controllers would
- * be to associate this gadget driver (yes?) with all of them, or
- * perhaps to bind specific drivers to specific devices.
- */
-
-static void usb_reset (struct net2280 *dev)
-{
-	u32	tmp;
-
-	dev->gadget.speed = USB_SPEED_UNKNOWN;
-	(void) readl (&dev->usb->usbctl);
-
-	net2280_led_init (dev);
-
-	/* disable automatic responses, and irqs */
-	writel (0, &dev->usb->stdrsp);
-	writel (0, &dev->regs->pciirqenb0);
-	writel (0, &dev->regs->pciirqenb1);
-
-	/* clear old dma and irq state */
-	for (tmp = 0; tmp < 4; tmp++) {
-		struct net2280_ep	*ep = &dev->ep [tmp + 1];
-
-		if (ep->dma)
-			abort_dma (ep);
-	}
-	writel (~0, &dev->regs->irqstat0),
-	writel (~(1 << SUSPEND_REQUEST_INTERRUPT), &dev->regs->irqstat1),
-
-	/* reset, and enable pci */
-	tmp = readl (&dev->regs->devinit)
-		| (1 << PCI_ENABLE)
-		| (1 << FIFO_SOFT_RESET)
-		| (1 << USB_SOFT_RESET)
-		| (1 << M8051_RESET);
-	writel (tmp, &dev->regs->devinit);
-
-	/* standard fifo and endpoint allocations */
-	set_fifo_mode (dev, (fifo_mode <= 2) ? fifo_mode : 0);
-}
-
-static void usb_reinit (struct net2280 *dev)
-{
-	u32	tmp;
-	int	init_dma;
-
-	/* use_dma changes are ignored till next device re-init */
-	init_dma = use_dma;
-
-	/* basic endpoint init */
-	for (tmp = 0; tmp < 7; tmp++) {
-		struct net2280_ep	*ep = &dev->ep [tmp];
-
-		ep->ep.name = ep_name [tmp];
-		ep->dev = dev;
-		ep->num = tmp;
-
-		if (tmp > 0 && tmp <= 4) {
-			ep->fifo_size = 1024;
-			if (init_dma)
-				ep->dma = &dev->dma [tmp - 1];
-		} else
-			ep->fifo_size = 64;
-		ep->regs = &dev->epregs [tmp];
-		ep_reset (dev->regs, ep);
-	}
-	usb_ep_set_maxpacket_limit(&dev->ep [0].ep, 64);
-	usb_ep_set_maxpacket_limit(&dev->ep [5].ep, 64);
-	usb_ep_set_maxpacket_limit(&dev->ep [6].ep, 64);
-
-	dev->gadget.ep0 = &dev->ep [0].ep;
-	dev->ep [0].stopped = 0;
-	INIT_LIST_HEAD (&dev->gadget.ep0->ep_list);
-
-	/* we want to prevent lowlevel/insecure access from the USB host,
-	 * but erratum 0119 means this enable bit is ignored
-	 */
-	for (tmp = 0; tmp < 5; tmp++)
-		writel (EP_DONTUSE, &dev->dep [tmp].dep_cfg);
-}
-
-static void ep0_start (struct net2280 *dev)
-{
-	writel (  (1 << CLEAR_EP_HIDE_STATUS_PHASE)
-		| (1 << CLEAR_NAK_OUT_PACKETS)
-		| (1 << CLEAR_CONTROL_STATUS_PHASE_HANDSHAKE)
-		, &dev->epregs [0].ep_rsp);
-
-	/*
-	 * hardware optionally handles a bunch of standard requests
-	 * that the API hides from drivers anyway.  have it do so.
-	 * endpoint status/features are handled in software, to
-	 * help pass tests for some dubious behavior.
-	 */
-	writel (  (1 << SET_TEST_MODE)
-		| (1 << SET_ADDRESS)
-		| (1 << DEVICE_SET_CLEAR_DEVICE_REMOTE_WAKEUP)
-		| (1 << GET_DEVICE_STATUS)
-		| (1 << GET_INTERFACE_STATUS)
-		, &dev->usb->stdrsp);
-	writel (  (1 << USB_ROOT_PORT_WAKEUP_ENABLE)
-		| (1 << SELF_POWERED_USB_DEVICE)
-		| (1 << REMOTE_WAKEUP_SUPPORT)
-		| (dev->softconnect << USB_DETECT_ENABLE)
-		| (1 << SELF_POWERED_STATUS)
-		, &dev->usb->usbctl);
-
-	/* enable irqs so we can see ep0 and general operation  */
-	writel (  (1 << SETUP_PACKET_INTERRUPT_ENABLE)
-		| (1 << ENDPOINT_0_INTERRUPT_ENABLE)
-		, &dev->regs->pciirqenb0);
-	writel (  (1 << PCI_INTERRUPT_ENABLE)
-		| (1 << PCI_MASTER_ABORT_RECEIVED_INTERRUPT_ENABLE)
-		| (1 << PCI_TARGET_ABORT_RECEIVED_INTERRUPT_ENABLE)
-		| (1 << PCI_RETRY_ABORT_INTERRUPT_ENABLE)
-		| (1 << VBUS_INTERRUPT_ENABLE)
-		| (1 << ROOT_PORT_RESET_INTERRUPT_ENABLE)
-		| (1 << SUSPEND_REQUEST_CHANGE_INTERRUPT_ENABLE)
-		, &dev->regs->pciirqenb1);
-
-	/* don't leave any writes posted */
-	(void) readl (&dev->usb->usbctl);
-}
-
-/* when a driver is successfully registered, it will receive
- * control requests including set_configuration(), which enables
- * non-control requests.  then usb traffic follows until a
- * disconnect is reported.  then a host may connect again, or
- * the driver might get unbound.
- */
-static int net2280_start(struct usb_gadget *_gadget,
-		struct usb_gadget_driver *driver)
-{
-	struct net2280		*dev;
-	int			retval;
-	unsigned		i;
-
-	/* insist on high speed support from the driver, since
-	 * (dev->usb->xcvrdiag & FORCE_FULL_SPEED_MODE)
-	 * "must not be used in normal operation"
-	 */
-	if (!driver || driver->max_speed < USB_SPEED_HIGH
-			|| !driver->setup)
-		return -EINVAL;
-
-	dev = container_of (_gadget, struct net2280, gadget);
-
-	for (i = 0; i < 7; i++)
-		dev->ep [i].irqs = 0;
-
-	/* hook up the driver ... */
-	dev->softconnect = 1;
-	driver->driver.bus = NULL;
-	dev->driver = driver;
-
-	retval = device_create_file (&dev->pdev->dev, &dev_attr_function);
-	if (retval) goto err_unbind;
-	retval = device_create_file (&dev->pdev->dev, &dev_attr_queues);
-	if (retval) goto err_func;
-
-	/* Enable force-full-speed testing mode, if desired */
-	if (full_speed)
-		writel(1 << FORCE_FULL_SPEED_MODE, &dev->usb->xcvrdiag);
-
-	/* ... then enable host detection and ep0; and we're ready
-	 * for set_configuration as well as eventual disconnect.
-	 */
-	net2280_led_active (dev, 1);
-	ep0_start (dev);
-
-	DEBUG (dev, "%s ready, usbctl %08x stdrsp %08x\n",
-			driver->driver.name,
-			readl (&dev->usb->usbctl),
-			readl (&dev->usb->stdrsp));
-
-	/* pci writes may still be posted */
-	return 0;
-
-err_func:
-	device_remove_file (&dev->pdev->dev, &dev_attr_function);
-err_unbind:
-	dev->driver = NULL;
-	return retval;
-}
-
-static void
-stop_activity (struct net2280 *dev, struct usb_gadget_driver *driver)
-{
-	int			i;
-
-	/* don't disconnect if it's not connected */
-	if (dev->gadget.speed == USB_SPEED_UNKNOWN)
-		driver = NULL;
-
-	/* stop hardware; prevent new request submissions;
-	 * and kill any outstanding requests.
-	 */
-	usb_reset (dev);
-	for (i = 0; i < 7; i++)
-		nuke (&dev->ep [i]);
-
-	/* report disconnect; the driver is already quiesced */
-	if (driver) {
-		spin_unlock(&dev->lock);
-		driver->disconnect(&dev->gadget);
-		spin_lock(&dev->lock);
-	}
-
-	usb_reinit (dev);
-}
-
-static int net2280_stop(struct usb_gadget *_gadget,
-		struct usb_gadget_driver *driver)
-{
-	struct net2280	*dev;
-	unsigned long	flags;
-
-	dev = container_of (_gadget, struct net2280, gadget);
-
-	spin_lock_irqsave (&dev->lock, flags);
-	stop_activity (dev, driver);
-	spin_unlock_irqrestore (&dev->lock, flags);
-
-	dev->driver = NULL;
-
-	net2280_led_active (dev, 0);
-
-	/* Disable full-speed test mode */
-	writel(0, &dev->usb->xcvrdiag);
-
-	device_remove_file (&dev->pdev->dev, &dev_attr_function);
-	device_remove_file (&dev->pdev->dev, &dev_attr_queues);
-
-	DEBUG(dev, "unregistered driver '%s'\n",
-			driver ? driver->driver.name : "");
-
-	return 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* handle ep0, ep-e, ep-f with 64 byte packets: packet per irq.
- * also works for dma-capable endpoints, in pio mode or just
- * to manually advance the queue after short OUT transfers.
- */
-static void handle_ep_small (struct net2280_ep *ep)
-{
-	struct net2280_request	*req;
-	u32			t;
-	/* 0 error, 1 mid-data, 2 done */
-	int			mode = 1;
-
-	if (!list_empty (&ep->queue))
-		req = list_entry (ep->queue.next,
-			struct net2280_request, queue);
-	else
-		req = NULL;
-
-	/* ack all, and handle what we care about */
-	t = readl (&ep->regs->ep_stat);
-	ep->irqs++;
-#if 0
-	VDEBUG (ep->dev, "%s ack ep_stat %08x, req %p\n",
-			ep->ep.name, t, req ? &req->req : 0);
-#endif
-	if (!ep->is_in || ep->dev->pdev->device == 0x2280)
-		writel (t & ~(1 << NAK_OUT_PACKETS), &ep->regs->ep_stat);
-	else
-		/* Added for 2282 */
-		writel (t, &ep->regs->ep_stat);
-
-	/* for ep0, monitor token irqs to catch data stage length errors
-	 * and to synchronize on status.
-	 *
-	 * also, to defer reporting of protocol stalls ... here's where
-	 * data or status first appears, handling stalls here should never
-	 * cause trouble on the host side..
-	 *
-	 * control requests could be slightly faster without token synch for
-	 * status, but status can jam up that way.
-	 */
-	if (unlikely (ep->num == 0)) {
-		if (ep->is_in) {
-			/* status; stop NAKing */
-			if (t & (1 << DATA_OUT_PING_TOKEN_INTERRUPT)) {
-				if (ep->dev->protocol_stall) {
-					ep->stopped = 1;
-					set_halt (ep);
-				}
-				if (!req)
-					allow_status (ep);
-				mode = 2;
-			/* reply to extra IN data tokens with a zlp */
-			} else if (t & (1 << DATA_IN_TOKEN_INTERRUPT)) {
-				if (ep->dev->protocol_stall) {
-					ep->stopped = 1;
-					set_halt (ep);
-					mode = 2;
-				} else if (ep->responded &&
-						!req && !ep->stopped)
-					write_fifo (ep, NULL);
-			}
-		} else {
-			/* status; stop NAKing */
-			if (t & (1 << DATA_IN_TOKEN_INTERRUPT)) {
-				if (ep->dev->protocol_stall) {
-					ep->stopped = 1;
-					set_halt (ep);
-				}
-				mode = 2;
-			/* an extra OUT token is an error */
-			} else if (((t & (1 << DATA_OUT_PING_TOKEN_INTERRUPT))
-					&& req
-					&& req->req.actual == req->req.length)
-					|| (ep->responded && !req)) {
-				ep->dev->protocol_stall = 1;
-				set_halt (ep);
-				ep->stopped = 1;
-				if (req)
-					done (ep, req, -EOVERFLOW);
-				req = NULL;
-			}
-		}
-	}
-
-	if (unlikely (!req))
-		return;
-
-	/* manual DMA queue advance after short OUT */
-	if (likely (ep->dma)) {
-		if (t & (1 << SHORT_PACKET_TRANSFERRED_INTERRUPT)) {
-			u32	count;
-			int	stopped = ep->stopped;
-
-			/* TRANSFERRED works around OUT_DONE erratum 0112.
-			 * we expect (N <= maxpacket) bytes; host wrote M.
-			 * iff (M < N) we won't ever see a DMA interrupt.
-			 */
-			ep->stopped = 1;
-			for (count = 0; ; t = readl (&ep->regs->ep_stat)) {
-
-				/* any preceding dma transfers must finish.
-				 * dma handles (M >= N), may empty the queue
-				 */
-				scan_dma_completions (ep);
-				if (unlikely (list_empty (&ep->queue)
-						|| ep->out_overflow)) {
-					req = NULL;
-					break;
-				}
-				req = list_entry (ep->queue.next,
-					struct net2280_request, queue);
-
-				/* here either (M < N), a "real" short rx;
-				 * or (M == N) and the queue didn't empty
-				 */
-				if (likely (t & (1 << FIFO_EMPTY))) {
-					count = readl (&ep->dma->dmacount);
-					count &= DMA_BYTE_COUNT_MASK;
-					if (readl (&ep->dma->dmadesc)
-							!= req->td_dma)
-						req = NULL;
-					break;
-				}
-				udelay(1);
-			}
-
-			/* stop DMA, leave ep NAKing */
-			writel ((1 << DMA_ABORT), &ep->dma->dmastat);
-			spin_stop_dma (ep->dma);
-
-			if (likely (req)) {
-				req->td->dmacount = 0;
-				t = readl (&ep->regs->ep_avail);
-				dma_done (ep, req, count,
-					(ep->out_overflow || t)
-						? -EOVERFLOW : 0);
-			}
-
-			/* also flush to prevent erratum 0106 trouble */
-			if (unlikely (ep->out_overflow
-					|| (ep->dev->chiprev == 0x0100
-						&& ep->dev->gadget.speed
-							== USB_SPEED_FULL))) {
-				out_flush (ep);
-				ep->out_overflow = 0;
-			}
-
-			/* (re)start dma if needed, stop NAKing */
-			ep->stopped = stopped;
-			if (!list_empty (&ep->queue))
-				restart_dma (ep);
-		} else
-			DEBUG (ep->dev, "%s dma ep_stat %08x ??\n",
-					ep->ep.name, t);
-		return;
-
-	/* data packet(s) received (in the fifo, OUT) */
-	} else if (t & (1 << DATA_PACKET_RECEIVED_INTERRUPT)) {
-		if (read_fifo (ep, req) && ep->num != 0)
-			mode = 2;
-
-	/* data packet(s) transmitted (IN) */
-	} else if (t & (1 << DATA_PACKET_TRANSMITTED_INTERRUPT)) {
-		unsigned	len;
-
-		len = req->req.length - req->req.actual;
-		if (len > ep->ep.maxpacket)
-			len = ep->ep.maxpacket;
-		req->req.actual += len;
-
-		/* if we wrote it all, we're usually done */
-		if (req->req.actual == req->req.length) {
-			if (ep->num == 0) {
-				/* send zlps until the status stage */
-			} else if (!req->req.zero || len != ep->ep.maxpacket)
-				mode = 2;
-		}
-
-	/* there was nothing to do ...  */
-	} else if (mode == 1)
-		return;
-
-	/* done */
-	if (mode == 2) {
-		/* stream endpoints often resubmit/unlink in completion */
-		done (ep, req, 0);
-
-		/* maybe advance queue to next request */
-		if (ep->num == 0) {
-			/* NOTE:  net2280 could let gadget driver start the
-			 * status stage later. since not all controllers let
-			 * them control that, the api doesn't (yet) allow it.
-			 */
-			if (!ep->stopped)
-				allow_status (ep);
-			req = NULL;
-		} else {
-			if (!list_empty (&ep->queue) && !ep->stopped)
-				req = list_entry (ep->queue.next,
-					struct net2280_request, queue);
-			else
-				req = NULL;
-			if (req && !ep->is_in)
-				stop_out_naking (ep);
-		}
-	}
-
-	/* is there a buffer for the next packet?
-	 * for best streaming performance, make sure there is one.
-	 */
-	if (req && !ep->stopped) {
-
-		/* load IN fifo with next packet (may be zlp) */
-		if (t & (1 << DATA_PACKET_TRANSMITTED_INTERRUPT))
-			write_fifo (ep, &req->req);
-	}
-}
-
-static struct net2280_ep *
-get_ep_by_addr (struct net2280 *dev, u16 wIndex)
-{
-	struct net2280_ep	*ep;
-
-	if ((wIndex & USB_ENDPOINT_NUMBER_MASK) == 0)
-		return &dev->ep [0];
-	list_for_each_entry (ep, &dev->gadget.ep_list, ep.ep_list) {
-		u8	bEndpointAddress;
-
-		if (!ep->desc)
-			continue;
-		bEndpointAddress = ep->desc->bEndpointAddress;
-		if ((wIndex ^ bEndpointAddress) & USB_DIR_IN)
-			continue;
-		if ((wIndex & 0x0f) == (bEndpointAddress & 0x0f))
-			return ep;
-	}
-	return NULL;
-}
-
-static void handle_stat0_irqs (struct net2280 *dev, u32 stat)
-{
-	struct net2280_ep	*ep;
-	u32			num, scratch;
-
-	/* most of these don't need individual acks */
-	stat &= ~(1 << INTA_ASSERTED);
-	if (!stat)
-		return;
-	// DEBUG (dev, "irqstat0 %04x\n", stat);
-
-	/* starting a control request? */
-	if (unlikely (stat & (1 << SETUP_PACKET_INTERRUPT))) {
-		union {
-			u32			raw [2];
-			struct usb_ctrlrequest	r;
-		} u;
-		int				tmp;
-		struct net2280_request		*req;
-
-		if (dev->gadget.speed == USB_SPEED_UNKNOWN) {
-			if (readl (&dev->usb->usbstat) & (1 << HIGH_SPEED))
-				dev->gadget.speed = USB_SPEED_HIGH;
-			else
-				dev->gadget.speed = USB_SPEED_FULL;
-			net2280_led_speed (dev, dev->gadget.speed);
-			DEBUG(dev, "%s\n", usb_speed_string(dev->gadget.speed));
-		}
-
-		ep = &dev->ep [0];
-		ep->irqs++;
-
-		/* make sure any leftover request state is cleared */
-		stat &= ~(1 << ENDPOINT_0_INTERRUPT);
-		while (!list_empty (&ep->queue)) {
-			req = list_entry (ep->queue.next,
-					struct net2280_request, queue);
-			done (ep, req, (req->req.actual == req->req.length)
-						? 0 : -EPROTO);
-		}
-		ep->stopped = 0;
-		dev->protocol_stall = 0;
-
-		if (ep->dev->pdev->device == 0x2280)
-			tmp = (1 << FIFO_OVERFLOW)
-				| (1 << FIFO_UNDERFLOW);
-		else
-			tmp = 0;
-
-		writel (tmp | (1 << TIMEOUT)
-			| (1 << USB_STALL_SENT)
-			| (1 << USB_IN_NAK_SENT)
-			| (1 << USB_IN_ACK_RCVD)
-			| (1 << USB_OUT_PING_NAK_SENT)
-			| (1 << USB_OUT_ACK_SENT)
-			| (1 << SHORT_PACKET_OUT_DONE_INTERRUPT)
-			| (1 << SHORT_PACKET_TRANSFERRED_INTERRUPT)
-			| (1 << DATA_PACKET_RECEIVED_INTERRUPT)
-			| (1 << DATA_PACKET_TRANSMITTED_INTERRUPT)
-			| (1 << DATA_OUT_PING_TOKEN_INTERRUPT)
-			| (1 << DATA_IN_TOKEN_INTERRUPT)
-			, &ep->regs->ep_stat);
-		u.raw [0] = readl (&dev->usb->setup0123);
-		u.raw [1] = readl (&dev->usb->setup4567);
-
-		cpu_to_le32s (&u.raw [0]);
-		cpu_to_le32s (&u.raw [1]);
-
-		tmp = 0;
-
-#define	w_value		le16_to_cpu(u.r.wValue)
-#define	w_index		le16_to_cpu(u.r.wIndex)
-#define	w_length	le16_to_cpu(u.r.wLength)
-
-		/* ack the irq */
-		writel (1 << SETUP_PACKET_INTERRUPT, &dev->regs->irqstat0);
-		stat ^= (1 << SETUP_PACKET_INTERRUPT);
-
-		/* watch control traffic at the token level, and force
-		 * synchronization before letting the status stage happen.
-		 * FIXME ignore tokens we'll NAK, until driver responds.
-		 * that'll mean a lot less irqs for some drivers.
-		 */
-		ep->is_in = (u.r.bRequestType & USB_DIR_IN) != 0;
-		if (ep->is_in) {
-			scratch = (1 << DATA_PACKET_TRANSMITTED_INTERRUPT)
-				| (1 << DATA_OUT_PING_TOKEN_INTERRUPT)
-				| (1 << DATA_IN_TOKEN_INTERRUPT);
-			stop_out_naking (ep);
-		} else
-			scratch = (1 << DATA_PACKET_RECEIVED_INTERRUPT)
-				| (1 << DATA_OUT_PING_TOKEN_INTERRUPT)
-				| (1 << DATA_IN_TOKEN_INTERRUPT);
-		writel (scratch, &dev->epregs [0].ep_irqenb);
-
-		/* we made the hardware handle most lowlevel requests;
-		 * everything else goes uplevel to the gadget code.
-		 */
-		ep->responded = 1;
-		switch (u.r.bRequest) {
-		case USB_REQ_GET_STATUS: {
-			struct net2280_ep	*e;
-			__le32			status;
-
-			/* hw handles device and interface status */
-			if (u.r.bRequestType != (USB_DIR_IN|USB_RECIP_ENDPOINT))
-				goto delegate;
-			if ((e = get_ep_by_addr (dev, w_index)) == NULL
-					|| w_length > 2)
-				goto do_stall;
-
-			if (readl (&e->regs->ep_rsp)
-					& (1 << SET_ENDPOINT_HALT))
-				status = cpu_to_le32 (1);
-			else
-				status = cpu_to_le32 (0);
-
-			/* don't bother with a request object! */
-			writel (0, &dev->epregs [0].ep_irqenb);
-			set_fifo_bytecount (ep, w_length);
-			writel ((__force u32)status, &dev->epregs [0].ep_data);
-			allow_status (ep);
-			VDEBUG (dev, "%s stat %02x\n", ep->ep.name, status);
-			goto next_endpoints;
-			}
-			break;
-		case USB_REQ_CLEAR_FEATURE: {
-			struct net2280_ep	*e;
-
-			/* hw handles device features */
-			if (u.r.bRequestType != USB_RECIP_ENDPOINT)
-				goto delegate;
-			if (w_value != USB_ENDPOINT_HALT
-					|| w_length != 0)
-				goto do_stall;
-			if ((e = get_ep_by_addr (dev, w_index)) == NULL)
-				goto do_stall;
-			if (e->wedged) {
-				VDEBUG(dev, "%s wedged, halt not cleared\n",
-						ep->ep.name);
-			} else {
-				VDEBUG(dev, "%s clear halt\n", ep->ep.name);
-				clear_halt(e);
-			}
-			allow_status (ep);
-			goto next_endpoints;
-			}
-			break;
-		case USB_REQ_SET_FEATURE: {
-			struct net2280_ep	*e;
-
-			/* hw handles device features */
-			if (u.r.bRequestType != USB_RECIP_ENDPOINT)
-				goto delegate;
-			if (w_value != USB_ENDPOINT_HALT
-					|| w_length != 0)
-				goto do_stall;
-			if ((e = get_ep_by_addr (dev, w_index)) == NULL)
-				goto do_stall;
-			if (e->ep.name == ep0name)
-				goto do_stall;
-			set_halt (e);
-			allow_status (ep);
-			VDEBUG (dev, "%s set halt\n", ep->ep.name);
-			goto next_endpoints;
-			}
-			break;
-		default:
-delegate:
-			VDEBUG (dev, "setup %02x.%02x v%04x i%04x l%04x "
-				"ep_cfg %08x\n",
-				u.r.bRequestType, u.r.bRequest,
-				w_value, w_index, w_length,
-				readl (&ep->regs->ep_cfg));
-			ep->responded = 0;
-			spin_unlock (&dev->lock);
-			tmp = dev->driver->setup (&dev->gadget, &u.r);
-			spin_lock (&dev->lock);
-		}
-
-		/* stall ep0 on error */
-		if (tmp < 0) {
-do_stall:
-			VDEBUG (dev, "req %02x.%02x protocol STALL; stat %d\n",
-					u.r.bRequestType, u.r.bRequest, tmp);
-			dev->protocol_stall = 1;
-		}
-
-		/* some in/out token irq should follow; maybe stall then.
-		 * driver must queue a request (even zlp) or halt ep0
-		 * before the host times out.
-		 */
-	}
-
-#undef	w_value
-#undef	w_index
-#undef	w_length
-
-next_endpoints:
-	/* endpoint data irq ? */
-	scratch = stat & 0x7f;
-	stat &= ~0x7f;
-	for (num = 0; scratch; num++) {
-		u32		t;
-
-		/* do this endpoint's FIFO and queue need tending? */
-		t = 1 << num;
-		if ((scratch & t) == 0)
-			continue;
-		scratch ^= t;
-
-		ep = &dev->ep [num];
-		handle_ep_small (ep);
-	}
-
-	if (stat)
-		DEBUG (dev, "unhandled irqstat0 %08x\n", stat);
-}
-
-#define DMA_INTERRUPTS ( \
-		  (1 << DMA_D_INTERRUPT) \
-		| (1 << DMA_C_INTERRUPT) \
-		| (1 << DMA_B_INTERRUPT) \
-		| (1 << DMA_A_INTERRUPT))
-#define	PCI_ERROR_INTERRUPTS ( \
-		  (1 << PCI_MASTER_ABORT_RECEIVED_INTERRUPT) \
-		| (1 << PCI_TARGET_ABORT_RECEIVED_INTERRUPT) \
-		| (1 << PCI_RETRY_ABORT_INTERRUPT))
-
-static void handle_stat1_irqs (struct net2280 *dev, u32 stat)
-{
-	struct net2280_ep	*ep;
-	u32			tmp, num, mask, scratch;
-
-	/* after disconnect there's nothing else to do! */
-	tmp = (1 << VBUS_INTERRUPT) | (1 << ROOT_PORT_RESET_INTERRUPT);
-	mask = (1 << HIGH_SPEED) | (1 << FULL_SPEED);
-
-	/* VBUS disconnect is indicated by VBUS_PIN and VBUS_INTERRUPT set.
-	 * Root Port Reset is indicated by ROOT_PORT_RESET_INTERRUPT set and
-	 * both HIGH_SPEED and FULL_SPEED clear (as ROOT_PORT_RESET_INTERRUPT
-	 * only indicates a change in the reset state).
-	 */
-	if (stat & tmp) {
-		writel (tmp, &dev->regs->irqstat1);
-		if ((((stat & (1 << ROOT_PORT_RESET_INTERRUPT))
-					&& ((readl (&dev->usb->usbstat) & mask)
-							== 0))
-				|| ((readl (&dev->usb->usbctl)
-					& (1 << VBUS_PIN)) == 0)
-			    ) && ( dev->gadget.speed != USB_SPEED_UNKNOWN)) {
-			DEBUG (dev, "disconnect %s\n",
-					dev->driver->driver.name);
-			stop_activity (dev, dev->driver);
-			ep0_start (dev);
-			return;
-		}
-		stat &= ~tmp;
-
-		/* vBUS can bounce ... one of many reasons to ignore the
-		 * notion of hotplug events on bus connect/disconnect!
-		 */
-		if (!stat)
-			return;
-	}
-
-	/* NOTE: chip stays in PCI D0 state for now, but it could
-	 * enter D1 to save more power
-	 */
-	tmp = (1 << SUSPEND_REQUEST_CHANGE_INTERRUPT);
-	if (stat & tmp) {
-		writel (tmp, &dev->regs->irqstat1);
-		if (stat & (1 << SUSPEND_REQUEST_INTERRUPT)) {
-			if (dev->driver->suspend)
-				dev->driver->suspend (&dev->gadget);
-			if (!enable_suspend)
-				stat &= ~(1 << SUSPEND_REQUEST_INTERRUPT);
-		} else {
-			if (dev->driver->resume)
-				dev->driver->resume (&dev->gadget);
-			/* at high speed, note erratum 0133 */
-		}
-		stat &= ~tmp;
-	}
-
-	/* clear any other status/irqs */
-	if (stat)
-		writel (stat, &dev->regs->irqstat1);
-
-	/* some status we can just ignore */
-	if (dev->pdev->device == 0x2280)
-		stat &= ~((1 << CONTROL_STATUS_INTERRUPT)
-			  | (1 << SUSPEND_REQUEST_INTERRUPT)
-			  | (1 << RESUME_INTERRUPT)
-			  | (1 << SOF_INTERRUPT));
-	else
-		stat &= ~((1 << CONTROL_STATUS_INTERRUPT)
-			  | (1 << RESUME_INTERRUPT)
-			  | (1 << SOF_DOWN_INTERRUPT)
-			  | (1 << SOF_INTERRUPT));
-
-	if (!stat)
-		return;
-	// DEBUG (dev, "irqstat1 %08x\n", stat);
-
-	/* DMA status, for ep-{a,b,c,d} */
-	scratch = stat & DMA_INTERRUPTS;
-	stat &= ~DMA_INTERRUPTS;
-	scratch >>= 9;
-	for (num = 0; scratch; num++) {
-		struct net2280_dma_regs	__iomem *dma;
-
-		tmp = 1 << num;
-		if ((tmp & scratch) == 0)
-			continue;
-		scratch ^= tmp;
-
-		ep = &dev->ep [num + 1];
-		dma = ep->dma;
-
-		if (!dma)
-			continue;
-
-		/* clear ep's dma status */
-		tmp = readl (&dma->dmastat);
-		writel (tmp, &dma->dmastat);
-
-		/* chaining should stop on abort, short OUT from fifo,
-		 * or (stat0 codepath) short OUT transfer.
-		 */
-		if (!use_dma_chaining) {
-			if ((tmp & (1 << DMA_TRANSACTION_DONE_INTERRUPT))
-					== 0) {
-				DEBUG (ep->dev, "%s no xact done? %08x\n",
-					ep->ep.name, tmp);
-				continue;
-			}
-			stop_dma (ep->dma);
-		}
-
-		/* OUT transfers terminate when the data from the
-		 * host is in our memory.  Process whatever's done.
-		 * On this path, we know transfer's last packet wasn't
-		 * less than req->length. NAK_OUT_PACKETS may be set,
-		 * or the FIFO may already be holding new packets.
-		 *
-		 * IN transfers can linger in the FIFO for a very
-		 * long time ... we ignore that for now, accounting
-		 * precisely (like PIO does) needs per-packet irqs
-		 */
-		scan_dma_completions (ep);
-
-		/* disable dma on inactive queues; else maybe restart */
-		if (list_empty (&ep->queue)) {
-			if (use_dma_chaining)
-				stop_dma (ep->dma);
-		} else {
-			tmp = readl (&dma->dmactl);
-			if (!use_dma_chaining
-					|| (tmp & (1 << DMA_ENABLE)) == 0)
-				restart_dma (ep);
-			else if (ep->is_in && use_dma_chaining) {
-				struct net2280_request	*req;
-				__le32			dmacount;
-
-				/* the descriptor at the head of the chain
-				 * may still have VALID_BIT clear; that's
-				 * used to trigger changing DMA_FIFO_VALIDATE
-				 * (affects automagic zlp writes).
-				 */
-				req = list_entry (ep->queue.next,
-						struct net2280_request, queue);
-				dmacount = req->td->dmacount;
-				dmacount &= cpu_to_le32 (
-						(1 << VALID_BIT)
-						| DMA_BYTE_COUNT_MASK);
-				if (dmacount && (dmacount & valid_bit) == 0)
-					restart_dma (ep);
-			}
-		}
-		ep->irqs++;
-	}
-
-	/* NOTE:  there are other PCI errors we might usefully notice.
-	 * if they appear very often, here's where to try recovering.
-	 */
-	if (stat & PCI_ERROR_INTERRUPTS) {
-		ERROR (dev, "pci dma error; stat %08x\n", stat);
-		stat &= ~PCI_ERROR_INTERRUPTS;
-		/* these are fatal errors, but "maybe" they won't
-		 * happen again ...
-		 */
-		stop_activity (dev, dev->driver);
-		ep0_start (dev);
-		stat = 0;
-	}
-
-	if (stat)
-		DEBUG (dev, "unhandled irqstat1 %08x\n", stat);
-}
-
-static irqreturn_t net2280_irq (int irq, void *_dev)
-{
-	struct net2280		*dev = _dev;
-
-	/* shared interrupt, not ours */
-	if (!(readl(&dev->regs->irqstat0) & (1 << INTA_ASSERTED)))
-		return IRQ_NONE;
-
-	spin_lock (&dev->lock);
-
-	/* handle disconnect, dma, and more */
-	handle_stat1_irqs (dev, readl (&dev->regs->irqstat1));
-
-	/* control requests and PIO */
-	handle_stat0_irqs (dev, readl (&dev->regs->irqstat0));
-
-	spin_unlock (&dev->lock);
-
-	return IRQ_HANDLED;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static void gadget_release (struct device *_dev)
-{
-	struct net2280	*dev = dev_get_drvdata (_dev);
-
-	kfree (dev);
-}
-
-/* tear down the binding between this driver and the pci device */
-
-static void net2280_remove (struct pci_dev *pdev)
-{
-	struct net2280		*dev = pci_get_drvdata (pdev);
-
-	usb_del_gadget_udc(&dev->gadget);
-
-	BUG_ON(dev->driver);
-
-	/* then clean up the resources we allocated during probe() */
-	net2280_led_shutdown (dev);
-	if (dev->requests) {
-		int		i;
-		for (i = 1; i < 5; i++) {
-			if (!dev->ep [i].dummy)
-				continue;
-			pci_pool_free (dev->requests, dev->ep [i].dummy,
-					dev->ep [i].td_dma);
-		}
-		pci_pool_destroy (dev->requests);
-	}
-	if (dev->got_irq)
-		free_irq (pdev->irq, dev);
-	if (dev->regs)
-		iounmap (dev->regs);
-	if (dev->region)
-		release_mem_region (pci_resource_start (pdev, 0),
-				pci_resource_len (pdev, 0));
-	if (dev->enabled)
-		pci_disable_device (pdev);
-	device_remove_file (&pdev->dev, &dev_attr_registers);
-
-	INFO (dev, "unbind\n");
-}
-
-/* wrap this driver around the specified device, but
- * don't respond over USB until a gadget driver binds to us.
- */
-
-static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id)
-{
-	struct net2280		*dev;
-	unsigned long		resource, len;
-	void			__iomem *base = NULL;
-	int			retval, i;
-
-	/* alloc, and start init */
-	dev = kzalloc (sizeof *dev, GFP_KERNEL);
-	if (dev == NULL){
-		retval = -ENOMEM;
-		goto done;
-	}
-
-	pci_set_drvdata (pdev, dev);
-	spin_lock_init (&dev->lock);
-	dev->pdev = pdev;
-	dev->gadget.ops = &net2280_ops;
-	dev->gadget.max_speed = USB_SPEED_HIGH;
-
-	/* the "gadget" abstracts/virtualizes the controller */
-	dev->gadget.name = driver_name;
-
-	/* now all the pci goodies ... */
-	if (pci_enable_device (pdev) < 0) {
-	        retval = -ENODEV;
-		goto done;
-	}
-	dev->enabled = 1;
-
-	/* BAR 0 holds all the registers
-	 * BAR 1 is 8051 memory; unused here (note erratum 0103)
-	 * BAR 2 is fifo memory; unused here
-	 */
-	resource = pci_resource_start (pdev, 0);
-	len = pci_resource_len (pdev, 0);
-	if (!request_mem_region (resource, len, driver_name)) {
-		DEBUG (dev, "controller already in use\n");
-		retval = -EBUSY;
-		goto done;
-	}
-	dev->region = 1;
-
-	/* FIXME provide firmware download interface to put
-	 * 8051 code into the chip, e.g. to turn on PCI PM.
-	 */
-
-	base = ioremap_nocache (resource, len);
-	if (base == NULL) {
-		DEBUG (dev, "can't map memory\n");
-		retval = -EFAULT;
-		goto done;
-	}
-	dev->regs = (struct net2280_regs __iomem *) base;
-	dev->usb = (struct net2280_usb_regs __iomem *) (base + 0x0080);
-	dev->pci = (struct net2280_pci_regs __iomem *) (base + 0x0100);
-	dev->dma = (struct net2280_dma_regs __iomem *) (base + 0x0180);
-	dev->dep = (struct net2280_dep_regs __iomem *) (base + 0x0200);
-	dev->epregs = (struct net2280_ep_regs __iomem *) (base + 0x0300);
-
-	/* put into initial config, link up all endpoints */
-	writel (0, &dev->usb->usbctl);
-	usb_reset (dev);
-	usb_reinit (dev);
-
-	/* irq setup after old hardware is cleaned up */
-	if (!pdev->irq) {
-		ERROR (dev, "No IRQ.  Check PCI setup!\n");
-		retval = -ENODEV;
-		goto done;
-	}
-
-	if (request_irq (pdev->irq, net2280_irq, IRQF_SHARED, driver_name, dev)
-			!= 0) {
-		ERROR (dev, "request interrupt %d failed\n", pdev->irq);
-		retval = -EBUSY;
-		goto done;
-	}
-	dev->got_irq = 1;
-
-	/* DMA setup */
-	/* NOTE:  we know only the 32 LSBs of dma addresses may be nonzero */
-	dev->requests = pci_pool_create ("requests", pdev,
-		sizeof (struct net2280_dma),
-		0 /* no alignment requirements */,
-		0 /* or page-crossing issues */);
-	if (!dev->requests) {
-		DEBUG (dev, "can't get request pool\n");
-		retval = -ENOMEM;
-		goto done;
-	}
-	for (i = 1; i < 5; i++) {
-		struct net2280_dma	*td;
-
-		td = pci_pool_alloc (dev->requests, GFP_KERNEL,
-				&dev->ep [i].td_dma);
-		if (!td) {
-			DEBUG (dev, "can't get dummy %d\n", i);
-			retval = -ENOMEM;
-			goto done;
-		}
-		td->dmacount = 0;	/* not VALID */
-		td->dmadesc = td->dmaaddr;
-		dev->ep [i].dummy = td;
-	}
-
-	/* enable lower-overhead pci memory bursts during DMA */
-	writel ( (1 << DMA_MEMORY_WRITE_AND_INVALIDATE_ENABLE)
-			// 256 write retries may not be enough...
-			// | (1 << PCI_RETRY_ABORT_ENABLE)
-			| (1 << DMA_READ_MULTIPLE_ENABLE)
-			| (1 << DMA_READ_LINE_ENABLE)
-			, &dev->pci->pcimstctl);
-	/* erratum 0115 shouldn't appear: Linux inits PCI_LATENCY_TIMER */
-	pci_set_master (pdev);
-	pci_try_set_mwi (pdev);
-
-	/* ... also flushes any posted pci writes */
-	dev->chiprev = get_idx_reg (dev->regs, REG_CHIPREV) & 0xffff;
-
-	/* done */
-	INFO (dev, "%s\n", driver_desc);
-	INFO (dev, "irq %d, pci mem %p, chip rev %04x\n",
-			pdev->irq, base, dev->chiprev);
-	INFO (dev, "version: " DRIVER_VERSION "; dma %s\n",
-			use_dma
-				? (use_dma_chaining ? "chaining" : "enabled")
-				: "disabled");
-	retval = device_create_file (&pdev->dev, &dev_attr_registers);
-	if (retval) goto done;
-
-	retval = usb_add_gadget_udc_release(&pdev->dev, &dev->gadget,
-			gadget_release);
-	if (retval)
-		goto done;
-	return 0;
-
-done:
-	if (dev)
-		net2280_remove (pdev);
-	return retval;
-}
-
-/* make sure the board is quiescent; otherwise it will continue
- * generating IRQs across the upcoming reboot.
- */
-
-static void net2280_shutdown (struct pci_dev *pdev)
-{
-	struct net2280		*dev = pci_get_drvdata (pdev);
-
-	/* disable IRQs */
-	writel (0, &dev->regs->pciirqenb0);
-	writel (0, &dev->regs->pciirqenb1);
-
-	/* disable the pullup so the host will think we're gone */
-	writel (0, &dev->usb->usbctl);
-
-	/* Disable full-speed test mode */
-	writel(0, &dev->usb->xcvrdiag);
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-static const struct pci_device_id pci_ids [] = { {
-	.class =	((PCI_CLASS_SERIAL_USB << 8) | 0xfe),
-	.class_mask =	~0,
-	.vendor =	0x17cc,
-	.device =	0x2280,
-	.subvendor =	PCI_ANY_ID,
-	.subdevice =	PCI_ANY_ID,
-}, {
-	.class =	((PCI_CLASS_SERIAL_USB << 8) | 0xfe),
-	.class_mask =	~0,
-	.vendor =	0x17cc,
-	.device =	0x2282,
-	.subvendor =	PCI_ANY_ID,
-	.subdevice =	PCI_ANY_ID,
-
-}, { /* end: all zeroes */ }
-};
-MODULE_DEVICE_TABLE (pci, pci_ids);
-
-/* pci driver glue; this is a "new style" PCI driver module */
-static struct pci_driver net2280_pci_driver = {
-	.name =		(char *) driver_name,
-	.id_table =	pci_ids,
-
-	.probe =	net2280_probe,
-	.remove =	net2280_remove,
-	.shutdown =	net2280_shutdown,
-
-	/* FIXME add power management support */
-};
-
-MODULE_DESCRIPTION (DRIVER_DESC);
-MODULE_AUTHOR ("David Brownell");
-MODULE_LICENSE ("GPL");
-
-static int __init init (void)
-{
-	if (!use_dma)
-		use_dma_chaining = 0;
-	return pci_register_driver (&net2280_pci_driver);
-}
-module_init (init);
-
-static void __exit cleanup (void)
-{
-	pci_unregister_driver (&net2280_pci_driver);
-}
-module_exit (cleanup);

+ 0 - 308
drivers/usb/gadget/net2280.h

@@ -1,308 +0,0 @@
-/*
- * NetChip 2280 high/full speed USB device controller.
- * Unlike many such controllers, this one talks PCI.
- */
-
-/*
- * Copyright (C) 2002 NetChip Technology, Inc. (http://www.netchip.com)
- * Copyright (C) 2003 David Brownell
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include <linux/usb/net2280.h>
-
-/*-------------------------------------------------------------------------*/
-
-#ifdef	__KERNEL__
-
-/* indexed registers [11.10] are accessed indirectly
- * caller must own the device lock.
- */
-
-static inline u32
-get_idx_reg (struct net2280_regs __iomem *regs, u32 index)
-{
-	writel (index, &regs->idxaddr);
-	/* NOTE:  synchs device/cpu memory views */
-	return readl (&regs->idxdata);
-}
-
-static inline void
-set_idx_reg (struct net2280_regs __iomem *regs, u32 index, u32 value)
-{
-	writel (index, &regs->idxaddr);
-	writel (value, &regs->idxdata);
-	/* posted, may not be visible yet */
-}
-
-#endif	/* __KERNEL__ */
-
-
-#define REG_DIAG		0x0
-#define     RETRY_COUNTER                                       16
-#define     FORCE_PCI_SERR                                      11
-#define     FORCE_PCI_INTERRUPT                                 10
-#define     FORCE_USB_INTERRUPT                                 9
-#define     FORCE_CPU_INTERRUPT                                 8
-#define     ILLEGAL_BYTE_ENABLES                                5
-#define     FAST_TIMES                                          4
-#define     FORCE_RECEIVE_ERROR                                 2
-#define     FORCE_TRANSMIT_CRC_ERROR                            0
-#define REG_FRAME		0x02	/* from last sof */
-#define REG_CHIPREV		0x03	/* in bcd */
-#define	REG_HS_NAK_RATE		0x0a	/* NAK per N uframes */
-
-#define	CHIPREV_1	0x0100
-#define	CHIPREV_1A	0x0110
-
-#ifdef	__KERNEL__
-
-/* ep a-f highspeed and fullspeed maxpacket, addresses
- * computed from ep->num
- */
-#define REG_EP_MAXPKT(dev,num) (((num) + 1) * 0x10 + \
-		(((dev)->gadget.speed == USB_SPEED_HIGH) ? 0 : 1))
-
-/*-------------------------------------------------------------------------*/
-
-/* [8.3] for scatter/gather i/o
- * use struct net2280_dma_regs bitfields
- */
-struct net2280_dma {
-	__le32		dmacount;
-	__le32		dmaaddr;		/* the buffer */
-	__le32		dmadesc;		/* next dma descriptor */
-	__le32		_reserved;
-} __attribute__ ((aligned (16)));
-
-/*-------------------------------------------------------------------------*/
-
-/* DRIVER DATA STRUCTURES and UTILITIES */
-
-struct net2280_ep {
-	struct usb_ep				ep;
-	struct net2280_ep_regs			__iomem *regs;
-	struct net2280_dma_regs			__iomem *dma;
-	struct net2280_dma			*dummy;
-	dma_addr_t				td_dma;	/* of dummy */
-	struct net2280				*dev;
-	unsigned long				irqs;
-
-	/* analogous to a host-side qh */
-	struct list_head			queue;
-	const struct usb_endpoint_descriptor	*desc;
-	unsigned				num : 8,
-						fifo_size : 12,
-						in_fifo_validate : 1,
-						out_overflow : 1,
-						stopped : 1,
-						wedged : 1,
-						is_in : 1,
-						is_iso : 1,
-						responded : 1;
-};
-
-static inline void allow_status (struct net2280_ep *ep)
-{
-	/* ep0 only */
-	writel (  (1 << CLEAR_CONTROL_STATUS_PHASE_HANDSHAKE)
-		| (1 << CLEAR_NAK_OUT_PACKETS)
-		| (1 << CLEAR_NAK_OUT_PACKETS_MODE)
-		, &ep->regs->ep_rsp);
-	ep->stopped = 1;
-}
-
-/* count (<= 4) bytes in the next fifo write will be valid */
-static inline void set_fifo_bytecount (struct net2280_ep *ep, unsigned count)
-{
-	writeb (count, 2 + (u8 __iomem *) &ep->regs->ep_cfg);
-}
-
-struct net2280_request {
-	struct usb_request		req;
-	struct net2280_dma		*td;
-	dma_addr_t			td_dma;
-	struct list_head		queue;
-	unsigned			mapped : 1,
-					valid : 1;
-};
-
-struct net2280 {
-	/* each pci device provides one gadget, several endpoints */
-	struct usb_gadget		gadget;
-	spinlock_t			lock;
-	struct net2280_ep		ep [7];
-	struct usb_gadget_driver 	*driver;
-	unsigned			enabled : 1,
-					protocol_stall : 1,
-					softconnect : 1,
-					got_irq : 1,
-					region : 1;
-	u16				chiprev;
-
-	/* pci state used to access those endpoints */
-	struct pci_dev			*pdev;
-	struct net2280_regs		__iomem *regs;
-	struct net2280_usb_regs		__iomem *usb;
-	struct net2280_pci_regs		__iomem *pci;
-	struct net2280_dma_regs		__iomem *dma;
-	struct net2280_dep_regs		__iomem *dep;
-	struct net2280_ep_regs		__iomem *epregs;
-
-	struct pci_pool			*requests;
-	// statistics...
-};
-
-static inline void set_halt (struct net2280_ep *ep)
-{
-	/* ep0 and bulk/intr endpoints */
-	writel (  (1 << CLEAR_CONTROL_STATUS_PHASE_HANDSHAKE)
-		    /* set NAK_OUT for erratum 0114 */
-		| ((ep->dev->chiprev == CHIPREV_1) << SET_NAK_OUT_PACKETS)
-		| (1 << SET_ENDPOINT_HALT)
-		, &ep->regs->ep_rsp);
-}
-
-static inline void clear_halt (struct net2280_ep *ep)
-{
-	/* ep0 and bulk/intr endpoints */
-	writel (  (1 << CLEAR_ENDPOINT_HALT)
-		| (1 << CLEAR_ENDPOINT_TOGGLE)
-		    /* unless the gadget driver left a short packet in the
-		     * fifo, this reverses the erratum 0114 workaround.
-		     */
-		| ((ep->dev->chiprev == CHIPREV_1) << CLEAR_NAK_OUT_PACKETS)
-		, &ep->regs->ep_rsp);
-}
-
-#ifdef USE_RDK_LEDS
-
-static inline void net2280_led_init (struct net2280 *dev)
-{
-	/* LED3 (green) is on during USB activity. note erratum 0113. */
-	writel ((1 << GPIO3_LED_SELECT)
-		| (1 << GPIO3_OUTPUT_ENABLE)
-		| (1 << GPIO2_OUTPUT_ENABLE)
-		| (1 << GPIO1_OUTPUT_ENABLE)
-		| (1 << GPIO0_OUTPUT_ENABLE)
-		, &dev->regs->gpioctl);
-}
-
-/* indicate speed with bi-color LED 0/1 */
-static inline
-void net2280_led_speed (struct net2280 *dev, enum usb_device_speed speed)
-{
-	u32	val = readl (&dev->regs->gpioctl);
-	switch (speed) {
-	case USB_SPEED_HIGH:		/* green */
-		val &= ~(1 << GPIO0_DATA);
-		val |= (1 << GPIO1_DATA);
-		break;
-	case USB_SPEED_FULL:		/* red */
-		val &= ~(1 << GPIO1_DATA);
-		val |= (1 << GPIO0_DATA);
-		break;
-	default:			/* (off/black) */
-		val &= ~((1 << GPIO1_DATA) | (1 << GPIO0_DATA));
-		break;
-	}
-	writel (val, &dev->regs->gpioctl);
-}
-
-/* indicate power with LED 2 */
-static inline void net2280_led_active (struct net2280 *dev, int is_active)
-{
-	u32	val = readl (&dev->regs->gpioctl);
-
-	// FIXME this LED never seems to turn on.
-	if (is_active)
-		val |= GPIO2_DATA;
-	else
-		val &= ~GPIO2_DATA;
-	writel (val, &dev->regs->gpioctl);
-}
-static inline void net2280_led_shutdown (struct net2280 *dev)
-{
-	/* turn off all four GPIO*_DATA bits */
-	writel (readl (&dev->regs->gpioctl) & ~0x0f,
-			&dev->regs->gpioctl);
-}
-
-#else
-
-#define net2280_led_init(dev)		do { } while (0)
-#define net2280_led_speed(dev, speed)	do { } while (0)
-#define net2280_led_shutdown(dev)	do { } while (0)
-
-#endif
-
-/*-------------------------------------------------------------------------*/
-
-#define xprintk(dev,level,fmt,args...) \
-	printk(level "%s %s: " fmt , driver_name , \
-			pci_name(dev->pdev) , ## args)
-
-#ifdef DEBUG
-#undef DEBUG
-#define DEBUG(dev,fmt,args...) \
-	xprintk(dev , KERN_DEBUG , fmt , ## args)
-#else
-#define DEBUG(dev,fmt,args...) \
-	do { } while (0)
-#endif /* DEBUG */
-
-#ifdef VERBOSE
-#define VDEBUG DEBUG
-#else
-#define VDEBUG(dev,fmt,args...) \
-	do { } while (0)
-#endif	/* VERBOSE */
-
-#define ERROR(dev,fmt,args...) \
-	xprintk(dev , KERN_ERR , fmt , ## args)
-#define WARNING(dev,fmt,args...) \
-	xprintk(dev , KERN_WARNING , fmt , ## args)
-#define INFO(dev,fmt,args...) \
-	xprintk(dev , KERN_INFO , fmt , ## args)
-
-/*-------------------------------------------------------------------------*/
-
-static inline void start_out_naking (struct net2280_ep *ep)
-{
-	/* NOTE:  hardware races lurk here, and PING protocol issues */
-	writel ((1 << SET_NAK_OUT_PACKETS), &ep->regs->ep_rsp);
-	/* synch with device */
-	readl (&ep->regs->ep_rsp);
-}
-
-#ifdef DEBUG
-static inline void assert_out_naking (struct net2280_ep *ep, const char *where)
-{
-	u32	tmp = readl (&ep->regs->ep_stat);
-
-	if ((tmp & (1 << NAK_OUT_PACKETS)) == 0) {
-		DEBUG (ep->dev, "%s %s %08x !NAK\n",
-				ep->ep.name, where, tmp);
-		writel ((1 << SET_NAK_OUT_PACKETS),
-			&ep->regs->ep_rsp);
-	}
-}
-#define ASSERT_OUT_NAKING(ep) assert_out_naking(ep,__func__)
-#else
-#define ASSERT_OUT_NAKING(ep) do {} while (0)
-#endif
-
-static inline void stop_out_naking (struct net2280_ep *ep)
-{
-	u32	tmp;
-
-	tmp = readl (&ep->regs->ep_stat);
-	if ((tmp & (1 << NAK_OUT_PACKETS)) != 0)
-		writel ((1 << CLEAR_NAK_OUT_PACKETS), &ep->regs->ep_rsp);
-}
-
-#endif	/* __KERNEL__ */

+ 46 - 13
drivers/usb/gadget/u_os_desc.h

@@ -35,27 +35,63 @@
 #define USB_EXT_PROP_UNICODE_LINK		6
 #define USB_EXT_PROP_UNICODE_MULTI		7
 
+static inline u8 *__usb_ext_prop_ptr(u8 *buf, size_t offset)
+{
+	return buf + offset;
+}
+
+static inline u8 *usb_ext_prop_size_ptr(u8 *buf)
+{
+	return __usb_ext_prop_ptr(buf, USB_EXT_PROP_DW_SIZE);
+}
+
+static inline u8 *usb_ext_prop_type_ptr(u8 *buf)
+{
+	return __usb_ext_prop_ptr(buf, USB_EXT_PROP_DW_PROPERTY_DATA_TYPE);
+}
+
+static inline u8 *usb_ext_prop_name_len_ptr(u8 *buf)
+{
+	return __usb_ext_prop_ptr(buf, USB_EXT_PROP_W_PROPERTY_NAME_LENGTH);
+}
+
+static inline u8 *usb_ext_prop_name_ptr(u8 *buf)
+{
+	return __usb_ext_prop_ptr(buf, USB_EXT_PROP_B_PROPERTY_NAME);
+}
+
+static inline u8 *usb_ext_prop_data_len_ptr(u8 *buf, size_t off)
+{
+	return __usb_ext_prop_ptr(buf,
+				  USB_EXT_PROP_DW_PROPERTY_DATA_LENGTH + off);
+}
+
+static inline u8 *usb_ext_prop_data_ptr(u8 *buf, size_t off)
+{
+	return __usb_ext_prop_ptr(buf, USB_EXT_PROP_B_PROPERTY_DATA + off);
+}
+
 static inline void usb_ext_prop_put_size(u8 *buf, int dw_size)
 {
-	put_unaligned_le32(dw_size, &buf[USB_EXT_PROP_DW_SIZE]);
+	put_unaligned_le32(dw_size, usb_ext_prop_size_ptr(buf));
 }
 
 static inline void usb_ext_prop_put_type(u8 *buf, int type)
 {
-	put_unaligned_le32(type, &buf[USB_EXT_PROP_DW_PROPERTY_DATA_TYPE]);
+	put_unaligned_le32(type, usb_ext_prop_type_ptr(buf));
 }
 
 static inline int usb_ext_prop_put_name(u8 *buf, const char *name, int pnl)
 {
 	int result;
 
-	put_unaligned_le16(pnl, &buf[USB_EXT_PROP_W_PROPERTY_NAME_LENGTH]);
+	put_unaligned_le16(pnl, usb_ext_prop_name_len_ptr(buf));
 	result = utf8s_to_utf16s(name, strlen(name), UTF16_LITTLE_ENDIAN,
-		(wchar_t *) &buf[USB_EXT_PROP_B_PROPERTY_NAME], pnl - 2);
+		(wchar_t *) usb_ext_prop_name_ptr(buf), pnl - 2);
 	if (result < 0)
 		return result;
 
-	put_unaligned_le16(0, &buf[USB_EXT_PROP_B_PROPERTY_NAME + pnl]);
+	put_unaligned_le16(0, &buf[USB_EXT_PROP_B_PROPERTY_NAME + pnl - 2]);
 
 	return pnl;
 }
@@ -63,26 +99,23 @@ static inline int usb_ext_prop_put_name(u8 *buf, const char *name, int pnl)
 static inline void usb_ext_prop_put_binary(u8 *buf, int pnl, const u8 *data,
 					   int data_len)
 {
-	put_unaligned_le32(data_len,
-			   &buf[USB_EXT_PROP_DW_PROPERTY_DATA_LENGTH + pnl]);
-	memcpy(&buf[USB_EXT_PROP_B_PROPERTY_DATA + pnl], data, data_len);
+	put_unaligned_le32(data_len, usb_ext_prop_data_len_ptr(buf, pnl));
+	memcpy(usb_ext_prop_data_ptr(buf, pnl), data, data_len);
 }
 
 static inline int usb_ext_prop_put_unicode(u8 *buf, int pnl, const char *string,
 					   int data_len)
 {
 	int result;
-	put_unaligned_le32(data_len,
-			&buf[USB_EXT_PROP_DW_PROPERTY_DATA_LENGTH + pnl]);
-
+	put_unaligned_le32(data_len, usb_ext_prop_data_len_ptr(buf, pnl));
 	result = utf8s_to_utf16s(string, data_len >> 1, UTF16_LITTLE_ENDIAN,
-			(wchar_t *) &buf[USB_EXT_PROP_B_PROPERTY_DATA + pnl],
+			(wchar_t *) usb_ext_prop_data_ptr(buf, pnl),
 			data_len - 2);
 	if (result < 0)
 		return result;
 
 	put_unaligned_le16(0,
-			&buf[USB_EXT_PROP_B_PROPERTY_DATA + pnl + data_len]);
+		&buf[USB_EXT_PROP_B_PROPERTY_DATA + pnl + data_len - 2]);
 
 	return data_len;
 }

+ 385 - 0
drivers/usb/gadget/udc/Kconfig

@@ -0,0 +1,385 @@
+#
+# USB Gadget support on a system involves
+#    (a) a peripheral controller, and
+#    (b) the gadget driver using it.
+#
+# NOTE:  Gadget support ** DOES NOT ** depend on host-side CONFIG_USB !!
+#
+#  - Host systems (like PCs) need CONFIG_USB (with "A" jacks).
+#  - Peripherals (like PDAs) need CONFIG_USB_GADGET (with "B" jacks).
+#  - Some systems have both kinds of controllers.
+#
+# With help from a special transceiver and a "Mini-AB" jack, systems with
+# both kinds of controller can also support "USB On-the-Go" (CONFIG_USB_OTG).
+#
+
+#
+# USB Peripheral Controller Support
+#
+# The order here is alphabetical, except that integrated controllers go
+# before discrete ones so they will be the initial/default value:
+#   - integrated/SOC controllers first
+#   - licensed IP used in both SOC and discrete versions
+#   - discrete ones (including all PCI-only controllers)
+#   - debug/dummy gadget+hcd is last.
+#
+menu "USB Peripheral Controller"
+
+#
+# Integrated controllers
+#
+
+config USB_AT91
+	tristate "Atmel AT91 USB Device Port"
+	depends on ARCH_AT91
+	help
+	   Many Atmel AT91 processors (such as the AT91RM2000) have a
+	   full speed USB Device Port with support for five configurable
+	   endpoints (plus endpoint zero).
+
+	   Say "y" to link the driver statically, or "m" to build a
+	   dynamically linked module called "at91_udc" and force all
+	   gadget drivers to also be dynamically linked.
+
+config USB_LPC32XX
+	tristate "LPC32XX USB Peripheral Controller"
+	depends on ARCH_LPC32XX && I2C
+	select USB_ISP1301
+	help
+	   This option selects the USB device controller in the LPC32xx SoC.
+
+	   Say "y" to link the driver statically, or "m" to build a
+	   dynamically linked module called "lpc32xx_udc" and force all
+	   gadget drivers to also be dynamically linked.
+
+config USB_ATMEL_USBA
+	tristate "Atmel USBA"
+	depends on AVR32 || ARCH_AT91
+	help
+	  USBA is the integrated high-speed USB Device controller on
+	  the AT32AP700x, some AT91SAM9 and AT91CAP9 processors from Atmel.
+
+config USB_BCM63XX_UDC
+	tristate "Broadcom BCM63xx Peripheral Controller"
+	depends on BCM63XX
+	help
+	   Many Broadcom BCM63xx chipsets (such as the BCM6328) have a
+	   high speed USB Device Port with support for four fixed endpoints
+	   (plus endpoint zero).
+
+	   Say "y" to link the driver statically, or "m" to build a
+	   dynamically linked module called "bcm63xx_udc".
+
+config USB_FSL_USB2
+	tristate "Freescale Highspeed USB DR Peripheral Controller"
+	depends on FSL_SOC || ARCH_MXC
+	select USB_FSL_MPH_DR_OF if OF
+	help
+	   Some of Freescale PowerPC and i.MX processors have a High Speed
+	   Dual-Role(DR) USB controller, which supports device mode.
+
+	   The number of programmable endpoints is different through
+	   SOC revisions.
+
+	   Say "y" to link the driver statically, or "m" to build a
+	   dynamically linked module called "fsl_usb2_udc" and force
+	   all gadget drivers to also be dynamically linked.
+
+config USB_FUSB300
+	tristate "Faraday FUSB300 USB Peripheral Controller"
+	depends on !PHYS_ADDR_T_64BIT && HAS_DMA
+	help
+	   Faraday usb device controller FUSB300 driver
+
+config USB_FOTG210_UDC
+	depends on HAS_DMA
+	tristate "Faraday FOTG210 USB Peripheral Controller"
+	help
+	   Faraday USB2.0 OTG controller which can be configured as
+	   high speed or full speed USB device. This driver supppors
+	   Bulk Transfer so far.
+
+	   Say "y" to link the driver statically, or "m" to build a
+	   dynamically linked module called "fotg210_udc".
+
+config USB_GR_UDC
+       tristate "Aeroflex Gaisler GRUSBDC USB Peripheral Controller Driver"
+       depends on HAS_DMA
+       help
+          Select this to support Aeroflex Gaisler GRUSBDC cores from the GRLIB
+	  VHDL IP core library.
+
+config USB_OMAP
+	tristate "OMAP USB Device Controller"
+	depends on ARCH_OMAP1
+	depends on ISP1301_OMAP || !(MACH_OMAP_H2 || MACH_OMAP_H3)
+	help
+	   Many Texas Instruments OMAP processors have flexible full
+	   speed USB device controllers, with support for up to 30
+	   endpoints (plus endpoint zero).  This driver supports the
+	   controller in the OMAP 1611, and should work with controllers
+	   in other OMAP processors too, given minor tweaks.
+
+	   Say "y" to link the driver statically, or "m" to build a
+	   dynamically linked module called "omap_udc" and force all
+	   gadget drivers to also be dynamically linked.
+
+config USB_PXA25X
+	tristate "PXA 25x or IXP 4xx"
+	depends on (ARCH_PXA && PXA25x) || ARCH_IXP4XX
+	help
+	   Intel's PXA 25x series XScale ARM-5TE processors include
+	   an integrated full speed USB 1.1 device controller.  The
+	   controller in the IXP 4xx series is register-compatible.
+
+	   It has fifteen fixed-function endpoints, as well as endpoint
+	   zero (for control transfers).
+
+	   Say "y" to link the driver statically, or "m" to build a
+	   dynamically linked module called "pxa25x_udc" and force all
+	   gadget drivers to also be dynamically linked.
+
+# if there's only one gadget driver, using only two bulk endpoints,
+# don't waste memory for the other endpoints
+config USB_PXA25X_SMALL
+	depends on USB_PXA25X
+	bool
+	default n if USB_ETH_RNDIS
+	default y if USB_ZERO
+	default y if USB_ETH
+	default y if USB_G_SERIAL
+
+config USB_R8A66597
+	tristate "Renesas R8A66597 USB Peripheral Controller"
+	depends on HAS_DMA
+	help
+	   R8A66597 is a discrete USB host and peripheral controller chip that
+	   supports both full and high speed USB 2.0 data transfers.
+	   It has nine configurable endpoints, and endpoint zero.
+
+	   Say "y" to link the driver statically, or "m" to build a
+	   dynamically linked module called "r8a66597_udc" and force all
+	   gadget drivers to also be dynamically linked.
+
+config USB_RENESAS_USBHS_UDC
+	tristate 'Renesas USBHS controller'
+	depends on USB_RENESAS_USBHS
+	help
+	   Renesas USBHS is a discrete USB host and peripheral controller chip
+	   that supports both full and high speed USB 2.0 data transfers.
+	   It has nine or more configurable endpoints, and endpoint zero.
+
+	   Say "y" to link the driver statically, or "m" to build a
+	   dynamically linked module called "renesas_usbhs" and force all
+	   gadget drivers to also be dynamically linked.
+
+config USB_PXA27X
+	tristate "PXA 27x"
+	help
+	   Intel's PXA 27x series XScale ARM v5TE processors include
+	   an integrated full speed USB 1.1 device controller.
+
+	   It has up to 23 endpoints, as well as endpoint zero (for
+	   control transfers).
+
+	   Say "y" to link the driver statically, or "m" to build a
+	   dynamically linked module called "pxa27x_udc" and force all
+	   gadget drivers to also be dynamically linked.
+
+config USB_S3C2410
+	tristate "S3C2410 USB Device Controller"
+	depends on ARCH_S3C24XX
+	help
+	  Samsung's S3C2410 is an ARM-4 processor with an integrated
+	  full speed USB 1.1 device controller.  It has 4 configurable
+	  endpoints, as well as endpoint zero (for control transfers).
+
+	  This driver has been tested on the S3C2410, S3C2412, and
+	  S3C2440 processors.
+
+config USB_S3C2410_DEBUG
+	boolean "S3C2410 udc debug messages"
+	depends on USB_S3C2410
+
+config USB_S3C_HSUDC
+	tristate "S3C2416, S3C2443 and S3C2450 USB Device Controller"
+	depends on ARCH_S3C24XX
+	help
+	  Samsung's S3C2416, S3C2443 and S3C2450 is an ARM9 based SoC
+	  integrated with dual speed USB 2.0 device controller. It has
+	  8 endpoints, as well as endpoint zero.
+
+	  This driver has been tested on S3C2416 and S3C2450 processors.
+
+config USB_MV_UDC
+	tristate "Marvell USB2.0 Device Controller"
+	depends on HAS_DMA
+	help
+	  Marvell Socs (including PXA and MMP series) include a high speed
+	  USB2.0 OTG controller, which can be configured as high speed or
+	  full speed USB peripheral.
+
+config USB_MV_U3D
+	depends on HAS_DMA
+	tristate "MARVELL PXA2128 USB 3.0 controller"
+	help
+	  MARVELL PXA2128 Processor series include a super speed USB3.0 device
+	  controller, which support super speed USB peripheral.
+
+#
+# Controllers available in both integrated and discrete versions
+#
+
+config USB_M66592
+	tristate "Renesas M66592 USB Peripheral Controller"
+	help
+	   M66592 is a discrete USB peripheral controller chip that
+	   supports both full and high speed USB 2.0 data transfers.
+	   It has seven configurable endpoints, and endpoint zero.
+
+	   Say "y" to link the driver statically, or "m" to build a
+	   dynamically linked module called "m66592_udc" and force all
+	   gadget drivers to also be dynamically linked.
+
+#
+# Controllers available only in discrete form (and all PCI controllers)
+#
+
+config USB_AMD5536UDC
+	tristate "AMD5536 UDC"
+	depends on PCI
+	help
+	   The AMD5536 UDC is part of the AMD Geode CS5536, an x86 southbridge.
+	   It is a USB Highspeed DMA capable USB device controller. Beside ep0
+	   it provides 4 IN and 4 OUT endpoints (bulk or interrupt type).
+	   The UDC port supports OTG operation, and may be used as a host port
+	   if it's not being used to implement peripheral or OTG roles.
+
+	   Say "y" to link the driver statically, or "m" to build a
+	   dynamically linked module called "amd5536udc" and force all
+	   gadget drivers to also be dynamically linked.
+
+config USB_FSL_QE
+	tristate "Freescale QE/CPM USB Device Controller"
+	depends on FSL_SOC && (QUICC_ENGINE || CPM)
+	help
+	   Some of Freescale PowerPC processors have a Full Speed
+	   QE/CPM2 USB controller, which support device mode with 4
+	   programmable endpoints. This driver supports the
+	   controller in the MPC8360 and MPC8272, and should work with
+	   controllers having QE or CPM2, given minor tweaks.
+
+	   Set CONFIG_USB_GADGET to "m" to build this driver as a
+	   dynamically linked module called "fsl_qe_udc".
+
+config USB_NET2272
+	tristate "PLX NET2272"
+	help
+	  PLX NET2272 is a USB peripheral controller which supports
+	  both full and high speed USB 2.0 data transfers.
+
+	  It has three configurable endpoints, as well as endpoint zero
+	  (for control transfer).
+	  Say "y" to link the driver statically, or "m" to build a
+	  dynamically linked module called "net2272" and force all
+	  gadget drivers to also be dynamically linked.
+
+config USB_NET2272_DMA
+	boolean "Support external DMA controller"
+	depends on USB_NET2272 && HAS_DMA
+	help
+	  The NET2272 part can optionally support an external DMA
+	  controller, but your board has to have support in the
+	  driver itself.
+
+	  If unsure, say "N" here.  The driver works fine in PIO mode.
+
+config USB_NET2280
+	tristate "NetChip 228x / PLX USB338x"
+	depends on PCI
+	help
+	   NetChip 2280 / 2282 is a PCI based USB peripheral controller which
+	   supports both full and high speed USB 2.0 data transfers.
+
+	   It has six configurable endpoints, as well as endpoint zero
+	   (for control transfers) and several endpoints with dedicated
+	   functions.
+
+	   PLX 3380 / 3382 is a PCIe based USB peripheral controller which
+	   supports full, high speed USB 2.0 and super speed USB 3.0
+	   data transfers.
+
+	   It has eight configurable endpoints, as well as endpoint zero
+	   (for control transfers) and several endpoints with dedicated
+	   functions.
+
+	   Say "y" to link the driver statically, or "m" to build a
+	   dynamically linked module called "net2280" and force all
+	   gadget drivers to also be dynamically linked.
+
+config USB_GOKU
+	tristate "Toshiba TC86C001 'Goku-S'"
+	depends on PCI
+	help
+	   The Toshiba TC86C001 is a PCI device which includes controllers
+	   for full speed USB devices, IDE, I2C, SIO, plus a USB host (OHCI).
+
+	   The device controller has three configurable (bulk or interrupt)
+	   endpoints, plus endpoint zero (for control transfers).
+
+	   Say "y" to link the driver statically, or "m" to build a
+	   dynamically linked module called "goku_udc" and to force all
+	   gadget drivers to also be dynamically linked.
+
+config USB_EG20T
+	tristate "Intel EG20T PCH/LAPIS Semiconductor IOH(ML7213/ML7831) UDC"
+	depends on PCI
+	help
+	  This is a USB device driver for EG20T PCH.
+	  EG20T PCH is the platform controller hub that is used in Intel's
+	  general embedded platform. EG20T PCH has USB device interface.
+	  Using this interface, it is able to access system devices connected
+	  to USB device.
+	  This driver enables USB device function.
+	  USB device is a USB peripheral controller which
+	  supports both full and high speed USB 2.0 data transfers.
+	  This driver supports both control transfer and bulk transfer modes.
+	  This driver dose not support interrupt transfer or isochronous
+	  transfer modes.
+
+	  This driver also can be used for LAPIS Semiconductor's ML7213 which is
+	  for IVI(In-Vehicle Infotainment) use.
+	  ML7831 is for general purpose use.
+	  ML7213/ML7831 is companion chip for Intel Atom E6xx series.
+	  ML7213/ML7831 is completely compatible for Intel EG20T PCH.
+
+#
+# LAST -- dummy/emulated controller
+#
+
+config USB_DUMMY_HCD
+	tristate "Dummy HCD (DEVELOPMENT)"
+	depends on USB=y || (USB=m && USB_GADGET=m)
+	help
+	  This host controller driver emulates USB, looping all data transfer
+	  requests back to a USB "gadget driver" in the same host.  The host
+	  side is the master; the gadget side is the slave.  Gadget drivers
+	  can be high, full, or low speed; and they have access to endpoints
+	  like those from NET2280, PXA2xx, or SA1100 hardware.
+
+	  This may help in some stages of creating a driver to embed in a
+	  Linux device, since it lets you debug several parts of the gadget
+	  driver without its hardware or drivers being involved.
+
+	  Since such a gadget side driver needs to interoperate with a host
+	  side Linux-USB device driver, this may help to debug both sides
+	  of a USB protocol stack.
+
+	  Say "y" to link the driver statically, or "m" to build a
+	  dynamically linked module called "dummy_hcd" and force all
+	  gadget drivers to also be dynamically linked.
+
+# NOTE:  Please keep dummy_hcd LAST so that "real hardware" appears
+# first and will be selected by default.
+
+endmenu

+ 31 - 0
drivers/usb/gadget/udc/Makefile

@@ -0,0 +1,31 @@
+#
+# USB peripheral controller drivers
+#
+obj-$(CONFIG_USB_GADGET)	+= udc-core.o
+obj-$(CONFIG_USB_DUMMY_HCD)	+= dummy_hcd.o
+obj-$(CONFIG_USB_NET2272)	+= net2272.o
+obj-$(CONFIG_USB_NET2280)	+= net2280.o
+obj-$(CONFIG_USB_AMD5536UDC)	+= amd5536udc.o
+obj-$(CONFIG_USB_PXA25X)	+= pxa25x_udc.o
+obj-$(CONFIG_USB_PXA27X)	+= pxa27x_udc.o
+obj-$(CONFIG_USB_GOKU)		+= goku_udc.o
+obj-$(CONFIG_USB_OMAP)		+= omap_udc.o
+obj-$(CONFIG_USB_S3C2410)	+= s3c2410_udc.o
+obj-$(CONFIG_USB_AT91)		+= at91_udc.o
+obj-$(CONFIG_USB_ATMEL_USBA)	+= atmel_usba_udc.o
+obj-$(CONFIG_USB_BCM63XX_UDC)	+= bcm63xx_udc.o
+obj-$(CONFIG_USB_FSL_USB2)	+= fsl_usb2_udc.o
+fsl_usb2_udc-y			:= fsl_udc_core.o
+fsl_usb2_udc-$(CONFIG_ARCH_MXC)	+= fsl_mxc_udc.o
+obj-$(CONFIG_USB_M66592)	+= m66592-udc.o
+obj-$(CONFIG_USB_R8A66597)	+= r8a66597-udc.o
+obj-$(CONFIG_USB_FSL_QE)	+= fsl_qe_udc.o
+obj-$(CONFIG_USB_S3C_HSUDC)	+= s3c-hsudc.o
+obj-$(CONFIG_USB_LPC32XX)	+= lpc32xx_udc.o
+obj-$(CONFIG_USB_EG20T)		+= pch_udc.o
+obj-$(CONFIG_USB_MV_UDC)	+= mv_udc.o
+mv_udc-y			:= mv_udc_core.o
+obj-$(CONFIG_USB_FUSB300)	+= fusb300_udc.o
+obj-$(CONFIG_USB_FOTG210_UDC)	+= fotg210-udc.o
+obj-$(CONFIG_USB_MV_U3D)	+= mv_u3d_core.o
+obj-$(CONFIG_USB_GR_UDC)	+= gr_udc.o

+ 0 - 0
drivers/usb/gadget/amd5536udc.c → drivers/usb/gadget/udc/amd5536udc.c


+ 0 - 0
drivers/usb/gadget/amd5536udc.h → drivers/usb/gadget/udc/amd5536udc.h


+ 0 - 0
drivers/usb/gadget/at91_udc.c → drivers/usb/gadget/udc/at91_udc.c


+ 0 - 0
drivers/usb/gadget/at91_udc.h → drivers/usb/gadget/udc/at91_udc.h


+ 1 - 1
drivers/usb/gadget/atmel_usba_udc.c → drivers/usb/gadget/udc/atmel_usba_udc.c

@@ -1979,7 +1979,7 @@ static struct usba_ep * usba_udc_pdata(struct platform_device *pdev,
 	return eps;
 }
 
-static int __init usba_udc_probe(struct platform_device *pdev)
+static int usba_udc_probe(struct platform_device *pdev)
 {
 	struct resource *regs, *fifo;
 	struct clk *pclk, *hclk;

+ 0 - 0
drivers/usb/gadget/atmel_usba_udc.h → drivers/usb/gadget/udc/atmel_usba_udc.h


+ 0 - 0
drivers/usb/gadget/bcm63xx_udc.c → drivers/usb/gadget/udc/bcm63xx_udc.c


+ 0 - 0
drivers/usb/gadget/dummy_hcd.c → drivers/usb/gadget/udc/dummy_hcd.c


+ 0 - 0
drivers/usb/gadget/fotg210-udc.c → drivers/usb/gadget/udc/fotg210-udc.c


+ 0 - 0
drivers/usb/gadget/fotg210.h → drivers/usb/gadget/udc/fotg210.h


+ 2 - 0
drivers/usb/gadget/fsl_mxc_udc.c → drivers/usb/gadget/udc/fsl_mxc_udc.c

@@ -18,6 +18,8 @@
 #include <linux/platform_device.h>
 #include <linux/io.h>
 
+#include "fsl_usb2_udc.h"
+
 static struct clk *mxc_ahb_clk;
 static struct clk *mxc_per_clk;
 static struct clk *mxc_ipg_clk;

+ 7 - 12
drivers/usb/gadget/fsl_qe_udc.c → drivers/usb/gadget/udc/fsl_qe_udc.c

@@ -2539,7 +2539,7 @@ static int qe_udc_probe(struct platform_device *ofdev)
 		goto err2;
 
 	/* create a buf for ZLP send, need to remain zeroed */
-	udc->nullbuf = kzalloc(256, GFP_KERNEL);
+	udc->nullbuf = devm_kzalloc(&ofdev->dev, 256, GFP_KERNEL);
 	if (udc->nullbuf == NULL) {
 		dev_err(udc->dev, "cannot alloc nullbuf\n");
 		ret = -ENOMEM;
@@ -2547,10 +2547,10 @@ static int qe_udc_probe(struct platform_device *ofdev)
 	}
 
 	/* buffer for data of get_status request */
-	udc->statusbuf = kzalloc(2, GFP_KERNEL);
+	udc->statusbuf = devm_kzalloc(&ofdev->dev, 2, GFP_KERNEL);
 	if (udc->statusbuf == NULL) {
 		ret = -ENOMEM;
-		goto err4;
+		goto err3;
 	}
 
 	udc->nullp = virt_to_phys((void *)udc->nullbuf);
@@ -2581,13 +2581,13 @@ static int qe_udc_probe(struct platform_device *ofdev)
 	if (ret) {
 		dev_err(udc->dev, "cannot request irq %d err %d\n",
 				udc->usb_irq, ret);
-		goto err5;
+		goto err4;
 	}
 
 	ret = usb_add_gadget_udc_release(&ofdev->dev, &udc->gadget,
 			qe_udc_release);
 	if (ret)
-		goto err6;
+		goto err5;
 
 	platform_set_drvdata(ofdev, udc);
 	dev_info(udc->dev,
@@ -2595,9 +2595,9 @@ static int qe_udc_probe(struct platform_device *ofdev)
 			(udc->soc_type == PORT_QE) ? "QE" : "CPM");
 	return 0;
 
-err6:
-	free_irq(udc->usb_irq, udc);
 err5:
+	free_irq(udc->usb_irq, udc);
+err4:
 	irq_dispose_mapping(udc->usb_irq);
 err_noirq:
 	if (udc->nullmap) {
@@ -2610,9 +2610,6 @@ err_noirq:
 			udc->nullp, 256,
 				DMA_TO_DEVICE);
 	}
-	kfree(udc->statusbuf);
-err4:
-	kfree(udc->nullbuf);
 err3:
 	ep = &udc->eps[0];
 	cpm_muram_free(cpm_muram_offset(ep->rxbase));
@@ -2660,8 +2657,6 @@ static int qe_udc_remove(struct platform_device *ofdev)
 			udc->nullp, 256,
 				DMA_TO_DEVICE);
 	}
-	kfree(udc->statusbuf);
-	kfree(udc->nullbuf);
 
 	ep = &udc->eps[0];
 	cpm_muram_free(cpm_muram_offset(ep->rxbase));

+ 0 - 0
drivers/usb/gadget/fsl_qe_udc.h → drivers/usb/gadget/udc/fsl_qe_udc.h


+ 11 - 8
drivers/usb/gadget/fsl_udc_core.c → drivers/usb/gadget/udc/fsl_udc_core.c

@@ -59,9 +59,9 @@
 static const char driver_name[] = "fsl-usb2-udc";
 static const char driver_desc[] = DRIVER_DESC;
 
-static struct usb_dr_device *dr_regs;
+static struct usb_dr_device __iomem *dr_regs;
 
-static struct usb_sys_interface *usb_sys_regs;
+static struct usb_sys_interface __iomem *usb_sys_regs;
 
 /* it is initialized in probe()  */
 static struct fsl_udc *udc_controller = NULL;
@@ -159,6 +159,8 @@ static inline void fsl_set_accessors(struct fsl_usb2_platform_data *pdata) {}
  *	request is still in progress.
  *--------------------------------------------------------------*/
 static void done(struct fsl_ep *ep, struct fsl_req *req, int status)
+__releases(ep->udc->lock)
+__acquires(ep->udc->lock)
 {
 	struct fsl_udc *udc = NULL;
 	unsigned char stopped = ep->stopped;
@@ -1392,6 +1394,8 @@ stall:
 
 static void setup_received_irq(struct fsl_udc *udc,
 		struct usb_ctrlrequest *setup)
+__releases(udc->lock)
+__acquires(udc->lock)
 {
 	u16 wValue = le16_to_cpu(setup->wValue);
 	u16 wIndex = le16_to_cpu(setup->wIndex);
@@ -1957,8 +1961,7 @@ static int fsl_udc_start(struct usb_gadget *g,
 						    &udc_controller->gadget);
 			if (retval < 0) {
 				ERR("can't bind to transceiver\n");
-				driver->unbind(&udc_controller->gadget);
-				udc_controller->driver = 0;
+				udc_controller->driver = NULL;
 				return retval;
 			}
 		}
@@ -2246,7 +2249,7 @@ static void fsl_udc_release(struct device *dev)
  * init resource for globle controller
  * Return the udc handle on success or NULL on failure
  ------------------------------------------------------------------*/
-static int __init struct_udc_setup(struct fsl_udc *udc,
+static int struct_udc_setup(struct fsl_udc *udc,
 		struct platform_device *pdev)
 {
 	struct fsl_usb2_platform_data *pdata;
@@ -2298,7 +2301,7 @@ static int __init struct_udc_setup(struct fsl_udc *udc,
  * ep0out is not used so do nothing here
  * ep0in should be taken care
  *--------------------------------------------------------------*/
-static int __init struct_ep_setup(struct fsl_udc *udc, unsigned char index,
+static int struct_ep_setup(struct fsl_udc *udc, unsigned char index,
 		char *name, int link)
 {
 	struct fsl_ep *ep = &udc->eps[index];
@@ -2331,7 +2334,7 @@ static int __init struct_ep_setup(struct fsl_udc *udc, unsigned char index,
  * all intialization operations implemented here except enabling usb_intr reg
  * board setup should have been done in the platform code
  */
-static int __init fsl_udc_probe(struct platform_device *pdev)
+static int fsl_udc_probe(struct platform_device *pdev)
 {
 	struct fsl_usb2_platform_data *pdata;
 	struct resource *res;
@@ -2380,7 +2383,7 @@ static int __init fsl_udc_probe(struct platform_device *pdev)
 		goto err_release_mem_region;
 	}
 
-	pdata->regs = (void *)dr_regs;
+	pdata->regs = (void __iomem *)dr_regs;
 
 	/*
 	 * do platform specific init: check the clock, grab/config pins, etc.

+ 3 - 0
drivers/usb/gadget/fsl_usb2_udc.h → drivers/usb/gadget/udc/fsl_usb2_udc.h

@@ -12,6 +12,9 @@
 #ifndef __FSL_USB2_UDC_H
 #define __FSL_USB2_UDC_H
 
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+
 /* ### define USB registers here
  */
 #define USB_MAX_CTRL_PAYLOAD		64

+ 1 - 3
drivers/usb/gadget/fusb300_udc.c → drivers/usb/gadget/udc/fusb300_udc.c

@@ -1325,8 +1325,6 @@ static int fusb300_udc_stop(struct usb_gadget *g,
 {
 	struct fusb300 *fusb300 = to_fusb300(g);
 
-	driver->unbind(&fusb300->gadget);
-
 	init_controller(fusb300);
 	fusb300->driver = NULL;
 
@@ -1359,7 +1357,7 @@ static int __exit fusb300_remove(struct platform_device *pdev)
 	return 0;
 }
 
-static int __init fusb300_probe(struct platform_device *pdev)
+static int fusb300_probe(struct platform_device *pdev)
 {
 	struct resource *res, *ires, *ires1;
 	void __iomem *reg = NULL;

+ 0 - 0
drivers/usb/gadget/fusb300_udc.h → drivers/usb/gadget/udc/fusb300_udc.h


+ 0 - 0
drivers/usb/gadget/gadget_chips.h → drivers/usb/gadget/udc/gadget_chips.h


+ 0 - 0
drivers/usb/gadget/goku_udc.c → drivers/usb/gadget/udc/goku_udc.c


部分文件因为文件数量过多而无法显示