]> git.openfabrics.org - ~shefty/rdma-dev.git/commitdiff
Merge 3.7-rc5 into usb-next
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 13 Nov 2012 18:33:29 +0000 (10:33 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 13 Nov 2012 18:33:29 +0000 (10:33 -0800)
This pulls in the 3.7-rc5 branch into usb-next

238 files changed:
Documentation/DocBook/gadget.tmpl
Documentation/devicetree/bindings/usb/am33xx-usb.txt
Documentation/usb/error-codes.txt
Documentation/usb/mass-storage.txt
arch/arm/configs/afeb9260_defconfig
arch/arm/configs/at91sam9260_defconfig
arch/arm/configs/at91sam9261_defconfig
arch/arm/configs/at91sam9263_defconfig
arch/arm/configs/at91sam9g20_defconfig
arch/arm/configs/corgi_defconfig
arch/arm/configs/davinci_all_defconfig
arch/arm/configs/h7202_defconfig
arch/arm/configs/magician_defconfig
arch/arm/configs/mini2440_defconfig
arch/arm/configs/omap1_defconfig
arch/arm/configs/prima2_defconfig
arch/arm/configs/spitz_defconfig
arch/arm/configs/stamp9g20_defconfig
arch/arm/configs/viper_defconfig
arch/arm/configs/zeus_defconfig
arch/arm/mach-cns3xxx/cns3420vb.c
arch/avr32/configs/atngw100_defconfig
arch/avr32/configs/atngw100_evklcd100_defconfig
arch/avr32/configs/atngw100_evklcd101_defconfig
arch/avr32/configs/atngw100_mrmt_defconfig
arch/avr32/configs/atngw100mkii_defconfig
arch/avr32/configs/atngw100mkii_evklcd100_defconfig
arch/avr32/configs/atngw100mkii_evklcd101_defconfig
arch/avr32/configs/atstk1002_defconfig
arch/avr32/configs/atstk1003_defconfig
arch/avr32/configs/atstk1004_defconfig
arch/avr32/configs/atstk1006_defconfig
arch/avr32/configs/favr-32_defconfig
arch/avr32/configs/hammerhead_defconfig
arch/blackfin/configs/CM-BF527_defconfig
arch/blackfin/configs/CM-BF548_defconfig
arch/blackfin/configs/CM-BF561_defconfig
arch/mips/alchemy/common/Makefile
arch/mips/alchemy/common/platform.c
arch/mips/alchemy/common/usb.c [new file with mode: 0644]
arch/mips/ath79/dev-usb.c
arch/mips/configs/bcm47xx_defconfig
arch/mips/configs/db1000_defconfig
arch/mips/configs/db1235_defconfig
arch/mips/configs/gpr_defconfig
arch/mips/configs/ls1b_defconfig
arch/mips/configs/mtx1_defconfig
arch/mips/loongson1/common/platform.c
arch/mips/netlogic/xlr/platform.c
arch/mips/pnx8550/common/platform.c
arch/sh/configs/ecovec24_defconfig
arch/sh/configs/se7724_defconfig
arch/sh/kernel/cpu/sh3/setup-sh7720.c
arch/sh/kernel/cpu/sh4a/setup-sh7757.c
arch/sh/kernel/cpu/sh4a/setup-sh7763.c
arch/sh/kernel/cpu/sh4a/setup-sh7786.c
drivers/usb/chipidea/Kconfig
drivers/usb/chipidea/debug.c
drivers/usb/chipidea/host.c
drivers/usb/core/devices.c
drivers/usb/core/hcd.c
drivers/usb/core/hub.c
drivers/usb/core/message.c
drivers/usb/core/urb.c
drivers/usb/core/usb.c
drivers/usb/dwc3/Makefile
drivers/usb/dwc3/core.c
drivers/usb/dwc3/core.h
drivers/usb/dwc3/dwc3-exynos.c
drivers/usb/dwc3/dwc3-omap.c
drivers/usb/dwc3/dwc3-pci.c
drivers/usb/early/ehci-dbgp.c
drivers/usb/gadget/Kconfig
drivers/usb/gadget/Makefile
drivers/usb/gadget/composite.c
drivers/usb/gadget/config.c
drivers/usb/gadget/dummy_hcd.c
drivers/usb/gadget/f_acm.c
drivers/usb/gadget/f_ecm.c
drivers/usb/gadget/f_eem.c
drivers/usb/gadget/f_fs.c
drivers/usb/gadget/f_hid.c
drivers/usb/gadget/f_loopback.c
drivers/usb/gadget/f_mass_storage.c
drivers/usb/gadget/f_midi.c
drivers/usb/gadget/f_ncm.c
drivers/usb/gadget/f_obex.c
drivers/usb/gadget/f_phonet.c
drivers/usb/gadget/f_rndis.c
drivers/usb/gadget/f_serial.c
drivers/usb/gadget/f_sourcesink.c
drivers/usb/gadget/f_subset.c
drivers/usb/gadget/f_uac1.c
drivers/usb/gadget/f_uac2.c
drivers/usb/gadget/f_uvc.c
drivers/usb/gadget/file_storage.c [deleted file]
drivers/usb/gadget/fsl_udc_core.c
drivers/usb/gadget/inode.c
drivers/usb/gadget/lpc32xx_udc.c
drivers/usb/gadget/net2280.c
drivers/usb/gadget/printer.c
drivers/usb/gadget/pxa27x_udc.h
drivers/usb/gadget/storage_common.c
drivers/usb/gadget/tcm_usb_gadget.c
drivers/usb/gadget/udc-core.c
drivers/usb/host/Kconfig
drivers/usb/host/Makefile
drivers/usb/host/alchemy-common.c [deleted file]
drivers/usb/host/ehci-atmel.c
drivers/usb/host/ehci-au1xxx.c [deleted file]
drivers/usb/host/ehci-cns3xxx.c [deleted file]
drivers/usb/host/ehci-dbg.c
drivers/usb/host/ehci-fsl.c
drivers/usb/host/ehci-grlib.c
drivers/usb/host/ehci-hcd.c
drivers/usb/host/ehci-hub.c
drivers/usb/host/ehci-ixp4xx.c [deleted file]
drivers/usb/host/ehci-lpm.c [deleted file]
drivers/usb/host/ehci-ls1x.c [deleted file]
drivers/usb/host/ehci-msm.c
drivers/usb/host/ehci-mxc.c
drivers/usb/host/ehci-octeon.c
drivers/usb/host/ehci-omap.c
drivers/usb/host/ehci-orion.c
drivers/usb/host/ehci-pci.c
drivers/usb/host/ehci-platform.c
drivers/usb/host/ehci-pmcmsp.c
drivers/usb/host/ehci-q.c
drivers/usb/host/ehci-s5p.c
drivers/usb/host/ehci-sched.c
drivers/usb/host/ehci-sh.c
drivers/usb/host/ehci-spear.c
drivers/usb/host/ehci-tegra.c
drivers/usb/host/ehci-vt8500.c
drivers/usb/host/ehci-w90x900.c
drivers/usb/host/ehci-xls.c [deleted file]
drivers/usb/host/ehci.h
drivers/usb/host/isp1760-if.c
drivers/usb/host/ohci-at91.c
drivers/usb/host/ohci-au1xxx.c [deleted file]
drivers/usb/host/ohci-cns3xxx.c [deleted file]
drivers/usb/host/ohci-ep93xx.c
drivers/usb/host/ohci-exynos.c
drivers/usb/host/ohci-hcd.c
drivers/usb/host/ohci-hub.c
drivers/usb/host/ohci-omap.c
drivers/usb/host/ohci-pci.c
drivers/usb/host/ohci-platform.c
drivers/usb/host/ohci-pnx8550.c [deleted file]
drivers/usb/host/ohci-ppc-soc.c [deleted file]
drivers/usb/host/ohci-pxa27x.c
drivers/usb/host/ohci-q.c
drivers/usb/host/ohci-s3c2410.c
drivers/usb/host/ohci-sh.c [deleted file]
drivers/usb/host/ohci-sm501.c
drivers/usb/host/ohci-spear.c
drivers/usb/host/ohci-tmio.c
drivers/usb/host/ohci-xls.c [deleted file]
drivers/usb/host/r8a66597-hcd.c
drivers/usb/host/uhci-q.c
drivers/usb/host/xhci-mem.c
drivers/usb/host/xhci-pci.c
drivers/usb/host/xhci-ring.c
drivers/usb/host/xhci.c
drivers/usb/host/xhci.h
drivers/usb/misc/ezusb.c
drivers/usb/musb/am35x.c
drivers/usb/musb/blackfin.c
drivers/usb/musb/cppi_dma.c
drivers/usb/musb/da8xx.c
drivers/usb/musb/davinci.c
drivers/usb/musb/musb_core.c
drivers/usb/musb/musb_core.h
drivers/usb/musb/musb_dsps.c
drivers/usb/musb/musb_gadget.c
drivers/usb/musb/musb_gadget_ep0.c
drivers/usb/musb/musb_host.c
drivers/usb/musb/musbhsdma.h
drivers/usb/musb/omap2430.c
drivers/usb/musb/tusb6010.c
drivers/usb/musb/ux500.c
drivers/usb/otg/mv_otg.c
drivers/usb/phy/Kconfig
drivers/usb/phy/Makefile
drivers/usb/phy/rcar-phy.c [new file with mode: 0644]
drivers/usb/phy/tegra_usb_phy.c
drivers/usb/renesas_usbhs/common.c
drivers/usb/renesas_usbhs/common.h
drivers/usb/renesas_usbhs/fifo.c
drivers/usb/renesas_usbhs/mod.c
drivers/usb/renesas_usbhs/mod_gadget.c
drivers/usb/renesas_usbhs/mod_host.c
drivers/usb/renesas_usbhs/pipe.c
drivers/usb/renesas_usbhs/pipe.h
drivers/usb/serial/aircable.c
drivers/usb/serial/ark3116.c
drivers/usb/serial/belkin_sa.c
drivers/usb/serial/cp210x.c
drivers/usb/serial/cyberjack.c
drivers/usb/serial/cypress_m8.c
drivers/usb/serial/digi_acceleport.c
drivers/usb/serial/empeg.c
drivers/usb/serial/ftdi_sio.c
drivers/usb/serial/generic.c
drivers/usb/serial/hp4x.c
drivers/usb/serial/io_edgeport.c
drivers/usb/serial/io_ti.c
drivers/usb/serial/ipaq.c
drivers/usb/serial/ipw.c
drivers/usb/serial/iuu_phoenix.c
drivers/usb/serial/keyspan.c
drivers/usb/serial/keyspan_pda.c
drivers/usb/serial/kl5kusb105.c
drivers/usb/serial/kobil_sct.c
drivers/usb/serial/mct_u232.c
drivers/usb/serial/metro-usb.c
drivers/usb/serial/mos7720.c
drivers/usb/serial/mos7840.c
drivers/usb/serial/omninet.c
drivers/usb/serial/option.c
drivers/usb/serial/oti6858.c
drivers/usb/serial/quatech2.c
drivers/usb/serial/siemens_mpi.c
drivers/usb/serial/sierra.c
drivers/usb/serial/spcp8x5.c
drivers/usb/serial/ssu100.c
drivers/usb/serial/usb_wwan.c
drivers/usb/serial/vivopay-serial.c
drivers/usb/storage/realtek_cr.c
drivers/usb/usb-skeleton.c
drivers/usb/wusbcore/devconnect.c
drivers/uwb/umc-bus.c
include/linux/usb.h
include/linux/usb/composite.h
include/linux/usb/ehci_pdriver.h
include/linux/usb/ezusb.h
include/linux/usb/gadget.h
include/linux/usb/ohci_pdriver.h

index 6ef2f0073e5aa45b72b33ffc9a52d1c650b8a3fb..4017f147ba2fb28c0b7f14352d0b7e09db8d5b87 100644 (file)
@@ -671,7 +671,7 @@ than a kernel driver.
 <para>There's a USB Mass Storage class driver, which provides
 a different solution for interoperability with systems such
 as MS-Windows and MacOS.
-That <emphasis>File-backed Storage</emphasis> driver uses a
+That <emphasis>Mass Storage</emphasis> driver uses a
 file or block device as backing store for a drive,
 like the <filename>loop</filename> driver.
 The USB host uses the BBB, CB, or CBI versions of the mass
index ca8fa56e9f03e6d5f6ad4a0f35885e9fb4fa66ed..a92250512a4efa43fc39d9a00e9a50954a388dc8 100644 (file)
@@ -3,12 +3,12 @@ AM33XX MUSB GLUE
  - ti,hwmods : must be "usb_otg_hs"
  - multipoint : Should be "1" indicating the musb controller supports
    multipoint. This is a MUSB configuration-specific setting.
- - num_eps : Specifies the number of endpoints. This is also a
+ - num-eps : Specifies the number of endpoints. This is also a
    MUSB configuration-specific setting. Should be set to "16"
- - ram_bits : Specifies the ram address size. Should be set to "12"
- - port0_mode : Should be "3" to represent OTG. "1" signifies HOST and "2"
+ - ram-bits : Specifies the ram address size. Should be set to "12"
+ - port0-mode : Should be "3" to represent OTG. "1" signifies HOST and "2"
    represents PERIPHERAL.
- - port1_mode : Should be "1" to represent HOST. "3" signifies OTG and "2"
+ - port1-mode : Should be "1" to represent HOST. "3" signifies OTG and "2"
    represents PERIPHERAL.
  - power : Should be "250". This signifies the controller can supply upto
    500mA when operating in host mode.
index b3f606b81a03926e287a13afa443ed8cd44d47a7..9c3eb845ebe514f20ddeacbfc644bb79d700153c 100644 (file)
@@ -21,6 +21,8 @@ Non-USB-specific:
 
 USB-specific:
 
+-EBUSY         The URB is already active.
+
 -ENODEV                specified USB-device or bus doesn't exist
 
 -ENOENT                specified interface or endpoint does not exist or
@@ -35,9 +37,8 @@ USB-specific:
                d) ISO: number_of_packets is < 0
                e) various other cases
 
--EAGAIN                a) specified ISO start frame too early
-               b) (using ISO-ASAP) too much scheduled for the future
-                  wait some time and try again.
+-EXDEV         ISO: URB_ISO_ASAP wasn't specified and all the frames
+               the URB would be scheduled in have already expired.
 
 -EFBIG         Host controller driver can't schedule that many ISO frames.
 
index e9b9334627bfd73b9cd6af691b7c05dbaff93f9e..59063ad7a60d025d3230babbb70af15cbf9c1983 100644 (file)
@@ -20,9 +20,9 @@
 
   This document describes how to use the gadget from user space, its
   relation to mass storage function (or MSF) and different gadgets
-  using it, and how it differs from File Storage Gadget (or FSG).  It
-  will talk only briefly about how to use MSF within composite
-  gadgets.
+  using it, and how it differs from File Storage Gadget (or FSG)
+  (which is no longer included in Linux).  It will talk only briefly
+  about how to use MSF within composite gadgets.
 
 * Module parameters
 
   The Mass Storage Function and thus the Mass Storage Gadget has been
   based on the File Storage Gadget.  The difference between the two is
   that MSG is a composite gadget (ie. uses the composite framework)
-  while file storage gadget is a traditional gadget.  From userspace
+  while file storage gadget was a traditional gadget.  From userspace
   point of view this distinction does not really matter, but from
   kernel hacker's point of view, this means that (i) MSG does not
   duplicate code needed for handling basic USB protocol commands and
   (ii) MSF can be used in any other composite gadget.
 
-  Because of that, File Storage Gadget has been deprecated and
-  scheduled to be removed in Linux 3.8.  All users need to transition
-  to the Mass Storage Gadget by that time.  The two gadgets behave
-  mostly the same from the outside except:
+  Because of that, File Storage Gadget has been removed in Linux 3.8.
+  All users need to transition to the Mass Storage Gadget.  The two
+  gadgets behave mostly the same from the outside except:
 
   1. In FSG the “removable” and “cdrom” module parameters set the flag
      for all logical units whereas in MSG they accept a list of y/n
index c285a9d777d933847a4ec3c9d8bf3e00ba2c18a5..a8dbc1e052539a4501d92cd22b05e08a73e5dfcd 100644 (file)
@@ -79,7 +79,7 @@ CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_ZERO=m
 CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
 CONFIG_USB_G_SERIAL=m
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_DEBUG=y
index 505b3765f87ebfb269184a11b9b096dc4fff8fea..0ea5d2c97fc437beee4316f194ef16fa276d4afc 100644 (file)
@@ -75,7 +75,7 @@ CONFIG_USB_STORAGE_DEBUG=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_ZERO=m
 CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
 CONFIG_USB_G_SERIAL=m
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_AT91SAM9=y
index 1e8712ef062e42733552cd948810b4b984e2e5d1..c87beb973b378d425c0c81a6922fdbb1a2d7f4c1 100644 (file)
@@ -125,7 +125,7 @@ CONFIG_USB_GADGET=y
 CONFIG_USB_ZERO=m
 CONFIG_USB_ETH=m
 CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
 CONFIG_USB_G_SERIAL=m
 CONFIG_MMC=y
 CONFIG_MMC_ATMELMCI=m
index d2050cada82d650334de0b44523efe6a5bcc1159..c5212f43eee6eb0cc640e9a3ffa2e2c47698b495 100644 (file)
@@ -133,7 +133,7 @@ CONFIG_USB_GADGET=y
 CONFIG_USB_ZERO=m
 CONFIG_USB_ETH=m
 CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
 CONFIG_USB_G_SERIAL=m
 CONFIG_MMC=y
 CONFIG_SDIO_UART=m
index e1b0e80b54a5693b792bfe2acaceb9be695c1c86..3b1881033ad8752c2f67ac761d35155e0fda8652 100644 (file)
@@ -96,7 +96,7 @@ CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_ZERO=m
 CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
 CONFIG_USB_G_SERIAL=m
 CONFIG_MMC=y
 CONFIG_MMC_ATMELMCI=m
index 4b8a25d9e6867b9baf1fb15037de71f2a760d4e2..1fd1d1de32201174a3681c404c1fcc0be052b67f 100644 (file)
@@ -218,7 +218,7 @@ CONFIG_USB_GADGET=y
 CONFIG_USB_ZERO=m
 CONFIG_USB_ETH=m
 CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
 CONFIG_USB_G_SERIAL=m
 CONFIG_MMC=y
 CONFIG_MMC_PXA=y
index 67b5abb6f8576e3fa47d248ecea51facf7f7b5dc..4ea7c95719d2cf6b873edec54e2b8476cd2c82ec 100644 (file)
@@ -144,7 +144,7 @@ CONFIG_USB_GADGET_DEBUG_FS=y
 CONFIG_USB_ZERO=m
 CONFIG_USB_ETH=m
 CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
 CONFIG_USB_G_SERIAL=m
 CONFIG_USB_G_PRINTER=m
 CONFIG_USB_CDC_COMPOSITE=m
index 69405a76242364a7bbb341bf19044c0d2b8e9fb0..e16d3f372e2ad240314dc5345c7272014dcd5bbc 100644 (file)
@@ -34,8 +34,7 @@ CONFIG_FB_MODE_HELPERS=y
 CONFIG_USB_GADGET=m
 CONFIG_USB_ZERO=m
 CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
-CONFIG_USB_FILE_STORAGE_TEST=y
+CONFIG_USB_MASS_STORAGE=m
 CONFIG_USB_G_SERIAL=m
 CONFIG_EXT2_FS=y
 CONFIG_TMPFS=y
index a691ef4c6008bac6a96c38aeb6615e685025d8ee..557dd291288b2975f4cd20575f6c4fabdfffc595 100644 (file)
@@ -136,7 +136,7 @@ CONFIG_USB_PXA27X=y
 CONFIG_USB_ETH=m
 # CONFIG_USB_ETH_RNDIS is not set
 CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
 CONFIG_USB_G_SERIAL=m
 CONFIG_USB_CDC_COMPOSITE=m
 CONFIG_USB_GPIO_VBUS=y
index 00630e6af45c2199f68998dfa7d9b5450a205bd5..a07948a87caa765cea44845bb793a68ab0f8dbdc 100644 (file)
@@ -240,7 +240,7 @@ CONFIG_USB_GADGET_S3C2410=y
 CONFIG_USB_ZERO=m
 CONFIG_USB_ETH=m
 CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
 CONFIG_USB_G_SERIAL=m
 CONFIG_USB_CDC_COMPOSITE=m
 CONFIG_MMC=y
index dde2a1af7b39bd73cec54cf22417a9e53920f792..42eab9a2a0fd53ba4cb26eb36c1a7a7c29909587 100644 (file)
@@ -214,8 +214,7 @@ CONFIG_USB_TEST=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_ETH=m
 # CONFIG_USB_ETH_RNDIS is not set
-CONFIG_USB_FILE_STORAGE=m
-CONFIG_USB_FILE_STORAGE_TEST=y
+CONFIG_USB_MASS_STORAGE=m
 CONFIG_MMC=y
 CONFIG_MMC_SDHCI=y
 CONFIG_MMC_SDHCI_PLTFM=y
index 807d4e2acb17c7261927565fe9f799939ef850d7..6a936c7c078afe7f56d0ade48de1dd5ff925cc08 100644 (file)
@@ -37,7 +37,6 @@ CONFIG_SPI_SIRF=y
 CONFIG_SPI_SPIDEV=y
 # CONFIG_HWMON is not set
 CONFIG_USB_GADGET=y
-CONFIG_USB_FILE_STORAGE=m
 CONFIG_USB_MASS_STORAGE=m
 CONFIG_MMC=y
 CONFIG_MMC_SDHCI=y
index df77931a43262c4a6c2f0740a891bbe0d38dc5bb..2e0419d1b9643ebbdca1726a6119a3b078ac8a17 100644 (file)
@@ -214,7 +214,7 @@ CONFIG_USB_GADGET_DUMMY_HCD=y
 CONFIG_USB_ZERO=m
 CONFIG_USB_ETH=m
 CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
 CONFIG_USB_G_SERIAL=m
 CONFIG_MMC=y
 CONFIG_MMC_PXA=y
index 52f1488591c7bb5724e848b8caa706973fa314d4..b845f5519bcc769924baa3035cff0839b5a6e282 100644 (file)
@@ -97,7 +97,7 @@ CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=m
 CONFIG_USB_ZERO=m
 CONFIG_USB_ETH=m
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
 CONFIG_USB_G_SERIAL=m
 CONFIG_MMC=y
 CONFIG_MMC_ATMELMCI=y
index 1d01ddd33122d76fa7db12e989ed0ac09e2293d7..d36e0d3c86ec65e3a2fdec5fcaa06151dd986d08 100644 (file)
@@ -139,7 +139,7 @@ CONFIG_USB_SERIAL_MCT_U232=m
 CONFIG_USB_GADGET=m
 CONFIG_USB_ETH=m
 CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
 CONFIG_USB_G_SERIAL=m
 CONFIG_USB_G_PRINTER=m
 CONFIG_RTC_CLASS=y
index 547a3c1e59dbcd88ea9da77505691110508f9daf..731d4f9853109b54869cbc99ee334129354f8f4a 100644 (file)
@@ -143,7 +143,7 @@ CONFIG_USB_GADGET=m
 CONFIG_USB_PXA27X=y
 CONFIG_USB_ETH=m
 CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
 CONFIG_USB_G_SERIAL=m
 CONFIG_USB_G_PRINTER=m
 CONFIG_MMC=y
index 2c5fb4c7e509b8786fb1ba0d45cb974bc373f4d2..ae305397003c767422c5237dd5d255e8f75ab9fd 100644 (file)
@@ -24,6 +24,8 @@
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/physmap.h>
 #include <linux/mtd/partitions.h>
+#include <linux/usb/ehci_pdriver.h>
+#include <linux/usb/ohci_pdriver.h>
 #include <asm/setup.h>
 #include <asm/mach-types.h>
 #include <asm/hardware/gic.h>
@@ -32,6 +34,7 @@
 #include <asm/mach/time.h>
 #include <mach/cns3xxx.h>
 #include <mach/irqs.h>
+#include <mach/pm.h>
 #include "core.h"
 #include "devices.h"
 
@@ -125,13 +128,52 @@ static struct resource cns3xxx_usb_ehci_resources[] = {
 
 static u64 cns3xxx_usb_ehci_dma_mask = DMA_BIT_MASK(32);
 
+static int csn3xxx_usb_power_on(struct platform_device *pdev)
+{
+       /*
+        * EHCI and OHCI share the same clock and power,
+        * resetting twice would cause the 1st controller been reset.
+        * Therefore only do power up  at the first up device, and
+        * power down at the last down device.
+        *
+        * Set USB AHB INCR length to 16
+        */
+       if (atomic_inc_return(&usb_pwr_ref) == 1) {
+               cns3xxx_pwr_power_up(1 << PM_PLL_HM_PD_CTRL_REG_OFFSET_PLL_USB);
+               cns3xxx_pwr_clk_en(1 << PM_CLK_GATE_REG_OFFSET_USB_HOST);
+               cns3xxx_pwr_soft_rst(1 << PM_SOFT_RST_REG_OFFST_USB_HOST);
+               __raw_writel((__raw_readl(MISC_CHIP_CONFIG_REG) | (0X2 << 24)),
+                       MISC_CHIP_CONFIG_REG);
+       }
+
+       return 0;
+}
+
+static void csn3xxx_usb_power_off(struct platform_device *pdev)
+{
+       /*
+        * EHCI and OHCI share the same clock and power,
+        * resetting twice would cause the 1st controller been reset.
+        * Therefore only do power up  at the first up device, and
+        * power down at the last down device.
+        */
+       if (atomic_dec_return(&usb_pwr_ref) == 0)
+               cns3xxx_pwr_clk_dis(1 << PM_CLK_GATE_REG_OFFSET_USB_HOST);
+}
+
+static struct usb_ehci_pdata cns3xxx_usb_ehci_pdata = {
+       .power_on       = csn3xxx_usb_power_on,
+       .power_off      = csn3xxx_usb_power_off,
+};
+
 static struct platform_device cns3xxx_usb_ehci_device = {
-       .name          = "cns3xxx-ehci",
+       .name          = "ehci-platform",
        .num_resources = ARRAY_SIZE(cns3xxx_usb_ehci_resources),
        .resource      = cns3xxx_usb_ehci_resources,
        .dev           = {
                .dma_mask          = &cns3xxx_usb_ehci_dma_mask,
                .coherent_dma_mask = DMA_BIT_MASK(32),
+               .platform_data     = &cns3xxx_usb_ehci_pdata,
        },
 };
 
@@ -149,13 +191,20 @@ static struct resource cns3xxx_usb_ohci_resources[] = {
 
 static u64 cns3xxx_usb_ohci_dma_mask = DMA_BIT_MASK(32);
 
+static struct usb_ohci_pdata cns3xxx_usb_ohci_pdata = {
+       .num_ports      = 1,
+       .power_on       = csn3xxx_usb_power_on,
+       .power_off      = csn3xxx_usb_power_off,
+};
+
 static struct platform_device cns3xxx_usb_ohci_device = {
-       .name          = "cns3xxx-ohci",
+       .name          = "ohci-platform",
        .num_resources = ARRAY_SIZE(cns3xxx_usb_ohci_resources),
        .resource      = cns3xxx_usb_ohci_resources,
        .dev           = {
                .dma_mask          = &cns3xxx_usb_ohci_dma_mask,
                .coherent_dma_mask = DMA_BIT_MASK(32),
+               .platform_data     = &cns3xxx_usb_ohci_pdata,
        },
 };
 
index a06bfccc2840e5204c5519203a6c343837ebac3c..f4025db184ff754fd6cf8974535c4ca3e0d56571 100644 (file)
@@ -109,7 +109,7 @@ CONFIG_USB_GADGET_VBUS_DRAW=350
 CONFIG_USB_ZERO=m
 CONFIG_USB_ETH=m
 CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
 CONFIG_USB_G_SERIAL=m
 CONFIG_USB_CDC_COMPOSITE=m
 CONFIG_MMC=y
index d8f1fe80d210daea5b764c50b0977a09d58c6a9f..c76a49b9e9d06130a75f6d41a7a73dd0ceb1c1e6 100644 (file)
@@ -125,7 +125,7 @@ CONFIG_USB_GADGET_VBUS_DRAW=350
 CONFIG_USB_ZERO=m
 CONFIG_USB_ETH=m
 CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
 CONFIG_USB_G_SERIAL=m
 CONFIG_USB_CDC_COMPOSITE=m
 CONFIG_MMC=y
index d4c5b19ec950a2eddc4b6399e8d0286626aeb0c9..2d8ab089a64e36d007a52f238d43483703e59725 100644 (file)
@@ -124,7 +124,7 @@ CONFIG_USB_GADGET_VBUS_DRAW=350
 CONFIG_USB_ZERO=m
 CONFIG_USB_ETH=m
 CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
 CONFIG_USB_G_SERIAL=m
 CONFIG_USB_CDC_COMPOSITE=m
 CONFIG_MMC=y
index 77ca4f905d2cf9da872e12cb1efb4536a728a8f4..b189e0cab04b38c6c209801091c71fddf013fd87 100644 (file)
@@ -99,7 +99,7 @@ CONFIG_SND_ATMEL_AC97C=m
 # CONFIG_SND_SPI is not set
 CONFIG_USB_GADGET=m
 CONFIG_USB_GADGET_DEBUG_FILES=y
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
 CONFIG_USB_G_SERIAL=m
 CONFIG_MMC=y
 CONFIG_MMC_ATMELMCI=y
index 6e0dca4d3131ff920a7580408ab48b45cd92b916..2e4de42a53c4ab8be5a4d0c27225609972138087 100644 (file)
@@ -111,7 +111,7 @@ CONFIG_USB_GADGET_VBUS_DRAW=350
 CONFIG_USB_ZERO=m
 CONFIG_USB_ETH=m
 CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
 CONFIG_USB_G_SERIAL=m
 CONFIG_USB_CDC_COMPOSITE=m
 CONFIG_MMC=y
index 7f2a344a5fa8334594929bcae48ec4fee4b5242c..fad3cd22dfd3c873141de7b0272730b0c42eeada 100644 (file)
@@ -128,7 +128,7 @@ CONFIG_USB_GADGET_VBUS_DRAW=350
 CONFIG_USB_ZERO=m
 CONFIG_USB_ETH=m
 CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
 CONFIG_USB_G_SERIAL=m
 CONFIG_USB_CDC_COMPOSITE=m
 CONFIG_MMC=y
index 085eeba88f67e5b94efefe4284c57b69ca1c60c7..29986230aaa5a48b1426f21fc3d9883e9f88b0d0 100644 (file)
@@ -127,7 +127,7 @@ CONFIG_USB_GADGET_VBUS_DRAW=350
 CONFIG_USB_ZERO=m
 CONFIG_USB_ETH=m
 CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
 CONFIG_USB_G_SERIAL=m
 CONFIG_USB_CDC_COMPOSITE=m
 CONFIG_MMC=y
index d1a887e6405595010c7181c6a928c5fc35a3cb7b..a582465e1cefb809a22262aaf661a3e8c694d0f0 100644 (file)
@@ -126,7 +126,7 @@ CONFIG_USB_GADGET=y
 CONFIG_USB_ZERO=m
 CONFIG_USB_ETH=m
 CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
 CONFIG_USB_G_SERIAL=m
 CONFIG_USB_CDC_COMPOSITE=m
 CONFIG_MMC=y
index 956f2819ad45495a96c9244a53781028b48c4d91..57a79df2ce5dd47f1419694582edd9ae382006a5 100644 (file)
@@ -105,7 +105,7 @@ CONFIG_USB_GADGET=y
 CONFIG_USB_ZERO=m
 CONFIG_USB_ETH=m
 CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
 CONFIG_USB_G_SERIAL=m
 CONFIG_USB_CDC_COMPOSITE=m
 CONFIG_MMC=y
index 40c69f38c61a2ab2b9a409dc1304cf495d0606b5..1a49bd8c6340c70bda11dcd964aa55e332ac29d9 100644 (file)
@@ -104,7 +104,7 @@ CONFIG_USB_GADGET=y
 CONFIG_USB_ZERO=m
 CONFIG_USB_ETH=m
 CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
 CONFIG_USB_G_SERIAL=m
 CONFIG_USB_CDC_COMPOSITE=m
 CONFIG_MMC=y
index 511eb8af356dab0a3681ee274aade2a988c89096..206a1b67f763e3f1d6e98598a156a8359459a44c 100644 (file)
@@ -129,7 +129,7 @@ CONFIG_USB_GADGET=y
 CONFIG_USB_ZERO=m
 CONFIG_USB_ETH=m
 CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
 CONFIG_USB_G_SERIAL=m
 CONFIG_USB_CDC_COMPOSITE=m
 CONFIG_MMC=y
index 19973b06170c94a5518619a4fb07869c08c1727d..0421498d666b979b992446fe83603325786f2e03 100644 (file)
@@ -117,7 +117,7 @@ CONFIG_USB_GADGET=y
 CONFIG_USB_ZERO=m
 CONFIG_USB_ETH=m
 CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
 CONFIG_USB_G_SERIAL=m
 CONFIG_USB_CDC_COMPOSITE=m
 CONFIG_MMC=y
index 6f45681196d135a1290c2a5d7ae8be2b7b180d99..82f24eb251bdf44da77341e14d373f72d4763efa 100644 (file)
@@ -127,7 +127,7 @@ CONFIG_USB_GADGET=y
 CONFIG_USB_ZERO=m
 CONFIG_USB_ETH=m
 CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
 CONFIG_USB_G_SERIAL=m
 CONFIG_MMC=m
 CONFIG_MMC_ATMELMCI=m
index c280a50e79435a8a590631e915008c0036146324..f59c80ee78e3cff496c18a1c1f8e1c70a5b1bd23 100644 (file)
@@ -106,7 +106,7 @@ CONFIG_MUSB_PIO_ONLY=y
 CONFIG_USB_STORAGE=m
 CONFIG_USB_GADGET=m
 CONFIG_USB_ETH=m
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
 CONFIG_USB_G_SERIAL=m
 CONFIG_USB_G_PRINTER=m
 CONFIG_RTC_CLASS=y
index 349922be01f35c489deacff6ac6cb9b22cc3259a..e961483f1879bf2c3c13fdefdeb2b8db999d78b1 100644 (file)
@@ -107,7 +107,7 @@ CONFIG_USB_ZERO=m
 CONFIG_USB_ETH=m
 # CONFIG_USB_ETH_RNDIS is not set
 CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
 CONFIG_USB_G_SERIAL=m
 CONFIG_USB_G_PRINTER=m
 CONFIG_MMC=m
index 0456deaa2d6fbc94b62bb7e6a5feb4b815e9a07f..24936b91a6ee225ab491c168b42200ee4e2004c8 100644 (file)
@@ -83,7 +83,7 @@ CONFIG_GPIOLIB=y
 CONFIG_GPIO_SYSFS=y
 CONFIG_USB_GADGET=m
 CONFIG_USB_ETH=m
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
 CONFIG_USB_G_SERIAL=m
 CONFIG_USB_G_PRINTER=m
 CONFIG_MMC=y
index 407ebc00e661f974bbaec96a345afcea8f6b6409..cb83d8d21aef33877d718b7494e0afa11b8b9a99 100644 (file)
@@ -6,7 +6,7 @@
 #
 
 obj-y += prom.o time.o clocks.o platform.o power.o setup.o \
-       sleeper.o dma.o dbdma.o vss.o irq.o
+       sleeper.o dma.o dbdma.o vss.o irq.o usb.o
 
 # optional gpiolib support
 ifeq ($(CONFIG_ALCHEMY_GPIO_INDIRECT),)
index c0f3ce6dcb56d448bcb2184c5fdc2c61498a8d7c..7af941d8e717089cdb78b016368774a09e3bd4ef 100644 (file)
@@ -17,6 +17,8 @@
 #include <linux/platform_device.h>
 #include <linux/serial_8250.h>
 #include <linux/slab.h>
+#include <linux/usb/ehci_pdriver.h>
+#include <linux/usb/ohci_pdriver.h>
 
 #include <asm/mach-au1x00/au1000.h>
 #include <asm/mach-au1x00/au1xxx_dbdma.h>
@@ -122,6 +124,53 @@ static void __init alchemy_setup_uarts(int ctype)
 static u64 alchemy_ohci_dmamask = DMA_BIT_MASK(32);
 static u64 __maybe_unused alchemy_ehci_dmamask = DMA_BIT_MASK(32);
 
+/* Power on callback for the ehci platform driver */
+static int alchemy_ehci_power_on(struct platform_device *pdev)
+{
+       return alchemy_usb_control(ALCHEMY_USB_EHCI0, 1);
+}
+
+/* Power off/suspend callback for the ehci platform driver */
+static void alchemy_ehci_power_off(struct platform_device *pdev)
+{
+       alchemy_usb_control(ALCHEMY_USB_EHCI0, 0);
+}
+
+static struct usb_ehci_pdata alchemy_ehci_pdata = {
+       .no_io_watchdog = 1,
+       .power_on       = alchemy_ehci_power_on,
+       .power_off      = alchemy_ehci_power_off,
+       .power_suspend  = alchemy_ehci_power_off,
+};
+
+/* Power on callback for the ohci platform driver */
+static int alchemy_ohci_power_on(struct platform_device *pdev)
+{
+       int unit;
+
+       unit = (pdev->id == 1) ?
+               ALCHEMY_USB_OHCI1 : ALCHEMY_USB_OHCI0;
+
+       return alchemy_usb_control(unit, 1);
+}
+
+/* Power off/suspend callback for the ohci platform driver */
+static void alchemy_ohci_power_off(struct platform_device *pdev)
+{
+       int unit;
+
+       unit = (pdev->id == 1) ?
+               ALCHEMY_USB_OHCI1 : ALCHEMY_USB_OHCI0;
+
+       alchemy_usb_control(unit, 0);
+}
+
+static struct usb_ohci_pdata alchemy_ohci_pdata = {
+       .power_on               = alchemy_ohci_power_on,
+       .power_off              = alchemy_ohci_power_off,
+       .power_suspend          = alchemy_ohci_power_off,
+};
+
 static unsigned long alchemy_ohci_data[][2] __initdata = {
        [ALCHEMY_CPU_AU1000] = { AU1000_USB_OHCI_PHYS_ADDR, AU1000_USB_HOST_INT },
        [ALCHEMY_CPU_AU1500] = { AU1000_USB_OHCI_PHYS_ADDR, AU1500_USB_HOST_INT },
@@ -169,9 +218,10 @@ static void __init alchemy_setup_usb(int ctype)
        res[1].start = alchemy_ohci_data[ctype][1];
        res[1].end = res[1].start;
        res[1].flags = IORESOURCE_IRQ;
-       pdev->name = "au1xxx-ohci";
+       pdev->name = "ohci-platform";
        pdev->id = 0;
        pdev->dev.dma_mask = &alchemy_ohci_dmamask;
+       pdev->dev.platform_data = &alchemy_ohci_pdata;
 
        if (platform_device_register(pdev))
                printk(KERN_INFO "Alchemy USB: cannot add OHCI0\n");
@@ -188,9 +238,10 @@ static void __init alchemy_setup_usb(int ctype)
                res[1].start = alchemy_ehci_data[ctype][1];
                res[1].end = res[1].start;
                res[1].flags = IORESOURCE_IRQ;
-               pdev->name = "au1xxx-ehci";
+               pdev->name = "ehci-platform";
                pdev->id = 0;
                pdev->dev.dma_mask = &alchemy_ehci_dmamask;
+               pdev->dev.platform_data = &alchemy_ehci_pdata;
 
                if (platform_device_register(pdev))
                        printk(KERN_INFO "Alchemy USB: cannot add EHCI0\n");
@@ -207,9 +258,10 @@ static void __init alchemy_setup_usb(int ctype)
                res[1].start = AU1300_USB_INT;
                res[1].end = res[1].start;
                res[1].flags = IORESOURCE_IRQ;
-               pdev->name = "au1xxx-ohci";
+               pdev->name = "ohci-platform";
                pdev->id = 1;
                pdev->dev.dma_mask = &alchemy_ohci_dmamask;
+               pdev->dev.platform_data = &alchemy_ohci_pdata;
 
                if (platform_device_register(pdev))
                        printk(KERN_INFO "Alchemy USB: cannot add OHCI1\n");
diff --git a/arch/mips/alchemy/common/usb.c b/arch/mips/alchemy/common/usb.c
new file mode 100644 (file)
index 0000000..936af83
--- /dev/null
@@ -0,0 +1,614 @@
+/*
+ * USB block power/access management abstraction.
+ *
+ * Au1000+: The OHCI block control register is at the far end of the OHCI memory
+ *         area. Au1550 has OHCI on different base address. No need to handle
+ *         UDC here.
+ * Au1200:  one register to control access and clocks to O/EHCI, UDC and OTG
+ *         as well as the PHY for EHCI and UDC.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/syscore_ops.h>
+#include <asm/mach-au1x00/au1000.h>
+
+/* control register offsets */
+#define AU1000_OHCICFG 0x7fffc
+#define AU1550_OHCICFG 0x07ffc
+#define AU1200_USBCFG  0x04
+
+/* Au1000 USB block config bits */
+#define USBHEN_RD      (1 << 4)                /* OHCI reset-done indicator */
+#define USBHEN_CE      (1 << 3)                /* OHCI block clock enable */
+#define USBHEN_E       (1 << 2)                /* OHCI block enable */
+#define USBHEN_C       (1 << 1)                /* OHCI block coherency bit */
+#define USBHEN_BE      (1 << 0)                /* OHCI Big-Endian */
+
+/* Au1200 USB config bits */
+#define USBCFG_PFEN    (1 << 31)               /* prefetch enable (undoc) */
+#define USBCFG_RDCOMB  (1 << 30)               /* read combining (undoc) */
+#define USBCFG_UNKNOWN (5 << 20)               /* unknown, leave this way */
+#define USBCFG_SSD     (1 << 23)               /* serial short detect en */
+#define USBCFG_PPE     (1 << 19)               /* HS PHY PLL */
+#define USBCFG_UCE     (1 << 18)               /* UDC clock enable */
+#define USBCFG_ECE     (1 << 17)               /* EHCI clock enable */
+#define USBCFG_OCE     (1 << 16)               /* OHCI clock enable */
+#define USBCFG_FLA(x)  (((x) & 0x3f) << 8)
+#define USBCFG_UCAM    (1 << 7)                /* coherent access (undoc) */
+#define USBCFG_GME     (1 << 6)                /* OTG mem access */
+#define USBCFG_DBE     (1 << 5)                /* UDC busmaster enable */
+#define USBCFG_DME     (1 << 4)                /* UDC mem enable */
+#define USBCFG_EBE     (1 << 3)                /* EHCI busmaster enable */
+#define USBCFG_EME     (1 << 2)                /* EHCI mem enable */
+#define USBCFG_OBE     (1 << 1)                /* OHCI busmaster enable */
+#define USBCFG_OME     (1 << 0)                /* OHCI mem enable */
+#define USBCFG_INIT_AU1200     (USBCFG_PFEN | USBCFG_RDCOMB | USBCFG_UNKNOWN |\
+                                USBCFG_SSD | USBCFG_FLA(0x20) | USBCFG_UCAM | \
+                                USBCFG_GME | USBCFG_DBE | USBCFG_DME |        \
+                                USBCFG_EBE | USBCFG_EME | USBCFG_OBE |        \
+                                USBCFG_OME)
+
+/* Au1300 USB config registers */
+#define USB_DWC_CTRL1          0x00
+#define USB_DWC_CTRL2          0x04
+#define USB_VBUS_TIMER         0x10
+#define USB_SBUS_CTRL          0x14
+#define USB_MSR_ERR            0x18
+#define USB_DWC_CTRL3          0x1C
+#define USB_DWC_CTRL4          0x20
+#define USB_OTG_STATUS         0x28
+#define USB_DWC_CTRL5          0x2C
+#define USB_DWC_CTRL6          0x30
+#define USB_DWC_CTRL7          0x34
+#define USB_PHY_STATUS         0xC0
+#define USB_INT_STATUS         0xC4
+#define USB_INT_ENABLE         0xC8
+
+#define USB_DWC_CTRL1_OTGD     0x04 /* set to DISable OTG */
+#define USB_DWC_CTRL1_HSTRS    0x02 /* set to ENable EHCI */
+#define USB_DWC_CTRL1_DCRS     0x01 /* set to ENable UDC */
+
+#define USB_DWC_CTRL2_PHY1RS   0x04 /* set to enable PHY1 */
+#define USB_DWC_CTRL2_PHY0RS   0x02 /* set to enable PHY0 */
+#define USB_DWC_CTRL2_PHYRS    0x01 /* set to enable PHY */
+
+#define USB_DWC_CTRL3_OHCI1_CKEN       (1 << 19)
+#define USB_DWC_CTRL3_OHCI0_CKEN       (1 << 18)
+#define USB_DWC_CTRL3_EHCI0_CKEN       (1 << 17)
+#define USB_DWC_CTRL3_OTG0_CKEN                (1 << 16)
+
+#define USB_SBUS_CTRL_SBCA             0x04 /* coherent access */
+
+#define USB_INTEN_FORCE                        0x20
+#define USB_INTEN_PHY                  0x10
+#define USB_INTEN_UDC                  0x08
+#define USB_INTEN_EHCI                 0x04
+#define USB_INTEN_OHCI1                        0x02
+#define USB_INTEN_OHCI0                        0x01
+
+static DEFINE_SPINLOCK(alchemy_usb_lock);
+
+static inline void __au1300_usb_phyctl(void __iomem *base, int enable)
+{
+       unsigned long r, s;
+
+       r = __raw_readl(base + USB_DWC_CTRL2);
+       s = __raw_readl(base + USB_DWC_CTRL3);
+
+       s &= USB_DWC_CTRL3_OHCI1_CKEN | USB_DWC_CTRL3_OHCI0_CKEN |
+               USB_DWC_CTRL3_EHCI0_CKEN | USB_DWC_CTRL3_OTG0_CKEN;
+
+       if (enable) {
+               /* simply enable all PHYs */
+               r |= USB_DWC_CTRL2_PHY1RS | USB_DWC_CTRL2_PHY0RS |
+                    USB_DWC_CTRL2_PHYRS;
+               __raw_writel(r, base + USB_DWC_CTRL2);
+               wmb();
+       } else if (!s) {
+               /* no USB block active, do disable all PHYs */
+               r &= ~(USB_DWC_CTRL2_PHY1RS | USB_DWC_CTRL2_PHY0RS |
+                      USB_DWC_CTRL2_PHYRS);
+               __raw_writel(r, base + USB_DWC_CTRL2);
+               wmb();
+       }
+}
+
+static inline void __au1300_ohci_control(void __iomem *base, int enable, int id)
+{
+       unsigned long r;
+
+       if (enable) {
+               __raw_writel(1, base + USB_DWC_CTRL7);  /* start OHCI clock */
+               wmb();
+
+               r = __raw_readl(base + USB_DWC_CTRL3);  /* enable OHCI block */
+               r |= (id == 0) ? USB_DWC_CTRL3_OHCI0_CKEN
+                              : USB_DWC_CTRL3_OHCI1_CKEN;
+               __raw_writel(r, base + USB_DWC_CTRL3);
+               wmb();
+
+               __au1300_usb_phyctl(base, enable);      /* power up the PHYs */
+
+               r = __raw_readl(base + USB_INT_ENABLE);
+               r |= (id == 0) ? USB_INTEN_OHCI0 : USB_INTEN_OHCI1;
+               __raw_writel(r, base + USB_INT_ENABLE);
+               wmb();
+
+               /* reset the OHCI start clock bit */
+               __raw_writel(0, base + USB_DWC_CTRL7);
+               wmb();
+       } else {
+               r = __raw_readl(base + USB_INT_ENABLE);
+               r &= ~((id == 0) ? USB_INTEN_OHCI0 : USB_INTEN_OHCI1);
+               __raw_writel(r, base + USB_INT_ENABLE);
+               wmb();
+
+               r = __raw_readl(base + USB_DWC_CTRL3);
+               r &= ~((id == 0) ? USB_DWC_CTRL3_OHCI0_CKEN
+                                : USB_DWC_CTRL3_OHCI1_CKEN);
+               __raw_writel(r, base + USB_DWC_CTRL3);
+               wmb();
+
+               __au1300_usb_phyctl(base, enable);
+       }
+}
+
+static inline void __au1300_ehci_control(void __iomem *base, int enable)
+{
+       unsigned long r;
+
+       if (enable) {
+               r = __raw_readl(base + USB_DWC_CTRL3);
+               r |= USB_DWC_CTRL3_EHCI0_CKEN;
+               __raw_writel(r, base + USB_DWC_CTRL3);
+               wmb();
+
+               r = __raw_readl(base + USB_DWC_CTRL1);
+               r |= USB_DWC_CTRL1_HSTRS;
+               __raw_writel(r, base + USB_DWC_CTRL1);
+               wmb();
+
+               __au1300_usb_phyctl(base, enable);
+
+               r = __raw_readl(base + USB_INT_ENABLE);
+               r |= USB_INTEN_EHCI;
+               __raw_writel(r, base + USB_INT_ENABLE);
+               wmb();
+       } else {
+               r = __raw_readl(base + USB_INT_ENABLE);
+               r &= ~USB_INTEN_EHCI;
+               __raw_writel(r, base + USB_INT_ENABLE);
+               wmb();
+
+               r = __raw_readl(base + USB_DWC_CTRL1);
+               r &= ~USB_DWC_CTRL1_HSTRS;
+               __raw_writel(r, base + USB_DWC_CTRL1);
+               wmb();
+
+               r = __raw_readl(base + USB_DWC_CTRL3);
+               r &= ~USB_DWC_CTRL3_EHCI0_CKEN;
+               __raw_writel(r, base + USB_DWC_CTRL3);
+               wmb();
+
+               __au1300_usb_phyctl(base, enable);
+       }
+}
+
+static inline void __au1300_udc_control(void __iomem *base, int enable)
+{
+       unsigned long r;
+
+       if (enable) {
+               r = __raw_readl(base + USB_DWC_CTRL1);
+               r |= USB_DWC_CTRL1_DCRS;
+               __raw_writel(r, base + USB_DWC_CTRL1);
+               wmb();
+
+               __au1300_usb_phyctl(base, enable);
+
+               r = __raw_readl(base + USB_INT_ENABLE);
+               r |= USB_INTEN_UDC;
+               __raw_writel(r, base + USB_INT_ENABLE);
+               wmb();
+       } else {
+               r = __raw_readl(base + USB_INT_ENABLE);
+               r &= ~USB_INTEN_UDC;
+               __raw_writel(r, base + USB_INT_ENABLE);
+               wmb();
+
+               r = __raw_readl(base + USB_DWC_CTRL1);
+               r &= ~USB_DWC_CTRL1_DCRS;
+               __raw_writel(r, base + USB_DWC_CTRL1);
+               wmb();
+
+               __au1300_usb_phyctl(base, enable);
+       }
+}
+
+static inline void __au1300_otg_control(void __iomem *base, int enable)
+{
+       unsigned long r;
+       if (enable) {
+               r = __raw_readl(base + USB_DWC_CTRL3);
+               r |= USB_DWC_CTRL3_OTG0_CKEN;
+               __raw_writel(r, base + USB_DWC_CTRL3);
+               wmb();
+
+               r = __raw_readl(base + USB_DWC_CTRL1);
+               r &= ~USB_DWC_CTRL1_OTGD;
+               __raw_writel(r, base + USB_DWC_CTRL1);
+               wmb();
+
+               __au1300_usb_phyctl(base, enable);
+       } else {
+               r = __raw_readl(base + USB_DWC_CTRL1);
+               r |= USB_DWC_CTRL1_OTGD;
+               __raw_writel(r, base + USB_DWC_CTRL1);
+               wmb();
+
+               r = __raw_readl(base + USB_DWC_CTRL3);
+               r &= ~USB_DWC_CTRL3_OTG0_CKEN;
+               __raw_writel(r, base + USB_DWC_CTRL3);
+               wmb();
+
+               __au1300_usb_phyctl(base, enable);
+       }
+}
+
+static inline int au1300_usb_control(int block, int enable)
+{
+       void __iomem *base =
+               (void __iomem *)KSEG1ADDR(AU1300_USB_CTL_PHYS_ADDR);
+       int ret = 0;
+
+       switch (block) {
+       case ALCHEMY_USB_OHCI0:
+               __au1300_ohci_control(base, enable, 0);
+               break;
+       case ALCHEMY_USB_OHCI1:
+               __au1300_ohci_control(base, enable, 1);
+               break;
+       case ALCHEMY_USB_EHCI0:
+               __au1300_ehci_control(base, enable);
+               break;
+       case ALCHEMY_USB_UDC0:
+               __au1300_udc_control(base, enable);
+               break;
+       case ALCHEMY_USB_OTG0:
+               __au1300_otg_control(base, enable);
+               break;
+       default:
+               ret = -ENODEV;
+       }
+       return ret;
+}
+
+static inline void au1300_usb_init(void)
+{
+       void __iomem *base =
+               (void __iomem *)KSEG1ADDR(AU1300_USB_CTL_PHYS_ADDR);
+
+       /* set some sane defaults.  Note: we don't fiddle with DWC_CTRL4
+        * here at all: Port 2 routing (EHCI or UDC) must be set either
+        * by boot firmware or platform init code; I can't autodetect
+        * a sane setting.
+        */
+       __raw_writel(0, base + USB_INT_ENABLE); /* disable all USB irqs */
+       wmb();
+       __raw_writel(0, base + USB_DWC_CTRL3); /* disable all clocks */
+       wmb();
+       __raw_writel(~0, base + USB_MSR_ERR); /* clear all errors */
+       wmb();
+       __raw_writel(~0, base + USB_INT_STATUS); /* clear int status */
+       wmb();
+       /* set coherent access bit */
+       __raw_writel(USB_SBUS_CTRL_SBCA, base + USB_SBUS_CTRL);
+       wmb();
+}
+
+static inline void __au1200_ohci_control(void __iomem *base, int enable)
+{
+       unsigned long r = __raw_readl(base + AU1200_USBCFG);
+       if (enable) {
+               __raw_writel(r | USBCFG_OCE, base + AU1200_USBCFG);
+               wmb();
+               udelay(2000);
+       } else {
+               __raw_writel(r & ~USBCFG_OCE, base + AU1200_USBCFG);
+               wmb();
+               udelay(1000);
+       }
+}
+
+static inline void __au1200_ehci_control(void __iomem *base, int enable)
+{
+       unsigned long r = __raw_readl(base + AU1200_USBCFG);
+       if (enable) {
+               __raw_writel(r | USBCFG_ECE | USBCFG_PPE, base + AU1200_USBCFG);
+               wmb();
+               udelay(1000);
+       } else {
+               if (!(r & USBCFG_UCE))          /* UDC also off? */
+                       r &= ~USBCFG_PPE;       /* yes: disable HS PHY PLL */
+               __raw_writel(r & ~USBCFG_ECE, base + AU1200_USBCFG);
+               wmb();
+               udelay(1000);
+       }
+}
+
+static inline void __au1200_udc_control(void __iomem *base, int enable)
+{
+       unsigned long r = __raw_readl(base + AU1200_USBCFG);
+       if (enable) {
+               __raw_writel(r | USBCFG_UCE | USBCFG_PPE, base + AU1200_USBCFG);
+               wmb();
+       } else {
+               if (!(r & USBCFG_ECE))          /* EHCI also off? */
+                       r &= ~USBCFG_PPE;       /* yes: disable HS PHY PLL */
+               __raw_writel(r & ~USBCFG_UCE, base + AU1200_USBCFG);
+               wmb();
+       }
+}
+
+static inline int au1200_coherency_bug(void)
+{
+#if defined(CONFIG_DMA_COHERENT)
+       /* Au1200 AB USB does not support coherent memory */
+       if (!(read_c0_prid() & 0xff)) {
+               printk(KERN_INFO "Au1200 USB: this is chip revision AB !!\n");
+               printk(KERN_INFO "Au1200 USB: update your board or re-configure"
+                                " the kernel\n");
+               return -ENODEV;
+       }
+#endif
+       return 0;
+}
+
+static inline int au1200_usb_control(int block, int enable)
+{
+       void __iomem *base =
+                       (void __iomem *)KSEG1ADDR(AU1200_USB_CTL_PHYS_ADDR);
+       int ret = 0;
+
+       switch (block) {
+       case ALCHEMY_USB_OHCI0:
+               ret = au1200_coherency_bug();
+               if (ret && enable)
+                       goto out;
+               __au1200_ohci_control(base, enable);
+               break;
+       case ALCHEMY_USB_UDC0:
+               __au1200_udc_control(base, enable);
+               break;
+       case ALCHEMY_USB_EHCI0:
+               ret = au1200_coherency_bug();
+               if (ret && enable)
+                       goto out;
+               __au1200_ehci_control(base, enable);
+               break;
+       default:
+               ret = -ENODEV;
+       }
+out:
+       return ret;
+}
+
+
+/* initialize USB block(s) to a known working state */
+static inline void au1200_usb_init(void)
+{
+       void __iomem *base =
+                       (void __iomem *)KSEG1ADDR(AU1200_USB_CTL_PHYS_ADDR);
+       __raw_writel(USBCFG_INIT_AU1200, base + AU1200_USBCFG);
+       wmb();
+       udelay(1000);
+}
+
+static inline void au1000_usb_init(unsigned long rb, int reg)
+{
+       void __iomem *base = (void __iomem *)KSEG1ADDR(rb + reg);
+       unsigned long r = __raw_readl(base);
+
+#if defined(__BIG_ENDIAN)
+       r |= USBHEN_BE;
+#endif
+       r |= USBHEN_C;
+
+       __raw_writel(r, base);
+       wmb();
+       udelay(1000);
+}
+
+
+static inline void __au1xx0_ohci_control(int enable, unsigned long rb, int creg)
+{
+       void __iomem *base = (void __iomem *)KSEG1ADDR(rb);
+       unsigned long r = __raw_readl(base + creg);
+
+       if (enable) {
+               __raw_writel(r | USBHEN_CE, base + creg);
+               wmb();
+               udelay(1000);
+               __raw_writel(r | USBHEN_CE | USBHEN_E, base + creg);
+               wmb();
+               udelay(1000);
+
+               /* wait for reset complete (read reg twice: au1500 erratum) */
+               while (__raw_readl(base + creg),
+                       !(__raw_readl(base + creg) & USBHEN_RD))
+                       udelay(1000);
+       } else {
+               __raw_writel(r & ~(USBHEN_CE | USBHEN_E), base + creg);
+               wmb();
+       }
+}
+
+static inline int au1000_usb_control(int block, int enable, unsigned long rb,
+                                    int creg)
+{
+       int ret = 0;
+
+       switch (block) {
+       case ALCHEMY_USB_OHCI0:
+               __au1xx0_ohci_control(enable, rb, creg);
+               break;
+       default:
+               ret = -ENODEV;
+       }
+       return ret;
+}
+
+/*
+ * alchemy_usb_control - control Alchemy on-chip USB blocks
+ * @block:     USB block to target
+ * @enable:    set 1 to enable a block, 0 to disable
+ */
+int alchemy_usb_control(int block, int enable)
+{
+       unsigned long flags;
+       int ret;
+
+       spin_lock_irqsave(&alchemy_usb_lock, flags);
+       switch (alchemy_get_cputype()) {
+       case ALCHEMY_CPU_AU1000:
+       case ALCHEMY_CPU_AU1500:
+       case ALCHEMY_CPU_AU1100:
+               ret = au1000_usb_control(block, enable,
+                               AU1000_USB_OHCI_PHYS_ADDR, AU1000_OHCICFG);
+               break;
+       case ALCHEMY_CPU_AU1550:
+               ret = au1000_usb_control(block, enable,
+                               AU1550_USB_OHCI_PHYS_ADDR, AU1550_OHCICFG);
+               break;
+       case ALCHEMY_CPU_AU1200:
+               ret = au1200_usb_control(block, enable);
+               break;
+       case ALCHEMY_CPU_AU1300:
+               ret = au1300_usb_control(block, enable);
+               break;
+       default:
+               ret = -ENODEV;
+       }
+       spin_unlock_irqrestore(&alchemy_usb_lock, flags);
+       return ret;
+}
+EXPORT_SYMBOL_GPL(alchemy_usb_control);
+
+
+static unsigned long alchemy_usb_pmdata[2];
+
+static void au1000_usb_pm(unsigned long br, int creg, int susp)
+{
+       void __iomem *base = (void __iomem *)KSEG1ADDR(br);
+
+       if (susp) {
+               alchemy_usb_pmdata[0] = __raw_readl(base + creg);
+               /* There appears to be some undocumented reset register.... */
+               __raw_writel(0, base + 0x04);
+               wmb();
+               __raw_writel(0, base + creg);
+               wmb();
+       } else {
+               __raw_writel(alchemy_usb_pmdata[0], base + creg);
+               wmb();
+       }
+}
+
+static void au1200_usb_pm(int susp)
+{
+       void __iomem *base =
+                       (void __iomem *)KSEG1ADDR(AU1200_USB_OTG_PHYS_ADDR);
+       if (susp) {
+               /* save OTG_CAP/MUX registers which indicate port routing */
+               /* FIXME: write an OTG driver to do that */
+               alchemy_usb_pmdata[0] = __raw_readl(base + 0x00);
+               alchemy_usb_pmdata[1] = __raw_readl(base + 0x04);
+       } else {
+               /* restore access to all MMIO areas */
+               au1200_usb_init();
+
+               /* restore OTG_CAP/MUX registers */
+               __raw_writel(alchemy_usb_pmdata[0], base + 0x00);
+               __raw_writel(alchemy_usb_pmdata[1], base + 0x04);
+               wmb();
+       }
+}
+
+static void au1300_usb_pm(int susp)
+{
+       void __iomem *base =
+                       (void __iomem *)KSEG1ADDR(AU1300_USB_CTL_PHYS_ADDR);
+       /* remember Port2 routing */
+       if (susp) {
+               alchemy_usb_pmdata[0] = __raw_readl(base + USB_DWC_CTRL4);
+       } else {
+               au1300_usb_init();
+               __raw_writel(alchemy_usb_pmdata[0], base + USB_DWC_CTRL4);
+               wmb();
+       }
+}
+
+static void alchemy_usb_pm(int susp)
+{
+       switch (alchemy_get_cputype()) {
+       case ALCHEMY_CPU_AU1000:
+       case ALCHEMY_CPU_AU1500:
+       case ALCHEMY_CPU_AU1100:
+               au1000_usb_pm(AU1000_USB_OHCI_PHYS_ADDR, AU1000_OHCICFG, susp);
+               break;
+       case ALCHEMY_CPU_AU1550:
+               au1000_usb_pm(AU1550_USB_OHCI_PHYS_ADDR, AU1550_OHCICFG, susp);
+               break;
+       case ALCHEMY_CPU_AU1200:
+               au1200_usb_pm(susp);
+               break;
+       case ALCHEMY_CPU_AU1300:
+               au1300_usb_pm(susp);
+               break;
+       }
+}
+
+static int alchemy_usb_suspend(void)
+{
+       alchemy_usb_pm(1);
+       return 0;
+}
+
+static void alchemy_usb_resume(void)
+{
+       alchemy_usb_pm(0);
+}
+
+static struct syscore_ops alchemy_usb_pm_ops = {
+       .suspend        = alchemy_usb_suspend,
+       .resume         = alchemy_usb_resume,
+};
+
+static int __init alchemy_usb_init(void)
+{
+       switch (alchemy_get_cputype()) {
+       case ALCHEMY_CPU_AU1000:
+       case ALCHEMY_CPU_AU1500:
+       case ALCHEMY_CPU_AU1100:
+               au1000_usb_init(AU1000_USB_OHCI_PHYS_ADDR, AU1000_OHCICFG);
+               break;
+       case ALCHEMY_CPU_AU1550:
+               au1000_usb_init(AU1550_USB_OHCI_PHYS_ADDR, AU1550_OHCICFG);
+               break;
+       case ALCHEMY_CPU_AU1200:
+               au1200_usb_init();
+               break;
+       case ALCHEMY_CPU_AU1300:
+               au1300_usb_init();
+               break;
+       }
+
+       register_syscore_ops(&alchemy_usb_pm_ops);
+
+       return 0;
+}
+arch_initcall(alchemy_usb_init);
index 072bb9be2304b2225e7a49ce44e860dc052504f5..bd2bc108e1b50a6052adad7619ecee6f6acf1511 100644 (file)
@@ -50,13 +50,11 @@ static u64 ath79_ehci_dmamask = DMA_BIT_MASK(32);
 
 static struct usb_ehci_pdata ath79_ehci_pdata_v1 = {
        .has_synopsys_hc_bug    = 1,
-       .port_power_off         = 1,
 };
 
 static struct usb_ehci_pdata ath79_ehci_pdata_v2 = {
        .caps_offset            = 0x100,
        .has_tt                 = 1,
-       .port_power_off         = 1,
 };
 
 static struct platform_device ath79_ehci_device = {
index b6fde2bb51b635390c88db8a118430233710e4cf..4ca8e5c99225f64ff77347b9e2be2184b586f399 100644 (file)
@@ -473,7 +473,7 @@ CONFIG_USB_GADGET_NET2280=y
 CONFIG_USB_ZERO=m
 CONFIG_USB_ETH=m
 CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
 CONFIG_USB_G_SERIAL=m
 CONFIG_USB_MIDI_GADGET=m
 CONFIG_LEDS_CLASS=y
index 17a36c12517296f95f772396670f0610a7f29b86..face9d26e6d5a1558c93cd149e60eb742fad8619 100644 (file)
@@ -233,6 +233,7 @@ CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_EHCI_ROOT_HUB_TT=y
 CONFIG_USB_EHCI_TT_NEWSCHED=y
 CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_OHCI_HCD_PLATFORM=y
 CONFIG_USB_UHCI_HCD=y
 CONFIG_USB_STORAGE=y
 CONFIG_NEW_LEDS=y
index c48998ffd198ebc8c34d6d90b6887019a566ed8b..14752dde754018170930faa0aabfbd049b2a4312 100644 (file)
@@ -346,8 +346,10 @@ CONFIG_USB=y
 CONFIG_USB_DYNAMIC_MINORS=y
 CONFIG_USB_SUSPEND=y
 CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_HCD_PLATFORM=y
 CONFIG_USB_EHCI_ROOT_HUB_TT=y
 CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_OHCI_HCD_PLATFORM=y
 CONFIG_USB_STORAGE=y
 CONFIG_MMC=y
 CONFIG_MMC_CLKGATE=y
index 48a40aefaf58fa615985e2f41eb07b7c2dbf04d6..fb64589015fc2bb6841e4e23676d030003590940 100644 (file)
@@ -291,6 +291,7 @@ CONFIG_USB_MON=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_EHCI_ROOT_HUB_TT=y
 CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_OHCI_HCD_PLATFORM=y
 CONFIG_USB_STORAGE=m
 CONFIG_USB_LIBUSUAL=y
 CONFIG_USB_SERIAL=y
index 80cff8bea8e82beddd5dde7b13aa0610c7799799..7eb75543ca1a23b5be78e89ae3ec33b0f3d446db 100644 (file)
@@ -76,6 +76,7 @@ CONFIG_HID_GENERIC=m
 CONFIG_USB=y
 CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
 CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_HCD_PLATFORM=y
 # CONFIG_USB_EHCI_TT_NEWSCHED is not set
 CONFIG_USB_STORAGE=m
 CONFIG_USB_SERIAL=m
index 46c61edcdf7b68440e54ce6d6032daa5075f7685..9fa8f16068d8c26ea03a3211e5ea2b0b46150a78 100644 (file)
@@ -581,6 +581,7 @@ CONFIG_USB_MON=m
 CONFIG_USB_EHCI_HCD=m
 CONFIG_USB_EHCI_ROOT_HUB_TT=y
 CONFIG_USB_OHCI_HCD=m
+CONFIG_USB_OHCI_HCD_PLATFORM=y
 CONFIG_USB_UHCI_HCD=m
 CONFIG_USB_U132_HCD=m
 CONFIG_USB_SL811_HCD=m
@@ -661,7 +662,7 @@ CONFIG_USB_GADGET_NET2280=y
 CONFIG_USB_ZERO=m
 CONFIG_USB_ETH=m
 CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
 CONFIG_USB_G_SERIAL=m
 CONFIG_USB_MIDI_GADGET=m
 CONFIG_MMC=m
index e92d59c4bd789e783809a5ed15e3e19c7f965ced..0412ad61e2908fb99552b1d2cd1ac6a27ead90bb 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/phy.h>
 #include <linux/serial_8250.h>
 #include <linux/stmmac.h>
+#include <linux/usb/ehci_pdriver.h>
 #include <asm-generic/sizes.h>
 
 #include <loongson1.h>
@@ -107,13 +108,17 @@ static struct resource ls1x_ehci_resources[] = {
        },
 };
 
+static struct usb_ehci_pdata ls1x_ehci_pdata = {
+};
+
 struct platform_device ls1x_ehci_device = {
-       .name           = "ls1x-ehci",
+       .name           = "ehci-platform",
        .id             = -1,
        .num_resources  = ARRAY_SIZE(ls1x_ehci_resources),
        .resource       = ls1x_ehci_resources,
        .dev            = {
                .dma_mask = &ls1x_ehci_dmamask,
+               .platform_data = &ls1x_ehci_pdata,
        },
 };
 
index 71b44d82621db706844aacfb52f698128a6f58b6..507230eeb7685e9292eb533e7932441db11e92e0 100644 (file)
@@ -15,6 +15,8 @@
 #include <linux/serial_8250.h>
 #include <linux/serial_reg.h>
 #include <linux/i2c.h>
+#include <linux/usb/ehci_pdriver.h>
+#include <linux/usb/ohci_pdriver.h>
 
 #include <asm/netlogic/haldefs.h>
 #include <asm/netlogic/xlr/iomap.h>
@@ -123,12 +125,18 @@ static u64 xls_usb_dmamask = ~(u32)0;
                },                                                      \
        }
 
+static struct usb_ehci_pdata xls_usb_ehci_pdata = {
+       .caps_offset    = 0,
+};
+
+static struct usb_ohci_pdata xls_usb_ohci_pdata;
+
 static struct platform_device xls_usb_ehci_device =
-                        USB_PLATFORM_DEV("ehci-xls", 0, PIC_USB_IRQ);
+                        USB_PLATFORM_DEV("ehci-platform", 0, PIC_USB_IRQ);
 static struct platform_device xls_usb_ohci_device_0 =
-                        USB_PLATFORM_DEV("ohci-xls-0", 1, PIC_USB_IRQ);
+                        USB_PLATFORM_DEV("ohci-platform", 1, PIC_USB_IRQ);
 static struct platform_device xls_usb_ohci_device_1 =
-                        USB_PLATFORM_DEV("ohci-xls-1", 2, PIC_USB_IRQ);
+                        USB_PLATFORM_DEV("ohci-platform", 2, PIC_USB_IRQ);
 
 static struct platform_device *xls_platform_devices[] = {
        &xls_usb_ehci_device,
@@ -172,14 +180,17 @@ int xls_platform_usb_init(void)
        memres = CPHYSADDR((unsigned long)usb_mmio);
        xls_usb_ehci_device.resource[0].start = memres;
        xls_usb_ehci_device.resource[0].end = memres + 0x400 - 1;
+       xls_usb_ehci_device.dev.platform_data = &xls_usb_ehci_pdata;
 
        memres += 0x400;
        xls_usb_ohci_device_0.resource[0].start = memres;
        xls_usb_ohci_device_0.resource[0].end = memres + 0x400 - 1;
+       xls_usb_ohci_device_0.dev.platform_data = &xls_usb_ohci_pdata;
 
        memres += 0x400;
        xls_usb_ohci_device_1.resource[0].start = memres;
        xls_usb_ohci_device_1.resource[0].end = memres + 0x400 - 1;
+       xls_usb_ohci_device_1.dev.platform_data = &xls_usb_ohci_pdata;
 
        return platform_add_devices(xls_platform_devices,
                                ARRAY_SIZE(xls_platform_devices));
index 5264cc09a27bacbe2057ca7a66e50645a3eefd04..0a8faeaa7b70e4c3c9e893dde55e377c31e85f9a 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/serial.h>
 #include <linux/serial_pnx8xxx.h>
 #include <linux/platform_device.h>
+#include <linux/usb/ohci_pdriver.h>
 
 #include <int.h>
 #include <usb.h>
@@ -96,12 +97,40 @@ static u64 ohci_dmamask = DMA_BIT_MASK(32);
 
 static u64 uart_dmamask = DMA_BIT_MASK(32);
 
+static int pnx8550_usb_ohci_power_on(struct platform_device *pdev)
+{
+       /*
+        * Set register CLK48CTL to enable and 48MHz
+        */
+       outl(0x00000003, PCI_BASE | 0x0004770c);
+
+       /*
+        * Set register CLK12CTL to enable and 48MHz
+        */
+       outl(0x00000003, PCI_BASE | 0x00047710);
+
+       udelay(100);
+
+       return 0;
+}
+
+static void pnx8550_usb_ohci_power_off(struct platform_device *pdev)
+{
+       udelay(10);
+}
+
+static struct usb_ohci_pdata pnx8550_usb_ohci_pdata = {
+       .power_on       = pnx8550_usb_ohci_power_on,
+       .power_off      = pnx8550_usb_ohci_power_off,
+};
+
 static struct platform_device pnx8550_usb_ohci_device = {
-       .name           = "pnx8550-ohci",
+       .name           = "ohci-platform",
        .id             = -1,
        .dev = {
                .dma_mask               = &ohci_dmamask,
                .coherent_dma_mask      = DMA_BIT_MASK(32),
+               .platform_data          = &pnx8550_usb_ohci_pdata,
        },
        .num_resources  = ARRAY_SIZE(pnx8550_usb_ohci_resources),
        .resource       = pnx8550_usb_ohci_resources,
index 911e30c9abfdc98603816a4a72ee438f062726ab..c6c2becdc8ab053f52884c3f0ab1e097b95cbb03 100644 (file)
@@ -112,7 +112,7 @@ CONFIG_USB_MON=y
 CONFIG_USB_R8A66597_HCD=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
 CONFIG_MMC=y
 CONFIG_MMC_SPI=y
 CONFIG_MMC_SDHI=y
index ed35093e375892701300277b1f2072cdefba01ad..1faa788aecae48754cadcb0cd8ff4600213f20bf 100644 (file)
@@ -109,7 +109,7 @@ CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_ETH=m
 CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_MASS_STORAGE=m
 CONFIG_USB_G_SERIAL=m
 CONFIG_MMC=y
 CONFIG_MMC_SPI=y
index 0c2f1b2c2e1973440465e679ec1dd674e2522836..42d991f632b1f4b013b55af71df2a81f143b6090 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/serial_sci.h>
 #include <linux/sh_timer.h>
 #include <linux/sh_intc.h>
+#include <linux/usb/ohci_pdriver.h>
 #include <asm/rtc.h>
 #include <cpu/serial.h>
 
@@ -103,12 +104,15 @@ static struct resource usb_ohci_resources[] = {
 
 static u64 usb_ohci_dma_mask = 0xffffffffUL;
 
+static struct usb_ohci_pdata usb_ohci_pdata;
+
 static struct platform_device usb_ohci_device = {
-       .name           = "sh_ohci",
+       .name           = "ohci-platform",
        .id             = -1,
        .dev = {
                .dma_mask               = &usb_ohci_dma_mask,
                .coherent_dma_mask      = 0xffffffff,
+               .platform_data          = &usb_ohci_pdata,
        },
        .num_resources  = ARRAY_SIZE(usb_ohci_resources),
        .resource       = usb_ohci_resources,
index 4a2f357f4df8a1b93fd285b0e0c461dbbc2897d5..9079a0f9ea9be7b48369ffd7bcc2e6e516916326 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/sh_timer.h>
 #include <linux/sh_dma.h>
 #include <linux/sh_intc.h>
+#include <linux/usb/ohci_pdriver.h>
 #include <cpu/dma-register.h>
 #include <cpu/sh7757.h>
 
@@ -750,12 +751,15 @@ static struct resource usb_ohci_resources[] = {
        },
 };
 
+static struct usb_ohci_pdata usb_ohci_pdata;
+
 static struct platform_device usb_ohci_device = {
-       .name           = "sh_ohci",
+       .name           = "ohci-platform",
        .id             = -1,
        .dev = {
                .dma_mask = &usb_ohci_device.dev.coherent_dma_mask,
                .coherent_dma_mask = DMA_BIT_MASK(32),
+               .platform_data  = &usb_ohci_pdata,
        },
        .num_resources  = ARRAY_SIZE(usb_ohci_resources),
        .resource       = usb_ohci_resources,
index bd0a8fbe610f678077cad20dc1b5af07f9b46b8b..1686acaaf45af226a8f6809f937896abee8000c5 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/sh_intc.h>
 #include <linux/io.h>
 #include <linux/serial_sci.h>
+#include <linux/usb/ohci_pdriver.h>
 
 static struct plat_sci_port scif0_platform_data = {
        .mapbase        = 0xffe00000,
@@ -106,12 +107,15 @@ static struct resource usb_ohci_resources[] = {
 
 static u64 usb_ohci_dma_mask = 0xffffffffUL;
 
+static struct usb_ohci_pdata usb_ohci_pdata;
+
 static struct platform_device usb_ohci_device = {
-       .name           = "sh_ohci",
+       .name           = "ohci-platform",
        .id             = -1,
        .dev = {
                .dma_mask               = &usb_ohci_dma_mask,
                .coherent_dma_mask      = 0xffffffff,
+               .platform_data          = &usb_ohci_pdata,
        },
        .num_resources  = ARRAY_SIZE(usb_ohci_resources),
        .resource       = usb_ohci_resources,
index 2e6952f87848e287a6ad042414fc8f3d9532ccc8..ab52d4d4484d460bffc3b66ec9be5a60287d92cd 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/sh_timer.h>
 #include <linux/sh_dma.h>
 #include <linux/sh_intc.h>
+#include <linux/usb/ohci_pdriver.h>
 #include <cpu/dma-register.h>
 #include <asm/mmzone.h>
 
@@ -583,12 +584,15 @@ static struct resource usb_ohci_resources[] = {
        },
 };
 
+static struct usb_ohci_pdata usb_ohci_pdata;
+
 static struct platform_device usb_ohci_device = {
-       .name           = "sh_ohci",
+       .name           = "ohci-platform",
        .id             = -1,
        .dev = {
                .dma_mask               = &usb_ohci_device.dev.coherent_dma_mask,
                .coherent_dma_mask      = DMA_BIT_MASK(32),
+               .platform_data          = &usb_ohci_pdata,
        },
        .num_resources  = ARRAY_SIZE(usb_ohci_resources),
        .resource       = usb_ohci_resources,
index 1ea932a13685f32acddfd8231affb29add64d220..608a2aeb400c929726c4a9581dfad1e09eeed179 100644 (file)
@@ -20,6 +20,7 @@ config USB_CHIPIDEA_UDC
 config USB_CHIPIDEA_HOST
        bool "ChipIdea host controller"
        depends on USB=y || USB=USB_CHIPIDEA
+       depends on USB_EHCI_HCD
        select USB_EHCI_ROOT_HUB_TT
        help
          Say Y here to enable host controller functionality of the
index c6f50a257565db0691528ea5341a2a3a9d2d74b0..3bc244d2636ab9c7d0f1b9281de6e318715dcd29 100644 (file)
@@ -160,9 +160,6 @@ static ssize_t show_device(struct device *dev, struct device_attribute *attr,
                       gadget->speed);
        n += scnprintf(buf + n, PAGE_SIZE - n, "max_speed         = %d\n",
                       gadget->max_speed);
-       /* TODO: Scheduled for removal in 3.8. */
-       n += scnprintf(buf + n, PAGE_SIZE - n, "is_dualspeed      = %d\n",
-                      gadget_is_dualspeed(gadget));
        n += scnprintf(buf + n, PAGE_SIZE - n, "is_otg            = %d\n",
                       gadget->is_otg);
        n += scnprintf(buf + n, PAGE_SIZE - n, "is_a_peripheral   = %d\n",
index ebff9f4f56ec172875b9c333de12c514b1b719e3..caecad9213f5cf14f3ef45827548c77e0648dfb9 100644 (file)
  */
 
 #include <linux/kernel.h>
+#include <linux/io.h>
 #include <linux/usb.h>
 #include <linux/usb/hcd.h>
 #include <linux/usb/chipidea.h>
 
-#define CHIPIDEA_EHCI
-#include "../host/ehci-hcd.c"
+#include "../host/ehci.h"
 
 #include "ci.h"
 #include "bits.h"
 #include "host.h"
 
-static int ci_ehci_setup(struct usb_hcd *hcd)
-{
-       struct ehci_hcd *ehci = hcd_to_ehci(hcd);
-       int ret;
-
-       hcd->has_tt = 1;
-
-       ret = ehci_setup(hcd);
-       if (ret)
-               return ret;
-
-       ehci_port_power(ehci, 0);
-
-       return ret;
-}
-
-static const struct hc_driver ci_ehci_hc_driver = {
-       .description    = "ehci_hcd",
-       .product_desc   = "ChipIdea HDRC EHCI",
-       .hcd_priv_size  = sizeof(struct ehci_hcd),
-
-       /*
-        * generic hardware linkage
-        */
-       .irq    = ehci_irq,
-       .flags  = HCD_MEMORY | HCD_USB2,
-
-       /*
-        * basic lifecycle operations
-        */
-       .reset          = ci_ehci_setup,
-       .start          = ehci_run,
-       .stop           = ehci_stop,
-       .shutdown       = ehci_shutdown,
-
-       /*
-        * managing i/o requests and associated device resources
-        */
-       .urb_enqueue            = ehci_urb_enqueue,
-       .urb_dequeue            = ehci_urb_dequeue,
-       .endpoint_disable       = ehci_endpoint_disable,
-       .endpoint_reset         = ehci_endpoint_reset,
-
-       /*
-        * scheduling support
-        */
-       .get_frame_number = ehci_get_frame,
-
-       /*
-        * root hub support
-        */
-       .hub_status_data        = ehci_hub_status_data,
-       .hub_control            = ehci_hub_control,
-       .bus_suspend            = ehci_bus_suspend,
-       .bus_resume             = ehci_bus_resume,
-       .relinquish_port        = ehci_relinquish_port,
-       .port_handed_over       = ehci_port_handed_over,
-
-       .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
-};
+static struct hc_driver __read_mostly ci_ehci_hc_driver;
 
 static irqreturn_t host_irq(struct ci13xxx *ci)
 {
@@ -157,5 +98,7 @@ int ci_hdrc_host_init(struct ci13xxx *ci)
        rdrv->name      = "host";
        ci->roles[CI_ROLE_HOST] = rdrv;
 
+       ehci_init_driver(&ci_ehci_hc_driver, NULL);
+
        return 0;
 }
index f460de31aceee80200ff9e91f514917bae9f7adc..cbacea933b18cbc9c6287acec62f465495569b1e 100644 (file)
@@ -591,16 +591,14 @@ static ssize_t usb_device_dump(char __user **buffer, size_t *nbytes,
 
        /* Now look at all of this device's children. */
        usb_hub_for_each_child(usbdev, chix, childdev) {
-               if (childdev) {
-                       usb_lock_device(childdev);
-                       ret = usb_device_dump(buffer, nbytes, skip_bytes,
-                                             file_offset, childdev, bus,
-                                             level + 1, chix - 1, ++cnt);
-                       usb_unlock_device(childdev);
-                       if (ret == -EFAULT)
-                               return total_written;
-                       total_written += ret;
-               }
+               usb_lock_device(childdev);
+               ret = usb_device_dump(buffer, nbytes, skip_bytes,
+                                     file_offset, childdev, bus,
+                                     level + 1, chix - 1, ++cnt);
+               usb_unlock_device(childdev);
+               if (ret == -EFAULT)
+                       return total_written;
+               total_written += ret;
        }
        return total_written;
 }
index 1e741bca02652e8f4ed2b027654abc3ac9d16a4f..eaa14514e173163bf46aba9dd65cddaa57fb85fd 100644 (file)
@@ -2039,8 +2039,9 @@ int hcd_bus_resume(struct usb_device *rhdev, pm_message_t msg)
        status = hcd->driver->bus_resume(hcd);
        clear_bit(HCD_FLAG_WAKEUP_PENDING, &hcd->flags);
        if (status == 0) {
-               /* TRSMRCY = 10 msec */
-               msleep(10);
+               struct usb_device *udev;
+               int port1;
+
                spin_lock_irq(&hcd_root_hub_lock);
                if (!HCD_DEAD(hcd)) {
                        usb_set_device_state(rhdev, rhdev->actconfig
@@ -2050,6 +2051,20 @@ int hcd_bus_resume(struct usb_device *rhdev, pm_message_t msg)
                        hcd->state = HC_STATE_RUNNING;
                }
                spin_unlock_irq(&hcd_root_hub_lock);
+
+               /*
+                * Check whether any of the enabled ports on the root hub are
+                * unsuspended.  If they are then a TRSMRCY delay is needed
+                * (this is what the USB-2 spec calls a "global resume").
+                * Otherwise we can skip the delay.
+                */
+               usb_hub_for_each_child(rhdev, port1, udev) {
+                       if (udev->state != USB_STATE_NOTATTACHED &&
+                                       !udev->port_is_suspended) {
+                               usleep_range(10000, 11000);     /* TRSMRCY */
+                               break;
+                       }
+               }
        } else {
                hcd->state = old_state;
                dev_dbg(&rhdev->dev, "bus %s fail, err %d\n",
index 1af04bdeaf0c1884487ed830bcee7dd32ee720b6..90accdefdc7db657c4ad5eff12c2d248e11cf31d 100644 (file)
@@ -39,6 +39,9 @@
 #endif
 #endif
 
+#define USB_VENDOR_GENESYS_LOGIC               0x05e3
+#define HUB_QUIRK_CHECK_PORT_AUTOSUSPEND       0x01
+
 struct usb_port {
        struct usb_device *child;
        struct device dev;
@@ -86,6 +89,8 @@ struct usb_hub {
        unsigned                quiescing:1;
        unsigned                disconnected:1;
 
+       unsigned                quirk_check_port_auto_suspend:1;
+
        unsigned                has_indicators:1;
        u8                      indicator[USB_MAXCHILDREN];
        struct delayed_work     leds;
@@ -736,7 +741,6 @@ static void hub_tt_work(struct work_struct *work)
        struct usb_hub          *hub =
                container_of(work, struct usb_hub, tt.clear_work);
        unsigned long           flags;
-       int                     limit = 100;
 
        spin_lock_irqsave (&hub->tt.lock, flags);
        while (!list_empty(&hub->tt.clear_list)) {
@@ -746,9 +750,6 @@ static void hub_tt_work(struct work_struct *work)
                const struct hc_driver  *drv;
                int                     status;
 
-               if (!hub->quiescing && --limit < 0)
-                       break;
-
                next = hub->tt.clear_list.next;
                clear = list_entry (next, struct usb_tt_clear, clear_list);
                list_del (&clear->clear_list);
@@ -1612,6 +1613,41 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id)
        desc = intf->cur_altsetting;
        hdev = interface_to_usbdev(intf);
 
+       /*
+        * Set default autosuspend delay as 0 to speedup bus suspend,
+        * based on the below considerations:
+        *
+        * - Unlike other drivers, the hub driver does not rely on the
+        *   autosuspend delay to provide enough time to handle a wakeup
+        *   event, and the submitted status URB is just to check future
+        *   change on hub downstream ports, so it is safe to do it.
+        *
+        * - The patch might cause one or more auto supend/resume for
+        *   below very rare devices when they are plugged into hub
+        *   first time:
+        *
+        *      devices having trouble initializing, and disconnect
+        *      themselves from the bus and then reconnect a second
+        *      or so later
+        *
+        *      devices just for downloading firmware, and disconnects
+        *      themselves after completing it
+        *
+        *   For these quite rare devices, their drivers may change the
+        *   autosuspend delay of their parent hub in the probe() to one
+        *   appropriate value to avoid the subtle problem if someone
+        *   does care it.
+        *
+        * - The patch may cause one or more auto suspend/resume on
+        *   hub during running 'lsusb', but it is probably too
+        *   infrequent to worry about.
+        *
+        * - Change autosuspend delay of hub can avoid unnecessary auto
+        *   suspend timer for hub, also may decrease power consumption
+        *   of USB bus.
+        */
+       pm_runtime_set_autosuspend_delay(&hdev->dev, 0);
+
        /* Hubs have proper suspend/resume support. */
        usb_enable_autosuspend(hdev);
 
@@ -1670,6 +1706,9 @@ descriptor_error:
        if (hdev->speed == USB_SPEED_HIGH)
                highspeed_hubs++;
 
+       if (id->driver_info & HUB_QUIRK_CHECK_PORT_AUTOSUSPEND)
+               hub->quirk_check_port_auto_suspend = 1;
+
        if (hub_configure(hub, endpoint) >= 0)
                return 0;
 
@@ -2012,7 +2051,7 @@ static void show_string(struct usb_device *udev, char *id, char *string)
 {
        if (!string)
                return;
-       dev_printk(KERN_INFO, &udev->dev, "%s: %s\n", id, string);
+       dev_info(&udev->dev, "%s: %s\n", id, string);
 }
 
 static void announce_device(struct usb_device *udev)
@@ -2879,6 +2918,7 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
                                (PMSG_IS_AUTO(msg) ? "auto-" : ""),
                                udev->do_remote_wakeup);
                usb_set_device_state(udev, USB_STATE_SUSPENDED);
+               udev->port_is_suspended = 1;
                msleep(10);
        }
        usb_mark_last_busy(hub->hdev);
@@ -3043,6 +3083,7 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg)
 
  SuspendCleared:
        if (status == 0) {
+               udev->port_is_suspended = 0;
                if (hub_is_superspeed(hub->hdev)) {
                        if (portchange & USB_PORT_STAT_C_LINK_STATE)
                                clear_port_feature(hub->hdev, port1,
@@ -3126,6 +3167,21 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg)
 
 #endif
 
+static int check_ports_changed(struct usb_hub *hub)
+{
+       int port1;
+
+       for (port1 = 1; port1 <= hub->hdev->maxchild; ++port1) {
+               u16 portstatus, portchange;
+               int status;
+
+               status = hub_port_status(hub, port1, &portstatus, &portchange);
+               if (!status && portchange)
+                       return 1;
+       }
+       return 0;
+}
+
 static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
 {
        struct usb_hub          *hub = usb_get_intfdata (intf);
@@ -3144,6 +3200,16 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
                                return -EBUSY;
                }
        }
+
+       if (hdev->do_remote_wakeup && hub->quirk_check_port_auto_suspend) {
+               /* check if there are changes pending on hub ports */
+               if (check_ports_changed(hub)) {
+                       if (PMSG_IS_AUTO(msg))
+                               return -EBUSY;
+                       pm_wakeup_event(&hdev->dev, 2000);
+               }
+       }
+
        if (hub_is_superspeed(hdev) && hdev->do_remote_wakeup) {
                /* Enable hub to send remote wakeup for all ports. */
                for (port1 = 1; port1 <= hdev->maxchild; port1++) {
@@ -4648,6 +4714,11 @@ static int hub_thread(void *__unused)
 }
 
 static const struct usb_device_id hub_id_table[] = {
+    { .match_flags = USB_DEVICE_ID_MATCH_VENDOR
+                  | USB_DEVICE_ID_MATCH_INT_CLASS,
+      .idVendor = USB_VENDOR_GENESYS_LOGIC,
+      .bInterfaceClass = USB_CLASS_HUB,
+      .driver_info = HUB_QUIRK_CHECK_PORT_AUTOSUSPEND},
     { .match_flags = USB_DEVICE_ID_MATCH_DEV_CLASS,
       .bDeviceClass = USB_CLASS_HUB},
     { .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS,
index 1ed5afd91e6dc2ea8366927efbf0804f8fd0d7ea..a557658f3223c48400864db9e069249235a4f928 100644 (file)
@@ -1806,29 +1806,8 @@ free_interfaces:
                goto free_interfaces;
        }
 
-       ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
-                             USB_REQ_SET_CONFIGURATION, 0, configuration, 0,
-                             NULL, 0, USB_CTRL_SET_TIMEOUT);
-       if (ret < 0) {
-               /* All the old state is gone, so what else can we do?
-                * The device is probably useless now anyway.
-                */
-               cp = NULL;
-       }
-
-       dev->actconfig = cp;
-       if (!cp) {
-               usb_set_device_state(dev, USB_STATE_ADDRESS);
-               usb_hcd_alloc_bandwidth(dev, NULL, NULL, NULL);
-               /* Leave LPM disabled while the device is unconfigured. */
-               mutex_unlock(hcd->bandwidth_mutex);
-               usb_autosuspend_device(dev);
-               goto free_interfaces;
-       }
-       mutex_unlock(hcd->bandwidth_mutex);
-       usb_set_device_state(dev, USB_STATE_CONFIGURED);
-
-       /* Initialize the new interface structures and the
+       /*
+        * Initialize the new interface structures and the
         * hc/hcd/usbcore interface/endpoint state.
         */
        for (i = 0; i < nintf; ++i) {
@@ -1872,6 +1851,35 @@ free_interfaces:
        }
        kfree(new_interfaces);
 
+       ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+                             USB_REQ_SET_CONFIGURATION, 0, configuration, 0,
+                             NULL, 0, USB_CTRL_SET_TIMEOUT);
+       if (ret < 0 && cp) {
+               /*
+                * All the old state is gone, so what else can we do?
+                * The device is probably useless now anyway.
+                */
+               usb_hcd_alloc_bandwidth(dev, NULL, NULL, NULL);
+               for (i = 0; i < nintf; ++i) {
+                       usb_disable_interface(dev, cp->interface[i], true);
+                       put_device(&cp->interface[i]->dev);
+                       cp->interface[i] = NULL;
+               }
+               cp = NULL;
+       }
+
+       dev->actconfig = cp;
+       mutex_unlock(hcd->bandwidth_mutex);
+
+       if (!cp) {
+               usb_set_device_state(dev, USB_STATE_ADDRESS);
+
+               /* Leave LPM disabled while the device is unconfigured. */
+               usb_autosuspend_device(dev);
+               return ret;
+       }
+       usb_set_device_state(dev, USB_STATE_CONFIGURED);
+
        if (cp->string == NULL &&
                        !(dev->quirks & USB_QUIRK_CONFIG_INTF_STRINGS))
                cp->string = usb_cache_string(dev, cp->desc.iConfiguration);
index 9d912bfdcffe0e5a47f58c685688e0bcf31547bf..e0d9d948218c665ce09730c00730757a5c33986e 100644 (file)
@@ -214,9 +214,25 @@ EXPORT_SYMBOL_GPL(usb_unanchor_urb);
  * urb->interval is modified to reflect the actual transfer period used
  * (normally some power of two units).  And for isochronous urbs,
  * urb->start_frame is modified to reflect when the URB's transfers were
- * scheduled to start.  Not all isochronous transfer scheduling policies
- * will work, but most host controller drivers should easily handle ISO
- * queues going from now until 10-200 msec into the future.
+ * scheduled to start.
+ *
+ * Not all isochronous transfer scheduling policies will work, but most
+ * host controller drivers should easily handle ISO queues going from now
+ * until 10-200 msec into the future.  Drivers should try to keep at
+ * least one or two msec of data in the queue; many controllers require
+ * that new transfers start at least 1 msec in the future when they are
+ * added.  If the driver is unable to keep up and the queue empties out,
+ * the behavior for new submissions is governed by the URB_ISO_ASAP flag.
+ * If the flag is set, or if the queue is idle, then the URB is always
+ * assigned to the first available (and not yet expired) slot in the
+ * endpoint's schedule.  If the flag is not set and the queue is active
+ * then the URB is always assigned to the next slot in the schedule
+ * following the end of the endpoint's previous URB, even if that slot is
+ * in the past.  When a packet is assigned in this way to a slot that has
+ * already expired, the packet is not transmitted and the corresponding
+ * usb_iso_packet_descriptor's status field will return -EXDEV.  If this
+ * would happen to all the packets in the URB, submission fails with a
+ * -EXDEV error code.
  *
  * For control endpoints, the synchronous usb_control_msg() call is
  * often used (in non-interrupt context) instead of this call.
@@ -305,8 +321,13 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
        struct usb_host_endpoint        *ep;
        int                             is_out;
 
-       if (!urb || urb->hcpriv || !urb->complete)
+       if (!urb || !urb->complete)
                return -EINVAL;
+       if (urb->hcpriv) {
+               WARN_ONCE(1, "URB %p submitted while active\n", urb);
+               return -EBUSY;
+       }
+
        dev = urb->dev;
        if ((!dev) || (dev->state < USB_STATE_UNAUTHENTICATED))
                return -ENODEV;
index cd8fb44a3e164030ffe59a38a0af0baa42371051..7d3de09a82e4ae70a51173dbacbb7fe81e07fadb 100644 (file)
@@ -370,14 +370,14 @@ struct usb_device *usb_alloc_dev(struct usb_device *parent,
                                 struct usb_bus *bus, unsigned port1)
 {
        struct usb_device *dev;
-       struct usb_hcd *usb_hcd = container_of(bus, struct usb_hcd, self);
+       struct usb_hcd *usb_hcd = bus_to_hcd(bus);
        unsigned root_hub = 0;
 
        dev = kzalloc(sizeof(*dev), GFP_KERNEL);
        if (!dev)
                return NULL;
 
-       if (!usb_get_hcd(bus_to_hcd(bus))) {
+       if (!usb_get_hcd(usb_hcd)) {
                kfree(dev);
                return NULL;
        }
index d441fe4c180b9f9d15c1c34f8428a82a5f20d638..4502648b8171e1bbb9444062c648d943fd864c39 100644 (file)
@@ -27,19 +27,7 @@ endif
 ##
 
 obj-$(CONFIG_USB_DWC3)         += dwc3-omap.o
-
-##
-# REVISIT Samsung Exynos platform needs the clk API which isn't
-# defined on all architectures. If we allow dwc3-exynos.c compile
-# always we will fail the linking phase on those architectures
-# which don't provide clk api implementation and that's unnaceptable.
-#
-# When Samsung's platform start supporting pm_runtime, this check
-# for HAVE_CLK should be removed.
-##
-ifneq ($(CONFIG_HAVE_CLK),)
-       obj-$(CONFIG_USB_DWC3)          += dwc3-exynos.o
-endif
+obj-$(CONFIG_USB_DWC3)         += dwc3-exynos.o
 
 ifneq ($(CONFIG_PCI),)
        obj-$(CONFIG_USB_DWC3)          += dwc3-pci.o
index c14ebc975ba422028b663b4b90ac6e605c1c6115..e71a62a652d0f22fe082446c45fed71cd8da5e53 100644 (file)
@@ -66,45 +66,6 @@ MODULE_PARM_DESC(maximum_speed, "Maximum supported speed.");
 
 /* -------------------------------------------------------------------------- */
 
-#define DWC3_DEVS_POSSIBLE     32
-
-static DECLARE_BITMAP(dwc3_devs, DWC3_DEVS_POSSIBLE);
-
-int dwc3_get_device_id(void)
-{
-       int             id;
-
-again:
-       id = find_first_zero_bit(dwc3_devs, DWC3_DEVS_POSSIBLE);
-       if (id < DWC3_DEVS_POSSIBLE) {
-               int old;
-
-               old = test_and_set_bit(id, dwc3_devs);
-               if (old)
-                       goto again;
-       } else {
-               pr_err("dwc3: no space for new device\n");
-               id = -ENOMEM;
-       }
-
-       return id;
-}
-EXPORT_SYMBOL_GPL(dwc3_get_device_id);
-
-void dwc3_put_device_id(int id)
-{
-       int                     ret;
-
-       if (id < 0)
-               return;
-
-       ret = test_bit(id, dwc3_devs);
-       WARN(!ret, "dwc3: ID %d not in use\n", id);
-       smp_mb__before_clear_bit();
-       clear_bit(id, dwc3_devs);
-}
-EXPORT_SYMBOL_GPL(dwc3_put_device_id);
-
 void dwc3_set_mode(struct dwc3 *dwc, u32 mode)
 {
        u32 reg;
@@ -169,7 +130,6 @@ static void dwc3_free_one_event_buffer(struct dwc3 *dwc,
                struct dwc3_event_buffer *evt)
 {
        dma_free_coherent(dwc->dev, evt->length, evt->buf, evt->dma);
-       kfree(evt);
 }
 
 /**
@@ -185,7 +145,7 @@ dwc3_alloc_one_event_buffer(struct dwc3 *dwc, unsigned length)
 {
        struct dwc3_event_buffer        *evt;
 
-       evt = kzalloc(sizeof(*evt), GFP_KERNEL);
+       evt = devm_kzalloc(dwc->dev, sizeof(*evt), GFP_KERNEL);
        if (!evt)
                return ERR_PTR(-ENOMEM);
 
@@ -193,10 +153,8 @@ dwc3_alloc_one_event_buffer(struct dwc3 *dwc, unsigned length)
        evt->length     = length;
        evt->buf        = dma_alloc_coherent(dwc->dev, length,
                        &evt->dma, GFP_KERNEL);
-       if (!evt->buf) {
-               kfree(evt);
+       if (!evt->buf)
                return ERR_PTR(-ENOMEM);
-       }
 
        return evt;
 }
@@ -215,8 +173,6 @@ static void dwc3_free_event_buffers(struct dwc3 *dwc)
                if (evt)
                        dwc3_free_one_event_buffer(dwc, evt);
        }
-
-       kfree(dwc->ev_buffs);
 }
 
 /**
@@ -235,7 +191,8 @@ static int __devinit dwc3_alloc_event_buffers(struct dwc3 *dwc, unsigned length)
        num = DWC3_NUM_INT(dwc->hwparams.hwparams1);
        dwc->num_event_buffers = num;
 
-       dwc->ev_buffs = kzalloc(sizeof(*dwc->ev_buffs) * num, GFP_KERNEL);
+       dwc->ev_buffs = devm_kzalloc(dwc->dev, sizeof(*dwc->ev_buffs) * num,
+                       GFP_KERNEL);
        if (!dwc->ev_buffs) {
                dev_err(dwc->dev, "can't allocate event buffers array\n");
                return -ENOMEM;
@@ -383,24 +340,14 @@ static int __devinit dwc3_core_init(struct dwc3 *dwc)
 
        dwc3_writel(dwc->regs, DWC3_GCTL, reg);
 
-       ret = dwc3_alloc_event_buffers(dwc, DWC3_EVENT_BUFFERS_SIZE);
-       if (ret) {
-               dev_err(dwc->dev, "failed to allocate event buffers\n");
-               ret = -ENOMEM;
-               goto err1;
-       }
-
        ret = dwc3_event_buffers_setup(dwc);
        if (ret) {
                dev_err(dwc->dev, "failed to setup event buffers\n");
-               goto err1;
+               goto err0;
        }
 
        return 0;
 
-err1:
-       dwc3_free_event_buffers(dwc);
-
 err0:
        return ret;
 }
@@ -408,11 +355,9 @@ err0:
 static void dwc3_core_exit(struct dwc3 *dwc)
 {
        dwc3_event_buffers_cleanup(dwc);
-       dwc3_free_event_buffers(dwc);
 
        usb_phy_shutdown(dwc->usb2_phy);
        usb_phy_shutdown(dwc->usb3_phy);
-
 }
 
 #define DWC3_ALIGN_MASK                (16 - 1)
@@ -515,10 +460,17 @@ static int __devinit dwc3_probe(struct platform_device *pdev)
        pm_runtime_get_sync(dev);
        pm_runtime_forbid(dev);
 
+       ret = dwc3_alloc_event_buffers(dwc, DWC3_EVENT_BUFFERS_SIZE);
+       if (ret) {
+               dev_err(dwc->dev, "failed to allocate event buffers\n");
+               ret = -ENOMEM;
+               goto err0;
+       }
+
        ret = dwc3_core_init(dwc);
        if (ret) {
                dev_err(dev, "failed to initialize core\n");
-               return ret;
+               goto err0;
        }
 
        mode = DWC3_MODE(dwc->hwparams.hwparams0);
@@ -590,6 +542,9 @@ err2:
 err1:
        dwc3_core_exit(dwc);
 
+err0:
+       dwc3_free_event_buffers(dwc);
+
        return ret;
 }
 
index 243affc9343120339bf6b5c0e27e104f228e2dcd..49995634426290c116c06f4ec37ee5496d933f40 100644 (file)
@@ -868,7 +868,4 @@ void dwc3_host_exit(struct dwc3 *dwc);
 int dwc3_gadget_init(struct dwc3 *dwc);
 void dwc3_gadget_exit(struct dwc3 *dwc);
 
-extern int dwc3_get_device_id(void);
-extern void dwc3_put_device_id(int id);
-
 #endif /* __DRIVERS_USB_DWC3_CORE_H */
index ca6597853f90339358bf670e37e1cad2f65cf4cc..dc35c5476f3756c530d7f8b178788504f3947d12 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/clk.h>
 #include <linux/usb/otg.h>
 #include <linux/usb/nop-usb-xceiv.h>
+#include <linux/of.h>
 
 #include "core.h"
 
@@ -87,14 +88,14 @@ err1:
        return ret;
 }
 
+static u64 dwc3_exynos_dma_mask = DMA_BIT_MASK(32);
+
 static int __devinit dwc3_exynos_probe(struct platform_device *pdev)
 {
-       struct dwc3_exynos_data *pdata = pdev->dev.platform_data;
        struct platform_device  *dwc3;
        struct dwc3_exynos      *exynos;
        struct clk              *clk;
 
-       int                     devid;
        int                     ret = -ENOMEM;
 
        exynos = kzalloc(sizeof(*exynos), GFP_KERNEL);
@@ -103,11 +104,15 @@ static int __devinit dwc3_exynos_probe(struct platform_device *pdev)
                goto err0;
        }
 
-       platform_set_drvdata(pdev, exynos);
+       /*
+        * Right now device-tree probed devices don't get dma_mask set.
+        * Since shared usb code relies on it, set it here for now.
+        * Once we move to full device tree support this will vanish off.
+        */
+       if (!pdev->dev.dma_mask)
+               pdev->dev.dma_mask = &dwc3_exynos_dma_mask;
 
-       devid = dwc3_get_device_id();
-       if (devid < 0)
-               goto err1;
+       platform_set_drvdata(pdev, exynos);
 
        ret = dwc3_exynos_register_phys(exynos);
        if (ret) {
@@ -115,10 +120,10 @@ static int __devinit dwc3_exynos_probe(struct platform_device *pdev)
                goto err1;
        }
 
-       dwc3 = platform_device_alloc("dwc3", devid);
+       dwc3 = platform_device_alloc("dwc3", PLATFORM_DEVID_AUTO);
        if (!dwc3) {
                dev_err(&pdev->dev, "couldn't allocate dwc3 device\n");
-               goto err2;
+               goto err1;
        }
 
        clk = clk_get(&pdev->dev, "usbdrd30");
@@ -139,14 +144,6 @@ static int __devinit dwc3_exynos_probe(struct platform_device *pdev)
 
        clk_enable(exynos->clk);
 
-       /* PHY initialization */
-       if (!pdata) {
-               dev_dbg(&pdev->dev, "missing platform data\n");
-       } else {
-               if (pdata->phy_init)
-                       pdata->phy_init(pdev, pdata->phy_type);
-       }
-
        ret = platform_device_add_resources(dwc3, pdev->resource,
                        pdev->num_resources);
        if (ret) {
@@ -163,15 +160,10 @@ static int __devinit dwc3_exynos_probe(struct platform_device *pdev)
        return 0;
 
 err4:
-       if (pdata && pdata->phy_exit)
-               pdata->phy_exit(pdev, pdata->phy_type);
-
        clk_disable(clk);
        clk_put(clk);
 err3:
        platform_device_put(dwc3);
-err2:
-       dwc3_put_device_id(devid);
 err1:
        kfree(exynos);
 err0:
@@ -181,17 +173,11 @@ err0:
 static int __devexit dwc3_exynos_remove(struct platform_device *pdev)
 {
        struct dwc3_exynos      *exynos = platform_get_drvdata(pdev);
-       struct dwc3_exynos_data *pdata = pdev->dev.platform_data;
 
        platform_device_unregister(exynos->dwc3);
        platform_device_unregister(exynos->usb2_phy);
        platform_device_unregister(exynos->usb3_phy);
 
-       dwc3_put_device_id(exynos->dwc3->id);
-
-       if (pdata && pdata->phy_exit)
-               pdata->phy_exit(pdev, pdata->phy_type);
-
        clk_disable(exynos->clk);
        clk_put(exynos->clk);
 
@@ -200,11 +186,20 @@ static int __devexit dwc3_exynos_remove(struct platform_device *pdev)
        return 0;
 }
 
+#ifdef CONFIG_OF
+static const struct of_device_id exynos_dwc3_match[] = {
+       { .compatible = "samsung,exynos-dwc3" },
+       {},
+};
+MODULE_DEVICE_TABLE(of, exynos_dwc3_match);
+#endif
+
 static struct platform_driver dwc3_exynos_driver = {
        .probe          = dwc3_exynos_probe,
        .remove         = __devexit_p(dwc3_exynos_remove),
        .driver         = {
                .name   = "exynos-dwc3",
+               .of_match_table = of_match_ptr(exynos_dwc3_match),
        },
 };
 
index ee57a10d90d044373455dd6a66ac4118fd3cab5a..900d435f41d106e838f930dbed751bcf8ee596d8 100644 (file)
@@ -272,7 +272,6 @@ static int __devinit dwc3_omap_probe(struct platform_device *pdev)
        struct resource         *res;
        struct device           *dev = &pdev->dev;
 
-       int                     devid;
        int                     size;
        int                     ret = -ENOMEM;
        int                     irq;
@@ -315,14 +314,10 @@ static int __devinit dwc3_omap_probe(struct platform_device *pdev)
                return ret;
        }
 
-       devid = dwc3_get_device_id();
-       if (devid < 0)
-               return -ENODEV;
-
-       dwc3 = platform_device_alloc("dwc3", devid);
+       dwc3 = platform_device_alloc("dwc3", PLATFORM_DEVID_AUTO);
        if (!dwc3) {
                dev_err(dev, "couldn't allocate dwc3 device\n");
-               goto err1;
+               return -ENOMEM;
        }
 
        context = devm_kzalloc(dev, resource_size(res), GFP_KERNEL);
@@ -423,10 +418,6 @@ static int __devinit dwc3_omap_probe(struct platform_device *pdev)
 
 err2:
        platform_device_put(dwc3);
-
-err1:
-       dwc3_put_device_id(devid);
-
        return ret;
 }
 
@@ -437,9 +428,6 @@ static int __devexit dwc3_omap_remove(struct platform_device *pdev)
        platform_device_unregister(omap->dwc3);
        platform_device_unregister(omap->usb2_phy);
        platform_device_unregister(omap->usb3_phy);
-
-       dwc3_put_device_id(omap->dwc3->id);
-
        return 0;
 }
 
index 94f550e37f986950f35c28e1e53d8773b4156031..13962597f3fe2a78fa9611af3143ff43bef2276c 100644 (file)
@@ -119,7 +119,6 @@ static int __devinit dwc3_pci_probe(struct pci_dev *pci,
        struct platform_device  *dwc3;
        struct dwc3_pci         *glue;
        int                     ret = -ENOMEM;
-       int                     devid;
        struct device           *dev = &pci->dev;
 
        glue = devm_kzalloc(dev, sizeof(*glue), GFP_KERNEL);
@@ -145,13 +144,7 @@ static int __devinit dwc3_pci_probe(struct pci_dev *pci,
                return ret;
        }
 
-       devid = dwc3_get_device_id();
-       if (devid < 0) {
-               ret = -ENOMEM;
-               goto err1;
-       }
-
-       dwc3 = platform_device_alloc("dwc3", devid);
+       dwc3 = platform_device_alloc("dwc3", PLATFORM_DEVID_AUTO);
        if (!dwc3) {
                dev_err(dev, "couldn't allocate dwc3 device\n");
                ret = -ENOMEM;
@@ -172,7 +165,7 @@ static int __devinit dwc3_pci_probe(struct pci_dev *pci,
        ret = platform_device_add_resources(dwc3, res, ARRAY_SIZE(res));
        if (ret) {
                dev_err(dev, "couldn't add resources to dwc3 device\n");
-               goto err2;
+               goto err1;
        }
 
        pci_set_drvdata(pci, glue);
@@ -195,10 +188,6 @@ static int __devinit dwc3_pci_probe(struct pci_dev *pci,
 err3:
        pci_set_drvdata(pci, NULL);
        platform_device_put(dwc3);
-
-err2:
-       dwc3_put_device_id(devid);
-
 err1:
        pci_disable_device(pci);
 
@@ -211,7 +200,6 @@ static void __devexit dwc3_pci_remove(struct pci_dev *pci)
 
        platform_device_unregister(glue->usb2_phy);
        platform_device_unregister(glue->usb3_phy);
-       dwc3_put_device_id(glue->dwc3->id);
        platform_device_unregister(glue->dwc3);
        pci_set_drvdata(pci, NULL);
        pci_disable_device(pci);
index e426ad626d7498bf5e6537ac100c7a508979066a..5e29ddeb4d33d0c65f29116dca2ddbe42ea5407f 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/usb/ehci_def.h>
 #include <linux/delay.h>
 #include <linux/serial_core.h>
+#include <linux/kconfig.h>
 #include <linux/kgdb.h>
 #include <linux/kthread.h>
 #include <asm/io.h>
@@ -614,12 +615,6 @@ err:
        return -ENODEV;
 }
 
-int dbgp_external_startup(struct usb_hcd *hcd)
-{
-       return xen_dbgp_external_startup(hcd) ?: _dbgp_external_startup();
-}
-EXPORT_SYMBOL_GPL(dbgp_external_startup);
-
 static int ehci_reset_port(int port)
 {
        u32 portsc;
@@ -979,6 +974,7 @@ struct console early_dbgp_console = {
        .index =        -1,
 };
 
+#if IS_ENABLED(CONFIG_USB)
 int dbgp_reset_prep(struct usb_hcd *hcd)
 {
        int ret = xen_dbgp_reset_prep(hcd);
@@ -1007,6 +1003,13 @@ int dbgp_reset_prep(struct usb_hcd *hcd)
 }
 EXPORT_SYMBOL_GPL(dbgp_reset_prep);
 
+int dbgp_external_startup(struct usb_hcd *hcd)
+{
+       return xen_dbgp_external_startup(hcd) ?: _dbgp_external_startup();
+}
+EXPORT_SYMBOL_GPL(dbgp_external_startup);
+#endif /* USB */
+
 #ifdef CONFIG_KGDB
 
 static char kgdbdbgp_buf[DBGP_MAX_PACKET];
index e0ff51b895296ab66988e509bd6b73d94a663701..14625fd2cecda40bb6922158c4b522866d062171 100644 (file)
@@ -721,31 +721,6 @@ config USB_FUNCTIONFS_GENERIC
          Include a configuration with the Function Filesystem alone with
          no Ethernet interface.
 
-config USB_FILE_STORAGE
-       tristate "File-backed Storage Gadget (DEPRECATED)"
-       depends on BLOCK
-       help
-         The File-backed 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.
-
-         Say "y" to link the driver statically, or "m" to build a
-         dynamically linked module called "g_file_storage".
-
-         NOTE: This driver is deprecated.  Its replacement is the
-         Mass Storage Gadget.
-
-config USB_FILE_STORAGE_TEST
-       bool "File-backed Storage Gadget testing version"
-       depends on USB_FILE_STORAGE
-       default n
-       help
-         Say "y" to generate the larger testing version of the
-         File-backed Storage Gadget, useful for probing the
-         behavior of USB Mass Storage hosts.  Not needed for
-         normal operation.
-
 config USB_MASS_STORAGE
        tristate "Mass Storage Gadget"
        depends on BLOCK
@@ -756,8 +731,8 @@ config USB_MASS_STORAGE
          device (in much the same way as the "loop" device driver),
          specified as a module parameter or sysfs option.
 
-         This driver is an updated replacement for the deprecated
-         File-backed Storage Gadget (g_file_storage).
+         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".
index 307be5fa824cf98e3d71001863a74a5fd03139f8..8b4acfd92aa31fa4b1d392f0b9f4051b20c57ac9 100644 (file)
@@ -44,7 +44,6 @@ g_ether-y                     := ether.o
 g_serial-y                     := serial.o
 g_midi-y                       := gmidi.o
 gadgetfs-y                     := inode.o
-g_file_storage-y               := file_storage.o
 g_mass_storage-y               := mass_storage.o
 g_printer-y                    := printer.o
 g_cdc-y                                := cdc2.o
@@ -62,7 +61,6 @@ 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_FILE_STORAGE) += g_file_storage.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
index 957f973dd96ad6f069a8eddf084d448c7a34ff0f..2a6bfe759c2971435a3fbb10203e5e3f0a3ee3c1 100644 (file)
@@ -107,7 +107,7 @@ int config_ep_by_speed(struct usb_gadget *g,
                }
                /* else: fall through */
        default:
-               speed_desc = f->descriptors;
+               speed_desc = f->fs_descriptors;
        }
        /* find descriptors */
        for_each_ep_desc(speed_desc, d_spd) {
@@ -200,7 +200,7 @@ int usb_add_function(struct usb_configuration *config,
         * as full speed ... it's the function drivers that will need
         * to avoid bulk and ISO transfers.
         */
-       if (!config->fullspeed && function->descriptors)
+       if (!config->fullspeed && function->fs_descriptors)
                config->fullspeed = true;
        if (!config->highspeed && function->hs_descriptors)
                config->highspeed = true;
@@ -363,7 +363,7 @@ static int config_buf(struct usb_configuration *config,
                        descriptors = f->hs_descriptors;
                        break;
                default:
-                       descriptors = f->descriptors;
+                       descriptors = f->fs_descriptors;
                }
 
                if (!descriptors)
@@ -620,7 +620,7 @@ static int set_config(struct usb_composite_dev *cdev,
                        descriptors = f->hs_descriptors;
                        break;
                default:
-                       descriptors = f->descriptors;
+                       descriptors = f->fs_descriptors;
                }
 
                for (; *descriptors; ++descriptors) {
index e3a98929d3463d50ad395be7bf7fe08c92dfc983..34e12fc52c23d45fa2148212938242bb05b777f3 100644 (file)
@@ -19,7 +19,7 @@
 
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
-
+#include <linux/usb/composite.h>
 
 /**
  * usb_descriptor_fillbuf - fill buffer with descriptors
@@ -158,3 +158,40 @@ usb_copy_descriptors(struct usb_descriptor_header **src)
        return ret;
 }
 EXPORT_SYMBOL_GPL(usb_copy_descriptors);
+
+int usb_assign_descriptors(struct usb_function *f,
+               struct usb_descriptor_header **fs,
+               struct usb_descriptor_header **hs,
+               struct usb_descriptor_header **ss)
+{
+       struct usb_gadget *g = f->config->cdev->gadget;
+
+       if (fs) {
+               f->fs_descriptors = usb_copy_descriptors(fs);
+               if (!f->fs_descriptors)
+                       goto err;
+       }
+       if (hs && gadget_is_dualspeed(g)) {
+               f->hs_descriptors = usb_copy_descriptors(hs);
+               if (!f->hs_descriptors)
+                       goto err;
+       }
+       if (ss && gadget_is_superspeed(g)) {
+               f->ss_descriptors = usb_copy_descriptors(ss);
+               if (!f->ss_descriptors)
+                       goto err;
+       }
+       return 0;
+err:
+       usb_free_all_descriptors(f);
+       return -ENOMEM;
+}
+EXPORT_SYMBOL_GPL(usb_assign_descriptors);
+
+void usb_free_all_descriptors(struct usb_function *f)
+{
+       usb_free_descriptors(f->fs_descriptors);
+       usb_free_descriptors(f->hs_descriptors);
+       usb_free_descriptors(f->ss_descriptors);
+}
+EXPORT_SYMBOL_GPL(usb_free_all_descriptors);
index 0f7541be28f36aaa2ff402aaf2fce40040cc119a..95d584dbed13b08516f23d90d83acb973d989a3a 100644 (file)
@@ -63,16 +63,20 @@ MODULE_LICENSE("GPL");
 struct dummy_hcd_module_parameters {
        bool is_super_speed;
        bool is_high_speed;
+       unsigned int num;
 };
 
 static struct dummy_hcd_module_parameters mod_data = {
        .is_super_speed = false,
        .is_high_speed = true,
+       .num = 1,
 };
 module_param_named(is_super_speed, mod_data.is_super_speed, bool, S_IRUGO);
 MODULE_PARM_DESC(is_super_speed, "true to simulate SuperSpeed connection");
 module_param_named(is_high_speed, mod_data.is_high_speed, bool, S_IRUGO);
 MODULE_PARM_DESC(is_high_speed, "true to simulate HighSpeed connection");
+module_param_named(num, mod_data.num, uint, S_IRUGO);
+MODULE_PARM_DESC(num, "number of emulated controllers");
 /*-------------------------------------------------------------------------*/
 
 /* gadget side driver data structres */
@@ -238,8 +242,6 @@ static inline struct dummy *gadget_dev_to_dummy(struct device *dev)
        return container_of(dev, struct dummy, gadget.dev);
 }
 
-static struct dummy                    the_controller;
-
 /*-------------------------------------------------------------------------*/
 
 /* SLAVE/GADGET SIDE UTILITY ROUTINES */
@@ -973,9 +975,10 @@ static void init_dummy_udc_hw(struct dummy *dum)
 
 static int dummy_udc_probe(struct platform_device *pdev)
 {
-       struct dummy    *dum = &the_controller;
+       struct dummy    *dum;
        int             rc;
 
+       dum = *((void **)dev_get_platdata(&pdev->dev));
        dum->gadget.name = gadget_name;
        dum->gadget.ops = &dummy_ops;
        dum->gadget.max_speed = USB_SPEED_SUPER;
@@ -2398,10 +2401,13 @@ static int dummy_h_get_frame(struct usb_hcd *hcd)
 
 static int dummy_setup(struct usb_hcd *hcd)
 {
+       struct dummy *dum;
+
+       dum = *((void **)dev_get_platdata(hcd->self.controller));
        hcd->self.sg_tablesize = ~0;
        if (usb_hcd_is_primary_hcd(hcd)) {
-               the_controller.hs_hcd = hcd_to_dummy_hcd(hcd);
-               the_controller.hs_hcd->dum = &the_controller;
+               dum->hs_hcd = hcd_to_dummy_hcd(hcd);
+               dum->hs_hcd->dum = dum;
                /*
                 * Mark the first roothub as being USB 2.0.
                 * The USB 3.0 roothub will be registered later by
@@ -2410,8 +2416,8 @@ static int dummy_setup(struct usb_hcd *hcd)
                hcd->speed = HCD_USB2;
                hcd->self.root_hub->speed = USB_SPEED_HIGH;
        } else {
-               the_controller.ss_hcd = hcd_to_dummy_hcd(hcd);
-               the_controller.ss_hcd->dum = &the_controller;
+               dum->ss_hcd = hcd_to_dummy_hcd(hcd);
+               dum->ss_hcd->dum = dum;
                hcd->speed = HCD_USB3;
                hcd->self.root_hub->speed = USB_SPEED_SUPER;
        }
@@ -2524,11 +2530,13 @@ static struct hc_driver dummy_hcd = {
 
 static int dummy_hcd_probe(struct platform_device *pdev)
 {
+       struct dummy            *dum;
        struct usb_hcd          *hs_hcd;
        struct usb_hcd          *ss_hcd;
        int                     retval;
 
        dev_info(&pdev->dev, "%s, driver " DRIVER_VERSION "\n", driver_desc);
+       dum = *((void **)dev_get_platdata(&pdev->dev));
 
        if (!mod_data.is_super_speed)
                dummy_hcd.flags = HCD_USB2;
@@ -2561,7 +2569,7 @@ dealloc_usb2_hcd:
        usb_remove_hcd(hs_hcd);
 put_usb2_hcd:
        usb_put_hcd(hs_hcd);
-       the_controller.hs_hcd = the_controller.ss_hcd = NULL;
+       dum->hs_hcd = dum->ss_hcd = NULL;
        return retval;
 }
 
@@ -2579,8 +2587,8 @@ static int dummy_hcd_remove(struct platform_device *pdev)
        usb_remove_hcd(dummy_hcd_to_hcd(dum->hs_hcd));
        usb_put_hcd(dummy_hcd_to_hcd(dum->hs_hcd));
 
-       the_controller.hs_hcd = NULL;
-       the_controller.ss_hcd = NULL;
+       dum->hs_hcd = NULL;
+       dum->ss_hcd = NULL;
 
        return 0;
 }
@@ -2627,13 +2635,15 @@ static struct platform_driver dummy_hcd_driver = {
 };
 
 /*-------------------------------------------------------------------------*/
-
-static struct platform_device *the_udc_pdev;
-static struct platform_device *the_hcd_pdev;
+#define MAX_NUM_UDC    2
+static struct platform_device *the_udc_pdev[MAX_NUM_UDC];
+static struct platform_device *the_hcd_pdev[MAX_NUM_UDC];
 
 static int __init init(void)
 {
        int     retval = -ENOMEM;
+       int     i;
+       struct  dummy *dum[MAX_NUM_UDC];
 
        if (usb_disabled())
                return -ENODEV;
@@ -2641,65 +2651,129 @@ static int __init init(void)
        if (!mod_data.is_high_speed && mod_data.is_super_speed)
                return -EINVAL;
 
-       the_hcd_pdev = platform_device_alloc(driver_name, -1);
-       if (!the_hcd_pdev)
-               return retval;
-       the_udc_pdev = platform_device_alloc(gadget_name, -1);
-       if (!the_udc_pdev)
-               goto err_alloc_udc;
+       if (mod_data.num < 1 || mod_data.num > MAX_NUM_UDC) {
+               pr_err("Number of emulated UDC must be in range of 1…%d\n",
+                               MAX_NUM_UDC);
+               return -EINVAL;
+       }
+
+       for (i = 0; i < mod_data.num; i++) {
+               the_hcd_pdev[i] = platform_device_alloc(driver_name, i);
+               if (!the_hcd_pdev[i]) {
+                       i--;
+                       while (i >= 0)
+                               platform_device_put(the_hcd_pdev[i--]);
+                       return retval;
+               }
+       }
+       for (i = 0; i < mod_data.num; i++) {
+               the_udc_pdev[i] = platform_device_alloc(gadget_name, i);
+               if (!the_udc_pdev[i]) {
+                       i--;
+                       while (i >= 0)
+                               platform_device_put(the_udc_pdev[i--]);
+                       goto err_alloc_udc;
+               }
+       }
+       for (i = 0; i < mod_data.num; i++) {
+               dum[i] = kzalloc(sizeof(struct dummy), GFP_KERNEL);
+               if (!dum[i])
+                       goto err_add_pdata;
+               retval = platform_device_add_data(the_hcd_pdev[i], &dum[i],
+                               sizeof(void *));
+               if (retval)
+                       goto err_add_pdata;
+               retval = platform_device_add_data(the_udc_pdev[i], &dum[i],
+                               sizeof(void *));
+               if (retval)
+                       goto err_add_pdata;
+       }
 
        retval = platform_driver_register(&dummy_hcd_driver);
        if (retval < 0)
-               goto err_register_hcd_driver;
+               goto err_add_pdata;
        retval = platform_driver_register(&dummy_udc_driver);
        if (retval < 0)
                goto err_register_udc_driver;
 
-       retval = platform_device_add(the_hcd_pdev);
-       if (retval < 0)
-               goto err_add_hcd;
-       if (!the_controller.hs_hcd ||
-           (!the_controller.ss_hcd && mod_data.is_super_speed)) {
-               /*
-                * The hcd was added successfully but its probe function failed
-                * for some reason.
-                */
-               retval = -EINVAL;
-               goto err_add_udc;
+       for (i = 0; i < mod_data.num; i++) {
+               retval = platform_device_add(the_hcd_pdev[i]);
+               if (retval < 0) {
+                       i--;
+                       while (i >= 0)
+                               platform_device_del(the_hcd_pdev[i--]);
+                       goto err_add_hcd;
+               }
        }
-       retval = platform_device_add(the_udc_pdev);
-       if (retval < 0)
-               goto err_add_udc;
-       if (!platform_get_drvdata(the_udc_pdev)) {
-               /*
-                * The udc was added successfully but its probe function failed
-                * for some reason.
-                */
-               retval = -EINVAL;
-               goto err_probe_udc;
+       for (i = 0; i < mod_data.num; i++) {
+               if (!dum[i]->hs_hcd ||
+                               (!dum[i]->ss_hcd && mod_data.is_super_speed)) {
+                       /*
+                        * The hcd was added successfully but its probe
+                        * function failed for some reason.
+                        */
+                       retval = -EINVAL;
+                       goto err_add_udc;
+               }
+       }
+
+       for (i = 0; i < mod_data.num; i++) {
+               retval = platform_device_add(the_udc_pdev[i]);
+               if (retval < 0) {
+                       i--;
+                       while (i >= 0)
+                               platform_device_del(the_udc_pdev[i]);
+                       goto err_add_udc;
+               }
+       }
+
+       for (i = 0; i < mod_data.num; i++) {
+               if (!platform_get_drvdata(the_udc_pdev[i])) {
+                       /*
+                        * The udc was added successfully but its probe
+                        * function failed for some reason.
+                        */
+                       retval = -EINVAL;
+                       goto err_probe_udc;
+               }
        }
        return retval;
 
 err_probe_udc:
-       platform_device_del(the_udc_pdev);
+       for (i = 0; i < mod_data.num; i++)
+               platform_device_del(the_udc_pdev[i]);
 err_add_udc:
-       platform_device_del(the_hcd_pdev);
+       for (i = 0; i < mod_data.num; i++)
+               platform_device_del(the_hcd_pdev[i]);
 err_add_hcd:
        platform_driver_unregister(&dummy_udc_driver);
 err_register_udc_driver:
        platform_driver_unregister(&dummy_hcd_driver);
-err_register_hcd_driver:
-       platform_device_put(the_udc_pdev);
+err_add_pdata:
+       for (i = 0; i < mod_data.num; i++)
+               kfree(dum[i]);
+       for (i = 0; i < mod_data.num; i++)
+               platform_device_put(the_udc_pdev[i]);
 err_alloc_udc:
-       platform_device_put(the_hcd_pdev);
+       for (i = 0; i < mod_data.num; i++)
+               platform_device_put(the_hcd_pdev[i]);
        return retval;
 }
 module_init(init);
 
 static void __exit cleanup(void)
 {
-       platform_device_unregister(the_udc_pdev);
-       platform_device_unregister(the_hcd_pdev);
+       int i;
+
+       for (i = 0; i < mod_data.num; i++) {
+               struct dummy *dum;
+
+               dum = *((void **)dev_get_platdata(&the_udc_pdev[i]->dev));
+
+               platform_device_unregister(the_udc_pdev[i]);
+               platform_device_unregister(the_hcd_pdev[i]);
+               kfree(dum);
+       }
        platform_driver_unregister(&dummy_udc_driver);
        platform_driver_unregister(&dummy_hcd_driver);
 }
index d672250a61fa60253e4507c16e7ec199038dae81..549174466c2160d40003ee5787a0b9e7adaa6fca 100644 (file)
@@ -87,7 +87,7 @@ static inline struct f_acm *port_to_acm(struct gserial *p)
 
 /* notification endpoint uses smallish and infrequent fixed-size messages */
 
-#define GS_LOG2_NOTIFY_INTERVAL                5       /* 1 << 5 == 32 msec */
+#define GS_NOTIFY_INTERVAL_MS          32
 #define GS_NOTIFY_MAXPACKET            10      /* notification + 2 bytes */
 
 /* interface and class descriptors: */
@@ -167,7 +167,7 @@ static struct usb_endpoint_descriptor acm_fs_notify_desc = {
        .bEndpointAddress =     USB_DIR_IN,
        .bmAttributes =         USB_ENDPOINT_XFER_INT,
        .wMaxPacketSize =       cpu_to_le16(GS_NOTIFY_MAXPACKET),
-       .bInterval =            1 << GS_LOG2_NOTIFY_INTERVAL,
+       .bInterval =            GS_NOTIFY_INTERVAL_MS,
 };
 
 static struct usb_endpoint_descriptor acm_fs_in_desc = {
@@ -199,14 +199,13 @@ static struct usb_descriptor_header *acm_fs_function[] = {
 };
 
 /* high speed support: */
-
 static struct usb_endpoint_descriptor acm_hs_notify_desc = {
        .bLength =              USB_DT_ENDPOINT_SIZE,
        .bDescriptorType =      USB_DT_ENDPOINT,
        .bEndpointAddress =     USB_DIR_IN,
        .bmAttributes =         USB_ENDPOINT_XFER_INT,
        .wMaxPacketSize =       cpu_to_le16(GS_NOTIFY_MAXPACKET),
-       .bInterval =            GS_LOG2_NOTIFY_INTERVAL+4,
+       .bInterval =            USB_MS_TO_HS_INTERVAL(GS_NOTIFY_INTERVAL_MS),
 };
 
 static struct usb_endpoint_descriptor acm_hs_in_desc = {
@@ -659,37 +658,22 @@ acm_bind(struct usb_configuration *c, struct usb_function *f)
        acm->notify_req->complete = acm_cdc_notify_complete;
        acm->notify_req->context = acm;
 
-       /* copy descriptors */
-       f->descriptors = usb_copy_descriptors(acm_fs_function);
-       if (!f->descriptors)
-               goto fail;
-
        /* support all relevant hardware speeds... we expect that when
         * hardware is dual speed, all bulk-capable endpoints work at
         * both speeds
         */
-       if (gadget_is_dualspeed(c->cdev->gadget)) {
-               acm_hs_in_desc.bEndpointAddress =
-                               acm_fs_in_desc.bEndpointAddress;
-               acm_hs_out_desc.bEndpointAddress =
-                               acm_fs_out_desc.bEndpointAddress;
-               acm_hs_notify_desc.bEndpointAddress =
-                               acm_fs_notify_desc.bEndpointAddress;
-
-               /* copy descriptors */
-               f->hs_descriptors = usb_copy_descriptors(acm_hs_function);
-       }
-       if (gadget_is_superspeed(c->cdev->gadget)) {
-               acm_ss_in_desc.bEndpointAddress =
-                       acm_fs_in_desc.bEndpointAddress;
-               acm_ss_out_desc.bEndpointAddress =
-                       acm_fs_out_desc.bEndpointAddress;
-
-               /* copy descriptors, and track endpoint copies */
-               f->ss_descriptors = usb_copy_descriptors(acm_ss_function);
-               if (!f->ss_descriptors)
-                       goto fail;
-       }
+       acm_hs_in_desc.bEndpointAddress = acm_fs_in_desc.bEndpointAddress;
+       acm_hs_out_desc.bEndpointAddress = acm_fs_out_desc.bEndpointAddress;
+       acm_hs_notify_desc.bEndpointAddress =
+               acm_fs_notify_desc.bEndpointAddress;
+
+       acm_ss_in_desc.bEndpointAddress = acm_fs_in_desc.bEndpointAddress;
+       acm_ss_out_desc.bEndpointAddress = acm_fs_out_desc.bEndpointAddress;
+
+       status = usb_assign_descriptors(f, acm_fs_function, acm_hs_function,
+                       acm_ss_function);
+       if (status)
+               goto fail;
 
        DBG(cdev, "acm ttyGS%d: %s speed IN/%s OUT/%s NOTIFY/%s\n",
                        acm->port_num,
@@ -721,11 +705,8 @@ acm_unbind(struct usb_configuration *c, struct usb_function *f)
 {
        struct f_acm            *acm = func_to_acm(f);
 
-       if (gadget_is_dualspeed(c->cdev->gadget))
-               usb_free_descriptors(f->hs_descriptors);
-       if (gadget_is_superspeed(c->cdev->gadget))
-               usb_free_descriptors(f->ss_descriptors);
-       usb_free_descriptors(f->descriptors);
+       acm_string_defs[0].id = 0;
+       usb_free_all_descriptors(f);
        gs_free_req(acm->notify, acm->notify_req);
        kfree(acm);
 }
@@ -762,27 +743,15 @@ int acm_bind_config(struct usb_configuration *c, u8 port_num)
         */
 
        /* maybe allocate device-global string IDs, and patch descriptors */
-       if (acm_string_defs[ACM_CTRL_IDX].id == 0) {
-               status = usb_string_id(c->cdev);
+       if (acm_string_defs[0].id == 0) {
+               status = usb_string_ids_tab(c->cdev, acm_string_defs);
                if (status < 0)
                        return status;
-               acm_string_defs[ACM_CTRL_IDX].id = status;
-
-               acm_control_interface_desc.iInterface = status;
-
-               status = usb_string_id(c->cdev);
-               if (status < 0)
-                       return status;
-               acm_string_defs[ACM_DATA_IDX].id = status;
-
-               acm_data_interface_desc.iInterface = status;
-
-               status = usb_string_id(c->cdev);
-               if (status < 0)
-                       return status;
-               acm_string_defs[ACM_IAD_IDX].id = status;
-
-               acm_iad_descriptor.iFunction = status;
+               acm_control_interface_desc.iInterface =
+                       acm_string_defs[ACM_CTRL_IDX].id;
+               acm_data_interface_desc.iInterface =
+                       acm_string_defs[ACM_DATA_IDX].id;
+               acm_iad_descriptor.iFunction = acm_string_defs[ACM_IAD_IDX].id;
        }
 
        /* allocate and initialize one new instance */
index 95bc94f8e57066a743428571707540d71775e751..83420a310fb71784db5b269bf39e7939ef9af1b3 100644 (file)
@@ -91,7 +91,7 @@ static inline unsigned ecm_bitrate(struct usb_gadget *g)
  * encapsulated commands (vendor-specific, using control-OUT).
  */
 
-#define LOG2_STATUS_INTERVAL_MSEC      5       /* 1 << 5 == 32 msec */
+#define ECM_STATUS_INTERVAL_MS         32
 #define ECM_STATUS_BYTECOUNT           16      /* 8 byte header + data */
 
 
@@ -192,7 +192,7 @@ static struct usb_endpoint_descriptor fs_ecm_notify_desc = {
        .bEndpointAddress =     USB_DIR_IN,
        .bmAttributes =         USB_ENDPOINT_XFER_INT,
        .wMaxPacketSize =       cpu_to_le16(ECM_STATUS_BYTECOUNT),
-       .bInterval =            1 << LOG2_STATUS_INTERVAL_MSEC,
+       .bInterval =            ECM_STATUS_INTERVAL_MS,
 };
 
 static struct usb_endpoint_descriptor fs_ecm_in_desc = {
@@ -239,7 +239,7 @@ static struct usb_endpoint_descriptor hs_ecm_notify_desc = {
        .bEndpointAddress =     USB_DIR_IN,
        .bmAttributes =         USB_ENDPOINT_XFER_INT,
        .wMaxPacketSize =       cpu_to_le16(ECM_STATUS_BYTECOUNT),
-       .bInterval =            LOG2_STATUS_INTERVAL_MSEC + 4,
+       .bInterval =            USB_MS_TO_HS_INTERVAL(ECM_STATUS_INTERVAL_MS),
 };
 
 static struct usb_endpoint_descriptor hs_ecm_in_desc = {
@@ -288,7 +288,7 @@ static struct usb_endpoint_descriptor ss_ecm_notify_desc = {
        .bEndpointAddress =     USB_DIR_IN,
        .bmAttributes =         USB_ENDPOINT_XFER_INT,
        .wMaxPacketSize =       cpu_to_le16(ECM_STATUS_BYTECOUNT),
-       .bInterval =            LOG2_STATUS_INTERVAL_MSEC + 4,
+       .bInterval =            USB_MS_TO_HS_INTERVAL(ECM_STATUS_INTERVAL_MS),
 };
 
 static struct usb_ss_ep_comp_descriptor ss_ecm_intr_comp_desc = {
@@ -330,6 +330,7 @@ static struct usb_ss_ep_comp_descriptor ss_ecm_bulk_comp_desc = {
 
 static struct usb_descriptor_header *ecm_ss_function[] = {
        /* CDC ECM control descriptors */
+       (struct usb_descriptor_header *) &ecm_iad_descriptor,
        (struct usb_descriptor_header *) &ecm_control_intf,
        (struct usb_descriptor_header *) &ecm_header_desc,
        (struct usb_descriptor_header *) &ecm_union_desc,
@@ -353,7 +354,7 @@ static struct usb_descriptor_header *ecm_ss_function[] = {
 
 static struct usb_string ecm_string_defs[] = {
        [0].s = "CDC Ethernet Control Model (ECM)",
-       [1].s = NULL /* DYNAMIC */,
+       [1].s = "",
        [2].s = "CDC Ethernet Data",
        [3].s = "CDC ECM",
        {  } /* end of list */
@@ -742,42 +743,24 @@ ecm_bind(struct usb_configuration *c, struct usb_function *f)
        ecm->notify_req->context = ecm;
        ecm->notify_req->complete = ecm_notify_complete;
 
-       /* copy descriptors, and track endpoint copies */
-       f->descriptors = usb_copy_descriptors(ecm_fs_function);
-       if (!f->descriptors)
-               goto fail;
-
        /* support all relevant hardware speeds... we expect that when
         * hardware is dual speed, all bulk-capable endpoints work at
         * both speeds
         */
-       if (gadget_is_dualspeed(c->cdev->gadget)) {
-               hs_ecm_in_desc.bEndpointAddress =
-                               fs_ecm_in_desc.bEndpointAddress;
-               hs_ecm_out_desc.bEndpointAddress =
-                               fs_ecm_out_desc.bEndpointAddress;
-               hs_ecm_notify_desc.bEndpointAddress =
-                               fs_ecm_notify_desc.bEndpointAddress;
-
-               /* copy descriptors, and track endpoint copies */
-               f->hs_descriptors = usb_copy_descriptors(ecm_hs_function);
-               if (!f->hs_descriptors)
-                       goto fail;
-       }
-
-       if (gadget_is_superspeed(c->cdev->gadget)) {
-               ss_ecm_in_desc.bEndpointAddress =
-                               fs_ecm_in_desc.bEndpointAddress;
-               ss_ecm_out_desc.bEndpointAddress =
-                               fs_ecm_out_desc.bEndpointAddress;
-               ss_ecm_notify_desc.bEndpointAddress =
-                               fs_ecm_notify_desc.bEndpointAddress;
-
-               /* copy descriptors, and track endpoint copies */
-               f->ss_descriptors = usb_copy_descriptors(ecm_ss_function);
-               if (!f->ss_descriptors)
-                       goto fail;
-       }
+       hs_ecm_in_desc.bEndpointAddress = fs_ecm_in_desc.bEndpointAddress;
+       hs_ecm_out_desc.bEndpointAddress = fs_ecm_out_desc.bEndpointAddress;
+       hs_ecm_notify_desc.bEndpointAddress =
+               fs_ecm_notify_desc.bEndpointAddress;
+
+       ss_ecm_in_desc.bEndpointAddress = fs_ecm_in_desc.bEndpointAddress;
+       ss_ecm_out_desc.bEndpointAddress = fs_ecm_out_desc.bEndpointAddress;
+       ss_ecm_notify_desc.bEndpointAddress =
+               fs_ecm_notify_desc.bEndpointAddress;
+
+       status = usb_assign_descriptors(f, ecm_fs_function, ecm_hs_function,
+                       ecm_ss_function);
+       if (status)
+               goto fail;
 
        /* NOTE:  all that is done without knowing or caring about
         * the network link ... which is unavailable to this code
@@ -795,11 +778,6 @@ ecm_bind(struct usb_configuration *c, struct usb_function *f)
        return 0;
 
 fail:
-       if (f->descriptors)
-               usb_free_descriptors(f->descriptors);
-       if (f->hs_descriptors)
-               usb_free_descriptors(f->hs_descriptors);
-
        if (ecm->notify_req) {
                kfree(ecm->notify_req->buf);
                usb_ep_free_request(ecm->notify, ecm->notify_req);
@@ -808,9 +786,9 @@ fail:
        /* we might as well release our claims on endpoints */
        if (ecm->notify)
                ecm->notify->driver_data = NULL;
-       if (ecm->port.out_ep->desc)
+       if (ecm->port.out_ep)
                ecm->port.out_ep->driver_data = NULL;
-       if (ecm->port.in_ep->desc)
+       if (ecm->port.in_ep)
                ecm->port.in_ep->driver_data = NULL;
 
        ERROR(cdev, "%s: can't bind, err %d\n", f->name, status);
@@ -825,16 +803,11 @@ ecm_unbind(struct usb_configuration *c, struct usb_function *f)
 
        DBG(c->cdev, "ecm unbind\n");
 
-       if (gadget_is_superspeed(c->cdev->gadget))
-               usb_free_descriptors(f->ss_descriptors);
-       if (gadget_is_dualspeed(c->cdev->gadget))
-               usb_free_descriptors(f->hs_descriptors);
-       usb_free_descriptors(f->descriptors);
+       ecm_string_defs[0].id = 0;
+       usb_free_all_descriptors(f);
 
        kfree(ecm->notify_req->buf);
        usb_ep_free_request(ecm->notify, ecm->notify_req);
-
-       ecm_string_defs[1].s = NULL;
        kfree(ecm);
 }
 
@@ -859,36 +832,15 @@ ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
        if (!can_support_ecm(c->cdev->gadget) || !ethaddr)
                return -EINVAL;
 
-       /* maybe allocate device-global string IDs */
        if (ecm_string_defs[0].id == 0) {
-
-               /* control interface label */
-               status = usb_string_id(c->cdev);
-               if (status < 0)
-                       return status;
-               ecm_string_defs[0].id = status;
-               ecm_control_intf.iInterface = status;
-
-               /* data interface label */
-               status = usb_string_id(c->cdev);
-               if (status < 0)
+               status = usb_string_ids_tab(c->cdev, ecm_string_defs);
+               if (status)
                        return status;
-               ecm_string_defs[2].id = status;
-               ecm_data_intf.iInterface = status;
 
-               /* MAC address */
-               status = usb_string_id(c->cdev);
-               if (status < 0)
-                       return status;
-               ecm_string_defs[1].id = status;
-               ecm_desc.iMACAddress = status;
-
-               /* IAD label */
-               status = usb_string_id(c->cdev);
-               if (status < 0)
-                       return status;
-               ecm_string_defs[3].id = status;
-               ecm_iad_descriptor.iFunction = status;
+               ecm_control_intf.iInterface = ecm_string_defs[0].id;
+               ecm_data_intf.iInterface = ecm_string_defs[2].id;
+               ecm_desc.iMACAddress = ecm_string_defs[1].id;
+               ecm_iad_descriptor.iFunction = ecm_string_defs[3].id;
        }
 
        /* allocate and initialize one new instance */
@@ -913,9 +865,7 @@ ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
        ecm->port.func.disable = ecm_disable;
 
        status = usb_add_function(c, &ecm->port.func);
-       if (status) {
-               ecm_string_defs[1].s = NULL;
+       if (status)
                kfree(ecm);
-       }
        return status;
 }
index 1a7b2dd7d408d1427a8d60b01d15f29ebc8282fd..cf0ebee855636c9412b76f17d484c3f1b86bd3e8 100644 (file)
@@ -274,38 +274,20 @@ eem_bind(struct usb_configuration *c, struct usb_function *f)
 
        status = -ENOMEM;
 
-       /* copy descriptors, and track endpoint copies */
-       f->descriptors = usb_copy_descriptors(eem_fs_function);
-       if (!f->descriptors)
-               goto fail;
-
        /* support all relevant hardware speeds... we expect that when
         * hardware is dual speed, all bulk-capable endpoints work at
         * both speeds
         */
-       if (gadget_is_dualspeed(c->cdev->gadget)) {
-               eem_hs_in_desc.bEndpointAddress =
-                               eem_fs_in_desc.bEndpointAddress;
-               eem_hs_out_desc.bEndpointAddress =
-                               eem_fs_out_desc.bEndpointAddress;
-
-               /* copy descriptors, and track endpoint copies */
-               f->hs_descriptors = usb_copy_descriptors(eem_hs_function);
-               if (!f->hs_descriptors)
-                       goto fail;
-       }
+       eem_hs_in_desc.bEndpointAddress = eem_fs_in_desc.bEndpointAddress;
+       eem_hs_out_desc.bEndpointAddress = eem_fs_out_desc.bEndpointAddress;
 
-       if (gadget_is_superspeed(c->cdev->gadget)) {
-               eem_ss_in_desc.bEndpointAddress =
-                               eem_fs_in_desc.bEndpointAddress;
-               eem_ss_out_desc.bEndpointAddress =
-                               eem_fs_out_desc.bEndpointAddress;
+       eem_ss_in_desc.bEndpointAddress = eem_fs_in_desc.bEndpointAddress;
+       eem_ss_out_desc.bEndpointAddress = eem_fs_out_desc.bEndpointAddress;
 
-               /* copy descriptors, and track endpoint copies */
-               f->ss_descriptors = usb_copy_descriptors(eem_ss_function);
-               if (!f->ss_descriptors)
-                       goto fail;
-       }
+       status = usb_assign_descriptors(f, eem_fs_function, eem_hs_function,
+                       eem_ss_function);
+       if (status)
+               goto fail;
 
        DBG(cdev, "CDC Ethernet (EEM): %s speed IN/%s OUT/%s\n",
                        gadget_is_superspeed(c->cdev->gadget) ? "super" :
@@ -314,15 +296,10 @@ eem_bind(struct usb_configuration *c, struct usb_function *f)
        return 0;
 
 fail:
-       if (f->descriptors)
-               usb_free_descriptors(f->descriptors);
-       if (f->hs_descriptors)
-               usb_free_descriptors(f->hs_descriptors);
-
-       /* we might as well release our claims on endpoints */
-       if (eem->port.out_ep->desc)
+       usb_free_all_descriptors(f);
+       if (eem->port.out_ep)
                eem->port.out_ep->driver_data = NULL;
-       if (eem->port.in_ep->desc)
+       if (eem->port.in_ep)
                eem->port.in_ep->driver_data = NULL;
 
        ERROR(cdev, "%s: can't bind, err %d\n", f->name, status);
@@ -337,11 +314,7 @@ eem_unbind(struct usb_configuration *c, struct usb_function *f)
 
        DBG(c->cdev, "eem unbind\n");
 
-       if (gadget_is_superspeed(c->cdev->gadget))
-               usb_free_descriptors(f->ss_descriptors);
-       if (gadget_is_dualspeed(c->cdev->gadget))
-               usb_free_descriptors(f->hs_descriptors);
-       usb_free_descriptors(f->descriptors);
+       usb_free_all_descriptors(f);
        kfree(eem);
 }
 
index 64c4ec10d1fcbe9db29220c5e79e33c9116de17c..4a6961c517f261103f006259bab366265dde7e4c 100644 (file)
@@ -2097,7 +2097,7 @@ static int __ffs_func_bind_do_descs(enum ffs_entity_type type, u8 *valuep,
        if (isHS)
                func->function.hs_descriptors[(long)valuep] = desc;
        else
-               func->function.descriptors[(long)valuep]    = desc;
+               func->function.fs_descriptors[(long)valuep]    = desc;
 
        if (!desc || desc->bDescriptorType != USB_DT_ENDPOINT)
                return 0;
@@ -2249,7 +2249,7 @@ static int ffs_func_bind(struct usb_configuration *c,
         * numbers without worrying that it may be described later on.
         */
        if (likely(full)) {
-               func->function.descriptors = data->fs_descs;
+               func->function.fs_descriptors = data->fs_descs;
                ret = ffs_do_descs(ffs->fs_descs_count,
                                   data->raw_descs,
                                   sizeof data->raw_descs,
index 511e527178e23d0e3cb3787700b5f7cc4f3baa32..6e69a8e8d22a7c7468994fd40eab738bddb52d1c 100644 (file)
@@ -573,7 +573,6 @@ static int __init hidg_bind(struct usb_configuration *c, struct usb_function *f)
                goto fail;
        hidg_interface_desc.bInterfaceNumber = status;
 
-
        /* allocate instance-specific endpoints */
        status = -ENODEV;
        ep = usb_ep_autoconfig(c->cdev->gadget, &hidg_fs_in_ep_desc);
@@ -609,20 +608,15 @@ static int __init hidg_bind(struct usb_configuration *c, struct usb_function *f)
        hidg_desc.desc[0].wDescriptorLength =
                cpu_to_le16(hidg->report_desc_length);
 
-       /* copy descriptors */
-       f->descriptors = usb_copy_descriptors(hidg_fs_descriptors);
-       if (!f->descriptors)
-               goto fail;
+       hidg_hs_in_ep_desc.bEndpointAddress =
+               hidg_fs_in_ep_desc.bEndpointAddress;
+       hidg_hs_out_ep_desc.bEndpointAddress =
+               hidg_fs_out_ep_desc.bEndpointAddress;
 
-       if (gadget_is_dualspeed(c->cdev->gadget)) {
-               hidg_hs_in_ep_desc.bEndpointAddress =
-                       hidg_fs_in_ep_desc.bEndpointAddress;
-               hidg_hs_out_ep_desc.bEndpointAddress =
-                       hidg_fs_out_ep_desc.bEndpointAddress;
-               f->hs_descriptors = usb_copy_descriptors(hidg_hs_descriptors);
-               if (!f->hs_descriptors)
-                       goto fail;
-       }
+       status = usb_assign_descriptors(f, hidg_fs_descriptors,
+                       hidg_hs_descriptors, NULL);
+       if (status)
+               goto fail;
 
        mutex_init(&hidg->lock);
        spin_lock_init(&hidg->spinlock);
@@ -649,9 +643,7 @@ fail:
                        usb_ep_free_request(hidg->in_ep, hidg->req);
        }
 
-       usb_free_descriptors(f->hs_descriptors);
-       usb_free_descriptors(f->descriptors);
-
+       usb_free_all_descriptors(f);
        return status;
 }
 
@@ -668,9 +660,7 @@ static void hidg_unbind(struct usb_configuration *c, struct usb_function *f)
        kfree(hidg->req->buf);
        usb_ep_free_request(hidg->in_ep, hidg->req);
 
-       /* free descriptors copies */
-       usb_free_descriptors(f->hs_descriptors);
-       usb_free_descriptors(f->descriptors);
+       usb_free_all_descriptors(f);
 
        kfree(hidg->report_desc);
        kfree(hidg);
index 7275706caeb0534301354976c177e2123de908a9..bb39cb2bb3a3f9f1ece4879f8e3a4e48c110ba0a 100644 (file)
@@ -177,6 +177,7 @@ loopback_bind(struct usb_configuration *c, struct usb_function *f)
        struct usb_composite_dev *cdev = c->cdev;
        struct f_loopback       *loop = func_to_loop(f);
        int                     id;
+       int ret;
 
        /* allocate interface ID(s) */
        id = usb_interface_id(c, f);
@@ -201,22 +202,19 @@ autoconf_fail:
        loop->out_ep->driver_data = cdev;       /* claim */
 
        /* support high speed hardware */
-       if (gadget_is_dualspeed(c->cdev->gadget)) {
-               hs_loop_source_desc.bEndpointAddress =
-                               fs_loop_source_desc.bEndpointAddress;
-               hs_loop_sink_desc.bEndpointAddress =
-                               fs_loop_sink_desc.bEndpointAddress;
-               f->hs_descriptors = hs_loopback_descs;
-       }
+       hs_loop_source_desc.bEndpointAddress =
+               fs_loop_source_desc.bEndpointAddress;
+       hs_loop_sink_desc.bEndpointAddress = fs_loop_sink_desc.bEndpointAddress;
 
        /* support super speed hardware */
-       if (gadget_is_superspeed(c->cdev->gadget)) {
-               ss_loop_source_desc.bEndpointAddress =
-                               fs_loop_source_desc.bEndpointAddress;
-               ss_loop_sink_desc.bEndpointAddress =
-                               fs_loop_sink_desc.bEndpointAddress;
-               f->ss_descriptors = ss_loopback_descs;
-       }
+       ss_loop_source_desc.bEndpointAddress =
+               fs_loop_source_desc.bEndpointAddress;
+       ss_loop_sink_desc.bEndpointAddress = fs_loop_sink_desc.bEndpointAddress;
+
+       ret = usb_assign_descriptors(f, fs_loopback_descs, hs_loopback_descs,
+                       ss_loopback_descs);
+       if (ret)
+               return ret;
 
        DBG(cdev, "%s speed %s: IN/%s, OUT/%s\n",
            (gadget_is_superspeed(c->cdev->gadget) ? "super" :
@@ -228,6 +226,7 @@ autoconf_fail:
 static void
 loopback_unbind(struct usb_configuration *c, struct usb_function *f)
 {
+       usb_free_all_descriptors(f);
        kfree(func_to_loop(f));
 }
 
@@ -379,7 +378,6 @@ static int __init loopback_bind_config(struct usb_configuration *c)
                return -ENOMEM;
 
        loop->function.name = "loopback";
-       loop->function.descriptors = fs_loopback_descs;
        loop->function.bind = loopback_bind;
        loop->function.unbind = loopback_unbind;
        loop->function.set_alt = loopback_set_alt;
index 3a7668bde3ef44bfc752f98ef1ebce7da531e885..5d027b3e1ef059e1e67af8d1499cb0a2f80a5f19 100644 (file)
 
 static const char fsg_string_interface[] = "Mass Storage";
 
-#define FSG_NO_DEVICE_STRINGS    1
-#define FSG_NO_OTG               1
-#define FSG_NO_INTR_EP           1
-
 #include "storage_common.c"
 
 
@@ -2904,9 +2900,7 @@ static void fsg_unbind(struct usb_configuration *c, struct usb_function *f)
        }
 
        fsg_common_put(common);
-       usb_free_descriptors(fsg->function.descriptors);
-       usb_free_descriptors(fsg->function.hs_descriptors);
-       usb_free_descriptors(fsg->function.ss_descriptors);
+       usb_free_all_descriptors(&fsg->function);
        kfree(fsg);
 }
 
@@ -2916,6 +2910,8 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f)
        struct usb_gadget       *gadget = c->cdev->gadget;
        int                     i;
        struct usb_ep           *ep;
+       unsigned                max_burst;
+       int                     ret;
 
        fsg->gadget = gadget;
 
@@ -2939,45 +2935,27 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f)
        ep->driver_data = fsg->common;  /* claim the endpoint */
        fsg->bulk_out = ep;
 
-       /* Copy descriptors */
-       f->descriptors = usb_copy_descriptors(fsg_fs_function);
-       if (unlikely(!f->descriptors))
-               return -ENOMEM;
-
-       if (gadget_is_dualspeed(gadget)) {
-               /* Assume endpoint addresses are the same for both speeds */
-               fsg_hs_bulk_in_desc.bEndpointAddress =
-                       fsg_fs_bulk_in_desc.bEndpointAddress;
-               fsg_hs_bulk_out_desc.bEndpointAddress =
-                       fsg_fs_bulk_out_desc.bEndpointAddress;
-               f->hs_descriptors = usb_copy_descriptors(fsg_hs_function);
-               if (unlikely(!f->hs_descriptors)) {
-                       usb_free_descriptors(f->descriptors);
-                       return -ENOMEM;
-               }
-       }
-
-       if (gadget_is_superspeed(gadget)) {
-               unsigned        max_burst;
+       /* Assume endpoint addresses are the same for both speeds */
+       fsg_hs_bulk_in_desc.bEndpointAddress =
+               fsg_fs_bulk_in_desc.bEndpointAddress;
+       fsg_hs_bulk_out_desc.bEndpointAddress =
+               fsg_fs_bulk_out_desc.bEndpointAddress;
 
-               /* Calculate bMaxBurst, we know packet size is 1024 */
-               max_burst = min_t(unsigned, FSG_BUFLEN / 1024, 15);
+       /* Calculate bMaxBurst, we know packet size is 1024 */
+       max_burst = min_t(unsigned, FSG_BUFLEN / 1024, 15);
 
-               fsg_ss_bulk_in_desc.bEndpointAddress =
-                       fsg_fs_bulk_in_desc.bEndpointAddress;
-               fsg_ss_bulk_in_comp_desc.bMaxBurst = max_burst;
+       fsg_ss_bulk_in_desc.bEndpointAddress =
+               fsg_fs_bulk_in_desc.bEndpointAddress;
+       fsg_ss_bulk_in_comp_desc.bMaxBurst = max_burst;
 
-               fsg_ss_bulk_out_desc.bEndpointAddress =
-                       fsg_fs_bulk_out_desc.bEndpointAddress;
-               fsg_ss_bulk_out_comp_desc.bMaxBurst = max_burst;
+       fsg_ss_bulk_out_desc.bEndpointAddress =
+               fsg_fs_bulk_out_desc.bEndpointAddress;
+       fsg_ss_bulk_out_comp_desc.bMaxBurst = max_burst;
 
-               f->ss_descriptors = usb_copy_descriptors(fsg_ss_function);
-               if (unlikely(!f->ss_descriptors)) {
-                       usb_free_descriptors(f->hs_descriptors);
-                       usb_free_descriptors(f->descriptors);
-                       return -ENOMEM;
-               }
-       }
+       ret = usb_assign_descriptors(f, fsg_fs_function, fsg_hs_function,
+                       fsg_ss_function);
+       if (ret)
+               goto autoconf_fail;
 
        return 0;
 
@@ -2986,7 +2964,6 @@ autoconf_fail:
        return -ENOTSUPP;
 }
 
-
 /****************************** ADD FUNCTION ******************************/
 
 static struct usb_gadget_strings *fsg_strings_array[] = {
index 8ed1259fe80d0f91bff200abf9d7b6c11966af5a..263e721c2694cdcdc9968d0a7c8f1c5957e16e75 100644 (file)
@@ -414,7 +414,7 @@ static void f_midi_unbind(struct usb_configuration *c, struct usb_function *f)
        kfree(midi->id);
        midi->id = NULL;
 
-       usb_free_descriptors(f->descriptors);
+       usb_free_all_descriptors(f);
        kfree(midi);
 }
 
@@ -881,19 +881,25 @@ f_midi_bind(struct usb_configuration *c, struct usb_function *f)
         * both speeds
         */
        /* copy descriptors, and track endpoint copies */
+       f->fs_descriptors = usb_copy_descriptors(midi_function);
+       if (!f->fs_descriptors)
+               goto fail_f_midi;
+
        if (gadget_is_dualspeed(c->cdev->gadget)) {
-               c->highspeed = true;
                bulk_in_desc.wMaxPacketSize = cpu_to_le16(512);
                bulk_out_desc.wMaxPacketSize = cpu_to_le16(512);
                f->hs_descriptors = usb_copy_descriptors(midi_function);
-       } else {
-               f->descriptors = usb_copy_descriptors(midi_function);
+               if (!f->hs_descriptors)
+                       goto fail_f_midi;
        }
 
        kfree(midi_function);
 
        return 0;
 
+fail_f_midi:
+       kfree(midi_function);
+       usb_free_descriptors(f->hs_descriptors);
 fail:
        /* we might as well release our claims on endpoints */
        if (midi->out_ep)
index b651b529c67f070dcd4a545cea8cfc40010602f3..6c8362f937bea2b40e22876219685005553e5a15 100644 (file)
@@ -102,7 +102,7 @@ static inline unsigned ncm_bitrate(struct usb_gadget *g)
                                 USB_CDC_NCM_NTB32_SUPPORTED)
 
 static struct usb_cdc_ncm_ntb_parameters ntb_parameters = {
-       .wLength = sizeof ntb_parameters,
+       .wLength = cpu_to_le16(sizeof(ntb_parameters)),
        .bmNtbFormatsSupported = cpu_to_le16(FORMATS_SUPPORTED),
        .dwNtbInMaxSize = cpu_to_le32(NTB_DEFAULT_IN_SIZE),
        .wNdpInDivisor = cpu_to_le16(4),
@@ -121,7 +121,7 @@ static struct usb_cdc_ncm_ntb_parameters ntb_parameters = {
  * waste less bandwidth.
  */
 
-#define LOG2_STATUS_INTERVAL_MSEC      5       /* 1 << 5 == 32 msec */
+#define NCM_STATUS_INTERVAL_MS         32
 #define NCM_STATUS_BYTECOUNT           16      /* 8 byte header + data */
 
 static struct usb_interface_assoc_descriptor ncm_iad_desc __initdata = {
@@ -230,7 +230,7 @@ static struct usb_endpoint_descriptor fs_ncm_notify_desc __initdata = {
        .bEndpointAddress =     USB_DIR_IN,
        .bmAttributes =         USB_ENDPOINT_XFER_INT,
        .wMaxPacketSize =       cpu_to_le16(NCM_STATUS_BYTECOUNT),
-       .bInterval =            1 << LOG2_STATUS_INTERVAL_MSEC,
+       .bInterval =            NCM_STATUS_INTERVAL_MS,
 };
 
 static struct usb_endpoint_descriptor fs_ncm_in_desc __initdata = {
@@ -275,7 +275,7 @@ static struct usb_endpoint_descriptor hs_ncm_notify_desc __initdata = {
        .bEndpointAddress =     USB_DIR_IN,
        .bmAttributes =         USB_ENDPOINT_XFER_INT,
        .wMaxPacketSize =       cpu_to_le16(NCM_STATUS_BYTECOUNT),
-       .bInterval =            LOG2_STATUS_INTERVAL_MSEC + 4,
+       .bInterval =            USB_MS_TO_HS_INTERVAL(NCM_STATUS_INTERVAL_MS),
 };
 static struct usb_endpoint_descriptor hs_ncm_in_desc __initdata = {
        .bLength =              USB_DT_ENDPOINT_SIZE,
@@ -321,7 +321,7 @@ static struct usb_descriptor_header *ncm_hs_function[] __initdata = {
 
 static struct usb_string ncm_string_defs[] = {
        [STRING_CTRL_IDX].s = "CDC Network Control Model (NCM)",
-       [STRING_MAC_IDX].s = NULL /* DYNAMIC */,
+       [STRING_MAC_IDX].s = "",
        [STRING_DATA_IDX].s = "CDC Network Data",
        [STRING_IAD_IDX].s = "CDC NCM",
        {  } /* end of list */
@@ -869,15 +869,19 @@ static struct sk_buff *ncm_wrap_ntb(struct gether *port,
        struct sk_buff  *skb2;
        int             ncb_len = 0;
        __le16          *tmp;
-       int             div = ntb_parameters.wNdpInDivisor;
-       int             rem = ntb_parameters.wNdpInPayloadRemainder;
+       int             div;
+       int             rem;
        int             pad;
-       int             ndp_align = ntb_parameters.wNdpInAlignment;
+       int             ndp_align;
        int             ndp_pad;
        unsigned        max_size = ncm->port.fixed_in_len;
        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);
+
        ncb_len += opts->nth_size;
        ndp_pad = ALIGN(ncb_len, ndp_align) - ncb_len;
        ncb_len += ndp_pad;
@@ -1208,30 +1212,18 @@ ncm_bind(struct usb_configuration *c, struct usb_function *f)
        ncm->notify_req->context = ncm;
        ncm->notify_req->complete = ncm_notify_complete;
 
-       /* copy descriptors, and track endpoint copies */
-       f->descriptors = usb_copy_descriptors(ncm_fs_function);
-       if (!f->descriptors)
-               goto fail;
-
        /*
         * support all relevant hardware speeds... we expect that when
         * hardware is dual speed, all bulk-capable endpoints work at
         * both speeds
         */
-       if (gadget_is_dualspeed(c->cdev->gadget)) {
-               hs_ncm_in_desc.bEndpointAddress =
-                               fs_ncm_in_desc.bEndpointAddress;
-               hs_ncm_out_desc.bEndpointAddress =
-                               fs_ncm_out_desc.bEndpointAddress;
-               hs_ncm_notify_desc.bEndpointAddress =
-                               fs_ncm_notify_desc.bEndpointAddress;
-
-               /* copy descriptors, and track endpoint copies */
-               f->hs_descriptors = usb_copy_descriptors(ncm_hs_function);
-               if (!f->hs_descriptors)
-                       goto fail;
-       }
+       hs_ncm_in_desc.bEndpointAddress = fs_ncm_in_desc.bEndpointAddress;
+       hs_ncm_out_desc.bEndpointAddress = fs_ncm_out_desc.bEndpointAddress;
+       hs_ncm_notify_desc.bEndpointAddress =
+               fs_ncm_notify_desc.bEndpointAddress;
 
+       status = usb_assign_descriptors(f, ncm_fs_function, ncm_hs_function,
+                       NULL);
        /*
         * NOTE:  all that is done without knowing or caring about
         * the network link ... which is unavailable to this code
@@ -1248,9 +1240,7 @@ ncm_bind(struct usb_configuration *c, struct usb_function *f)
        return 0;
 
 fail:
-       if (f->descriptors)
-               usb_free_descriptors(f->descriptors);
-
+       usb_free_all_descriptors(f);
        if (ncm->notify_req) {
                kfree(ncm->notify_req->buf);
                usb_ep_free_request(ncm->notify, ncm->notify_req);
@@ -1259,9 +1249,9 @@ fail:
        /* we might as well release our claims on endpoints */
        if (ncm->notify)
                ncm->notify->driver_data = NULL;
-       if (ncm->port.out_ep->desc)
+       if (ncm->port.out_ep)
                ncm->port.out_ep->driver_data = NULL;
-       if (ncm->port.in_ep->desc)
+       if (ncm->port.in_ep)
                ncm->port.in_ep->driver_data = NULL;
 
        ERROR(cdev, "%s: can't bind, err %d\n", f->name, status);
@@ -1276,14 +1266,12 @@ ncm_unbind(struct usb_configuration *c, struct usb_function *f)
 
        DBG(c->cdev, "ncm unbind\n");
 
-       if (gadget_is_dualspeed(c->cdev->gadget))
-               usb_free_descriptors(f->hs_descriptors);
-       usb_free_descriptors(f->descriptors);
+       ncm_string_defs[0].id = 0;
+       usb_free_all_descriptors(f);
 
        kfree(ncm->notify_req->buf);
        usb_ep_free_request(ncm->notify, ncm->notify_req);
 
-       ncm_string_defs[1].s = NULL;
        kfree(ncm);
 }
 
@@ -1307,37 +1295,19 @@ int __init ncm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
        if (!can_support_ecm(c->cdev->gadget) || !ethaddr)
                return -EINVAL;
 
-       /* maybe allocate device-global string IDs */
        if (ncm_string_defs[0].id == 0) {
-
-               /* control interface label */
-               status = usb_string_id(c->cdev);
+               status = usb_string_ids_tab(c->cdev, ncm_string_defs);
                if (status < 0)
                        return status;
-               ncm_string_defs[STRING_CTRL_IDX].id = status;
-               ncm_control_intf.iInterface = status;
+               ncm_control_intf.iInterface =
+                       ncm_string_defs[STRING_CTRL_IDX].id;
 
-               /* data interface label */
-               status = usb_string_id(c->cdev);
-               if (status < 0)
-                       return status;
-               ncm_string_defs[STRING_DATA_IDX].id = status;
+               status = ncm_string_defs[STRING_DATA_IDX].id;
                ncm_data_nop_intf.iInterface = status;
                ncm_data_intf.iInterface = status;
 
-               /* MAC address */
-               status = usb_string_id(c->cdev);
-               if (status < 0)
-                       return status;
-               ncm_string_defs[STRING_MAC_IDX].id = status;
-               ecm_desc.iMACAddress = status;
-
-               /* IAD */
-               status = usb_string_id(c->cdev);
-               if (status < 0)
-                       return status;
-               ncm_string_defs[STRING_IAD_IDX].id = status;
-               ncm_iad_desc.iFunction = status;
+               ecm_desc.iMACAddress = ncm_string_defs[STRING_MAC_IDX].id;
+               ncm_iad_desc.iFunction = ncm_string_defs[STRING_IAD_IDX].id;
        }
 
        /* allocate and initialize one new instance */
@@ -1347,7 +1317,7 @@ int __init ncm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
 
        /* export host's Ethernet address in CDC format */
        snprintf(ncm->ethaddr, sizeof ncm->ethaddr, "%pm", ethaddr);
-       ncm_string_defs[1].s = ncm->ethaddr;
+       ncm_string_defs[STRING_MAC_IDX].s = ncm->ethaddr;
 
        spin_lock_init(&ncm->lock);
        ncm_reset_values(ncm);
@@ -1367,9 +1337,7 @@ int __init ncm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
        ncm->port.unwrap = ncm_unwrap_ntb;
 
        status = usb_add_function(c, &ncm->port.func);
-       if (status) {
-               ncm_string_defs[1].s = NULL;
+       if (status)
                kfree(ncm);
-       }
        return status;
 }
index 5f400f66aa9b5dfa3c4844639d62ad23ad11608b..d8dd8782768cd6a878750e094bb88f19c222181c 100644 (file)
@@ -331,23 +331,19 @@ obex_bind(struct usb_configuration *c, struct usb_function *f)
        obex->port.out = ep;
        ep->driver_data = cdev; /* claim */
 
-       /* copy descriptors, and track endpoint copies */
-       f->descriptors = usb_copy_descriptors(fs_function);
-
        /* support all relevant hardware speeds... we expect that when
         * hardware is dual speed, all bulk-capable endpoints work at
         * both speeds
         */
-       if (gadget_is_dualspeed(c->cdev->gadget)) {
 
-               obex_hs_ep_in_desc.bEndpointAddress =
-                               obex_fs_ep_in_desc.bEndpointAddress;
-               obex_hs_ep_out_desc.bEndpointAddress =
-                               obex_fs_ep_out_desc.bEndpointAddress;
+       obex_hs_ep_in_desc.bEndpointAddress =
+               obex_fs_ep_in_desc.bEndpointAddress;
+       obex_hs_ep_out_desc.bEndpointAddress =
+               obex_fs_ep_out_desc.bEndpointAddress;
 
-               /* copy descriptors, and track endpoint copies */
-               f->hs_descriptors = usb_copy_descriptors(hs_function);
-       }
+       status = usb_assign_descriptors(f, fs_function, hs_function, NULL);
+       if (status)
+               goto fail;
 
        /* Avoid letting this gadget enumerate until the userspace
         * OBEX server is active.
@@ -368,6 +364,7 @@ obex_bind(struct usb_configuration *c, struct usb_function *f)
        return 0;
 
 fail:
+       usb_free_all_descriptors(f);
        /* we might as well release our claims on endpoints */
        if (obex->port.out)
                obex->port.out->driver_data = NULL;
@@ -382,9 +379,8 @@ fail:
 static void
 obex_unbind(struct usb_configuration *c, struct usb_function *f)
 {
-       if (gadget_is_dualspeed(c->cdev->gadget))
-               usb_free_descriptors(f->hs_descriptors);
-       usb_free_descriptors(f->descriptors);
+       obex_string_defs[OBEX_CTRL_IDX].id = 0;
+       usb_free_all_descriptors(f);
        kfree(func_to_obex(f));
 }
 
@@ -423,22 +419,16 @@ int __init obex_bind_config(struct usb_configuration *c, u8 port_num)
        if (!can_support_obex(c))
                return -EINVAL;
 
-       /* maybe allocate device-global string IDs, and patch descriptors */
        if (obex_string_defs[OBEX_CTRL_IDX].id == 0) {
-               status = usb_string_id(c->cdev);
-               if (status < 0)
-                       return status;
-               obex_string_defs[OBEX_CTRL_IDX].id = status;
-
-               obex_control_intf.iInterface = status;
-
-               status = usb_string_id(c->cdev);
+               status = usb_string_ids_tab(c->cdev, obex_string_defs);
                if (status < 0)
                        return status;
-               obex_string_defs[OBEX_DATA_IDX].id = status;
+               obex_control_intf.iInterface =
+                       obex_string_defs[OBEX_CTRL_IDX].id;
 
-               obex_data_nop_intf.iInterface =
-                       obex_data_intf.iInterface = status;
+               status = obex_string_defs[OBEX_DATA_IDX].id;
+               obex_data_nop_intf.iInterface = status;
+               obex_data_intf.iInterface = status;
        }
 
        /* allocate and initialize one new instance */
index 8ee9268fe253f2dc01de4f84f451ef3a1870a69a..b21ab558b6c01ada7fbca98bf63ec2949090a17d 100644 (file)
@@ -515,14 +515,14 @@ int pn_bind(struct usb_configuration *c, struct usb_function *f)
        fp->in_ep = ep;
        ep->driver_data = fp; /* Claim */
 
-       pn_hs_sink_desc.bEndpointAddress =
-               pn_fs_sink_desc.bEndpointAddress;
-       pn_hs_source_desc.bEndpointAddress =
-               pn_fs_source_desc.bEndpointAddress;
+       pn_hs_sink_desc.bEndpointAddress = pn_fs_sink_desc.bEndpointAddress;
+       pn_hs_source_desc.bEndpointAddress = pn_fs_source_desc.bEndpointAddress;
 
        /* Do not try to bind Phonet twice... */
-       fp->function.descriptors = fs_pn_function;
-       fp->function.hs_descriptors = hs_pn_function;
+       status = usb_assign_descriptors(f, fs_pn_function, hs_pn_function,
+                       NULL);
+       if (status)
+               goto err;
 
        /* Incoming USB requests */
        status = -ENOMEM;
@@ -531,7 +531,7 @@ int pn_bind(struct usb_configuration *c, struct usb_function *f)
 
                req = usb_ep_alloc_request(fp->out_ep, GFP_KERNEL);
                if (!req)
-                       goto err;
+                       goto err_req;
 
                req->complete = pn_rx_complete;
                fp->out_reqv[i] = req;
@@ -540,14 +540,18 @@ int pn_bind(struct usb_configuration *c, struct usb_function *f)
        /* Outgoing USB requests */
        fp->in_req = usb_ep_alloc_request(fp->in_ep, GFP_KERNEL);
        if (!fp->in_req)
-               goto err;
+               goto err_req;
 
        INFO(cdev, "USB CDC Phonet function\n");
        INFO(cdev, "using %s, OUT %s, IN %s\n", cdev->gadget->name,
                fp->out_ep->name, fp->in_ep->name);
        return 0;
 
+err_req:
+       for (i = 0; i < phonet_rxq_size && fp->out_reqv[i]; i++)
+               usb_ep_free_request(fp->out_ep, fp->out_reqv[i]);
 err:
+       usb_free_all_descriptors(f);
        if (fp->out_ep)
                fp->out_ep->driver_data = NULL;
        if (fp->in_ep)
@@ -569,6 +573,7 @@ pn_unbind(struct usb_configuration *c, struct usb_function *f)
                if (fp->out_reqv[i])
                        usb_ep_free_request(fp->out_ep, fp->out_reqv[i]);
 
+       usb_free_all_descriptors(f);
        kfree(fp);
 }
 
index b1681e45aca76749c65f99a53c943a993cff4ccf..71beeb83355874b601998a5764abddc076515138 100644 (file)
@@ -101,7 +101,7 @@ static unsigned int bitrate(struct usb_gadget *g)
 /*
  */
 
-#define LOG2_STATUS_INTERVAL_MSEC      5       /* 1 << 5 == 32 msec */
+#define RNDIS_STATUS_INTERVAL_MS       32
 #define STATUS_BYTECOUNT               8       /* 8 bytes data */
 
 
@@ -190,7 +190,7 @@ static struct usb_endpoint_descriptor fs_notify_desc = {
        .bEndpointAddress =     USB_DIR_IN,
        .bmAttributes =         USB_ENDPOINT_XFER_INT,
        .wMaxPacketSize =       cpu_to_le16(STATUS_BYTECOUNT),
-       .bInterval =            1 << LOG2_STATUS_INTERVAL_MSEC,
+       .bInterval =            RNDIS_STATUS_INTERVAL_MS,
 };
 
 static struct usb_endpoint_descriptor fs_in_desc = {
@@ -236,7 +236,7 @@ static struct usb_endpoint_descriptor hs_notify_desc = {
        .bEndpointAddress =     USB_DIR_IN,
        .bmAttributes =         USB_ENDPOINT_XFER_INT,
        .wMaxPacketSize =       cpu_to_le16(STATUS_BYTECOUNT),
-       .bInterval =            LOG2_STATUS_INTERVAL_MSEC + 4,
+       .bInterval =            USB_MS_TO_HS_INTERVAL(RNDIS_STATUS_INTERVAL_MS)
 };
 
 static struct usb_endpoint_descriptor hs_in_desc = {
@@ -284,7 +284,7 @@ static struct usb_endpoint_descriptor ss_notify_desc = {
        .bEndpointAddress =     USB_DIR_IN,
        .bmAttributes =         USB_ENDPOINT_XFER_INT,
        .wMaxPacketSize =       cpu_to_le16(STATUS_BYTECOUNT),
-       .bInterval =            LOG2_STATUS_INTERVAL_MSEC + 4,
+       .bInterval =            USB_MS_TO_HS_INTERVAL(RNDIS_STATUS_INTERVAL_MS)
 };
 
 static struct usb_ss_ep_comp_descriptor ss_intr_comp_desc = {
@@ -722,42 +722,22 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f)
        rndis->notify_req->context = rndis;
        rndis->notify_req->complete = rndis_response_complete;
 
-       /* copy descriptors, and track endpoint copies */
-       f->descriptors = usb_copy_descriptors(eth_fs_function);
-       if (!f->descriptors)
-               goto fail;
-
        /* support all relevant hardware speeds... we expect that when
         * hardware is dual speed, all bulk-capable endpoints work at
         * both speeds
         */
-       if (gadget_is_dualspeed(c->cdev->gadget)) {
-               hs_in_desc.bEndpointAddress =
-                               fs_in_desc.bEndpointAddress;
-               hs_out_desc.bEndpointAddress =
-                               fs_out_desc.bEndpointAddress;
-               hs_notify_desc.bEndpointAddress =
-                               fs_notify_desc.bEndpointAddress;
-
-               /* copy descriptors, and track endpoint copies */
-               f->hs_descriptors = usb_copy_descriptors(eth_hs_function);
-               if (!f->hs_descriptors)
-                       goto fail;
-       }
+       hs_in_desc.bEndpointAddress = fs_in_desc.bEndpointAddress;
+       hs_out_desc.bEndpointAddress = fs_out_desc.bEndpointAddress;
+       hs_notify_desc.bEndpointAddress = fs_notify_desc.bEndpointAddress;
 
-       if (gadget_is_superspeed(c->cdev->gadget)) {
-               ss_in_desc.bEndpointAddress =
-                               fs_in_desc.bEndpointAddress;
-               ss_out_desc.bEndpointAddress =
-                               fs_out_desc.bEndpointAddress;
-               ss_notify_desc.bEndpointAddress =
-                               fs_notify_desc.bEndpointAddress;
-
-               /* copy descriptors, and track endpoint copies */
-               f->ss_descriptors = usb_copy_descriptors(eth_ss_function);
-               if (!f->ss_descriptors)
-                       goto fail;
-       }
+       ss_in_desc.bEndpointAddress = fs_in_desc.bEndpointAddress;
+       ss_out_desc.bEndpointAddress = fs_out_desc.bEndpointAddress;
+       ss_notify_desc.bEndpointAddress = fs_notify_desc.bEndpointAddress;
+
+       status = usb_assign_descriptors(f, eth_fs_function, eth_hs_function,
+                       eth_ss_function);
+       if (status)
+               goto fail;
 
        rndis->port.open = rndis_open;
        rndis->port.close = rndis_close;
@@ -788,12 +768,7 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f)
        return 0;
 
 fail:
-       if (gadget_is_superspeed(c->cdev->gadget) && f->ss_descriptors)
-               usb_free_descriptors(f->ss_descriptors);
-       if (gadget_is_dualspeed(c->cdev->gadget) && f->hs_descriptors)
-               usb_free_descriptors(f->hs_descriptors);
-       if (f->descriptors)
-               usb_free_descriptors(f->descriptors);
+       usb_free_all_descriptors(f);
 
        if (rndis->notify_req) {
                kfree(rndis->notify_req->buf);
@@ -803,9 +778,9 @@ fail:
        /* we might as well release our claims on endpoints */
        if (rndis->notify)
                rndis->notify->driver_data = NULL;
-       if (rndis->port.out_ep->desc)
+       if (rndis->port.out_ep)
                rndis->port.out_ep->driver_data = NULL;
-       if (rndis->port.in_ep->desc)
+       if (rndis->port.in_ep)
                rndis->port.in_ep->driver_data = NULL;
 
        ERROR(cdev, "%s: can't bind, err %d\n", f->name, status);
@@ -820,13 +795,9 @@ rndis_unbind(struct usb_configuration *c, struct usb_function *f)
 
        rndis_deregister(rndis->config);
        rndis_exit();
-       rndis_string_defs[0].id = 0;
 
-       if (gadget_is_superspeed(c->cdev->gadget))
-               usb_free_descriptors(f->ss_descriptors);
-       if (gadget_is_dualspeed(c->cdev->gadget))
-               usb_free_descriptors(f->hs_descriptors);
-       usb_free_descriptors(f->descriptors);
+       rndis_string_defs[0].id = 0;
+       usb_free_all_descriptors(f);
 
        kfree(rndis->notify_req->buf);
        usb_ep_free_request(rndis->notify, rndis->notify_req);
@@ -851,34 +822,19 @@ rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
        if (!can_support_rndis(c) || !ethaddr)
                return -EINVAL;
 
-       /* maybe allocate device-global string IDs */
        if (rndis_string_defs[0].id == 0) {
-
                /* ... and setup RNDIS itself */
                status = rndis_init();
                if (status < 0)
                        return status;
 
-               /* control interface label */
-               status = usb_string_id(c->cdev);
-               if (status < 0)
+               status = usb_string_ids_tab(c->cdev, rndis_string_defs);
+               if (status)
                        return status;
-               rndis_string_defs[0].id = status;
-               rndis_control_intf.iInterface = status;
 
-               /* data interface label */
-               status = usb_string_id(c->cdev);
-               if (status < 0)
-                       return status;
-               rndis_string_defs[1].id = status;
-               rndis_data_intf.iInterface = status;
-
-               /* IAD iFunction label */
-               status = usb_string_id(c->cdev);
-               if (status < 0)
-                       return status;
-               rndis_string_defs[2].id = status;
-               rndis_iad_descriptor.iFunction = status;
+               rndis_control_intf.iInterface = rndis_string_defs[0].id;
+               rndis_data_intf.iInterface = rndis_string_defs[1].id;
+               rndis_iad_descriptor.iFunction = rndis_string_defs[2].id;
        }
 
        /* allocate and initialize one new instance */
index 07197d63d9b1d056e75c79cd85261059279715fa..98fa7795df5f8bccc9b03a89bb43e78c0392865f 100644 (file)
@@ -213,34 +213,20 @@ gser_bind(struct usb_configuration *c, struct usb_function *f)
        gser->port.out = ep;
        ep->driver_data = cdev; /* claim */
 
-       /* copy descriptors, and track endpoint copies */
-       f->descriptors = usb_copy_descriptors(gser_fs_function);
-
        /* support all relevant hardware speeds... we expect that when
         * hardware is dual speed, all bulk-capable endpoints work at
         * both speeds
         */
-       if (gadget_is_dualspeed(c->cdev->gadget)) {
-               gser_hs_in_desc.bEndpointAddress =
-                               gser_fs_in_desc.bEndpointAddress;
-               gser_hs_out_desc.bEndpointAddress =
-                               gser_fs_out_desc.bEndpointAddress;
-
-               /* copy descriptors, and track endpoint copies */
-               f->hs_descriptors = usb_copy_descriptors(gser_hs_function);
-       }
-       if (gadget_is_superspeed(c->cdev->gadget)) {
-               gser_ss_in_desc.bEndpointAddress =
-                       gser_fs_in_desc.bEndpointAddress;
-               gser_ss_out_desc.bEndpointAddress =
-                       gser_fs_out_desc.bEndpointAddress;
-
-               /* copy descriptors, and track endpoint copies */
-               f->ss_descriptors = usb_copy_descriptors(gser_ss_function);
-               if (!f->ss_descriptors)
-                       goto fail;
-       }
+       gser_hs_in_desc.bEndpointAddress = gser_fs_in_desc.bEndpointAddress;
+       gser_hs_out_desc.bEndpointAddress = gser_fs_out_desc.bEndpointAddress;
 
+       gser_ss_in_desc.bEndpointAddress = gser_fs_in_desc.bEndpointAddress;
+       gser_ss_out_desc.bEndpointAddress = gser_fs_out_desc.bEndpointAddress;
+
+       status = usb_assign_descriptors(f, gser_fs_function, gser_hs_function,
+                       gser_ss_function);
+       if (status)
+               goto fail;
        DBG(cdev, "generic ttyGS%d: %s speed IN/%s OUT/%s\n",
                        gser->port_num,
                        gadget_is_superspeed(c->cdev->gadget) ? "super" :
@@ -263,11 +249,7 @@ fail:
 static void
 gser_unbind(struct usb_configuration *c, struct usb_function *f)
 {
-       if (gadget_is_dualspeed(c->cdev->gadget))
-               usb_free_descriptors(f->hs_descriptors);
-       if (gadget_is_superspeed(c->cdev->gadget))
-               usb_free_descriptors(f->ss_descriptors);
-       usb_free_descriptors(f->descriptors);
+       usb_free_all_descriptors(f);
        kfree(func_to_gser(f));
 }
 
index 3c126fde6e7e7131168c47805a32f94379b68fcc..102d49beb9dfe833f3bf00a07b3bba8685aa0a35 100644 (file)
@@ -319,6 +319,7 @@ sourcesink_bind(struct usb_configuration *c, struct usb_function *f)
        struct usb_composite_dev *cdev = c->cdev;
        struct f_sourcesink     *ss = func_to_ss(f);
        int     id;
+       int ret;
 
        /* allocate interface ID(s) */
        id = usb_interface_id(c, f);
@@ -387,64 +388,57 @@ no_iso:
                isoc_maxpacket = 1024;
 
        /* support high speed hardware */
-       if (gadget_is_dualspeed(c->cdev->gadget)) {
-               hs_source_desc.bEndpointAddress =
-                               fs_source_desc.bEndpointAddress;
-               hs_sink_desc.bEndpointAddress =
-                               fs_sink_desc.bEndpointAddress;
+       hs_source_desc.bEndpointAddress = fs_source_desc.bEndpointAddress;
+       hs_sink_desc.bEndpointAddress = fs_sink_desc.bEndpointAddress;
 
-               /*
-                * Fill in the HS isoc descriptors from the module parameters.
-                * We assume that the user knows what they are doing and won't
-                * give parameters that their UDC doesn't support.
-                */
-               hs_iso_source_desc.wMaxPacketSize = isoc_maxpacket;
-               hs_iso_source_desc.wMaxPacketSize |= isoc_mult << 11;
-               hs_iso_source_desc.bInterval = isoc_interval;
-               hs_iso_source_desc.bEndpointAddress =
-                               fs_iso_source_desc.bEndpointAddress;
-
-               hs_iso_sink_desc.wMaxPacketSize = isoc_maxpacket;
-               hs_iso_sink_desc.wMaxPacketSize |= isoc_mult << 11;
-               hs_iso_sink_desc.bInterval = isoc_interval;
-               hs_iso_sink_desc.bEndpointAddress =
-                               fs_iso_sink_desc.bEndpointAddress;
-
-               f->hs_descriptors = hs_source_sink_descs;
-       }
+       /*
+        * Fill in the HS isoc descriptors from the module parameters.
+        * We assume that the user knows what they are doing and won't
+        * give parameters that their UDC doesn't support.
+        */
+       hs_iso_source_desc.wMaxPacketSize = isoc_maxpacket;
+       hs_iso_source_desc.wMaxPacketSize |= isoc_mult << 11;
+       hs_iso_source_desc.bInterval = isoc_interval;
+       hs_iso_source_desc.bEndpointAddress =
+               fs_iso_source_desc.bEndpointAddress;
+
+       hs_iso_sink_desc.wMaxPacketSize = isoc_maxpacket;
+       hs_iso_sink_desc.wMaxPacketSize |= isoc_mult << 11;
+       hs_iso_sink_desc.bInterval = isoc_interval;
+       hs_iso_sink_desc.bEndpointAddress = fs_iso_sink_desc.bEndpointAddress;
 
        /* support super speed hardware */
-       if (gadget_is_superspeed(c->cdev->gadget)) {
-               ss_source_desc.bEndpointAddress =
-                               fs_source_desc.bEndpointAddress;
-               ss_sink_desc.bEndpointAddress =
-                               fs_sink_desc.bEndpointAddress;
+       ss_source_desc.bEndpointAddress =
+               fs_source_desc.bEndpointAddress;
+       ss_sink_desc.bEndpointAddress =
+               fs_sink_desc.bEndpointAddress;
 
-               /*
-                * Fill in the SS isoc descriptors from the module parameters.
-                * We assume that the user knows what they are doing and won't
-                * give parameters that their UDC doesn't support.
-                */
-               ss_iso_source_desc.wMaxPacketSize = isoc_maxpacket;
-               ss_iso_source_desc.bInterval = isoc_interval;
-               ss_iso_source_comp_desc.bmAttributes = isoc_mult;
-               ss_iso_source_comp_desc.bMaxBurst = isoc_maxburst;
-               ss_iso_source_comp_desc.wBytesPerInterval =
-                       isoc_maxpacket * (isoc_mult + 1) * (isoc_maxburst + 1);
-               ss_iso_source_desc.bEndpointAddress =
-                               fs_iso_source_desc.bEndpointAddress;
-
-               ss_iso_sink_desc.wMaxPacketSize = isoc_maxpacket;
-               ss_iso_sink_desc.bInterval = isoc_interval;
-               ss_iso_sink_comp_desc.bmAttributes = isoc_mult;
-               ss_iso_sink_comp_desc.bMaxBurst = isoc_maxburst;
-               ss_iso_sink_comp_desc.wBytesPerInterval =
-                       isoc_maxpacket * (isoc_mult + 1) * (isoc_maxburst + 1);
-               ss_iso_sink_desc.bEndpointAddress =
-                               fs_iso_sink_desc.bEndpointAddress;
-
-               f->ss_descriptors = ss_source_sink_descs;
-       }
+       /*
+        * Fill in the SS isoc descriptors from the module parameters.
+        * We assume that the user knows what they are doing and won't
+        * give parameters that their UDC doesn't support.
+        */
+       ss_iso_source_desc.wMaxPacketSize = isoc_maxpacket;
+       ss_iso_source_desc.bInterval = isoc_interval;
+       ss_iso_source_comp_desc.bmAttributes = isoc_mult;
+       ss_iso_source_comp_desc.bMaxBurst = isoc_maxburst;
+       ss_iso_source_comp_desc.wBytesPerInterval =
+               isoc_maxpacket * (isoc_mult + 1) * (isoc_maxburst + 1);
+       ss_iso_source_desc.bEndpointAddress =
+               fs_iso_source_desc.bEndpointAddress;
+
+       ss_iso_sink_desc.wMaxPacketSize = isoc_maxpacket;
+       ss_iso_sink_desc.bInterval = isoc_interval;
+       ss_iso_sink_comp_desc.bmAttributes = isoc_mult;
+       ss_iso_sink_comp_desc.bMaxBurst = isoc_maxburst;
+       ss_iso_sink_comp_desc.wBytesPerInterval =
+               isoc_maxpacket * (isoc_mult + 1) * (isoc_maxburst + 1);
+       ss_iso_sink_desc.bEndpointAddress = fs_iso_sink_desc.bEndpointAddress;
+
+       ret = usb_assign_descriptors(f, fs_source_sink_descs,
+                       hs_source_sink_descs, ss_source_sink_descs);
+       if (ret)
+               return ret;
 
        DBG(cdev, "%s speed %s: IN/%s, OUT/%s, ISO-IN/%s, ISO-OUT/%s\n",
            (gadget_is_superspeed(c->cdev->gadget) ? "super" :
@@ -458,6 +452,7 @@ no_iso:
 static void
 sourcesink_unbind(struct usb_configuration *c, struct usb_function *f)
 {
+       usb_free_all_descriptors(f);
        kfree(func_to_ss(f));
 }
 
@@ -773,7 +768,6 @@ static int __init sourcesink_bind_config(struct usb_configuration *c)
                return -ENOMEM;
 
        ss->function.name = "source/sink";
-       ss->function.descriptors = fs_source_sink_descs;
        ss->function.bind = sourcesink_bind;
        ss->function.unbind = sourcesink_unbind;
        ss->function.set_alt = sourcesink_set_alt;
index 4060c0bd9785cf5a033b2e30981374fd0cdc5fb0..f172bd152fbb905d34906a468e79e0422e98483b 100644 (file)
@@ -236,7 +236,7 @@ static struct usb_descriptor_header *ss_eth_function[] = {
 
 static struct usb_string geth_string_defs[] = {
        [0].s = "CDC Ethernet Subset/SAFE",
-       [1].s = NULL /* DYNAMIC */,
+       [1].s = "",
        {  } /* end of list */
 };
 
@@ -319,38 +319,22 @@ geth_bind(struct usb_configuration *c, struct usb_function *f)
        geth->port.out_ep = ep;
        ep->driver_data = cdev; /* claim */
 
-       /* copy descriptors, and track endpoint copies */
-       f->descriptors = usb_copy_descriptors(fs_eth_function);
-       if (!f->descriptors)
-               goto fail;
-
        /* support all relevant hardware speeds... we expect that when
         * hardware is dual speed, all bulk-capable endpoints work at
         * both speeds
         */
-       if (gadget_is_dualspeed(c->cdev->gadget)) {
-               hs_subset_in_desc.bEndpointAddress =
-                               fs_subset_in_desc.bEndpointAddress;
-               hs_subset_out_desc.bEndpointAddress =
-                               fs_subset_out_desc.bEndpointAddress;
-
-               /* copy descriptors, and track endpoint copies */
-               f->hs_descriptors = usb_copy_descriptors(hs_eth_function);
-               if (!f->hs_descriptors)
-                       goto fail;
-       }
+       hs_subset_in_desc.bEndpointAddress = fs_subset_in_desc.bEndpointAddress;
+       hs_subset_out_desc.bEndpointAddress =
+               fs_subset_out_desc.bEndpointAddress;
 
-       if (gadget_is_superspeed(c->cdev->gadget)) {
-               ss_subset_in_desc.bEndpointAddress =
-                               fs_subset_in_desc.bEndpointAddress;
-               ss_subset_out_desc.bEndpointAddress =
-                               fs_subset_out_desc.bEndpointAddress;
+       ss_subset_in_desc.bEndpointAddress = fs_subset_in_desc.bEndpointAddress;
+       ss_subset_out_desc.bEndpointAddress =
+               fs_subset_out_desc.bEndpointAddress;
 
-               /* copy descriptors, and track endpoint copies */
-               f->ss_descriptors = usb_copy_descriptors(ss_eth_function);
-               if (!f->ss_descriptors)
-                       goto fail;
-       }
+       status = usb_assign_descriptors(f, fs_eth_function, hs_eth_function,
+                       ss_eth_function);
+       if (status)
+               goto fail;
 
        /* NOTE:  all that is done without knowing or caring about
         * the network link ... which is unavailable to this code
@@ -364,15 +348,11 @@ geth_bind(struct usb_configuration *c, struct usb_function *f)
        return 0;
 
 fail:
-       if (f->descriptors)
-               usb_free_descriptors(f->descriptors);
-       if (f->hs_descriptors)
-               usb_free_descriptors(f->hs_descriptors);
-
+       usb_free_all_descriptors(f);
        /* we might as well release our claims on endpoints */
-       if (geth->port.out_ep->desc)
+       if (geth->port.out_ep)
                geth->port.out_ep->driver_data = NULL;
-       if (geth->port.in_ep->desc)
+       if (geth->port.in_ep)
                geth->port.in_ep->driver_data = NULL;
 
        ERROR(cdev, "%s: can't bind, err %d\n", f->name, status);
@@ -383,12 +363,8 @@ fail:
 static void
 geth_unbind(struct usb_configuration *c, struct usb_function *f)
 {
-       if (gadget_is_superspeed(c->cdev->gadget))
-               usb_free_descriptors(f->ss_descriptors);
-       if (gadget_is_dualspeed(c->cdev->gadget))
-               usb_free_descriptors(f->hs_descriptors);
-       usb_free_descriptors(f->descriptors);
-       geth_string_defs[1].s = NULL;
+       geth_string_defs[0].id = 0;
+       usb_free_all_descriptors(f);
        kfree(func_to_geth(f));
 }
 
@@ -414,20 +390,11 @@ int geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
 
        /* maybe allocate device-global string IDs */
        if (geth_string_defs[0].id == 0) {
-
-               /* interface label */
-               status = usb_string_id(c->cdev);
+               status = usb_string_ids_tab(c->cdev, geth_string_defs);
                if (status < 0)
                        return status;
-               geth_string_defs[0].id = status;
-               subset_data_intf.iInterface = status;
-
-               /* MAC address */
-               status = usb_string_id(c->cdev);
-               if (status < 0)
-                       return status;
-               geth_string_defs[1].id = status;
-               ether_desc.iMACAddress = status;
+               subset_data_intf.iInterface = geth_string_defs[0].id;
+               ether_desc.iMACAddress = geth_string_defs[1].id;
        }
 
        /* allocate and initialize one new instance */
@@ -449,9 +416,7 @@ int geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
        geth->port.func.disable = geth_disable;
 
        status = usb_add_function(c, &geth->port.func);
-       if (status) {
-               geth_string_defs[1].s = NULL;
+       if (status)
                kfree(geth);
-       }
        return status;
 }
index 1a5dcd5565e31e58c170d1a351368dbf1d9aeb14..f570e667a640d0619cd6abaffaf9705738fcab24 100644 (file)
@@ -630,7 +630,7 @@ f_audio_bind(struct usb_configuration *c, struct usb_function *f)
        struct usb_composite_dev *cdev = c->cdev;
        struct f_audio          *audio = func_to_audio(f);
        int                     status;
-       struct usb_ep           *ep;
+       struct usb_ep           *ep = NULL;
 
        f_audio_build_desc(audio);
 
@@ -659,22 +659,14 @@ f_audio_bind(struct usb_configuration *c, struct usb_function *f)
        status = -ENOMEM;
 
        /* copy descriptors, and track endpoint copies */
-       f->descriptors = usb_copy_descriptors(f_audio_desc);
-
-       /*
-        * support all relevant hardware speeds... we expect that when
-        * hardware is dual speed, all bulk-capable endpoints work at
-        * both speeds
-        */
-       if (gadget_is_dualspeed(c->cdev->gadget)) {
-               c->highspeed = true;
-               f->hs_descriptors = usb_copy_descriptors(f_audio_desc);
-       }
-
+       status = usb_assign_descriptors(f, f_audio_desc, f_audio_desc, NULL);
+       if (status)
+               goto fail;
        return 0;
 
 fail:
-
+       if (ep)
+               ep->driver_data = NULL;
        return status;
 }
 
@@ -683,8 +675,7 @@ f_audio_unbind(struct usb_configuration *c, struct usb_function *f)
 {
        struct f_audio          *audio = func_to_audio(f);
 
-       usb_free_descriptors(f->descriptors);
-       usb_free_descriptors(f->hs_descriptors);
+       usb_free_all_descriptors(f);
        kfree(audio);
 }
 
index d3c6cffccb72c0566cb7c1daad4c613d3e501e4c..91396a1683ebd4396a2c2b0a86914e86d6fadf27 100644 (file)
@@ -50,13 +50,6 @@ static int c_ssize = 2;
 module_param(c_ssize, uint, S_IRUGO);
 MODULE_PARM_DESC(c_ssize, "Capture Sample Size(bytes)");
 
-#define DMA_ADDR_INVALID       (~(dma_addr_t)0)
-
-#define ALT_SET(x, a)  do {(x) &= ~0xff; (x) |= (a); } while (0)
-#define ALT_GET(x)     ((x) & 0xff)
-#define INTF_SET(x, i) do {(x) &= 0xff; (x) |= ((i) << 8); } while (0)
-#define INTF_GET(x)    ((x >> 8) & 0xff)
-
 /* Keep everyone on toes */
 #define USB_XFERS      2
 
@@ -144,8 +137,9 @@ static struct snd_pcm_hardware uac2_pcm_hardware = {
 };
 
 struct audio_dev {
-       /* Currently active {Interface[15:8] | AltSettings[7:0]} */
-       __u16 ac_alt, as_out_alt, as_in_alt;
+       u8 ac_intf, ac_alt;
+       u8 as_out_intf, as_out_alt;
+       u8 as_in_intf, as_in_alt;
 
        struct usb_ep *in_ep, *out_ep;
        struct usb_function func;
@@ -526,32 +520,22 @@ enum {
        STR_AS_IN_ALT1,
 };
 
-static const char ifassoc[] = "Source/Sink";
-static const char ifctrl[] = "Topology Control";
 static char clksrc_in[8];
 static char clksrc_out[8];
-static const char usb_it[] = "USBH Out";
-static const char io_it[] = "USBD Out";
-static const char usb_ot[] = "USBH In";
-static const char io_ot[] = "USBD In";
-static const char out_alt0[] = "Playback Inactive";
-static const char out_alt1[] = "Playback Active";
-static const char in_alt0[] = "Capture Inactive";
-static const char in_alt1[] = "Capture Active";
 
 static struct usb_string strings_fn[] = {
-       [STR_ASSOC].s = ifassoc,
-       [STR_IF_CTRL].s = ifctrl,
+       [STR_ASSOC].s = "Source/Sink",
+       [STR_IF_CTRL].s = "Topology Control",
        [STR_CLKSRC_IN].s = clksrc_in,
        [STR_CLKSRC_OUT].s = clksrc_out,
-       [STR_USB_IT].s = usb_it,
-       [STR_IO_IT].s = io_it,
-       [STR_USB_OT].s = usb_ot,
-       [STR_IO_OT].s = io_ot,
-       [STR_AS_OUT_ALT0].s = out_alt0,
-       [STR_AS_OUT_ALT1].s = out_alt1,
-       [STR_AS_IN_ALT0].s = in_alt0,
-       [STR_AS_IN_ALT1].s = in_alt1,
+       [STR_USB_IT].s = "USBH Out",
+       [STR_IO_IT].s = "USBD Out",
+       [STR_USB_OT].s = "USBH In",
+       [STR_IO_OT].s = "USBD In",
+       [STR_AS_OUT_ALT0].s = "Playback Inactive",
+       [STR_AS_OUT_ALT1].s = "Playback Active",
+       [STR_AS_IN_ALT0].s = "Capture Inactive",
+       [STR_AS_IN_ALT1].s = "Capture Active",
        { },
 };
 
@@ -952,8 +936,8 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)
                return ret;
        }
        std_ac_if_desc.bInterfaceNumber = ret;
-       ALT_SET(agdev->ac_alt, 0);
-       INTF_SET(agdev->ac_alt, ret);
+       agdev->ac_intf = ret;
+       agdev->ac_alt = 0;
 
        ret = usb_interface_id(cfg, fn);
        if (ret < 0) {
@@ -963,8 +947,8 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)
        }
        std_as_out_if0_desc.bInterfaceNumber = ret;
        std_as_out_if1_desc.bInterfaceNumber = ret;
-       ALT_SET(agdev->as_out_alt, 0);
-       INTF_SET(agdev->as_out_alt, ret);
+       agdev->as_out_intf = ret;
+       agdev->as_out_alt = 0;
 
        ret = usb_interface_id(cfg, fn);
        if (ret < 0) {
@@ -974,19 +958,23 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)
        }
        std_as_in_if0_desc.bInterfaceNumber = ret;
        std_as_in_if1_desc.bInterfaceNumber = ret;
-       ALT_SET(agdev->as_in_alt, 0);
-       INTF_SET(agdev->as_in_alt, ret);
+       agdev->as_in_intf = ret;
+       agdev->as_in_alt = 0;
 
        agdev->out_ep = usb_ep_autoconfig(gadget, &fs_epout_desc);
-       if (!agdev->out_ep)
+       if (!agdev->out_ep) {
                dev_err(&uac2->pdev.dev,
                        "%s:%d Error!\n", __func__, __LINE__);
+               goto err;
+       }
        agdev->out_ep->driver_data = agdev;
 
        agdev->in_ep = usb_ep_autoconfig(gadget, &fs_epin_desc);
-       if (!agdev->in_ep)
+       if (!agdev->in_ep) {
                dev_err(&uac2->pdev.dev,
                        "%s:%d Error!\n", __func__, __LINE__);
+               goto err;
+       }
        agdev->in_ep->driver_data = agdev;
 
        hs_epout_desc.bEndpointAddress = fs_epout_desc.bEndpointAddress;
@@ -994,9 +982,9 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)
        hs_epin_desc.bEndpointAddress = fs_epin_desc.bEndpointAddress;
        hs_epin_desc.wMaxPacketSize = fs_epin_desc.wMaxPacketSize;
 
-       fn->descriptors = usb_copy_descriptors(fs_audio_desc);
-       if (gadget_is_dualspeed(gadget))
-               fn->hs_descriptors = usb_copy_descriptors(hs_audio_desc);
+       ret = usb_assign_descriptors(fn, fs_audio_desc, hs_audio_desc, NULL);
+       if (ret)
+               goto err;
 
        prm = &agdev->uac2.c_prm;
        prm->max_psize = hs_epout_desc.wMaxPacketSize;
@@ -1005,6 +993,7 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)
                prm->max_psize = 0;
                dev_err(&uac2->pdev.dev,
                        "%s:%d Error!\n", __func__, __LINE__);
+               goto err;
        }
 
        prm = &agdev->uac2.p_prm;
@@ -1014,17 +1003,28 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)
                prm->max_psize = 0;
                dev_err(&uac2->pdev.dev,
                        "%s:%d Error!\n", __func__, __LINE__);
+               goto err;
        }
 
-       return alsa_uac2_init(agdev);
+       ret = alsa_uac2_init(agdev);
+       if (ret)
+               goto err;
+       return 0;
+err:
+       kfree(agdev->uac2.p_prm.rbuf);
+       kfree(agdev->uac2.c_prm.rbuf);
+       usb_free_all_descriptors(fn);
+       if (agdev->in_ep)
+               agdev->in_ep->driver_data = NULL;
+       if (agdev->out_ep)
+               agdev->out_ep->driver_data = NULL;
+       return -EINVAL;
 }
 
 static void
 afunc_unbind(struct usb_configuration *cfg, struct usb_function *fn)
 {
        struct audio_dev *agdev = func_to_agdev(fn);
-       struct usb_composite_dev *cdev = cfg->cdev;
-       struct usb_gadget *gadget = cdev->gadget;
        struct uac2_rtd_params *prm;
 
        alsa_uac2_exit(agdev);
@@ -1034,10 +1034,7 @@ afunc_unbind(struct usb_configuration *cfg, struct usb_function *fn)
 
        prm = &agdev->uac2.c_prm;
        kfree(prm->rbuf);
-
-       if (gadget_is_dualspeed(gadget))
-               usb_free_descriptors(fn->hs_descriptors);
-       usb_free_descriptors(fn->descriptors);
+       usb_free_all_descriptors(fn);
 
        if (agdev->in_ep)
                agdev->in_ep->driver_data = NULL;
@@ -1064,7 +1061,7 @@ afunc_set_alt(struct usb_function *fn, unsigned intf, unsigned alt)
                return -EINVAL;
        }
 
-       if (intf == INTF_GET(agdev->ac_alt)) {
+       if (intf == agdev->ac_intf) {
                /* Control I/f has only 1 AltSetting - 0 */
                if (alt) {
                        dev_err(&uac2->pdev.dev,
@@ -1074,16 +1071,16 @@ afunc_set_alt(struct usb_function *fn, unsigned intf, unsigned alt)
                return 0;
        }
 
-       if (intf == INTF_GET(agdev->as_out_alt)) {
+       if (intf == agdev->as_out_intf) {
                ep = agdev->out_ep;
                prm = &uac2->c_prm;
                config_ep_by_speed(gadget, fn, ep);
-               ALT_SET(agdev->as_out_alt, alt);
-       } else if (intf == INTF_GET(agdev->as_in_alt)) {
+               agdev->as_out_alt = alt;
+       } else if (intf == agdev->as_in_intf) {
                ep = agdev->in_ep;
                prm = &uac2->p_prm;
                config_ep_by_speed(gadget, fn, ep);
-               ALT_SET(agdev->as_in_alt, alt);
+               agdev->as_in_alt = alt;
        } else {
                dev_err(&uac2->pdev.dev,
                        "%s:%d Error!\n", __func__, __LINE__);
@@ -1117,7 +1114,6 @@ afunc_set_alt(struct usb_function *fn, unsigned intf, unsigned alt)
                prm->ureq[i].pp = prm;
 
                req->zero = 0;
-               req->dma = DMA_ADDR_INVALID;
                req->context = &prm->ureq[i];
                req->length = prm->max_psize;
                req->complete = agdev_iso_complete;
@@ -1136,12 +1132,12 @@ afunc_get_alt(struct usb_function *fn, unsigned intf)
        struct audio_dev *agdev = func_to_agdev(fn);
        struct snd_uac2_chip *uac2 = &agdev->uac2;
 
-       if (intf == INTF_GET(agdev->ac_alt))
-               return ALT_GET(agdev->ac_alt);
-       else if (intf == INTF_GET(agdev->as_out_alt))
-               return ALT_GET(agdev->as_out_alt);
-       else if (intf == INTF_GET(agdev->as_in_alt))
-               return ALT_GET(agdev->as_in_alt);
+       if (intf == agdev->ac_intf)
+               return agdev->ac_alt;
+       else if (intf == agdev->as_out_intf)
+               return agdev->as_out_alt;
+       else if (intf == agdev->as_in_intf)
+               return agdev->as_in_alt;
        else
                dev_err(&uac2->pdev.dev,
                        "%s:%d Invalid Interface %d!\n",
@@ -1157,10 +1153,10 @@ afunc_disable(struct usb_function *fn)
        struct snd_uac2_chip *uac2 = &agdev->uac2;
 
        free_ep(&uac2->p_prm, agdev->in_ep);
-       ALT_SET(agdev->as_in_alt, 0);
+       agdev->as_in_alt = 0;
 
        free_ep(&uac2->c_prm, agdev->out_ep);
-       ALT_SET(agdev->as_out_alt, 0);
+       agdev->as_out_alt = 0;
 }
 
 static int
@@ -1267,7 +1263,7 @@ setup_rq_inf(struct usb_function *fn, const struct usb_ctrlrequest *cr)
        u16 w_index = le16_to_cpu(cr->wIndex);
        u8 intf = w_index & 0xff;
 
-       if (intf != INTF_GET(agdev->ac_alt)) {
+       if (intf != agdev->ac_intf) {
                dev_err(&uac2->pdev.dev,
                        "%s:%d Error!\n", __func__, __LINE__);
                return -EOPNOTSUPP;
@@ -1316,7 +1312,7 @@ afunc_setup(struct usb_function *fn, const struct usb_ctrlrequest *cr)
 
 static int audio_bind_config(struct usb_configuration *cfg)
 {
-       int id, res;
+       int res;
 
        agdev_g = kzalloc(sizeof *agdev_g, GFP_KERNEL);
        if (agdev_g == NULL) {
@@ -1324,89 +1320,21 @@ static int audio_bind_config(struct usb_configuration *cfg)
                return -ENOMEM;
        }
 
-       id = usb_string_id(cfg->cdev);
-       if (id < 0)
-               return id;
-
-       strings_fn[STR_ASSOC].id = id;
-       iad_desc.iFunction = id,
-
-       id = usb_string_id(cfg->cdev);
-       if (id < 0)
-               return id;
-
-       strings_fn[STR_IF_CTRL].id = id;
-       std_ac_if_desc.iInterface = id,
-
-       id = usb_string_id(cfg->cdev);
-       if (id < 0)
-               return id;
-
-       strings_fn[STR_CLKSRC_IN].id = id;
-       in_clk_src_desc.iClockSource = id,
-
-       id = usb_string_id(cfg->cdev);
-       if (id < 0)
-               return id;
-
-       strings_fn[STR_CLKSRC_OUT].id = id;
-       out_clk_src_desc.iClockSource = id,
-
-       id = usb_string_id(cfg->cdev);
-       if (id < 0)
-               return id;
-
-       strings_fn[STR_USB_IT].id = id;
-       usb_out_it_desc.iTerminal = id,
-
-       id = usb_string_id(cfg->cdev);
-       if (id < 0)
-               return id;
-
-       strings_fn[STR_IO_IT].id = id;
-       io_in_it_desc.iTerminal = id;
-
-       id = usb_string_id(cfg->cdev);
-       if (id < 0)
-               return id;
-
-       strings_fn[STR_USB_OT].id = id;
-       usb_in_ot_desc.iTerminal = id;
-
-       id = usb_string_id(cfg->cdev);
-       if (id < 0)
-               return id;
-
-       strings_fn[STR_IO_OT].id = id;
-       io_out_ot_desc.iTerminal = id;
-
-       id = usb_string_id(cfg->cdev);
-       if (id < 0)
-               return id;
-
-       strings_fn[STR_AS_OUT_ALT0].id = id;
-       std_as_out_if0_desc.iInterface = id;
-
-       id = usb_string_id(cfg->cdev);
-       if (id < 0)
-               return id;
-
-       strings_fn[STR_AS_OUT_ALT1].id = id;
-       std_as_out_if1_desc.iInterface = id;
-
-       id = usb_string_id(cfg->cdev);
-       if (id < 0)
-               return id;
-
-       strings_fn[STR_AS_IN_ALT0].id = id;
-       std_as_in_if0_desc.iInterface = id;
-
-       id = usb_string_id(cfg->cdev);
-       if (id < 0)
-               return id;
-
-       strings_fn[STR_AS_IN_ALT1].id = id;
-       std_as_in_if1_desc.iInterface = id;
+       res = usb_string_ids_tab(cfg->cdev, strings_fn);
+       if (res)
+               return res;
+       iad_desc.iFunction = strings_fn[STR_ASSOC].id;
+       std_ac_if_desc.iInterface = strings_fn[STR_IF_CTRL].id;
+       in_clk_src_desc.iClockSource = strings_fn[STR_CLKSRC_IN].id;
+       out_clk_src_desc.iClockSource = strings_fn[STR_CLKSRC_OUT].id;
+       usb_out_it_desc.iTerminal = strings_fn[STR_USB_IT].id;
+       io_in_it_desc.iTerminal = strings_fn[STR_IO_IT].id;
+       usb_in_ot_desc.iTerminal = strings_fn[STR_USB_OT].id;
+       io_out_ot_desc.iTerminal = strings_fn[STR_IO_OT].id;
+       std_as_out_if0_desc.iInterface = strings_fn[STR_AS_OUT_ALT0].id;
+       std_as_out_if1_desc.iInterface = strings_fn[STR_AS_OUT_ALT1].id;
+       std_as_in_if0_desc.iInterface = strings_fn[STR_AS_IN_ALT0].id;
+       std_as_in_if1_desc.iInterface = strings_fn[STR_AS_IN_ALT1].id;
 
        agdev_g->func.name = "uac2_func";
        agdev_g->func.strings = fn_strings;
index 2a8bf0655c60d29ccbed68cc21ab240ef8f303ce..5b629876941bc282d1ceea95e3caac4c2cdd6cbf 100644 (file)
@@ -417,7 +417,6 @@ uvc_register_video(struct uvc_device *uvc)
                return -ENOMEM;
 
        video->parent = &cdev->gadget->dev;
-       video->minor = -1;
        video->fops = &uvc_v4l2_fops;
        video->release = video_device_release;
        strncpy(video->name, cdev->gadget->name, sizeof(video->name));
@@ -577,27 +576,15 @@ uvc_function_unbind(struct usb_configuration *c, struct usb_function *f)
 
        INFO(cdev, "uvc_function_unbind\n");
 
-       if (uvc->vdev) {
-               if (uvc->vdev->minor == -1)
-                       video_device_release(uvc->vdev);
-               else
-                       video_unregister_device(uvc->vdev);
-               uvc->vdev = NULL;
-       }
+       video_unregister_device(uvc->vdev);
+       uvc->control_ep->driver_data = NULL;
+       uvc->video.ep->driver_data = NULL;
 
-       if (uvc->control_ep)
-               uvc->control_ep->driver_data = NULL;
-       if (uvc->video.ep)
-               uvc->video.ep->driver_data = NULL;
-
-       if (uvc->control_req) {
-               usb_ep_free_request(cdev->gadget->ep0, uvc->control_req);
-               kfree(uvc->control_buf);
-       }
+       uvc_en_us_strings[UVC_STRING_ASSOCIATION_IDX].id = 0;
+       usb_ep_free_request(cdev->gadget->ep0, uvc->control_req);
+       kfree(uvc->control_buf);
 
-       kfree(f->descriptors);
-       kfree(f->hs_descriptors);
-       kfree(f->ss_descriptors);
+       usb_free_all_descriptors(f);
 
        kfree(uvc);
 }
@@ -663,49 +650,40 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f)
        /* sanity check the streaming endpoint module parameters */
        if (streaming_maxpacket > 1024)
                streaming_maxpacket = 1024;
+       /*
+        * Fill in the HS descriptors from the module parameters for the Video
+        * Streaming endpoint.
+        * NOTE: We assume that the user knows what they are doing and won't
+        * give parameters that their UDC doesn't support.
+        */
+       uvc_hs_streaming_ep.wMaxPacketSize = streaming_maxpacket;
+       uvc_hs_streaming_ep.wMaxPacketSize |= streaming_mult << 11;
+       uvc_hs_streaming_ep.bInterval = streaming_interval;
+       uvc_hs_streaming_ep.bEndpointAddress =
+               uvc_fs_streaming_ep.bEndpointAddress;
 
-       /* Copy descriptors for FS. */
-       f->descriptors = uvc_copy_descriptors(uvc, USB_SPEED_FULL);
-
-       /* support high speed hardware */
-       if (gadget_is_dualspeed(cdev->gadget)) {
-               /*
-                * Fill in the HS descriptors from the module parameters for the
-                * Video Streaming endpoint.
-                * NOTE: We assume that the user knows what they are doing and
-                * won't give parameters that their UDC doesn't support.
-                */
-               uvc_hs_streaming_ep.wMaxPacketSize = streaming_maxpacket;
-               uvc_hs_streaming_ep.wMaxPacketSize |= streaming_mult << 11;
-               uvc_hs_streaming_ep.bInterval = streaming_interval;
-               uvc_hs_streaming_ep.bEndpointAddress =
-                               uvc_fs_streaming_ep.bEndpointAddress;
-
-               /* Copy descriptors. */
-               f->hs_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_HIGH);
-       }
+       /*
+        * Fill in the SS descriptors from the module parameters for the Video
+        * Streaming endpoint.
+        * NOTE: We assume that the user knows what they are doing and won't
+        * give parameters that their UDC doesn't support.
+        */
+       uvc_ss_streaming_ep.wMaxPacketSize = streaming_maxpacket;
+       uvc_ss_streaming_ep.bInterval = streaming_interval;
+       uvc_ss_streaming_comp.bmAttributes = streaming_mult;
+       uvc_ss_streaming_comp.bMaxBurst = streaming_maxburst;
+       uvc_ss_streaming_comp.wBytesPerInterval =
+               streaming_maxpacket * (streaming_mult + 1) *
+               (streaming_maxburst + 1);
+       uvc_ss_streaming_ep.bEndpointAddress =
+               uvc_fs_streaming_ep.bEndpointAddress;
 
-       /* support super speed hardware */
-       if (gadget_is_superspeed(c->cdev->gadget)) {
-               /*
-                * Fill in the SS descriptors from the module parameters for the
-                * Video Streaming endpoint.
-                * NOTE: We assume that the user knows what they are doing and
-                * won't give parameters that their UDC doesn't support.
-                */
-               uvc_ss_streaming_ep.wMaxPacketSize = streaming_maxpacket;
-               uvc_ss_streaming_ep.bInterval = streaming_interval;
-               uvc_ss_streaming_comp.bmAttributes = streaming_mult;
-               uvc_ss_streaming_comp.bMaxBurst = streaming_maxburst;
-               uvc_ss_streaming_comp.wBytesPerInterval =
-                       streaming_maxpacket * (streaming_mult + 1) *
-                       (streaming_maxburst + 1);
-               uvc_ss_streaming_ep.bEndpointAddress =
-                               uvc_fs_streaming_ep.bEndpointAddress;
-
-               /* Copy descriptors. */
+       /* Copy descriptors */
+       f->fs_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_FULL);
+       if (gadget_is_dualspeed(cdev->gadget))
+               f->hs_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_HIGH);
+       if (gadget_is_superspeed(c->cdev->gadget))
                f->ss_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_SUPER);
-       }
 
        /* Preallocate control endpoint request. */
        uvc->control_req = usb_ep_alloc_request(cdev->gadget->ep0, GFP_KERNEL);
@@ -740,7 +718,20 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f)
        return 0;
 
 error:
-       uvc_function_unbind(c, f);
+       if (uvc->vdev)
+               video_device_release(uvc->vdev);
+
+       if (uvc->control_ep)
+               uvc->control_ep->driver_data = NULL;
+       if (uvc->video.ep)
+               uvc->video.ep->driver_data = NULL;
+
+       if (uvc->control_req) {
+               usb_ep_free_request(cdev->gadget->ep0, uvc->control_req);
+               kfree(uvc->control_buf);
+       }
+
+       usb_free_all_descriptors(f);
        return ret;
 }
 
@@ -808,25 +799,16 @@ uvc_bind_config(struct usb_configuration *c,
        uvc->desc.hs_streaming = hs_streaming;
        uvc->desc.ss_streaming = ss_streaming;
 
-       /* maybe allocate device-global string IDs, and patch descriptors */
+       /* Allocate string descriptor numbers. */
        if (uvc_en_us_strings[UVC_STRING_ASSOCIATION_IDX].id == 0) {
-               /* Allocate string descriptor numbers. */
-               ret = usb_string_id(c->cdev);
-               if (ret < 0)
-                       goto error;
-               uvc_en_us_strings[UVC_STRING_ASSOCIATION_IDX].id = ret;
-               uvc_iad.iFunction = ret;
-
-               ret = usb_string_id(c->cdev);
-               if (ret < 0)
-                       goto error;
-               uvc_en_us_strings[UVC_STRING_CONTROL_IDX].id = ret;
-               uvc_control_intf.iInterface = ret;
-
-               ret = usb_string_id(c->cdev);
-               if (ret < 0)
+               ret = usb_string_ids_tab(c->cdev, uvc_en_us_strings);
+               if (ret)
                        goto error;
-               uvc_en_us_strings[UVC_STRING_STREAMING_IDX].id = ret;
+               uvc_iad.iFunction =
+                       uvc_en_us_strings[UVC_STRING_ASSOCIATION_IDX].id;
+               uvc_control_intf.iInterface =
+                       uvc_en_us_strings[UVC_STRING_CONTROL_IDX].id;
+               ret = uvc_en_us_strings[UVC_STRING_STREAMING_IDX].id;
                uvc_streaming_intf_alt0.iInterface = ret;
                uvc_streaming_intf_alt1.iInterface = ret;
        }
diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
deleted file mode 100644 (file)
index 3f7d640..0000000
+++ /dev/null
@@ -1,3656 +0,0 @@
-/*
- * file_storage.c -- File-backed USB Storage Gadget, for USB development
- *
- * Copyright (C) 2003-2008 Alan Stern
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions, and the following disclaimer,
- *    without modification.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. The names of the above-listed copyright holders may not be used
- *    to endorse or promote products derived from this software without
- *    specific prior written permission.
- *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") as published by the Free Software
- * Foundation, either version 2 of that License or (at your option) any
- * later version.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-/*
- * The File-backed Storage Gadget acts as a USB Mass Storage device,
- * appearing to the host as a disk drive or as a CD-ROM drive.  In addition
- * to providing an example of a genuinely useful gadget driver for a USB
- * device, it also illustrates a technique of double-buffering for increased
- * throughput.  Last but not least, it gives an easy way to probe the
- * behavior of the Mass Storage drivers in a USB host.
- *
- * Backing storage is provided by a regular file or a block device, specified
- * by the "file" module parameter.  Access can be limited to read-only by
- * setting the optional "ro" module parameter.  (For CD-ROM emulation,
- * access is always read-only.)  The gadget will indicate that it has
- * removable media if the optional "removable" module parameter is set.
- *
- * The gadget supports the Control-Bulk (CB), Control-Bulk-Interrupt (CBI),
- * and Bulk-Only (also known as Bulk-Bulk-Bulk or BBB) transports, selected
- * by the optional "transport" module parameter.  It also supports the
- * following protocols: RBC (0x01), ATAPI or SFF-8020i (0x02), QIC-157 (0c03),
- * UFI (0x04), SFF-8070i (0x05), and transparent SCSI (0x06), selected by
- * the optional "protocol" module parameter.  In addition, the default
- * Vendor ID, Product ID, release number and serial number can be overridden.
- *
- * There is support for multiple logical units (LUNs), each of which has
- * its own backing file.  The number of LUNs can be set using the optional
- * "luns" module parameter (anywhere from 1 to 8), and the corresponding
- * files are specified using comma-separated lists for "file" and "ro".
- * The default number of LUNs is taken from the number of "file" elements;
- * it is 1 if "file" is not given.  If "removable" is not set then a backing
- * file must be specified for each LUN.  If it is set, then an unspecified
- * or empty backing filename means the LUN's medium is not loaded.  Ideally
- * each LUN would be settable independently as a disk drive or a CD-ROM
- * drive, but currently all LUNs have to be the same type.  The CD-ROM
- * emulation includes a single data track and no audio tracks; hence there
- * need be only one backing file per LUN.
- *
- * Requirements are modest; only a bulk-in and a bulk-out endpoint are
- * needed (an interrupt-out endpoint is also needed for CBI).  The memory
- * requirement amounts to two 16K buffers, size configurable by a parameter.
- * Support is included for both full-speed and high-speed operation.
- *
- * Note that the driver is slightly non-portable in that it assumes a
- * single memory/DMA buffer will be useable for bulk-in, bulk-out, and
- * interrupt-in endpoints.  With most device controllers this isn't an
- * issue, but there may be some with hardware restrictions that prevent
- * a buffer from being used by more than one endpoint.
- *
- * Module options:
- *
- *     file=filename[,filename...]
- *                             Required if "removable" is not set, names of
- *                                     the files or block devices used for
- *                                     backing storage
- *     serial=HHHH...          Required serial number (string of hex chars)
- *     ro=b[,b...]             Default false, booleans for read-only access
- *     removable               Default false, boolean for removable media
- *     luns=N                  Default N = number of filenames, number of
- *                                     LUNs to support
- *     nofua=b[,b...]          Default false, booleans for ignore FUA flag
- *                                     in SCSI WRITE(10,12) commands
- *     stall                   Default determined according to the type of
- *                                     USB device controller (usually true),
- *                                     boolean to permit the driver to halt
- *                                     bulk endpoints
- *     cdrom                   Default false, boolean for whether to emulate
- *                                     a CD-ROM drive
- *     transport=XXX           Default BBB, transport name (CB, CBI, or BBB)
- *     protocol=YYY            Default SCSI, protocol name (RBC, 8020 or
- *                                     ATAPI, QIC, UFI, 8070, or SCSI;
- *                                     also 1 - 6)
- *     vendor=0xVVVV           Default 0x0525 (NetChip), USB Vendor ID
- *     product=0xPPPP          Default 0xa4a5 (FSG), USB Product ID
- *     release=0xRRRR          Override the USB release number (bcdDevice)
- *     buflen=N                Default N=16384, buffer size used (will be
- *                                     rounded down to a multiple of
- *                                     PAGE_CACHE_SIZE)
- *
- * If CONFIG_USB_FILE_STORAGE_TEST is not set, only the "file", "serial", "ro",
- * "removable", "luns", "nofua", "stall", and "cdrom" options are available;
- * default values are used for everything else.
- *
- * The pathnames of the backing files and the ro settings are available in
- * the attribute files "file", "nofua", and "ro" in the lun<n> subdirectory of
- * the gadget's sysfs directory.  If the "removable" option is set, writing to
- * these files will simulate ejecting/loading the medium (writing an empty
- * line means eject) and adjusting a write-enable tab.  Changes to the ro
- * setting are not allowed when the medium is loaded or if CD-ROM emulation
- * is being used.
- *
- * This gadget driver is heavily based on "Gadget Zero" by David Brownell.
- * The driver's SCSI command interface was based on the "Information
- * technology - Small Computer System Interface - 2" document from
- * X3T9.2 Project 375D, Revision 10L, 7-SEP-93, available at
- * <http://www.t10.org/ftp/t10/drafts/s2/s2-r10l.pdf>.  The single exception
- * is opcode 0x23 (READ FORMAT CAPACITIES), which was based on the
- * "Universal Serial Bus Mass Storage Class UFI Command Specification"
- * document, Revision 1.0, December 14, 1998, available at
- * <http://www.usb.org/developers/devclass_docs/usbmass-ufi10.pdf>.
- */
-
-
-/*
- *                             Driver Design
- *
- * The FSG driver is fairly straightforward.  There is a main kernel
- * thread that handles most of the work.  Interrupt routines field
- * callbacks from the controller driver: bulk- and interrupt-request
- * completion notifications, endpoint-0 events, and disconnect events.
- * Completion events are passed to the main thread by wakeup calls.  Many
- * ep0 requests are handled at interrupt time, but SetInterface,
- * SetConfiguration, and device reset requests are forwarded to the
- * thread in the form of "exceptions" using SIGUSR1 signals (since they
- * should interrupt any ongoing file I/O operations).
- *
- * The thread's main routine implements the standard command/data/status
- * parts of a SCSI interaction.  It and its subroutines are full of tests
- * for pending signals/exceptions -- all this polling is necessary since
- * the kernel has no setjmp/longjmp equivalents.  (Maybe this is an
- * indication that the driver really wants to be running in userspace.)
- * An important point is that so long as the thread is alive it keeps an
- * open reference to the backing file.  This will prevent unmounting
- * the backing file's underlying filesystem and could cause problems
- * during system shutdown, for example.  To prevent such problems, the
- * thread catches INT, TERM, and KILL signals and converts them into
- * an EXIT exception.
- *
- * In normal operation the main thread is started during the gadget's
- * fsg_bind() callback and stopped during fsg_unbind().  But it can also
- * exit when it receives a signal, and there's no point leaving the
- * gadget running when the thread is dead.  So just before the thread
- * exits, it deregisters the gadget driver.  This makes things a little
- * tricky: The driver is deregistered at two places, and the exiting
- * thread can indirectly call fsg_unbind() which in turn can tell the
- * thread to exit.  The first problem is resolved through the use of the
- * REGISTERED atomic bitflag; the driver will only be deregistered once.
- * The second problem is resolved by having fsg_unbind() check
- * fsg->state; it won't try to stop the thread if the state is already
- * FSG_STATE_TERMINATED.
- *
- * To provide maximum throughput, the driver uses a circular pipeline of
- * buffer heads (struct fsg_buffhd).  In principle the pipeline can be
- * arbitrarily long; in practice the benefits don't justify having more
- * than 2 stages (i.e., double buffering).  But it helps to think of the
- * pipeline as being a long one.  Each buffer head contains a bulk-in and
- * a bulk-out request pointer (since the buffer can be used for both
- * output and input -- directions always are given from the host's
- * point of view) as well as a pointer to the buffer and various state
- * variables.
- *
- * Use of the pipeline follows a simple protocol.  There is a variable
- * (fsg->next_buffhd_to_fill) that points to the next buffer head to use.
- * At any time that buffer head may still be in use from an earlier
- * request, so each buffer head has a state variable indicating whether
- * it is EMPTY, FULL, or BUSY.  Typical use involves waiting for the
- * buffer head to be EMPTY, filling the buffer either by file I/O or by
- * USB I/O (during which the buffer head is BUSY), and marking the buffer
- * head FULL when the I/O is complete.  Then the buffer will be emptied
- * (again possibly by USB I/O, during which it is marked BUSY) and
- * finally marked EMPTY again (possibly by a completion routine).
- *
- * A module parameter tells the driver to avoid stalling the bulk
- * endpoints wherever the transport specification allows.  This is
- * necessary for some UDCs like the SuperH, which cannot reliably clear a
- * halt on a bulk endpoint.  However, under certain circumstances the
- * Bulk-only specification requires a stall.  In such cases the driver
- * will halt the endpoint and set a flag indicating that it should clear
- * the halt in software during the next device reset.  Hopefully this
- * will permit everything to work correctly.  Furthermore, although the
- * specification allows the bulk-out endpoint to halt when the host sends
- * too much data, implementing this would cause an unavoidable race.
- * The driver will always use the "no-stall" approach for OUT transfers.
- *
- * One subtle point concerns sending status-stage responses for ep0
- * requests.  Some of these requests, such as device reset, can involve
- * interrupting an ongoing file I/O operation, which might take an
- * arbitrarily long time.  During that delay the host might give up on
- * the original ep0 request and issue a new one.  When that happens the
- * driver should not notify the host about completion of the original
- * request, as the host will no longer be waiting for it.  So the driver
- * assigns to each ep0 request a unique tag, and it keeps track of the
- * tag value of the request associated with a long-running exception
- * (device-reset, interface-change, or configuration-change).  When the
- * exception handler is finished, the status-stage response is submitted
- * only if the current ep0 request tag is equal to the exception request
- * tag.  Thus only the most recently received ep0 request will get a
- * status-stage response.
- *
- * Warning: This driver source file is too long.  It ought to be split up
- * into a header file plus about 3 separate .c files, to handle the details
- * of the Gadget, USB Mass Storage, and SCSI protocols.
- */
-
-
-/* #define VERBOSE_DEBUG */
-/* #define DUMP_MSGS */
-
-
-#include <linux/blkdev.h>
-#include <linux/completion.h>
-#include <linux/dcache.h>
-#include <linux/delay.h>
-#include <linux/device.h>
-#include <linux/fcntl.h>
-#include <linux/file.h>
-#include <linux/fs.h>
-#include <linux/kref.h>
-#include <linux/kthread.h>
-#include <linux/limits.h>
-#include <linux/module.h>
-#include <linux/rwsem.h>
-#include <linux/slab.h>
-#include <linux/spinlock.h>
-#include <linux/string.h>
-#include <linux/freezer.h>
-#include <linux/utsname.h>
-
-#include <linux/usb/composite.h>
-#include <linux/usb/ch9.h>
-#include <linux/usb/gadget.h>
-
-#include "gadget_chips.h"
-
-#define DRIVER_DESC            "File-backed Storage Gadget"
-#define DRIVER_NAME            "g_file_storage"
-#define DRIVER_VERSION         "1 September 2010"
-
-static       char fsg_string_manufacturer[64];
-static const char fsg_string_product[] = DRIVER_DESC;
-static const char fsg_string_config[] = "Self-powered";
-static const char fsg_string_interface[] = "Mass Storage";
-
-
-#include "storage_common.c"
-
-
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_AUTHOR("Alan Stern");
-MODULE_LICENSE("Dual BSD/GPL");
-
-/*
- * This driver assumes self-powered hardware and has no way for users to
- * trigger remote wakeup.  It uses autoconfiguration to select endpoints
- * and endpoint addresses.
- */
-
-
-/*-------------------------------------------------------------------------*/
-
-
-/* Encapsulate the module parameter settings */
-
-static struct {
-       char            *file[FSG_MAX_LUNS];
-       char            *serial;
-       bool            ro[FSG_MAX_LUNS];
-       bool            nofua[FSG_MAX_LUNS];
-       unsigned int    num_filenames;
-       unsigned int    num_ros;
-       unsigned int    num_nofuas;
-       unsigned int    nluns;
-
-       bool            removable;
-       bool            can_stall;
-       bool            cdrom;
-
-       char            *transport_parm;
-       char            *protocol_parm;
-       unsigned short  vendor;
-       unsigned short  product;
-       unsigned short  release;
-       unsigned int    buflen;
-
-       int             transport_type;
-       char            *transport_name;
-       int             protocol_type;
-       char            *protocol_name;
-
-} mod_data = {                                 // Default values
-       .transport_parm         = "BBB",
-       .protocol_parm          = "SCSI",
-       .removable              = 0,
-       .can_stall              = 1,
-       .cdrom                  = 0,
-       .vendor                 = FSG_VENDOR_ID,
-       .product                = FSG_PRODUCT_ID,
-       .release                = 0xffff,       // Use controller chip type
-       .buflen                 = 16384,
-       };
-
-
-module_param_array_named(file, mod_data.file, charp, &mod_data.num_filenames,
-               S_IRUGO);
-MODULE_PARM_DESC(file, "names of backing files or devices");
-
-module_param_named(serial, mod_data.serial, charp, S_IRUGO);
-MODULE_PARM_DESC(serial, "USB serial number");
-
-module_param_array_named(ro, mod_data.ro, bool, &mod_data.num_ros, S_IRUGO);
-MODULE_PARM_DESC(ro, "true to force read-only");
-
-module_param_array_named(nofua, mod_data.nofua, bool, &mod_data.num_nofuas,
-               S_IRUGO);
-MODULE_PARM_DESC(nofua, "true to ignore SCSI WRITE(10,12) FUA bit");
-
-module_param_named(luns, mod_data.nluns, uint, S_IRUGO);
-MODULE_PARM_DESC(luns, "number of LUNs");
-
-module_param_named(removable, mod_data.removable, bool, S_IRUGO);
-MODULE_PARM_DESC(removable, "true to simulate removable media");
-
-module_param_named(stall, mod_data.can_stall, bool, S_IRUGO);
-MODULE_PARM_DESC(stall, "false to prevent bulk stalls");
-
-module_param_named(cdrom, mod_data.cdrom, bool, S_IRUGO);
-MODULE_PARM_DESC(cdrom, "true to emulate cdrom instead of disk");
-
-/* In the non-TEST version, only the module parameters listed above
- * are available. */
-#ifdef CONFIG_USB_FILE_STORAGE_TEST
-
-module_param_named(transport, mod_data.transport_parm, charp, S_IRUGO);
-MODULE_PARM_DESC(transport, "type of transport (BBB, CBI, or CB)");
-
-module_param_named(protocol, mod_data.protocol_parm, charp, S_IRUGO);
-MODULE_PARM_DESC(protocol, "type of protocol (RBC, 8020, QIC, UFI, "
-               "8070, or SCSI)");
-
-module_param_named(vendor, mod_data.vendor, ushort, S_IRUGO);
-MODULE_PARM_DESC(vendor, "USB Vendor ID");
-
-module_param_named(product, mod_data.product, ushort, S_IRUGO);
-MODULE_PARM_DESC(product, "USB Product ID");
-
-module_param_named(release, mod_data.release, ushort, S_IRUGO);
-MODULE_PARM_DESC(release, "USB release number");
-
-module_param_named(buflen, mod_data.buflen, uint, S_IRUGO);
-MODULE_PARM_DESC(buflen, "I/O buffer size");
-
-#endif /* CONFIG_USB_FILE_STORAGE_TEST */
-
-
-/*
- * These definitions will permit the compiler to avoid generating code for
- * parts of the driver that aren't used in the non-TEST version.  Even gcc
- * can recognize when a test of a constant expression yields a dead code
- * path.
- */
-
-#ifdef CONFIG_USB_FILE_STORAGE_TEST
-
-#define transport_is_bbb()     (mod_data.transport_type == USB_PR_BULK)
-#define transport_is_cbi()     (mod_data.transport_type == USB_PR_CBI)
-#define protocol_is_scsi()     (mod_data.protocol_type == USB_SC_SCSI)
-
-#else
-
-#define transport_is_bbb()     1
-#define transport_is_cbi()     0
-#define protocol_is_scsi()     1
-
-#endif /* CONFIG_USB_FILE_STORAGE_TEST */
-
-
-/*-------------------------------------------------------------------------*/
-
-
-struct fsg_dev {
-       /* lock protects: state, all the req_busy's, and cbbuf_cmnd */
-       spinlock_t              lock;
-       struct usb_gadget       *gadget;
-
-       /* filesem protects: backing files in use */
-       struct rw_semaphore     filesem;
-
-       /* reference counting: wait until all LUNs are released */
-       struct kref             ref;
-
-       struct usb_ep           *ep0;           // Handy copy of gadget->ep0
-       struct usb_request      *ep0req;        // For control responses
-       unsigned int            ep0_req_tag;
-       const char              *ep0req_name;
-
-       struct usb_request      *intreq;        // For interrupt responses
-       int                     intreq_busy;
-       struct fsg_buffhd       *intr_buffhd;