]> git.kernelconcepts.de Git - karo-tx-linux.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

237 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 [moved from drivers/usb/host/alchemy-common.c with 100% similarity]
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/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");
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;
-
-       unsigned int            bulk_out_maxpacket;
-       enum fsg_state          state;          // For exception handling
-       unsigned int            exception_req_tag;
-
-       u8                      config, new_config;
-
-       unsigned int            running : 1;
-       unsigned int            bulk_in_enabled : 1;
-       unsigned int            bulk_out_enabled : 1;
-       unsigned int            intr_in_enabled : 1;
-       unsigned int            phase_error : 1;
-       unsigned int            short_packet_received : 1;
-       unsigned int            bad_lun_okay : 1;
-
-       unsigned long           atomic_bitflags;
-#define REGISTERED             0
-#define IGNORE_BULK_OUT                1
-#define SUSPENDED              2
-
-       struct usb_ep           *bulk_in;
-       struct usb_ep           *bulk_out;
-       struct usb_ep           *intr_in;
-
-       struct fsg_buffhd       *next_buffhd_to_fill;
-       struct fsg_buffhd       *next_buffhd_to_drain;
-
-       int                     thread_wakeup_needed;
-       struct completion       thread_notifier;
-       struct task_struct      *thread_task;
-
-       int                     cmnd_size;
-       u8                      cmnd[MAX_COMMAND_SIZE];
-       enum data_direction     data_dir;
-       u32                     data_size;
-       u32                     data_size_from_cmnd;
-       u32                     tag;
-       unsigned int            lun;
-       u32                     residue;
-       u32                     usb_amount_left;
-
-       /* The CB protocol offers no way for a host to know when a command
-        * has completed.  As a result the next command may arrive early,
-        * and we will still have to handle it.  For that reason we need
-        * a buffer to store new commands when using CB (or CBI, which
-        * does not oblige a host to wait for command completion either). */
-       int                     cbbuf_cmnd_size;
-       u8                      cbbuf_cmnd[MAX_COMMAND_SIZE];
-
-       unsigned int            nluns;
-       struct fsg_lun          *luns;
-       struct fsg_lun          *curlun;
-       /* Must be the last entry */
-       struct fsg_buffhd       buffhds[];
-};
-
-typedef void (*fsg_routine_t)(struct fsg_dev *);
-
-static int exception_in_progress(struct fsg_dev *fsg)
-{
-       return (fsg->state > FSG_STATE_IDLE);
-}
-
-/* Make bulk-out requests be divisible by the maxpacket size */
-static void set_bulk_out_req_length(struct fsg_dev *fsg,
-               struct fsg_buffhd *bh, unsigned int length)
-{
-       unsigned int    rem;
-
-       bh->bulk_out_intended_length = length;
-       rem = length % fsg->bulk_out_maxpacket;
-       if (rem > 0)
-               length += fsg->bulk_out_maxpacket - rem;
-       bh->outreq->length = length;
-}
-
-static struct fsg_dev                  *the_fsg;
-static struct usb_gadget_driver                fsg_driver;
-
-
-/*-------------------------------------------------------------------------*/
-
-static int fsg_set_halt(struct fsg_dev *fsg, struct usb_ep *ep)
-{
-       const char      *name;
-
-       if (ep == fsg->bulk_in)
-               name = "bulk-in";
-       else if (ep == fsg->bulk_out)
-               name = "bulk-out";
-       else
-               name = ep->name;
-       DBG(fsg, "%s set halt\n", name);
-       return usb_ep_set_halt(ep);
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * DESCRIPTORS ... most are static, but strings and (full) configuration
- * descriptors are built on demand.  Also the (static) config and interface
- * descriptors are adjusted during fsg_bind().
- */
-
-/* There is only one configuration. */
-#define        CONFIG_VALUE            1
-
-static struct usb_device_descriptor
-device_desc = {
-       .bLength =              sizeof device_desc,
-       .bDescriptorType =      USB_DT_DEVICE,
-
-       .bcdUSB =               cpu_to_le16(0x0200),
-       .bDeviceClass =         USB_CLASS_PER_INTERFACE,
-
-       /* The next three values can be overridden by module parameters */
-       .idVendor =             cpu_to_le16(FSG_VENDOR_ID),
-       .idProduct =            cpu_to_le16(FSG_PRODUCT_ID),
-       .bcdDevice =            cpu_to_le16(0xffff),
-
-       .iManufacturer =        FSG_STRING_MANUFACTURER,
-       .iProduct =             FSG_STRING_PRODUCT,
-       .iSerialNumber =        FSG_STRING_SERIAL,
-       .bNumConfigurations =   1,
-};
-
-static struct usb_config_descriptor
-config_desc = {
-       .bLength =              sizeof config_desc,
-       .bDescriptorType =      USB_DT_CONFIG,
-
-       /* wTotalLength computed by usb_gadget_config_buf() */
-       .bNumInterfaces =       1,
-       .bConfigurationValue =  CONFIG_VALUE,
-       .iConfiguration =       FSG_STRING_CONFIG,
-       .bmAttributes =         USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
-       .bMaxPower =            CONFIG_USB_GADGET_VBUS_DRAW / 2,
-};
-
-
-static struct usb_qualifier_descriptor
-dev_qualifier = {
-       .bLength =              sizeof dev_qualifier,
-       .bDescriptorType =      USB_DT_DEVICE_QUALIFIER,
-
-       .bcdUSB =               cpu_to_le16(0x0200),
-       .bDeviceClass =         USB_CLASS_PER_INTERFACE,
-
-       .bNumConfigurations =   1,
-};
-
-static int populate_bos(struct fsg_dev *fsg, u8 *buf)
-{
-       memcpy(buf, &fsg_bos_desc, USB_DT_BOS_SIZE);
-       buf += USB_DT_BOS_SIZE;
-
-       memcpy(buf, &fsg_ext_cap_desc, USB_DT_USB_EXT_CAP_SIZE);
-       buf += USB_DT_USB_EXT_CAP_SIZE;
-
-       memcpy(buf, &fsg_ss_cap_desc, USB_DT_USB_SS_CAP_SIZE);
-
-       return USB_DT_BOS_SIZE + USB_DT_USB_SS_CAP_SIZE
-               + USB_DT_USB_EXT_CAP_SIZE;
-}
-
-/*
- * Config descriptors must agree with the code that sets configurations
- * and with code managing interfaces and their altsettings.  They must
- * also handle different speeds and other-speed requests.
- */
-static int populate_config_buf(struct usb_gadget *gadget,
-               u8 *buf, u8 type, unsigned index)
-{
-       enum usb_device_speed                   speed = gadget->speed;
-       int                                     len;
-       const struct usb_descriptor_header      **function;
-
-       if (index > 0)
-               return -EINVAL;
-
-       if (gadget_is_dualspeed(gadget) && type == USB_DT_OTHER_SPEED_CONFIG)
-               speed = (USB_SPEED_FULL + USB_SPEED_HIGH) - speed;
-       function = gadget_is_dualspeed(gadget) && speed == USB_SPEED_HIGH
-               ? (const struct usb_descriptor_header **)fsg_hs_function
-               : (const struct usb_descriptor_header **)fsg_fs_function;
-
-       /* for now, don't advertise srp-only devices */
-       if (!gadget_is_otg(gadget))
-               function++;
-
-       len = usb_gadget_config_buf(&config_desc, buf, EP0_BUFSIZE, function);
-       ((struct usb_config_descriptor *) buf)->bDescriptorType = type;
-       return len;
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-/* These routines may be called in process context or in_irq */
-
-/* Caller must hold fsg->lock */
-static void wakeup_thread(struct fsg_dev *fsg)
-{
-       /* Tell the main thread that something has happened */
-       fsg->thread_wakeup_needed = 1;
-       if (fsg->thread_task)
-               wake_up_process(fsg->thread_task);
-}
-
-
-static void raise_exception(struct fsg_dev *fsg, enum fsg_state new_state)
-{
-       unsigned long           flags;
-
-       /* Do nothing if a higher-priority exception is already in progress.
-        * If a lower-or-equal priority exception is in progress, preempt it
-        * and notify the main thread by sending it a signal. */
-       spin_lock_irqsave(&fsg->lock, flags);
-       if (fsg->state <= new_state) {
-               fsg->exception_req_tag = fsg->ep0_req_tag;
-               fsg->state = new_state;
-               if (fsg->thread_task)
-                       send_sig_info(SIGUSR1, SEND_SIG_FORCED,
-                                       fsg->thread_task);
-       }
-       spin_unlock_irqrestore(&fsg->lock, flags);
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-/* The disconnect callback and ep0 routines.  These always run in_irq,
- * except that ep0_queue() is called in the main thread to acknowledge
- * completion of various requests: set config, set interface, and
- * Bulk-only device reset. */
-
-static void fsg_disconnect(struct usb_gadget *gadget)
-{
-       struct fsg_dev          *fsg = get_gadget_data(gadget);
-
-       DBG(fsg, "disconnect or port reset\n");
-       raise_exception(fsg, FSG_STATE_DISCONNECT);
-}
-
-
-static int ep0_queue(struct fsg_dev *fsg)
-{
-       int     rc;
-
-       rc = usb_ep_queue(fsg->ep0, fsg->ep0req, GFP_ATOMIC);
-       if (rc != 0 && rc != -ESHUTDOWN) {
-
-               /* We can't do much more than wait for a reset */
-               WARNING(fsg, "error in submission: %s --> %d\n",
-                               fsg->ep0->name, rc);
-       }
-       return rc;
-}
-
-static void ep0_complete(struct usb_ep *ep, struct usb_request *req)
-{
-       struct fsg_dev          *fsg = ep->driver_data;
-
-       if (req->actual > 0)
-               dump_msg(fsg, fsg->ep0req_name, req->buf, req->actual);
-       if (req->status || req->actual != req->length)
-               DBG(fsg, "%s --> %d, %u/%u\n", __func__,
-                               req->status, req->actual, req->length);
-       if (req->status == -ECONNRESET)         // Request was cancelled
-               usb_ep_fifo_flush(ep);
-
-       if (req->status == 0 && req->context)
-               ((fsg_routine_t) (req->context))(fsg);
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-/* Bulk and interrupt endpoint completion handlers.
- * These always run in_irq. */
-
-static void bulk_in_complete(struct usb_ep *ep, struct usb_request *req)
-{
-       struct fsg_dev          *fsg = ep->driver_data;
-       struct fsg_buffhd       *bh = req->context;
-
-       if (req->status || req->actual != req->length)
-               DBG(fsg, "%s --> %d, %u/%u\n", __func__,
-                               req->status, req->actual, req->length);
-       if (req->status == -ECONNRESET)         // Request was cancelled
-               usb_ep_fifo_flush(ep);
-
-       /* Hold the lock while we update the request and buffer states */
-       smp_wmb();
-       spin_lock(&fsg->lock);
-       bh->inreq_busy = 0;
-       bh->state = BUF_STATE_EMPTY;
-       wakeup_thread(fsg);
-       spin_unlock(&fsg->lock);
-}
-
-static void bulk_out_complete(struct usb_ep *ep, struct usb_request *req)
-{
-       struct fsg_dev          *fsg = ep->driver_data;
-       struct fsg_buffhd       *bh = req->context;
-
-       dump_msg(fsg, "bulk-out", req->buf, req->actual);
-       if (req->status || req->actual != bh->bulk_out_intended_length)
-               DBG(fsg, "%s --> %d, %u/%u\n", __func__,
-                               req->status, req->actual,
-                               bh->bulk_out_intended_length);
-       if (req->status == -ECONNRESET)         // Request was cancelled
-               usb_ep_fifo_flush(ep);
-
-       /* Hold the lock while we update the request and buffer states */
-       smp_wmb();
-       spin_lock(&fsg->lock);
-       bh->outreq_busy = 0;
-       bh->state = BUF_STATE_FULL;
-       wakeup_thread(fsg);
-       spin_unlock(&fsg->lock);
-}
-
-
-#ifdef CONFIG_USB_FILE_STORAGE_TEST
-static void intr_in_complete(struct usb_ep *ep, struct usb_request *req)
-{
-       struct fsg_dev          *fsg = ep->driver_data;
-       struct fsg_buffhd       *bh = req->context;
-
-       if (req->status || req->actual != req->length)
-               DBG(fsg, "%s --> %d, %u/%u\n", __func__,
-                               req->status, req->actual, req->length);
-       if (req->status == -ECONNRESET)         // Request was cancelled
-               usb_ep_fifo_flush(ep);
-
-       /* Hold the lock while we update the request and buffer states */
-       smp_wmb();
-       spin_lock(&fsg->lock);
-       fsg->intreq_busy = 0;
-       bh->state = BUF_STATE_EMPTY;
-       wakeup_thread(fsg);
-       spin_unlock(&fsg->lock);
-}
-
-#else
-static void intr_in_complete(struct usb_ep *ep, struct usb_request *req)
-{}
-#endif /* CONFIG_USB_FILE_STORAGE_TEST */
-
-
-/*-------------------------------------------------------------------------*/
-
-/* Ep0 class-specific handlers.  These always run in_irq. */
-
-#ifdef CONFIG_USB_FILE_STORAGE_TEST
-static void received_cbi_adsc(struct fsg_dev *fsg, struct fsg_buffhd *bh)
-{
-       struct usb_request      *req = fsg->ep0req;
-       static u8               cbi_reset_cmnd[6] = {
-                       SEND_DIAGNOSTIC, 4, 0xff, 0xff, 0xff, 0xff};
-
-       /* Error in command transfer? */
-       if (req->status || req->length != req->actual ||
-                       req->actual < 6 || req->actual > MAX_COMMAND_SIZE) {
-
-               /* Not all controllers allow a protocol stall after
-                * receiving control-out data, but we'll try anyway. */
-               fsg_set_halt(fsg, fsg->ep0);
-               return;                 // Wait for reset
-       }
-
-       /* Is it the special reset command? */
-       if (req->actual >= sizeof cbi_reset_cmnd &&
-                       memcmp(req->buf, cbi_reset_cmnd,
-                               sizeof cbi_reset_cmnd) == 0) {
-
-               /* Raise an exception to stop the current operation
-                * and reinitialize our state. */
-               DBG(fsg, "cbi reset request\n");
-               raise_exception(fsg, FSG_STATE_RESET);
-               return;
-       }
-
-       VDBG(fsg, "CB[I] accept device-specific command\n");
-       spin_lock(&fsg->lock);
-
-       /* Save the command for later */
-       if (fsg->cbbuf_cmnd_size)
-               WARNING(fsg, "CB[I] overwriting previous command\n");
-       fsg->cbbuf_cmnd_size = req->actual;
-       memcpy(fsg->cbbuf_cmnd, req->buf, fsg->cbbuf_cmnd_size);
-
-       wakeup_thread(fsg);
-       spin_unlock(&fsg->lock);
-}
-
-#else
-static void received_cbi_adsc(struct fsg_dev *fsg, struct fsg_buffhd *bh)
-{}
-#endif /* CONFIG_USB_FILE_STORAGE_TEST */
-
-
-static int class_setup_req(struct fsg_dev *fsg,
-               const struct usb_ctrlrequest *ctrl)
-{
-       struct usb_request      *req = fsg->ep0req;
-       int                     value = -EOPNOTSUPP;
-       u16                     w_index = le16_to_cpu(ctrl->wIndex);
-       u16                     w_value = le16_to_cpu(ctrl->wValue);
-       u16                     w_length = le16_to_cpu(ctrl->wLength);
-
-       if (!fsg->config)
-               return value;
-
-       /* Handle Bulk-only class-specific requests */
-       if (transport_is_bbb()) {
-               switch (ctrl->bRequest) {
-
-               case US_BULK_RESET_REQUEST:
-                       if (ctrl->bRequestType != (USB_DIR_OUT |
-                                       USB_TYPE_CLASS | USB_RECIP_INTERFACE))
-                               break;
-                       if (w_index != 0 || w_value != 0 || w_length != 0) {
-                               value = -EDOM;
-                               break;
-                       }
-
-                       /* Raise an exception to stop the current operation
-                        * and reinitialize our state. */
-                       DBG(fsg, "bulk reset request\n");
-                       raise_exception(fsg, FSG_STATE_RESET);
-                       value = DELAYED_STATUS;
-                       break;
-
-               case US_BULK_GET_MAX_LUN:
-                       if (ctrl->bRequestType != (USB_DIR_IN |
-                                       USB_TYPE_CLASS | USB_RECIP_INTERFACE))
-                               break;
-                       if (w_index != 0 || w_value != 0 || w_length != 1) {
-                               value = -EDOM;
-                               break;
-                       }
-                       VDBG(fsg, "get max LUN\n");
-                       *(u8 *) req->buf = fsg->nluns - 1;
-                       value = 1;
-                       break;
-               }
-       }
-
-       /* Handle CBI class-specific requests */
-       else {
-               switch (ctrl->bRequest) {
-
-               case USB_CBI_ADSC_REQUEST:
-                       if (ctrl->bRequestType != (USB_DIR_OUT |
-                                       USB_TYPE_CLASS | USB_RECIP_INTERFACE))
-                               break;
-                       if (w_index != 0 || w_value != 0) {
-                               value = -EDOM;
-                               break;
-                       }
-                       if (w_length > MAX_COMMAND_SIZE) {
-                               value = -EOVERFLOW;
-                               break;
-                       }
-                       value = w_length;
-                       fsg->ep0req->context = received_cbi_adsc;
-                       break;
-               }
-       }
-
-       if (value == -EOPNOTSUPP)
-               VDBG(fsg,
-                       "unknown class-specific control req "
-                       "%02x.%02x v%04x i%04x l%u\n",
-                       ctrl->bRequestType, ctrl->bRequest,
-                       le16_to_cpu(ctrl->wValue), w_index, w_length);
-       return value;
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-/* Ep0 standard request handlers.  These always run in_irq. */
-
-static int standard_setup_req(struct fsg_dev *fsg,
-               const struct usb_ctrlrequest *ctrl)
-{
-       struct usb_request      *req = fsg->ep0req;
-       int                     value = -EOPNOTSUPP;
-       u16                     w_index = le16_to_cpu(ctrl->wIndex);
-       u16                     w_value = le16_to_cpu(ctrl->wValue);
-
-       /* Usually this just stores reply data in the pre-allocated ep0 buffer,
-        * but config change events will also reconfigure hardware. */
-       switch (ctrl->bRequest) {
-
-       case USB_REQ_GET_DESCRIPTOR:
-               if (ctrl->bRequestType != (USB_DIR_IN | USB_TYPE_STANDARD |
-                               USB_RECIP_DEVICE))
-                       break;
-               switch (w_value >> 8) {
-
-               case USB_DT_DEVICE:
-                       VDBG(fsg, "get device descriptor\n");
-                       device_desc.bMaxPacketSize0 = fsg->ep0->maxpacket;
-                       value = sizeof device_desc;
-                       memcpy(req->buf, &device_desc, value);
-                       break;
-               case USB_DT_DEVICE_QUALIFIER:
-                       VDBG(fsg, "get device qualifier\n");
-                       if (!gadget_is_dualspeed(fsg->gadget) ||
-                                       fsg->gadget->speed == USB_SPEED_SUPER)
-                               break;
-                       /*
-                        * Assume ep0 uses the same maxpacket value for both
-                        * speeds
-                        */
-                       dev_qualifier.bMaxPacketSize0 = fsg->ep0->maxpacket;
-                       value = sizeof dev_qualifier;
-                       memcpy(req->buf, &dev_qualifier, value);
-                       break;
-
-               case USB_DT_OTHER_SPEED_CONFIG:
-                       VDBG(fsg, "get other-speed config descriptor\n");
-                       if (!gadget_is_dualspeed(fsg->gadget) ||
-                                       fsg->gadget->speed == USB_SPEED_SUPER)
-                               break;
-                       goto get_config;
-               case USB_DT_CONFIG:
-                       VDBG(fsg, "get configuration descriptor\n");
-get_config:
-                       value = populate_config_buf(fsg->gadget,
-                                       req->buf,
-                                       w_value >> 8,
-                                       w_value & 0xff);
-                       break;
-
-               case USB_DT_STRING:
-                       VDBG(fsg, "get string descriptor\n");
-
-                       /* wIndex == language code */
-                       value = usb_gadget_get_string(&fsg_stringtab,
-                                       w_value & 0xff, req->buf);
-                       break;
-
-               case USB_DT_BOS:
-                       VDBG(fsg, "get bos descriptor\n");
-
-                       if (gadget_is_superspeed(fsg->gadget))
-                               value = populate_bos(fsg, req->buf);
-                       break;
-               }
-
-               break;
-
-       /* One config, two speeds */
-       case USB_REQ_SET_CONFIGURATION:
-               if (ctrl->bRequestType != (USB_DIR_OUT | USB_TYPE_STANDARD |
-                               USB_RECIP_DEVICE))
-                       break;
-               VDBG(fsg, "set configuration\n");
-               if (w_value == CONFIG_VALUE || w_value == 0) {
-                       fsg->new_config = w_value;
-
-                       /* Raise an exception to wipe out previous transaction
-                        * state (queued bufs, etc) and set the new config. */
-                       raise_exception(fsg, FSG_STATE_CONFIG_CHANGE);
-                       value = DELAYED_STATUS;
-               }
-               break;
-       case USB_REQ_GET_CONFIGURATION:
-               if (ctrl->bRequestType != (USB_DIR_IN | USB_TYPE_STANDARD |
-                               USB_RECIP_DEVICE))
-                       break;
-               VDBG(fsg, "get configuration\n");
-               *(u8 *) req->buf = fsg->config;
-               value = 1;
-               break;
-
-       case USB_REQ_SET_INTERFACE:
-               if (ctrl->bRequestType != (USB_DIR_OUT| USB_TYPE_STANDARD |
-                               USB_RECIP_INTERFACE))
-                       break;
-               if (fsg->config && w_index == 0) {
-
-                       /* Raise an exception to wipe out previous transaction
-                        * state (queued bufs, etc) and install the new
-                        * interface altsetting. */
-                       raise_exception(fsg, FSG_STATE_INTERFACE_CHANGE);
-                       value = DELAYED_STATUS;
-               }
-               break;
-       case USB_REQ_GET_INTERFACE:
-               if (ctrl->bRequestType != (USB_DIR_IN | USB_TYPE_STANDARD |
-                               USB_RECIP_INTERFACE))
-                       break;
-               if (!fsg->config)
-                       break;
-               if (w_index != 0) {
-                       value = -EDOM;
-                       break;
-               }
-               VDBG(fsg, "get interface\n");
-               *(u8 *) req->buf = 0;
-               value = 1;
-               break;
-
-       default:
-               VDBG(fsg,
-                       "unknown control req %02x.%02x v%04x i%04x l%u\n",
-                       ctrl->bRequestType, ctrl->bRequest,
-                       w_value, w_index, le16_to_cpu(ctrl->wLength));
-       }
-
-       return value;
-}
-
-
-static int fsg_setup(struct usb_gadget *gadget,
-               const struct usb_ctrlrequest *ctrl)
-{
-       struct fsg_dev          *fsg = get_gadget_data(gadget);
-       int                     rc;
-       int                     w_length = le16_to_cpu(ctrl->wLength);
-
-       ++fsg->ep0_req_tag;             // Record arrival of a new request
-       fsg->ep0req->context = NULL;
-       fsg->ep0req->length = 0;
-       dump_msg(fsg, "ep0-setup", (u8 *) ctrl, sizeof(*ctrl));
-
-       if ((ctrl->bRequestType & USB_TYPE_MASK) == USB_TYPE_CLASS)
-               rc = class_setup_req(fsg, ctrl);
-       else
-               rc = standard_setup_req(fsg, ctrl);
-
-       /* Respond with data/status or defer until later? */
-       if (rc >= 0 && rc != DELAYED_STATUS) {
-               rc = min(rc, w_length);
-               fsg->ep0req->length = rc;
-               fsg->ep0req->zero = rc < w_length;
-               fsg->ep0req_name = (ctrl->bRequestType & USB_DIR_IN ?
-                               "ep0-in" : "ep0-out");
-               rc = ep0_queue(fsg);
-       }
-
-       /* Device either stalls (rc < 0) or reports success */
-       return rc;
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-/* All the following routines run in process context */
-
-
-/* Use this for bulk or interrupt transfers, not ep0 */
-static void start_transfer(struct fsg_dev *fsg, struct usb_ep *ep,
-               struct usb_request *req, int *pbusy,
-               enum fsg_buffer_state *state)
-{
-       int     rc;
-
-       if (ep == fsg->bulk_in)
-               dump_msg(fsg, "bulk-in", req->buf, req->length);
-       else if (ep == fsg->intr_in)
-               dump_msg(fsg, "intr-in", req->buf, req->length);
-
-       spin_lock_irq(&fsg->lock);
-       *pbusy = 1;
-       *state = BUF_STATE_BUSY;
-       spin_unlock_irq(&fsg->lock);
-       rc = usb_ep_queue(ep, req, GFP_KERNEL);
-       if (rc != 0) {
-               *pbusy = 0;
-               *state = BUF_STATE_EMPTY;
-
-               /* We can't do much more than wait for a reset */
-
-               /* Note: currently the net2280 driver fails zero-length
-                * submissions if DMA is enabled. */
-               if (rc != -ESHUTDOWN && !(rc == -EOPNOTSUPP &&
-                                               req->length == 0))
-                       WARNING(fsg, "error in submission: %s --> %d\n",
-                                       ep->name, rc);
-       }
-}
-
-
-static int sleep_thread(struct fsg_dev *fsg)
-{
-       int     rc = 0;
-
-       /* Wait until a signal arrives or we are woken up */
-       for (;;) {
-               try_to_freeze();
-               set_current_state(TASK_INTERRUPTIBLE);
-               if (signal_pending(current)) {
-                       rc = -EINTR;
-                       break;
-               }
-               if (fsg->thread_wakeup_needed)
-                       break;
-               schedule();
-       }
-       __set_current_state(TASK_RUNNING);
-       fsg->thread_wakeup_needed = 0;
-       return rc;
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-static int do_read(struct fsg_dev *fsg)
-{
-       struct fsg_lun          *curlun = fsg->curlun;
-       u32                     lba;
-       struct fsg_buffhd       *bh;
-       int                     rc;
-       u32                     amount_left;
-       loff_t                  file_offset, file_offset_tmp;
-       unsigned int            amount;
-       ssize_t                 nread;
-
-       /* Get the starting Logical Block Address and check that it's
-        * not too big */
-       if (fsg->cmnd[0] == READ_6)
-               lba = get_unaligned_be24(&fsg->cmnd[1]);
-       else {
-               lba = get_unaligned_be32(&fsg->cmnd[2]);
-
-               /* We allow DPO (Disable Page Out = don't save data in the
-                * cache) and FUA (Force Unit Access = don't read from the
-                * cache), but we don't implement them. */
-               if ((fsg->cmnd[1] & ~0x18) != 0) {
-                       curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
-                       return -EINVAL;
-               }
-       }
-       if (lba >= curlun->num_sectors) {
-               curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
-               return -EINVAL;
-       }
-       file_offset = ((loff_t) lba) << curlun->blkbits;
-
-       /* Carry out the file reads */
-       amount_left = fsg->data_size_from_cmnd;
-       if (unlikely(amount_left == 0))
-               return -EIO;            // No default reply
-
-       for (;;) {
-
-               /* Figure out how much we need to read:
-                * Try to read the remaining amount.
-                * But don't read more than the buffer size.
-                * And don't try to read past the end of the file.
-                */
-               amount = min((unsigned int) amount_left, mod_data.buflen);
-               amount = min((loff_t) amount,
-                               curlun->file_length - file_offset);
-
-               /* Wait for the next buffer to become available */
-               bh = fsg->next_buffhd_to_fill;
-               while (bh->state != BUF_STATE_EMPTY) {
-                       rc = sleep_thread(fsg);
-                       if (rc)
-                               return rc;
-               }
-
-               /* If we were asked to read past the end of file,
-                * end with an empty buffer. */
-               if (amount == 0) {
-                       curlun->sense_data =
-                                       SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
-                       curlun->sense_data_info = file_offset >> curlun->blkbits;
-                       curlun->info_valid = 1;
-                       bh->inreq->length = 0;
-                       bh->state = BUF_STATE_FULL;
-                       break;
-               }
-
-               /* Perform the read */
-               file_offset_tmp = file_offset;
-               nread = vfs_read(curlun->filp,
-                               (char __user *) bh->buf,
-                               amount, &file_offset_tmp);
-               VLDBG(curlun, "file read %u @ %llu -> %d\n", amount,
-                               (unsigned long long) file_offset,
-                               (int) nread);
-               if (signal_pending(current))
-                       return -EINTR;
-
-               if (nread < 0) {
-                       LDBG(curlun, "error in file read: %d\n",
-                                       (int) nread);
-                       nread = 0;
-               } else if (nread < amount) {
-                       LDBG(curlun, "partial file read: %d/%u\n",
-                                       (int) nread, amount);
-                       nread = round_down(nread, curlun->blksize);
-               }
-               file_offset  += nread;
-               amount_left  -= nread;
-               fsg->residue -= nread;
-
-               /* Except at the end of the transfer, nread will be
-                * equal to the buffer size, which is divisible by the
-                * bulk-in maxpacket size.
-                */
-               bh->inreq->length = nread;
-               bh->state = BUF_STATE_FULL;
-
-               /* If an error occurred, report it and its position */
-               if (nread < amount) {
-                       curlun->sense_data = SS_UNRECOVERED_READ_ERROR;
-                       curlun->sense_data_info = file_offset >> curlun->blkbits;
-                       curlun->info_valid = 1;
-                       break;
-               }
-
-               if (amount_left == 0)
-                       break;          // No more left to read
-
-               /* Send this buffer and go read some more */
-               bh->inreq->zero = 0;
-               start_transfer(fsg, fsg->bulk_in, bh->inreq,
-                               &bh->inreq_busy, &bh->state);
-               fsg->next_buffhd_to_fill = bh->next;
-       }
-
-       return -EIO;            // No default reply
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-static int do_write(struct fsg_dev *fsg)
-{
-       struct fsg_lun          *curlun = fsg->curlun;
-       u32                     lba;
-       struct fsg_buffhd       *bh;
-       int                     get_some_more;
-       u32                     amount_left_to_req, amount_left_to_write;
-       loff_t                  usb_offset, file_offset, file_offset_tmp;
-       unsigned int            amount;
-       ssize_t                 nwritten;
-       int                     rc;
-
-       if (curlun->ro) {
-               curlun->sense_data = SS_WRITE_PROTECTED;
-               return -EINVAL;
-       }
-       spin_lock(&curlun->filp->f_lock);
-       curlun->filp->f_flags &= ~O_SYNC;       // Default is not to wait
-       spin_unlock(&curlun->filp->f_lock);
-
-       /* Get the starting Logical Block Address and check that it's
-        * not too big */
-       if (fsg->cmnd[0] == WRITE_6)
-               lba = get_unaligned_be24(&fsg->cmnd[1]);
-       else {
-               lba = get_unaligned_be32(&fsg->cmnd[2]);
-
-               /* We allow DPO (Disable Page Out = don't save data in the
-                * cache) and FUA (Force Unit Access = write directly to the
-                * medium).  We don't implement DPO; we implement FUA by
-                * performing synchronous output. */
-               if ((fsg->cmnd[1] & ~0x18) != 0) {
-                       curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
-                       return -EINVAL;
-               }
-               /* FUA */
-               if (!curlun->nofua && (fsg->cmnd[1] & 0x08)) {
-                       spin_lock(&curlun->filp->f_lock);
-                       curlun->filp->f_flags |= O_DSYNC;
-                       spin_unlock(&curlun->filp->f_lock);
-               }
-       }
-       if (lba >= curlun->num_sectors) {
-               curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
-               return -EINVAL;
-       }
-
-       /* Carry out the file writes */
-       get_some_more = 1;
-       file_offset = usb_offset = ((loff_t) lba) << curlun->blkbits;
-       amount_left_to_req = amount_left_to_write = fsg->data_size_from_cmnd;
-
-       while (amount_left_to_write > 0) {
-
-               /* Queue a request for more data from the host */
-               bh = fsg->next_buffhd_to_fill;
-               if (bh->state == BUF_STATE_EMPTY && get_some_more) {
-
-                       /* Figure out how much we want to get:
-                        * Try to get the remaining amount,
-                        * but not more than the buffer size.
-                        */
-                       amount = min(amount_left_to_req, mod_data.buflen);
-
-                       /* Beyond the end of the backing file? */
-                       if (usb_offset >= curlun->file_length) {
-                               get_some_more = 0;
-                               curlun->sense_data =
-                                       SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
-                               curlun->sense_data_info = usb_offset >> curlun->blkbits;
-                               curlun->info_valid = 1;
-                               continue;
-                       }
-
-                       /* Get the next buffer */
-                       usb_offset += amount;
-                       fsg->usb_amount_left -= amount;
-                       amount_left_to_req -= amount;
-                       if (amount_left_to_req == 0)
-                               get_some_more = 0;
-
-                       /* Except at the end of the transfer, amount will be
-                        * equal to the buffer size, which is divisible by
-                        * the bulk-out maxpacket size.
-                        */
-                       set_bulk_out_req_length(fsg, bh, amount);
-                       start_transfer(fsg, fsg->bulk_out, bh->outreq,
-                                       &bh->outreq_busy, &bh->state);
-                       fsg->next_buffhd_to_fill = bh->next;
-                       continue;
-               }
-
-               /* Write the received data to the backing file */
-               bh = fsg->next_buffhd_to_drain;
-               if (bh->state == BUF_STATE_EMPTY && !get_some_more)
-                       break;                  // We stopped early
-               if (bh->state == BUF_STATE_FULL) {
-                       smp_rmb();
-                       fsg->next_buffhd_to_drain = bh->next;
-                       bh->state = BUF_STATE_EMPTY;
-
-                       /* Did something go wrong with the transfer? */
-                       if (bh->outreq->status != 0) {
-                               curlun->sense_data = SS_COMMUNICATION_FAILURE;
-                               curlun->sense_data_info = file_offset >> curlun->blkbits;
-                               curlun->info_valid = 1;
-                               break;
-                       }
-
-                       amount = bh->outreq->actual;
-                       if (curlun->file_length - file_offset < amount) {
-                               LERROR(curlun,
-       "write %u @ %llu beyond end %llu\n",
-       amount, (unsigned long long) file_offset,
-       (unsigned long long) curlun->file_length);
-                               amount = curlun->file_length - file_offset;
-                       }
-
-                       /* Don't accept excess data.  The spec doesn't say
-                        * what to do in this case.  We'll ignore the error.
-                        */
-                       amount = min(amount, bh->bulk_out_intended_length);
-
-                       /* Don't write a partial block */
-                       amount = round_down(amount, curlun->blksize);
-                       if (amount == 0)
-                               goto empty_write;
-
-                       /* Perform the write */
-                       file_offset_tmp = file_offset;
-                       nwritten = vfs_write(curlun->filp,
-                                       (char __user *) bh->buf,
-                                       amount, &file_offset_tmp);
-                       VLDBG(curlun, "file write %u @ %llu -> %d\n", amount,
-                                       (unsigned long long) file_offset,
-                                       (int) nwritten);
-                       if (signal_pending(current))
-                               return -EINTR;          // Interrupted!
-
-                       if (nwritten < 0) {
-                               LDBG(curlun, "error in file write: %d\n",
-                                               (int) nwritten);
-                               nwritten = 0;
-                       } else if (nwritten < amount) {
-                               LDBG(curlun, "partial file write: %d/%u\n",
-                                               (int) nwritten, amount);
-                               nwritten = round_down(nwritten, curlun->blksize);
-                       }
-                       file_offset += nwritten;
-                       amount_left_to_write -= nwritten;
-                       fsg->residue -= nwritten;
-
-                       /* If an error occurred, report it and its position */
-                       if (nwritten < amount) {
-                               curlun->sense_data = SS_WRITE_ERROR;
-                               curlun->sense_data_info = file_offset >> curlun->blkbits;
-                               curlun->info_valid = 1;
-                               break;
-                       }
-
- empty_write:
-                       /* Did the host decide to stop early? */
-                       if (bh->outreq->actual < bh->bulk_out_intended_length) {
-                               fsg->short_packet_received = 1;
-                               break;
-                       }
-                       continue;
-               }
-
-               /* Wait for something to happen */
-               rc = sleep_thread(fsg);
-               if (rc)
-                       return rc;
-       }
-
-       return -EIO;            // No default reply
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-static int do_synchronize_cache(struct fsg_dev *fsg)
-{
-       struct fsg_lun  *curlun = fsg->curlun;
-       int             rc;
-
-       /* We ignore the requested LBA and write out all file's
-        * dirty data buffers. */
-       rc = fsg_lun_fsync_sub(curlun);
-       if (rc)
-               curlun->sense_data = SS_WRITE_ERROR;
-       return 0;
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-static void invalidate_sub(struct fsg_lun *curlun)
-{
-       struct file     *filp = curlun->filp;
-       struct inode    *inode = filp->f_path.dentry->d_inode;
-       unsigned long   rc;
-
-       rc = invalidate_mapping_pages(inode->i_mapping, 0, -1);
-       VLDBG(curlun, "invalidate_mapping_pages -> %ld\n", rc);
-}
-
-static int do_verify(struct fsg_dev *fsg)
-{
-       struct fsg_lun          *curlun = fsg->curlun;
-       u32                     lba;
-       u32                     verification_length;
-       struct fsg_buffhd       *bh = fsg->next_buffhd_to_fill;
-       loff_t                  file_offset, file_offset_tmp;
-       u32                     amount_left;
-       unsigned int            amount;
-       ssize_t                 nread;
-
-       /* Get the starting Logical Block Address and check that it's
-        * not too big */
-       lba = get_unaligned_be32(&fsg->cmnd[2]);
-       if (lba >= curlun->num_sectors) {
-               curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
-               return -EINVAL;
-       }
-
-       /* We allow DPO (Disable Page Out = don't save data in the
-        * cache) but we don't implement it. */
-       if ((fsg->cmnd[1] & ~0x10) != 0) {
-               curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
-               return -EINVAL;
-       }
-
-       verification_length = get_unaligned_be16(&fsg->cmnd[7]);
-       if (unlikely(verification_length == 0))
-               return -EIO;            // No default reply
-
-       /* Prepare to carry out the file verify */
-       amount_left = verification_length << curlun->blkbits;
-       file_offset = ((loff_t) lba) << curlun->blkbits;
-
-       /* Write out all the dirty buffers before invalidating them */
-       fsg_lun_fsync_sub(curlun);
-       if (signal_pending(current))
-               return -EINTR;
-
-       invalidate_sub(curlun);
-       if (signal_pending(current))
-               return -EINTR;
-
-       /* Just try to read the requested blocks */
-       while (amount_left > 0) {
-
-               /* Figure out how much we need to read:
-                * Try to read the remaining amount, but not more than
-                * the buffer size.
-                * And don't try to read past the end of the file.
-                */
-               amount = min((unsigned int) amount_left, mod_data.buflen);
-               amount = min((loff_t) amount,
-                               curlun->file_length - file_offset);
-               if (amount == 0) {
-                       curlun->sense_data =
-                                       SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
-                       curlun->sense_data_info = file_offset >> curlun->blkbits;
-                       curlun->info_valid = 1;
-                       break;
-               }
-
-               /* Perform the read */
-               file_offset_tmp = file_offset;
-               nread = vfs_read(curlun->filp,
-                               (char __user *) bh->buf,
-                               amount, &file_offset_tmp);
-               VLDBG(curlun, "file read %u @ %llu -> %d\n", amount,
-                               (unsigned long long) file_offset,
-                               (int) nread);
-               if (signal_pending(current))
-                       return -EINTR;
-
-               if (nread < 0) {
-                       LDBG(curlun, "error in file verify: %d\n",
-                                       (int) nread);
-                       nread = 0;
-               } else if (nread < amount) {
-                       LDBG(curlun, "partial file verify: %d/%u\n",
-                                       (int) nread, amount);
-                       nread = round_down(nread, curlun->blksize);
-               }
-               if (nread == 0) {
-                       curlun->sense_data = SS_UNRECOVERED_READ_ERROR;
-                       curlun->sense_data_info = file_offset >> curlun->blkbits;
-                       curlun->info_valid = 1;
-                       break;
-               }
-               file_offset += nread;
-               amount_left -= nread;
-       }
-       return 0;
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-static int do_inquiry(struct fsg_dev *fsg, struct fsg_buffhd *bh)
-{
-       u8      *buf = (u8 *) bh->buf;
-
-       static char vendor_id[] = "Linux   ";
-       static char product_disk_id[] = "File-Stor Gadget";
-       static char product_cdrom_id[] = "File-CD Gadget  ";
-
-       if (!fsg->curlun) {             // Unsupported LUNs are okay
-               fsg->bad_lun_okay = 1;
-               memset(buf, 0, 36);
-               buf[0] = 0x7f;          // Unsupported, no device-type
-               buf[4] = 31;            // Additional length
-               return 36;
-       }
-
-       memset(buf, 0, 8);
-       buf[0] = (mod_data.cdrom ? TYPE_ROM : TYPE_DISK);
-       if (mod_data.removable)
-               buf[1] = 0x80;
-       buf[2] = 2;             // ANSI SCSI level 2
-       buf[3] = 2;             // SCSI-2 INQUIRY data format
-       buf[4] = 31;            // Additional length
-                               // No special options
-       sprintf(buf + 8, "%-8s%-16s%04x", vendor_id,
-                       (mod_data.cdrom ? product_cdrom_id :
-                               product_disk_id),
-                       mod_data.release);
-       return 36;
-}
-
-
-static int do_request_sense(struct fsg_dev *fsg, struct fsg_buffhd *bh)
-{
-       struct fsg_lun  *curlun = fsg->curlun;
-       u8              *buf = (u8 *) bh->buf;
-       u32             sd, sdinfo;
-       int             valid;
-
-       /*
-        * From the SCSI-2 spec., section 7.9 (Unit attention condition):
-        *
-        * If a REQUEST SENSE command is received from an initiator
-        * with a pending unit attention condition (before the target
-        * generates the contingent allegiance condition), then the
-        * target shall either:
-        *   a) report any pending sense data and preserve the unit
-        *      attention condition on the logical unit, or,
-        *   b) report the unit attention condition, may discard any
-        *      pending sense data, and clear the unit attention
-        *      condition on the logical unit for that initiator.
-        *
-        * FSG normally uses option a); enable this code to use option b).
-        */
-#if 0
-       if (curlun && curlun->unit_attention_data != SS_NO_SENSE) {
-               curlun->sense_data = curlun->unit_attention_data;
-               curlun->unit_attention_data = SS_NO_SENSE;
-       }
-#endif
-
-       if (!curlun) {          // Unsupported LUNs are okay
-               fsg->bad_lun_okay = 1;
-               sd = SS_LOGICAL_UNIT_NOT_SUPPORTED;
-               sdinfo = 0;
-               valid = 0;
-       } else {
-               sd = curlun->sense_data;
-               sdinfo = curlun->sense_data_info;
-               valid = curlun->info_valid << 7;
-               curlun->sense_data = SS_NO_SENSE;
-               curlun->sense_data_info = 0;
-               curlun->info_valid = 0;
-       }
-
-       memset(buf, 0, 18);
-       buf[0] = valid | 0x70;                  // Valid, current error
-       buf[2] = SK(sd);
-       put_unaligned_be32(sdinfo, &buf[3]);    /* Sense information */
-       buf[7] = 18 - 8;                        // Additional sense length
-       buf[12] = ASC(sd);
-       buf[13] = ASCQ(sd);
-       return 18;
-}
-
-
-static int do_read_capacity(struct fsg_dev *fsg, struct fsg_buffhd *bh)
-{
-       struct fsg_lun  *curlun = fsg->curlun;
-       u32             lba = get_unaligned_be32(&fsg->cmnd[2]);
-       int             pmi = fsg->cmnd[8];
-       u8              *buf = (u8 *) bh->buf;
-
-       /* Check the PMI and LBA fields */
-       if (pmi > 1 || (pmi == 0 && lba != 0)) {
-               curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
-               return -EINVAL;
-       }
-
-       put_unaligned_be32(curlun->num_sectors - 1, &buf[0]);
-                                               /* Max logical block */
-       put_unaligned_be32(curlun->blksize, &buf[4]);   /* Block length */
-       return 8;
-}
-
-
-static int do_read_header(struct fsg_dev *fsg, struct fsg_buffhd *bh)
-{
-       struct fsg_lun  *curlun = fsg->curlun;
-       int             msf = fsg->cmnd[1] & 0x02;
-       u32             lba = get_unaligned_be32(&fsg->cmnd[2]);
-       u8              *buf = (u8 *) bh->buf;
-
-       if ((fsg->cmnd[1] & ~0x02) != 0) {              /* Mask away MSF */
-               curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
-               return -EINVAL;
-       }
-       if (lba >= curlun->num_sectors) {
-               curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
-               return -EINVAL;
-       }
-
-       memset(buf, 0, 8);
-       buf[0] = 0x01;          /* 2048 bytes of user data, rest is EC */
-       store_cdrom_address(&buf[4], msf, lba);
-       return 8;
-}
-
-
-static int do_read_toc(struct fsg_dev *fsg, struct fsg_buffhd *bh)
-{
-       struct fsg_lun  *curlun = fsg->curlun;
-       int             msf = fsg->cmnd[1] & 0x02;
-       int             start_track = fsg->cmnd[6];
-       u8              *buf = (u8 *) bh->buf;
-
-       if ((fsg->cmnd[1] & ~0x02) != 0 ||              /* Mask away MSF */
-                       start_track > 1) {
-               curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
-               return -EINVAL;
-       }
-
-       memset(buf, 0, 20);
-       buf[1] = (20-2);                /* TOC data length */
-       buf[2] = 1;                     /* First track number */
-       buf[3] = 1;                     /* Last track number */
-       buf[5] = 0x16;                  /* Data track, copying allowed */
-       buf[6] = 0x01;                  /* Only track is number 1 */
-       store_cdrom_address(&buf[8], msf, 0);
-
-       buf[13] = 0x16;                 /* Lead-out track is data */
-       buf[14] = 0xAA;                 /* Lead-out track number */
-       store_cdrom_address(&buf[16], msf, curlun->num_sectors);
-       return 20;
-}
-
-
-static int do_mode_sense(struct fsg_dev *fsg, struct fsg_buffhd *bh)
-{
-       struct fsg_lun  *curlun = fsg->curlun;
-       int             mscmnd = fsg->cmnd[0];
-       u8              *buf = (u8 *) bh->buf;
-       u8              *buf0 = buf;
-       int             pc, page_code;
-       int             changeable_values, all_pages;
-       int             valid_page = 0;
-       int             len, limit;
-
-       if ((fsg->cmnd[1] & ~0x08) != 0) {              // Mask away DBD
-               curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
-               return -EINVAL;
-       }
-       pc = fsg->cmnd[2] >> 6;
-       page_code = fsg->cmnd[2] & 0x3f;
-       if (pc == 3) {
-               curlun->sense_data = SS_SAVING_PARAMETERS_NOT_SUPPORTED;
-               return -EINVAL;
-       }
-       changeable_values = (pc == 1);
-       all_pages = (page_code == 0x3f);
-
-       /* Write the mode parameter header.  Fixed values are: default
-        * medium type, no cache control (DPOFUA), and no block descriptors.
-        * The only variable value is the WriteProtect bit.  We will fill in
-        * the mode data length later. */
-       memset(buf, 0, 8);
-       if (mscmnd == MODE_SENSE) {
-               buf[2] = (curlun->ro ? 0x80 : 0x00);            // WP, DPOFUA
-               buf += 4;
-               limit = 255;
-       } else {                        // MODE_SENSE_10
-               buf[3] = (curlun->ro ? 0x80 : 0x00);            // WP, DPOFUA
-               buf += 8;
-               limit = 65535;          // Should really be mod_data.buflen
-       }
-
-       /* No block descriptors */
-
-       /* The mode pages, in numerical order.  The only page we support
-        * is the Caching page. */
-       if (page_code == 0x08 || all_pages) {
-               valid_page = 1;
-               buf[0] = 0x08;          // Page code
-               buf[1] = 10;            // Page length
-               memset(buf+2, 0, 10);   // None of the fields are changeable
-
-               if (!changeable_values) {
-                       buf[2] = 0x04;  // Write cache enable,
-                                       // Read cache not disabled
-                                       // No cache retention priorities
-                       put_unaligned_be16(0xffff, &buf[4]);
-                                       /* Don't disable prefetch */
-                                       /* Minimum prefetch = 0 */
-                       put_unaligned_be16(0xffff, &buf[8]);
-                                       /* Maximum prefetch */
-                       put_unaligned_be16(0xffff, &buf[10]);
-                                       /* Maximum prefetch ceiling */
-               }
-               buf += 12;
-       }
-
-       /* Check that a valid page was requested and the mode data length
-        * isn't too long. */
-       len = buf - buf0;
-       if (!valid_page || len > limit) {
-               curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
-               return -EINVAL;
-       }
-
-       /*  Store the mode data length */
-       if (mscmnd == MODE_SENSE)
-               buf0[0] = len - 1;
-       else
-               put_unaligned_be16(len - 2, buf0);
-       return len;
-}
-
-
-static int do_start_stop(struct fsg_dev *fsg)
-{
-       struct fsg_lun  *curlun = fsg->curlun;
-       int             loej, start;
-
-       if (!mod_data.removable) {
-               curlun->sense_data = SS_INVALID_COMMAND;
-               return -EINVAL;
-       }
-
-       // int immed = fsg->cmnd[1] & 0x01;
-       loej = fsg->cmnd[4] & 0x02;
-       start = fsg->cmnd[4] & 0x01;
-
-#ifdef CONFIG_USB_FILE_STORAGE_TEST
-       if ((fsg->cmnd[1] & ~0x01) != 0 ||              // Mask away Immed
-                       (fsg->cmnd[4] & ~0x03) != 0) {  // Mask LoEj, Start
-               curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
-               return -EINVAL;
-       }
-
-       if (!start) {
-
-               /* Are we allowed to unload the media? */
-               if (curlun->prevent_medium_removal) {
-                       LDBG(curlun, "unload attempt prevented\n");
-                       curlun->sense_data = SS_MEDIUM_REMOVAL_PREVENTED;
-                       return -EINVAL;
-               }
-               if (loej) {             // Simulate an unload/eject
-                       up_read(&fsg->filesem);
-                       down_write(&fsg->filesem);
-                       fsg_lun_close(curlun);
-                       up_write(&fsg->filesem);
-                       down_read(&fsg->filesem);
-               }
-       } else {
-
-               /* Our emulation doesn't support mounting; the medium is
-                * available for use as soon as it is loaded. */
-               if (!fsg_lun_is_open(curlun)) {
-                       curlun->sense_data = SS_MEDIUM_NOT_PRESENT;
-                       return -EINVAL;
-               }
-       }
-#endif
-       return 0;
-}
-
-
-static int do_prevent_allow(struct fsg_dev *fsg)
-{
-       struct fsg_lun  *curlun = fsg->curlun;
-       int             prevent;
-
-       if (!mod_data.removable) {
-               curlun->sense_data = SS_INVALID_COMMAND;
-               return -EINVAL;
-       }
-
-       prevent = fsg->cmnd[4] & 0x01;
-       if ((fsg->cmnd[4] & ~0x01) != 0) {              // Mask away Prevent
-               curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
-               return -EINVAL;
-       }
-
-       if (curlun->prevent_medium_removal && !prevent)
-               fsg_lun_fsync_sub(curlun);
-       curlun->prevent_medium_removal = prevent;
-       return 0;
-}
-
-
-static int do_read_format_capacities(struct fsg_dev *fsg,
-                       struct fsg_buffhd *bh)
-{
-       struct fsg_lun  *curlun = fsg->curlun;
-       u8              *buf = (u8 *) bh->buf;
-
-       buf[0] = buf[1] = buf[2] = 0;
-       buf[3] = 8;             // Only the Current/Maximum Capacity Descriptor
-       buf += 4;
-
-       put_unaligned_be32(curlun->num_sectors, &buf[0]);
-                                               /* Number of blocks */
-       put_unaligned_be32(curlun->blksize, &buf[4]);   /* Block length */
-       buf[4] = 0x02;                          /* Current capacity */
-       return 12;
-}
-
-
-static int do_mode_select(struct fsg_dev *fsg, struct fsg_buffhd *bh)
-{
-       struct fsg_lun  *curlun = fsg->curlun;
-
-       /* We don't support MODE SELECT */
-       curlun->sense_data = SS_INVALID_COMMAND;
-       return -EINVAL;
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-static int halt_bulk_in_endpoint(struct fsg_dev *fsg)
-{
-       int     rc;
-
-       rc = fsg_set_halt(fsg, fsg->bulk_in);
-       if (rc == -EAGAIN)
-               VDBG(fsg, "delayed bulk-in endpoint halt\n");
-       while (rc != 0) {
-               if (rc != -EAGAIN) {
-                       WARNING(fsg, "usb_ep_set_halt -> %d\n", rc);
-                       rc = 0;
-                       break;
-               }
-
-               /* Wait for a short time and then try again */
-               if (msleep_interruptible(100) != 0)
-                       return -EINTR;
-               rc = usb_ep_set_halt(fsg->bulk_in);
-       }
-       return rc;
-}
-
-static int wedge_bulk_in_endpoint(struct fsg_dev *fsg)
-{
-       int     rc;
-
-       DBG(fsg, "bulk-in set wedge\n");
-       rc = usb_ep_set_wedge(fsg->bulk_in);
-       if (rc == -EAGAIN)
-               VDBG(fsg, "delayed bulk-in endpoint wedge\n");
-       while (rc != 0) {
-               if (rc != -EAGAIN) {
-                       WARNING(fsg, "usb_ep_set_wedge -> %d\n", rc);
-                       rc = 0;
-                       break;
-               }
-
-               /* Wait for a short time and then try again */
-               if (msleep_interruptible(100) != 0)
-                       return -EINTR;
-               rc = usb_ep_set_wedge(fsg->bulk_in);
-       }
-       return rc;
-}
-
-static int throw_away_data(struct fsg_dev *fsg)
-{
-       struct fsg_buffhd       *bh;
-       u32                     amount;
-       int                     rc;
-
-       while ((bh = fsg->next_buffhd_to_drain)->state != BUF_STATE_EMPTY ||
-                       fsg->usb_amount_left > 0) {
-
-               /* Throw away the data in a filled buffer */
-               if (bh->state == BUF_STATE_FULL) {
-                       smp_rmb();
-                       bh->state = BUF_STATE_EMPTY;
-                       fsg->next_buffhd_to_drain = bh->next;
-
-                       /* A short packet or an error ends everything */
-                       if (bh->outreq->actual < bh->bulk_out_intended_length ||
-                                       bh->outreq->status != 0) {
-                               raise_exception(fsg, FSG_STATE_ABORT_BULK_OUT);
-                               return -EINTR;
-                       }
-                       continue;
-               }
-
-               /* Try to submit another request if we need one */
-               bh = fsg->next_buffhd_to_fill;
-               if (bh->state == BUF_STATE_EMPTY && fsg->usb_amount_left > 0) {
-                       amount = min(fsg->usb_amount_left,
-                                       (u32) mod_data.buflen);
-
-                       /* Except at the end of the transfer, amount will be
-                        * equal to the buffer size, which is divisible by
-                        * the bulk-out maxpacket size.
-                        */
-                       set_bulk_out_req_length(fsg, bh, amount);
-                       start_transfer(fsg, fsg->bulk_out, bh->outreq,
-                                       &bh->outreq_busy, &bh->state);
-                       fsg->next_buffhd_to_fill = bh->next;
-                       fsg->usb_amount_left -= amount;
-                       continue;
-               }
-
-               /* Otherwise wait for something to happen */
-               rc = sleep_thread(fsg);
-               if (rc)
-                       return rc;
-       }
-       return 0;
-}
-
-
-static int finish_reply(struct fsg_dev *fsg)
-{
-       struct fsg_buffhd       *bh = fsg->next_buffhd_to_fill;
-       int                     rc = 0;
-
-       switch (fsg->data_dir) {
-       case DATA_DIR_NONE:
-               break;                  // Nothing to send
-
-       /* If we don't know whether the host wants to read or write,
-        * this must be CB or CBI with an unknown command.  We mustn't
-        * try to send or receive any data.  So stall both bulk pipes
-        * if we can and wait for a reset. */
-       case DATA_DIR_UNKNOWN:
-               if (mod_data.can_stall) {
-                       fsg_set_halt(fsg, fsg->bulk_out);
-                       rc = halt_bulk_in_endpoint(fsg);
-               }
-               break;
-
-       /* All but the last buffer of data must have already been sent */
-       case DATA_DIR_TO_HOST:
-               if (fsg->data_size == 0)
-                       ;               // Nothing to send
-
-               /* If there's no residue, simply send the last buffer */
-               else if (fsg->residue == 0) {
-                       bh->inreq->zero = 0;
-                       start_transfer(fsg, fsg->bulk_in, bh->inreq,
-                                       &bh->inreq_busy, &bh->state);
-                       fsg->next_buffhd_to_fill = bh->next;
-               }
-
-               /* There is a residue.  For CB and CBI, simply mark the end
-                * of the data with a short packet.  However, if we are
-                * allowed to stall, there was no data at all (residue ==
-                * data_size), and the command failed (invalid LUN or
-                * sense data is set), then halt the bulk-in endpoint
-                * instead. */
-               else if (!transport_is_bbb()) {
-                       if (mod_data.can_stall &&
-                                       fsg->residue == fsg->data_size &&
-       (!fsg->curlun || fsg->curlun->sense_data != SS_NO_SENSE)) {
-                               bh->state = BUF_STATE_EMPTY;
-                               rc = halt_bulk_in_endpoint(fsg);
-                       } else {
-                               bh->inreq->zero = 1;
-                               start_transfer(fsg, fsg->bulk_in, bh->inreq,
-                                               &bh->inreq_busy, &bh->state);
-                               fsg->next_buffhd_to_fill = bh->next;
-                       }
-               }
-
-               /*
-                * For Bulk-only, mark the end of the data with a short
-                * packet.  If we are allowed to stall, halt the bulk-in
-                * endpoint.  (Note: This violates the Bulk-Only Transport
-                * specification, which requires us to pad the data if we
-                * don't halt the endpoint.  Presumably nobody will mind.)
-                */
-               else {
-                       bh->inreq->zero = 1;
-                       start_transfer(fsg, fsg->bulk_in, bh->inreq,
-                                       &bh->inreq_busy, &bh->state);
-                       fsg->next_buffhd_to_fill = bh->next;
-                       if (mod_data.can_stall)
-                               rc = halt_bulk_in_endpoint(fsg);
-               }
-               break;
-
-       /* We have processed all we want from the data the host has sent.
-        * There may still be outstanding bulk-out requests. */
-       case DATA_DIR_FROM_HOST:
-               if (fsg->residue == 0)
-                       ;               // Nothing to receive
-
-               /* Did the host stop sending unexpectedly early? */
-               else if (fsg->short_packet_received) {
-                       raise_exception(fsg, FSG_STATE_ABORT_BULK_OUT);
-                       rc = -EINTR;
-               }
-
-               /* We haven't processed all the incoming data.  Even though
-                * we may be allowed to stall, doing so would cause a race.
-                * The controller may already have ACK'ed all the remaining
-                * bulk-out packets, in which case the host wouldn't see a
-                * STALL.  Not realizing the endpoint was halted, it wouldn't
-                * clear the halt -- leading to problems later on. */
-#if 0
-               else if (mod_data.can_stall) {
-                       fsg_set_halt(fsg, fsg->bulk_out);
-                       raise_exception(fsg, FSG_STATE_ABORT_BULK_OUT);
-                       rc = -EINTR;
-               }
-#endif
-
-               /* We can't stall.  Read in the excess data and throw it
-                * all away. */
-               else
-                       rc = throw_away_data(fsg);
-               break;
-       }
-       return rc;
-}
-
-
-static int send_status(struct fsg_dev *fsg)
-{
-       struct fsg_lun          *curlun = fsg->curlun;
-       struct fsg_buffhd       *bh;
-       int                     rc;
-       u8                      status = US_BULK_STAT_OK;
-       u32                     sd, sdinfo = 0;
-
-       /* Wait for the next buffer to become available */
-       bh = fsg->next_buffhd_to_fill;
-       while (bh->state != BUF_STATE_EMPTY) {
-               rc = sleep_thread(fsg);
-               if (rc)
-                       return rc;
-       }
-
-       if (curlun) {
-               sd = curlun->sense_data;
-               sdinfo = curlun->sense_data_info;
-       } else if (fsg->bad_lun_okay)
-               sd = SS_NO_SENSE;
-       else
-               sd = SS_LOGICAL_UNIT_NOT_SUPPORTED;
-
-       if (fsg->phase_error) {
-               DBG(fsg, "sending phase-error status\n");
-               status = US_BULK_STAT_PHASE;
-               sd = SS_INVALID_COMMAND;
-       } else if (sd != SS_NO_SENSE) {
-               DBG(fsg, "sending command-failure status\n");
-               status = US_BULK_STAT_FAIL;
-               VDBG(fsg, "  sense data: SK x%02x, ASC x%02x, ASCQ x%02x;"
-                               "  info x%x\n",
-                               SK(sd), ASC(sd), ASCQ(sd), sdinfo);
-       }
-
-       if (transport_is_bbb()) {
-               struct bulk_cs_wrap     *csw = bh->buf;
-
-               /* Store and send the Bulk-only CSW */
-               csw->Signature = cpu_to_le32(US_BULK_CS_SIGN);
-               csw->Tag = fsg->tag;
-               csw->Residue = cpu_to_le32(fsg->residue);
-               csw->Status = status;
-
-               bh->inreq->length = US_BULK_CS_WRAP_LEN;
-               bh->inreq->zero = 0;
-               start_transfer(fsg, fsg->bulk_in, bh->inreq,
-                               &bh->inreq_busy, &bh->state);
-
-       } else if (mod_data.transport_type == USB_PR_CB) {
-
-               /* Control-Bulk transport has no status phase! */
-               return 0;
-
-       } else {                        // USB_PR_CBI
-               struct interrupt_data   *buf = bh->buf;
-
-               /* Store and send the Interrupt data.  UFI sends the ASC
-                * and ASCQ bytes.  Everything else sends a Type (which
-                * is always 0) and the status Value. */
-               if (mod_data.protocol_type == USB_SC_UFI) {
-                       buf->bType = ASC(sd);
-                       buf->bValue = ASCQ(sd);
-               } else {
-                       buf->bType = 0;
-                       buf->bValue = status;
-               }
-               fsg->intreq->length = CBI_INTERRUPT_DATA_LEN;
-
-               fsg->intr_buffhd = bh;          // Point to the right buffhd
-               fsg->intreq->buf = bh->inreq->buf;
-               fsg->intreq->context = bh;
-               start_transfer(fsg, fsg->intr_in, fsg->intreq,
-                               &fsg->intreq_busy, &bh->state);
-       }
-
-       fsg->next_buffhd_to_fill = bh->next;
-       return 0;
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-/* Check whether the command is properly formed and whether its data size
- * and direction agree with the values we already have. */
-static int check_command(struct fsg_dev *fsg, int cmnd_size,
-               enum data_direction data_dir, unsigned int mask,
-               int needs_medium, const char *name)
-{
-       int                     i;
-       int                     lun = fsg->cmnd[1] >> 5;
-       static const char       dirletter[4] = {'u', 'o', 'i', 'n'};
-       char                    hdlen[20];
-       struct fsg_lun          *curlun;
-
-       /* Adjust the expected cmnd_size for protocol encapsulation padding.
-        * Transparent SCSI doesn't pad. */
-       if (protocol_is_scsi())
-               ;
-
-       /* There's some disagreement as to whether RBC pads commands or not.
-        * We'll play it safe and accept either form. */
-       else if (mod_data.protocol_type == USB_SC_RBC) {
-               if (fsg->cmnd_size == 12)
-                       cmnd_size = 12;
-
-       /* All the other protocols pad to 12 bytes */
-       } else
-               cmnd_size = 12;
-
-       hdlen[0] = 0;
-       if (fsg->data_dir != DATA_DIR_UNKNOWN)
-               sprintf(hdlen, ", H%c=%u", dirletter[(int) fsg->data_dir],
-                               fsg->data_size);
-       VDBG(fsg, "SCSI command: %s;  Dc=%d, D%c=%u;  Hc=%d%s\n",
-                       name, cmnd_size, dirletter[(int) data_dir],
-                       fsg->data_size_from_cmnd, fsg->cmnd_size, hdlen);
-
-       /* We can't reply at all until we know the correct data direction
-        * and size. */
-       if (fsg->data_size_from_cmnd == 0)
-               data_dir = DATA_DIR_NONE;
-       if (fsg->data_dir == DATA_DIR_UNKNOWN) {        // CB or CBI
-               fsg->data_dir = data_dir;
-               fsg->data_size = fsg->data_size_from_cmnd;
-
-       } else {                                        // Bulk-only
-               if (fsg->data_size < fsg->data_size_from_cmnd) {
-
-                       /* Host data size < Device data size is a phase error.
-                        * Carry out the command, but only transfer as much
-                        * as we are allowed. */
-                       fsg->data_size_from_cmnd = fsg->data_size;
-                       fsg->phase_error = 1;
-               }
-       }
-       fsg->residue = fsg->usb_amount_left = fsg->data_size;
-
-       /* Conflicting data directions is a phase error */
-       if (fsg->data_dir != data_dir && fsg->data_size_from_cmnd > 0) {
-               fsg->phase_error = 1;
-               return -EINVAL;
-       }
-
-       /* Verify the length of the command itself */
-       if (cmnd_size != fsg->cmnd_size) {
-
-               /* Special case workaround: There are plenty of buggy SCSI
-                * implementations. Many have issues with cbw->Length
-                * field passing a wrong command size. For those cases we
-                * always try to work around the problem by using the length
-                * sent by the host side provided it is at least as large
-                * as the correct command length.
-                * Examples of such cases would be MS-Windows, which issues
-                * REQUEST SENSE with cbw->Length == 12 where it should
-                * be 6, and xbox360 issuing INQUIRY, TEST UNIT READY and
-                * REQUEST SENSE with cbw->Length == 10 where it should
-                * be 6 as well.
-                */
-               if (cmnd_size <= fsg->cmnd_size) {
-                       DBG(fsg, "%s is buggy! Expected length %d "
-                                       "but we got %d\n", name,
-                                       cmnd_size, fsg->cmnd_size);
-                       cmnd_size = fsg->cmnd_size;
-               } else {
-                       fsg->phase_error = 1;
-                       return -EINVAL;
-               }
-       }
-
-       /* Check that the LUN values are consistent */
-       if (transport_is_bbb()) {
-               if (fsg->lun != lun)
-                       DBG(fsg, "using LUN %d from CBW, "
-                                       "not LUN %d from CDB\n",
-                                       fsg->lun, lun);
-       }
-
-       /* Check the LUN */
-       curlun = fsg->curlun;
-       if (curlun) {
-               if (fsg->cmnd[0] != REQUEST_SENSE) {
-                       curlun->sense_data = SS_NO_SENSE;
-                       curlun->sense_data_info = 0;
-                       curlun->info_valid = 0;
-               }
-       } else {
-               fsg->bad_lun_okay = 0;
-
-               /* INQUIRY and REQUEST SENSE commands are explicitly allowed
-                * to use unsupported LUNs; all others may not. */
-               if (fsg->cmnd[0] != INQUIRY &&
-                               fsg->cmnd[0] != REQUEST_SENSE) {
-                       DBG(fsg, "unsupported LUN %d\n", fsg->lun);
-                       return -EINVAL;
-               }
-       }
-
-       /* If a unit attention condition exists, only INQUIRY and
-        * REQUEST SENSE commands are allowed; anything else must fail. */
-       if (curlun && curlun->unit_attention_data != SS_NO_SENSE &&
-                       fsg->cmnd[0] != INQUIRY &&
-                       fsg->cmnd[0] != REQUEST_SENSE) {
-               curlun->sense_data = curlun->unit_attention_data;
-               curlun->unit_attention_data = SS_NO_SENSE;
-               return -EINVAL;
-       }
-
-       /* Check that only command bytes listed in the mask are non-zero */
-       fsg->cmnd[1] &= 0x1f;                   // Mask away the LUN
-       for (i = 1; i < cmnd_size; ++i) {
-               if (fsg->cmnd[i] && !(mask & (1 << i))) {
-                       if (curlun)
-                               curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
-                       return -EINVAL;
-               }
-       }
-
-       /* If the medium isn't mounted and the command needs to access
-        * it, return an error. */
-       if (curlun && !fsg_lun_is_open(curlun) && needs_medium) {
-               curlun->sense_data = SS_MEDIUM_NOT_PRESENT;
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-/* wrapper of check_command for data size in blocks handling */
-static int check_command_size_in_blocks(struct fsg_dev *fsg, int cmnd_size,
-               enum data_direction data_dir, unsigned int mask,
-               int needs_medium, const char *name)
-{
-       if (fsg->curlun)
-               fsg->data_size_from_cmnd <<= fsg->curlun->blkbits;
-       return check_command(fsg, cmnd_size, data_dir,
-                       mask, needs_medium, name);
-}
-
-static int do_scsi_command(struct fsg_dev *fsg)
-{
-       struct fsg_buffhd       *bh;
-       int                     rc;
-       int                     reply = -EINVAL;
-       int                     i;
-       static char             unknown[16];
-
-       dump_cdb(fsg);
-
-       /* Wait for the next buffer to become available for data or status */
-       bh = fsg->next_buffhd_to_drain = fsg->next_buffhd_to_fill;
-       while (bh->state != BUF_STATE_EMPTY) {
-               rc = sleep_thread(fsg);
-               if (rc)
-                       return rc;
-       }
-       fsg->phase_error = 0;
-       fsg->short_packet_received = 0;
-
-       down_read(&fsg->filesem);       // We're using the backing file
-       switch (fsg->cmnd[0]) {
-
-       case INQUIRY:
-               fsg->data_size_from_cmnd = fsg->cmnd[4];
-               if ((reply = check_command(fsg, 6, DATA_DIR_TO_HOST,
-                               (1<<4), 0,
-                               "INQUIRY")) == 0)
-                       reply = do_inquiry(fsg, bh);
-               break;
-
-       case MODE_SELECT:
-               fsg->data_size_from_cmnd = fsg->cmnd[4];
-               if ((reply = check_command(fsg, 6, DATA_DIR_FROM_HOST,
-                               (1<<1) | (1<<4), 0,
-                               "MODE SELECT(6)")) == 0)
-                       reply = do_mode_select(fsg, bh);
-               break;
-
-       case MODE_SELECT_10:
-               fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]);
-               if ((reply = check_command(fsg, 10, DATA_DIR_FROM_HOST,
-                               (1<<1) | (3<<7), 0,
-                               "MODE SELECT(10)")) == 0)
-                       reply = do_mode_select(fsg, bh);
-               break;
-
-       case MODE_SENSE:
-               fsg->data_size_from_cmnd = fsg->cmnd[4];
-               if ((reply = check_command(fsg, 6, DATA_DIR_TO_HOST,
-                               (1<<1) | (1<<2) | (1<<4), 0,
-                               "MODE SENSE(6)")) == 0)
-                       reply = do_mode_sense(fsg, bh);
-               break;
-
-       case MODE_SENSE_10:
-               fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]);
-               if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST,
-                               (1<<1) | (1<<2) | (3<<7), 0,
-                               "MODE SENSE(10)")) == 0)
-                       reply = do_mode_sense(fsg, bh);
-               break;
-
-       case ALLOW_MEDIUM_REMOVAL:
-               fsg->data_size_from_cmnd = 0;
-               if ((reply = check_command(fsg, 6, DATA_DIR_NONE,
-                               (1<<4), 0,
-                               "PREVENT-ALLOW MEDIUM REMOVAL")) == 0)
-                       reply = do_prevent_allow(fsg);
-               break;
-
-       case READ_6:
-               i = fsg->cmnd[4];
-               fsg->data_size_from_cmnd = (i == 0) ? 256 : i;
-               if ((reply = check_command_size_in_blocks(fsg, 6,
-                               DATA_DIR_TO_HOST,
-                               (7<<1) | (1<<4), 1,
-                               "READ(6)")) == 0)
-                       reply = do_read(fsg);
-               break;
-
-       case READ_10:
-               fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]);
-               if ((reply = check_command_size_in_blocks(fsg, 10,
-                               DATA_DIR_TO_HOST,
-                               (1<<1) | (0xf<<2) | (3<<7), 1,
-                               "READ(10)")) == 0)
-                       reply = do_read(fsg);
-               break;
-
-       case READ_12:
-               fsg->data_size_from_cmnd = get_unaligned_be32(&fsg->cmnd[6]);
-               if ((reply = check_command_size_in_blocks(fsg, 12,
-                               DATA_DIR_TO_HOST,
-                               (1<<1) | (0xf<<2) | (0xf<<6), 1,
-                               "READ(12)")) == 0)
-                       reply = do_read(fsg);
-               break;
-
-       case READ_CAPACITY:
-               fsg->data_size_from_cmnd = 8;
-               if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST,
-                               (0xf<<2) | (1<<8), 1,
-                               "READ CAPACITY")) == 0)
-                       reply = do_read_capacity(fsg, bh);
-               break;
-
-       case READ_HEADER:
-               if (!mod_data.cdrom)
-                       goto unknown_cmnd;
-               fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]);
-               if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST,
-                               (3<<7) | (0x1f<<1), 1,
-                               "READ HEADER")) == 0)
-                       reply = do_read_header(fsg, bh);
-               break;
-
-       case READ_TOC:
-               if (!mod_data.cdrom)
-                       goto unknown_cmnd;
-               fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]);
-               if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST,
-                               (7<<6) | (1<<1), 1,
-                               "READ TOC")) == 0)
-                       reply = do_read_toc(fsg, bh);
-               break;
-
-       case READ_FORMAT_CAPACITIES:
-               fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]);
-               if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST,
-                               (3<<7), 1,
-                               "READ FORMAT CAPACITIES")) == 0)
-                       reply = do_read_format_capacities(fsg, bh);
-               break;
-
-       case REQUEST_SENSE:
-               fsg->data_size_from_cmnd = fsg->cmnd[4];
-               if ((reply = check_command(fsg, 6, DATA_DIR_TO_HOST,
-                               (1<<4), 0,
-                               "REQUEST SENSE")) == 0)
-                       reply = do_request_sense(fsg, bh);
-               break;
-
-       case START_STOP:
-               fsg->data_size_from_cmnd = 0;
-               if ((reply = check_command(fsg, 6, DATA_DIR_NONE,
-                               (1<<1) | (1<<4), 0,
-                               "START-STOP UNIT")) == 0)
-                       reply = do_start_stop(fsg);
-               break;
-
-       case SYNCHRONIZE_CACHE:
-               fsg->data_size_from_cmnd = 0;
-               if ((reply = check_command(fsg, 10, DATA_DIR_NONE,
-                               (0xf<<2) | (3<<7), 1,
-                               "SYNCHRONIZE CACHE")) == 0)
-                       reply = do_synchronize_cache(fsg);
-               break;
-
-       case TEST_UNIT_READY:
-               fsg->data_size_from_cmnd = 0;
-               reply = check_command(fsg, 6, DATA_DIR_NONE,
-                               0, 1,
-                               "TEST UNIT READY");
-               break;
-
-       /* Although optional, this command is used by MS-Windows.  We
-        * support a minimal version: BytChk must be 0. */
-       case VERIFY:
-               fsg->data_size_from_cmnd = 0;
-               if ((reply = check_command(fsg, 10, DATA_DIR_NONE,
-                               (1<<1) | (0xf<<2) | (3<<7), 1,
-                               "VERIFY")) == 0)
-                       reply = do_verify(fsg);
-               break;
-
-       case WRITE_6:
-               i = fsg->cmnd[4];
-               fsg->data_size_from_cmnd = (i == 0) ? 256 : i;
-               if ((reply = check_command_size_in_blocks(fsg, 6,
-                               DATA_DIR_FROM_HOST,
-                               (7<<1) | (1<<4), 1,
-                               "WRITE(6)")) == 0)
-                       reply = do_write(fsg);
-               break;
-
-       case WRITE_10:
-               fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]);
-               if ((reply = check_command_size_in_blocks(fsg, 10,
-                               DATA_DIR_FROM_HOST,
-                               (1<<1) | (0xf<<2) | (3<<7), 1,
-                               "WRITE(10)")) == 0)
-                       reply = do_write(fsg);
-               break;
-
-       case WRITE_12:
-               fsg->data_size_from_cmnd = get_unaligned_be32(&fsg->cmnd[6]);
-               if ((reply = check_command_size_in_blocks(fsg, 12,
-                               DATA_DIR_FROM_HOST,
-                               (1<<1) | (0xf<<2) | (0xf<<6), 1,
-                               "WRITE(12)")) == 0)
-                       reply = do_write(fsg);
-               break;
-
-       /* Some mandatory commands that we recognize but don't implement.
-        * They don't mean much in this setting.  It's left as an exercise
-        * for anyone interested to implement RESERVE and RELEASE in terms
-        * of Posix locks. */
-       case FORMAT_UNIT:
-       case RELEASE:
-       case RESERVE:
-       case SEND_DIAGNOSTIC:
-               // Fall through
-
-       default:
- unknown_cmnd:
-               fsg->data_size_from_cmnd = 0;
-               sprintf(unknown, "Unknown x%02x", fsg->cmnd[0]);
-               if ((reply = check_command(fsg, fsg->cmnd_size,
-                               DATA_DIR_UNKNOWN, ~0, 0, unknown)) == 0) {
-                       fsg->curlun->sense_data = SS_INVALID_COMMAND;
-                       reply = -EINVAL;
-               }
-               break;
-       }
-       up_read(&fsg->filesem);
-
-       if (reply == -EINTR || signal_pending(current))
-               return -EINTR;
-
-       /* Set up the single reply buffer for finish_reply() */
-       if (reply == -EINVAL)
-               reply = 0;              // Error reply length
-       if (reply >= 0 && fsg->data_dir == DATA_DIR_TO_HOST) {
-               reply = min((u32) reply, fsg->data_size_from_cmnd);
-               bh->inreq->length = reply;
-               bh->state = BUF_STATE_FULL;
-               fsg->residue -= reply;
-       }                               // Otherwise it's already set
-
-       return 0;
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh)
-{
-       struct usb_request              *req = bh->outreq;
-       struct bulk_cb_wrap     *cbw = req->buf;
-
-       /* Was this a real packet?  Should it be ignored? */
-       if (req->status || test_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags))
-               return -EINVAL;
-
-       /* Is the CBW valid? */
-       if (req->actual != US_BULK_CB_WRAP_LEN ||
-                       cbw->Signature != cpu_to_le32(
-                               US_BULK_CB_SIGN)) {
-               DBG(fsg, "invalid CBW: len %u sig 0x%x\n",
-                               req->actual,
-                               le32_to_cpu(cbw->Signature));
-
-               /* The Bulk-only spec says we MUST stall the IN endpoint
-                * (6.6.1), so it's unavoidable.  It also says we must
-                * retain this state until the next reset, but there's
-                * no way to tell the controller driver it should ignore
-                * Clear-Feature(HALT) requests.
-                *
-                * We aren't required to halt the OUT endpoint; instead
-                * we can simply accept and discard any data received
-                * until the next reset. */
-               wedge_bulk_in_endpoint(fsg);
-               set_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags);
-               return -EINVAL;
-       }
-
-       /* Is the CBW meaningful? */
-       if (cbw->Lun >= FSG_MAX_LUNS || cbw->Flags & ~US_BULK_FLAG_IN ||
-                       cbw->Length <= 0 || cbw->Length > MAX_COMMAND_SIZE) {
-               DBG(fsg, "non-meaningful CBW: lun = %u, flags = 0x%x, "
-                               "cmdlen %u\n",
-                               cbw->Lun, cbw->Flags, cbw->Length);
-
-               /* We can do anything we want here, so let's stall the
-                * bulk pipes if we are allowed to. */
-               if (mod_data.can_stall) {
-                       fsg_set_halt(fsg, fsg->bulk_out);
-                       halt_bulk_in_endpoint(fsg);
-               }
-               return -EINVAL;
-       }
-
-       /* Save the command for later */
-       fsg->cmnd_size = cbw->Length;
-       memcpy(fsg->cmnd, cbw->CDB, fsg->cmnd_size);
-       if (cbw->Flags & US_BULK_FLAG_IN)
-               fsg->data_dir = DATA_DIR_TO_HOST;
-       else
-               fsg->data_dir = DATA_DIR_FROM_HOST;
-       fsg->data_size = le32_to_cpu(cbw->DataTransferLength);
-       if (fsg->data_size == 0)
-               fsg->data_dir = DATA_DIR_NONE;
-       fsg->lun = cbw->Lun;
-       fsg->tag = cbw->Tag;
-       return 0;
-}
-
-
-static int get_next_command(struct fsg_dev *fsg)
-{
-       struct fsg_buffhd       *bh;
-       int                     rc = 0;
-
-       if (transport_is_bbb()) {
-
-               /* Wait for the next buffer to become available */
-               bh = fsg->next_buffhd_to_fill;
-               while (bh->state != BUF_STATE_EMPTY) {
-                       rc = sleep_thread(fsg);
-                       if (rc)
-                               return rc;
-               }
-
-               /* Queue a request to read a Bulk-only CBW */
-               set_bulk_out_req_length(fsg, bh, US_BULK_CB_WRAP_LEN);
-               start_transfer(fsg, fsg->bulk_out, bh->outreq,
-                               &bh->outreq_busy, &bh->state);
-
-               /* We will drain the buffer in software, which means we
-                * can reuse it for the next filling.  No need to advance
-                * next_buffhd_to_fill. */
-
-               /* Wait for the CBW to arrive */
-               while (bh->state != BUF_STATE_FULL) {
-                       rc = sleep_thread(fsg);
-                       if (rc)
-                               return rc;
-               }
-               smp_rmb();
-               rc = received_cbw(fsg, bh);
-               bh->state = BUF_STATE_EMPTY;
-
-       } else {                // USB_PR_CB or USB_PR_CBI
-
-               /* Wait for the next command to arrive */
-               while (fsg->cbbuf_cmnd_size == 0) {
-                       rc = sleep_thread(fsg);
-                       if (rc)
-                               return rc;
-               }
-
-               /* Is the previous status interrupt request still busy?
-                * The host is allowed to skip reading the status,
-                * so we must cancel it. */
-               if (fsg->intreq_busy)
-                       usb_ep_dequeue(fsg->intr_in, fsg->intreq);
-
-               /* Copy the command and mark the buffer empty */
-               fsg->data_dir = DATA_DIR_UNKNOWN;
-               spin_lock_irq(&fsg->lock);
-               fsg->cmnd_size = fsg->cbbuf_cmnd_size;
-               memcpy(fsg->cmnd, fsg->cbbuf_cmnd, fsg->cmnd_size);
-               fsg->cbbuf_cmnd_size = 0;
-               spin_unlock_irq(&fsg->lock);
-
-               /* Use LUN from the command */
-               fsg->lun = fsg->cmnd[1] >> 5;
-       }
-
-       /* Update current lun */
-       if (fsg->lun >= 0 && fsg->lun < fsg->nluns)
-               fsg->curlun = &fsg->luns[fsg->lun];
-       else
-               fsg->curlun = NULL;
-
-       return rc;
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-static int enable_endpoint(struct fsg_dev *fsg, struct usb_ep *ep,
-               const struct usb_endpoint_descriptor *d)
-{
-       int     rc;
-
-       ep->driver_data = fsg;
-       ep->desc = d;
-       rc = usb_ep_enable(ep);
-       if (rc)
-               ERROR(fsg, "can't enable %s, result %d\n", ep->name, rc);
-       return rc;
-}
-
-static int alloc_request(struct fsg_dev *fsg, struct usb_ep *ep,
-               struct usb_request **preq)
-{
-       *preq = usb_ep_alloc_request(ep, GFP_ATOMIC);
-       if (*preq)
-               return 0;
-       ERROR(fsg, "can't allocate request for %s\n", ep->name);
-       return -ENOMEM;
-}
-
-/*
- * Reset interface setting and re-init endpoint state (toggle etc).
- * Call with altsetting < 0 to disable the interface.  The only other
- * available altsetting is 0, which enables the interface.
- */
-static int do_set_interface(struct fsg_dev *fsg, int altsetting)
-{
-       int     rc = 0;
-       int     i;
-       const struct usb_endpoint_descriptor    *d;
-
-       if (fsg->running)
-               DBG(fsg, "reset interface\n");
-
-reset:
-       /* Deallocate the requests */
-       for (i = 0; i < fsg_num_buffers; ++i) {
-               struct fsg_buffhd *bh = &fsg->buffhds[i];
-
-               if (bh->inreq) {
-                       usb_ep_free_request(fsg->bulk_in, bh->inreq);
-                       bh->inreq = NULL;
-               }
-               if (bh->outreq) {
-                       usb_ep_free_request(fsg->bulk_out, bh->outreq);
-                       bh->outreq = NULL;
-               }
-       }
-       if (fsg->intreq) {
-               usb_ep_free_request(fsg->intr_in, fsg->intreq);
-               fsg->intreq = NULL;
-       }
-
-       /* Disable the endpoints */
-       if (fsg->bulk_in_enabled) {
-               usb_ep_disable(fsg->bulk_in);
-               fsg->bulk_in_enabled = 0;
-       }
-       if (fsg->bulk_out_enabled) {
-               usb_ep_disable(fsg->bulk_out);
-               fsg->bulk_out_enabled = 0;
-       }
-       if (fsg->intr_in_enabled) {
-               usb_ep_disable(fsg->intr_in);
-               fsg->intr_in_enabled = 0;
-       }
-
-       fsg->running = 0;
-       if (altsetting < 0 || rc != 0)
-               return rc;
-
-       DBG(fsg, "set interface %d\n", altsetting);
-
-       /* Enable the endpoints */
-       d = fsg_ep_desc(fsg->gadget,
-                       &fsg_fs_bulk_in_desc, &fsg_hs_bulk_in_desc,
-                       &fsg_ss_bulk_in_desc);
-       if ((rc = enable_endpoint(fsg, fsg->bulk_in, d)) != 0)
-               goto reset;
-       fsg->bulk_in_enabled = 1;
-
-       d = fsg_ep_desc(fsg->gadget,
-                       &fsg_fs_bulk_out_desc, &fsg_hs_bulk_out_desc,
-                       &fsg_ss_bulk_out_desc);
-       if ((rc = enable_endpoint(fsg, fsg->bulk_out, d)) != 0)
-               goto reset;
-       fsg->bulk_out_enabled = 1;
-       fsg->bulk_out_maxpacket = usb_endpoint_maxp(d);
-       clear_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags);
-
-       if (transport_is_cbi()) {
-               d = fsg_ep_desc(fsg->gadget,
-                               &fsg_fs_intr_in_desc, &fsg_hs_intr_in_desc,
-                               &fsg_ss_intr_in_desc);
-               if ((rc = enable_endpoint(fsg, fsg->intr_in, d)) != 0)
-                       goto reset;
-               fsg->intr_in_enabled = 1;
-       }
-
-       /* Allocate the requests */
-       for (i = 0; i < fsg_num_buffers; ++i) {
-               struct fsg_buffhd       *bh = &fsg->buffhds[i];
-
-               if ((rc = alloc_request(fsg, fsg->bulk_in, &bh->inreq)) != 0)
-                       goto reset;
-               if ((rc = alloc_request(fsg, fsg->bulk_out, &bh->outreq)) != 0)
-                       goto reset;
-               bh->inreq->buf = bh->outreq->buf = bh->buf;
-               bh->inreq->context = bh->outreq->context = bh;
-               bh->inreq->complete = bulk_in_complete;
-               bh->outreq->complete = bulk_out_complete;
-       }
-       if (transport_is_cbi()) {
-               if ((rc = alloc_request(fsg, fsg->intr_in, &fsg->intreq)) != 0)
-                       goto reset;
-               fsg->intreq->complete = intr_in_complete;
-       }
-
-       fsg->running = 1;
-       for (i = 0; i < fsg->nluns; ++i)
-               fsg->luns[i].unit_attention_data = SS_RESET_OCCURRED;
-       return rc;
-}
-
-
-/*
- * Change our operational configuration.  This code must agree with the code
- * that returns config descriptors, and with interface altsetting code.
- *
- * It's also responsible for power management interactions.  Some
- * configurations might not work with our current power sources.
- * For now we just assume the gadget is always self-powered.
- */
-static int do_set_config(struct fsg_dev *fsg, u8 new_config)
-{
-       int     rc = 0;
-
-       /* Disable the single interface */
-       if (fsg->config != 0) {
-               DBG(fsg, "reset config\n");
-               fsg->config = 0;
-               rc = do_set_interface(fsg, -1);
-       }
-
-       /* Enable the interface */
-       if (new_config != 0) {
-               fsg->config = new_config;
-               if ((rc = do_set_interface(fsg, 0)) != 0)
-                       fsg->config = 0;        // Reset on errors
-               else
-                       INFO(fsg, "%s config #%d\n",
-                            usb_speed_string(fsg->gadget->speed),
-                            fsg->config);
-       }
-       return rc;
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-static void handle_exception(struct fsg_dev *fsg)
-{
-       siginfo_t               info;
-       int                     sig;
-       int                     i;
-       int                     num_active;
-       struct fsg_buffhd       *bh;
-       enum fsg_state          old_state;
-       u8                      new_config;
-       struct fsg_lun          *curlun;
-       unsigned int            exception_req_tag;
-       int                     rc;
-
-       /* Clear the existing signals.  Anything but SIGUSR1 is converted
-        * into a high-priority EXIT exception. */
-       for (;;) {
-               sig = dequeue_signal_lock(current, &current->blocked, &info);
-               if (!sig)
-                       break;
-               if (sig != SIGUSR1) {
-                       if (fsg->state < FSG_STATE_EXIT)
-                               DBG(fsg, "Main thread exiting on signal\n");
-                       raise_exception(fsg, FSG_STATE_EXIT);
-               }
-       }
-
-       /* Cancel all the pending transfers */
-       if (fsg->intreq_busy)
-               usb_ep_dequeue(fsg->intr_in, fsg->intreq);
-       for (i = 0; i < fsg_num_buffers; ++i) {
-               bh = &fsg->buffhds[i];
-               if (bh->inreq_busy)
-                       usb_ep_dequeue(fsg->bulk_in, bh->inreq);
-               if (bh->outreq_busy)
-                       usb_ep_dequeue(fsg->bulk_out, bh->outreq);
-       }
-
-       /* Wait until everything is idle */
-       for (;;) {
-               num_active = fsg->intreq_busy;
-               for (i = 0; i < fsg_num_buffers; ++i) {
-                       bh = &fsg->buffhds[i];
-                       num_active += bh->inreq_busy + bh->outreq_busy;
-               }
-               if (num_active == 0)
-                       break;
-               if (sleep_thread(fsg))
-                       return;
-       }
-
-       /* Clear out the controller's fifos */
-       if (fsg->bulk_in_enabled)
-               usb_ep_fifo_flush(fsg->bulk_in);
-       if (fsg->bulk_out_enabled)
-               usb_ep_fifo_flush(fsg->bulk_out);
-       if (fsg->intr_in_enabled)
-               usb_ep_fifo_flush(fsg->intr_in);
-
-       /* Reset the I/O buffer states and pointers, the SCSI
-        * state, and the exception.  Then invoke the handler. */
-       spin_lock_irq(&fsg->lock);
-
-       for (i = 0; i < fsg_num_buffers; ++i) {
-               bh = &fsg->buffhds[i];
-               bh->state = BUF_STATE_EMPTY;
-       }
-       fsg->next_buffhd_to_fill = fsg->next_buffhd_to_drain =
-                       &fsg->buffhds[0];
-
-       exception_req_tag = fsg->exception_req_tag;
-       new_config = fsg->new_config;
-       old_state = fsg->state;
-
-       if (old_state == FSG_STATE_ABORT_BULK_OUT)
-               fsg->state = FSG_STATE_STATUS_PHASE;
-       else {
-               for (i = 0; i < fsg->nluns; ++i) {
-                       curlun = &fsg->luns[i];
-                       curlun->prevent_medium_removal = 0;
-                       curlun->sense_data = curlun->unit_attention_data =
-                                       SS_NO_SENSE;
-                       curlun->sense_data_info = 0;
-                       curlun->info_valid = 0;
-               }
-               fsg->state = FSG_STATE_IDLE;
-       }
-       spin_unlock_irq(&fsg->lock);
-
-       /* Carry out any extra actions required for the exception */
-       switch (old_state) {
-       default:
-               break;
-
-       case FSG_STATE_ABORT_BULK_OUT:
-               send_status(fsg);
-               spin_lock_irq(&fsg->lock);
-               if (fsg->state == FSG_STATE_STATUS_PHASE)
-                       fsg->state = FSG_STATE_IDLE;
-               spin_unlock_irq(&fsg->lock);
-               break;
-
-       case FSG_STATE_RESET:
-               /* In case we were forced against our will to halt a
-                * bulk endpoint, clear the halt now.  (The SuperH UDC
-                * requires this.) */
-               if (test_and_clear_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags))
-                       usb_ep_clear_halt(fsg->bulk_in);
-
-               if (transport_is_bbb()) {
-                       if (fsg->ep0_req_tag == exception_req_tag)
-                               ep0_queue(fsg); // Complete the status stage
-
-               } else if (transport_is_cbi())
-                       send_status(fsg);       // Status by interrupt pipe
-
-               /* Technically this should go here, but it would only be
-                * a waste of time.  Ditto for the INTERFACE_CHANGE and
-                * CONFIG_CHANGE cases. */
-               // for (i = 0; i < fsg->nluns; ++i)
-               //      fsg->luns[i].unit_attention_data = SS_RESET_OCCURRED;
-               break;
-
-       case FSG_STATE_INTERFACE_CHANGE:
-               rc = do_set_interface(fsg, 0);
-               if (fsg->ep0_req_tag != exception_req_tag)
-                       break;
-               if (rc != 0)                    // STALL on errors
-                       fsg_set_halt(fsg, fsg->ep0);
-               else                            // Complete the status stage
-                       ep0_queue(fsg);
-               break;
-
-       case FSG_STATE_CONFIG_CHANGE:
-               rc = do_set_config(fsg, new_config);
-               if (fsg->ep0_req_tag != exception_req_tag)
-                       break;
-               if (rc != 0)                    // STALL on errors
-                       fsg_set_halt(fsg, fsg->ep0);
-               else                            // Complete the status stage
-                       ep0_queue(fsg);
-               break;
-
-       case FSG_STATE_DISCONNECT:
-               for (i = 0; i < fsg->nluns; ++i)
-                       fsg_lun_fsync_sub(fsg->luns + i);
-               do_set_config(fsg, 0);          // Unconfigured state
-               break;
-
-       case FSG_STATE_EXIT:
-       case FSG_STATE_TERMINATED:
-               do_set_config(fsg, 0);                  // Free resources
-               spin_lock_irq(&fsg->lock);
-               fsg->state = FSG_STATE_TERMINATED;      // Stop the thread
-               spin_unlock_irq(&fsg->lock);
-               break;
-       }
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-static int fsg_main_thread(void *fsg_)
-{
-       struct fsg_dev          *fsg = fsg_;
-
-       /* Allow the thread to be killed by a signal, but set the signal mask
-        * to block everything but INT, TERM, KILL, and USR1. */
-       allow_signal(SIGINT);
-       allow_signal(SIGTERM);
-       allow_signal(SIGKILL);
-       allow_signal(SIGUSR1);
-
-       /* Allow the thread to be frozen */
-       set_freezable();
-
-       /* Arrange for userspace references to be interpreted as kernel
-        * pointers.  That way we can pass a kernel pointer to a routine
-        * that expects a __user pointer and it will work okay. */
-       set_fs(get_ds());
-
-       /* The main loop */
-       while (fsg->state != FSG_STATE_TERMINATED) {
-               if (exception_in_progress(fsg) || signal_pending(current)) {
-                       handle_exception(fsg);
-                       continue;
-               }
-
-               if (!fsg->running) {
-                       sleep_thread(fsg);
-                       continue;
-               }
-
-               if (get_next_command(fsg))
-                       continue;
-
-               spin_lock_irq(&fsg->lock);
-               if (!exception_in_progress(fsg))
-                       fsg->state = FSG_STATE_DATA_PHASE;
-               spin_unlock_irq(&fsg->lock);
-
-               if (do_scsi_command(fsg) || finish_reply(fsg))
-                       continue;
-
-               spin_lock_irq(&fsg->lock);
-               if (!exception_in_progress(fsg))
-                       fsg->state = FSG_STATE_STATUS_PHASE;
-               spin_unlock_irq(&fsg->lock);
-
-               if (send_status(fsg))
-                       continue;
-
-               spin_lock_irq(&fsg->lock);
-               if (!exception_in_progress(fsg))
-                       fsg->state = FSG_STATE_IDLE;
-               spin_unlock_irq(&fsg->lock);
-               }
-
-       spin_lock_irq(&fsg->lock);
-       fsg->thread_task = NULL;
-       spin_unlock_irq(&fsg->lock);
-
-       /* If we are exiting because of a signal, unregister the
-        * gadget driver. */
-       if (test_and_clear_bit(REGISTERED, &fsg->atomic_bitflags))
-               usb_gadget_unregister_driver(&fsg_driver);
-
-       /* Let the unbind and cleanup routines know the thread has exited */
-       complete_and_exit(&fsg->thread_notifier, 0);
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-
-/* The write permissions and store_xxx pointers are set in fsg_bind() */
-static DEVICE_ATTR(ro, 0444, fsg_show_ro, NULL);
-static DEVICE_ATTR(nofua, 0644, fsg_show_nofua, NULL);
-static DEVICE_ATTR(file, 0444, fsg_show_file, NULL);
-
-
-/*-------------------------------------------------------------------------*/
-
-static void fsg_release(struct kref *ref)
-{
-       struct fsg_dev  *fsg = container_of(ref, struct fsg_dev, ref);
-
-       kfree(fsg->luns);
-       kfree(fsg);
-}
-
-static void lun_release(struct device *dev)
-{
-       struct rw_semaphore     *filesem = dev_get_drvdata(dev);
-       struct fsg_dev          *fsg =
-               container_of(filesem, struct fsg_dev, filesem);
-
-       kref_put(&fsg->ref, fsg_release);
-}
-
-static void /* __init_or_exit */ fsg_unbind(struct usb_gadget *gadget)
-{
-       struct fsg_dev          *fsg = get_gadget_data(gadget);
-       int                     i;
-       struct fsg_lun          *curlun;
-       struct usb_request      *req = fsg->ep0req;
-
-       DBG(fsg, "unbind\n");
-       clear_bit(REGISTERED, &fsg->atomic_bitflags);
-
-       /* If the thread isn't already dead, tell it to exit now */
-       if (fsg->state != FSG_STATE_TERMINATED) {
-               raise_exception(fsg, FSG_STATE_EXIT);
-               wait_for_completion(&fsg->thread_notifier);
-
-               /* The cleanup routine waits for this completion also */
-               complete(&fsg->thread_notifier);
-       }
-
-       /* Unregister the sysfs attribute files and the LUNs */
-       for (i = 0; i < fsg->nluns; ++i) {
-               curlun = &fsg->luns[i];
-               if (curlun->registered) {
-                       device_remove_file(&curlun->dev, &dev_attr_nofua);
-                       device_remove_file(&curlun->dev, &dev_attr_ro);
-                       device_remove_file(&curlun->dev, &dev_attr_file);
-                       fsg_lun_close(curlun);
-                       device_unregister(&curlun->dev);
-                       curlun->registered = 0;
-               }
-       }
-
-       /* Free the data buffers */
-       for (i = 0; i < fsg_num_buffers; ++i)
-               kfree(fsg->buffhds[i].buf);
-
-       /* Free the request and buffer for endpoint 0 */
-       if (req) {
-               kfree(req->buf);
-               usb_ep_free_request(fsg->ep0, req);
-       }
-
-       set_gadget_data(gadget, NULL);
-}
-
-
-static int __init check_parameters(struct fsg_dev *fsg)
-{
-       int     prot;
-
-       /* Store the default values */
-       mod_data.transport_type = USB_PR_BULK;
-       mod_data.transport_name = "Bulk-only";
-       mod_data.protocol_type = USB_SC_SCSI;
-       mod_data.protocol_name = "Transparent SCSI";
-
-       /* Some peripheral controllers are known not to be able to
-        * halt bulk endpoints correctly.  If one of them is present,
-        * disable stalls.
-        */
-       if (gadget_is_at91(fsg->gadget))
-               mod_data.can_stall = 0;
-
-       if (mod_data.release == 0xffff)
-               mod_data.release = get_default_bcdDevice();
-
-       prot = simple_strtol(mod_data.protocol_parm, NULL, 0);
-
-#ifdef CONFIG_USB_FILE_STORAGE_TEST
-       if (strnicmp(mod_data.transport_parm, "BBB", 10) == 0) {
-               ;               // Use default setting
-       } else if (strnicmp(mod_data.transport_parm, "CB", 10) == 0) {
-               mod_data.transport_type = USB_PR_CB;
-               mod_data.transport_name = "Control-Bulk";
-       } else if (strnicmp(mod_data.transport_parm, "CBI", 10) == 0) {
-               mod_data.transport_type = USB_PR_CBI;
-               mod_data.transport_name = "Control-Bulk-Interrupt";
-       } else {
-               ERROR(fsg, "invalid transport: %s\n", mod_data.transport_parm);
-               return -EINVAL;
-       }
-
-       if (strnicmp(mod_data.protocol_parm, "SCSI", 10) == 0 ||
-                       prot == USB_SC_SCSI) {
-               ;               // Use default setting
-       } else if (strnicmp(mod_data.protocol_parm, "RBC", 10) == 0 ||
-                       prot == USB_SC_RBC) {
-               mod_data.protocol_type = USB_SC_RBC;
-               mod_data.protocol_name = "RBC";
-       } else if (strnicmp(mod_data.protocol_parm, "8020", 4) == 0 ||
-                       strnicmp(mod_data.protocol_parm, "ATAPI", 10) == 0 ||
-                       prot == USB_SC_8020) {
-               mod_data.protocol_type = USB_SC_8020;
-               mod_data.protocol_name = "8020i (ATAPI)";
-       } else if (strnicmp(mod_data.protocol_parm, "QIC", 3) == 0 ||
-                       prot == USB_SC_QIC) {
-               mod_data.protocol_type = USB_SC_QIC;
-               mod_data.protocol_name = "QIC-157";
-       } else if (strnicmp(mod_data.protocol_parm, "UFI", 10) == 0 ||
-                       prot == USB_SC_UFI) {
-               mod_data.protocol_type = USB_SC_UFI;
-               mod_data.protocol_name = "UFI";
-       } else if (strnicmp(mod_data.protocol_parm, "8070", 4) == 0 ||
-                       prot == USB_SC_8070) {
-               mod_data.protocol_type = USB_SC_8070;
-               mod_data.protocol_name = "8070i";
-       } else {
-               ERROR(fsg, "invalid protocol: %s\n", mod_data.protocol_parm);
-               return -EINVAL;
-       }
-
-       mod_data.buflen &= PAGE_CACHE_MASK;
-       if (mod_data.buflen <= 0) {
-               ERROR(fsg, "invalid buflen\n");
-               return -ETOOSMALL;
-       }
-
-#endif /* CONFIG_USB_FILE_STORAGE_TEST */
-
-       /* Serial string handling.
-        * On a real device, the serial string would be loaded
-        * from permanent storage. */
-       if (mod_data.serial) {
-               const char *ch;
-               unsigned len = 0;
-
-               /* Sanity check :
-                * The CB[I] specification limits the serial string to
-                * 12 uppercase hexadecimal characters.
-                * BBB need at least 12 uppercase hexadecimal characters,
-                * with a maximum of 126. */
-               for (ch = mod_data.serial; *ch; ++ch) {
-                       ++len;
-                       if ((*ch < '0' || *ch > '9') &&
-                           (*ch < 'A' || *ch > 'F')) { /* not uppercase hex */
-                               WARNING(fsg,
-                                       "Invalid serial string character: %c\n",
-                                       *ch);
-                               goto no_serial;
-                       }
-               }
-               if (len > 126 ||
-                   (mod_data.transport_type == USB_PR_BULK && len < 12) ||
-                   (mod_data.transport_type != USB_PR_BULK && len > 12)) {
-                       WARNING(fsg, "Invalid serial string length!\n");
-                       goto no_serial;
-               }
-               fsg_strings[FSG_STRING_SERIAL - 1].s = mod_data.serial;
-       } else {
-               WARNING(fsg, "No serial-number string provided!\n");
- no_serial:
-               device_desc.iSerialNumber = 0;
-       }
-
-       return 0;
-}
-
-
-static int __init fsg_bind(struct usb_gadget *gadget,
-               struct usb_gadget_driver *driver)
-{
-       struct fsg_dev          *fsg = the_fsg;
-       int                     rc;
-       int                     i;
-       struct fsg_lun          *curlun;
-       struct usb_ep           *ep;
-       struct usb_request      *req;
-       char                    *pathbuf, *p;
-
-       fsg->gadget = gadget;
-       set_gadget_data(gadget, fsg);
-       fsg->ep0 = gadget->ep0;
-       fsg->ep0->driver_data = fsg;
-
-       if ((rc = check_parameters(fsg)) != 0)
-               goto out;
-
-       if (mod_data.removable) {       // Enable the store_xxx attributes
-               dev_attr_file.attr.mode = 0644;
-               dev_attr_file.store = fsg_store_file;
-               if (!mod_data.cdrom) {
-                       dev_attr_ro.attr.mode = 0644;
-                       dev_attr_ro.store = fsg_store_ro;
-               }
-       }
-
-       /* Only for removable media? */
-       dev_attr_nofua.attr.mode = 0644;
-       dev_attr_nofua.store = fsg_store_nofua;
-
-       /* Find out how many LUNs there should be */
-       i = mod_data.nluns;
-       if (i == 0)
-               i = max(mod_data.num_filenames, 1u);
-       if (i > FSG_MAX_LUNS) {
-               ERROR(fsg, "invalid number of LUNs: %d\n", i);
-               rc = -EINVAL;
-               goto out;
-       }
-
-       /* Create the LUNs, open their backing files, and register the
-        * LUN devices in sysfs. */
-       fsg->luns = kzalloc(i * sizeof(struct fsg_lun), GFP_KERNEL);
-       if (!fsg->luns) {
-               rc = -ENOMEM;
-               goto out;
-       }
-       fsg->nluns = i;
-
-       for (i = 0; i < fsg->nluns; ++i) {
-               curlun = &fsg->luns[i];
-               curlun->cdrom = !!mod_data.cdrom;
-               curlun->ro = mod_data.cdrom || mod_data.ro[i];
-               curlun->initially_ro = curlun->ro;
-               curlun->removable = mod_data.removable;
-               curlun->nofua = mod_data.nofua[i];
-               curlun->dev.release = lun_release;
-               curlun->dev.parent = &gadget->dev;
-               curlun->dev.driver = &fsg_driver.driver;
-               dev_set_drvdata(&curlun->dev, &fsg->filesem);
-               dev_set_name(&curlun->dev,"%s-lun%d",
-                            dev_name(&gadget->dev), i);
-
-               kref_get(&fsg->ref);
-               rc = device_register(&curlun->dev);
-               if (rc) {
-                       INFO(fsg, "failed to register LUN%d: %d\n", i, rc);
-                       put_device(&curlun->dev);
-                       goto out;
-               }
-               curlun->registered = 1;
-
-               rc = device_create_file(&curlun->dev, &dev_attr_ro);
-               if (rc)
-                       goto out;
-               rc = device_create_file(&curlun->dev, &dev_attr_nofua);
-               if (rc)
-                       goto out;
-               rc = device_create_file(&curlun->dev, &dev_attr_file);
-               if (rc)
-                       goto out;
-
-               if (mod_data.file[i] && *mod_data.file[i]) {
-                       rc = fsg_lun_open(curlun, mod_data.file[i]);
-                       if (rc)
-                               goto out;
-               } else if (!mod_data.removable) {
-                       ERROR(fsg, "no file given for LUN%d\n", i);
-                       rc = -EINVAL;
-                       goto out;
-               }
-       }
-
-       /* Find all the endpoints we will use */
-       usb_ep_autoconfig_reset(gadget);
-       ep = usb_ep_autoconfig(gadget, &fsg_fs_bulk_in_desc);
-       if (!ep)
-               goto autoconf_fail;
-       ep->driver_data = fsg;          // claim the endpoint
-       fsg->bulk_in = ep;
-
-       ep = usb_ep_autoconfig(gadget, &fsg_fs_bulk_out_desc);
-       if (!ep)
-               goto autoconf_fail;
-       ep->driver_data = fsg;          // claim the endpoint
-       fsg->bulk_out = ep;
-
-       if (transport_is_cbi()) {
-               ep = usb_ep_autoconfig(gadget, &fsg_fs_intr_in_desc);
-               if (!ep)
-                       goto autoconf_fail;
-               ep->driver_data = fsg;          // claim the endpoint
-               fsg->intr_in = ep;
-       }
-
-       /* Fix up the descriptors */
-       device_desc.idVendor = cpu_to_le16(mod_data.vendor);
-       device_desc.idProduct = cpu_to_le16(mod_data.product);
-       device_desc.bcdDevice = cpu_to_le16(mod_data.release);
-
-       i = (transport_is_cbi() ? 3 : 2);       // Number of endpoints
-       fsg_intf_desc.bNumEndpoints = i;
-       fsg_intf_desc.bInterfaceSubClass = mod_data.protocol_type;
-       fsg_intf_desc.bInterfaceProtocol = mod_data.transport_type;
-       fsg_fs_function[i + FSG_FS_FUNCTION_PRE_EP_ENTRIES] = NULL;
-
-       if (gadget_is_dualspeed(gadget)) {
-               fsg_hs_function[i + FSG_HS_FUNCTION_PRE_EP_ENTRIES] = NULL;
-
-               /* 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;
-               fsg_hs_intr_in_desc.bEndpointAddress =
-                       fsg_fs_intr_in_desc.bEndpointAddress;
-       }
-
-       if (gadget_is_superspeed(gadget)) {
-               unsigned                max_burst;
-
-               fsg_ss_function[i + FSG_SS_FUNCTION_PRE_EP_ENTRIES] = NULL;
-
-               /* Calculate bMaxBurst, we know packet size is 1024 */
-               max_burst = min_t(unsigned, mod_data.buflen / 1024, 15);
-
-               /* Assume endpoint addresses are the same for both speeds */
-               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;
-       }
-
-       if (gadget_is_otg(gadget))
-               fsg_otg_desc.bmAttributes |= USB_OTG_HNP;
-
-       rc = -ENOMEM;
-
-       /* Allocate the request and buffer for endpoint 0 */
-       fsg->ep0req = req = usb_ep_alloc_request(fsg->ep0, GFP_KERNEL);
-       if (!req)
-               goto out;
-       req->buf = kmalloc(EP0_BUFSIZE, GFP_KERNEL);
-       if (!req->buf)
-               goto out;
-       req->complete = ep0_complete;
-
-       /* Allocate the data buffers */
-       for (i = 0; i < fsg_num_buffers; ++i) {
-               struct fsg_buffhd       *bh = &fsg->buffhds[i];
-
-               /* Allocate for the bulk-in endpoint.  We assume that
-                * the buffer will also work with the bulk-out (and
-                * interrupt-in) endpoint. */
-               bh->buf = kmalloc(mod_data.buflen, GFP_KERNEL);
-               if (!bh->buf)
-                       goto out;
-               bh->next = bh + 1;
-       }
-       fsg->buffhds[fsg_num_buffers - 1].next = &fsg->buffhds[0];
-
-       /* This should reflect the actual gadget power source */
-       usb_gadget_set_selfpowered(gadget);
-
-       snprintf(fsg_string_manufacturer, sizeof fsg_string_manufacturer,
-                       "%s %s with %s",
-                       init_utsname()->sysname, init_utsname()->release,
-                       gadget->name);
-
-       fsg->thread_task = kthread_create(fsg_main_thread, fsg,
-                       "file-storage-gadget");
-       if (IS_ERR(fsg->thread_task)) {
-               rc = PTR_ERR(fsg->thread_task);
-               goto out;
-       }
-
-       INFO(fsg, DRIVER_DESC ", version: " DRIVER_VERSION "\n");
-       INFO(fsg, "NOTE: This driver is deprecated.  "
-                       "Consider using g_mass_storage instead.\n");
-       INFO(fsg, "Number of LUNs=%d\n", fsg->nluns);
-
-       pathbuf = kmalloc(PATH_MAX, GFP_KERNEL);
-       for (i = 0; i < fsg->nluns; ++i) {
-               curlun = &fsg->luns[i];
-               if (fsg_lun_is_open(curlun)) {
-                       p = NULL;
-                       if (pathbuf) {
-                               p = d_path(&curlun->filp->f_path,
-                                          pathbuf, PATH_MAX);
-                               if (IS_ERR(p))
-                                       p = NULL;
-                       }
-                       LINFO(curlun, "ro=%d, nofua=%d, file: %s\n",
-                             curlun->ro, curlun->nofua, (p ? p : "(error)"));
-               }
-       }
-       kfree(pathbuf);
-
-       DBG(fsg, "transport=%s (x%02x)\n",
-                       mod_data.transport_name, mod_data.transport_type);
-       DBG(fsg, "protocol=%s (x%02x)\n",
-                       mod_data.protocol_name, mod_data.protocol_type);
-       DBG(fsg, "VendorID=x%04x, ProductID=x%04x, Release=x%04x\n",
-                       mod_data.vendor, mod_data.product, mod_data.release);
-       DBG(fsg, "removable=%d, stall=%d, cdrom=%d, buflen=%u\n",
-                       mod_data.removable, mod_data.can_stall,
-                       mod_data.cdrom, mod_data.buflen);
-       DBG(fsg, "I/O thread pid: %d\n", task_pid_nr(fsg->thread_task));
-
-       set_bit(REGISTERED, &fsg->atomic_bitflags);
-
-       /* Tell the thread to start working */
-       wake_up_process(fsg->thread_task);
-       return 0;
-
-autoconf_fail:
-       ERROR(fsg, "unable to autoconfigure all endpoints\n");
-       rc = -ENOTSUPP;
-
-out:
-       fsg->state = FSG_STATE_TERMINATED;      // The thread is dead
-       fsg_unbind(gadget);
-       complete(&fsg->thread_notifier);
-       return rc;
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-static void fsg_suspend(struct usb_gadget *gadget)
-{
-       struct fsg_dev          *fsg = get_gadget_data(gadget);
-
-       DBG(fsg, "suspend\n");
-       set_bit(SUSPENDED, &fsg->atomic_bitflags);
-}
-
-static void fsg_resume(struct usb_gadget *gadget)
-{
-       struct fsg_dev          *fsg = get_gadget_data(gadget);
-
-       DBG(fsg, "resume\n");
-       clear_bit(SUSPENDED, &fsg->atomic_bitflags);
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-static __refdata struct usb_gadget_driver              fsg_driver = {
-       .max_speed      = USB_SPEED_SUPER,
-       .function       = (char *) fsg_string_product,
-       .bind           = fsg_bind,
-       .unbind         = fsg_unbind,
-       .disconnect     = fsg_disconnect,
-       .setup          = fsg_setup,
-       .suspend        = fsg_suspend,
-       .resume         = fsg_resume,
-
-       .driver         = {
-               .name           = DRIVER_NAME,
-               .owner          = THIS_MODULE,
-               // .release = ...
-               // .suspend = ...
-               // .resume = ...
-       },
-};
-
-
-static int __init fsg_alloc(void)
-{
-       struct fsg_dev          *fsg;
-
-       fsg = kzalloc(sizeof *fsg +
-                     fsg_num_buffers * sizeof *(fsg->buffhds), GFP_KERNEL);
-
-       if (!fsg)
-               return -ENOMEM;
-       spin_lock_init(&fsg->lock);
-       init_rwsem(&fsg->filesem);
-       kref_init(&fsg->ref);
-       init_completion(&fsg->thread_notifier);
-
-       the_fsg = fsg;
-       return 0;
-}
-
-
-static int __init fsg_init(void)
-{
-       int             rc;
-       struct fsg_dev  *fsg;
-
-       rc = fsg_num_buffers_validate();
-       if (rc != 0)
-               return rc;
-
-       if ((rc = fsg_alloc()) != 0)
-               return rc;
-       fsg = the_fsg;
-       rc = usb_gadget_probe_driver(&fsg_driver);
-       if (rc != 0)
-               kref_put(&fsg->ref, fsg_release);
-       return rc;
-}
-module_init(fsg_init);
-
-
-static void __exit fsg_cleanup(void)
-{
-       struct fsg_dev  *fsg = the_fsg;
-
-       /* Unregister the driver iff the thread hasn't already done so */
-       if (test_and_clear_bit(REGISTERED, &fsg->atomic_bitflags))
-               usb_gadget_unregister_driver(&fsg_driver);
-
-       /* Wait for the thread to finish up */
-       wait_for_completion(&fsg->thread_notifier);
-
-       kref_put(&fsg->ref, fsg_release);
-}
-module_exit(fsg_cleanup);
index 6ae70cba0c4a99684b51b3e8cbbce890c63aaff1..c19f7f13790bf5be541b5e854beab49c969443ef 100644 (file)
@@ -2126,7 +2126,7 @@ static int fsl_proc_read(char *page, char **start, off_t off, int count,
 
        tmp_reg = fsl_readl(&dr_regs->usbintr);
        t = scnprintf(next, size,
-                       "USB Intrrupt Enable Reg:\n"
+                       "USB Interrupt Enable Reg:\n"
                        "Sleep Enable: %d SOF Received Enable: %d "
                        "Reset Enable: %d\n"
                        "System Error Enable: %d "
index 76494cabf4e46e28cb2771b1fdd3566b8e6cc5b2..8ac840f25ba9641f2939f807af8f4d768169702e 100644 (file)
@@ -76,7 +76,6 @@ MODULE_LICENSE ("GPL");
 /*----------------------------------------------------------------------*/
 
 #define GADGETFS_MAGIC         0xaee71ee7
-#define DMA_ADDR_INVALID       (~(dma_addr_t)0)
 
 /* /dev/gadget/$CHIP represents ep0 and the whole device */
 enum ep0_state {
@@ -918,7 +917,6 @@ static void clean_req (struct usb_ep *ep, struct usb_request *req)
        if (req->buf != dev->rbuf) {
                kfree(req->buf);
                req->buf = dev->rbuf;
-               req->dma = DMA_ADDR_INVALID;
        }
        req->complete = epio_complete;
        dev->setup_out_ready = 0;
@@ -1408,7 +1406,6 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
                dev->setup_abort = 1;
 
        req->buf = dev->rbuf;
-       req->dma = DMA_ADDR_INVALID;
        req->context = NULL;
        value = -EOPNOTSUPP;
        switch (ctrl->bRequest) {
index 21a9861dabf0a9660a3c1cf74f04d055fbb0b649..d1cf1f4db16aa6280e8f2e8f32ebc9f65ddb8c9a 100644 (file)
@@ -2399,7 +2399,7 @@ static void udc_handle_ep0_setup(struct lpc32xx_udc *udc)
 
                if (i < 0) {
                        /* setup processing failed, force stall */
-                       dev_err(udc->dev,
+                       dev_dbg(udc->dev,
                                "req %02x.%02x protocol STALL; stat %d\n",
                                reqtype, req, i);
                        udc->ep0state = WAIT_FOR_SETUP;
index ac335af154ba7fa45368378a9960e4bec616e148..708c0b55dcc8f87f4f66b0b7fbdb590a592e1a22 100644 (file)
@@ -9,7 +9,7 @@
  * CODE STATUS HIGHLIGHTS
  *
  * This driver should work well with most "gadget" drivers, including
- * the File Storage, Serial, and Ethernet/RNDIS gadget drivers
+ * the Mass Storage, Serial, and Ethernet/RNDIS gadget drivers
  * as well as Gadget Zero and Gadgetfs.
  *
  * DMA is enabled by default.  Drivers using transfer queues might use
index e156e3f267273c3a8b45b0a06025fcbd7e1541a1..35bcc83d1e0428388a30632c8f9b1c2e7f8212e8 100644 (file)
@@ -983,8 +983,10 @@ static int __init printer_func_bind(struct usb_configuration *c,
 {
        struct printer_dev *dev = container_of(f, struct printer_dev, function);
        struct usb_composite_dev *cdev = c->cdev;
-       struct usb_ep           *in_ep, *out_ep;
+       struct usb_ep *in_ep;
+       struct usb_ep *out_ep = NULL;
        int id;
+       int ret;
 
        id = usb_interface_id(c, f);
        if (id < 0)
@@ -1010,6 +1012,11 @@ autoconf_fail:
        hs_ep_in_desc.bEndpointAddress = fs_ep_in_desc.bEndpointAddress;
        hs_ep_out_desc.bEndpointAddress = fs_ep_out_desc.bEndpointAddress;
 
+       ret = usb_assign_descriptors(f, fs_printer_function,
+                       hs_printer_function, NULL);
+       if (ret)
+               return ret;
+
        dev->in_ep = in_ep;
        dev->out_ep = out_ep;
        return 0;
@@ -1018,6 +1025,7 @@ autoconf_fail:
 static void printer_func_unbind(struct usb_configuration *c,
                struct usb_function *f)
 {
+       usb_free_all_descriptors(f);
 }
 
 static int printer_func_set_alt(struct usb_function *f,
@@ -1110,8 +1118,6 @@ static int __init printer_bind_config(struct usb_configuration *c)
        dev = &usb_printer_gadget;
 
        dev->function.name = shortname;
-       dev->function.descriptors = fs_printer_function;
-       dev->function.hs_descriptors = hs_printer_function;
        dev->function.bind = printer_func_bind;
        dev->function.setup = printer_func_setup;
        dev->function.unbind = printer_func_unbind;
index a1d268c6f2ccb243249e19e7f2c7a87936ac2eec..79d81a4b234409b6943a49c6c978c42219149f94 100644 (file)
@@ -418,7 +418,7 @@ struct udc_stats {
  * @irq: udc irq
  * @clk: udc clock
  * @usb_gadget: udc gadget structure
- * @driver: bound gadget (zero, g_ether, g_file_storage, ...)
+ * @driver: bound gadget (zero, g_ether, g_mass_storage, ...)
  * @dev: device
  * @mach: machine info, used to activate specific GPIO
  * @transceiver: external transceiver to handle vbus sense and D+ pullup
index 8d9bcd8207c8d1fee7e47813d7d6ee7f76ca0b6b..0e3ae43454a246543317d323eb07667ae1693ea1 100644 (file)
  * (at your option) any later version.
  */
 
-
 /*
  * This file requires the following identifiers used in USB strings to
  * be defined (each of type pointer to char):
- *  - fsg_string_manufacturer -- name of the manufacturer
- *  - fsg_string_product      -- name of the product
- *  - fsg_string_config       -- name of the configuration
  *  - fsg_string_interface    -- name of the interface
- * The first four are only needed when FSG_DESCRIPTORS_DEVICE_STRINGS
- * macro is defined prior to including this file.
- */
-
-/*
- * When FSG_NO_INTR_EP is defined fsg_fs_intr_in_desc and
- * fsg_hs_intr_in_desc objects as well as
- * FSG_FS_FUNCTION_PRE_EP_ENTRIES and FSG_HS_FUNCTION_PRE_EP_ENTRIES
- * macros are not defined.
- *
- * When FSG_NO_DEVICE_STRINGS is defined FSG_STRING_MANUFACTURER,
- * FSG_STRING_PRODUCT, FSG_STRING_SERIAL and FSG_STRING_CONFIG are not
- * defined (as well as corresponding entries in string tables are
- * missing) and FSG_STRING_INTERFACE has value of zero.
- *
- * When FSG_NO_OTG is defined fsg_otg_desc won't be defined.
  */
 
 /*
 #define LWARN(lun, fmt, args...)  dev_warn(&(lun)->dev, fmt, ## args)
 #define LINFO(lun, fmt, args...)  dev_info(&(lun)->dev, fmt, ## args)
 
-/*
- * Keep those macros in sync with those in
- * include/linux/usb/composite.h or else GCC will complain.  If they
- * are identical (the same names of arguments, white spaces in the
- * same places) GCC will allow redefinition otherwise (even if some
- * white space is removed or added) warning will be issued.
- *
- * Those macros are needed here because File Storage Gadget does not
- * include the composite.h header.  For composite gadgets those macros
- * are redundant since composite.h is included any way.
- *
- * One could check whether those macros are already defined (which
- * would indicate composite.h had been included) or not (which would
- * indicate we were in FSG) but this is not done because a warning is
- * desired if definitions here differ from the ones in composite.h.
- *
- * We want the definitions to match and be the same in File Storage
- * Gadget as well as Mass Storage Function (and so composite gadgets
- * using MSF).  If someone changes them in composite.h it will produce
- * a warning in this file when building MSF.
- */
-#define DBG(d, fmt, args...)     dev_dbg(&(d)->gadget->dev , fmt , ## args)
-#define VDBG(d, fmt, args...)    dev_vdbg(&(d)->gadget->dev , fmt , ## args)
-#define ERROR(d, fmt, args...)   dev_err(&(d)->gadget->dev , fmt , ## args)
-#define WARNING(d, fmt, args...) dev_warn(&(d)->gadget->dev , fmt , ## args)
-#define INFO(d, fmt, args...)    dev_info(&(d)->gadget->dev , fmt , ## args)
-
-
 
 #ifdef DUMP_MSGS
 
@@ -203,9 +155,12 @@ struct fsg_lun {
        struct device   dev;
 };
 
-#define fsg_lun_is_open(curlun)        ((curlun)->filp != NULL)
+static inline bool fsg_lun_is_open(struct fsg_lun *curlun)
+{
+       return curlun->filp != NULL;
+}
 
-static struct fsg_lun *fsg_lun_from_dev(struct device *dev)
+static inline struct fsg_lun *fsg_lun_from_dev(struct device *dev)
 {
        return container_of(dev, struct fsg_lun, dev);
 }
@@ -308,26 +263,10 @@ static inline u32 get_unaligned_be24(u8 *buf)
 
 
 enum {
-#ifndef FSG_NO_DEVICE_STRINGS
-       FSG_STRING_MANUFACTURER = 1,
-       FSG_STRING_PRODUCT,
-       FSG_STRING_SERIAL,
-       FSG_STRING_CONFIG,
-#endif
        FSG_STRING_INTERFACE
 };
 
 
-#ifndef FSG_NO_OTG
-static struct usb_otg_descriptor
-fsg_otg_desc = {
-       .bLength =              sizeof fsg_otg_desc,
-       .bDescriptorType =      USB_DT_OTG,
-
-       .bmAttributes =         USB_OTG_SRP,
-};
-#endif
-
 /* There is only one interface. */
 
 static struct usb_interface_descriptor
@@ -367,37 +306,10 @@ fsg_fs_bulk_out_desc = {
        /* wMaxPacketSize set by autoconfiguration */
 };
 
-#ifndef FSG_NO_INTR_EP
-
-static struct usb_endpoint_descriptor
-fsg_fs_intr_in_desc = {
-       .bLength =              USB_DT_ENDPOINT_SIZE,
-       .bDescriptorType =      USB_DT_ENDPOINT,
-
-       .bEndpointAddress =     USB_DIR_IN,
-       .bmAttributes =         USB_ENDPOINT_XFER_INT,
-       .wMaxPacketSize =       cpu_to_le16(2),
-       .bInterval =            32,     /* frames -> 32 ms */
-};
-
-#ifndef FSG_NO_OTG
-#  define FSG_FS_FUNCTION_PRE_EP_ENTRIES       2
-#else
-#  define FSG_FS_FUNCTION_PRE_EP_ENTRIES       1
-#endif
-
-#endif
-
 static struct usb_descriptor_header *fsg_fs_function[] = {
-#ifndef FSG_NO_OTG
-       (struct usb_descriptor_header *) &fsg_otg_desc,
-#endif
        (struct usb_descriptor_header *) &fsg_intf_desc,
        (struct usb_descriptor_header *) &fsg_fs_bulk_in_desc,
        (struct usb_descriptor_header *) &fsg_fs_bulk_out_desc,
-#ifndef FSG_NO_INTR_EP
-       (struct usb_descriptor_header *) &fsg_fs_intr_in_desc,
-#endif
        NULL,
 };
 
@@ -431,37 +343,11 @@ fsg_hs_bulk_out_desc = {
        .bInterval =            1,      /* NAK every 1 uframe */
 };
 
-#ifndef FSG_NO_INTR_EP
-
-static struct usb_endpoint_descriptor
-fsg_hs_intr_in_desc = {
-       .bLength =              USB_DT_ENDPOINT_SIZE,
-       .bDescriptorType =      USB_DT_ENDPOINT,
-
-       /* bEndpointAddress copied from fs_intr_in_desc during fsg_bind() */
-       .bmAttributes =         USB_ENDPOINT_XFER_INT,
-       .wMaxPacketSize =       cpu_to_le16(2),
-       .bInterval =            9,      /* 2**(9-1) = 256 uframes -> 32 ms */
-};
-
-#ifndef FSG_NO_OTG
-#  define FSG_HS_FUNCTION_PRE_EP_ENTRIES       2
-#else
-#  define FSG_HS_FUNCTION_PRE_EP_ENTRIES       1
-#endif
-
-#endif
 
 static struct usb_descriptor_header *fsg_hs_function[] = {
-#ifndef FSG_NO_OTG
-       (struct usb_descriptor_header *) &fsg_otg_desc,
-#endif
        (struct usb_descriptor_header *) &fsg_intf_desc,
        (struct usb_descriptor_header *) &fsg_hs_bulk_in_desc,
        (struct usb_descriptor_header *) &fsg_hs_bulk_out_desc,
-#ifndef FSG_NO_INTR_EP
-       (struct usb_descriptor_header *) &fsg_hs_intr_in_desc,
-#endif
        NULL,
 };
 
@@ -499,34 +385,6 @@ static struct usb_ss_ep_comp_descriptor fsg_ss_bulk_out_comp_desc = {
        /*.bMaxBurst =          DYNAMIC, */
 };
 
-#ifndef FSG_NO_INTR_EP
-
-static struct usb_endpoint_descriptor
-fsg_ss_intr_in_desc = {
-       .bLength =              USB_DT_ENDPOINT_SIZE,
-       .bDescriptorType =      USB_DT_ENDPOINT,
-
-       /* bEndpointAddress copied from fs_intr_in_desc during fsg_bind() */
-       .bmAttributes =         USB_ENDPOINT_XFER_INT,
-       .wMaxPacketSize =       cpu_to_le16(2),
-       .bInterval =            9,      /* 2**(9-1) = 256 uframes -> 32 ms */
-};
-
-static struct usb_ss_ep_comp_descriptor fsg_ss_intr_in_comp_desc = {
-       .bLength =              sizeof(fsg_ss_bulk_in_comp_desc),
-       .bDescriptorType =      USB_DT_SS_ENDPOINT_COMP,
-
-       .wBytesPerInterval =    cpu_to_le16(2),
-};
-
-#ifndef FSG_NO_OTG
-#  define FSG_SS_FUNCTION_PRE_EP_ENTRIES       2
-#else
-#  define FSG_SS_FUNCTION_PRE_EP_ENTRIES       1
-#endif
-
-#endif
-
 static __maybe_unused struct usb_ext_cap_descriptor fsg_ext_cap_desc = {
        .bLength =              USB_DT_USB_EXT_CAP_SIZE,
        .bDescriptorType =      USB_DT_DEVICE_CAPABILITY,
@@ -563,18 +421,11 @@ static __maybe_unused struct usb_bos_descriptor fsg_bos_desc = {
 };
 
 static struct usb_descriptor_header *fsg_ss_function[] = {
-#ifndef FSG_NO_OTG
-       (struct usb_descriptor_header *) &fsg_otg_desc,
-#endif
        (struct usb_descriptor_header *) &fsg_intf_desc,
        (struct usb_descriptor_header *) &fsg_ss_bulk_in_desc,
        (struct usb_descriptor_header *) &fsg_ss_bulk_in_comp_desc,
        (struct usb_descriptor_header *) &fsg_ss_bulk_out_desc,
        (struct usb_descriptor_header *) &fsg_ss_bulk_out_comp_desc,
-#ifndef FSG_NO_INTR_EP
-       (struct usb_descriptor_header *) &fsg_ss_intr_in_desc,
-       (struct usb_descriptor_header *) &fsg_ss_intr_in_comp_desc,
-#endif
        NULL,
 };
 
@@ -594,12 +445,6 @@ fsg_ep_desc(struct usb_gadget *g, struct usb_endpoint_descriptor *fs,
 
 /* Static strings, in UTF-8 (for simplicity we use only ASCII characters) */
 static struct usb_string               fsg_strings[] = {
-#ifndef FSG_NO_DEVICE_STRINGS
-       {FSG_STRING_MANUFACTURER,       fsg_string_manufacturer},
-       {FSG_STRING_PRODUCT,            fsg_string_product},
-       {FSG_STRING_SERIAL,             ""},
-       {FSG_STRING_CONFIG,             fsg_string_config},
-#endif
        {FSG_STRING_INTERFACE,          fsg_string_interface},
        {}
 };
index 97e68b38cfdf5ebab332f1ae0f670ed7b7edc56b..4f7f76f00c7452239067a5b5498a500d26093f50 100644 (file)
@@ -1384,7 +1384,7 @@ static struct se_node_acl *usbg_alloc_fabric_acl(struct se_portal_group *se_tpg)
 
        nacl = kzalloc(sizeof(struct usbg_nacl), GFP_KERNEL);
        if (!nacl) {
-               printk(KERN_ERR "Unable to alocate struct usbg_nacl\n");
+               printk(KERN_ERR "Unable to allocate struct usbg_nacl\n");
                return NULL;
        }
 
@@ -2139,6 +2139,7 @@ static struct usb_descriptor_header *uasp_fs_function_desc[] = {
        (struct usb_descriptor_header *) &uasp_status_pipe_desc,
        (struct usb_descriptor_header *) &uasp_fs_cmd_desc,
        (struct usb_descriptor_header *) &uasp_cmd_pipe_desc,
+       NULL,
 };
 
 static struct usb_descriptor_header *uasp_hs_function_desc[] = {
@@ -2239,6 +2240,7 @@ static int usbg_bind(struct usb_configuration *c, struct usb_function *f)
        struct usb_gadget       *gadget = c->cdev->gadget;
        struct usb_ep           *ep;
        int                     iface;
+       int                     ret;
 
        iface = usb_interface_id(c, f);
        if (iface < 0)
@@ -2289,6 +2291,11 @@ static int usbg_bind(struct usb_configuration *c, struct usb_function *f)
                uasp_ss_status_desc.bEndpointAddress;
        uasp_fs_cmd_desc.bEndpointAddress = uasp_ss_cmd_desc.bEndpointAddress;
 
+       ret = usb_assign_descriptors(f, uasp_fs_function_desc,
+                       uasp_hs_function_desc, uasp_ss_function_desc);
+       if (ret)
+               goto ep_fail;
+
        return 0;
 ep_fail:
        pr_err("Can't claim all required eps\n");
@@ -2304,6 +2311,7 @@ static void usbg_unbind(struct usb_configuration *c, struct usb_function *f)
 {
        struct f_uas *fu = to_f_uas(f);
 
+       usb_free_all_descriptors(f);
        kfree(fu);
 }
 
@@ -2384,9 +2392,6 @@ static int usbg_cfg_bind(struct usb_configuration *c)
        if (!fu)
                return -ENOMEM;
        fu->function.name = "Target Function";
-       fu->function.descriptors = uasp_fs_function_desc;
-       fu->function.hs_descriptors = uasp_hs_function_desc;
-       fu->function.ss_descriptors = uasp_ss_function_desc;
        fu->function.bind = usbg_bind;
        fu->function.unbind = usbg_unbind;
        fu->function.set_alt = usbg_set_alt;
index f3cd9690b101d6945fca7924e40ebfdd5df608f1..4d90a800063ce93a66a2486f95bfd1273c348d7d 100644 (file)
@@ -439,16 +439,6 @@ static DEVICE_ATTR(name, S_IRUSR, usb_udc_##param##_show, NULL)
 static USB_UDC_SPEED_ATTR(current_speed, speed);
 static USB_UDC_SPEED_ATTR(maximum_speed, max_speed);
 
-/* TODO: Scheduled for removal in 3.8. */
-static ssize_t usb_udc_is_dualspeed_show(struct device *dev,
-               struct device_attribute *attr, char *buf)
-{
-       struct usb_udc          *udc = container_of(dev, struct usb_udc, dev);
-       return snprintf(buf, PAGE_SIZE, "%d\n",
-                       gadget_is_dualspeed(udc->gadget));
-}
-static DEVICE_ATTR(is_dualspeed, S_IRUSR, usb_udc_is_dualspeed_show, NULL);
-
 #define USB_UDC_ATTR(name)                                     \
 ssize_t usb_udc_##name##_show(struct device *dev,              \
                struct device_attribute *attr, char *buf)       \
@@ -472,7 +462,6 @@ static struct attribute *usb_udc_attrs[] = {
        &dev_attr_current_speed.attr,
        &dev_attr_maximum_speed.attr,
 
-       &dev_attr_is_dualspeed.attr,
        &dev_attr_is_otg.attr,
        &dev_attr_is_a_peripheral.attr,
        &dev_attr_b_hnp_enable.attr,
index 3f1431d37e1c836f88b32aff5b002fb9cf4efa0b..d6bb128ce21ee424a02dfb7db31c96bc88c9af44 100644 (file)
@@ -95,6 +95,11 @@ config USB_EHCI_TT_NEWSCHED
 
          If unsure, say Y.
 
+config USB_EHCI_PCI
+       tristate
+       depends on USB_EHCI_HCD && PCI
+       default y
+
 config USB_EHCI_HCD_PMC_MSP
        tristate "EHCI support for on-chip PMC MSP71xx USB controller"
        depends on USB_EHCI_HCD && MSP_HAS_USB
@@ -215,9 +220,13 @@ config USB_W90X900_EHCI
                Enables support for the W90X900 USB controller
 
 config USB_CNS3XXX_EHCI
-       bool "Cavium CNS3XXX EHCI Module"
+       bool "Cavium CNS3XXX EHCI Module (DEPRECATED)"
        depends on USB_EHCI_HCD && ARCH_CNS3XXX
+       select USB_EHCI_HCD_PLATFORM
        ---help---
+         This option is deprecated now and the driver was removed, use
+         USB_EHCI_HCD_PLATFORM instead.
+
          Enable support for the CNS3XXX SOC's on-chip EHCI controller.
          It is needed for high-speed (480Mbit/sec) USB 2.0 device
          support.
@@ -333,16 +342,6 @@ config USB_OHCI_ATH79
          Enables support for the built-in OHCI controller present on the
          Atheros AR71XX/AR7240 SoCs.
 
-config USB_OHCI_HCD_PPC_SOC
-       bool "OHCI support for on-chip PPC USB controller"
-       depends on USB_OHCI_HCD && (STB03xxx || PPC_MPC52xx)
-       default y
-       select USB_OHCI_BIG_ENDIAN_DESC
-       select USB_OHCI_BIG_ENDIAN_MMIO
-       ---help---
-         Enables support for the USB controller on the MPC52xx or
-         STB03xxx processor chip.  If unsure, say Y.
-
 config USB_OHCI_HCD_PPC_OF_BE
        bool "OHCI support for OF platform bus (big endian)"
        depends on USB_OHCI_HCD && PPC_OF
@@ -393,9 +392,13 @@ config USB_OHCI_HCD_SSB
          If unsure, say N.
 
 config USB_OHCI_SH
-       bool "OHCI support for SuperH USB controller"
+       bool "OHCI support for SuperH USB controller (DEPRECATED)"
        depends on USB_OHCI_HCD && SUPERH
+       select USB_OHCI_HCD_PLATFORM
        ---help---
+         This option is deprecated now and the driver was removed, use
+         USB_OHCI_HCD_PLATFORM instead.
+
          Enables support for the on-chip OHCI controller on the SuperH.
          If you use the PCI OHCI controller, this option is not necessary.
 
@@ -406,9 +409,13 @@ config USB_OHCI_EXYNOS
         Enable support for the Samsung Exynos SOC's on-chip OHCI controller.
 
 config USB_CNS3XXX_OHCI
-       bool "Cavium CNS3XXX OHCI Module"
+       bool "Cavium CNS3XXX OHCI Module (DEPRECATED)"
        depends on USB_OHCI_HCD && ARCH_CNS3XXX
+       select USB_OHCI_HCD_PLATFORM
        ---help---
+         This option is deprecated now and the driver was removed, use
+         USB_OHCI_HCD_PLATFORM instead.
+
          Enable support for the CNS3XXX SOC's on-chip OHCI controller.
          It is needed for low-speed USB 1.0 device support.
 
@@ -423,7 +430,7 @@ config USB_OHCI_HCD_PLATFORM
          If unsure, say N.
 
 config USB_EHCI_HCD_PLATFORM
-       bool "Generic EHCI driver for a platform device"
+       tristate "Generic EHCI driver for a platform device"
        depends on USB_EHCI_HCD
        default n
        ---help---
index 9e0a89ced15cb3aa6d699aabd5be7a34df9e53c0..1eb4c3006e9eab8b7d2588c0322d38b9ad724327 100644 (file)
@@ -24,6 +24,9 @@ obj-$(CONFIG_USB_WHCI_HCD)    += whci/
 obj-$(CONFIG_PCI)              += pci-quirks.o
 
 obj-$(CONFIG_USB_EHCI_HCD)     += ehci-hcd.o
+obj-$(CONFIG_USB_EHCI_PCI)     += ehci-pci.o
+obj-$(CONFIG_USB_EHCI_HCD_PLATFORM)    += ehci-platform.o
+
 obj-$(CONFIG_USB_OXU210HP_HCD) += oxu210hp-hcd.o
 obj-$(CONFIG_USB_ISP116X_HCD)  += isp116x-hcd.o
 obj-$(CONFIG_USB_ISP1362_HCD)  += isp1362-hcd.o
@@ -40,6 +43,5 @@ obj-$(CONFIG_USB_HWA_HCD)     += hwa-hc.o
 obj-$(CONFIG_USB_IMX21_HCD)    += imx21-hcd.o
 obj-$(CONFIG_USB_FSL_MPH_DR_OF)        += fsl-mph-dr-of.o
 obj-$(CONFIG_USB_OCTEON2_COMMON) += octeon2-common.o
-obj-$(CONFIG_MIPS_ALCHEMY)     += alchemy-common.o
 obj-$(CONFIG_USB_HCD_BCMA)     += bcma-hcd.o
 obj-$(CONFIG_USB_HCD_SSB)      += ssb-hcd.o
index 411bb74152ebe2ba3b063fb0e5e3445626d61af1..d23321ec0e46121082c97a8e0b6d67074fd19d3c 100644 (file)
@@ -53,18 +53,11 @@ static void atmel_stop_ehci(struct platform_device *pdev)
 static int ehci_atmel_setup(struct usb_hcd *hcd)
 {
        struct ehci_hcd *ehci = hcd_to_ehci(hcd);
-       int retval;
 
        /* registers start at offset 0x0 */
        ehci->caps = hcd->regs;
 
-       retval = ehci_setup(hcd);
-       if (retval)
-               return retval;
-
-       ehci_port_power(ehci, 0);
-
-       return retval;
+       return ehci_setup(hcd);
 }
 
 static const struct hc_driver ehci_atmel_hc_driver = {
diff --git a/drivers/usb/host/ehci-au1xxx.c b/drivers/usb/host/ehci-au1xxx.c
deleted file mode 100644 (file)
index 65c945e..0000000
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * EHCI HCD (Host Controller Driver) for USB.
- *
- * Bus Glue for AMD Alchemy Au1xxx
- *
- * Based on "ohci-au1xxx.c" by Matt Porter <mporter@kernel.crashing.org>
- *
- * Modified for AMD Alchemy Au1200 EHC
- *  by K.Boge <karsten.boge@amd.com>
- *
- * This file is licenced under the GPL.
- */
-
-#include <linux/platform_device.h>
-#include <asm/mach-au1x00/au1000.h>
-
-
-extern int usb_disabled(void);
-
-static int au1xxx_ehci_setup(struct usb_hcd *hcd)
-{
-       struct ehci_hcd *ehci = hcd_to_ehci(hcd);
-       int ret;
-
-       ehci->caps = hcd->regs;
-       ret = ehci_setup(hcd);
-
-       ehci->need_io_watchdog = 0;
-       return ret;
-}
-
-static const struct hc_driver ehci_au1xxx_hc_driver = {
-       .description            = hcd_name,
-       .product_desc           = "Au1xxx EHCI",
-       .hcd_priv_size          = sizeof(struct ehci_hcd),
-
-       /*
-        * generic hardware linkage
-        */
-       .irq                    = ehci_irq,
-       .flags                  = HCD_MEMORY | HCD_USB2,
-
-       /*
-        * basic lifecycle operations
-        *
-        * FIXME -- ehci_init() doesn't do enough here.
-        * See ehci-ppc-soc for a complete implementation.
-        */
-       .reset                  = au1xxx_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 int ehci_hcd_au1xxx_drv_probe(struct platform_device *pdev)
-{
-       struct usb_hcd *hcd;
-       struct resource *res;
-       int ret;
-
-       if (usb_disabled())
-               return -ENODEV;
-
-       if (pdev->resource[1].flags != IORESOURCE_IRQ) {
-               pr_debug("resource[1] is not IORESOURCE_IRQ");
-               return -ENOMEM;
-       }
-       hcd = usb_create_hcd(&ehci_au1xxx_hc_driver, &pdev->dev, "Au1xxx");
-       if (!hcd)
-               return -ENOMEM;
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       hcd->rsrc_start = res->start;
-       hcd->rsrc_len = resource_size(res);
-
-       hcd->regs = devm_request_and_ioremap(&pdev->dev, res);
-       if (!hcd->regs) {
-               pr_debug("devm_request_and_ioremap failed");
-               ret = -ENOMEM;
-               goto err1;
-       }
-
-       if (alchemy_usb_control(ALCHEMY_USB_EHCI0, 1)) {
-               printk(KERN_INFO "%s: controller init failed!\n", pdev->name);
-               ret = -ENODEV;
-               goto err1;
-       }
-
-       ret = usb_add_hcd(hcd, pdev->resource[1].start,
-                         IRQF_SHARED);
-       if (ret == 0) {
-               platform_set_drvdata(pdev, hcd);
-               return ret;
-       }
-
-       alchemy_usb_control(ALCHEMY_USB_EHCI0, 0);
-err1:
-       usb_put_hcd(hcd);
-       return ret;
-}
-
-static int ehci_hcd_au1xxx_drv_remove(struct platform_device *pdev)
-{
-       struct usb_hcd *hcd = platform_get_drvdata(pdev);
-
-       usb_remove_hcd(hcd);
-       alchemy_usb_control(ALCHEMY_USB_EHCI0, 0);
-       usb_put_hcd(hcd);
-       platform_set_drvdata(pdev, NULL);
-
-       return 0;
-}
-
-#ifdef CONFIG_PM
-static int ehci_hcd_au1xxx_drv_suspend(struct device *dev)
-{
-       struct usb_hcd *hcd = dev_get_drvdata(dev);
-       bool do_wakeup = device_may_wakeup(dev);
-       int rc;
-
-       rc = ehci_suspend(hcd, do_wakeup);
-       alchemy_usb_control(ALCHEMY_USB_EHCI0, 0);
-
-       return rc;
-}
-
-static int ehci_hcd_au1xxx_drv_resume(struct device *dev)
-{
-       struct usb_hcd *hcd = dev_get_drvdata(dev);
-
-       alchemy_usb_control(ALCHEMY_USB_EHCI0, 1);
-       ehci_resume(hcd, false);
-
-       return 0;
-}
-
-static const struct dev_pm_ops au1xxx_ehci_pmops = {
-       .suspend        = ehci_hcd_au1xxx_drv_suspend,
-       .resume         = ehci_hcd_au1xxx_drv_resume,
-};
-
-#define AU1XXX_EHCI_PMOPS &au1xxx_ehci_pmops
-
-#else
-#define AU1XXX_EHCI_PMOPS NULL
-#endif
-
-static struct platform_driver ehci_hcd_au1xxx_driver = {
-       .probe          = ehci_hcd_au1xxx_drv_probe,
-       .remove         = ehci_hcd_au1xxx_drv_remove,
-       .shutdown       = usb_hcd_platform_shutdown,
-       .driver = {
-               .name   = "au1xxx-ehci",
-               .owner  = THIS_MODULE,
-               .pm     = AU1XXX_EHCI_PMOPS,
-       }
-};
-
-MODULE_ALIAS("platform:au1xxx-ehci");
diff --git a/drivers/usb/host/ehci-cns3xxx.c b/drivers/usb/host/ehci-cns3xxx.c
deleted file mode 100644 (file)
index d91708d..0000000
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * Copyright 2008 Cavium Networks
- *
- * This file is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License, Version 2, as
- * published by the Free Software Foundation.
- */
-
-#include <linux/platform_device.h>
-#include <linux/atomic.h>
-#include <mach/cns3xxx.h>
-#include <mach/pm.h>
-
-static int cns3xxx_ehci_init(struct usb_hcd *hcd)
-{
-       struct ehci_hcd *ehci = hcd_to_ehci(hcd);
-       int retval;
-
-       /*
-        * 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);
-       }
-
-       ehci->caps = hcd->regs;
-
-       hcd->has_tt = 0;
-
-       retval = ehci_setup(hcd);
-       if (retval)
-               return retval;
-
-       ehci_port_power(ehci, 0);
-
-       return retval;
-}
-
-static const struct hc_driver cns3xxx_ehci_hc_driver = {
-       .description            = hcd_name,
-       .product_desc           = "CNS3XXX EHCI Host Controller",
-       .hcd_priv_size          = sizeof(struct ehci_hcd),
-       .irq                    = ehci_irq,
-       .flags                  = HCD_MEMORY | HCD_USB2,
-       .reset                  = cns3xxx_ehci_init,
-       .start                  = ehci_run,
-       .stop                   = ehci_stop,
-       .shutdown               = ehci_shutdown,
-       .urb_enqueue            = ehci_urb_enqueue,
-       .urb_dequeue            = ehci_urb_dequeue,
-       .endpoint_disable       = ehci_endpoint_disable,
-       .endpoint_reset         = ehci_endpoint_reset,
-       .get_frame_number       = ehci_get_frame,
-       .hub_status_data        = ehci_hub_status_data,
-       .hub_control            = ehci_hub_control,
-#ifdef CONFIG_PM
-       .bus_suspend            = ehci_bus_suspend,
-       .bus_resume             = ehci_bus_resume,
-#endif
-       .relinquish_port        = ehci_relinquish_port,
-       .port_handed_over       = ehci_port_handed_over,
-
-       .clear_tt_buffer_complete       = ehci_clear_tt_buffer_complete,
-};
-
-static int cns3xxx_ehci_probe(struct platform_device *pdev)
-{
-       struct device *dev = &pdev->dev;
-       struct usb_hcd *hcd;
-       const struct hc_driver *driver = &cns3xxx_ehci_hc_driver;
-       struct resource *res;
-       int irq;
-       int retval;
-
-       if (usb_disabled())
-               return -ENODEV;
-
-       res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-       if (!res) {
-               dev_err(dev, "Found HC with no IRQ.\n");
-               return -ENODEV;
-       }
-       irq = res->start;
-
-       hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev));
-       if (!hcd)
-               return -ENOMEM;
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               dev_err(dev, "Found HC with no register addr.\n");
-               retval = -ENODEV;
-               goto err1;
-       }
-
-       hcd->rsrc_start = res->start;
-       hcd->rsrc_len = resource_size(res);
-
-       hcd->regs = devm_request_and_ioremap(&pdev->dev, res);
-       if (hcd->regs == NULL) {
-               dev_dbg(dev, "error mapping memory\n");
-               retval = -EFAULT;
-               goto err1;
-       }
-
-       retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
-       if (retval == 0)
-               return retval;
-
-err1:
-       usb_put_hcd(hcd);
-
-       return retval;
-}
-
-static int cns3xxx_ehci_remove(struct platform_device *pdev)
-{
-       struct usb_hcd *hcd = platform_get_drvdata(pdev);
-
-       usb_remove_hcd(hcd);
-
-       /*
-        * 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);
-
-       usb_put_hcd(hcd);
-
-       platform_set_drvdata(pdev, NULL);
-
-       return 0;
-}
-
-MODULE_ALIAS("platform:cns3xxx-ehci");
-
-static struct platform_driver cns3xxx_ehci_driver = {
-       .probe = cns3xxx_ehci_probe,
-       .remove = cns3xxx_ehci_remove,
-       .driver = {
-               .name = "cns3xxx-ehci",
-       },
-};
index 1599806e3d47cddd7de228a4bb779b2a5e11fdd9..70b496dc18a008c0bbfc261f5005bdd5ca50d204 100644 (file)
 
 /* this file is part of ehci-hcd.c */
 
-#define ehci_dbg(ehci, fmt, args...) \
-       dev_dbg (ehci_to_hcd(ehci)->self.controller , fmt , ## args )
-#define ehci_err(ehci, fmt, args...) \
-       dev_err (ehci_to_hcd(ehci)->self.controller , fmt , ## args )
-#define ehci_info(ehci, fmt, args...) \
-       dev_info (ehci_to_hcd(ehci)->self.controller , fmt , ## args )
-#define ehci_warn(ehci, fmt, args...) \
-       dev_warn (ehci_to_hcd(ehci)->self.controller , fmt , ## args )
-
-#ifdef VERBOSE_DEBUG
-#      define ehci_vdbg ehci_dbg
-#else
-       static inline void ehci_vdbg(struct ehci_hcd *ehci, ...) {}
-#endif
-
 #ifdef DEBUG
 
 /* check the values in the HCSPARAMS register
@@ -352,11 +337,6 @@ static int debug_async_open(struct inode *, struct file *);
 static int debug_periodic_open(struct inode *, struct file *);
 static int debug_registers_open(struct inode *, struct file *);
 static int debug_async_open(struct inode *, struct file *);
-static ssize_t debug_lpm_read(struct file *file, char __user *user_buf,
-                                  size_t count, loff_t *ppos);
-static ssize_t debug_lpm_write(struct file *file, const char __user *buffer,
-                             size_t count, loff_t *ppos);
-static int debug_lpm_close(struct inode *inode, struct file *file);
 
 static ssize_t debug_output(struct file*, char __user*, size_t, loff_t*);
 static int debug_close(struct inode *, struct file *);
@@ -382,14 +362,6 @@ static const struct file_operations debug_registers_fops = {
        .release        = debug_close,
        .llseek         = default_llseek,
 };
-static const struct file_operations debug_lpm_fops = {
-       .owner          = THIS_MODULE,
-       .open           = simple_open,
-       .read           = debug_lpm_read,
-       .write          = debug_lpm_write,
-       .release        = debug_lpm_close,
-       .llseek         = noop_llseek,
-};
 
 static struct dentry *ehci_debug_root;
 
@@ -971,86 +943,6 @@ static int debug_registers_open(struct inode *inode, struct file *file)
        return file->private_data ? 0 : -ENOMEM;
 }
 
-static int debug_lpm_close(struct inode *inode, struct file *file)
-{
-       return 0;
-}
-
-static ssize_t debug_lpm_read(struct file *file, char __user *user_buf,
-                                  size_t count, loff_t *ppos)
-{
-       /* TODO: show lpm stats */
-       return 0;
-}
-
-static ssize_t debug_lpm_write(struct file *file, const char __user *user_buf,
-                             size_t count, loff_t *ppos)
-{
-       struct usb_hcd          *hcd;
-       struct ehci_hcd         *ehci;
-       char buf[50];
-       size_t len;
-       u32 temp;
-       unsigned long port;
-       u32 __iomem     *portsc ;
-       u32 params;
-
-       hcd = bus_to_hcd(file->private_data);
-       ehci = hcd_to_ehci(hcd);
-
-       len = min(count, sizeof(buf) - 1);
-       if (copy_from_user(buf, user_buf, len))
-               return -EFAULT;
-       buf[len] = '\0';
-       if (len > 0 && buf[len - 1] == '\n')
-               buf[len - 1] = '\0';
-
-       if (strncmp(buf, "enable", 5) == 0) {
-               if (strict_strtoul(buf + 7, 10, &port))
-                       return -EINVAL;
-               params = ehci_readl(ehci, &ehci->caps->hcs_params);
-               if (port > HCS_N_PORTS(params)) {
-                       ehci_dbg(ehci, "ERR: LPM on bad port %lu\n", port);
-                       return -ENODEV;
-               }
-               portsc = &ehci->regs->port_status[port-1];
-               temp = ehci_readl(ehci, portsc);
-               if (!(temp & PORT_DEV_ADDR)) {
-                       ehci_dbg(ehci, "LPM: no device attached\n");
-                       return -ENODEV;
-               }
-               temp |= PORT_LPM;
-               ehci_writel(ehci, temp, portsc);
-               printk(KERN_INFO "force enable LPM for port %lu\n", port);
-       } else if (strncmp(buf, "hird=", 5) == 0) {
-               unsigned long hird;
-               if (strict_strtoul(buf + 5, 16, &hird))
-                       return -EINVAL;
-               printk(KERN_INFO "setting hird %s %lu\n", buf + 6, hird);
-               ehci->command = (ehci->command & ~CMD_HIRD) | (hird << 24);
-               ehci_writel(ehci, ehci->command, &ehci->regs->command);
-       } else if (strncmp(buf, "disable", 7) == 0) {
-               if (strict_strtoul(buf + 8, 10, &port))
-                       return -EINVAL;
-               params = ehci_readl(ehci, &ehci->caps->hcs_params);
-               if (port > HCS_N_PORTS(params)) {
-                       ehci_dbg(ehci, "ERR: LPM off bad port %lu\n", port);
-                       return -ENODEV;
-               }
-               portsc = &ehci->regs->port_status[port-1];
-               temp = ehci_readl(ehci, portsc);
-               if (!(temp & PORT_DEV_ADDR)) {
-                       ehci_dbg(ehci, "ERR: no device attached\n");
-                       return -ENODEV;
-               }
-               temp &= ~PORT_LPM;
-               ehci_writel(ehci, temp, portsc);
-               printk(KERN_INFO "disabled LPM for port %lu\n", port);
-       } else
-               return -EOPNOTSUPP;
-       return count;
-}
-
 static inline void create_debug_files (struct ehci_hcd *ehci)
 {
        struct usb_bus *bus = &ehci_to_hcd(ehci)->self;
@@ -1071,10 +963,6 @@ static inline void create_debug_files (struct ehci_hcd *ehci)
                                                    &debug_registers_fops))
                goto file_error;
 
-       if (!debugfs_create_file("lpm", S_IRUGO|S_IWUSR, ehci->debug_dir, bus,
-                                                   &debug_lpm_fops))
-               goto file_error;
-
        return;
 
 file_error:
index 0d2f35ca93f1d5e7091cc77122e70b162f22679d..fd9b5424b860a20e7d04c54fe3cf4fc76ca3be2d 100644 (file)
@@ -349,7 +349,6 @@ static int ehci_fsl_reinit(struct ehci_hcd *ehci)
 {
        if (ehci_fsl_usb_setup(ehci))
                return -EINVAL;
-       ehci_port_power(ehci, 0);
 
        return 0;
 }
index 3180cb3624d9839d90846c1dceea48ab5ac817c1..da4269550fba35d41b1569cc65baca7287324b5f 100644 (file)
 
 #define GRUSBHC_HCIVERSION 0x0100 /* Known value of cap. reg. HCIVERSION */
 
-/* called during probe() after chip reset completes */
-static int ehci_grlib_setup(struct usb_hcd *hcd)
-{
-       struct ehci_hcd *ehci = hcd_to_ehci(hcd);
-       int             retval;
-
-       retval = ehci_setup(hcd);
-       if (retval)
-               return retval;
-
-       ehci_port_power(ehci, 1);
-
-       return retval;
-}
-
-
 static const struct hc_driver ehci_grlib_hc_driver = {
        .description            = hcd_name,
        .product_desc           = "GRLIB GRUSBHC EHCI",
@@ -64,7 +48,7 @@ static const struct hc_driver ehci_grlib_hc_driver = {
        /*
         * basic lifecycle operations
         */
-       .reset                  = ehci_grlib_setup,
+       .reset                  = ehci_setup,
        .start                  = ehci_run,
        .stop                   = ehci_stop,
        .shutdown               = ehci_shutdown,
index 6bf6c42481e8a6c645236ab27c170819c6f76024..c97503bb0b0e064a027575f9eb0d28094d3fda80 100644 (file)
@@ -39,7 +39,6 @@
 #include <linux/dma-mapping.h>
 #include <linux/debugfs.h>
 #include <linux/slab.h>
-#include <linux/uaccess.h>
 
 #include <asm/byteorder.h>
 #include <asm/io.h>
@@ -108,19 +107,39 @@ static bool ignore_oc = 0;
 module_param (ignore_oc, bool, S_IRUGO);
 MODULE_PARM_DESC (ignore_oc, "ignore bogus hardware overcurrent indications");
 
-/* for link power management(LPM) feature */
-static unsigned int hird;
-module_param(hird, int, S_IRUGO);
-MODULE_PARM_DESC(hird, "host initiated resume duration, +1 for each 75us");
-
 #define        INTR_MASK (STS_IAA | STS_FATAL | STS_PCD | STS_ERR | STS_INT)
 
 /*-------------------------------------------------------------------------*/
 
 #include "ehci.h"
-#include "ehci-dbg.c"
 #include "pci-quirks.h"
 
+/*
+ * The MosChip MCS9990 controller updates its microframe counter
+ * a little before the frame counter, and occasionally we will read
+ * the invalid intermediate value.  Avoid problems by checking the
+ * microframe number (the low-order 3 bits); if they are 0 then
+ * re-read the register to get the correct value.
+ */
+static unsigned ehci_moschip_read_frame_index(struct ehci_hcd *ehci)
+{
+       unsigned uf;
+
+       uf = ehci_readl(ehci, &ehci->regs->frame_index);
+       if (unlikely((uf & 7) == 0))
+               uf = ehci_readl(ehci, &ehci->regs->frame_index);
+       return uf;
+}
+
+static inline unsigned ehci_read_frame_index(struct ehci_hcd *ehci)
+{
+       if (ehci->frame_index_bug)
+               return ehci_moschip_read_frame_index(ehci);
+       return ehci_readl(ehci, &ehci->regs->frame_index);
+}
+
+#include "ehci-dbg.c"
+
 /*-------------------------------------------------------------------------*/
 
 /*
@@ -293,7 +312,6 @@ static void end_unlink_intr(struct ehci_hcd *ehci, struct ehci_qh *qh);
 
 #include "ehci-timer.c"
 #include "ehci-hub.c"
-#include "ehci-lpm.c"
 #include "ehci-mem.c"
 #include "ehci-q.c"
 #include "ehci-sched.c"
@@ -353,24 +371,6 @@ static void ehci_shutdown(struct usb_hcd *hcd)
        hrtimer_cancel(&ehci->hrtimer);
 }
 
-static void ehci_port_power (struct ehci_hcd *ehci, int is_on)
-{
-       unsigned port;
-
-       if (!HCS_PPC (ehci->hcs_params))
-               return;
-
-       ehci_dbg (ehci, "...power%s ports...\n", is_on ? "up" : "down");
-       for (port = HCS_N_PORTS (ehci->hcs_params); port > 0; )
-               (void) ehci_hub_control(ehci_to_hcd(ehci),
-                               is_on ? SetPortFeature : ClearPortFeature,
-                               USB_PORT_FEAT_POWER,
-                               port--, NULL, 0);
-       /* Flush those writes */
-       ehci_readl(ehci, &ehci->regs->command);
-       msleep(20);
-}
-
 /*-------------------------------------------------------------------------*/
 
 /*
@@ -503,7 +503,7 @@ static int ehci_init(struct usb_hcd *hcd)
 
        /* controllers may cache some of the periodic schedule ... */
        if (HCC_ISOC_CACHE(hcc_params))         // full frame cache
-               ehci->i_thresh = 2 + 8;
+               ehci->i_thresh = 0;
        else                                    // N microframes cached
                ehci->i_thresh = 2 + HCC_ISOC_THRES(hcc_params);
 
@@ -555,17 +555,6 @@ static int ehci_init(struct usb_hcd *hcd)
                temp &= ~(3 << 2);
                temp |= (EHCI_TUNE_FLS << 2);
        }
-       if (HCC_LPM(hcc_params)) {
-               /* support link power management EHCI 1.1 addendum */
-               ehci_dbg(ehci, "support lpm\n");
-               ehci->has_lpm = 1;
-               if (hird > 0xf) {
-                       ehci_dbg(ehci, "hird %d invalid, use default 0",
-                       hird);
-                       hird = 0;
-               }
-               temp |= hird << 24;
-       }
        ehci->command = temp;
 
        /* Accept arbitrarily long scatter-gather lists */
@@ -660,7 +649,7 @@ static int ehci_run (struct usb_hcd *hcd)
        return 0;
 }
 
-static int ehci_setup(struct usb_hcd *hcd)
+int ehci_setup(struct usb_hcd *hcd)
 {
        struct ehci_hcd *ehci = hcd_to_ehci(hcd);
        int retval;
@@ -691,6 +680,7 @@ static int ehci_setup(struct usb_hcd *hcd)
 
        return 0;
 }
+EXPORT_SYMBOL_GPL(ehci_setup);
 
 /*-------------------------------------------------------------------------*/
 
@@ -1096,7 +1086,7 @@ static int ehci_get_frame (struct usb_hcd *hcd)
 
 /* These routines handle the generic parts of controller suspend/resume */
 
-static int __maybe_unused ehci_suspend(struct usb_hcd *hcd, bool do_wakeup)
+int ehci_suspend(struct usb_hcd *hcd, bool do_wakeup)
 {
        struct ehci_hcd         *ehci = hcd_to_ehci(hcd);
 
@@ -1119,9 +1109,10 @@ static int __maybe_unused ehci_suspend(struct usb_hcd *hcd, bool do_wakeup)
 
        return 0;
 }
+EXPORT_SYMBOL_GPL(ehci_suspend);
 
 /* Returns 0 if power was preserved, 1 if power was lost */
-static int __maybe_unused ehci_resume(struct usb_hcd *hcd, bool hibernated)
+int ehci_resume(struct usb_hcd *hcd, bool hibernated)
 {
        struct ehci_hcd         *ehci = hcd_to_ehci(hcd);
 
@@ -1177,33 +1168,83 @@ static int __maybe_unused ehci_resume(struct usb_hcd *hcd, bool hibernated)
        ehci->rh_state = EHCI_RH_SUSPENDED;
        spin_unlock_irq(&ehci->lock);
 
-       /* here we "know" root ports should always stay powered */
-       ehci_port_power(ehci, 1);
-
        return 1;
 }
+EXPORT_SYMBOL_GPL(ehci_resume);
 
 #endif
 
 /*-------------------------------------------------------------------------*/
 
 /*
- * The EHCI in ChipIdea HDRC cannot be a separate module or device,
- * because its registers (and irq) are shared between host/gadget/otg
- * functions  and in order to facilitate role switching we cannot
- * give the ehci driver exclusive access to those.
+ * Generic structure: This gets copied for platform drivers so that
+ * individual entries can be overridden as needed.
  */
-#ifndef CHIPIDEA_EHCI
+
+static const struct hc_driver ehci_hc_driver = {
+       .description =          hcd_name,
+       .product_desc =         "EHCI Host Controller",
+       .hcd_priv_size =        sizeof(struct ehci_hcd),
+
+       /*
+        * generic hardware linkage
+        */
+       .irq =                  ehci_irq,
+       .flags =                HCD_MEMORY | HCD_USB2,
+
+       /*
+        * basic lifecycle operations
+        */
+       .reset =                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,
+       .clear_tt_buffer_complete =     ehci_clear_tt_buffer_complete,
+
+       /*
+        * 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,
+};
+
+void ehci_init_driver(struct hc_driver *drv,
+               const struct ehci_driver_overrides *over)
+{
+       /* Copy the generic table to drv and then apply the overrides */
+       *drv = ehci_hc_driver;
+
+       if (over) {
+               drv->hcd_priv_size += over->extra_priv_size;
+               if (over->reset)
+                       drv->reset = over->reset;
+       }
+}
+EXPORT_SYMBOL_GPL(ehci_init_driver);
+
+/*-------------------------------------------------------------------------*/
 
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_AUTHOR (DRIVER_AUTHOR);
 MODULE_LICENSE ("GPL");
 
-#ifdef CONFIG_PCI
-#include "ehci-pci.c"
-#define        PCI_DRIVER              ehci_pci_driver
-#endif
-
 #ifdef CONFIG_USB_EHCI_FSL
 #include "ehci-fsl.c"
 #define        PLATFORM_DRIVER         ehci_fsl_driver
@@ -1219,11 +1260,6 @@ MODULE_LICENSE ("GPL");
 #define PLATFORM_DRIVER                ehci_hcd_sh_driver
 #endif
 
-#ifdef CONFIG_MIPS_ALCHEMY
-#include "ehci-au1xxx.c"
-#define        PLATFORM_DRIVER         ehci_hcd_au1xxx_driver
-#endif
-
 #ifdef CONFIG_USB_EHCI_HCD_OMAP
 #include "ehci-omap.c"
 #define        PLATFORM_DRIVER         ehci_hcd_omap_driver
@@ -1249,11 +1285,6 @@ MODULE_LICENSE ("GPL");
 #define        PLATFORM_DRIVER         ehci_orion_driver
 #endif
 
-#ifdef CONFIG_ARCH_IXP4XX
-#include "ehci-ixp4xx.c"
-#define        PLATFORM_DRIVER         ixp4xx_ehci_driver
-#endif
-
 #ifdef CONFIG_USB_W90X900_EHCI
 #include "ehci-w90x900.c"
 #define        PLATFORM_DRIVER         ehci_hcd_w90x900_driver
@@ -1269,11 +1300,6 @@ MODULE_LICENSE ("GPL");
 #define PLATFORM_DRIVER                ehci_octeon_driver
 #endif
 
-#ifdef CONFIG_USB_CNS3XXX_EHCI
-#include "ehci-cns3xxx.c"
-#define PLATFORM_DRIVER                cns3xxx_ehci_driver
-#endif
-
 #ifdef CONFIG_ARCH_VT8500
 #include "ehci-vt8500.c"
 #define        PLATFORM_DRIVER         vt8500_ehci_driver
@@ -1314,34 +1340,23 @@ MODULE_LICENSE ("GPL");
 #define PLATFORM_DRIVER                ehci_grlib_driver
 #endif
 
-#ifdef CONFIG_CPU_XLR
-#include "ehci-xls.c"
-#define PLATFORM_DRIVER                ehci_xls_driver
-#endif
-
 #ifdef CONFIG_USB_EHCI_MV
 #include "ehci-mv.c"
 #define        PLATFORM_DRIVER         ehci_mv_driver
 #endif
 
-#ifdef CONFIG_MACH_LOONGSON1
-#include "ehci-ls1x.c"
-#define PLATFORM_DRIVER                ehci_ls1x_driver
-#endif
-
 #ifdef CONFIG_MIPS_SEAD3
 #include "ehci-sead3.c"
 #define        PLATFORM_DRIVER         ehci_hcd_sead3_driver
 #endif
 
-#ifdef CONFIG_USB_EHCI_HCD_PLATFORM
-#include "ehci-platform.c"
-#define PLATFORM_DRIVER                ehci_platform_driver
-#endif
-
-#if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \
-    !defined(PS3_SYSTEM_BUS_DRIVER) && !defined(OF_PLATFORM_DRIVER) && \
-    !defined(XILINX_OF_PLATFORM_DRIVER)
+#if !IS_ENABLED(CONFIG_USB_EHCI_PCI) && \
+       !IS_ENABLED(CONFIG_USB_EHCI_HCD_PLATFORM) && \
+       !defined(CONFIG_USB_CHIPIDEA_HOST) && \
+       !defined(PLATFORM_DRIVER) && \
+       !defined(PS3_SYSTEM_BUS_DRIVER) && \
+       !defined(OF_PLATFORM_DRIVER) && \
+       !defined(XILINX_OF_PLATFORM_DRIVER)
 #error "missing bus glue for ehci-hcd"
 #endif
 
@@ -1378,12 +1393,6 @@ static int __init ehci_hcd_init(void)
                goto clean0;
 #endif
 
-#ifdef PCI_DRIVER
-       retval = pci_register_driver(&PCI_DRIVER);
-       if (retval < 0)
-               goto clean1;
-#endif
-
 #ifdef PS3_SYSTEM_BUS_DRIVER
        retval = ps3_ehci_driver_register(&PS3_SYSTEM_BUS_DRIVER);
        if (retval < 0)
@@ -1415,10 +1424,6 @@ clean3:
        ps3_ehci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);
 clean2:
 #endif
-#ifdef PCI_DRIVER
-       pci_unregister_driver(&PCI_DRIVER);
-clean1:
-#endif
 #ifdef PLATFORM_DRIVER
        platform_driver_unregister(&PLATFORM_DRIVER);
 clean0:
@@ -1444,9 +1449,6 @@ static void __exit ehci_hcd_cleanup(void)
 #ifdef PLATFORM_DRIVER
        platform_driver_unregister(&PLATFORM_DRIVER);
 #endif
-#ifdef PCI_DRIVER
-       pci_unregister_driver(&PCI_DRIVER);
-#endif
 #ifdef PS3_SYSTEM_BUS_DRIVER
        ps3_ehci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);
 #endif
@@ -1456,5 +1458,3 @@ static void __exit ehci_hcd_cleanup(void)
        clear_bit(USB_EHCI_LOADED, &usb_hcds_loaded);
 }
 module_exit(ehci_hcd_cleanup);
-
-#endif /* CHIPIDEA_EHCI */
index 914ce9370e70f4a1d9a956ccf50fae9b97973b21..4ccb97c0678f93fd8379af59584bd79e8b8d10ef 100644 (file)
@@ -56,6 +56,19 @@ static void ehci_handover_companion_ports(struct ehci_hcd *ehci)
        if (!ehci->owned_ports)
                return;
 
+       /* Make sure the ports are powered */
+       port = HCS_N_PORTS(ehci->hcs_params);
+       while (port--) {
+               if (test_bit(port, &ehci->owned_ports)) {
+                       reg = &ehci->regs->port_status[port];
+                       status = ehci_readl(ehci, reg) & ~PORT_RWC_BITS;
+                       if (!(status & PORT_POWER)) {
+                               status |= PORT_POWER;
+                               ehci_writel(ehci, status, reg);
+                       }
+               }
+       }
+
        /* Give the connections some time to appear */
        msleep(20);
 
@@ -384,11 +397,24 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
        ehci_writel(ehci, ehci->command, &ehci->regs->command);
        ehci->rh_state = EHCI_RH_RUNNING;
 
-       /* Some controller/firmware combinations need a delay during which
-        * they set up the port statuses.  See Bugzilla #8190. */
-       spin_unlock_irq(&ehci->lock);
-       msleep(8);
-       spin_lock_irq(&ehci->lock);
+       /*
+        * According to Bugzilla #8190, the port status for some controllers
+        * will be wrong without a delay. At their wrong status, the port
+        * is enabled, but not suspended neither resumed.
+        */
+       i = HCS_N_PORTS(ehci->hcs_params);
+       while (i--) {
+               temp = ehci_readl(ehci, &ehci->regs->port_status[i]);
+               if ((temp & PORT_PE) &&
+                               !(temp & (PORT_SUSPEND | PORT_RESUME))) {
+                       ehci_dbg(ehci, "Port status(0x%x) is wrong\n", temp);
+                       spin_unlock_irq(&ehci->lock);
+                       msleep(8);
+                       spin_lock_irq(&ehci->lock);
+                       break;
+               }
+       }
+
        if (ehci->shutdown)
                goto shutdown;
 
@@ -764,11 +790,6 @@ static int ehci_hub_control (
                                                status_reg);
                        break;
                case USB_PORT_FEAT_C_CONNECTION:
-                       if (ehci->has_lpm) {
-                               /* clear PORTSC bits on disconnect */
-                               temp &= ~PORT_LPM;
-                               temp &= ~PORT_DEV_ADDR;
-                       }
                        ehci_writel(ehci, temp | PORT_CSC, status_reg);
                        break;
                case USB_PORT_FEAT_C_OVER_CURRENT:
@@ -1088,8 +1109,7 @@ error_exit:
        return retval;
 }
 
-static void __maybe_unused ehci_relinquish_port(struct usb_hcd *hcd,
-               int portnum)
+static void ehci_relinquish_port(struct usb_hcd *hcd, int portnum)
 {
        struct ehci_hcd         *ehci = hcd_to_ehci(hcd);
 
@@ -1098,8 +1118,7 @@ static void __maybe_unused ehci_relinquish_port(struct usb_hcd *hcd,
        set_owner(ehci, --portnum, PORT_OWNER);
 }
 
-static int __maybe_unused ehci_port_handed_over(struct usb_hcd *hcd,
-               int portnum)
+static int ehci_port_handed_over(struct usb_hcd *hcd, int portnum)
 {
        struct ehci_hcd         *ehci = hcd_to_ehci(hcd);
        u32 __iomem             *reg;
diff --git a/drivers/usb/host/ehci-ixp4xx.c b/drivers/usb/host/ehci-ixp4xx.c
deleted file mode 100644 (file)
index f224c0a..0000000
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * IXP4XX EHCI Host Controller Driver
- *
- * Author: Vladimir Barinov <vbarinov@embeddedalley.com>
- *
- * Based on "ehci-fsl.c" by Randy Vinson <rvinson@mvista.com>
- *
- * 2007 (c) MontaVista Software, Inc. This file is licensed under
- * the terms of the GNU General Public License version 2. This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- */
-
-#include <linux/platform_device.h>
-
-static int ixp4xx_ehci_init(struct usb_hcd *hcd)
-{
-       struct ehci_hcd *ehci = hcd_to_ehci(hcd);
-       int retval = 0;
-
-       ehci->big_endian_desc = 1;
-       ehci->big_endian_mmio = 1;
-
-       ehci->caps = hcd->regs + 0x100;
-
-       hcd->has_tt = 1;
-
-       retval = ehci_setup(hcd);
-       if (retval)
-               return retval;
-
-       ehci_port_power(ehci, 0);
-
-       return retval;
-}
-
-static const struct hc_driver ixp4xx_ehci_hc_driver = {
-       .description            = hcd_name,
-       .product_desc           = "IXP4XX EHCI Host Controller",
-       .hcd_priv_size          = sizeof(struct ehci_hcd),
-       .irq                    = ehci_irq,
-       .flags                  = HCD_MEMORY | HCD_USB2,
-       .reset                  = ixp4xx_ehci_init,
-       .start                  = ehci_run,
-       .stop                   = ehci_stop,
-       .shutdown               = ehci_shutdown,
-       .urb_enqueue            = ehci_urb_enqueue,
-       .urb_dequeue            = ehci_urb_dequeue,
-       .endpoint_disable       = ehci_endpoint_disable,
-       .endpoint_reset         = ehci_endpoint_reset,
-       .get_frame_number       = ehci_get_frame,
-       .hub_status_data        = ehci_hub_status_data,
-       .hub_control            = ehci_hub_control,
-#if defined(CONFIG_PM)
-       .bus_suspend            = ehci_bus_suspend,
-       .bus_resume             = ehci_bus_resume,
-#endif
-       .relinquish_port        = ehci_relinquish_port,
-       .port_handed_over       = ehci_port_handed_over,
-
-       .clear_tt_buffer_complete       = ehci_clear_tt_buffer_complete,
-};
-
-static int ixp4xx_ehci_probe(struct platform_device *pdev)
-{
-       struct usb_hcd *hcd;
-       const struct hc_driver *driver = &ixp4xx_ehci_hc_driver;
-       struct resource *res;
-       int irq;
-       int retval;
-
-       if (usb_disabled())
-               return -ENODEV;
-
-       res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-       if (!res) {
-               dev_err(&pdev->dev,
-                       "Found HC with no IRQ. Check %s setup!\n",
-                       dev_name(&pdev->dev));
-               return -ENODEV;
-       }
-       irq = res->start;
-
-       hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev));
-       if (!hcd) {
-               retval = -ENOMEM;
-               goto fail_create_hcd;
-       }
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               dev_err(&pdev->dev,
-                       "Found HC with no register addr. Check %s setup!\n",
-                       dev_name(&pdev->dev));
-               retval = -ENODEV;
-               goto fail_request_resource;
-       }
-       hcd->rsrc_start = res->start;
-       hcd->rsrc_len = resource_size(res);
-
-       hcd->regs = devm_request_and_ioremap(&pdev->dev, res);
-       if (hcd->regs == NULL) {
-               dev_dbg(&pdev->dev, "error mapping memory\n");
-               retval = -EFAULT;
-               goto fail_request_resource;
-       }
-
-       retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
-       if (retval)
-               goto fail_request_resource;
-
-       return retval;
-
-fail_request_resource:
-       usb_put_hcd(hcd);
-fail_create_hcd:
-       dev_err(&pdev->dev, "init %s fail, %d\n", dev_name(&pdev->dev), retval);
-       return retval;
-}
-
-static int ixp4xx_ehci_remove(struct platform_device *pdev)
-{
-       struct usb_hcd *hcd = platform_get_drvdata(pdev);
-
-       usb_remove_hcd(hcd);
-       usb_put_hcd(hcd);
-
-       return 0;
-}
-
-MODULE_ALIAS("platform:ixp4xx-ehci");
-
-static struct platform_driver ixp4xx_ehci_driver = {
-       .probe = ixp4xx_ehci_probe,
-       .remove = ixp4xx_ehci_remove,
-       .driver = {
-               .name = "ixp4xx-ehci",
-       },
-};
diff --git a/drivers/usb/host/ehci-lpm.c b/drivers/usb/host/ehci-lpm.c
deleted file mode 100644 (file)
index 2111627..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-/* ehci-lpm.c EHCI HCD LPM support code
- * Copyright (c) 2008 - 2010,  Intel Corporation.
- * Author: Jacob Pan <jacob.jun.pan@intel.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-/* this file is part of ehci-hcd.c */
-static int __maybe_unused ehci_lpm_set_da(struct ehci_hcd *ehci,
-       int dev_addr, int port_num)
-{
-       u32 __iomem portsc;
-
-       ehci_dbg(ehci, "set dev address %d for port %d\n", dev_addr, port_num);
-       if (port_num > HCS_N_PORTS(ehci->hcs_params)) {
-               ehci_dbg(ehci, "invalid port number %d\n", port_num);
-               return -ENODEV;
-       }
-       portsc = ehci_readl(ehci, &ehci->regs->port_status[port_num-1]);
-       portsc &= ~PORT_DEV_ADDR;
-       portsc |= dev_addr<<25;
-       ehci_writel(ehci, portsc, &ehci->regs->port_status[port_num-1]);
-       return 0;
-}
-
-/*
- * this function is used to check if the device support LPM
- * if yes, mark the PORTSC register with PORT_LPM bit
- */
-static int __maybe_unused ehci_lpm_check(struct ehci_hcd *ehci, int port)
-{
-       u32 __iomem     *portsc ;
-       u32 val32;
-       int retval;
-
-       portsc = &ehci->regs->port_status[port-1];
-       val32 = ehci_readl(ehci, portsc);
-       if (!(val32 & PORT_DEV_ADDR)) {
-               ehci_dbg(ehci, "LPM: no device attached\n");
-               return -ENODEV;
-       }
-       val32 |= PORT_LPM;
-       ehci_writel(ehci, val32, portsc);
-       msleep(5);
-       val32 |= PORT_SUSPEND;
-       ehci_dbg(ehci, "Sending LPM 0x%08x to port %d\n", val32, port);
-       ehci_writel(ehci, val32, portsc);
-       /* wait for ACK */
-       msleep(10);
-       retval = handshake(ehci, &ehci->regs->port_status[port-1], PORT_SSTS,
-                       PORTSC_SUSPEND_STS_ACK, 125);
-       dbg_port(ehci, "LPM", port, val32);
-       if (retval != -ETIMEDOUT) {
-               ehci_dbg(ehci, "LPM: device ACK for LPM\n");
-               val32 |= PORT_LPM;
-               /*
-                * now device should be in L1 sleep, let's wake up the device
-                * so that we can complete enumeration.
-                */
-               ehci_writel(ehci, val32, portsc);
-               msleep(10);
-               val32 |= PORT_RESUME;
-               ehci_writel(ehci, val32, portsc);
-       } else {
-               ehci_dbg(ehci, "LPM: device does not ACK, disable LPM %d\n",
-                       retval);
-               val32 &= ~PORT_LPM;
-               retval = -ETIMEDOUT;
-               ehci_writel(ehci, val32, portsc);
-       }
-
-       return retval;
-}
diff --git a/drivers/usb/host/ehci-ls1x.c b/drivers/usb/host/ehci-ls1x.c
deleted file mode 100644 (file)
index ca75965..0000000
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- *  Bus Glue for Loongson LS1X built-in EHCI controller.
- *
- *  Copyright (c) 2012 Zhang, Keguang <keguang.zhang@gmail.com>
- *
- *  This program is free software; you can redistribute it and/or modify it
- *  under the terms of the GNU General Public License version 2 as published
- *  by the Free Software Foundation.
- */
-
-
-#include <linux/platform_device.h>
-
-static int ehci_ls1x_reset(struct usb_hcd *hcd)
-{
-       struct ehci_hcd *ehci = hcd_to_ehci(hcd);
-       int ret;
-
-       ehci->caps = hcd->regs;
-
-       ret = ehci_setup(hcd);
-       if (ret)
-               return ret;
-
-       ehci_port_power(ehci, 0);
-
-       return 0;
-}
-
-static const struct hc_driver ehci_ls1x_hc_driver = {
-       .description            = hcd_name,
-       .product_desc           = "LOONGSON1 EHCI",
-       .hcd_priv_size          = sizeof(struct ehci_hcd),
-
-       /*
-        * generic hardware linkage
-        */
-       .irq                    = ehci_irq,
-       .flags                  = HCD_MEMORY | HCD_USB2,
-
-       /*
-        * basic lifecycle operations
-        */
-       .reset                  = ehci_ls1x_reset,
-       .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,
-       .relinquish_port        = ehci_relinquish_port,
-       .port_handed_over       = ehci_port_handed_over,
-
-       .clear_tt_buffer_complete       = ehci_clear_tt_buffer_complete,
-};
-
-static int ehci_hcd_ls1x_probe(struct platform_device *pdev)
-{
-       struct usb_hcd *hcd;
-       struct resource *res;
-       int irq;
-       int ret;
-
-       pr_debug("initializing loongson1 ehci USB Controller\n");
-
-       if (usb_disabled())
-               return -ENODEV;
-
-       res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-       if (!res) {
-               dev_err(&pdev->dev,
-                       "Found HC with no IRQ. Check %s setup!\n",
-                       dev_name(&pdev->dev));
-               return -ENODEV;
-       }
-       irq = res->start;
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               dev_err(&pdev->dev,
-                       "Found HC with no register addr. Check %s setup!\n",
-                       dev_name(&pdev->dev));
-               return -ENODEV;
-       }
-
-       hcd = usb_create_hcd(&ehci_ls1x_hc_driver, &pdev->dev,
-                               dev_name(&pdev->dev));
-       if (!hcd)
-               return -ENOMEM;
-       hcd->rsrc_start = res->start;
-       hcd->rsrc_len   = resource_size(res);
-
-       hcd->regs = devm_request_and_ioremap(&pdev->dev, res);
-       if (hcd->regs == NULL) {
-               dev_dbg(&pdev->dev, "error mapping memory\n");
-               ret = -EFAULT;
-               goto err_put_hcd;
-       }
-
-       ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
-       if (ret)
-               goto err_put_hcd;
-
-       return ret;
-
-err_put_hcd:
-       usb_put_hcd(hcd);
-       return ret;
-}
-
-static int ehci_hcd_ls1x_remove(struct platform_device *pdev)
-{
-       struct usb_hcd *hcd = platform_get_drvdata(pdev);
-
-       usb_remove_hcd(hcd);
-       usb_put_hcd(hcd);
-
-       return 0;
-}
-
-static struct platform_driver ehci_ls1x_driver = {
-       .probe = ehci_hcd_ls1x_probe,
-       .remove = ehci_hcd_ls1x_remove,
-       .shutdown = usb_hcd_platform_shutdown,
-       .driver = {
-               .name = "ls1x-ehci",
-               .owner  = THIS_MODULE,
-       },
-};
-
-MODULE_ALIAS(PLATFORM_MODULE_PREFIX "ls1x-ehci");
index 4af4dc5b618c5710bd4f6226361916763122ac53..7fa1ba4de78965a6f410d645fd3ff91ab935d09e 100644 (file)
@@ -53,7 +53,6 @@ static int ehci_msm_reset(struct usb_hcd *hcd)
        /* Disable streaming mode and select host mode */
        writel(0x13, USB_USBMODE);
 
-       ehci_port_power(ehci, 1);
        return 0;
 }
 
index 4a08fc0b27c9e541da76b9598120b646ab7aa9a5..a37224a4a49b88c06f9f2ddba55cec404531ab1f 100644 (file)
@@ -40,16 +40,10 @@ struct ehci_mxc_priv {
 static int ehci_mxc_setup(struct usb_hcd *hcd)
 {
        struct ehci_hcd *ehci = hcd_to_ehci(hcd);
-       int retval;
 
        hcd->has_tt = 1;
 
-       retval = ehci_setup(hcd);
-       if (retval)
-               return retval;
-
-       ehci_port_power(ehci, 0);
-       return 0;
+       return ehci_setup(hcd);
 }
 
 static const struct hc_driver ehci_mxc_hc_driver = {
index ba26957abf462095d6d1d74d682aa31f3545a836..a89750fff4ff09d38d9dc1090590c1efd68f8d24 100644 (file)
@@ -159,9 +159,6 @@ static int ehci_octeon_drv_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, hcd);
 
-       /* root ports should always stay powered */
-       ehci_port_power(ehci, 1);
-
        return 0;
 err3:
        ehci_octeon_stop();
index d7fe287d067803e484d56efdf53060546634ea1e..44e7d0f638e8f943507ce473f36595c27314537d 100644 (file)
@@ -146,9 +146,6 @@ static int omap_ehci_init(struct usb_hcd *hcd)
                        gpio_set_value_cansleep(pdata->reset_gpio_port[1], 1);
        }
 
-       /* root ports should always stay powered */
-       ehci_port_power(ehci, 1);
-
        return rc;
 }
 
index 9c2717d66730ad74d9f99ef2aa0795b25c716a1b..96da679becef3a5d98da4b3da9833f6e3ebeeed0 100644 (file)
@@ -101,20 +101,6 @@ static void orion_usb_phy_v1_setup(struct usb_hcd *hcd)
        wrl(USB_MODE, 0x13);
 }
 
-static int ehci_orion_setup(struct usb_hcd *hcd)
-{
-       struct ehci_hcd *ehci = hcd_to_ehci(hcd);
-       int retval;
-
-       retval = ehci_setup(hcd);
-       if (retval)
-               return retval;
-
-       ehci_port_power(ehci, 0);
-
-       return retval;
-}
-
 static const struct hc_driver ehci_orion_hc_driver = {
        .description = hcd_name,
        .product_desc = "Marvell Orion EHCI",
@@ -129,7 +115,7 @@ static const struct hc_driver ehci_orion_hc_driver = {
        /*
         * basic lifecycle operations
         */
-       .reset = ehci_orion_setup,
+       .reset = ehci_setup,
        .start = ehci_run,
        .stop = ehci_stop,
        .shutdown = ehci_shutdown,
index 2cb7d370c4eff93ee39509f739e9669ff2cd3a0a..3fb76ca6184814944288d01b568cc7096eb9e45b 100644 (file)
  * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#ifndef CONFIG_PCI
-#error "This file is PCI bus glue.  CONFIG_PCI must be defined."
-#endif
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/usb.h>
+#include <linux/usb/hcd.h>
+
+#include "ehci.h"
+#include "pci-quirks.h"
+
+#define DRIVER_DESC "EHCI PCI platform driver"
+
+static const char hcd_name[] = "ehci-pci";
 
 /* defined here to avoid adding to pci_ids.h for single instance use */
 #define PCI_DEVICE_ID_INTEL_CE4100_USB 0x2e70
@@ -103,7 +112,6 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
                }
                break;
        case PCI_VENDOR_ID_INTEL:
-               ehci->fs_i_thresh = 1;
                if (pdev->device == PCI_DEVICE_ID_INTEL_CE4100_USB)
                        hcd->has_tt = 1;
                break;
@@ -203,11 +211,6 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
                break;
        case PCI_VENDOR_ID_INTEL:
                ehci->need_io_watchdog = 0;
-               if (pdev->device == 0x0806 || pdev->device == 0x0811
-                               || pdev->device == 0x0829) {
-                       ehci_info(ehci, "disable lpm for langwell/penwell\n");
-                       ehci->has_lpm = 0;
-               }
                break;
        case PCI_VENDOR_ID_NVIDIA:
                switch (pdev->device) {
@@ -217,8 +220,7 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
                 * devices with PPCD enabled.
                 */
                case 0x0d9d:
-                       ehci_info(ehci, "disable lpm/ppcd for nvidia mcp89");
-                       ehci->has_lpm = 0;
+                       ehci_info(ehci, "disable ppcd for nvidia mcp89\n");
                        ehci->has_ppcd = 0;
                        ehci->command &= ~CMD_PPCEE;
                        break;
@@ -304,7 +306,6 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
                ehci_warn(ehci, "selective suspend/wakeup unavailable\n");
 #endif
 
-       ehci_port_power(ehci, 1);
        retval = ehci_pci_reinit(ehci, pdev);
 done:
        return retval;
@@ -323,11 +324,6 @@ done:
  * Also they depend on separate root hub suspend/resume.
  */
 
-static int ehci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup)
-{
-       return ehci_suspend(hcd, do_wakeup);
-}
-
 static bool usb_is_intel_switchable_ehci(struct pci_dev *pdev)
 {
        return pdev->class == PCI_CLASS_SERIAL_USB_EHCI &&
@@ -378,76 +374,17 @@ static int ehci_pci_resume(struct usb_hcd *hcd, bool hibernated)
                (void) ehci_pci_reinit(ehci, pdev);
        return 0;
 }
-#endif
 
-static int ehci_update_device(struct usb_hcd *hcd, struct usb_device *udev)
-{
-       struct ehci_hcd *ehci = hcd_to_ehci(hcd);
-       int rc = 0;
-
-       if (!udev->parent) /* udev is root hub itself, impossible */
-               rc = -1;
-       /* we only support lpm device connected to root hub yet */
-       if (ehci->has_lpm && !udev->parent->parent) {
-               rc = ehci_lpm_set_da(ehci, udev->devnum, udev->portnum);
-               if (!rc)
-                       rc = ehci_lpm_check(ehci, udev->portnum);
-       }
-       return rc;
-}
+#else
 
-static const struct hc_driver ehci_pci_hc_driver = {
-       .description =          hcd_name,
-       .product_desc =         "EHCI Host Controller",
-       .hcd_priv_size =        sizeof(struct ehci_hcd),
+#define ehci_suspend           NULL
+#define ehci_pci_resume                NULL
+#endif /* CONFIG_PM */
 
-       /*
-        * generic hardware linkage
-        */
-       .irq =                  ehci_irq,
-       .flags =                HCD_MEMORY | HCD_USB2,
+static struct hc_driver __read_mostly ehci_pci_hc_driver;
 
-       /*
-        * basic lifecycle operations
-        */
+static const struct ehci_driver_overrides pci_overrides __initdata = {
        .reset =                ehci_pci_setup,
-       .start =                ehci_run,
-#ifdef CONFIG_PM
-       .pci_suspend =          ehci_pci_suspend,
-       .pci_resume =           ehci_pci_resume,
-#endif
-       .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,
-
-       /*
-        * call back when device connected and addressed
-        */
-       .update_device =        ehci_update_device,
-
-       .clear_tt_buffer_complete       = ehci_clear_tt_buffer_complete,
 };
 
 /*-------------------------------------------------------------------------*/
@@ -480,3 +417,31 @@ static struct pci_driver ehci_pci_driver = {
        },
 #endif
 };
+
+static int __init ehci_pci_init(void)
+{
+       if (usb_disabled())
+               return -ENODEV;
+
+       pr_info("%s: " DRIVER_DESC "\n", hcd_name);
+
+       ehci_init_driver(&ehci_pci_hc_driver, &pci_overrides);
+
+       /* Entries for the PCI suspend/resume callbacks are special */
+       ehci_pci_hc_driver.pci_suspend = ehci_suspend;
+       ehci_pci_hc_driver.pci_resume = ehci_pci_resume;
+
+       return pci_register_driver(&ehci_pci_driver);
+}
+module_init(ehci_pci_init);
+
+static void __exit ehci_pci_cleanup(void)
+{
+       pci_unregister_driver(&ehci_pci_driver);
+}
+module_exit(ehci_pci_cleanup);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_AUTHOR("David Brownell");
+MODULE_AUTHOR("Alan Stern");
+MODULE_LICENSE("GPL");
index 764e0100b6f438d82ab64057e8cb37abd638fa79..f14c542b142f3e2ba0aa3b29faf5d01137b3f267 100644 (file)
  *
  * Licensed under the GNU/GPL. See COPYING for details.
  */
+#include <linux/kernel.h>
+#include <linux/hrtimer.h>
+#include <linux/io.h>
+#include <linux/module.h>
 #include <linux/platform_device.h>
+#include <linux/usb.h>
+#include <linux/usb/hcd.h>
 #include <linux/usb/ehci_pdriver.h>
 
+#include "ehci.h"
+
+#define DRIVER_DESC "EHCI generic platform driver"
+
+static const char hcd_name[] = "ehci-platform";
+
 static int ehci_platform_reset(struct usb_hcd *hcd)
 {
        struct platform_device *pdev = to_platform_device(hcd->self.controller);
@@ -38,44 +50,15 @@ static int ehci_platform_reset(struct usb_hcd *hcd)
        if (retval)
                return retval;
 
-       if (pdata->port_power_on)
-               ehci_port_power(ehci, 1);
-       if (pdata->port_power_off)
-               ehci_port_power(ehci, 0);
-
+       if (pdata->no_io_watchdog)
+               ehci->need_io_watchdog = 0;
        return 0;
 }
 
-static const struct hc_driver ehci_platform_hc_driver = {
-       .description            = hcd_name,
-       .product_desc           = "Generic Platform EHCI Controller",
-       .hcd_priv_size          = sizeof(struct ehci_hcd),
-
-       .irq                    = ehci_irq,
-       .flags                  = HCD_MEMORY | HCD_USB2,
-
-       .reset                  = ehci_platform_reset,
-       .start                  = ehci_run,
-       .stop                   = ehci_stop,
-       .shutdown               = ehci_shutdown,
-
-       .urb_enqueue            = ehci_urb_enqueue,
-       .urb_dequeue            = ehci_urb_dequeue,
-       .endpoint_disable       = ehci_endpoint_disable,
-       .endpoint_reset         = ehci_endpoint_reset,
+static struct hc_driver __read_mostly ehci_platform_hc_driver;
 
-       .get_frame_number       = ehci_get_frame,
-
-       .hub_status_data        = ehci_hub_status_data,
-       .hub_control            = ehci_hub_control,
-#if defined(CONFIG_PM)
-       .bus_suspend            = ehci_bus_suspend,
-       .bus_resume             = ehci_bus_resume,
-#endif
-       .relinquish_port        = ehci_relinquish_port,
-       .port_handed_over       = ehci_port_handed_over,
-
-       .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
+static const struct ehci_driver_overrides platform_overrides __initdata = {
+       .reset =        ehci_platform_reset,
 };
 
 static int __devinit ehci_platform_probe(struct platform_device *dev)
@@ -96,12 +79,12 @@ static int __devinit ehci_platform_probe(struct platform_device *dev)
 
        irq = platform_get_irq(dev, 0);
        if (irq < 0) {
-               pr_err("no irq provided");
+               dev_err(&dev->dev, "no irq provided");
                return irq;
        }
        res_mem = platform_get_resource(dev, IORESOURCE_MEM, 0);
        if (!res_mem) {
-               pr_err("no memory recourse provided");
+               dev_err(&dev->dev, "no memory resource provided");
                return -ENXIO;
        }
 
@@ -121,29 +104,19 @@ static int __devinit ehci_platform_probe(struct platform_device *dev)
        hcd->rsrc_start = res_mem->start;
        hcd->rsrc_len = resource_size(res_mem);
 
-       if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
-               pr_err("controller already in use");
-               err = -EBUSY;
-               goto err_put_hcd;
-       }
-
-       hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len);
+       hcd->regs = devm_request_and_ioremap(&dev->dev, res_mem);
        if (!hcd->regs) {
                err = -ENOMEM;
-               goto err_release_region;
+               goto err_put_hcd;
        }
        err = usb_add_hcd(hcd, irq, IRQF_SHARED);
        if (err)
-               goto err_iounmap;
+               goto err_put_hcd;
 
        platform_set_drvdata(dev, hcd);
 
        return err;
 
-err_iounmap:
-       iounmap(hcd->regs);
-err_release_region:
-       release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
 err_put_hcd:
        usb_put_hcd(hcd);
 err_power:
@@ -159,8 +132,6 @@ static int __devexit ehci_platform_remove(struct platform_device *dev)
        struct usb_ehci_pdata *pdata = dev->dev.platform_data;
 
        usb_remove_hcd(hcd);
-       iounmap(hcd->regs);
-       release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
        usb_put_hcd(hcd);
        platform_set_drvdata(dev, NULL);
 
@@ -233,3 +204,26 @@ static struct platform_driver ehci_platform_driver = {
                .pm     = &ehci_platform_pm_ops,
        }
 };
+
+static int __init ehci_platform_init(void)
+{
+       if (usb_disabled())
+               return -ENODEV;
+
+       pr_info("%s: " DRIVER_DESC "\n", hcd_name);
+
+       ehci_init_driver(&ehci_platform_hc_driver, &platform_overrides);
+       return platform_driver_register(&ehci_platform_driver);
+}
+module_init(ehci_platform_init);
+
+static void __exit ehci_platform_cleanup(void)
+{
+       platform_driver_unregister(&ehci_platform_driver);
+}
+module_exit(ehci_platform_cleanup);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_AUTHOR("Hauke Mehrtens");
+MODULE_AUTHOR("Alan Stern");
+MODULE_LICENSE("GPL");
index 087aee2a904f0fecc9221702f400918367690648..363890ee41d2bcb640231b9d12b1d01b09a694b4 100644 (file)
@@ -90,7 +90,6 @@ static int ehci_msp_setup(struct usb_hcd *hcd)
                return retval;
 
        usb_hcd_tdi_set_mode(ehci);
-       ehci_port_power(ehci, 0);
 
        return retval;
 }
index 4b66374bdc8e33f74e20ff7bc30b7894ab24698e..3d989028c8365e6644b86428fea2f24cfba9be6e 100644 (file)
@@ -264,15 +264,9 @@ ehci_urb_done(struct ehci_hcd *ehci, struct urb *urb, int status)
 __releases(ehci->lock)
 __acquires(ehci->lock)
 {
-       if (likely (urb->hcpriv != NULL)) {
-               struct ehci_qh  *qh = (struct ehci_qh *) urb->hcpriv;
-
-               /* S-mask in a QH means it's an interrupt urb */
-               if ((qh->hw->hw_info2 & cpu_to_hc32(ehci, QH_SMASK)) != 0) {
-
-                       /* ... update hc-wide periodic stats (for usbfs) */
-                       ehci_to_hcd(ehci)->self.bandwidth_int_reqs--;
-               }
+       if (usb_pipetype(urb->pipe) == PIPE_INTERRUPT) {
+               /* ... update hc-wide periodic stats */
+               ehci_to_hcd(ehci)->self.bandwidth_int_reqs--;
        }
 
        if (unlikely(urb->unlinked)) {
index 85b74be202eb3b25a2c75dbde9386805dd9d6f79..abc178d21fe49fd3bbd504a913c7bae529f2d092 100644 (file)
@@ -136,7 +136,7 @@ static int __devinit s5p_ehci_probe(struct platform_device *pdev)
                goto fail_clk;
        }
 
-       err = clk_enable(s5p_ehci->clk);
+       err = clk_prepare_enable(s5p_ehci->clk);
        if (err)
                goto fail_clk;
 
@@ -183,7 +183,7 @@ static int __devinit s5p_ehci_probe(struct platform_device *pdev)
        return 0;
 
 fail_io:
-       clk_disable(s5p_ehci->clk);
+       clk_disable_unprepare(s5p_ehci->clk);
 fail_clk:
        usb_put_hcd(hcd);
        return err;
@@ -200,7 +200,7 @@ static int __devexit s5p_ehci_remove(struct platform_device *pdev)
        if (pdata && pdata->phy_exit)
                pdata->phy_exit(pdev, S5P_USB_PHY_HOST);
 
-       clk_disable(s5p_ehci->clk);
+       clk_disable_unprepare(s5p_ehci->clk);
 
        usb_put_hcd(hcd);
 
@@ -231,7 +231,7 @@ static int s5p_ehci_suspend(struct device *dev)
        if (pdata && pdata->phy_exit)
                pdata->phy_exit(pdev, S5P_USB_PHY_HOST);
 
-       clk_disable(s5p_ehci->clk);
+       clk_disable_unprepare(s5p_ehci->clk);
 
        return rc;
 }
@@ -243,7 +243,7 @@ static int s5p_ehci_resume(struct device *dev)
        struct platform_device *pdev = to_platform_device(dev);
        struct s5p_ehci_platdata *pdata = pdev->dev.platform_data;
 
-       clk_enable(s5p_ehci->clk);
+       clk_prepare_enable(s5p_ehci->clk);
 
        if (pdata && pdata->phy_init)
                pdata->phy_init(pdev, S5P_USB_PHY_HOST);
index 7cf3da7babf0009b6732302ecef280cc01429ff6..69ebee73c0c153581895dbd7860ab75024784394 100644 (file)
 
 static int ehci_get_frame (struct usb_hcd *hcd);
 
-#ifdef CONFIG_PCI
-
-static unsigned ehci_read_frame_index(struct ehci_hcd *ehci)
-{
-       unsigned uf;
-
-       /*
-        * The MosChip MCS9990 controller updates its microframe counter
-        * a little before the frame counter, and occasionally we will read
-        * the invalid intermediate value.  Avoid problems by checking the
-        * microframe number (the low-order 3 bits); if they are 0 then
-        * re-read the register to get the correct value.
-        */
-       uf = ehci_readl(ehci, &ehci->regs->frame_index);
-       if (unlikely(ehci->frame_index_bug && ((uf & 7) == 0)))
-               uf = ehci_readl(ehci, &ehci->regs->frame_index);
-       return uf;
-}
-
-#endif
-
-/*-------------------------------------------------------------------------*/
-
 /*
  * periodic_next_shadow - return "next" pointer on shadow list
  * @periodic: host pointer to qh/itd/sitd
@@ -1361,7 +1338,7 @@ sitd_slot_ok (
  * given EHCI_TUNE_FLS and the slop).  Or, write a smarter scheduler!
  */
 
-#define SCHEDULE_SLOP  80      /* microframes */
+#define SCHEDULING_DELAY       40      /* microframes */
 
 static int
 iso_stream_schedule (
@@ -1370,7 +1347,7 @@ iso_stream_schedule (
        struct ehci_iso_stream  *stream
 )
 {
-       u32                     now, next, start, period, span;
+       u32                     now, base, next, start, period, span;
        int                     status;
        unsigned                mod = ehci->periodic_size << 3;
        struct ehci_iso_sched   *sched = urb->hcpriv;
@@ -1382,62 +1359,72 @@ iso_stream_schedule (
                span <<= 3;
        }
 
-       if (span > mod - SCHEDULE_SLOP) {
-               ehci_dbg (ehci, "iso request %p too long\n", urb);
-               status = -EFBIG;
-               goto fail;
-       }
-
        now = ehci_read_frame_index(ehci) & (mod - 1);
 
        /* Typical case: reuse current schedule, stream is still active.
         * Hopefully there are no gaps from the host falling behind
-        * (irq delays etc), but if there are we'll take the next
-        * slot in the schedule, implicitly assuming URB_ISO_ASAP.
+        * (irq delays etc).  If there are, the behavior depends on
+        * whether URB_ISO_ASAP is set.
         */
        if (likely (!list_empty (&stream->td_list))) {
-               u32     excess;
 
-               /* For high speed devices, allow scheduling within the
-                * isochronous scheduling threshold.  For full speed devices
-                * and Intel PCI-based controllers, don't (work around for
-                * Intel ICH9 bug).
-                */
-               if (!stream->highspeed && ehci->fs_i_thresh)
-                       next = now + ehci->i_thresh;
+               /* Take the isochronous scheduling threshold into account */
+               if (ehci->i_thresh)
+                       next = now + ehci->i_thresh;    /* uframe cache */
                else
-                       next = now;
+                       next = (now + 2 + 7) & ~0x07;   /* full frame cache */
 
-               /* Fell behind (by up to twice the slop amount)?
-                * We decide based on the time of the last currently-scheduled
-                * slot, not the time of the next available slot.
+               /*
+                * Use ehci->last_iso_frame as the base.  There can't be any
+                * TDs scheduled for earlier than that.
                 */
-               excess = (stream->next_uframe - period - next) & (mod - 1);
-               if (excess >= mod - 2 * SCHEDULE_SLOP)
-                       start = next + excess - mod + period *
-                                       DIV_ROUND_UP(mod - excess, period);
-               else
-                       start = next + excess + period;
-               if (start - now >= mod) {
-                       ehci_dbg(ehci, "request %p would overflow (%d+%d >= %d)\n",
-                                       urb, start - now - period, period,
-                                       mod);
-                       status = -EFBIG;
+               base = ehci->last_iso_frame << 3;
+               next = (next - base) & (mod - 1);
+               start = (stream->next_uframe - base) & (mod - 1);
+
+               /* Is the schedule already full? */
+               if (unlikely(start < period)) {
+                       ehci_dbg(ehci, "iso sched full %p (%u-%u < %u mod %u)\n",
+                                       urb, stream->next_uframe, base,
+                                       period, mod);
+                       status = -ENOSPC;
                        goto fail;
                }
+
+               /* Behind the scheduling threshold? */
+               if (unlikely(start < next)) {
+
+                       /* USB_ISO_ASAP: Round up to the first available slot */
+                       if (urb->transfer_flags & URB_ISO_ASAP)
+                               start += (next - start + period - 1) & -period;
+
+                       /*
+                        * Not ASAP: Use the next slot in the stream.  If
+                        * the entire URB falls before the threshold, fail.
+                        */
+                       else if (start + span - period < next) {
+                               ehci_dbg(ehci, "iso urb late %p (%u+%u < %u)\n",
+                                               urb, start + base,
+                                               span - period, next + base);
+                               status = -EXDEV;
+                               goto fail;
+                       }
+               }
+
+               start += base;
        }
 
        /* need to schedule; when's the next (u)frame we could start?
         * this is bigger than ehci->i_thresh allows; scheduling itself
-        * isn't free, the slop should handle reasonably slow cpus.  it
+        * isn't free, the delay should handle reasonably slow cpus.  it
         * can also help high bandwidth if the dma and irq loads don't
         * jump until after the queue is primed.
         */
        else {
                int done = 0;
-               start = SCHEDULE_SLOP + (now & ~0x07);
 
-               /* NOTE:  assumes URB_ISO_ASAP, to limit complexity/bugs */
+               base = now & ~0x07;
+               start = base + SCHEDULING_DELAY;
 
                /* find a uframe slot with enough bandwidth.
                 * Early uframes are more precious because full-speed
@@ -1464,19 +1451,16 @@ iso_stream_schedule (
 
                /* no room in the schedule */
                if (!done) {
-                       ehci_dbg(ehci, "iso resched full %p (now %d max %d)\n",
-                               urb, now, now + mod);
+                       ehci_dbg(ehci, "iso sched full %p", urb);
                        status = -ENOSPC;
                        goto fail;
                }
        }
 
        /* Tried to schedule too far into the future? */
-       if (unlikely(start - now + span - period
-                               >= mod - 2 * SCHEDULE_SLOP)) {
-               ehci_dbg(ehci, "request %p would overflow (%d+%d >= %d)\n",
-                               urb, start - now, span - period,
-                               mod - 2 * SCHEDULE_SLOP);
+       if (unlikely(start - base + span - period >= mod)) {
+               ehci_dbg(ehci, "request %p would overflow (%u+%u >= %u)\n",
+                               urb, start - base, span - period, mod);
                status = -EFBIG;
                goto fail;
        }
@@ -1490,7 +1474,7 @@ iso_stream_schedule (
 
        /* Make sure scan_isoc() sees these */
        if (ehci->isoc_count == 0)
-               ehci->next_frame = now >> 3;
+               ehci->last_iso_frame = now >> 3;
        return 0;
 
  fail:
@@ -1646,7 +1630,7 @@ static void itd_link_urb(
 
        /* don't need that schedule data any more */
        iso_sched_free (stream, iso_sched);
-       urb->hcpriv = NULL;
+       urb->hcpriv = stream;
 
        ++ehci->isoc_count;
        enable_periodic(ehci);
@@ -1708,7 +1692,7 @@ static bool itd_complete(struct ehci_hcd *ehci, struct ehci_itd *itd)
                        urb->actual_length += desc->actual_length;
                } else {
                        /* URB was too late */
-                       desc->status = -EXDEV;
+                       urb->error_count++;
                }
        }
 
@@ -2045,7 +2029,7 @@ static void sitd_link_urb(
 
        /* don't need that schedule data any more */
        iso_sched_free (stream, sched);
-       urb->hcpriv = NULL;
+       urb->hcpriv = stream;
 
        ++ehci->isoc_count;
        enable_periodic(ehci);
@@ -2081,7 +2065,7 @@ static bool sitd_complete(struct ehci_hcd *ehci, struct ehci_sitd *sitd)
        t = hc32_to_cpup(ehci, &sitd->hw_results);
 
        /* report transfer status */
-       if (t & SITD_ERRS) {
+       if (unlikely(t & SITD_ERRS)) {
                urb->error_count++;
                if (t & SITD_STS_DBE)
                        desc->status = usb_pipein (urb->pipe)
@@ -2091,6 +2075,9 @@ static bool sitd_complete(struct ehci_hcd *ehci, struct ehci_sitd *sitd)
                        desc->status = -EOVERFLOW;
                else /* XACT, MMF, etc */
                        desc->status = -EPROTO;
+       } else if (unlikely(t & SITD_STS_ACTIVE)) {
+               /* URB was too late */
+               urb->error_count++;
        } else {
                desc->status = 0;
                desc->actual_length = desc->length - SITD_LENGTH(t);
@@ -2220,16 +2207,16 @@ static void scan_isoc(struct ehci_hcd *ehci)
                now_frame = (uf >> 3) & fmask;
                live = true;
        } else  {
-               now_frame = (ehci->next_frame - 1) & fmask;
+               now_frame = (ehci->last_iso_frame - 1) & fmask;
                live = false;
        }
        ehci->now_frame = now_frame;
 
-       frame = ehci->next_frame;
        for (;;) {
                union ehci_shadow       q, *q_p;
                __hc32                  type, *hw_p;
 
+               frame = ehci->last_iso_frame;
 restart:
                /* scan each element in frame's queue for completions */
                q_p = &ehci->pshadow [frame];
@@ -2334,7 +2321,6 @@ restart:
                /* Stop when we have reached the current frame */
                if (frame == now_frame)
                        break;
-               frame = (frame + 1) & fmask;
+               ehci->last_iso_frame = (frame + 1) & fmask;
        }
-       ehci->next_frame = now_frame;
 }
index 6081e1ed3ac9d9e8338c233829103661d1d46a99..0c90a24fa989286a36f76f54e41350cf26a65d3f 100644 (file)
@@ -21,17 +21,10 @@ struct ehci_sh_priv {
 static int ehci_sh_reset(struct usb_hcd *hcd)
 {
        struct ehci_hcd *ehci = hcd_to_ehci(hcd);
-       int ret;
 
        ehci->caps = hcd->regs;
 
-       ret = ehci_setup(hcd);
-       if (unlikely(ret))
-               return ret;
-
-       ehci_port_power(ehci, 0);
-
-       return ret;
+       return ehci_setup(hcd);
 }
 
 static const struct hc_driver ehci_sh_hc_driver = {
index c718a065e154d675d634b48269160086148bfbe1..719ca48a471ac407ab68b2fa7892b20730bc2e34 100644 (file)
@@ -37,18 +37,11 @@ static void spear_stop_ehci(struct spear_ehci *ehci)
 static int ehci_spear_setup(struct usb_hcd *hcd)
 {
        struct ehci_hcd *ehci = hcd_to_ehci(hcd);
-       int retval = 0;
 
        /* registers start at offset 0x0 */
        ehci->caps = hcd->regs;
 
-       retval = ehci_setup(hcd);
-       if (retval)
-               return retval;
-
-       ehci_port_power(ehci, 0);
-
-       return retval;
+       return ehci_setup(hcd);
 }
 
 static const struct hc_driver ehci_spear_hc_driver = {
index 6223d1757848c6d43db7aa59d7042b1c8c736f02..94ee3212094e81524e87836573115e4041c0b622 100644 (file)
 #include <linux/pm_runtime.h>
 
 #include <linux/usb/tegra_usb_phy.h>
-#include <mach/iomap.h>
+
+#define TEGRA_USB_BASE                 0xC5000000
+#define TEGRA_USB2_BASE                        0xC5004000
+#define TEGRA_USB3_BASE                        0xC5008000
 
 #define TEGRA_USB_DMA_ALIGN 32
 
@@ -277,7 +280,6 @@ static void tegra_ehci_shutdown(struct usb_hcd *hcd)
 static int tegra_ehci_setup(struct usb_hcd *hcd)
 {
        struct ehci_hcd *ehci = hcd_to_ehci(hcd);
-       int retval;
 
        /* EHCI registers start at offset 0x100 */
        ehci->caps = hcd->regs + 0x100;
@@ -285,12 +287,7 @@ static int tegra_ehci_setup(struct usb_hcd *hcd)
        /* switch to host mode */
        hcd->has_tt = 1;
 
-       retval = ehci_setup(hcd);
-       if (retval)
-               return retval;
-
-       ehci_port_power(ehci, 1);
-       return retval;
+       return ehci_setup(hcd);
 }
 
 struct dma_aligned_buffer {
index d3c9a3e397b99ed4f423ee41575038890ff4e4eb..11695d5b9d869aa840c5f840f54a3b6dfa989641 100644 (file)
 #include <linux/of.h>
 #include <linux/platform_device.h>
 
-static int ehci_update_device(struct usb_hcd *hcd, struct usb_device *udev)
-{
-       struct ehci_hcd *ehci = hcd_to_ehci(hcd);
-       int rc = 0;
-
-       if (!udev->parent) /* udev is root hub itself, impossible */
-               rc = -1;
-       /* we only support lpm device connected to root hub yet */
-       if (ehci->has_lpm && !udev->parent->parent) {
-               rc = ehci_lpm_set_da(ehci, udev->devnum, udev->portnum);
-               if (!rc)
-                       rc = ehci_lpm_check(ehci, udev->portnum);
-       }
-       return rc;
-}
-
 static const struct hc_driver vt8500_ehci_hc_driver = {
        .description            = hcd_name,
        .product_desc           = "VT8500 EHCI",
@@ -77,11 +61,6 @@ static const struct hc_driver vt8500_ehci_hc_driver = {
        .relinquish_port        = ehci_relinquish_port,
        .port_handed_over       = ehci_port_handed_over,
 
-       /*
-        * call back when device connected and addressed
-        */
-       .update_device =        ehci_update_device,
-
        .clear_tt_buffer_complete       = ehci_clear_tt_buffer_complete,
 };
 
index ec598082c14b09476f7de3369f75b0d04b3a6a69..fdd7c4873cf20361aed91c58910828eff9cdebf0 100644 (file)
@@ -13,7 +13,7 @@
 
 #include <linux/platform_device.h>
 
-/*ebable phy0 and phy1 for w90p910*/
+/* enable phy0 and phy1 for w90p910 */
 #define        ENPHY           (0x01<<8)
 #define PHY0_CTR       (0xA4)
 #define PHY1_CTR       (0xA8)
diff --git a/drivers/usb/host/ehci-xls.c b/drivers/usb/host/ehci-xls.c
deleted file mode 100644 (file)
index 8dc6a22..0000000
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * EHCI HCD for Netlogic XLS processors.
- *
- * (C) Copyright 2011 Netlogic Microsystems Inc.
- *
- *  Based on various ehci-*.c drivers
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file COPYING in the main directory of this archive for
- * more details.
- */
-
-#include <linux/platform_device.h>
-
-static int ehci_xls_setup(struct usb_hcd *hcd)
-{
-       struct ehci_hcd *ehci = hcd_to_ehci(hcd);
-
-       ehci->caps = hcd->regs;
-
-       return ehci_setup(hcd);
-}
-
-int ehci_xls_probe_internal(const struct hc_driver *driver,
-       struct platform_device *pdev)
-{
-       struct usb_hcd  *hcd;
-       struct resource *res;
-       int retval, irq;
-
-       /* Get our IRQ from an earlier registered Platform Resource */
-       irq = platform_get_irq(pdev, 0);
-       if (irq < 0) {
-               dev_err(&pdev->dev, "Found HC with no IRQ. Check %s setup!\n",
-                               dev_name(&pdev->dev));
-               return -ENODEV;
-       }
-
-       /* Get our Memory Handle */
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               dev_err(&pdev->dev, "Error: MMIO Handle %s setup!\n",
-                               dev_name(&pdev->dev));
-               return -ENODEV;
-       }
-       hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev));
-       if (!hcd) {
-               retval = -ENOMEM;
-               goto err1;
-       }
-
-       hcd->rsrc_start = res->start;
-       hcd->rsrc_len = resource_size(res);
-
-       if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len,
-                               driver->description)) {
-               dev_dbg(&pdev->dev, "controller already in use\n");
-               retval = -EBUSY;
-               goto err2;
-       }
-       hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len);
-
-       if (hcd->regs == NULL) {
-               dev_dbg(&pdev->dev, "error mapping memory\n");
-               retval = -EFAULT;
-               goto err3;
-       }
-
-       retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
-       if (retval != 0)
-               goto err4;
-       return retval;
-
-err4:
-       iounmap(hcd->regs);
-err3:
-       release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
-err2:
-       usb_put_hcd(hcd);
-err1:
-       dev_err(&pdev->dev, "init %s fail, %d\n", dev_name(&pdev->dev),
-                       retval);
-       return retval;
-}
-
-static struct hc_driver ehci_xls_hc_driver = {
-       .description    = hcd_name,
-       .product_desc   = "XLS EHCI Host Controller",
-       .hcd_priv_size  = sizeof(struct ehci_hcd),
-       .irq            = ehci_irq,
-       .flags          = HCD_USB2 | HCD_MEMORY,
-       .reset          = ehci_xls_setup,
-       .start          = ehci_run,
-       .stop           = ehci_stop,
-       .shutdown       = ehci_shutdown,
-
-       .urb_enqueue    = ehci_urb_enqueue,
-       .urb_dequeue    = ehci_urb_dequeue,
-       .endpoint_disable = ehci_endpoint_disable,
-       .endpoint_reset = ehci_endpoint_reset,
-
-       .get_frame_number = ehci_get_frame,
-
-       .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 int ehci_xls_probe(struct platform_device *pdev)
-{
-       if (usb_disabled())
-               return -ENODEV;
-
-       return ehci_xls_probe_internal(&ehci_xls_hc_driver, pdev);
-}
-
-static int ehci_xls_remove(struct platform_device *pdev)
-{
-       struct usb_hcd *hcd = platform_get_drvdata(pdev);
-
-       usb_remove_hcd(hcd);
-       iounmap(hcd->regs);
-       release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
-       usb_put_hcd(hcd);
-       return 0;
-}
-
-MODULE_ALIAS("ehci-xls");
-
-static struct platform_driver ehci_xls_driver = {
-       .probe          = ehci_xls_probe,
-       .remove         = ehci_xls_remove,
-       .shutdown       = usb_hcd_platform_shutdown,
-       .driver         = {
-               .name = "ehci-xls",
-       },
-};
index da07d98f7d1de7780c578853e92b705c1231d316..9dadc7118d68e13a84e793a10171a500e6d52fad 100644 (file)
@@ -143,7 +143,7 @@ struct ehci_hcd {                   /* one per controller */
        struct ehci_qh          *intr_unlink_last;
        unsigned                intr_unlink_cycle;
        unsigned                now_frame;      /* frame from HC hardware */
-       unsigned                next_frame;     /* scan periodic, start here */
+       unsigned                last_iso_frame; /* last frame scanned for iso */
        unsigned                intr_count;     /* intr activity count */
        unsigned                isoc_count;     /* isoc activity count */
        unsigned                periodic_count; /* periodic activity count */
@@ -193,7 +193,6 @@ struct ehci_hcd {                   /* one per controller */
        unsigned                has_amcc_usb23:1;
        unsigned                need_io_watchdog:1;
        unsigned                amd_pll_fix:1;
-       unsigned                fs_i_thresh:1;  /* Intel iso scheduling */
        unsigned                use_dummy_qh:1; /* AMD Frame List table quirk*/
        unsigned                has_synopsys_hc_bug:1; /* Synopsys HC */
        unsigned                frame_index_bug:1; /* MosChip (AKA NetMos) */
@@ -207,7 +206,6 @@ struct ehci_hcd {                   /* one per controller */
        #define OHCI_HCCTRL_LEN         0x4
        __hc32                  *ohci_hcctrl_reg;
        unsigned                has_hostpc:1;
-       unsigned                has_lpm:1;  /* support link power management */
        unsigned                has_ppcd:1; /* support per-port change bits */
        u8                      sbrn;           /* packed release number */
 
@@ -762,26 +760,41 @@ static inline u32 hc32_to_cpup (const struct ehci_hcd *ehci, const __hc32 *x)
 
 /*-------------------------------------------------------------------------*/
 
-#ifdef CONFIG_PCI
-
-/* For working around the MosChip frame-index-register bug */
-static unsigned ehci_read_frame_index(struct ehci_hcd *ehci);
-
+#define ehci_dbg(ehci, fmt, args...) \
+       dev_dbg(ehci_to_hcd(ehci)->self.controller , fmt , ## args)
+#define ehci_err(ehci, fmt, args...) \
+       dev_err(ehci_to_hcd(ehci)->self.controller , fmt , ## args)
+#define ehci_info(ehci, fmt, args...) \
+       dev_info(ehci_to_hcd(ehci)->self.controller , fmt , ## args)
+#define ehci_warn(ehci, fmt, args...) \
+       dev_warn(ehci_to_hcd(ehci)->self.controller , fmt , ## args)
+
+#ifdef VERBOSE_DEBUG
+#      define ehci_vdbg ehci_dbg
 #else
-
-static inline unsigned ehci_read_frame_index(struct ehci_hcd *ehci)
-{
-       return ehci_readl(ehci, &ehci->regs->frame_index);
-}
-
+       static inline void ehci_vdbg(struct ehci_hcd *ehci, ...) {}
 #endif
 
-/*-------------------------------------------------------------------------*/
-
 #ifndef DEBUG
 #define STUB_DEBUG_FILES
 #endif /* DEBUG */
 
 /*-------------------------------------------------------------------------*/
 
+/* Declarations of things exported for use by ehci platform drivers */
+
+struct ehci_driver_overrides {
+       size_t          extra_priv_size;
+       int             (*reset)(struct usb_hcd *hcd);
+};
+
+extern void    ehci_init_driver(struct hc_driver *drv,
+                               const struct ehci_driver_overrides *over);
+extern int     ehci_setup(struct usb_hcd *hcd);
+
+#ifdef CONFIG_PM
+extern int     ehci_suspend(struct usb_hcd *hcd, bool do_wakeup);
+extern int     ehci_resume(struct usb_hcd *hcd, bool hibernated);
+#endif /* CONFIG_PM */
+
 #endif /* __LINUX_EHCI_HCD_H */
index fff114fd546155382d092b883547a12bca306ce2..958379f9de79596ad5fa5b5d179dbde0042ad7c4 100644 (file)
@@ -43,7 +43,6 @@ static int of_isp1760_probe(struct platform_device *dev)
        struct device_node *dp = dev->dev.of_node;
        struct resource *res;
        struct resource memory;
-       struct of_irq oirq;
        int virq;
        resource_size_t res_len;
        int ret;
@@ -69,14 +68,12 @@ static int of_isp1760_probe(struct platform_device *dev)
                goto free_data;
        }
 
-       if (of_irq_map_one(dp, 0, &oirq)) {
+       virq = irq_of_parse_and_map(dp, 0);
+       if (!virq) {
                ret = -ENODEV;
                goto release_reg;
        }
 
-       virq = irq_create_of_mapping(oirq.controller, oirq.specifier,
-                       oirq.size);
-
        if (of_device_is_compatible(dp, "nxp,usb-isp1761"))
                devflags |= ISP1760_FLAG_ISP1761;
 
index 0bf72f943b00d392654fdc9613e4f397bfac2d32..908d84af1dd72bca08b80f40177dfdecc881bd00 100644 (file)
@@ -705,7 +705,7 @@ static int ohci_hcd_at91_drv_resume(struct platform_device *pdev)
        if (!clocked)
                at91_start_clock();
 
-       ohci_finish_controller_resume(hcd);
+       ohci_resume(hcd, false);
        return 0;
 }
 #else
diff --git a/drivers/usb/host/ohci-au1xxx.c b/drivers/usb/host/ohci-au1xxx.c
deleted file mode 100644 (file)
index c611699..0000000
+++ /dev/null
@@ -1,234 +0,0 @@
-/*
- * OHCI HCD (Host Controller Driver) for USB.
- *
- * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
- * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
- * (C) Copyright 2002 Hewlett-Packard Company
- *
- * Bus Glue for AMD Alchemy Au1xxx
- *
- * Written by Christopher Hoover <ch@hpl.hp.com>
- * Based on fragments of previous driver by Russell King et al.
- *
- * Modified for LH7A404 from ohci-sa1111.c
- *  by Durgesh Pattamatta <pattamattad@sharpsec.com>
- * Modified for AMD Alchemy Au1xxx
- *  by Matt Porter <mporter@kernel.crashing.org>
- *
- * This file is licenced under the GPL.
- */
-
-#include <linux/platform_device.h>
-#include <linux/signal.h>
-
-#include <asm/mach-au1x00/au1000.h>
-
-
-extern int usb_disabled(void);
-
-static int __devinit ohci_au1xxx_start(struct usb_hcd *hcd)
-{
-       struct ohci_hcd *ohci = hcd_to_ohci(hcd);
-       int ret;
-
-       ohci_dbg(ohci, "ohci_au1xxx_start, ohci:%p", ohci);
-
-       if ((ret = ohci_init(ohci)) < 0)
-               return ret;
-
-       if ((ret = ohci_run(ohci)) < 0) {
-               dev_err(hcd->self.controller, "can't start %s",
-                       hcd->self.bus_name);
-               ohci_stop(hcd);
-               return ret;
-       }
-
-       return 0;
-}
-
-static const struct hc_driver ohci_au1xxx_hc_driver = {
-       .description =          hcd_name,
-       .product_desc =         "Au1xxx OHCI",
-       .hcd_priv_size =        sizeof(struct ohci_hcd),
-
-       /*
-        * generic hardware linkage
-        */
-       .irq =                  ohci_irq,
-       .flags =                HCD_USB11 | HCD_MEMORY,
-
-       /*
-        * basic lifecycle operations
-        */
-       .start =                ohci_au1xxx_start,
-       .stop =                 ohci_stop,
-       .shutdown =             ohci_shutdown,
-
-       /*
-        * managing i/o requests and associated device resources
-        */
-       .urb_enqueue =          ohci_urb_enqueue,
-       .urb_dequeue =          ohci_urb_dequeue,
-       .endpoint_disable =     ohci_endpoint_disable,
-
-       /*
-        * scheduling support
-        */
-       .get_frame_number =     ohci_get_frame,
-
-       /*
-        * root hub support
-        */
-       .hub_status_data =      ohci_hub_status_data,
-       .hub_control =          ohci_hub_control,
-#ifdef CONFIG_PM
-       .bus_suspend =          ohci_bus_suspend,
-       .bus_resume =           ohci_bus_resume,
-#endif
-       .start_port_reset =     ohci_start_port_reset,
-};
-
-static int ohci_hcd_au1xxx_drv_probe(struct platform_device *pdev)
-{
-       int ret, unit;
-       struct usb_hcd *hcd;
-
-       if (usb_disabled())
-               return -ENODEV;
-
-       if (pdev->resource[1].flags != IORESOURCE_IRQ) {
-               pr_debug("resource[1] is not IORESOURCE_IRQ\n");
-               return -ENOMEM;
-       }
-
-       hcd = usb_create_hcd(&ohci_au1xxx_hc_driver, &pdev->dev, "au1xxx");
-       if (!hcd)
-               return -ENOMEM;
-
-       hcd->rsrc_start = pdev->resource[0].start;
-       hcd->rsrc_len = pdev->resource[0].end - pdev->resource[0].start + 1;
-
-       if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
-               pr_debug("request_mem_region failed\n");
-               ret = -EBUSY;
-               goto err1;
-       }
-
-       hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
-       if (!hcd->regs) {
-               pr_debug("ioremap failed\n");
-               ret = -ENOMEM;
-               goto err2;
-       }
-
-       unit = (hcd->rsrc_start == AU1300_USB_OHCI1_PHYS_ADDR) ?
-                       ALCHEMY_USB_OHCI1 : ALCHEMY_USB_OHCI0;
-       if (alchemy_usb_control(unit, 1)) {
-               printk(KERN_INFO "%s: controller init failed!\n", pdev->name);
-               ret = -ENODEV;
-               goto err3;
-       }
-
-       ohci_hcd_init(hcd_to_ohci(hcd));
-
-       ret = usb_add_hcd(hcd, pdev->resource[1].start,
-                         IRQF_SHARED);
-       if (ret == 0) {
-               platform_set_drvdata(pdev, hcd);
-               return ret;
-       }
-
-       alchemy_usb_control(unit, 0);
-err3:
-       iounmap(hcd->regs);
-err2:
-       release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
-err1:
-       usb_put_hcd(hcd);
-       return ret;
-}
-
-static int ohci_hcd_au1xxx_drv_remove(struct platform_device *pdev)
-{
-       struct usb_hcd *hcd = platform_get_drvdata(pdev);
-       int unit;
-
-       unit = (hcd->rsrc_start == AU1300_USB_OHCI1_PHYS_ADDR) ?
-                       ALCHEMY_USB_OHCI1 : ALCHEMY_USB_OHCI0;
-       usb_remove_hcd(hcd);
-       alchemy_usb_control(unit, 0);
-       iounmap(hcd->regs);
-       release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
-       usb_put_hcd(hcd);
-       platform_set_drvdata(pdev, NULL);
-
-       return 0;
-}
-
-#ifdef CONFIG_PM
-static int ohci_hcd_au1xxx_drv_suspend(struct device *dev)
-{
-       struct usb_hcd *hcd = dev_get_drvdata(dev);
-       struct ohci_hcd *ohci = hcd_to_ohci(hcd);
-       unsigned long flags;
-       int rc;
-
-       rc = 0;
-
-       /* Root hub was already suspended. Disable irq emission and
-        * mark HW unaccessible, bail out if RH has been resumed. Use
-        * the spinlock to properly synchronize with possible pending
-        * RH suspend or resume activity.
-        */
-       spin_lock_irqsave(&ohci->lock, flags);
-       if (ohci->rh_state != OHCI_RH_SUSPENDED) {
-               rc = -EINVAL;
-               goto bail;
-       }
-       ohci_writel(ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable);
-       (void)ohci_readl(ohci, &ohci->regs->intrdisable);
-
-       clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
-
-       alchemy_usb_control(ALCHEMY_USB_OHCI0, 0);
-bail:
-       spin_unlock_irqrestore(&ohci->lock, flags);
-
-       return rc;
-}
-
-static int ohci_hcd_au1xxx_drv_resume(struct device *dev)
-{
-       struct usb_hcd *hcd = dev_get_drvdata(dev);
-
-       alchemy_usb_control(ALCHEMY_USB_OHCI0, 1);
-
-       set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
-       ohci_finish_controller_resume(hcd);
-
-       return 0;
-}
-
-static const struct dev_pm_ops au1xxx_ohci_pmops = {
-       .suspend        = ohci_hcd_au1xxx_drv_suspend,
-       .resume         = ohci_hcd_au1xxx_drv_resume,
-};
-
-#define AU1XXX_OHCI_PMOPS &au1xxx_ohci_pmops
-
-#else
-#define AU1XXX_OHCI_PMOPS NULL
-#endif
-
-static struct platform_driver ohci_hcd_au1xxx_driver = {
-       .probe          = ohci_hcd_au1xxx_drv_probe,
-       .remove         = ohci_hcd_au1xxx_drv_remove,
-       .shutdown       = usb_hcd_platform_shutdown,
-       .driver         = {
-               .name   = "au1xxx-ohci",
-               .owner  = THIS_MODULE,
-               .pm     = AU1XXX_OHCI_PMOPS,
-       },
-};
-
-MODULE_ALIAS("platform:au1xxx-ohci");
diff --git a/drivers/usb/host/ohci-cns3xxx.c b/drivers/usb/host/ohci-cns3xxx.c
deleted file mode 100644 (file)
index 2c9f233..0000000
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- * Copyright 2008 Cavium Networks
- *
- * This file is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License, Version 2, as
- * published by the Free Software Foundation.
- */
-
-#include <linux/platform_device.h>
-#include <linux/atomic.h>
-#include <mach/cns3xxx.h>
-#include <mach/pm.h>
-
-static int __devinit
-cns3xxx_ohci_start(struct usb_hcd *hcd)
-{
-       struct ohci_hcd *ohci = hcd_to_ohci(hcd);
-       int ret;
-
-       /*
-        * 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);
-       }
-
-       ret = ohci_init(ohci);
-       if (ret < 0)
-               return ret;
-
-       ohci->num_ports = 1;
-
-       ret = ohci_run(ohci);
-       if (ret < 0) {
-               dev_err(hcd->self.controller, "can't start %s\n",
-                       hcd->self.bus_name);
-               ohci_stop(hcd);
-               return ret;
-       }
-       return 0;
-}
-
-static const struct hc_driver cns3xxx_ohci_hc_driver = {
-       .description            = hcd_name,
-       .product_desc           = "CNS3XXX OHCI Host controller",
-       .hcd_priv_size          = sizeof(struct ohci_hcd),
-       .irq                    = ohci_irq,
-       .flags                  = HCD_USB11 | HCD_MEMORY,
-       .start                  = cns3xxx_ohci_start,
-       .stop                   = ohci_stop,
-       .shutdown               = ohci_shutdown,
-       .urb_enqueue            = ohci_urb_enqueue,
-       .urb_dequeue            = ohci_urb_dequeue,
-       .endpoint_disable       = ohci_endpoint_disable,
-       .get_frame_number       = ohci_get_frame,
-       .hub_status_data        = ohci_hub_status_data,
-       .hub_control            = ohci_hub_control,
-#ifdef CONFIG_PM
-       .bus_suspend            = ohci_bus_suspend,
-       .bus_resume             = ohci_bus_resume,
-#endif
-       .start_port_reset       = ohci_start_port_reset,
-};
-
-static int cns3xxx_ohci_probe(struct platform_device *pdev)
-{
-       struct device *dev = &pdev->dev;
-       struct usb_hcd *hcd;
-       const struct hc_driver *driver = &cns3xxx_ohci_hc_driver;
-       struct resource *res;
-       int irq;
-       int retval;
-
-       if (usb_disabled())
-               return -ENODEV;
-
-       res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-       if (!res) {
-               dev_err(dev, "Found HC with no IRQ.\n");
-               return -ENODEV;
-       }
-       irq = res->start;
-
-       hcd = usb_create_hcd(driver, dev, dev_name(dev));
-       if (!hcd)
-               return -ENOMEM;
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               dev_err(dev, "Found HC with no register addr.\n");
-               retval = -ENODEV;
-               goto err1;
-       }
-       hcd->rsrc_start = res->start;
-       hcd->rsrc_len = resource_size(res);
-
-       if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len,
-                       driver->description)) {
-               dev_dbg(dev, "controller already in use\n");
-               retval = -EBUSY;
-               goto err1;
-       }
-
-       hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
-       if (!hcd->regs) {
-               dev_dbg(dev, "error mapping memory\n");
-               retval = -EFAULT;
-               goto err2;
-       }
-
-       ohci_hcd_init(hcd_to_ohci(hcd));
-
-       retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
-       if (retval == 0)
-               return retval;
-
-       iounmap(hcd->regs);
-err2:
-       release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
-err1:
-       usb_put_hcd(hcd);
-       return retval;
-}
-
-static int cns3xxx_ohci_remove(struct platform_device *pdev)
-{
-       struct usb_hcd *hcd = platform_get_drvdata(pdev);
-
-       usb_remove_hcd(hcd);
-       iounmap(hcd->regs);
-       release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
-
-       /*
-        * 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);
-
-       usb_put_hcd(hcd);
-
-       platform_set_drvdata(pdev, NULL);
-
-       return 0;
-}
-
-MODULE_ALIAS("platform:cns3xxx-ohci");
-
-static struct platform_driver ohci_hcd_cns3xxx_driver = {
-       .probe = cns3xxx_ohci_probe,
-       .remove = cns3xxx_ohci_remove,
-       .driver = {
-               .name = "cns3xxx-ohci",
-       },
-};
index dbfbd1dfd2e2f798aae4fc60456d2190e47d0428..a982f04ed78705b037af6e91037ebea20a84ab85 100644 (file)
@@ -194,7 +194,7 @@ static int ohci_hcd_ep93xx_drv_resume(struct platform_device *pdev)
 
        ep93xx_start_hc(&pdev->dev);
 
-       ohci_finish_controller_resume(hcd);
+       ohci_resume(hcd, false);
        return 0;
 }
 #endif
index 20a50081f9225d7111c7a9ddfe3d91dc1f8bde97..6a30fc5bec934defc560b5d295bd6bbe709e137e 100644 (file)
@@ -23,6 +23,11 @@ struct exynos_ohci_hcd {
        struct clk *clk;
 };
 
+static int ohci_exynos_reset(struct usb_hcd *hcd)
+{
+       return ohci_init(hcd_to_ohci(hcd));
+}
+
 static int ohci_exynos_start(struct usb_hcd *hcd)
 {
        struct ohci_hcd *ohci = hcd_to_ohci(hcd);
@@ -30,10 +35,6 @@ static int ohci_exynos_start(struct usb_hcd *hcd)
 
        ohci_dbg(ohci, "ohci_exynos_start, ohci:%p", ohci);
 
-       ret = ohci_init(ohci);
-       if (ret < 0)
-               return ret;
-
        ret = ohci_run(ohci);
        if (ret < 0) {
                dev_err(hcd->self.controller, "can't start %s\n",
@@ -53,6 +54,7 @@ static const struct hc_driver exynos_ohci_hc_driver = {
        .irq                    = ohci_irq,
        .flags                  = HCD_MEMORY|HCD_USB11,
 
+       .reset                  = ohci_exynos_reset,
        .start                  = ohci_exynos_start,
        .stop                   = ohci_stop,
        .shutdown               = ohci_shutdown,
@@ -115,7 +117,7 @@ static int __devinit exynos_ohci_probe(struct platform_device *pdev)
        }
 
        exynos_ohci->hcd = hcd;
-       exynos_ohci->clk = clk_get(&pdev->dev, "usbhost");
+       exynos_ohci->clk = devm_clk_get(&pdev->dev, "usbhost");
 
        if (IS_ERR(exynos_ohci->clk)) {
                dev_err(&pdev->dev, "Failed to get usbhost clock\n");
@@ -123,9 +125,9 @@ static int __devinit exynos_ohci_probe(struct platform_device *pdev)
                goto fail_clk;
        }
 
-       err = clk_enable(exynos_ohci->clk);
+       err = clk_prepare_enable(exynos_ohci->clk);
        if (err)
-               goto fail_clken;
+               goto fail_clk;
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!res) {
@@ -167,9 +169,7 @@ static int __devinit exynos_ohci_probe(struct platform_device *pdev)
        return 0;
 
 fail_io:
-       clk_disable(exynos_ohci->clk);
-fail_clken:
-       clk_put(exynos_ohci->clk);
+       clk_disable_unprepare(exynos_ohci->clk);
 fail_clk:
        usb_put_hcd(hcd);
        return err;
@@ -186,8 +186,7 @@ static int __devexit exynos_ohci_remove(struct platform_device *pdev)
        if (pdata && pdata->phy_exit)
                pdata->phy_exit(pdev, S5P_USB_PHY_HOST);
 
-       clk_disable(exynos_ohci->clk);
-       clk_put(exynos_ohci->clk);
+       clk_disable_unprepare(exynos_ohci->clk);
 
        usb_put_hcd(hcd);
 
@@ -232,7 +231,7 @@ static int exynos_ohci_suspend(struct device *dev)
        if (pdata && pdata->phy_exit)
                pdata->phy_exit(pdev, S5P_USB_PHY_HOST);
 
-       clk_disable(exynos_ohci->clk);
+       clk_disable_unprepare(exynos_ohci->clk);
 
 fail:
        spin_unlock_irqrestore(&ohci->lock, flags);
@@ -247,15 +246,12 @@ static int exynos_ohci_resume(struct device *dev)
        struct platform_device *pdev = to_platform_device(dev);
        struct exynos4_ohci_platdata *pdata = pdev->dev.platform_data;
 
-       clk_enable(exynos_ohci->clk);
+       clk_prepare_enable(exynos_ohci->clk);
 
        if (pdata && pdata->phy_init)
                pdata->phy_init(pdev, S5P_USB_PHY_HOST);
 
-       /* Mark hardware accessible again as we are out of D3 state by now */
-       set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
-
-       ohci_finish_controller_resume(hcd);
+       ohci_resume(hcd, false);
 
        return 0;
 }
index 4a1d64d92338e7653035b054decf6e714909a41f..180a2b01db56c9d496fb52388a324d2df2b4a931 100644 (file)
@@ -231,13 +231,41 @@ static int ohci_urb_enqueue (
                        frame &= ~(ed->interval - 1);
                        frame |= ed->branch;
                        urb->start_frame = frame;
+               }
+       } else if (ed->type == PIPE_ISOCHRONOUS) {
+               u16     next = ohci_frame_no(ohci) + 2;
+               u16     frame = ed->last_iso + ed->interval;
+
+               /* Behind the scheduling threshold? */
+               if (unlikely(tick_before(frame, next))) {
 
-                       /* yes, only URB_ISO_ASAP is supported, and
-                        * urb->start_frame is never used as input.
+                       /* USB_ISO_ASAP: Round up to the first available slot */
+                       if (urb->transfer_flags & URB_ISO_ASAP)
+                               frame += (next - frame + ed->interval - 1) &
+                                               -ed->interval;
+
+                       /*
+                        * Not ASAP: Use the next slot in the stream.  If
+                        * the entire URB falls before the threshold, fail.
                         */
+                       else if (tick_before(frame + ed->interval *
+                                       (urb->number_of_packets - 1), next)) {
+                               retval = -EXDEV;
+                               usb_hcd_unlink_urb_from_ep(hcd, urb);
+                               goto fail;
+                       }
+
+                       /*
+                        * Some OHCI hardware doesn't handle late TDs
+                        * correctly.  After retiring them it proceeds to
+                        * the next ED instead of the next TD.  Therefore
+                        * we have to omit the late TDs entirely.
+                        */
+                       urb_priv->td_cnt = DIV_ROUND_UP(next - frame,
+                                       ed->interval);
                }
-       } else if (ed->type == PIPE_ISOCHRONOUS)
-               urb->start_frame = ed->last_iso + ed->interval;
+               urb->start_frame = frame;
+       }
 
        /* fill the TDs and link them to the ed; and
         * enable that part of the schedule, if needed
@@ -983,6 +1011,79 @@ static int ohci_restart (struct ohci_hcd *ohci)
 
 #endif
 
+#ifdef CONFIG_PM
+
+static int __maybe_unused ohci_suspend(struct usb_hcd *hcd, bool do_wakeup)
+{
+       struct ohci_hcd *ohci = hcd_to_ohci (hcd);
+       unsigned long   flags;
+
+       /* Disable irq emission and mark HW unaccessible. Use
+        * the spinlock to properly synchronize with possible pending
+        * RH suspend or resume activity.
+        */
+       spin_lock_irqsave (&ohci->lock, flags);
+       ohci_writel(ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable);
+       (void)ohci_readl(ohci, &ohci->regs->intrdisable);
+
+       clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+       spin_unlock_irqrestore (&ohci->lock, flags);
+
+       return 0;
+}
+
+
+static int __maybe_unused ohci_resume(struct usb_hcd *hcd, bool hibernated)
+{
+       struct ohci_hcd         *ohci = hcd_to_ohci(hcd);
+       int                     port;
+       bool                    need_reinit = false;
+
+       set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+
+       /* Make sure resume from hibernation re-enumerates everything */
+       if (hibernated)
+               ohci_usb_reset(ohci);
+
+       /* See if the controller is already running or has been reset */
+       ohci->hc_control = ohci_readl(ohci, &ohci->regs->control);
+       if (ohci->hc_control & (OHCI_CTRL_IR | OHCI_SCHED_ENABLES)) {
+               need_reinit = true;
+       } else {
+               switch (ohci->hc_control & OHCI_CTRL_HCFS) {
+               case OHCI_USB_OPER:
+               case OHCI_USB_RESET:
+                       need_reinit = true;
+               }
+       }
+
+       /* If needed, reinitialize and suspend the root hub */
+       if (need_reinit) {
+               spin_lock_irq(&ohci->lock);
+               ohci_rh_resume(ohci);
+               ohci_rh_suspend(ohci, 0);
+               spin_unlock_irq(&ohci->lock);
+       }
+
+       /* Normally just turn on port power and enable interrupts */
+       else {
+               ohci_dbg(ohci, "powerup ports\n");
+               for (port = 0; port < ohci->num_ports; port++)
+                       ohci_writel(ohci, RH_PS_PPS,
+                                       &ohci->regs->roothub.portstatus[port]);
+
+               ohci_writel(ohci, OHCI_INTR_MIE, &ohci->regs->intrenable);
+               ohci_readl(ohci, &ohci->regs->intrenable);
+               msleep(20);
+       }
+
+       usb_hcd_resume_root_hub(hcd);
+
+       return 0;
+}
+
+#endif
+
 /*-------------------------------------------------------------------------*/
 
 MODULE_AUTHOR (DRIVER_AUTHOR);
@@ -1029,21 +1130,6 @@ MODULE_LICENSE ("GPL");
 #define PLATFORM_DRIVER                ohci_hcd_ep93xx_driver
 #endif
 
-#ifdef CONFIG_MIPS_ALCHEMY
-#include "ohci-au1xxx.c"
-#define PLATFORM_DRIVER                ohci_hcd_au1xxx_driver
-#endif
-
-#ifdef CONFIG_PNX8550
-#include "ohci-pnx8550.c"
-#define PLATFORM_DRIVER                ohci_hcd_pnx8550_driver
-#endif
-
-#ifdef CONFIG_USB_OHCI_HCD_PPC_SOC
-#include "ohci-ppc-soc.c"
-#define PLATFORM_DRIVER                ohci_hcd_ppc_soc_driver
-#endif
-
 #ifdef CONFIG_ARCH_AT91
 #include "ohci-at91.c"
 #define PLATFORM_DRIVER                ohci_hcd_at91_driver
@@ -1059,11 +1145,6 @@ MODULE_LICENSE ("GPL");
 #define PLATFORM_DRIVER                ohci_hcd_da8xx_driver
 #endif
 
-#ifdef CONFIG_USB_OHCI_SH
-#include "ohci-sh.c"
-#define PLATFORM_DRIVER                ohci_hcd_sh_driver
-#endif
-
 
 #ifdef CONFIG_USB_OHCI_HCD_PPC_OF
 #include "ohci-ppc-of.c"
@@ -1105,16 +1186,6 @@ MODULE_LICENSE ("GPL");
 #define PLATFORM_DRIVER                ohci_hcd_tilegx_driver
 #endif
 
-#ifdef CONFIG_USB_CNS3XXX_OHCI
-#include "ohci-cns3xxx.c"
-#define PLATFORM_DRIVER                ohci_hcd_cns3xxx_driver
-#endif
-
-#ifdef CONFIG_CPU_XLR
-#include "ohci-xls.c"
-#define PLATFORM_DRIVER                ohci_xls_driver
-#endif
-
 #ifdef CONFIG_USB_OHCI_HCD_PLATFORM
 #include "ohci-platform.c"
 #define PLATFORM_DRIVER                ohci_platform_driver
index 2f3619eefefa9bca87189e5da44dd6bbb0cd8191..db09dae7b557a18063d424a3ffc58c1edb8ccca8 100644 (file)
@@ -316,48 +316,6 @@ static int ohci_bus_resume (struct usb_hcd *hcd)
        return rc;
 }
 
-/* Carry out the final steps of resuming the controller device */
-static void __maybe_unused ohci_finish_controller_resume(struct usb_hcd *hcd)
-{
-       struct ohci_hcd         *ohci = hcd_to_ohci(hcd);
-       int                     port;
-       bool                    need_reinit = false;
-
-       /* See if the controller is already running or has been reset */
-       ohci->hc_control = ohci_readl(ohci, &ohci->regs->control);
-       if (ohci->hc_control & (OHCI_CTRL_IR | OHCI_SCHED_ENABLES)) {
-               need_reinit = true;
-       } else {
-               switch (ohci->hc_control & OHCI_CTRL_HCFS) {
-               case OHCI_USB_OPER:
-               case OHCI_USB_RESET:
-                       need_reinit = true;
-               }
-       }
-
-       /* If needed, reinitialize and suspend the root hub */
-       if (need_reinit) {
-               spin_lock_irq(&ohci->lock);
-               ohci_rh_resume(ohci);
-               ohci_rh_suspend(ohci, 0);
-               spin_unlock_irq(&ohci->lock);
-       }
-
-       /* Normally just turn on port power and enable interrupts */
-       else {
-               ohci_dbg(ohci, "powerup ports\n");
-               for (port = 0; port < ohci->num_ports; port++)
-                       ohci_writel(ohci, RH_PS_PPS,
-                                       &ohci->regs->roothub.portstatus[port]);
-
-               ohci_writel(ohci, OHCI_INTR_MIE, &ohci->regs->intrenable);
-               ohci_readl(ohci, &ohci->regs->intrenable);
-               msleep(20);
-       }
-
-       usb_hcd_resume_root_hub(hcd);
-}
-
 /* Carry out polling-, autostop-, and autoresume-related state changes */
 static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed,
                int any_connected, int rhsc_status)
index 4531d03503c32371f4b1c5cd505ac38243dafe13..733c77c36355ac95082ec08cc3ceb4e3c7d9d881 100644 (file)
@@ -530,7 +530,7 @@ static int ohci_omap_resume(struct platform_device *dev)
        ohci->next_statechange = jiffies;
 
        omap_ohci_clock_power(1);
-       ohci_finish_controller_resume(hcd);
+       ohci_resume(hcd, false);
        return 0;
 }
 
index 1843bb68ac7ceefc73afcc2ed9f3a2f7fa8de1db..6afa7dc4e4c39a3f4ec5374915819b8483e74a9f 100644 (file)
@@ -296,49 +296,6 @@ static int __devinit ohci_pci_start (struct usb_hcd *hcd)
        return ret;
 }
 
-#ifdef CONFIG_PM
-
-static int ohci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup)
-{
-       struct ohci_hcd *ohci = hcd_to_ohci (hcd);
-       unsigned long   flags;
-       int             rc = 0;
-
-       /* Root hub was already suspended. Disable irq emission and
-        * mark HW unaccessible, bail out if RH has been resumed. Use
-        * the spinlock to properly synchronize with possible pending
-        * RH suspend or resume activity.
-        */
-       spin_lock_irqsave (&ohci->lock, flags);
-       if (ohci->rh_state != OHCI_RH_SUSPENDED) {
-               rc = -EINVAL;
-               goto bail;
-       }
-       ohci_writel(ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable);
-       (void)ohci_readl(ohci, &ohci->regs->intrdisable);
-
-       clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
- bail:
-       spin_unlock_irqrestore (&ohci->lock, flags);
-
-       return rc;
-}
-
-
-static int ohci_pci_resume(struct usb_hcd *hcd, bool hibernated)
-{
-       set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
-
-       /* Make sure resume from hibernation re-enumerates everything */
-       if (hibernated)
-               ohci_usb_reset(hcd_to_ohci(hcd));
-
-       ohci_finish_controller_resume(hcd);
-       return 0;
-}
-
-#endif /* CONFIG_PM */
-
 
 /*-------------------------------------------------------------------------*/
 
@@ -362,8 +319,8 @@ static const struct hc_driver ohci_pci_hc_driver = {
        .shutdown =             ohci_shutdown,
 
 #ifdef CONFIG_PM
-       .pci_suspend =          ohci_pci_suspend,
-       .pci_resume =           ohci_pci_resume,
+       .pci_suspend =          ohci_suspend,
+       .pci_resume =           ohci_resume,
 #endif
 
        /*
index e24ec9f79164afc9e6563a147cb76d4c0f3c96c3..bda4e0bb8ab3c14a0b4e02e8e40b2bd2b9306359 100644 (file)
@@ -31,6 +31,10 @@ static int ohci_platform_reset(struct usb_hcd *hcd)
                ohci->flags |= OHCI_QUIRK_FRAME_NO;
 
        ohci_hcd_init(ohci);
+
+       if (pdata->num_ports)
+               ohci->num_ports = pdata->num_ports;
+
        err = ohci_init(ohci);
 
        return err;
@@ -97,13 +101,13 @@ static int __devinit ohci_platform_probe(struct platform_device *dev)
 
        irq = platform_get_irq(dev, 0);
        if (irq < 0) {
-               pr_err("no irq provided");
+               dev_err(&dev->dev, "no irq provided");
                return irq;
        }
 
        res_mem = platform_get_resource(dev, IORESOURCE_MEM, 0);
        if (!res_mem) {
-               pr_err("no memory recourse provided");
+               dev_err(&dev->dev, "no memory resource provided");
                return -ENXIO;
        }
 
@@ -123,29 +127,19 @@ static int __devinit ohci_platform_probe(struct platform_device *dev)
        hcd->rsrc_start = res_mem->start;
        hcd->rsrc_len = resource_size(res_mem);
 
-       if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
-               pr_err("controller already in use");
-               err = -EBUSY;
-               goto err_put_hcd;
-       }
-
-       hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len);
+       hcd->regs = devm_request_and_ioremap(&dev->dev, res_mem);
        if (!hcd->regs) {
                err = -ENOMEM;
-               goto err_release_region;
+               goto err_put_hcd;
        }
        err = usb_add_hcd(hcd, irq, IRQF_SHARED);
        if (err)
-               goto err_iounmap;
+               goto err_put_hcd;
 
        platform_set_drvdata(dev, hcd);
 
        return err;
 
-err_iounmap:
-       iounmap(hcd->regs);
-err_release_region:
-       release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
 err_put_hcd:
        usb_put_hcd(hcd);
 err_power:
@@ -161,8 +155,6 @@ static int __devexit ohci_platform_remove(struct platform_device *dev)
        struct usb_ohci_pdata *pdata = dev->dev.platform_data;
 
        usb_remove_hcd(hcd);
-       iounmap(hcd->regs);
-       release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
        usb_put_hcd(hcd);
        platform_set_drvdata(dev, NULL);
 
@@ -199,7 +191,7 @@ static int ohci_platform_resume(struct device *dev)
                        return err;
        }
 
-       ohci_finish_controller_resume(hcd);
+       ohci_resume(hcd, false);
        return 0;
 }
 
diff --git a/drivers/usb/host/ohci-pnx8550.c b/drivers/usb/host/ohci-pnx8550.c
deleted file mode 100644 (file)
index 148d27d..0000000
+++ /dev/null
@@ -1,243 +0,0 @@
-/*
- * OHCI HCD (Host Controller Driver) for USB.
- *
- * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
- * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
- * (C) Copyright 2002 Hewlett-Packard Company
- * (C) Copyright 2005 Embedded Alley Solutions, Inc.
- *
- * Bus Glue for PNX8550
- *
- * Written by Christopher Hoover <ch@hpl.hp.com>
- * Based on fragments of previous driver by Russell King et al.
- *
- * Modified for LH7A404 from ohci-sa1111.c
- *  by Durgesh Pattamatta <pattamattad@sharpsec.com>
- *
- * Modified for PNX8550 from ohci-sa1111.c and sa-omap.c
- *  by Vitaly Wool <vitalywool@gmail.com>
- *
- * This file is licenced under the GPL.
- */
-
-#include <linux/device.h>
-#include <linux/platform_device.h>
-#include <asm/mach-pnx8550/usb.h>
-#include <asm/mach-pnx8550/int.h>
-#include <asm/mach-pnx8550/pci.h>
-
-#ifndef CONFIG_PNX8550
-#error "This file is PNX8550 bus glue.  CONFIG_PNX8550 must be defined."
-#endif
-
-extern int usb_disabled(void);
-
-/*-------------------------------------------------------------------------*/
-
-static void pnx8550_start_hc(struct platform_device *dev)
-{
-       /*
-        * 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);
-}
-
-static void pnx8550_stop_hc(struct platform_device *dev)
-{
-       udelay(10);
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-/* configure so an HC device and id are always provided */
-/* always called with process context; sleeping is OK */
-
-
-/**
- * usb_hcd_pnx8550_probe - initialize pnx8550-based HCDs
- * Context: !in_interrupt()
- *
- * Allocates basic resources for this USB host controller, and
- * then invokes the start() method for the HCD associated with it
- * through the hotplug entry's driver_data.
- *
- */
-int usb_hcd_pnx8550_probe (const struct hc_driver *driver,
-                         struct platform_device *dev)
-{
-       int retval;
-       struct usb_hcd *hcd;
-
-       if (dev->resource[0].flags != IORESOURCE_MEM ||
-                       dev->resource[1].flags != IORESOURCE_IRQ) {
-               dev_err (&dev->dev,"invalid resource type\n");
-               return -ENOMEM;
-       }
-
-       hcd = usb_create_hcd (driver, &dev->dev, "pnx8550");
-       if (!hcd)
-               return -ENOMEM;
-       hcd->rsrc_start = dev->resource[0].start;
-       hcd->rsrc_len = dev->resource[0].end - dev->resource[0].start + 1;
-
-       if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
-               dev_err(&dev->dev, "request_mem_region [0x%08llx, 0x%08llx] "
-                               "failed\n", hcd->rsrc_start, hcd->rsrc_len);
-               retval = -EBUSY;
-               goto err1;
-       }
-
-       hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
-       if (!hcd->regs) {
-               dev_err(&dev->dev, "ioremap [[0x%08llx, 0x%08llx] failed\n",
-                               hcd->rsrc_start, hcd->rsrc_len);
-               retval = -ENOMEM;
-               goto err2;
-       }
-
-       pnx8550_start_hc(dev);
-
-       ohci_hcd_init(hcd_to_ohci(hcd));
-
-       retval = usb_add_hcd(hcd, dev->resource[1].start, 0);
-       if (retval == 0)
-               return retval;
-
-       pnx8550_stop_hc(dev);
-       iounmap(hcd->regs);
- err2:
-       release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
- err1:
-       usb_put_hcd(hcd);
-       return retval;
-}
-
-
-/* may be called without controller electrically present */
-/* may be called with controller, bus, and devices active */
-
-/**
- * usb_hcd_pnx8550_remove - shutdown processing for pnx8550-based HCDs
- * @dev: USB Host Controller being removed
- * Context: !in_interrupt()
- *
- * Reverses the effect of usb_hcd_pnx8550_probe(), first invoking
- * the HCD's stop() method.  It is always called from a thread
- * context, normally "rmmod", "apmd", or something similar.
- *
- */
-void usb_hcd_pnx8550_remove (struct usb_hcd *hcd, struct platform_device *dev)
-{
-       usb_remove_hcd(hcd);
-       pnx8550_stop_hc(dev);
-       iounmap(hcd->regs);
-       release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
-       usb_put_hcd(hcd);
-}
-
-/*-------------------------------------------------------------------------*/
-
-static int __devinit
-ohci_pnx8550_start (struct usb_hcd *hcd)
-{
-       struct ohci_hcd *ohci = hcd_to_ohci (hcd);
-       int             ret;
-
-       ohci_dbg (ohci, "ohci_pnx8550_start, ohci:%p", ohci);
-
-       if ((ret = ohci_init(ohci)) < 0)
-               return ret;
-
-       if ((ret = ohci_run (ohci)) < 0) {
-               dev_err(hcd->self.controller, "can't start %s",
-                       hcd->self.bus_name);
-               ohci_stop (hcd);
-               return ret;
-       }
-
-       return 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static const struct hc_driver ohci_pnx8550_hc_driver = {
-       .description =          hcd_name,
-       .product_desc =         "PNX8550 OHCI",
-       .hcd_priv_size =        sizeof(struct ohci_hcd),
-
-       /*
-        * generic hardware linkage
-        */
-       .irq =                  ohci_irq,
-       .flags =                HCD_USB11 | HCD_MEMORY,
-
-       /*
-        * basic lifecycle operations
-        */
-       .start =                ohci_pnx8550_start,
-       .stop =                 ohci_stop,
-
-       /*
-        * managing i/o requests and associated device resources
-        */
-       .urb_enqueue =          ohci_urb_enqueue,
-       .urb_dequeue =          ohci_urb_dequeue,
-       .endpoint_disable =     ohci_endpoint_disable,
-
-       /*
-        * scheduling support
-        */
-       .get_frame_number =     ohci_get_frame,
-
-       /*
-        * root hub support
-        */
-       .hub_status_data =      ohci_hub_status_data,
-       .hub_control =          ohci_hub_control,
-#ifdef CONFIG_PM
-       .bus_suspend =          ohci_bus_suspend,
-       .bus_resume =           ohci_bus_resume,
-#endif
-       .start_port_reset =     ohci_start_port_reset,
-};
-
-/*-------------------------------------------------------------------------*/
-
-static int ohci_hcd_pnx8550_drv_probe(struct platform_device *pdev)
-{
-       int ret;
-
-       if (usb_disabled())
-               return -ENODEV;
-
-       ret = usb_hcd_pnx8550_probe(&ohci_pnx8550_hc_driver, pdev);
-       return ret;
-}
-
-static int ohci_hcd_pnx8550_drv_remove(struct platform_device *pdev)
-{
-       struct usb_hcd *hcd = platform_get_drvdata(pdev);
-
-       usb_hcd_pnx8550_remove(hcd, pdev);
-       return 0;
-}
-
-MODULE_ALIAS("platform:pnx8550-ohci");
-
-static struct platform_driver ohci_hcd_pnx8550_driver = {
-       .driver = {
-               .name   = "pnx8550-ohci",
-               .owner  = THIS_MODULE,
-       },
-       .probe          = ohci_hcd_pnx8550_drv_probe,
-       .remove         = ohci_hcd_pnx8550_drv_remove,
-};
-
diff --git a/drivers/usb/host/ohci-ppc-soc.c b/drivers/usb/host/ohci-ppc-soc.c
deleted file mode 100644 (file)
index 185c39e..0000000
+++ /dev/null
@@ -1,216 +0,0 @@
-/*
- * OHCI HCD (Host Controller Driver) for USB.
- *
- * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
- * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
- * (C) Copyright 2002 Hewlett-Packard Company
- * (C) Copyright 2003-2005 MontaVista Software Inc.
- *
- * Bus Glue for PPC On-Chip OHCI driver
- * Tested on Freescale MPC5200 and IBM STB04xxx
- *
- * Modified by Dale Farnsworth <dale@farnsworth.org> from ohci-sa1111.c
- *
- * This file is licenced under the GPL.
- */
-
-#include <linux/platform_device.h>
-#include <linux/signal.h>
-
-/* configure so an HC device and id are always provided */
-/* always called with process context; sleeping is OK */
-
-/**
- * usb_hcd_ppc_soc_probe - initialize On-Chip HCDs
- * Context: !in_interrupt()
- *
- * Allocates basic resources for this USB host controller.
- *
- * Store this function in the HCD's struct pci_driver as probe().
- */
-static int usb_hcd_ppc_soc_probe(const struct hc_driver *driver,
-                         struct platform_device *pdev)
-{
-       int retval;
-       struct usb_hcd *hcd;
-       struct ohci_hcd *ohci;
-       struct resource *res;
-       int irq;
-
-       pr_debug("initializing PPC-SOC USB Controller\n");
-
-       res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-       if (!res) {
-               pr_debug("%s: no irq\n", __FILE__);
-               return -ENODEV;
-       }
-       irq = res->start;
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               pr_debug("%s: no reg addr\n", __FILE__);
-               return -ENODEV;
-       }
-
-       hcd = usb_create_hcd(driver, &pdev->dev, "PPC-SOC USB");
-       if (!hcd)
-               return -ENOMEM;
-       hcd->rsrc_start = res->start;
-       hcd->rsrc_len = resource_size(res);
-
-       if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
-               pr_debug("%s: request_mem_region failed\n", __FILE__);
-               retval = -EBUSY;
-               goto err1;
-       }
-
-       hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
-       if (!hcd->regs) {
-               pr_debug("%s: ioremap failed\n", __FILE__);
-               retval = -ENOMEM;
-               goto err2;
-       }
-
-       ohci = hcd_to_ohci(hcd);
-       ohci->flags |= OHCI_QUIRK_BE_MMIO | OHCI_QUIRK_BE_DESC;
-
-#ifdef CONFIG_PPC_MPC52xx
-       /* MPC52xx doesn't need frame_no shift */
-       ohci->flags |= OHCI_QUIRK_FRAME_NO;
-#endif
-       ohci_hcd_init(ohci);
-
-       retval = usb_add_hcd(hcd, irq, 0);
-       if (retval == 0)
-               return retval;
-
-       pr_debug("Removing PPC-SOC USB Controller\n");
-
-       iounmap(hcd->regs);
- err2:
-       release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
- err1:
-       usb_put_hcd(hcd);
-       return retval;
-}
-
-
-/* may be called without controller electrically present */
-/* may be called with controller, bus, and devices active */
-
-/**
- * usb_hcd_ppc_soc_remove - shutdown processing for On-Chip HCDs
- * @pdev: USB Host Controller being removed
- * Context: !in_interrupt()
- *
- * Reverses the effect of usb_hcd_ppc_soc_probe().
- * It is always called from a thread
- * context, normally "rmmod", "apmd", or something similar.
- *
- */
-static void usb_hcd_ppc_soc_remove(struct usb_hcd *hcd,
-               struct platform_device *pdev)
-{
-       usb_remove_hcd(hcd);
-
-       pr_debug("stopping PPC-SOC USB Controller\n");
-
-       iounmap(hcd->regs);
-       release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
-       usb_put_hcd(hcd);
-}
-
-static int __devinit
-ohci_ppc_soc_start(struct usb_hcd *hcd)
-{
-       struct ohci_hcd *ohci = hcd_to_ohci(hcd);
-       int             ret;
-
-       if ((ret = ohci_init(ohci)) < 0)
-               return ret;
-
-       if ((ret = ohci_run(ohci)) < 0) {
-               dev_err(hcd->self.controller, "can't start %s\n",
-                       hcd->self.bus_name);
-               ohci_stop(hcd);
-               return ret;
-       }
-
-       return 0;
-}
-
-static const struct hc_driver ohci_ppc_soc_hc_driver = {
-       .description =          hcd_name,
-       .hcd_priv_size =        sizeof(struct ohci_hcd),
-
-       /*
-        * generic hardware linkage
-        */
-       .irq =                  ohci_irq,
-       .flags =                HCD_USB11 | HCD_MEMORY,
-
-       /*
-        * basic lifecycle operations
-        */
-       .start =                ohci_ppc_soc_start,
-       .stop =                 ohci_stop,
-       .shutdown =             ohci_shutdown,
-
-       /*
-        * managing i/o requests and associated device resources
-        */
-       .urb_enqueue =          ohci_urb_enqueue,
-       .urb_dequeue =          ohci_urb_dequeue,
-       .endpoint_disable =     ohci_endpoint_disable,
-
-       /*
-        * scheduling support
-        */
-       .get_frame_number =     ohci_get_frame,
-
-       /*
-        * root hub support
-        */
-       .hub_status_data =      ohci_hub_status_data,
-       .hub_control =          ohci_hub_control,
-#ifdef CONFIG_PM
-       .bus_suspend =          ohci_bus_suspend,
-       .bus_resume =           ohci_bus_resume,
-#endif
-       .start_port_reset =     ohci_start_port_reset,
-};
-
-static int ohci_hcd_ppc_soc_drv_probe(struct platform_device *pdev)
-{
-       int ret;
-
-       if (usb_disabled())
-               return -ENODEV;
-
-       ret = usb_hcd_ppc_soc_probe(&ohci_ppc_soc_hc_driver, pdev);
-       return ret;
-}
-
-static int ohci_hcd_ppc_soc_drv_remove(struct platform_device *pdev)
-{
-       struct usb_hcd *hcd = platform_get_drvdata(pdev);
-
-       usb_hcd_ppc_soc_remove(hcd, pdev);
-       return 0;
-}
-
-static struct platform_driver ohci_hcd_ppc_soc_driver = {
-       .probe          = ohci_hcd_ppc_soc_drv_probe,
-       .remove         = ohci_hcd_ppc_soc_drv_remove,
-       .shutdown       = usb_hcd_platform_shutdown,
-#ifdef CONFIG_PM
-       /*.suspend      = ohci_hcd_ppc_soc_drv_suspend,*/
-       /*.resume       = ohci_hcd_ppc_soc_drv_resume,*/
-#endif
-       .driver         = {
-               .name   = "ppc-soc-ohci",
-               .owner  = THIS_MODULE,
-       },
-};
-
-MODULE_ALIAS("platform:ppc-soc-ohci");
index 2bf11440b010443290f2cbd6795cf22ddf561b0d..156d289d3bb51112b6aad220291101ceafe5e4ff 100644 (file)
@@ -591,7 +591,7 @@ static int ohci_hcd_pxa27x_drv_resume(struct device *dev)
        /* Select Power Management Mode */
        pxa27x_ohci_select_pmm(ohci, inf->port_mode);
 
-       ohci_finish_controller_resume(hcd);
+       ohci_resume(hcd, false);
        return 0;
 }
 
index c5a1ea9145faec6e65809ddf1fdbb7046f6897cc..177a213790d47f6d9abe059c15e8043230f690c8 100644 (file)
@@ -596,7 +596,6 @@ static void td_submit_urb (
                urb_priv->ed->hwHeadP &= ~cpu_to_hc32 (ohci, ED_C);
        }
 
-       urb_priv->td_cnt = 0;
        list_add (&urb_priv->pending, &ohci->pending);
 
        if (data_len)
@@ -672,7 +671,8 @@ static void td_submit_urb (
         * we could often reduce the number of TDs here.
         */
        case PIPE_ISOCHRONOUS:
-               for (cnt = 0; cnt < urb->number_of_packets; cnt++) {
+               for (cnt = urb_priv->td_cnt; cnt < urb->number_of_packets;
+                               cnt++) {
                        int     frame = urb->start_frame;
 
                        // FIXME scheduling should handle frame counter
index 0d2309ca471eeb9fff1be06da36081f4878bd42c..e84190f25c6b7b6995d32f53d7e1818f1f6608bc 100644 (file)
@@ -323,8 +323,6 @@ usb_hcd_s3c2410_remove(struct usb_hcd *hcd, struct platform_device *dev)
 {
        usb_remove_hcd(hcd);
        s3c2410_stop_hc(dev);
-       iounmap(hcd->regs);
-       release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
        usb_put_hcd(hcd);
 }
 
@@ -353,35 +351,29 @@ static int usb_hcd_s3c2410_probe(const struct hc_driver *driver,
        hcd->rsrc_start = dev->resource[0].start;
        hcd->rsrc_len   = resource_size(&dev->resource[0]);
 
-       if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
-               dev_err(&dev->dev, "request_mem_region failed\n");
-               retval = -EBUSY;
+       hcd->regs = devm_request_and_ioremap(&dev->dev, &dev->resource[0]);
+       if (!hcd->regs) {
+               dev_err(&dev->dev, "devm_request_and_ioremap failed\n");
+               retval = -ENOMEM;
                goto err_put;
        }
 
-       clk = clk_get(&dev->dev, "usb-host");
+       clk = devm_clk_get(&dev->dev, "usb-host");
        if (IS_ERR(clk)) {
                dev_err(&dev->dev, "cannot get usb-host clock\n");
                retval = PTR_ERR(clk);
-               goto err_mem;
+               goto err_put;
        }
 
-       usb_clk = clk_get(&dev->dev, "usb-bus-host");
+       usb_clk = devm_clk_get(&dev->dev, "usb-bus-host");
        if (IS_ERR(usb_clk)) {
                dev_err(&dev->dev, "cannot get usb-bus-host clock\n");
                retval = PTR_ERR(usb_clk);
-               goto err_clk;
+               goto err_put;
        }
 
        s3c2410_start_hc(dev, hcd);
 
-       hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
-       if (!hcd->regs) {
-               dev_err(&dev->dev, "ioremap failed\n");
-               retval = -ENOMEM;
-               goto err_ioremap;
-       }
-
        ohci_hcd_init(hcd_to_ohci(hcd));
 
        retval = usb_add_hcd(hcd, dev->resource[1].start, 0);
@@ -392,14 +384,6 @@ static int usb_hcd_s3c2410_probe(const struct hc_driver *driver,
 
  err_ioremap:
        s3c2410_stop_hc(dev);
-       iounmap(hcd->regs);
-       clk_put(usb_clk);
-
- err_clk:
-       clk_put(clk);
-
- err_mem:
-       release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
 
  err_put:
        usb_put_hcd(hcd);
@@ -524,8 +508,7 @@ static int ohci_hcd_s3c2410_drv_resume(struct device *dev)
 
        s3c2410_start_hc(pdev, hcd);
 
-       set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
-       ohci_finish_controller_resume(hcd);
+       ohci_resume(hcd, false);
 
        return 0;
 }
diff --git a/drivers/usb/host/ohci-sh.c b/drivers/usb/host/ohci-sh.c
deleted file mode 100644 (file)
index 76a20c2..0000000
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * OHCI HCD (Host Controller Driver) for USB.
- *
- * Copyright (C) 2008 Renesas Solutions Corp.
- *
- * Author : Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- *
- */
-
-#include <linux/platform_device.h>
-
-static int ohci_sh_start(struct usb_hcd *hcd)
-{
-       struct ohci_hcd *ohci = hcd_to_ohci(hcd);
-
-       ohci_hcd_init(ohci);
-       ohci_init(ohci);
-       ohci_run(ohci);
-       return 0;
-}
-
-static const struct hc_driver ohci_sh_hc_driver = {
-       .description =          hcd_name,
-       .product_desc =         "SuperH OHCI",
-       .hcd_priv_size =        sizeof(struct ohci_hcd),
-
-       /*
-        * generic hardware linkage
-        */
-       .irq =                  ohci_irq,
-       .flags =                HCD_USB11 | HCD_MEMORY,
-
-       /*
-        * basic lifecycle operations
-        */
-       .start =                ohci_sh_start,
-       .stop =                 ohci_stop,
-       .shutdown =             ohci_shutdown,
-
-       /*
-        * managing i/o requests and associated device resources
-        */
-       .urb_enqueue =          ohci_urb_enqueue,
-       .urb_dequeue =          ohci_urb_dequeue,
-       .endpoint_disable =     ohci_endpoint_disable,
-
-       /*
-        * scheduling support
-        */
-       .get_frame_number =     ohci_get_frame,
-
-       /*
-        * root hub support
-        */
-       .hub_status_data =      ohci_hub_status_data,
-       .hub_control =          ohci_hub_control,
-#ifdef CONFIG_PM
-       .bus_suspend =          ohci_bus_suspend,
-       .bus_resume =           ohci_bus_resume,
-#endif
-       .start_port_reset =     ohci_start_port_reset,
-};
-
-/*-------------------------------------------------------------------------*/
-
-static int ohci_hcd_sh_probe(struct platform_device *pdev)
-{
-       struct resource *res = NULL;
-       struct usb_hcd *hcd = NULL;
-       int irq = -1;
-       int ret;
-
-       if (usb_disabled())
-               return -ENODEV;
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               dev_err(&pdev->dev, "platform_get_resource error.\n");
-               return -ENODEV;
-       }
-
-       irq = platform_get_irq(pdev, 0);
-       if (irq < 0) {
-               dev_err(&pdev->dev, "platform_get_irq error.\n");
-               return -ENODEV;
-       }
-
-       /* initialize hcd */
-       hcd = usb_create_hcd(&ohci_sh_hc_driver, &pdev->dev, (char *)hcd_name);
-       if (!hcd) {
-               dev_err(&pdev->dev, "Failed to create hcd\n");
-               return -ENOMEM;
-       }
-
-       hcd->regs = (void __iomem *)res->start;
-       hcd->rsrc_start = res->start;
-       hcd->rsrc_len = resource_size(res);
-       ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
-       if (ret != 0) {
-               dev_err(&pdev->dev, "Failed to add hcd\n");
-               usb_put_hcd(hcd);
-               return ret;
-       }
-
-       return ret;
-}
-
-static int ohci_hcd_sh_remove(struct platform_device *pdev)
-{
-       struct usb_hcd *hcd = platform_get_drvdata(pdev);
-
-       usb_remove_hcd(hcd);
-       usb_put_hcd(hcd);
-
-       return 0;
-}
-
-static struct platform_driver ohci_hcd_sh_driver = {
-       .probe          = ohci_hcd_sh_probe,
-       .remove         = ohci_hcd_sh_remove,
-       .shutdown       = usb_hcd_platform_shutdown,
-       .driver         = {
-               .name   = "sh_ohci",
-               .owner  = THIS_MODULE,
-       },
-};
-
-MODULE_ALIAS("platform:sh_ohci");
index 5596ac2ba1ca55851c21b1f3044d0bfef0e17085..3b5b908fd47b29e25f0f90198c85607182152fef 100644 (file)
@@ -238,7 +238,7 @@ static int ohci_sm501_resume(struct platform_device *pdev)
        ohci->next_statechange = jiffies;
 
        sm501_unit_power(dev->parent, SM501_GATE_USB_HOST, 1);
-       ohci_finish_controller_resume(hcd);
+       ohci_resume(hcd, false);
        return 0;
 }
 #else
index fc7305ee3c9cd465ecdb68c64b140e9f9da10fc9..d607be33c03c865a6a6abcd5245deee02e8b3a03 100644 (file)
@@ -231,7 +231,7 @@ static int spear_ohci_hcd_drv_resume(struct platform_device *dev)
        ohci->next_statechange = jiffies;
 
        spear_start_ohci(ohci_p);
-       ohci_finish_controller_resume(hcd);
+       ohci_resume(hcd, false);
        return 0;
 }
 #endif
index 60c2b0722f2e16280f32db0ada071260e9ef30d4..2c9ab8f126d456df6ce02e7cccd771e651b4b3e6 100644 (file)
@@ -352,7 +352,7 @@ static int ohci_hcd_tmio_drv_resume(struct platform_device *dev)
 
        spin_unlock_irqrestore(&tmio->lock, flags);
 
-       ohci_finish_controller_resume(hcd);
+       ohci_resume(hcd, false);
 
        return 0;
 }
diff --git a/drivers/usb/host/ohci-xls.c b/drivers/usb/host/ohci-xls.c
deleted file mode 100644 (file)
index 84201cd..0000000
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * OHCI HCD for Netlogic XLS processors.
- *
- * (C) Copyright 2011 Netlogic Microsystems Inc.
- *
- *  Based on ohci-au1xxx.c, and other Linux OHCI drivers.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file COPYING in the main directory of this archive for
- * more details.
- */
-
-#include <linux/platform_device.h>
-#include <linux/signal.h>
-
-static int ohci_xls_probe_internal(const struct hc_driver *driver,
-                       struct platform_device *dev)
-{
-       struct resource *res;
-       struct usb_hcd *hcd;
-       int retval, irq;
-
-       /* Get our IRQ from an earlier registered Platform Resource */
-       irq = platform_get_irq(dev, 0);
-       if (irq < 0) {
-               dev_err(&dev->dev, "Found HC with no IRQ\n");
-               return -ENODEV;
-       }
-
-       /* Get our Memory Handle */
-       res = platform_get_resource(dev, IORESOURCE_MEM, 0);
-       if (!res) {
-               dev_err(&dev->dev, "MMIO Handle incorrect!\n");
-               return -ENODEV;
-       }
-
-       hcd = usb_create_hcd(driver, &dev->dev, "XLS");
-       if (!hcd) {
-               retval = -ENOMEM;
-               goto err1;
-       }
-       hcd->rsrc_start = res->start;
-       hcd->rsrc_len = resource_size(res);
-
-       if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len,
-                       driver->description)) {
-               dev_dbg(&dev->dev, "Controller already in use\n");
-               retval = -EBUSY;
-               goto err2;
-       }
-
-       hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len);
-       if (hcd->regs == NULL) {
-               dev_dbg(&dev->dev, "error mapping memory\n");
-               retval = -EFAULT;
-               goto err3;
-       }
-
-       retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
-       if (retval != 0)
-               goto err4;
-       return retval;
-
-err4:
-       iounmap(hcd->regs);
-err3:
-       release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
-err2:
-       usb_put_hcd(hcd);
-err1:
-       dev_err(&dev->dev, "init fail, %d\n", retval);
-       return retval;
-}
-
-static int ohci_xls_reset(struct usb_hcd *hcd)
-{
-       struct ohci_hcd *ohci = hcd_to_ohci(hcd);
-
-       ohci_hcd_init(ohci);
-       return ohci_init(ohci);
-}
-
-static int __devinit ohci_xls_start(struct usb_hcd *hcd)
-{
-       struct ohci_hcd *ohci;
-       int ret;
-
-       ohci = hcd_to_ohci(hcd);
-       ret = ohci_run(ohci);
-       if (ret < 0) {
-               dev_err(hcd->self.controller, "can't start %s\n",
-                       hcd->self.bus_name);
-               ohci_stop(hcd);
-               return ret;
-       }
-       return 0;
-}
-
-static struct hc_driver ohci_xls_hc_driver = {
-       .description    = hcd_name,
-       .product_desc   = "XLS OHCI Host Controller",
-       .hcd_priv_size  = sizeof(struct ohci_hcd),
-       .irq            = ohci_irq,
-       .flags          = HCD_MEMORY | HCD_USB11,
-       .reset          = ohci_xls_reset,
-       .start          = ohci_xls_start,
-       .stop           = ohci_stop,
-       .shutdown       = ohci_shutdown,
-       .urb_enqueue    = ohci_urb_enqueue,
-       .urb_dequeue    = ohci_urb_dequeue,
-       .endpoint_disable = ohci_endpoint_disable,
-       .get_frame_number = ohci_get_frame,
-       .hub_status_data = ohci_hub_status_data,
-       .hub_control    = ohci_hub_control,
-#ifdef CONFIG_PM
-       .bus_suspend    = ohci_bus_suspend,
-       .bus_resume     = ohci_bus_resume,
-#endif
-       .start_port_reset = ohci_start_port_reset,
-};
-
-static int ohci_xls_probe(struct platform_device *dev)
-{
-       int ret;
-
-       pr_debug("In ohci_xls_probe");
-       if (usb_disabled())
-               return -ENODEV;
-       ret = ohci_xls_probe_internal(&ohci_xls_hc_driver, dev);
-       return ret;
-}
-
-static int ohci_xls_remove(struct platform_device *dev)
-{
-       struct usb_hcd *hcd = platform_get_drvdata(dev);
-
-       usb_remove_hcd(hcd);
-       iounmap(hcd->regs);
-       release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
-       usb_put_hcd(hcd);
-       return 0;
-}
-
-static struct platform_driver ohci_xls_driver = {
-       .probe          = ohci_xls_probe,
-       .remove         = ohci_xls_remove,
-       .shutdown       = usb_hcd_platform_shutdown,
-       .driver         = {
-               .name   = "ohci-xls-0",
-               .owner  = THIS_MODULE,
-       },
-};
index fcc09e5ec0addc9cd9661086b1e18165bd5f8ba4..b3eea0ba97a936b9743245971d0a94a1e6b2e45e 100644 (file)
@@ -2036,10 +2036,8 @@ static void collect_usb_address_map(struct usb_device *udev, unsigned long *map)
            udev->parent->descriptor.bDeviceClass == USB_CLASS_HUB)
                map[udev->devnum/32] |= (1 << (udev->devnum % 32));
 
-       usb_hub_for_each_child(udev, chix, childdev) {
-               if (childdev)
-                       collect_usb_address_map(childdev, map);
-       }
+       usb_hub_for_each_child(udev, chix, childdev)
+               collect_usb_address_map(childdev, map);
 }
 
 /* this function must be called with interrupt disabled */
index d2c6f5ac4626af6c0297ab1348b9a14b18f77605..15921fd55048614de4940dabbdfb95564a129392 100644 (file)
@@ -1256,7 +1256,8 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb,
                struct uhci_qh *qh)
 {
        struct uhci_td *td = NULL;      /* Since urb->number_of_packets > 0 */
-       int i, frame;
+       int i;
+       unsigned frame, next;
        unsigned long destination, status;
        struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv;
 
@@ -1265,37 +1266,29 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb,
                        urb->number_of_packets >= UHCI_NUMFRAMES)
                return -EFBIG;
 
+       uhci_get_current_frame_number(uhci);
+
        /* Check the period and figure out the starting frame number */
        if (!qh->bandwidth_reserved) {
                qh->period = urb->interval;
-               if (urb->transfer_flags & URB_ISO_ASAP) {
-                       qh->phase = -1;         /* Find the best phase */
-                       i = uhci_check_bandwidth(uhci, qh);
-                       if (i)
-                               return i;
-
-                       /* Allow a little time to allocate the TDs */
-                       uhci_get_current_frame_number(uhci);
-                       frame = uhci->frame_number + 10;
-
-                       /* Move forward to the first frame having the
-                        * correct phase */
-                       urb->start_frame = frame + ((qh->phase - frame) &
-                                       (qh->period - 1));
-               } else {
-                       i = urb->start_frame - uhci->last_iso_frame;
-                       if (i <= 0 || i >= UHCI_NUMFRAMES)
-                               return -EINVAL;
-                       qh->phase = urb->start_frame & (qh->period - 1);
-                       i = uhci_check_bandwidth(uhci, qh);
-                       if (i)
-                               return i;
-               }
+               qh->phase = -1;         /* Find the best phase */
+               i = uhci_check_bandwidth(uhci, qh);
+               if (i)
+                       return i;
+
+               /* Allow a little time to allocate the TDs */
+               next = uhci->frame_number + 10;
+               frame = qh->phase;
+
+               /* Round up to the first available slot */
+               frame += (next - frame + qh->period - 1) & -qh->period;
 
        } else if (qh->period != urb->interval) {
                return -EINVAL;         /* Can't change the period */
 
        } else {
+               next = uhci->frame_number + 2;
+
                /* Find the next unused frame */
                if (list_empty(&qh->queue)) {
                        frame = qh->iso_frame;
@@ -1308,25 +1301,31 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb,
                                        lurb->number_of_packets *
                                        lurb->interval;
                }
-               if (urb->transfer_flags & URB_ISO_ASAP) {
-                       /* Skip some frames if necessary to insure
-                        * the start frame is in the future.
+
+               /* Fell behind? */
+               if (uhci_frame_before_eq(frame, next)) {
+
+                       /* USB_ISO_ASAP: Round up to the first available slot */
+                       if (urb->transfer_flags & URB_ISO_ASAP)
+                               frame += (next - frame + qh->period - 1) &
+                                               -qh->period;
+
+                       /*
+                        * Not ASAP: Use the next slot in the stream.  If
+                        * the entire URB falls before the threshold, fail.
                         */
-                       uhci_get_current_frame_number(uhci);
-                       if (uhci_frame_before_eq(frame, uhci->frame_number)) {
-                               frame = uhci->frame_number + 1;
-                               frame += ((qh->phase - frame) &
-                                       (qh->period - 1));
-                       }
-               }       /* Otherwise pick up where the last URB leaves off */
-               urb->start_frame = frame;
+                       else if (!uhci_frame_before_eq(next,
+                                       frame + (urb->number_of_packets - 1) *
+                                               qh->period))
+                               return -EXDEV;
+               }
        }
 
        /* Make sure we won't have to go too far into the future */
        if (uhci_frame_before_eq(uhci->last_iso_frame + UHCI_NUMFRAMES,
-                       urb->start_frame + urb->number_of_packets *
-                               urb->interval))
+                       frame + urb->number_of_packets * urb->interval))
                return -EFBIG;
+       urb->start_frame = frame;
 
        status = TD_CTRL_ACTIVE | TD_CTRL_IOS;
        destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid(urb->pipe);
index 487bc083dead0ac0385c81abf81f52917872ac38..fb51c7085ad0d19c7159afd9a069c82846afd405 100644 (file)
@@ -205,7 +205,12 @@ static int xhci_alloc_segments_for_ring(struct xhci_hcd *xhci,
 
                next = xhci_segment_alloc(xhci, cycle_state, flags);
                if (!next) {
-                       xhci_free_segments_for_ring(xhci, *first);
+                       prev = *first;
+                       while (prev) {
+                               next = prev->next;
+                               xhci_segment_free(xhci, prev);
+                               prev = next;
+                       }
                        return -ENOMEM;
                }
                xhci_link_segments(xhci, prev, next, type);
@@ -258,7 +263,7 @@ static struct xhci_ring *xhci_ring_alloc(struct xhci_hcd *xhci,
        return ring;
 
 fail:
-       xhci_ring_free(xhci, ring);
+       kfree(ring);
        return NULL;
 }
 
index 8345d7c23061c2346b0f1e8d4f826c4c3ed2b7c6..af259e0ec172aa4a5664ca15acb2adf8d90bf02c 100644 (file)
@@ -29,6 +29,7 @@
 /* Device for a quirk */
 #define PCI_VENDOR_ID_FRESCO_LOGIC     0x1b73
 #define PCI_DEVICE_ID_FRESCO_LOGIC_PDK 0x1000
+#define PCI_DEVICE_ID_FRESCO_LOGIC_FL1400      0x1400
 
 #define PCI_VENDOR_ID_ETRON            0x1b6f
 #define PCI_DEVICE_ID_ASROCK_P67       0x7023
@@ -58,8 +59,10 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
 
        /* Look for vendor-specific quirks */
        if (pdev->vendor == PCI_VENDOR_ID_FRESCO_LOGIC &&
-                       pdev->device == PCI_DEVICE_ID_FRESCO_LOGIC_PDK) {
-               if (pdev->revision == 0x0) {
+                       (pdev->device == PCI_DEVICE_ID_FRESCO_LOGIC_PDK ||
+                        pdev->device == PCI_DEVICE_ID_FRESCO_LOGIC_FL1400)) {
+               if (pdev->device == PCI_DEVICE_ID_FRESCO_LOGIC_PDK &&
+                               pdev->revision == 0x0) {
                        xhci->quirks |= XHCI_RESET_EP_QUIRK;
                        xhci_dbg(xhci, "QUIRK: Fresco Logic xHC needs configure"
                                        " endpoint cmd after reset endpoint\n");
@@ -218,15 +221,8 @@ static void xhci_pci_remove(struct pci_dev *dev)
 static int xhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup)
 {
        struct xhci_hcd *xhci = hcd_to_xhci(hcd);
-       int     retval = 0;
 
-       if (hcd->state != HC_STATE_SUSPENDED ||
-                       xhci->shared_hcd->state != HC_STATE_SUSPENDED)
-               return -EINVAL;
-
-       retval = xhci_suspend(xhci);
-
-       return retval;
+       return xhci_suspend(xhci);
 }
 
 static int xhci_pci_resume(struct usb_hcd *hcd, bool hibernated)
index 4e1a8946b8d167c1f36be62b3bc63265f7271815..cbb44b7b9d6553e01f9c2f45da23c8fad1b7fe92 100644 (file)
@@ -318,7 +318,7 @@ static int xhci_abort_cmd_ring(struct xhci_hcd *xhci)
         * seconds), then it should assume that the there are
         * larger problems with the xHC and assert HCRST.
         */
-       ret = handshake(xhci, &xhci->op_regs->cmd_ring,
+       ret = xhci_handshake(xhci, &xhci->op_regs->cmd_ring,
                        CMD_RING_RUNNING, 0, 5 * 1000 * 1000);
        if (ret < 0) {
                xhci_err(xhci, "Stopped the command ring failed, "
@@ -3071,11 +3071,11 @@ static u32 xhci_td_remainder(unsigned int remainder)
 }
 
 /*
- * For xHCI 1.0 host controllers, TD size is the number of packets remaining in
- * the TD (*not* including this TRB).
+ * For xHCI 1.0 host controllers, TD size is the number of max packet sized
+ * packets remaining in the TD (*not* including this TRB).
  *
  * Total TD packet count = total_packet_count =
- *     roundup(TD size in bytes / wMaxPacketSize)
+ *     DIV_ROUND_UP(TD size in bytes / wMaxPacketSize)
  *
  * Packets transferred up to and including this TRB = packets_transferred =
  *     rounddown(total bytes transferred including this TRB / wMaxPacketSize)
@@ -3083,15 +3083,16 @@ static u32 xhci_td_remainder(unsigned int remainder)
  * TD size = total_packet_count - packets_transferred
  *
  * It must fit in bits 21:17, so it can't be bigger than 31.
+ * The last TRB in a TD must have the TD size set to zero.
  */
-
 static u32 xhci_v1_0_td_remainder(int running_total, int trb_buff_len,
-               unsigned int total_packet_count, struct urb *urb)
+               unsigned int total_packet_count, struct urb *urb,
+               unsigned int num_trbs_left)
 {
        int packets_transferred;
 
        /* One TRB with a zero-length data packet. */
-       if (running_total == 0 && trb_buff_len == 0)
+       if (num_trbs_left == 0 || (running_total == 0 && trb_buff_len == 0))
                return 0;
 
        /* All the TRB queueing functions don't count the current TRB in
@@ -3100,7 +3101,9 @@ static u32 xhci_v1_0_td_remainder(int running_total, int trb_buff_len,
        packets_transferred = (running_total + trb_buff_len) /
                usb_endpoint_maxp(&urb->ep->desc);
 
-       return xhci_td_remainder(total_packet_count - packets_transferred);
+       if ((total_packet_count - packets_transferred) > 31)
+               return 31 << 17;
+       return (total_packet_count - packets_transferred) << 17;
 }
 
 static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
@@ -3127,7 +3130,7 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
 
        num_trbs = count_sg_trbs_needed(xhci, urb);
        num_sgs = urb->num_mapped_sgs;
-       total_packet_count = roundup(urb->transfer_buffer_length,
+       total_packet_count = DIV_ROUND_UP(urb->transfer_buffer_length,
                        usb_endpoint_maxp(&urb->ep->desc));
 
        trb_buff_len = prepare_transfer(xhci, xhci->devs[slot_id],
@@ -3210,7 +3213,8 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
                                        running_total);
                } else {
                        remainder = xhci_v1_0_td_remainder(running_total,
-                                       trb_buff_len, total_packet_count, urb);
+                                       trb_buff_len, total_packet_count, urb,
+                                       num_trbs - 1);
                }
                length_field = TRB_LEN(trb_buff_len) |
                        remainder |
@@ -3318,7 +3322,7 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
        start_cycle = ep_ring->cycle_state;
 
        running_total = 0;
-       total_packet_count = roundup(urb->transfer_buffer_length,
+       total_packet_count = DIV_ROUND_UP(urb->transfer_buffer_length,
                        usb_endpoint_maxp(&urb->ep->desc));
        /* How much data is in the first TRB? */
        addr = (u64) urb->transfer_dma;
@@ -3364,7 +3368,8 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
                                        running_total);
                } else {
                        remainder = xhci_v1_0_td_remainder(running_total,
-                                       trb_buff_len, total_packet_count, urb);
+                                       trb_buff_len, total_packet_count, urb,
+                                       num_trbs - 1);
                }
                length_field = TRB_LEN(trb_buff_len) |
                        remainder |
@@ -3627,7 +3632,7 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
                addr = start_addr + urb->iso_frame_desc[i].offset;
                td_len = urb->iso_frame_desc[i].length;
                td_remain_len = td_len;
-               total_packet_count = roundup(td_len,
+               total_packet_count = DIV_ROUND_UP(td_len,
                                usb_endpoint_maxp(&urb->ep->desc));
                /* A zero-length transfer still involves at least one packet. */
                if (total_packet_count == 0)
@@ -3706,7 +3711,8 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
                        } else {
                                remainder = xhci_v1_0_td_remainder(
                                                running_total, trb_buff_len,
-                                               total_packet_count, urb);
+                                               total_packet_count, urb,
+                                               (trbs_per_td - j - 1));
                        }
                        length_field = TRB_LEN(trb_buff_len) |
                                remainder |
index c9e419f29b7454225516cb8629ddff80af5187d9..5c72c431bab18da941ec9a1a235c134086065482 100644 (file)
@@ -40,7 +40,7 @@ MODULE_PARM_DESC(link_quirk, "Don't clear the chain bit on a link TRB");
 
 /* TODO: copied from ehci-hcd.c - can this be refactored? */
 /*
- * handshake - spin reading hc until handshake completes or fails
+ * xhci_handshake - spin reading hc until handshake completes or fails
  * @ptr: address of hc register to be read
  * @mask: bits to look at in result of read
  * @done: value of those bits when handshake succeeds
@@ -52,7 +52,7 @@ MODULE_PARM_DESC(link_quirk, "Don't clear the chain bit on a link TRB");
  * handshake done).  There are two failure modes:  "usec" have passed (major
  * hardware flakeout), or the register reads as all-ones (hardware removed).
  */
-int handshake(struct xhci_hcd *xhci, void __iomem *ptr,
+int xhci_handshake(struct xhci_hcd *xhci, void __iomem *ptr,
                      u32 mask, u32 done, int usec)
 {
        u32     result;
@@ -103,7 +103,7 @@ int xhci_halt(struct xhci_hcd *xhci)
        xhci_dbg(xhci, "// Halt the HC\n");
        xhci_quiesce(xhci);
 
-       ret = handshake(xhci, &xhci->op_regs->status,
+       ret = xhci_handshake(xhci, &xhci->op_regs->status,
                        STS_HALT, STS_HALT, XHCI_MAX_HALT_USEC);
        if (!ret) {
                xhci->xhc_state |= XHCI_STATE_HALTED;
@@ -132,7 +132,7 @@ static int xhci_start(struct xhci_hcd *xhci)
         * Wait for the HCHalted Status bit to be 0 to indicate the host is
         * running.
         */
-       ret = handshake(xhci, &xhci->op_regs->status,
+       ret = xhci_handshake(xhci, &xhci->op_regs->status,
                        STS_HALT, 0, XHCI_MAX_HALT_USEC);
        if (ret == -ETIMEDOUT)
                xhci_err(xhci, "Host took too long to start, "
@@ -167,7 +167,7 @@ int xhci_reset(struct xhci_hcd *xhci)
        command |= CMD_RESET;
        xhci_writel(xhci, command, &xhci->op_regs->command);
 
-       ret = handshake(xhci, &xhci->op_regs->command,
+       ret = xhci_handshake(xhci, &xhci->op_regs->command,
                        CMD_RESET, 0, 10 * 1000 * 1000);
        if (ret)
                return ret;
@@ -177,7 +177,7 @@ int xhci_reset(struct xhci_hcd *xhci)
         * xHCI cannot write to any doorbells or operational registers other
         * than status until the "Controller Not Ready" flag is cleared.
         */
-       ret = handshake(xhci, &xhci->op_regs->status,
+       ret = xhci_handshake(xhci, &xhci->op_regs->status,
                        STS_CNR, 0, 10 * 1000 * 1000);
 
        for (i = 0; i < 2; ++i) {
@@ -480,7 +480,7 @@ static bool compliance_mode_recovery_timer_quirk_check(void)
        if (strstr(dmi_product_name, "Z420") ||
                        strstr(dmi_product_name, "Z620") ||
                        strstr(dmi_product_name, "Z820") ||
-                       strstr(dmi_product_name, "Z1"))
+                       strstr(dmi_product_name, "Z1 Workstation"))
                return true;
 
        return false;
@@ -880,6 +880,10 @@ int xhci_suspend(struct xhci_hcd *xhci)
        struct usb_hcd          *hcd = xhci_to_hcd(xhci);
        u32                     command;
 
+       if (hcd->state != HC_STATE_SUSPENDED ||
+                       xhci->shared_hcd->state != HC_STATE_SUSPENDED)
+               return -EINVAL;
+
        spin_lock_irq(&xhci->lock);
        clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
        clear_bit(HCD_FLAG_HW_ACCESSIBLE, &xhci->shared_hcd->flags);
@@ -890,7 +894,7 @@ int xhci_suspend(struct xhci_hcd *xhci)
        command = xhci_readl(xhci, &xhci->op_regs->command);
        command &= ~CMD_RUN;
        xhci_writel(xhci, command, &xhci->op_regs->command);
-       if (handshake(xhci, &xhci->op_regs->status,
+       if (xhci_handshake(xhci, &xhci->op_regs->status,
                      STS_HALT, STS_HALT, XHCI_MAX_HALT_USEC)) {
                xhci_warn(xhci, "WARN: xHC CMD_RUN timeout\n");
                spin_unlock_irq(&xhci->lock);
@@ -905,7 +909,8 @@ int xhci_suspend(struct xhci_hcd *xhci)
        command = xhci_readl(xhci, &xhci->op_regs->command);
        command |= CMD_CSS;
        xhci_writel(xhci, command, &xhci->op_regs->command);
-       if (handshake(xhci, &xhci->op_regs->status, STS_SAVE, 0, 10 * 1000)) {
+       if (xhci_handshake(xhci, &xhci->op_regs->status,
+                               STS_SAVE, 0, 10 * 1000)) {
                xhci_warn(xhci, "WARN: xHC save state timeout\n");
                spin_unlock_irq(&xhci->lock);
                return -ETIMEDOUT;
@@ -967,7 +972,7 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
                command = xhci_readl(xhci, &xhci->op_regs->command);
                command |= CMD_CRS;
                xhci_writel(xhci, command, &xhci->op_regs->command);
-               if (handshake(xhci, &xhci->op_regs->status,
+               if (xhci_handshake(xhci, &xhci->op_regs->status,
                              STS_RESTORE, 0, 10 * 1000)) {
                        xhci_warn(xhci, "WARN: xHC restore state timeout\n");
                        spin_unlock_irq(&xhci->lock);
@@ -1035,7 +1040,7 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
        command = xhci_readl(xhci, &xhci->op_regs->command);
        command |= CMD_RUN;
        xhci_writel(xhci, command, &xhci->op_regs->command);
-       handshake(xhci, &xhci->op_regs->status, STS_HALT,
+       xhci_handshake(xhci, &xhci->op_regs->status, STS_HALT,
                  0, 250 * 1000);
 
        /* step 5: walk topology and initialize portsc,
@@ -2254,7 +2259,7 @@ static bool xhci_is_async_ep(unsigned int ep_type)
 
 static bool xhci_is_sync_in_ep(unsigned int ep_type)
 {
-       return (ep_type == ISOC_IN_EP || ep_type != INT_IN_EP);
+       return (ep_type == ISOC_IN_EP || ep_type == INT_IN_EP);
 }
 
 static unsigned int xhci_get_ss_bw_consumed(struct xhci_bw_info *ep_bw)
@@ -3874,7 +3879,8 @@ static int xhci_usb2_software_lpm_test(struct usb_hcd *hcd,
        spin_lock_irqsave(&xhci->lock, flags);
 
        /* Check L1 Status */
-       ret = handshake(xhci, pm_addr, PORT_L1S_MASK, PORT_L1S_SUCCESS, 125);
+       ret = xhci_handshake(xhci, pm_addr,
+                       PORT_L1S_MASK, PORT_L1S_SUCCESS, 125);
        if (ret != -ETIMEDOUT) {
                /* enter L1 successfully */
                temp = xhci_readl(xhci, addr);
index 53df4e70ca074ccc37593f99d09cc6f23d991b25..f791bd0aee6cda4ad2bf5407ba5ad71b912cc5f5 100644 (file)
@@ -1720,7 +1720,7 @@ static inline void xhci_unregister_plat(void)
 
 /* xHCI host controller glue */
 typedef void (*xhci_get_quirks_t)(struct device *, struct xhci_hcd *);
-int handshake(struct xhci_hcd *xhci, void __iomem *ptr,
+int xhci_handshake(struct xhci_hcd *xhci, void __iomem *ptr,
                u32 mask, u32 done, int usec);
 void xhci_quiesce(struct xhci_hcd *xhci);
 int xhci_halt(struct xhci_hcd *xhci);
index 6589268a651517da44f99cd7391e2ca35f84f12a..e712afed947c0743dffa1a099ca91832288eeb89 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/usb.h>
 #include <linux/firmware.h>
 #include <linux/ihex.h>
+#include <linux/usb/ezusb.h>
 
 struct ezusb_fx_type {
        /* EZ-USB Control and Status Register.  Bit 0 controls 8051 reset */
@@ -22,21 +23,16 @@ struct ezusb_fx_type {
        unsigned short max_internal_adress;
 };
 
-struct ezusb_fx_type ezusb_fx1 = {
+static struct ezusb_fx_type ezusb_fx1 = {
        .cpucs_reg = 0x7F92,
        .max_internal_adress = 0x1B3F,
 };
 
-struct ezusb_fx_type ezusb_fx2 = {
-       .cpucs_reg = 0xE600,
-       .max_internal_adress = 0x3FFF,
-};
-
 /* Commands for writing to memory */
 #define WRITE_INT_RAM 0xA0
 #define WRITE_EXT_RAM 0xA3
 
-int ezusb_writememory(struct usb_device *dev, int address,
+static int ezusb_writememory(struct usb_device *dev, int address,
                                unsigned char *data, int length, __u8 request)
 {
        int result;
@@ -58,10 +54,9 @@ int ezusb_writememory(struct usb_device *dev, int address,
        kfree(transfer_buffer);
        return result;
 }
-EXPORT_SYMBOL_GPL(ezusb_writememory);
 
-int ezusb_set_reset(struct usb_device *dev, unsigned short cpucs_reg,
-                        unsigned char reset_bit)
+static int ezusb_set_reset(struct usb_device *dev, unsigned short cpucs_reg,
+                          unsigned char reset_bit)
 {
        int response = ezusb_writememory(dev, cpucs_reg, &reset_bit, 1, WRITE_INT_RAM);
        if (response < 0)
@@ -76,12 +71,6 @@ int ezusb_fx1_set_reset(struct usb_device *dev, unsigned char reset_bit)
 }
 EXPORT_SYMBOL_GPL(ezusb_fx1_set_reset);
 
-int ezusb_fx2_set_reset(struct usb_device *dev, unsigned char reset_bit)
-{
-       return ezusb_set_reset(dev, ezusb_fx2.cpucs_reg, reset_bit);
-}
-EXPORT_SYMBOL_GPL(ezusb_fx2_set_reset);
-
 static int ezusb_ihex_firmware_download(struct usb_device *dev,
                                        struct ezusb_fx_type fx,
                                        const char *firmware_path)
@@ -151,11 +140,28 @@ int ezusb_fx1_ihex_firmware_download(struct usb_device *dev,
 }
 EXPORT_SYMBOL_GPL(ezusb_fx1_ihex_firmware_download);
 
+#if 0
+/*
+ * Once someone one needs these fx2 functions, uncomment them
+ * and add them to ezusb.h and all should be good.
+ */
+static struct ezusb_fx_type ezusb_fx2 = {
+       .cpucs_reg = 0xE600,
+       .max_internal_adress = 0x3FFF,
+};
+
+int ezusb_fx2_set_reset(struct usb_device *dev, unsigned char reset_bit)
+{
+       return ezusb_set_reset(dev, ezusb_fx2.cpucs_reg, reset_bit);
+}
+EXPORT_SYMBOL_GPL(ezusb_fx2_set_reset);
+
 int ezusb_fx2_ihex_firmware_download(struct usb_device *dev,
                                     const char *firmware_path)
 {
        return ezusb_ihex_firmware_download(dev, ezusb_fx2, firmware_path);
 }
 EXPORT_SYMBOL_GPL(ezusb_fx2_ihex_firmware_download);
+#endif
 
 MODULE_LICENSE("GPL");
index c964d6af178bd0196e20a80bd482529c38369900..3baccf7654188c80bda9853bab8c5959cfe5e06f 100644 (file)
@@ -465,7 +465,6 @@ static int __devinit am35x_probe(struct platform_device *pdev)
        struct clk                      *clk;
 
        int                             ret = -ENOMEM;
-       int                             musbid;
 
        glue = kzalloc(sizeof(*glue), GFP_KERNEL);
        if (!glue) {
@@ -473,18 +472,10 @@ static int __devinit am35x_probe(struct platform_device *pdev)
                goto err0;
        }
 
-       /* get the musb id */
-       musbid = musb_get_id(&pdev->dev, GFP_KERNEL);
-       if (musbid < 0) {
-               dev_err(&pdev->dev, "failed to allocate musb id\n");
-               ret = -ENOMEM;
-               goto err1;
-       }
-
-       musb = platform_device_alloc("musb-hdrc", musbid);
+       musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO);
        if (!musb) {
                dev_err(&pdev->dev, "failed to allocate musb device\n");
-               goto err2;
+               goto err1;
        }
 
        phy_clk = clk_get(&pdev->dev, "fck");
@@ -513,7 +504,6 @@ static int __devinit am35x_probe(struct platform_device *pdev)
                goto err6;
        }
 
-       musb->id                        = musbid;
        musb->dev.parent                = &pdev->dev;
        musb->dev.dma_mask              = &am35x_dmamask;
        musb->dev.coherent_dma_mask     = am35x_dmamask;
@@ -563,9 +553,6 @@ err4:
 err3:
        platform_device_put(musb);
 
-err2:
-       musb_put_id(&pdev->dev, musbid);
-
 err1:
        kfree(glue);
 
@@ -577,9 +564,7 @@ static int __devexit am35x_remove(struct platform_device *pdev)
 {
        struct am35x_glue       *glue = platform_get_drvdata(pdev);
 
-       musb_put_id(&pdev->dev, glue->musb->id);
-       platform_device_del(glue->musb);
-       platform_device_put(glue->musb);
+       platform_device_unregister(glue->musb);
        clk_disable(glue->clk);
        clk_disable(glue->phy_clk);
        clk_put(glue->clk);
@@ -654,15 +639,4 @@ static struct platform_driver am35x_driver = {
 MODULE_DESCRIPTION("AM35x MUSB Glue Layer");
 MODULE_AUTHOR("Ajay Kumar Gupta <ajay.gupta@ti.com>");
 MODULE_LICENSE("GPL v2");
-
-static int __init am35x_init(void)
-{
-       return platform_driver_register(&am35x_driver);
-}
-module_init(am35x_init);
-
-static void __exit am35x_exit(void)
-{
-       platform_driver_unregister(&am35x_driver);
-}
-module_exit(am35x_exit);
+module_platform_driver(am35x_driver);
index e8cff9bb9d230a57c811573d58d101f1351ace27..7e4d60a41728090e35f7eba33b7cdd62887fd2b8 100644 (file)
@@ -455,7 +455,6 @@ static int __devinit bfin_probe(struct platform_device *pdev)
        struct bfin_glue                *glue;
 
        int                             ret = -ENOMEM;
-       int                             musbid;
 
        glue = kzalloc(sizeof(*glue), GFP_KERNEL);
        if (!glue) {
@@ -463,21 +462,12 @@ static int __devinit bfin_probe(struct platform_device *pdev)
                goto err0;
        }
 
-       /* get the musb id */
-       musbid = musb_get_id(&pdev->dev, GFP_KERNEL);
-       if (musbid < 0) {
-               dev_err(&pdev->dev, "failed to allocate musb id\n");
-               ret = -ENOMEM;
-               goto err1;
-       }
-
-       musb = platform_device_alloc("musb-hdrc", musbid);
+       musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO);
        if (!musb) {
                dev_err(&pdev->dev, "failed to allocate musb device\n");
-               goto err2;
+               goto err1;
        }
 
-       musb->id                        = musbid;
        musb->dev.parent                = &pdev->dev;
        musb->dev.dma_mask              = &bfin_dmamask;
        musb->dev.coherent_dma_mask     = bfin_dmamask;
@@ -513,9 +503,6 @@ static int __devinit bfin_probe(struct platform_device *pdev)
 err3:
        platform_device_put(musb);
 
-err2:
-       musb_put_id(&pdev->dev, musbid);
-
 err1:
        kfree(glue);
 
@@ -527,9 +514,7 @@ static int __devexit bfin_remove(struct platform_device *pdev)
 {
        struct bfin_glue                *glue = platform_get_drvdata(pdev);
 
-       musb_put_id(&pdev->dev, glue->musb->id);
-       platform_device_del(glue->musb);
-       platform_device_put(glue->musb);
+       platform_device_unregister(glue->musb);
        kfree(glue);
 
        return 0;
@@ -585,15 +570,4 @@ static struct platform_driver bfin_driver = {
 MODULE_DESCRIPTION("Blackfin MUSB Glue Layer");
 MODULE_AUTHOR("Bryan Wy <cooloney@kernel.org>");
 MODULE_LICENSE("GPL v2");
-
-static int __init bfin_init(void)
-{
-       return platform_driver_register(&bfin_driver);
-}
-module_init(bfin_init);
-
-static void __exit bfin_exit(void)
-{
-       platform_driver_unregister(&bfin_driver);
-}
-module_exit(bfin_exit);
+module_platform_driver(bfin_driver);
index e19da82b478248bd81633875115ffaa9d1d0d50f..3a6c2fd1f913d1a3dbc75953c1103ebbdeff9b62 100644 (file)
@@ -1314,6 +1314,7 @@ irqreturn_t cppi_interrupt(int irq, void *dev_id)
 
        return IRQ_HANDLED;
 }
+EXPORT_SYMBOL_GPL(cppi_interrupt);
 
 /* Instantiate a software object representing a DMA controller. */
 struct dma_controller *__devinit
index 8bc44b76eec2b3cd78e2d78c24e79568880d5b07..67b8ae704e9a93ac45536ba4820515e44725ed5d 100644 (file)
@@ -480,7 +480,6 @@ static int __devinit da8xx_probe(struct platform_device *pdev)
        struct clk                      *clk;
 
        int                             ret = -ENOMEM;
-       int                             musbid;
 
        glue = kzalloc(sizeof(*glue), GFP_KERNEL);
        if (!glue) {
@@ -488,18 +487,10 @@ static int __devinit da8xx_probe(struct platform_device *pdev)
                goto err0;
        }
 
-       /* get the musb id */
-       musbid = musb_get_id(&pdev->dev, GFP_KERNEL);
-       if (musbid < 0) {
-               dev_err(&pdev->dev, "failed to allocate musb id\n");
-               ret = -ENOMEM;
-               goto err1;
-       }
-
-       musb = platform_device_alloc("musb-hdrc", musbid);
+       musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO);
        if (!musb) {
                dev_err(&pdev->dev, "failed to allocate musb device\n");
-               goto err2;
+               goto err1;
        }
 
        clk = clk_get(&pdev->dev, "usb20");
@@ -515,7 +506,6 @@ static int __devinit da8xx_probe(struct platform_device *pdev)
                goto err4;
        }
 
-       musb->id                        = musbid;
        musb->dev.parent                = &pdev->dev;
        musb->dev.dma_mask              = &da8xx_dmamask;
        musb->dev.coherent_dma_mask     = da8xx_dmamask;
@@ -558,9 +548,6 @@ err4:
 err3:
        platform_device_put(musb);
 
-err2:
-       musb_put_id(&pdev->dev, musbid);
-
 err1:
        kfree(glue);
 
@@ -572,9 +559,7 @@ static int __devexit da8xx_remove(struct platform_device *pdev)
 {
        struct da8xx_glue               *glue = platform_get_drvdata(pdev);
 
-       musb_put_id(&pdev->dev, glue->musb->id);
-       platform_device_del(glue->musb);
-       platform_device_put(glue->musb);
+       platform_device_unregister(glue->musb);
        clk_disable(glue->clk);
        clk_put(glue->clk);
        kfree(glue);
@@ -593,15 +578,4 @@ static struct platform_driver da8xx_driver = {
 MODULE_DESCRIPTION("DA8xx/OMAP-L1x MUSB Glue Layer");
 MODULE_AUTHOR("Sergei Shtylyov <sshtylyov@ru.mvista.com>");
 MODULE_LICENSE("GPL v2");
-
-static int __init da8xx_init(void)
-{
-       return platform_driver_register(&da8xx_driver);
-}
-module_init(da8xx_init);
-
-static void __exit da8xx_exit(void)
-{
-       platform_driver_unregister(&da8xx_driver);
-}
-module_exit(da8xx_exit);
+module_platform_driver(da8xx_driver);
index 606bfd00cde6abe726ccf64b6b1f10a68e9ed1de..b3c0a943950c63c10f50979d8d4b1f4ac7afca75 100644 (file)
@@ -512,7 +512,6 @@ static int __devinit davinci_probe(struct platform_device *pdev)
        struct clk                      *clk;
 
        int                             ret = -ENOMEM;
-       int                             musbid;
 
        glue = kzalloc(sizeof(*glue), GFP_KERNEL);
        if (!glue) {
@@ -520,18 +519,10 @@ static int __devinit davinci_probe(struct platform_device *pdev)
                goto err0;
        }
 
-       /* get the musb id */
-       musbid = musb_get_id(&pdev->dev, GFP_KERNEL);
-       if (musbid < 0) {
-               dev_err(&pdev->dev, "failed to allocate musb id\n");
-               ret = -ENOMEM;
-               goto err1;
-       }
-
-       musb = platform_device_alloc("musb-hdrc", musbid);
+       musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO);
        if (!musb) {
                dev_err(&pdev->dev, "failed to allocate musb device\n");
-               goto err2;
+               goto err1;
        }
 
        clk = clk_get(&pdev->dev, "usb");
@@ -547,7 +538,6 @@ static int __devinit davinci_probe(struct platform_device *pdev)
                goto err4;
        }
 
-       musb->id                        = musbid;
        musb->dev.parent                = &pdev->dev;
        musb->dev.dma_mask              = &davinci_dmamask;
        musb->dev.coherent_dma_mask     = davinci_dmamask;
@@ -590,9 +580,6 @@ err4:
 err3:
        platform_device_put(musb);
 
-err2:
-       musb_put_id(&pdev->dev, musbid);
-
 err1:
        kfree(glue);
 
@@ -604,9 +591,7 @@ static int __devexit davinci_remove(struct platform_device *pdev)
 {
        struct davinci_glue             *glue = platform_get_drvdata(pdev);
 
-       musb_put_id(&pdev->dev, glue->musb->id);
-       platform_device_del(glue->musb);
-       platform_device_put(glue->musb);
+       platform_device_unregister(glue->musb);
        clk_disable(glue->clk);
        clk_put(glue->clk);
        kfree(glue);
@@ -625,15 +610,4 @@ static struct platform_driver davinci_driver = {
 MODULE_DESCRIPTION("DaVinci MUSB Glue Layer");
 MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>");
 MODULE_LICENSE("GPL v2");
-
-static int __init davinci_init(void)
-{
-       return platform_driver_register(&davinci_driver);
-}
-module_init(davinci_init);
-
-static void __exit davinci_exit(void)
-{
-       platform_driver_unregister(&davinci_driver);
-}
-module_exit(davinci_exit);
+module_platform_driver(davinci_driver);
index bb56a0e8b23bf5620f0a5030e94e0f556e5da985..774d8154a28602ece397e96dca3a44821bca837d 100644 (file)
 
 #define MUSB_DRIVER_NAME "musb-hdrc"
 const char musb_driver_name[] = MUSB_DRIVER_NAME;
-static DEFINE_IDA(musb_ida);
 
 MODULE_DESCRIPTION(DRIVER_INFO);
 MODULE_AUTHOR(DRIVER_AUTHOR);
@@ -133,35 +132,6 @@ static inline struct musb *dev_to_musb(struct device *dev)
 
 /*-------------------------------------------------------------------------*/
 
-int musb_get_id(struct device *dev, gfp_t gfp_mask)
-{
-       int ret;
-       int id;
-
-       ret = ida_pre_get(&musb_ida, gfp_mask);
-       if (!ret) {
-               dev_err(dev, "failed to reserve resource for id\n");
-               return -ENOMEM;
-       }
-
-       ret = ida_get_new(&musb_ida, &id);
-       if (ret < 0) {
-               dev_err(dev, "failed to allocate a new id\n");
-               return ret;
-       }
-
-       return id;
-}
-EXPORT_SYMBOL_GPL(musb_get_id);
-
-void musb_put_id(struct device *dev, int id)
-{
-
-       dev_dbg(dev, "removing id %d\n", id);
-       ida_remove(&musb_ida, id);
-}
-EXPORT_SYMBOL_GPL(musb_put_id);
-
 #ifndef CONFIG_BLACKFIN
 static int musb_ulpi_read(struct usb_phy *phy, u32 offset)
 {
@@ -467,12 +437,12 @@ void musb_hnp_stop(struct musb *musb)
  */
 
 static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
-                               u8 devctl, u8 power)
+                               u8 devctl)
 {
        struct usb_otg *otg = musb->xceiv->otg;
        irqreturn_t handled = IRQ_NONE;
 
-       dev_dbg(musb->controller, "<== Power=%02x, DevCtl=%02x, int_usb=0x%x\n", power, devctl,
+       dev_dbg(musb->controller, "<== DevCtl=%02x, int_usb=0x%x\n", devctl,
                int_usb);
 
        /* in host mode, the peripheral may issue remote wakeup.
@@ -485,6 +455,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
 
                if (devctl & MUSB_DEVCTL_HM) {
                        void __iomem *mbase = musb->mregs;
+                       u8 power;
 
                        switch (musb->xceiv->state) {
                        case OTG_STATE_A_SUSPEND:
@@ -492,6 +463,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
                                 * will stop RESUME signaling
                                 */
 
+                               power = musb_readb(musb->mregs, MUSB_POWER);
                                if (power & MUSB_POWER_SUSPENDM) {
                                        /* spurious */
                                        musb->int_usb &= ~MUSB_INTR_SUSPEND;
@@ -655,8 +627,8 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
        }
 
        if (int_usb & MUSB_INTR_SUSPEND) {
-               dev_dbg(musb->controller, "SUSPEND (%s) devctl %02x power %02x\n",
-                       otg_state_string(musb->xceiv->state), devctl, power);
+               dev_dbg(musb->controller, "SUSPEND (%s) devctl %02x\n",
+                       otg_state_string(musb->xceiv->state), devctl);
                handled = IRQ_HANDLED;
 
                switch (musb->xceiv->state) {
@@ -722,8 +694,10 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
                if (is_peripheral_active(musb)) {
                        /* REVISIT HNP; just force disconnect */
                }
-               musb_writew(musb->mregs, MUSB_INTRTXE, musb->epmask);
-               musb_writew(musb->mregs, MUSB_INTRRXE, musb->epmask & 0xfffe);
+               musb->intrtxe = musb->epmask;
+               musb_writew(musb->mregs, MUSB_INTRTXE, musb->intrtxe);
+               musb->intrrxe = musb->epmask & 0xfffe;
+               musb_writew(musb->mregs, MUSB_INTRRXE, musb->intrrxe);
                musb_writeb(musb->mregs, MUSB_INTRUSBE, 0xf7);
                musb->port1_status &= ~(USB_PORT_STAT_LOW_SPEED
                                        |USB_PORT_STAT_HIGH_SPEED
@@ -944,8 +918,10 @@ void musb_start(struct musb *musb)
        dev_dbg(musb->controller, "<== devctl %02x\n", devctl);
 
        /*  Set INT enable registers, enable interrupts */
-       musb_writew(regs, MUSB_INTRTXE, musb->epmask);
-       musb_writew(regs, MUSB_INTRRXE, musb->epmask & 0xfffe);
+       musb->intrtxe = musb->epmask;
+       musb_writew(regs, MUSB_INTRTXE, musb->intrtxe);
+       musb->intrrxe = musb->epmask & 0xfffe;
+       musb_writew(regs, MUSB_INTRRXE, musb->intrrxe);
        musb_writeb(regs, MUSB_INTRUSBE, 0xf7);
 
        musb_writeb(regs, MUSB_TESTMODE, 0);
@@ -983,7 +959,9 @@ static void musb_generic_disable(struct musb *musb)
 
        /* disable interrupts */
        musb_writeb(mbase, MUSB_INTRUSBE, 0);
+       musb->intrtxe = 0;
        musb_writew(mbase, MUSB_INTRTXE, 0);
+       musb->intrrxe = 0;
        musb_writew(mbase, MUSB_INTRRXE, 0);
 
        /* off */
@@ -1523,33 +1501,6 @@ static int __devinit musb_core_init(u16 musb_type, struct musb *musb)
 
 /*-------------------------------------------------------------------------*/
 
-#if defined(CONFIG_SOC_OMAP2430) || defined(CONFIG_SOC_OMAP3430) || \
-       defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_ARCH_U8500)
-
-static irqreturn_t generic_interrupt(int irq, void *__hci)
-{
-       unsigned long   flags;
-       irqreturn_t     retval = IRQ_NONE;
-       struct musb     *musb = __hci;
-
-       spin_lock_irqsave(&musb->lock, flags);
-
-       musb->int_usb = musb_readb(musb->mregs, MUSB_INTRUSB);
-       musb->int_tx = musb_readw(musb->mregs, MUSB_INTRTX);
-       musb->int_rx = musb_readw(musb->mregs, MUSB_INTRRX);
-
-       if (musb->int_usb || musb->int_tx || musb->int_rx)
-               retval = musb_interrupt(musb);
-
-       spin_unlock_irqrestore(&musb->lock, flags);
-
-       return retval;
-}
-
-#else
-#define generic_interrupt      NULL
-#endif
-
 /*
  * handle all the irqs defined by the HDRC core. for now we expect:  other
  * irq sources (phy, dma, etc) will be handled first, musb->int_* values
@@ -1560,12 +1511,11 @@ static irqreturn_t generic_interrupt(int irq, void *__hci)
 irqreturn_t musb_interrupt(struct musb *musb)
 {
        irqreturn_t     retval = IRQ_NONE;
-       u8              devctl, power;
+       u8              devctl;
        int             ep_num;
        u32             reg;
 
        devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
-       power = musb_readb(musb->mregs, MUSB_POWER);
 
        dev_dbg(musb->controller, "** IRQ %s usb%04x tx%04x rx%04x\n",
                (devctl & MUSB_DEVCTL_HM) ? "host" : "peripheral",
@@ -1576,7 +1526,7 @@ irqreturn_t musb_interrupt(struct musb *musb)
         */
        if (musb->int_usb)
                retval |= musb_stage0_irq(musb, musb->int_usb,
-                               devctl, power);
+                               devctl);
 
        /* "stage 1" is handling endpoint irqs */
 
@@ -1919,7 +1869,8 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
        musb->ops = plat->platform_ops;
 
        /* The musb_platform_init() call:
-        *   - adjusts musb->mregs and musb->isr if needed,
+        *   - adjusts musb->mregs
+        *   - sets the musb->isr
         *   - may initialize an integrated tranceiver
         *   - initializes musb->xceiv, usually by otg_get_phy()
         *   - stops powering VBUS
@@ -1929,7 +1880,6 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
         * external/discrete ones in various flavors (twl4030 family,
         * isp1504, non-OTG, etc) mostly hooking up through ULPI.
         */
-       musb->isr = generic_interrupt;
        status = musb_platform_init(musb);
        if (status < 0)
                goto fail1;
@@ -2120,8 +2070,6 @@ static void musb_save_context(struct musb *musb)
        musb->context.testmode = musb_readb(musb_base, MUSB_TESTMODE);
        musb->context.busctl = musb_read_ulpi_buscontrol(musb->mregs);
        musb->context.power = musb_readb(musb_base, MUSB_POWER);
-       musb->context.intrtxe = musb_readw(musb_base, MUSB_INTRTXE);
-       musb->context.intrrxe = musb_readw(musb_base, MUSB_INTRRXE);
        musb->context.intrusbe = musb_readb(musb_base, MUSB_INTRUSBE);
        musb->context.index = musb_readb(musb_base, MUSB_INDEX);
        musb->context.devctl = musb_readb(musb_base, MUSB_DEVCTL);
@@ -2194,8 +2142,8 @@ static void musb_restore_context(struct musb *musb)
        musb_writeb(musb_base, MUSB_TESTMODE, musb->context.testmode);
        musb_write_ulpi_buscontrol(musb->mregs, musb->context.busctl);
        musb_writeb(musb_base, MUSB_POWER, musb->context.power);
-       musb_writew(musb_base, MUSB_INTRTXE, musb->context.intrtxe);
-       musb_writew(musb_base, MUSB_INTRRXE, musb->context.intrrxe);
+       musb_writew(musb_base, MUSB_INTRTXE, musb->intrtxe);
+       musb_writew(musb_base, MUSB_INTRRXE, musb->intrrxe);
        musb_writeb(musb_base, MUSB_INTRUSBE, musb->context.intrusbe);
        musb_writeb(musb_base, MUSB_DEVCTL, musb->context.devctl);
 
index c158aacd6de881c8fea326e59ba93a89f5a096da..7fb4819a6f115f54d097ef09eb131fb820994d05 100644 (file)
@@ -288,7 +288,6 @@ struct musb_csr_regs {
 struct musb_context_registers {
 
        u8 power;
-       u16 intrtxe, intrrxe;
        u8 intrusbe;
        u16 frame;
        u8 index, testmode;
@@ -313,6 +312,8 @@ struct musb {
        struct work_struct      irq_work;
        u16                     hwvers;
 
+       u16                     intrrxe;
+       u16                     intrtxe;
 /* this hub status bit is reserved by USB 2.0 and not seen by usbcore */
 #define MUSB_PORT_STAT_RESUME  (1 << 31)
 
@@ -521,8 +522,6 @@ extern const char musb_driver_name[];
 
 extern void musb_start(struct musb *musb);
 extern void musb_stop(struct musb *musb);
-extern int musb_get_id(struct device *dev, gfp_t gfp_mask);
-extern void musb_put_id(struct device *dev, int id);
 
 extern void musb_write_fifo(struct musb_hw_ep *ep, u16 len, const u8 *src);
 extern void musb_read_fifo(struct musb_hw_ep *ep, u16 len, u8 *dst);
index ff5f112053d28f114e4d90844b7aa2172f3856d4..b108473e4d5fcfb00151bbd62a92b579d8df2216 100644 (file)
@@ -124,8 +124,44 @@ struct dsps_glue {
        const struct dsps_musb_wrapper *wrp; /* wrapper register offsets */
        struct timer_list timer[2];     /* otg_workaround timer */
        unsigned long last_timer[2];    /* last timer data for each instance */
+       u32 __iomem *usb_ctrl[2];
 };
 
+#define        DSPS_AM33XX_CONTROL_MODULE_PHYS_0       0x44e10620
+#define        DSPS_AM33XX_CONTROL_MODULE_PHYS_1       0x44e10628
+
+static const resource_size_t dsps_control_module_phys[] = {
+       DSPS_AM33XX_CONTROL_MODULE_PHYS_0,
+       DSPS_AM33XX_CONTROL_MODULE_PHYS_1,
+};
+
+/**
+ * musb_dsps_phy_control - phy on/off
+ * @glue: struct dsps_glue *
+ * @id: musb instance
+ * @on: flag for phy to be switched on or off
+ *
+ * This is to enable the PHY using usb_ctrl register in system control
+ * module space.
+ *
+ * XXX: This function will be removed once we have a seperate driver for
+ * control module
+ */
+static void musb_dsps_phy_control(struct dsps_glue *glue, u8 id, u8 on)
+{
+       u32 usbphycfg;
+
+       usbphycfg = readl(glue->usb_ctrl[id]);
+
+       if (on) {
+               usbphycfg &= ~(USBPHY_CM_PWRDN | USBPHY_OTG_PWRDN);
+               usbphycfg |= USBPHY_OTGVDET_EN | USBPHY_OTGSESSEND_EN;
+       } else {
+               usbphycfg |= USBPHY_CM_PWRDN | USBPHY_OTG_PWRDN;
+       }
+
+       writel(usbphycfg, glue->usb_ctrl[id]);
+}
 /**
  * dsps_musb_enable - enable interrupts
  */
@@ -296,7 +332,7 @@ static irqreturn_t dsps_interrupt(int irq, void *hci)
         * Also, DRVVBUS pulses for SRP (but not at 5V) ...
         */
        if (usbintr & MUSB_INTR_BABBLE)
-               pr_info("CAUTION: musb: Babble Interrupt Occured\n");
+               pr_info("CAUTION: musb: Babble Interrupt Occurred\n");
 
        if (usbintr & ((1 << wrp->drvvbus) << wrp->usb_shift)) {
                int drvvbus = dsps_readl(reg_base, wrp->status);
@@ -365,11 +401,9 @@ static irqreturn_t dsps_interrupt(int irq, void *hci)
 static int dsps_musb_init(struct musb *musb)
 {
        struct device *dev = musb->controller;
-       struct musb_hdrc_platform_data *plat = dev->platform_data;
        struct platform_device *pdev = to_platform_device(dev);
        struct dsps_glue *glue = dev_get_drvdata(dev->parent);
        const struct dsps_musb_wrapper *wrp = glue->wrp;
-       struct omap_musb_board_data *data = plat->board_data;
        void __iomem *reg_base = musb->ctrl_base;
        u32 rev, val;
        int status;
@@ -377,7 +411,8 @@ static int dsps_musb_init(struct musb *musb)
        /* mentor core register starts at offset of 0x400 from musb base */
        musb->mregs += wrp->musb_core_offset;
 
-       /* Get the NOP PHY */
+       /* NOP driver needs change if supporting dual instance */
+       usb_nop_xceiv_register();
        musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
        if (IS_ERR_OR_NULL(musb->xceiv))
                return -ENODEV;
@@ -395,8 +430,7 @@ static int dsps_musb_init(struct musb *musb)
        dsps_writel(reg_base, wrp->control, (1 << wrp->reset));
 
        /* Start the on-chip PHY and its PLL. */
-       if (data->set_phy_power)
-               data->set_phy_power(1);
+       musb_dsps_phy_control(glue, pdev->id, 1);
 
        musb->isr = dsps_interrupt;
 
@@ -418,16 +452,13 @@ err0:
 static int dsps_musb_exit(struct musb *musb)
 {
        struct device *dev = musb->controller;
-       struct musb_hdrc_platform_data *plat = dev->platform_data;
-       struct omap_musb_board_data *data = plat->board_data;
        struct platform_device *pdev = to_platform_device(dev);
        struct dsps_glue *glue = dev_get_drvdata(dev->parent);
 
        del_timer_sync(&glue->timer[pdev->id]);
 
        /* Shutdown the on-chip PHY and its PLL. */
-       if (data->set_phy_power)
-               data->set_phy_power(0);
+       musb_dsps_phy_control(glue, pdev->id, 0);
 
        /* NOP driver needs change if supporting dual instance */
        usb_put_phy(musb->xceiv);
@@ -459,24 +490,33 @@ static int __devinit dsps_create_musb_pdev(struct dsps_glue *glue, u8 id)
        struct resource *res;
        struct resource resources[2];
        char res_name[11];
-       int ret, musbid;
+       int ret;
 
-       /* get memory resource */
-       snprintf(res_name, sizeof(res_name), "musb%d", id);
-       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, res_name);
+       resources[0].start = dsps_control_module_phys[id];
+       resources[0].end = resources[0].start + SZ_4 - 1;
+       resources[0].flags = IORESOURCE_MEM;
+
+       glue->usb_ctrl[id] = devm_request_and_ioremap(&pdev->dev, resources);
+       if (glue->usb_ctrl[id] == NULL) {
+               dev_err(dev, "Failed to obtain usb_ctrl%d memory\n", id);
+               ret = -ENODEV;
+               goto err0;
+       }
+
+       /* first resource is for usbss, so start index from 1 */
+       res = platform_get_resource(pdev, IORESOURCE_MEM, id + 1);
        if (!res) {
-               dev_err(dev, "%s get mem resource failed\n", res_name);
+               dev_err(dev, "failed to get memory for instance %d\n", id);
                ret = -ENODEV;
                goto err0;
        }
        res->parent = NULL;
        resources[0] = *res;
 
-       /* get irq resource */
-       snprintf(res_name, sizeof(res_name), "musb%d-irq", id);
-       res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, res_name);
+       /* first resource is for usbss, so start index from 1 */
+       res = platform_get_resource(pdev, IORESOURCE_IRQ, id + 1);
        if (!res) {
-               dev_err(dev, "%s get irq resource failed\n", res_name);
+               dev_err(dev, "failed to get irq for instance %d\n", id);
                ret = -ENODEV;
                goto err0;
        }
@@ -484,22 +524,14 @@ static int __devinit dsps_create_musb_pdev(struct dsps_glue *glue, u8 id)
        resources[1] = *res;
        resources[1].name = "mc";
 
-       /* get the musb id */
-       musbid = musb_get_id(dev, GFP_KERNEL);
-       if (musbid < 0) {
-               dev_err(dev, "failed to allocate musb id\n");
-               ret = -ENOMEM;
-               goto err0;
-       }
        /* allocate the child platform device */
-       musb = platform_device_alloc("musb-hdrc", musbid);
+       musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO);
        if (!musb) {
                dev_err(dev, "failed to allocate musb device\n");
                ret = -ENOMEM;
-               goto err1;
+               goto err0;
        }
 
-       musb->id                        = musbid;
        musb->dev.parent                = dev;
        musb->dev.dma_mask              = &musb_dmamask;
        musb->dev.coherent_dma_mask     = musb_dmamask;
@@ -556,19 +588,10 @@ static int __devinit dsps_create_musb_pdev(struct dsps_glue *glue, u8 id)
 
 err2:
        platform_device_put(musb);
-err1:
-       musb_put_id(dev, musbid);
 err0:
        return ret;
 }
 
-static void dsps_delete_musb_pdev(struct dsps_glue *glue, u8 id)
-{
-       musb_put_id(glue->dev, glue->musb[id]->id);
-       platform_device_del(glue->musb[id]);
-       platform_device_put(glue->musb[id]);
-}
-
 static int __devinit dsps_probe(struct platform_device *pdev)
 {
        struct device_node *np = pdev->dev.of_node;
@@ -628,7 +651,7 @@ static int __devinit dsps_probe(struct platform_device *pdev)
                        dev_err(&pdev->dev, "failed to create child pdev\n");
                        /* release resources of previously created instances */
                        for (i--; i >= 0 ; i--)
-                               dsps_delete_musb_pdev(glue, i);
+                               platform_device_unregister(glue->musb[i]);
                        goto err3;
                }
        }
@@ -653,7 +676,7 @@ static int __devexit dsps_remove(struct platform_device *pdev)
 
        /* delete the child platform device */
        for (i = 0; i < wrp->instances ; i++)
-               dsps_delete_musb_pdev(glue, i);
+               platform_device_unregister(glue->musb[i]);
 
        /* disable usbss clocks */
        pm_runtime_put(&pdev->dev);
@@ -666,24 +689,26 @@ static int __devexit dsps_remove(struct platform_device *pdev)
 #ifdef CONFIG_PM_SLEEP
 static int dsps_suspend(struct device *dev)
 {
-       struct musb_hdrc_platform_data *plat = dev->platform_data;
-       struct omap_musb_board_data *data = plat->board_data;
+       struct platform_device *pdev = to_platform_device(dev->parent);
+       struct dsps_glue *glue = platform_get_drvdata(pdev);
+       const struct dsps_musb_wrapper *wrp = glue->wrp;
+       int i;
 
-       /* Shutdown the on-chip PHY and its PLL. */
-       if (data->set_phy_power)
-               data->set_phy_power(0);
+       for (i = 0; i < wrp->instances; i++)
+               musb_dsps_phy_control(glue, i, 0);
 
        return 0;
 }
 
 static int dsps_resume(struct device *dev)
 {
-       struct musb_hdrc_platform_data *plat = dev->platform_data;
-       struct omap_musb_board_data *data = plat->board_data;
+       struct platform_device *pdev = to_platform_device(dev->parent);
+       struct dsps_glue *glue = platform_get_drvdata(pdev);
+       const struct dsps_musb_wrapper *wrp = glue->wrp;
+       int i;
 
-       /* Start the on-chip PHY and its PLL. */
-       if (data->set_phy_power)
-               data->set_phy_power(1);
+       for (i = 0; i < wrp->instances; i++)
+               musb_dsps_phy_control(glue, i, 1);
 
        return 0;
 }
@@ -719,7 +744,7 @@ static const struct dsps_musb_wrapper ti81xx_driver_data __devinitconst = {
        .rxep_bitmap            = (0xfffe << 16),
        .musb_core_offset       = 0x400,
        .poll_seconds           = 2,
-       .instances              = 2,
+       .instances              = 1,
 };
 
 static const struct platform_device_id musb_dsps_id_table[] __devinitconst = {
index d0b87e7b4abfd98b232c135df7661d6dbe0bfe90..28b9790e84ea9f225b59f36d226529716571778f 100644 (file)
@@ -1068,7 +1068,6 @@ static int musb_gadget_enable(struct usb_ep *ep,
         */
        musb_ep_select(mbase, epnum);
        if (usb_endpoint_dir_in(desc)) {
-               u16 int_txe = musb_readw(mbase, MUSB_INTRTXE);
 
                if (hw_ep->is_shared_fifo)
                        musb_ep->is_in = 1;
@@ -1080,8 +1079,8 @@ static int musb_gadget_enable(struct usb_ep *ep,
                        goto fail;
                }
 
-               int_txe |= (1 << epnum);
-               musb_writew(mbase, MUSB_INTRTXE, int_txe);
+               musb->intrtxe |= (1 << epnum);
+               musb_writew(mbase, MUSB_INTRTXE, musb->intrtxe);
 
                /* REVISIT if can_bulk_split(), use by updating "tmp";
                 * likewise high bandwidth periodic tx
@@ -1108,7 +1107,6 @@ static int musb_gadget_enable(struct usb_ep *ep,
                musb_writew(regs, MUSB_TXCSR, csr);
 
        } else {
-               u16 int_rxe = musb_readw(mbase, MUSB_INTRRXE);
 
                if (hw_ep->is_shared_fifo)
                        musb_ep->is_in = 0;
@@ -1120,8 +1118,8 @@ static int musb_gadget_enable(struct usb_ep *ep,
                        goto fail;
                }
 
-               int_rxe |= (1 << epnum);
-               musb_writew(mbase, MUSB_INTRRXE, int_rxe);
+               musb->intrrxe |= (1 << epnum);
+               musb_writew(mbase, MUSB_INTRRXE, musb->intrrxe);
 
                /* REVISIT if can_bulk_combine() use by updating "tmp"
                 * likewise high bandwidth periodic rx
@@ -1209,14 +1207,12 @@ static int musb_gadget_disable(struct usb_ep *ep)
 
        /* zero the endpoint sizes */
        if (musb_ep->is_in) {
-               u16 int_txe = musb_readw(musb->mregs, MUSB_INTRTXE);
-               int_txe &= ~(1 << epnum);
-               musb_writew(musb->mregs, MUSB_INTRTXE, int_txe);
+               musb->intrtxe &= ~(1 << epnum);
+               musb_writew(musb->mregs, MUSB_INTRTXE, musb->intrtxe);
                musb_writew(epio, MUSB_TXMAXP, 0);
        } else {
-               u16 int_rxe = musb_readw(musb->mregs, MUSB_INTRRXE);
-               int_rxe &= ~(1 << epnum);
-               musb_writew(musb->mregs, MUSB_INTRRXE, int_rxe);
+               musb->intrrxe &= ~(1 << epnum);
+               musb_writew(musb->mregs, MUSB_INTRRXE, musb->intrrxe);
                musb_writew(epio, MUSB_RXMAXP, 0);
        }
 
@@ -1532,7 +1528,7 @@ static void musb_gadget_fifo_flush(struct usb_ep *ep)
        void __iomem    *epio = musb->endpoints[epnum].regs;
        void __iomem    *mbase;
        unsigned long   flags;
-       u16             csr, int_txe;
+       u16             csr;
 
        mbase = musb->mregs;
 
@@ -1540,8 +1536,7 @@ static void musb_gadget_fifo_flush(struct usb_ep *ep)
        musb_ep_select(mbase, (u8) epnum);
 
        /* disable interrupts */
-       int_txe = musb_readw(mbase, MUSB_INTRTXE);
-       musb_writew(mbase, MUSB_INTRTXE, int_txe & ~(1 << epnum));
+       musb_writew(mbase, MUSB_INTRTXE, musb->intrtxe & ~(1 << epnum));
 
        if (musb_ep->is_in) {
                csr = musb_readw(epio, MUSB_TXCSR);
@@ -1565,7 +1560,7 @@ static void musb_gadget_fifo_flush(struct usb_ep *ep)
        }
 
        /* re-enable interrupt */
-       musb_writew(mbase, MUSB_INTRTXE, int_txe);
+       musb_writew(mbase, MUSB_INTRTXE, musb->intrtxe);
        spin_unlock_irqrestore(&musb->lock, flags);
 }
 
@@ -2154,10 +2149,9 @@ __acquires(musb->lock)
        u8              devctl = musb_readb(mbase, MUSB_DEVCTL);
        u8              power;
 
-       dev_dbg(musb->controller, "<== %s addr=%x driver '%s'\n",
+       dev_dbg(musb->controller, "<== %s driver '%s'\n",
                        (devctl & MUSB_DEVCTL_BDEVICE)
                                ? "B-Device" : "A-Device",
-                       musb_readb(mbase, MUSB_FADDR),
                        musb->gadget_driver
                                ? musb->gadget_driver->driver.name
                                : NULL
index e40d7647caf1c636a52d6e539f53c78360062a62..c9c1ac4e075f758ae01eaf0a79b738ee41da0611 100644 (file)
@@ -673,10 +673,8 @@ irqreturn_t musb_g_ep0_irq(struct musb *musb)
        csr = musb_readw(regs, MUSB_CSR0);
        len = musb_readb(regs, MUSB_COUNT0);
 
-       dev_dbg(musb->controller, "csr %04x, count %d, myaddr %d, ep0stage %s\n",
-                       csr, len,
-                       musb_readb(mbase, MUSB_FADDR),
-                       decode_ep0stage(musb->ep0_state));
+       dev_dbg(musb->controller, "csr %04x, count %d, ep0stage %s\n",
+                       csr, len, decode_ep0stage(musb->ep0_state));
 
        if (csr & MUSB_CSR0_P_DATAEND) {
                /*
index 3df6a76b851dbefc91c6d5488570f9d53813a59b..e9f0fd9ddd2d05284283ee3448785984cc760c10 100644 (file)
@@ -740,7 +740,7 @@ static void musb_ep_program(struct musb *musb, u8 epnum,
                csr = musb_readw(epio, MUSB_TXCSR);
 
                /* disable interrupt in case we flush */
-               int_txe = musb_readw(mbase, MUSB_INTRTXE);
+               int_txe = musb->intrtxe;
                musb_writew(mbase, MUSB_INTRTXE, int_txe & ~(1 << epnum));
 
                /* general endpoint setup */
index 320fd4afb93f7cd31b05e26e125819ae03af95c2..f7b13fd252574f848e7984905cbaef4478c2e90a 100644 (file)
  *
  */
 
-#if defined(CONFIG_SOC_OMAP2430) || defined(CONFIG_SOC_OMAP3430)
-#include "omap2430.h"
-#endif
-
 #ifndef CONFIG_BLACKFIN
 
 #define MUSB_HSDMA_BASE                0x200
index a538fe17a966b0932400a3be02087be1aec5f26c..32f531e7a2e6ff48db2b4f5d9a8f8f4c1572d65a 100644 (file)
@@ -333,6 +333,26 @@ static void omap_musb_mailbox_work(struct work_struct *mailbox_work)
        omap_musb_set_mailbox(glue);
 }
 
+static irqreturn_t omap2430_musb_interrupt(int irq, void *__hci)
+{
+       unsigned long   flags;
+       irqreturn_t     retval = IRQ_NONE;
+       struct musb     *musb = __hci;
+
+       spin_lock_irqsave(&musb->lock, flags);
+
+       musb->int_usb = musb_readb(musb->mregs, MUSB_INTRUSB);
+       musb->int_tx = musb_readw(musb->mregs, MUSB_INTRTX);
+       musb->int_rx = musb_readw(musb->mregs, MUSB_INTRRX);
+
+       if (musb->int_usb || musb->int_tx || musb->int_rx)
+               retval = musb_interrupt(musb);
+
+       spin_unlock_irqrestore(&musb->lock, flags);
+
+       return retval;
+}
+
 static int omap2430_musb_init(struct musb *musb)
 {
        u32 l;
@@ -352,6 +372,8 @@ static int omap2430_musb_init(struct musb *musb)
                return -ENODEV;
        }
 
+       musb->isr = omap2430_musb_interrupt;
+
        status = pm_runtime_get_sync(dev);
        if (status < 0) {
                dev_err(dev, "pm_runtime_get_sync FAILED %d\n", status);
@@ -478,7 +500,6 @@ static int __devinit omap2430_probe(struct platform_device *pdev)
        struct musb_hdrc_config         *config;
        struct resource                 *res;
        int                             ret = -ENOMEM;
-       int                             musbid;
 
        glue = devm_kzalloc(&pdev->dev, sizeof(*glue), GFP_KERNEL);
        if (!glue) {
@@ -486,21 +507,12 @@ static int __devinit omap2430_probe(struct platform_device *pdev)
                goto err0;
        }
 
-       /* get the musb id */
-       musbid = musb_get_id(&pdev->dev, GFP_KERNEL);
-       if (musbid < 0) {
-               dev_err(&pdev->dev, "failed to allocate musb id\n");
-               ret = -ENOMEM;
-               goto err0;
-       }
-
-       musb = platform_device_alloc("musb-hdrc", musbid);
+       musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO);
        if (!musb) {
                dev_err(&pdev->dev, "failed to allocate musb device\n");
-               goto err1;
+               goto err0;
        }
 
-       musb->id                        = musbid;
        musb->dev.parent                = &pdev->dev;
        musb->dev.dma_mask              = &omap2430_dmamask;
        musb->dev.coherent_dma_mask     = omap2430_dmamask;
@@ -521,7 +533,7 @@ static int __devinit omap2430_probe(struct platform_device *pdev)
                        dev_err(&pdev->dev,
                                "failed to allocate musb platfrom data\n");
                        ret = -ENOMEM;
-                       goto err1;
+                       goto err2;
                }
 
                data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
@@ -529,14 +541,14 @@ static int __devinit omap2430_probe(struct platform_device *pdev)
                        dev_err(&pdev->dev,
                                        "failed to allocate musb board data\n");
                        ret = -ENOMEM;
-                       goto err1;
+                       goto err2;
                }
 
                config = devm_kzalloc(&pdev->dev, sizeof(*config), GFP_KERNEL);
                if (!data) {
                        dev_err(&pdev->dev,
                                "failed to allocate musb hdrc config\n");
-                       goto err1;
+                       goto err2;
                }
 
                of_property_read_u32(np, "mode", (u32 *)&pdata->mode);
@@ -589,9 +601,6 @@ static int __devinit omap2430_probe(struct platform_device *pdev)
 err2:
        platform_device_put(musb);
 
-err1:
-       musb_put_id(&pdev->dev, musbid);
-
 err0:
        return ret;
 }
@@ -601,7 +610,6 @@ static int __devexit omap2430_remove(struct platform_device *pdev)
        struct omap2430_glue            *glue = platform_get_drvdata(pdev);
 
        cancel_work_sync(&glue->omap_musb_mailbox_work);
-       musb_put_id(&pdev->dev, glue->musb->id);
        platform_device_unregister(glue->musb);
 
        return 0;
index dc4d75ea13adb4059a6aba4cad92f269279b8ce4..812719b683d1a858a976f31aa4efd4af6f3ad494 100644 (file)
@@ -1160,7 +1160,6 @@ static int __devinit tusb_probe(struct platform_device *pdev)
        struct tusb6010_glue            *glue;
 
        int                             ret = -ENOMEM;
-       int                             musbid;
 
        glue = kzalloc(sizeof(*glue), GFP_KERNEL);
        if (!glue) {
@@ -1168,21 +1167,12 @@ static int __devinit tusb_probe(struct platform_device *pdev)
                goto err0;
        }
 
-       /* get the musb id */
-       musbid = musb_get_id(&pdev->dev, GFP_KERNEL);
-       if (musbid < 0) {
-               dev_err(&pdev->dev, "failed to allocate musb id\n");
-               ret = -ENOMEM;
-               goto err1;
-       }
-
-       musb = platform_device_alloc("musb-hdrc", musbid);
+       musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO);
        if (!musb) {
                dev_err(&pdev->dev, "failed to allocate musb device\n");
-               goto err2;
+               goto err1;
        }
 
-       musb->id                        = musbid;
        musb->dev.parent                = &pdev->dev;
        musb->dev.dma_mask              = &tusb_dmamask;
        musb->dev.coherent_dma_mask     = tusb_dmamask;
@@ -1218,9 +1208,6 @@ static int __devinit tusb_probe(struct platform_device *pdev)
 err3:
        platform_device_put(musb);
 
-err2:
-       musb_put_id(&pdev->dev, musbid);
-
 err1:
        kfree(glue);
 
@@ -1232,9 +1219,7 @@ static int __devexit tusb_remove(struct platform_device *pdev)
 {
        struct tusb6010_glue            *glue = platform_get_drvdata(pdev);
 
-       musb_put_id(&pdev->dev, glue->musb->id);
-       platform_device_del(glue->musb);
-       platform_device_put(glue->musb);
+       platform_device_unregister(glue->musb);
        kfree(glue);
 
        return 0;
@@ -1251,15 +1236,4 @@ static struct platform_driver tusb_driver = {
 MODULE_DESCRIPTION("TUSB6010 MUSB Glue Layer");
 MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>");
 MODULE_LICENSE("GPL v2");
-
-static int __init tusb_init(void)
-{
-       return platform_driver_register(&tusb_driver);
-}
-module_init(tusb_init);
-
-static void __exit tusb_exit(void)
-{
-       platform_driver_unregister(&tusb_driver);
-}
-module_exit(tusb_exit);
+module_platform_driver(tusb_driver);
index d62a91fedc221c02774de2c8b9c9e66c3a880ade..286f1be6594acd8c56a5e55e010c69e853adab6a 100644 (file)
@@ -36,6 +36,26 @@ struct ux500_glue {
 };
 #define glue_to_musb(g)        platform_get_drvdata(g->musb)
 
+static irqreturn_t ux500_musb_interrupt(int irq, void *__hci)
+{
+       unsigned long   flags;
+       irqreturn_t     retval = IRQ_NONE;
+       struct musb     *musb = __hci;
+
+       spin_lock_irqsave(&musb->lock, flags);
+
+       musb->int_usb = musb_readb(musb->mregs, MUSB_INTRUSB);
+       musb->int_tx = musb_readw(musb->mregs, MUSB_INTRTX);
+       musb->int_rx = musb_readw(musb->mregs, MUSB_INTRRX);
+
+       if (musb->int_usb || musb->int_tx || musb->int_rx)
+               retval = musb_interrupt(musb);
+
+       spin_unlock_irqrestore(&musb->lock, flags);
+
+       return retval;
+}
+
 static int ux500_musb_init(struct musb *musb)
 {
        musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
@@ -44,6 +64,8 @@ static int ux500_musb_init(struct musb *musb)
                return -ENODEV;
        }
 
+       musb->isr = ux500_musb_interrupt;
+
        return 0;
 }
 
@@ -65,7 +87,6 @@ static int __devinit ux500_probe(struct platform_device *pdev)
        struct platform_device          *musb;
        struct ux500_glue               *glue;
        struct clk                      *clk;
-
        int                             ret = -ENOMEM;
 
        glue = kzalloc(sizeof(*glue), GFP_KERNEL);
@@ -74,18 +95,10 @@ static int __devinit ux500_probe(struct platform_device *pdev)
                goto err0;
        }
 
-       /* get the musb id */
-       musbid = musb_get_id(&pdev->dev, GFP_KERNEL);
-       if (musbid < 0) {
-               dev_err(&pdev->dev, "failed to allocate musb id\n");
-               ret = -ENOMEM;
-               goto err1;
-       }
-
-       musb = platform_device_alloc("musb-hdrc", musbid);
+       musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO);
        if (!musb) {
                dev_err(&pdev->dev, "failed to allocate musb device\n");
-               goto err2;
+               goto err1;
        }
 
        clk = clk_get(&pdev->dev, "usb");
@@ -101,7 +114,6 @@ static int __devinit ux500_probe(struct platform_device *pdev)
                goto err4;
        }
 
-       musb->id                        = musbid;
        musb->dev.parent                = &pdev->dev;
        musb->dev.dma_mask              = pdev->dev.dma_mask;
        musb->dev.coherent_dma_mask     = pdev->dev.coherent_dma_mask;
@@ -144,9 +156,6 @@ err4:
 err3:
        platform_device_put(musb);
 
-err2:
-       musb_put_id(&pdev->dev, musbid);
-
 err1:
        kfree(glue);
 
@@ -158,9 +167,7 @@ static int __devexit ux500_remove(struct platform_device *pdev)
 {
        struct ux500_glue       *glue = platform_get_drvdata(pdev);
 
-       musb_put_id(&pdev->dev, glue->musb->id);
-       platform_device_del(glue->musb);
-       platform_device_put(glue->musb);
+       platform_device_unregister(glue->musb);
        clk_disable(glue->clk);
        clk_put(glue->clk);
        kfree(glue);
@@ -219,15 +226,4 @@ static struct platform_driver ux500_driver = {
 MODULE_DESCRIPTION("UX500 MUSB Glue Layer");
 MODULE_AUTHOR("Mian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.com>");
 MODULE_LICENSE("GPL v2");
-
-static int __init ux500_init(void)
-{
-       return platform_driver_register(&ux500_driver);
-}
-module_init(ux500_init);
-
-static void __exit ux500_exit(void)
-{
-       platform_driver_unregister(&ux500_driver);
-}
-module_exit(ux500_exit);
+module_platform_driver(ux500_driver);
index 3f124e8f5792957585494cf91234dad6d6e62888..1dd57504186db5225b28b353527001b4e1914b2e 100644 (file)
@@ -958,16 +958,4 @@ static struct platform_driver mv_otg_driver = {
        .resume = mv_otg_resume,
 #endif
 };
-
-static int __init mv_otg_init(void)
-{
-       return platform_driver_register(&mv_otg_driver);
-}
-
-static void __exit mv_otg_exit(void)
-{
-       platform_driver_unregister(&mv_otg_driver);
-}
-
-module_init(mv_otg_init);
-module_exit(mv_otg_exit);
+module_platform_driver(mv_otg_driver);
index 63c339b3e676f2f439db0178c9debc627d8aa5ac..7eb73c561bd2896d5c135a8c53e40e0ae352bad6 100644 (file)
@@ -32,3 +32,15 @@ config MV_U3D_PHY
        help
          Enable this to support Marvell USB 3.0 phy controller for Marvell
          SoC.
+
+config USB_RCAR_PHY
+       tristate "Renesas R-Car USB phy support"
+       depends on USB || USB_GADGET
+       select USB_OTG_UTILS
+       help
+         Say Y here to add support for the Renesas R-Car USB phy driver.
+         This chip is typically used as USB phy for USB host, gadget.
+         This driver supports: R8A7779
+
+         To compile this driver as a module, choose M here: the
+         module will be called rcar-phy.
index b069f29f122590a5b76dccb96acbe38d06250668..1a579a860a037b3b9226839c0d5fa7981a5d0687 100644 (file)
@@ -8,3 +8,4 @@ obj-$(CONFIG_OMAP_USB2)                 += omap-usb2.o
 obj-$(CONFIG_USB_ISP1301)              += isp1301.o
 obj-$(CONFIG_MV_U3D_PHY)               += mv_u3d_phy.o
 obj-$(CONFIG_USB_EHCI_TEGRA)   += tegra_usb_phy.o
+obj-$(CONFIG_USB_RCAR_PHY)             += rcar-phy.o
diff --git a/drivers/usb/phy/rcar-phy.c b/drivers/usb/phy/rcar-phy.c
new file mode 100644 (file)
index 0000000..792f505
--- /dev/null
@@ -0,0 +1,220 @@
+/*
+ * Renesas R-Car USB phy driver
+ *
+ * Copyright (C) 2012 Renesas Solutions Corp.
+ * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/usb/otg.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+#include <linux/module.h>
+
+/* USBH common register */
+#define USBPCTRL0      0x0800
+#define USBPCTRL1      0x0804
+#define USBST          0x0808
+#define USBEH0         0x080C
+#define USBOH0         0x081C
+#define USBCTL0                0x0858
+#define EIIBC1         0x0094
+#define EIIBC2         0x009C
+
+/* USBPCTRL1 */
+#define PHY_RST                (1 << 2)
+#define PLL_ENB                (1 << 1)
+#define PHY_ENB                (1 << 0)
+
+/* USBST */
+#define ST_ACT         (1 << 31)
+#define ST_PLL         (1 << 30)
+
+struct rcar_usb_phy_priv {
+       struct usb_phy phy;
+       spinlock_t lock;
+
+       void __iomem *reg0;
+       void __iomem *reg1;
+       int counter;
+};
+
+#define usb_phy_to_priv(p) container_of(p, struct rcar_usb_phy_priv, phy)
+
+
+/*
+ * USB initial/install operation.
+ *
+ * This function setup USB phy.
+ * The used value and setting order came from
+ * [USB :: Initial setting] on datasheet.
+ */
+static int rcar_usb_phy_init(struct usb_phy *phy)
+{
+       struct rcar_usb_phy_priv *priv = usb_phy_to_priv(phy);
+       struct device *dev = phy->dev;
+       void __iomem *reg0 = priv->reg0;
+       void __iomem *reg1 = priv->reg1;
+       int i;
+       u32 val;
+       unsigned long flags;
+
+       spin_lock_irqsave(&priv->lock, flags);
+       if (priv->counter++ == 0) {
+
+               /*
+                * USB phy start-up
+                */
+
+               /* (1) USB-PHY standby release */
+               iowrite32(PHY_ENB, (reg0 + USBPCTRL1));
+
+               /* (2) start USB-PHY internal PLL */
+               iowrite32(PHY_ENB | PLL_ENB, (reg0 + USBPCTRL1));
+
+               /* (3) USB module status check */
+               for (i = 0; i < 1024; i++) {
+                       udelay(10);
+                       val = ioread32(reg0 + USBST);
+                       if (val == (ST_ACT | ST_PLL))
+                               break;
+               }
+
+               if (val != (ST_ACT | ST_PLL)) {
+                       dev_err(dev, "USB phy not ready\n");
+                       goto phy_init_end;
+               }
+
+               /* (4) USB-PHY reset clear */
+               iowrite32(PHY_ENB | PLL_ENB | PHY_RST, (reg0 + USBPCTRL1));
+
+               /* set platform specific port settings */
+               iowrite32(0x00000000, (reg0 + USBPCTRL0));
+
+               /*
+                * EHCI IP internal buffer setting
+                * EHCI IP internal buffer enable
+                *
+                * These are recommended value of a datasheet
+                * see [USB :: EHCI internal buffer setting]
+                */
+               iowrite32(0x00ff0040, (reg0 + EIIBC1));
+               iowrite32(0x00ff0040, (reg1 + EIIBC1));
+
+               iowrite32(0x00000001, (reg0 + EIIBC2));
+               iowrite32(0x00000001, (reg1 + EIIBC2));
+
+               /*
+                * Bus alignment settings
+                */
+
+               /* (1) EHCI bus alignment (little endian) */
+               iowrite32(0x00000000, (reg0 + USBEH0));
+
+               /* (1) OHCI bus alignment (little endian) */
+               iowrite32(0x00000000, (reg0 + USBOH0));
+       }
+
+phy_init_end:
+       spin_unlock_irqrestore(&priv->lock, flags);
+
+       return 0;
+}
+
+static void rcar_usb_phy_shutdown(struct usb_phy *phy)
+{
+       struct rcar_usb_phy_priv *priv = usb_phy_to_priv(phy);
+       void __iomem *reg0 = priv->reg0;
+       unsigned long flags;
+
+       spin_lock_irqsave(&priv->lock, flags);
+
+       if (priv->counter-- == 1) { /* last user */
+               iowrite32(0x00000000, (reg0 + USBPCTRL0));
+               iowrite32(0x00000000, (reg0 + USBPCTRL1));
+       }
+
+       spin_unlock_irqrestore(&priv->lock, flags);
+}
+
+static int __devinit rcar_usb_phy_probe(struct platform_device *pdev)
+{
+       struct rcar_usb_phy_priv *priv;
+       struct resource *res0, *res1;
+       struct device *dev = &pdev->dev;
+       void __iomem *reg0, *reg1;
+       int ret;
+
+       res0 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       res1 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+       if (!res0 || !res1) {
+               dev_err(dev, "Not enough platform resources\n");
+               return -EINVAL;
+       }
+
+       /*
+        * CAUTION
+        *
+        * Because this phy address is also mapped under OHCI/EHCI address area,
+        * this driver can't use devm_request_and_ioremap(dev, res) here
+        */
+       reg0 = devm_ioremap_nocache(dev, res0->start, resource_size(res0));
+       reg1 = devm_ioremap_nocache(dev, res1->start, resource_size(res1));
+       if (!reg0 || !reg1) {
+               dev_err(dev, "ioremap error\n");
+               return -ENOMEM;
+       }
+
+       priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+       if (!priv) {
+               dev_err(dev, "priv data allocation error\n");
+               return -ENOMEM;
+       }
+
+       priv->reg0              = reg0;
+       priv->reg1              = reg1;
+       priv->counter           = 0;
+       priv->phy.dev           = dev;
+       priv->phy.label         = dev_name(dev);
+       priv->phy.init          = rcar_usb_phy_init;
+       priv->phy.shutdown      = rcar_usb_phy_shutdown;
+       spin_lock_init(&priv->lock);
+
+       ret = usb_add_phy(&priv->phy, USB_PHY_TYPE_USB2);
+       if (ret < 0) {
+               dev_err(dev, "usb phy addition error\n");
+               return ret;
+       }
+
+       platform_set_drvdata(pdev, priv);
+
+       return ret;
+}
+
+static int __devexit rcar_usb_phy_remove(struct platform_device *pdev)
+{
+       struct rcar_usb_phy_priv *priv = platform_get_drvdata(pdev);
+
+       usb_remove_phy(&priv->phy);
+
+       return 0;
+}
+
+static struct platform_driver rcar_usb_phy_driver = {
+       .driver         = {
+               .name   = "rcar_usb_phy",
+       },
+       .probe          = rcar_usb_phy_probe,
+       .remove         = __devexit_p(rcar_usb_phy_remove),
+};
+
+module_platform_driver(rcar_usb_phy_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Renesas R-Car USB phy");
+MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");
index 987116f9efcdec0fc7693725f3d315850f5f9eb8..9d13c81754e0cd0d2b38299dcb6143847ad380b2 100644 (file)
@@ -29,7 +29,9 @@
 #include <linux/usb/ulpi.h>
 #include <asm/mach-types.h>
 #include <linux/usb/tegra_usb_phy.h>
-#include <mach/iomap.h>
+
+#define TEGRA_USB_BASE         0xC5000000
+#define TEGRA_USB_SIZE         SZ_16K
 
 #define ULPI_VIEWPORT          0x170
 
index 072edc1cc55f8ec020c3cb5f75bec072e9091a63..3bf922ab045e9669e07ba515b656bb15e55e1474 100644 (file)
@@ -132,6 +132,11 @@ void usbhs_sys_function_ctrl(struct usbhs_priv *priv, int enable)
        usbhs_bset(priv, SYSCFG, mask, enable ? val : 0);
 }
 
+void usbhs_sys_function_pullup(struct usbhs_priv *priv, int enable)
+{
+       usbhs_bset(priv, SYSCFG, DPRPU, enable ? DPRPU : 0);
+}
+
 void usbhs_sys_set_test_mode(struct usbhs_priv *priv, u16 mode)
 {
        usbhs_write(priv, TESTMODE, mode);
index dddf40a59dedc456d3cc0f270b950b5dcb3b4671..c69dd2fba3603259b4591d21a11dda0fafc5e2b8 100644 (file)
@@ -285,6 +285,7 @@ void usbhs_bset(struct usbhs_priv *priv, u32 reg, u16 mask, u16 data);
  */
 void usbhs_sys_host_ctrl(struct usbhs_priv *priv, int enable);
 void usbhs_sys_function_ctrl(struct usbhs_priv *priv, int enable);
+void usbhs_sys_function_pullup(struct usbhs_priv *priv, int enable);
 void usbhs_sys_set_test_mode(struct usbhs_priv *priv, u16 mode);
 
 /*
index c021b202c0f3fe05894d3a94075c55bea8dd1a66..9538f0feafe2c37f6b98f5598126fa8b75906af3 100644 (file)
@@ -163,7 +163,7 @@ static int usbhsf_pkt_handler(struct usbhs_pipe *pipe, int type)
                func = pkt->handler->dma_done;
                break;
        default:
-               dev_err(dev, "unknown pkt hander\n");
+               dev_err(dev, "unknown pkt handler\n");
                goto __usbhs_pkt_handler_end;
        }
 
@@ -192,8 +192,8 @@ void usbhs_pkt_start(struct usbhs_pipe *pipe)
 /*
  *             irq enable/disable function
  */
-#define usbhsf_irq_empty_ctrl(p, e) usbhsf_irq_callback_ctrl(p, bempsts, e)
-#define usbhsf_irq_ready_ctrl(p, e) usbhsf_irq_callback_ctrl(p, brdysts, e)
+#define usbhsf_irq_empty_ctrl(p, e) usbhsf_irq_callback_ctrl(p, irq_bempsts, e)
+#define usbhsf_irq_ready_ctrl(p, e) usbhsf_irq_callback_ctrl(p, irq_brdysts, e)
 #define usbhsf_irq_callback_ctrl(pipe, status, enable)                 \
        ({                                                              \
                struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);     \
@@ -202,9 +202,9 @@ void usbhs_pkt_start(struct usbhs_pipe *pipe)
                if (!mod)                                               \
                        return;                                         \
                if (enable)                                             \
-                       mod->irq_##status |= status;                    \
+                       mod->status |= status;                          \
                else                                                    \
-                       mod->irq_##status &= ~status;                   \
+                       mod->status &= ~status;                         \
                usbhs_irq_callback_update(priv, mod);                   \
        })
 
@@ -488,6 +488,8 @@ static int usbhsf_pio_try_push(struct usbhs_pkt *pkt, int *is_done)
        usbhs_pipe_data_sequence(pipe, pkt->sequence);
        pkt->sequence = -1; /* -1 sequence will be ignored */
 
+       usbhs_pipe_set_trans_count_if_bulk(pipe, pkt->length);
+
        ret = usbhsf_fifo_select(pipe, fifo, 1);
        if (ret < 0)
                return 0;
@@ -594,6 +596,7 @@ static int usbhsf_prepare_pop(struct usbhs_pkt *pkt, int *is_done)
        usbhs_pipe_data_sequence(pipe, pkt->sequence);
        pkt->sequence = -1; /* -1 sequence will be ignored */
 
+       usbhs_pipe_set_trans_count_if_bulk(pipe, pkt->length);
        usbhs_pipe_enable(pipe);
        usbhsf_rx_irq_ctrl(pipe, 1);
 
@@ -795,6 +798,7 @@ static void xfer_work(struct work_struct *work)
        dev_dbg(dev, "  %s %d (%d/ %d)\n",
                fifo->name, usbhs_pipe_number(pipe), pkt->length, pkt->zero);
 
+       usbhs_pipe_set_trans_count_if_bulk(pipe, pkt->trans);
        usbhs_pipe_enable(pipe);
        usbhsf_dma_start(pipe, fifo);
        dma_async_issue_pending(chan);
index 61933a90e5bfdbe41fed1679979977e6ff849b4b..6a030b931a3b71d721870181d1170ba451dacc8b 100644 (file)
@@ -151,7 +151,7 @@ int usbhs_mod_probe(struct usbhs_priv *priv)
                goto mod_init_host_err;
 
        /* irq settings */
-       ret = request_irq(priv->irq, usbhs_interrupt,
+       ret = devm_request_irq(dev, priv->irq, usbhs_interrupt,
                          priv->irqflags, dev_name(dev), priv);
        if (ret) {
                dev_err(dev, "irq request err\n");
@@ -172,7 +172,6 @@ void usbhs_mod_remove(struct usbhs_priv *priv)
 {
        usbhs_mod_host_remove(priv);
        usbhs_mod_gadget_remove(priv);
-       free_irq(priv->irq, priv);
 }
 
 /*
index 28478ce26c3429c59289dfabbdc5f6cd2b61a846..dd41f61893ef87484fbfc233dc338427bcfcede6 100644 (file)
@@ -883,6 +883,16 @@ static int usbhsg_get_frame(struct usb_gadget *gadget)
        return usbhs_frame_get_num(priv);
 }
 
+static int usbhsg_pullup(struct usb_gadget *gadget, int is_on)
+{
+       struct usbhsg_gpriv *gpriv = usbhsg_gadget_to_gpriv(gadget);
+       struct usbhs_priv *priv = usbhsg_gpriv_to_priv(gpriv);
+
+       usbhs_sys_function_pullup(priv, is_on);
+
+       return 0;
+}
+
 static int usbhsg_set_selfpowered(struct usb_gadget *gadget, int is_self)
 {
        struct usbhsg_gpriv *gpriv = usbhsg_gadget_to_gpriv(gadget);
@@ -900,6 +910,7 @@ static struct usb_gadget_ops usbhsg_gadget_ops = {
        .set_selfpowered        = usbhsg_set_selfpowered,
        .udc_start              = usbhsg_gadget_start,
        .udc_stop               = usbhsg_gadget_stop,
+       .pullup                 = usbhsg_pullup,
 };
 
 static int usbhsg_start(struct usbhs_priv *priv)
index 069cd765400cbf51f649564d5ed8490d90cd8259..3d3cd6ca2689894a497efefeb6ffc1edf6002cba 100644 (file)
@@ -85,6 +85,7 @@ struct usbhsh_ep {
        struct usbhsh_device    *udev;   /* attached udev */
        struct usb_host_endpoint *ep;
        struct list_head        ep_list; /* list to usbhsh_device */
+       unsigned int            counter; /* pipe attach counter */
 };
 
 #define USBHSH_DEVICE_MAX      10 /* see DEVADDn / DCPMAXP / PIPEMAXP */
@@ -271,8 +272,12 @@ static int usbhsh_pipe_attach(struct usbhsh_hpriv *hpriv,
        /********************  spin lock ********************/
        usbhs_lock(priv, flags);
 
-       if (unlikely(usbhsh_uep_to_pipe(uep))) {
-               dev_err(dev, "uep already has pipe\n");
+       /*
+        * if uep has been attached to pipe,
+        * reuse it
+        */
+       if (usbhsh_uep_to_pipe(uep)) {
+               ret = 0;
                goto usbhsh_pipe_attach_done;
        }
 
@@ -320,6 +325,9 @@ static int usbhsh_pipe_attach(struct usbhsh_hpriv *hpriv,
        }
 
 usbhsh_pipe_attach_done:
+       if (0 == ret)
+               uep->counter++;
+
        usbhs_unlock(priv, flags);
        /********************  spin unlock ******************/
 
@@ -346,7 +354,7 @@ static void usbhsh_pipe_detach(struct usbhsh_hpriv *hpriv,
 
        if (unlikely(!pipe)) {
                dev_err(dev, "uep doens't have pipe\n");
-       } else {
+       } else if (1 == uep->counter--) { /* last user */
                struct usb_host_endpoint *ep = usbhsh_uep_to_ep(uep);
                struct usbhsh_device *udev = usbhsh_uep_to_udev(uep);
 
@@ -391,6 +399,7 @@ static int usbhsh_endpoint_attach(struct usbhsh_hpriv *hpriv,
        /*
         * init endpoint
         */
+       uep->counter = 0;
        INIT_LIST_HEAD(&uep->ep_list);
        list_add_tail(&uep->ep_list, &udev->ep_list_head);
 
@@ -686,9 +695,9 @@ static int usbhsh_queue_push(struct usb_hcd *hcd,
        }
 
        if (usb_pipein(urb->pipe))
-               pipe->handler = &usbhs_fifo_pio_pop_handler;
+               pipe->handler = &usbhs_fifo_dma_pop_handler;
        else
-               pipe->handler = &usbhs_fifo_pio_push_handler;
+               pipe->handler = &usbhs_fifo_dma_push_handler;
 
        buf = (void *)(urb->transfer_buffer + urb->actual_length);
        len = urb->transfer_buffer_length - urb->actual_length;
@@ -921,6 +930,19 @@ static int usbhsh_dcp_queue_push(struct usb_hcd *hcd,
  */
 static int usbhsh_dma_map_ctrl(struct usbhs_pkt *pkt, int map)
 {
+       if (map) {
+               struct usbhsh_request *ureq = usbhsh_pkt_to_ureq(pkt);
+               struct urb *urb = ureq->urb;
+
+               /* it can not use scatter/gather */
+               if (urb->num_sgs)
+                       return -EINVAL;
+
+               pkt->dma = urb->transfer_dma;
+               if (!pkt->dma)
+                       return -EINVAL;
+       }
+
        return 0;
 }
 
@@ -946,7 +968,6 @@ static int usbhsh_urb_enqueue(struct usb_hcd *hcd,
        struct usb_host_endpoint *ep = urb->ep;
        struct usbhsh_device *new_udev = NULL;
        int is_dir_in = usb_pipein(urb->pipe);
-       int i;
        int ret;
 
        dev_dbg(dev, "%s (%s)\n", __func__, is_dir_in ? "in" : "out");
@@ -992,13 +1013,7 @@ static int usbhsh_urb_enqueue(struct usb_hcd *hcd,
         * attach pipe to endpoint
         * see [image of mod_host]
         */
-       for (i = 0; i < 1024; i++) {
-               ret = usbhsh_pipe_attach(hpriv, urb);
-               if (ret < 0)
-                       msleep(100);
-               else
-                       break;
-       }
+       ret = usbhsh_pipe_attach(hpriv, urb);
        if (ret < 0) {
                dev_err(dev, "pipe attach failed\n");
                goto usbhsh_urb_enqueue_error_free_endpoint;
@@ -1072,8 +1087,6 @@ static void usbhsh_endpoint_disable(struct usb_hcd *hcd,
 static int usbhsh_hub_status_data(struct usb_hcd *hcd, char *buf)
 {
        struct usbhsh_hpriv *hpriv = usbhsh_hcd_to_hpriv(hcd);
-       struct usbhs_priv *priv = usbhsh_hpriv_to_priv(hpriv);
-       struct device *dev = usbhs_priv_to_dev(priv);
        int roothub_id = 1; /* only 1 root hub */
 
        /*
@@ -1085,8 +1098,6 @@ static int usbhsh_hub_status_data(struct usb_hcd *hcd, char *buf)
        else
                *buf = 0;
 
-       dev_dbg(dev, "%s (%02x)\n", __func__, *buf);
-
        return !!(*buf);
 }
 
index 122526cfd32be21828b7116cfb639ca0abd50583..7926e1c700f1a036abf8dd6592ec33866f00d6a0 100644 (file)
@@ -92,6 +92,82 @@ static void usbhsp_pipe_cfg_set(struct usbhs_pipe *pipe, u16 mask, u16 val)
        __usbhsp_pipe_xxx_set(pipe, DCPCFG, PIPECFG, mask, val);
 }
 
+/*
+ *             PIPEnTRN/PIPEnTRE functions
+ */
+static void usbhsp_pipe_trn_set(struct usbhs_pipe *pipe, u16 mask, u16 val)
+{
+       struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
+       struct device *dev = usbhs_priv_to_dev(priv);
+       int num = usbhs_pipe_number(pipe);
+       u16 reg;
+
+       /*
+        * It is impossible to calculate address,
+        * since PIPEnTRN addresses were mapped randomly.
+        */
+#define CASE_PIPExTRN(a)               \
+       case 0x ## a:                   \
+               reg = PIPE ## a ## TRN; \
+               break;
+
+       switch (num) {
+       CASE_PIPExTRN(1);
+       CASE_PIPExTRN(2);
+       CASE_PIPExTRN(3);
+       CASE_PIPExTRN(4);
+       CASE_PIPExTRN(5);
+       CASE_PIPExTRN(B);
+       CASE_PIPExTRN(C);
+       CASE_PIPExTRN(D);
+       CASE_PIPExTRN(E);
+       CASE_PIPExTRN(F);
+       CASE_PIPExTRN(9);
+       CASE_PIPExTRN(A);
+       default:
+               dev_err(dev, "unknown pipe (%d)\n", num);
+               return;
+       }
+       __usbhsp_pipe_xxx_set(pipe, 0, reg, mask, val);
+}
+
+static void usbhsp_pipe_tre_set(struct usbhs_pipe *pipe, u16 mask, u16 val)
+{
+       struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
+       struct device *dev = usbhs_priv_to_dev(priv);
+       int num = usbhs_pipe_number(pipe);
+       u16 reg;
+
+       /*
+        * It is impossible to calculate address,
+        * since PIPEnTRE addresses were mapped randomly.
+        */
+#define CASE_PIPExTRE(a)                       \
+       case 0x ## a:                           \
+               reg = PIPE ## a ## TRE;         \
+               break;
+
+       switch (num) {
+       CASE_PIPExTRE(1);
+       CASE_PIPExTRE(2);
+       CASE_PIPExTRE(3);
+       CASE_PIPExTRE(4);
+       CASE_PIPExTRE(5);
+       CASE_PIPExTRE(B);
+       CASE_PIPExTRE(C);
+       CASE_PIPExTRE(D);
+       CASE_PIPExTRE(E);
+       CASE_PIPExTRE(F);
+       CASE_PIPExTRE(9);
+       CASE_PIPExTRE(A);
+       default:
+               dev_err(dev, "unknown pipe (%d)\n", num);
+               return;
+       }
+
+       __usbhsp_pipe_xxx_set(pipe, 0, reg, mask, val);
+}
+
 /*
  *             PIPEBUF
  */
@@ -264,6 +340,31 @@ int usbhs_pipe_is_stall(struct usbhs_pipe *pipe)
        return (int)(pid == PID_STALL10 || pid == PID_STALL11);
 }
 
+void usbhs_pipe_set_trans_count_if_bulk(struct usbhs_pipe *pipe, int len)
+{
+       if (!usbhs_pipe_type_is(pipe, USB_ENDPOINT_XFER_BULK))
+               return;
+
+       /*
+        * clear and disable transfer counter for IN/OUT pipe
+        */
+       usbhsp_pipe_tre_set(pipe, TRCLR | TRENB, TRCLR);
+
+       /*
+        * Only IN direction bulk pipe can use transfer count.
+        * Without using this function,
+        * received data will break if it was large data size.
+        * see PIPEnTRN/PIPEnTRE for detail
+        */
+       if (usbhs_pipe_is_dir_in(pipe)) {
+               int maxp = usbhs_pipe_get_maxpacket(pipe);
+
+               usbhsp_pipe_trn_set(pipe, 0xffff, DIV_ROUND_UP(len, maxp));
+               usbhsp_pipe_tre_set(pipe, TRENB, TRENB); /* enable */
+       }
+}
+
+
 /*
  *             pipe setup
  */
index 3d80c7b1fd1b4ba15133e2ffcd3c5db7be2e9933..b476fde955bf0ca71c4fb952565506c4f6aecb17 100644 (file)
@@ -88,6 +88,7 @@ void usbhs_pipe_enable(struct usbhs_pipe *pipe);
 void usbhs_pipe_disable(struct usbhs_pipe *pipe);
 void usbhs_pipe_stall(struct usbhs_pipe *pipe);
 int usbhs_pipe_is_stall(struct usbhs_pipe *pipe);
+void usbhs_pipe_set_trans_count_if_bulk(struct usbhs_pipe *pipe, int len);
 void usbhs_pipe_select_fifo(struct usbhs_pipe *pipe, struct usbhs_fifo *fifo);
 void usbhs_pipe_config_update(struct usbhs_pipe *pipe, u16 devsel,
                              u16 epnum, u16 maxp);
index 54e1bb6372e766dbf4a0eb3583545bfa94689c18..6d110a3bc7e7675a56a59ff7ee64a41834426b0c 100644 (file)
 #define THROTTLED              0x01
 #define ACTUALLY_THROTTLED     0x02
 
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v2.0"
 #define DRIVER_AUTHOR "Naranjo, Manuel Francisco <naranjo.manuel@gmail.com>, Johan Hovold <jhovold@gmail.com>"
 #define DRIVER_DESC "AIRcable USB Driver"
 
@@ -192,5 +188,4 @@ module_usb_serial_driver(serial_drivers, id_table);
 
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_VERSION(DRIVER_VERSION);
 MODULE_LICENSE("GPL");
index bd50a8a41a0f583a589c06586d09765ae2c13a27..a88882c0e2376283a015d38732096472a50fb5f7 100644 (file)
 #include <linux/mutex.h>
 #include <linux/spinlock.h>
 
-/*
- * Version information
- */
-
-#define DRIVER_VERSION "v0.7"
 #define DRIVER_AUTHOR "Bart Hartgers <bart.hartgers+ark3116@gmail.com>"
 #define DRIVER_DESC "USB ARK3116 serial/IrDA driver"
 #define DRIVER_DEV_DESC "ARK3116 RS232/IrDA"
index ea29556f0d7222a87475afa34e6fe683f6b4e513..b72a4c1667055b7881f9ec8513006f36029628cb 100644 (file)
 #include <linux/usb/serial.h>
 #include "belkin_sa.h"
 
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v1.3"
 #define DRIVER_AUTHOR "William Greathouse <wgreathouse@smva.com>"
 #define DRIVER_DESC "USB Belkin Serial converter driver"
 
@@ -509,5 +505,4 @@ module_usb_serial_driver(serial_drivers, id_table);
 
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_VERSION(DRIVER_VERSION);
 MODULE_LICENSE("GPL");
index eb033fc92a156bf3c8f43e94a248ead38f695642..2858d8a9eac8e7a3ebe6c18d62ad1ae6070a1287 100644 (file)
 #include <linux/uaccess.h>
 #include <linux/usb/serial.h>
 
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v0.09"
 #define DRIVER_DESC "Silicon Labs CP210x RS232 serial adaptor driver"
 
 /*
@@ -35,8 +31,7 @@
  */
 static int cp210x_open(struct tty_struct *tty, struct usb_serial_port *);
 static void cp210x_close(struct usb_serial_port *);
-static void cp210x_get_termios(struct tty_struct *,
-       struct usb_serial_port *port);
+static void cp210x_get_termios(struct tty_struct *, struct usb_serial_port *);
 static void cp210x_get_termios_port(struct usb_serial_port *port,
        unsigned int *cflagp, unsigned int *baudp);
 static void cp210x_change_speed(struct tty_struct *, struct usb_serial_port *,
@@ -169,7 +164,7 @@ struct cp210x_serial_private {
 static struct usb_serial_driver cp210x_device = {
        .driver = {
                .owner =        THIS_MODULE,
-               .name =         "cp210x",
+               .name =         "cp210x",
        },
        .id_table               = id_table,
        .num_ports              = 1,
@@ -179,7 +174,7 @@ static struct usb_serial_driver cp210x_device = {
        .close                  = cp210x_close,
        .break_ctl              = cp210x_break_ctl,
        .set_termios            = cp210x_set_termios,
-       .tiocmget               = cp210x_tiocmget,
+       .tiocmget               = cp210x_tiocmget,
        .tiocmset               = cp210x_tiocmset,
        .attach                 = cp210x_startup,
        .release                = cp210x_release,
@@ -281,7 +276,7 @@ static int cp210x_get_config(struct usb_serial_port *port, u8 request,
        int result, i, length;
 
        /* Number of integers required to contain the array */
-       length = (((size - 1) | 3) + 1)/4;
+       length = (((size - 1) | 3) + 1) / 4;
 
        buf = kcalloc(length, sizeof(__le32), GFP_KERNEL);
        if (!buf) {
@@ -328,12 +323,11 @@ static int cp210x_set_config(struct usb_serial_port *port, u8 request,
        int result, i, length;
 
        /* Number of integers required to contain the array */
-       length = (((size - 1) | 3) + 1)/4;
+       length = (((size - 1) | 3) + 1) / 4;
 
        buf = kmalloc(length * sizeof(__le32), GFP_KERNEL);
        if (!buf) {
-               dev_err(&port->dev, "%s - out of memory.\n",
-                               __func__);
+               dev_err(&port->dev, "%s - out of memory.\n", __func__);
                return -ENOMEM;
        }
 
@@ -384,7 +378,8 @@ static inline int cp210x_set_config_single(struct usb_serial_port *port,
  * cp210x_quantise_baudrate
  * Quantises the baud rate as per AN205 Table 1
  */
-static unsigned int cp210x_quantise_baudrate(unsigned int baud) {
+static unsigned int cp210x_quantise_baudrate(unsigned int baud)
+{
        if (baud <= 300)
                baud = 300;
        else if (baud <= 600)      baud = 600;
@@ -467,9 +462,7 @@ static void cp210x_get_termios(struct tty_struct *tty,
                cp210x_get_termios_port(tty->driver_data,
                        &tty->termios.c_cflag, &baud);
                tty_encode_baud_rate(tty, baud, baud);
-       }
-
-       else {
+       } else {
                unsigned int cflag;
                cflag = 0;
                cp210x_get_termios_port(port, &cflag, &baud);
@@ -693,8 +686,8 @@ static void cp210x_set_termios(struct tty_struct *tty,
                        break;*/
                default:
                        dev_dbg(dev, "cp210x driver does not support the number of bits requested, using 8 bit mode\n");
-                               bits |= BITS_DATA_8;
-                               break;
+                       bits |= BITS_DATA_8;
+                       break;
                }
                if (cp210x_set_config(port, CP210X_SET_LINE_CTL, &bits, 2))
                        dev_dbg(dev, "Number of data bits requested not supported by device\n");
@@ -767,7 +760,7 @@ static void cp210x_set_termios(struct tty_struct *tty,
 
 }
 
-static int cp210x_tiocmset (struct tty_struct *tty,
+static int cp210x_tiocmset(struct tty_struct *tty,
                unsigned int set, unsigned int clear)
 {
        struct usb_serial_port *port = tty->driver_data;
@@ -809,7 +802,7 @@ static void cp210x_dtr_rts(struct usb_serial_port *p, int on)
                cp210x_tiocmset_port(p, 0, TIOCM_DTR|TIOCM_RTS);
 }
 
-static int cp210x_tiocmget (struct tty_struct *tty)
+static int cp210x_tiocmget(struct tty_struct *tty)
 {
        struct usb_serial_port *port = tty->driver_data;
        unsigned int control;
@@ -829,7 +822,7 @@ static int cp210x_tiocmget (struct tty_struct *tty)
        return result;
 }
 
-static void cp210x_break_ctl (struct tty_struct *tty, int break_state)
+static void cp210x_break_ctl(struct tty_struct *tty, int break_state)
 {
        struct usb_serial_port *port = tty->driver_data;
        unsigned int state;
@@ -874,5 +867,4 @@ static void cp210x_release(struct usb_serial *serial)
 module_usb_serial_driver(serial_drivers, id_table);
 
 MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_VERSION(DRIVER_VERSION);
 MODULE_LICENSE("GPL");
index 4ee77dcbe690dc73e95f79ebf2d3d75e2784326b..69a4fa1cee25b4cdcf7cb8673e7b5b21548a9913 100644 (file)
 
 #define CYBERJACK_LOCAL_BUF_SIZE 32
 
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v1.01"
 #define DRIVER_AUTHOR "Matthias Bruestle"
 #define DRIVER_DESC "REINER SCT cyberJack pinpad/e-com USB Chipcard Reader Driver"
 
@@ -441,5 +437,4 @@ module_usb_serial_driver(serial_drivers, id_table);
 
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_VERSION(DRIVER_VERSION);
 MODULE_LICENSE("GPL");
index f0da1279c11410ece644a5fd4f4cf9e4532588c8..fd8c35fd452e168b1fc6a948c9d5819e1625a386 100644 (file)
@@ -50,10 +50,6 @@ static bool stats;
 static int interval;
 static bool unstable_bauds;
 
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v1.10"
 #define DRIVER_AUTHOR "Lonnie Mendez <dignome@gmail.com>, Neil Whelchel <koyama@firstlight.net>"
 #define DRIVER_DESC "Cypress USB to Serial Driver"
 
@@ -1303,7 +1299,6 @@ module_usb_serial_driver(serial_drivers, id_table_combined);
 
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_VERSION(DRIVER_VERSION);
 MODULE_LICENSE("GPL");
 
 module_param(stats, bool, S_IRUGO | S_IWUSR);
index b50fa1c6d885be8df8d5675edbedc6637fb9c33f..45d4af62967ff239fa2894d52318c75ada2a4f83 100644 (file)
 
 /* Defines */
 
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v1.80.1.2"
 #define DRIVER_AUTHOR "Peter Berger <pberger@brimson.com>, Al Borchers <borchers@steinerpoint.com>"
 #define DRIVER_DESC "Digi AccelePort USB-2/USB-4 Serial Converter driver"
 
index 43ede4a1e12c3aeada37bb775cdc543cce152207..0f658618db13c84a5ccef1d225047604c76b7a95 100644 (file)
 #include <linux/usb.h>
 #include <linux/usb/serial.h>
 
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v1.3"
 #define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>, Gary Brubaker <xavyer@ix.netcom.com>"
 #define DRIVER_DESC "USB Empeg Mark I/II Driver"
 
index be845873e23dba98fc306fecceb71a672a2c7d74..8c3379b52f242b0feca6a93204e5a9cd2c1e94c4 100644 (file)
@@ -73,7 +73,6 @@ struct ftdi_private {
        char prev_status;        /* Used for TIOCMIWAIT */
        bool dev_gone;        /* Used to abort TIOCMIWAIT */
        char transmit_empty;    /* If transmitter is empty or not */
-       struct usb_serial_port *port;
        __u16 interface;        /* FT2232C, FT2232H or FT4232H port interface
                                   (0 for FT232/245) */
 
@@ -923,6 +922,9 @@ static int ftdi_get_icount(struct tty_struct *tty,
 static int  ftdi_ioctl(struct tty_struct *tty,
                        unsigned int cmd, unsigned long arg);
 static void ftdi_break_ctl(struct tty_struct *tty, int break_state);
+static int ftdi_chars_in_buffer(struct tty_struct *tty);
+static int ftdi_get_modem_status(struct tty_struct *tty,
+                                               unsigned char status[2]);
 
 static unsigned short int ftdi_232am_baud_base_to_divisor(int baud, int base);
 static unsigned short int ftdi_232am_baud_to_divisor(int baud);
@@ -957,6 +959,7 @@ static struct usb_serial_driver ftdi_sio_device = {
        .ioctl =                ftdi_ioctl,
        .set_termios =          ftdi_set_termios,
        .break_ctl =            ftdi_break_ctl,
+       .chars_in_buffer =      ftdi_chars_in_buffer,
 };
 
 static struct usb_serial_driver * const serial_drivers[] = {
@@ -1090,6 +1093,7 @@ static int update_mctrl(struct usb_serial_port *port, unsigned int set,
                        __func__,
                        (set & TIOCM_DTR) ? "HIGH" : (clear & TIOCM_DTR) ? "LOW" : "unchanged",
                        (set & TIOCM_RTS) ? "HIGH" : (clear & TIOCM_RTS) ? "LOW" : "unchanged");
+               rv = usb_translate_errors(rv);
        } else {
                dev_dbg(dev, "%s - DTR %s, RTS %s\n", __func__,
                        (set & TIOCM_DTR) ? "HIGH" : (clear & TIOCM_DTR) ? "LOW" : "unchanged",
@@ -1682,7 +1686,6 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port)
 
        kref_init(&priv->kref);
        mutex_init(&priv->cfg_lock);
-       memset(&priv->icount, 0x00, sizeof(priv->icount));
        init_waitqueue_head(&priv->delta_msr_wait);
 
        priv->flags = ASYNC_LOW_LATENCY;
@@ -1691,7 +1694,6 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port)
        if (quirk && quirk->port_probe)
                quirk->port_probe(priv);
 
-       priv->port = port;
        usb_set_serial_port_data(port, priv);
 
        ftdi_determine_type(port);
@@ -2089,6 +2091,29 @@ static void ftdi_break_ctl(struct tty_struct *tty, int break_state)
 
 }
 
+static int ftdi_chars_in_buffer(struct tty_struct *tty)
+{
+       struct usb_serial_port *port = tty->driver_data;
+       int chars;
+       unsigned char buf[2];
+       int ret;
+
+       chars = usb_serial_generic_chars_in_buffer(tty);
+       if (chars)
+               goto out;
+
+       /* Check if hardware buffer is empty. */
+       ret = ftdi_get_modem_status(tty, buf);
+       if (ret == 2) {
+               if (!(buf[1] & FTDI_RS_TEMT))
+                       chars = 1;
+       }
+out:
+       dev_dbg(&port->dev, "%s - %d\n", __func__, chars);
+
+       return chars;
+}
+
 /* old_termios contains the original termios settings and tty->termios contains
  * the new setting to be used
  * WARNING: set_termios calls this with old_termios in kernel space
@@ -2272,7 +2297,14 @@ no_c_cflag_changes:
        }
 }
 
-static int ftdi_tiocmget(struct tty_struct *tty)
+/*
+ * Get modem-control status.
+ *
+ * Returns the number of status bytes retrieved (device dependant), or
+ * negative error code.
+ */
+static int ftdi_get_modem_status(struct tty_struct *tty,
+                                               unsigned char status[2])
 {
        struct usb_serial_port *port = tty->driver_data;
        struct ftdi_private *priv = usb_get_serial_port_data(port);
@@ -2312,16 +2344,43 @@ static int ftdi_tiocmget(struct tty_struct *tty)
                        FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE,
                        0, priv->interface,
                        buf, len, WDR_TIMEOUT);
-       if (ret < 0)
+       if (ret < 0) {
+               dev_err(&port->dev, "failed to get modem status: %d\n", ret);
+               ret = usb_translate_errors(ret);
                goto out;
+       }
 
-       ret = (buf[0] & FTDI_SIO_DSR_MASK ? TIOCM_DSR : 0) |
-               (buf[0] & FTDI_SIO_CTS_MASK ? TIOCM_CTS : 0) |
-               (buf[0]  & FTDI_SIO_RI_MASK  ? TIOCM_RI  : 0) |
-               (buf[0]  & FTDI_SIO_RLSD_MASK ? TIOCM_CD  : 0) |
-               priv->last_dtr_rts;
+       status[0] = buf[0];
+       if (ret > 1)
+               status[1] = buf[1];
+       else
+               status[1] = 0;
+
+       dev_dbg(&port->dev, "%s - 0x%02x%02x\n", __func__, status[0],
+                                                               status[1]);
 out:
        kfree(buf);
+
+       return ret;
+}
+
+static int ftdi_tiocmget(struct tty_struct *tty)
+{
+       struct usb_serial_port *port = tty->driver_data;
+       struct ftdi_private *priv = usb_get_serial_port_data(port);
+       unsigned char buf[2];
+       int ret;
+
+       ret = ftdi_get_modem_status(tty, buf);
+       if (ret < 0)
+               return ret;
+
+       ret =   (buf[0] & FTDI_SIO_DSR_MASK  ? TIOCM_DSR : 0) |
+               (buf[0] & FTDI_SIO_CTS_MASK  ? TIOCM_CTS : 0) |
+               (buf[0] & FTDI_SIO_RI_MASK   ? TIOCM_RI  : 0) |
+               (buf[0] & FTDI_SIO_RLSD_MASK ? TIOCM_CD  : 0) |
+               priv->last_dtr_rts;
+
        return ret;
 }
 
index 296612153ea20ca5bac102b9b98716e4bb7e2cdb..2ea70a631996f0fd856159a68392cb209d7a3134 100644 (file)
@@ -262,6 +262,7 @@ int usb_serial_generic_chars_in_buffer(struct tty_struct *tty)
        dev_dbg(&port->dev, "%s - returns %d\n", __func__, chars);
        return chars;
 }
+EXPORT_SYMBOL_GPL(usb_serial_generic_chars_in_buffer);
 
 static int usb_serial_generic_submit_read_urb(struct usb_serial_port *port,
                                                int index, gfp_t mem_flags)
index 0bbaf21a9d1ef2d30508e13ca94b5d4fbbac0243..2cba60d90c7983222b956302b5d142da64195448 100644 (file)
 #include <linux/usb.h>
 #include <linux/usb/serial.h>
 
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v1.00"
 #define DRIVER_DESC "HP4x (48/49) Generic Serial driver"
 
 #define HP_VENDOR_ID 0x03f0
@@ -52,5 +48,4 @@ static struct usb_serial_driver * const serial_drivers[] = {
 module_usb_serial_driver(serial_drivers, id_table);
 
 MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_VERSION(DRIVER_VERSION);
 MODULE_LICENSE("GPL");
index 5acc0d13864a400344a012400f20bc989fa23574..7b770c7f8b1165fa0a1e23fb5616137a49a72c66 100644 (file)
 #include "io_ionsp.h"          /* info for the iosp messages */
 #include "io_16654.h"          /* 16654 UART defines */
 
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v2.7"
 #define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com> and David Iacovelli"
 #define DRIVER_DESC "Edgeport USB Serial Driver"
 
index 60023c2d2a317008d7aab0c78bd5120f77b1597c..58184f3de6867bfa9ebbbc6d6afbe074d80a8f12 100644 (file)
 #include "io_usbvend.h"
 #include "io_ti.h"
 
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v0.7mode043006"
 #define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com> and David Iacovelli"
 #define DRIVER_DESC "Edgeport USB Serial Driver"
 
index 1068bf22e27e6d3b7dcd42259a8b0967af3b1674..76c9a847da5dd0b3c0e9c7b2e435b897e20f2ed7 100644 (file)
 
 #define KP_RETRIES     100
 
-/*
- * Version Information
- */
-
-#define DRIVER_VERSION "v1.0"
 #define DRIVER_AUTHOR "Ganesh Varadarajan <ganesh@veritas.com>"
 #define DRIVER_DESC "USB PocketPC PDA driver"
 
index 4264821a3b34fb653d28dafe2171e6b9239ca8e5..155eab14b30ed575083e1fc8d4d681374063df01 100644 (file)
 #include <linux/uaccess.h>
 #include "usb-wwan.h"
 
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v0.4"
 #define DRIVER_AUTHOR  "Roelf Diedericks"
 #define DRIVER_DESC    "IPWireless tty driver"
 
index cd5533e81de7e113d77898795996346ce036378a..1e1fbed65ef244a80f3a2c41d3a117f67eb6c014 100644 (file)
 #include "iuu_phoenix.h"
 #include <linux/random.h>
 
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v0.12"
 #define DRIVER_DESC "Infinity USB Unlimited Phoenix driver"
 
 static const struct usb_device_id id_table[] = {
@@ -1164,7 +1160,7 @@ static ssize_t store_vcc_mode(struct device *dev,
        struct iuu_private *priv = usb_get_serial_port_data(port);
        unsigned long v;
 
-       if (strict_strtoul(buf, 10, &v)) {
+       if (kstrtoul(buf, 10, &v)) {
                dev_err(dev, "%s - vcc_mode: %s is not a unsigned long\n",
                                __func__, buf);
                goto fail_store_vcc_mode;
@@ -1232,8 +1228,6 @@ MODULE_AUTHOR("Alain Degreffe eczema@ecze.com");
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
-MODULE_VERSION(DRIVER_VERSION);
-
 module_param(xmas, bool, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(xmas, "Xmas colors enabled or not");
 
index 7179b0c5f8148e183219b2a71c34d6d7bf7494a6..991ca6a690a0747f676d1e58cd350fa1dac6aeb0 100644 (file)
 #include <linux/usb/ezusb.h>
 #include "keyspan.h"
 
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v1.1.5"
 #define DRIVER_AUTHOR "Hugh Blemings <hugh@misc.nu"
 #define DRIVER_DESC "Keyspan USB to Serial Converter Driver"
 
index bb87e29c4ac29645804b05a9e52455f8125ff05c..41b01092af072265e2fd5618ecd4e97b162059d5 100644 (file)
        #undef XIRCOM
 #endif
 
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v1.1"
 #define DRIVER_AUTHOR "Brian Warner <warner@lothar.com>"
 #define DRIVER_DESC "USB Keyspan PDA Converter driver"
 
index 1f4517864cd25cd6bdf665bce9d154f0c708f99d..fc9e14a1e9b31404be20118dcbc34bd0909dd44b 100644 (file)
 #include <linux/usb/serial.h>
 #include "kl5kusb105.h"
 
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v0.4"
 #define DRIVER_AUTHOR "Utz-Uwe Haus <haus@uuhaus.de>, Johan Hovold <jhovold@gmail.com>"
 #define DRIVER_DESC "KLSI KL5KUSB105 chipset USB->Serial Converter driver"
 
index c9ca7a5b12e09c883f08562ca93a8fbede32e82b..b747ba615d0bc4b5d9611fa33413b5348b74b362 100644 (file)
@@ -38,8 +38,6 @@
 #include <linux/ioctl.h>
 #include "kobil_sct.h"
 
-/* Version Information */
-#define DRIVER_VERSION "21/05/2004"
 #define DRIVER_AUTHOR "KOBIL Systems GmbH - http://www.kobil.com"
 #define DRIVER_DESC "KOBIL USB Smart Card Terminal Driver (experimental)"
 
index 8a2081004107977dc929d586ffda41fdf34abf06..b6911757c855b6802d82c126ce60f778d5b0f8db 100644 (file)
 #include <linux/ioctl.h>
 #include "mct_u232.h"
 
-/*
- * Version Information
- */
-#define DRIVER_VERSION "z2.1"          /* Linux in-kernel version */
 #define DRIVER_AUTHOR "Wolfgang Grandegger <wolfgang@ces.ch>"
 #define DRIVER_DESC "Magic Control Technology USB-RS232 converter driver"
 
index 6f29c74eb76925098a9cab841142c955c6d3a725..3d258448c29af70e03fbbe91f8215a7e988b8aae 100644 (file)
@@ -20,8 +20,6 @@
 #include <linux/uaccess.h>
 #include <linux/usb/serial.h>
 
-/* Version Information */
-#define DRIVER_VERSION "v1.2.0.0"
 #define DRIVER_DESC "Metrologic Instruments Inc. - USB-POS driver"
 
 /* Product information. */
index 75267421aad85636d480b732a507a176e874814f..f57a6b1fe7879ec9898bf5110d5e11364196fbee 100644 (file)
 #include <linux/uaccess.h>
 #include <linux/parport.h>
 
-/*
- * Version Information
- */
-#define DRIVER_VERSION "2.1"
 #define DRIVER_AUTHOR "Aspire Communications pvt Ltd."
 #define DRIVER_DESC "Moschip USB Serial Driver"
 
index 1cf3375ec1afb12fbea2314a63539ced2c36b221..66d9e088d9d91e250e630e0f29747f5382194e93 100644 (file)
 #include <linux/usb/serial.h>
 #include <linux/uaccess.h>
 
-/*
- * Version Information
- */
-#define DRIVER_VERSION "1.3.2"
 #define DRIVER_DESC "Moschip 7840/7820 USB Serial Driver"
 
 /*
index 9ab73d2957746d49292357382f7a081faa25cd55..7818af931a48fcbb1c5ed77e77dd26b438137c8a 100644 (file)
 #include <linux/usb.h>
 #include <linux/usb/serial.h>
 
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v1.1"
 #define DRIVER_AUTHOR "Alessandro Zummo"
 #define DRIVER_DESC "USB ZyXEL omni.net LCD PLUS Driver"
 
index 5dee7d61241e2269d6453a0c5693af3a354e8a0e..5839f4d662dc142372dd15383e3ae59b949174ca 100644 (file)
@@ -28,7 +28,6 @@
   device features.
 */
 
-#define DRIVER_VERSION "v0.7.2"
 #define DRIVER_AUTHOR "Matthias Urlichs <smurf@smurf.noris.de>"
 #define DRIVER_DESC "USB Driver for GSM modems"
 
@@ -733,23 +732,23 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_620UW) },
        { USB_DEVICE(AXESSTEL_VENDOR_ID, AXESSTEL_PRODUCT_MV110H) },
        { USB_DEVICE(YISO_VENDOR_ID, YISO_PRODUCT_U893) },
-       { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_C100_1) },
-       { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_C100_2) },
-       { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1004) },
-       { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1005) },
-       { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1006) },
-       { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1007) },
-       { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1008) },
-       { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1009) },
-       { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100A) },
-       { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100B) },
-       { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100C) },
-       { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100D) },
-       { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100E) },
-       { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100F) },
-       { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1010) },
-       { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1011) },
-       { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1012) },
+       { USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_C100_1, 0xff) },
+       { USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_C100_2, 0xff) },
+       { USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1004, 0xff) },
+       { USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1005, 0xff) },
+       { USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1006, 0xff) },
+       { USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1007, 0xff) },
+       { USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1008, 0xff) },
+       { USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1009, 0xff) },
+       { USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100A, 0xff) },
+       { USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100B, 0xff) },
+       { USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100C, 0xff) },
+       { USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100D, 0xff) },
+       { USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100E, 0xff) },
+       { USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100F, 0xff) },
+       { USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1010, 0xff) },
+       { USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1011, 0xff) },
+       { USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1012, 0xff) },
        { USB_DEVICE(KYOCERA_VENDOR_ID, KYOCERA_PRODUCT_KPC650) },
        { USB_DEVICE(KYOCERA_VENDOR_ID, KYOCERA_PRODUCT_KPC680) },
        { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6000)}, /* ZTE AC8700 */
@@ -1165,22 +1164,22 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE(LONGCHEER_VENDOR_ID, ZOOM_PRODUCT_4597) },
        { USB_DEVICE(HAIER_VENDOR_ID, HAIER_PRODUCT_CE100) },
        /* Pirelli  */
-       { USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_C100_1)},
-       { USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_C100_2)},
-       { USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1004)},
-       { USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1005)},
-       { USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1006)},
-       { USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1007)},
-       { USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1008)},
-       { USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1009)},
-       { USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100A)},
-       { USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100B) },
-       { USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100C) },
-       { USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100D) },
-       { USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100E) },
-       { USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100F) },
-       { USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1011)},
-       { USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1012)},
+       { USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_C100_1, 0xff) },
+       { USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_C100_2, 0xff) },
+       { USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1004, 0xff) },
+       { USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1005, 0xff) },
+       { USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1006, 0xff) },
+       { USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1007, 0xff) },
+       { USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1008, 0xff) },
+       { USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1009, 0xff) },
+       { USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100A, 0xff) },
+       { USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100B, 0xff) },
+       { USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100C, 0xff) },
+       { USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100D, 0xff) },
+       { USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100E, 0xff) },
+       { USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100F, 0xff) },
+       { USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1011, 0xff) },
+       { USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1012, 0xff) },
        /* Cinterion */
        { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_EU3_E) },
        { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_EU3_P) },
@@ -1341,20 +1340,10 @@ static int option_probe(struct usb_serial *serial,
                                &serial->interface->cur_altsetting->desc;
        struct usb_device_descriptor *dev_desc = &serial->dev->descriptor;
 
-       /*
-        * D-Link DWM 652 still exposes CD-Rom emulation interface in modem
-        * mode.
-        */
-       if (dev_desc->idVendor == DLINK_VENDOR_ID &&
-               dev_desc->idProduct == DLINK_PRODUCT_DWM_652 &&
-               iface_desc->bInterfaceClass == 0x08)
+       /* Never bind to the CD-Rom emulation interface */
+       if (iface_desc->bInterfaceClass == 0x08)
                return -ENODEV;
 
-       /* Bandrich modem and AT command interface is 0xff */
-       if ((dev_desc->idVendor == BANDRICH_VENDOR_ID ||
-               dev_desc->idVendor == PIRELLI_VENDOR_ID) &&
-               iface_desc->bInterfaceClass != 0xff)
-               return -ENODEV;
        /*
         * Don't bind reserved interfaces (like network ones) which often have
         * the same class/subclass/protocol as the serial interfaces.  Look at
@@ -1369,9 +1358,9 @@ static int option_probe(struct usb_serial *serial,
         * Don't bind network interface on Samsung GT-B3730, it is handled by
         * a separate module.
         */
-       if (dev_desc->idVendor == SAMSUNG_VENDOR_ID &&
-               dev_desc->idProduct == SAMSUNG_PRODUCT_GT_B3730 &&
-               iface_desc->bInterfaceClass != USB_CLASS_CDC_DATA)
+       if (dev_desc->idVendor == cpu_to_le16(SAMSUNG_VENDOR_ID) &&
+           dev_desc->idProduct == cpu_to_le16(SAMSUNG_PRODUCT_GT_B3730) &&
+           iface_desc->bInterfaceClass != USB_CLASS_CDC_DATA)
                return -ENODEV;
 
        /* Store device id so we can use it during attach. */
@@ -1509,5 +1498,4 @@ static int option_send_setup(struct usb_serial_port *port)
 
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_VERSION(DRIVER_VERSION);
 MODULE_LICENSE("GPL");
index cee9a52ca891cd0857b324fba5f99933b03771f0..d217fd6ee43ffab5601083fc662bd599e5f26e81 100644 (file)
@@ -57,7 +57,6 @@
 #define OTI6858_DESCRIPTION \
        "Ours Technology Inc. OTi-6858 USB to serial adapter driver"
 #define OTI6858_AUTHOR "Tomasz Michal Lukaszewski <FIXME@FIXME>"
-#define OTI6858_VERSION "0.2"
 
 static const struct usb_device_id id_table[] = {
        { USB_DEVICE(OTI6858_VENDOR_ID, OTI6858_PRODUCT_ID) },
@@ -899,5 +898,4 @@ module_usb_serial_driver(serial_drivers, id_table);
 
 MODULE_DESCRIPTION(OTI6858_DESCRIPTION);
 MODULE_AUTHOR(OTI6858_AUTHOR);
-MODULE_VERSION(OTI6858_VERSION);
 MODULE_LICENSE("GPL");
index ffcfc962ab10b5a4043cd900f8ca6e90094ff417..d152be97d041b61727df4648fa8918e5eff10a23 100644 (file)
@@ -65,8 +65,6 @@
 #define QT2_WRITE_BUFFER_SIZE   512  /* size of write buffer */
 #define QT2_WRITE_CONTROL_SIZE  5    /* control bytes used for a write */
 
-/* Version Information */
-#define DRIVER_VERSION "v0.1"
 #define DRIVER_DESC "Quatech 2nd gen USB to Serial Driver"
 
 #define        USB_VENDOR_ID_QUATECH   0x061d
index e4a1787cdbac3d4c475a1e468a64cd5bdacdc954..a76b1ae54a2a3cc917a37d3e299d654734760b14 100644 (file)
@@ -16,8 +16,6 @@
 #include <linux/usb.h>
 #include <linux/usb/serial.h>
 
-/* Version Information */
-#define DRIVER_VERSION "Version 0.1 09/26/2005"
 #define DRIVER_AUTHOR "Thomas Hergenhahn@web.de http://libnodave.sf.net"
 #define DRIVER_DESC "Driver for Siemens USB/MPI adapter"
 
index 270860f6bb2aee0a97f2091c7c33041332cccc1e..af06f2f5f38b36f1b11976429cec35cd92ddb9b5 100644 (file)
@@ -18,7 +18,7 @@
 */
 /* Uncomment to log function calls */
 /* #define DEBUG */
-#define DRIVER_VERSION "v.1.7.16"
+
 #define DRIVER_AUTHOR "Kevin Lloyd, Elina Pasheva, Matthew Safar, Rory Filer"
 #define DRIVER_DESC "USB Driver for Sierra Wireless USB modems"
 
@@ -1078,7 +1078,6 @@ module_usb_serial_driver(serial_drivers, id_table);
 
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_VERSION(DRIVER_VERSION);
 MODULE_LICENSE("GPL");
 
 module_param(nmea, bool, S_IRUGO | S_IWUSR);
index 769c137f8975689fd9a798e12fda23bf27036728..a42536af1256afd47352e3ee2de2165ff4312232 100644 (file)
@@ -28,9 +28,6 @@
 #include <linux/usb.h>
 #include <linux/usb/serial.h>
 
-
-/* Version Information */
-#define DRIVER_VERSION "v0.10"
 #define DRIVER_DESC    "SPCP8x5 USB to serial adaptor driver"
 
 #define SPCP8x5_007_VID                0x04FC
@@ -651,5 +648,4 @@ static struct usb_serial_driver * const serial_drivers[] = {
 module_usb_serial_driver(serial_drivers, id_table);
 
 MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_VERSION(DRIVER_VERSION);
 MODULE_LICENSE("GPL");
index 868d1e6852e2ab6086a354cd62a352a241cb51c7..4543ea35022939976886dc576b7e6c1f2d37584c 100644 (file)
@@ -46,8 +46,6 @@
 #define FULLPWRBIT          0x00000080
 #define NEXT_BOARD_POWER_BIT        0x00000004
 
-/* Version Information */
-#define DRIVER_VERSION "v0.1"
 #define DRIVER_DESC "Quatech SSU-100 USB to Serial Driver"
 
 #define        USB_VENDOR_ID_QUATECH   0x061d  /* Quatech VID */
index 61a73ad1a1877c4558444a34884e236a8352e0d9..2be2b5b639ae1fa2789b00c6e7aafd1bc90f7eb1 100644 (file)
@@ -19,7 +19,6 @@
   - controlling the baud rate doesn't make sense
 */
 
-#define DRIVER_VERSION "v0.7.2"
 #define DRIVER_AUTHOR "Matthias Urlichs <smurf@smurf.noris.de>"
 #define DRIVER_DESC "USB Driver for GSM modems"
 
@@ -710,5 +709,4 @@ EXPORT_SYMBOL(usb_wwan_resume);
 
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_VERSION(DRIVER_VERSION);
 MODULE_LICENSE("GPL");
index 0c0aa876c20938c2ddeb16945201203e38211961..6299526ff8c35080bf1d639514ad371ac0586a9b 100644 (file)
@@ -10,8 +10,6 @@
 #include <linux/usb.h>
 #include <linux/usb/serial.h>
 
-
-#define DRIVER_VERSION "v1.0"
 #define DRIVER_DESC "ViVOpay USB Serial Driver"
 
 #define VIVOPAY_VENDOR_ID 0x1d5f
@@ -42,5 +40,4 @@ module_usb_serial_driver(serial_drivers, id_table);
 
 MODULE_AUTHOR("Forest Bond <forest.bond@outpostembedded.com>");
 MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_VERSION(DRIVER_VERSION);
 MODULE_LICENSE("GPL");
index d36446dd7ae867629258b9051b3c1173cde9641f..ea5f2586fbdd3f9b8279c2d7230a2dbe5f067334 100644 (file)
@@ -455,7 +455,7 @@ static int rts51x_check_status(struct us_data *us, u8 lun)
        u8 buf[16];
 
        retval = rts51x_read_status(us, lun, buf, 16, &(chip->status_len));
-       if (retval < 0)
+       if (retval != STATUS_SUCCESS)
                return -EIO;
 
        US_DEBUGP("chip->status_len = %d\n", chip->status_len);
index 0616f235bd6b512ecf54769cfc346e12180febd7..ce310170829fdc66442a8c7b629fc028152c96af 100644 (file)
@@ -105,20 +105,15 @@ static int skel_open(struct inode *inode, struct file *file)
                goto exit;
        }
 
-       /* increment our usage count for the device */
-       kref_get(&dev->kref);
-
-       /* lock the device to allow correctly handling errors
-        * in resumption */
-       mutex_lock(&dev->io_mutex);
-
        retval = usb_autopm_get_interface(interface);
        if (retval)
-               goto out_err;
+               goto exit;
+
+       /* increment our usage count for the device */
+       kref_get(&dev->kref);
 
        /* save our object in the file's private structure */
        file->private_data = dev;
-       mutex_unlock(&dev->io_mutex);
 
 exit:
        return retval;
index 231009af65a3a05712dfd34d8484a7b0a02da18e..1d365316960cdad1a0a020d6d2757a0e5f73f85e 100644 (file)
@@ -847,19 +847,6 @@ static void wusb_dev_bos_rm(struct wusb_dev *wusb_dev)
        wusb_dev->wusb_cap_descr = NULL;
 };
 
-static struct usb_wireless_cap_descriptor wusb_cap_descr_default = {
-       .bLength = sizeof(wusb_cap_descr_default),
-       .bDescriptorType = USB_DT_DEVICE_CAPABILITY,
-       .bDevCapabilityType = USB_CAP_TYPE_WIRELESS_USB,
-
-       .bmAttributes = USB_WIRELESS_BEACON_NONE,
-       .wPHYRates = cpu_to_le16(USB_WIRELESS_PHY_53),
-       .bmTFITXPowerInfo = 0,
-       .bmFFITXPowerInfo = 0,
-       .bmBandGroup = cpu_to_le16(0x0001),     /* WUSB1.0[7.4.1] bottom */
-       .bReserved = 0
-};
-
 /*
  * USB stack's device addition Notifier Callback
  *
index 82a84d53120f27f2a1734fcef5ab5774d5fbc0a3..5c5b3fc9088a30d25fd526fca9427006e9f9d23e 100644 (file)
@@ -63,7 +63,7 @@ int umc_controller_reset(struct umc_dev *umc)
        struct device *parent = umc->dev.parent;
        int ret = 0;
 
-       if (device_trylock(parent))
+       if (!device_trylock(parent))
                return -EAGAIN;
        ret = device_for_each_child(parent, parent, umc_bus_pre_reset_helper);
        if (ret >= 0)
index 10278d18709cf439d3fc2aeea2b7057f22eee16a..689b14b26c8d84343d8271b87d9aefca00b20904 100644 (file)
@@ -482,6 +482,7 @@ struct usb3_lpm_parameters {
  * @connect_time: time device was first connected
  * @do_remote_wakeup:  remote wakeup should be enabled
  * @reset_resume: needs reset instead of resume
+ * @port_is_suspended: the upstream port is suspended (L2 or U3)
  * @wusb_dev: if this is a Wireless USB device, link to the WUSB
  *     specific data for the device.
  * @slot_id: Slot ID assigned by xHCI
@@ -560,6 +561,7 @@ struct usb_device {
 
        unsigned do_remote_wakeup:1;
        unsigned reset_resume:1;
+       unsigned port_is_suspended:1;
 #endif
        struct wusb_dev *wusb_dev;
        int slot_id;
@@ -588,8 +590,9 @@ extern struct usb_device *usb_hub_find_child(struct usb_device *hdev,
  */
 #define usb_hub_for_each_child(hdev, port1, child) \
        for (port1 = 1, child = usb_hub_find_child(hdev, port1); \
-               port1 <= hdev->maxchild; \
-               child = usb_hub_find_child(hdev, ++port1))
+                       port1 <= hdev->maxchild; \
+                       child = usb_hub_find_child(hdev, ++port1)) \
+               if (!child) continue; else
 
 /* USB device locking */
 #define usb_lock_device(udev)          device_lock(&(udev)->dev)
@@ -804,6 +807,22 @@ static inline int usb_make_path(struct usb_device *dev, char *buf, size_t size)
        .bcdDevice_lo = (lo), \
        .bcdDevice_hi = (hi)
 
+/**
+ * USB_DEVICE_INTERFACE_CLASS - describe a usb device with a specific interface class
+ * @vend: the 16 bit USB Vendor ID
+ * @prod: the 16 bit USB Product ID
+ * @cl: bInterfaceClass value
+ *
+ * This macro is used to create a struct usb_device_id that matches a
+ * specific interface class of devices.
+ */
+#define USB_DEVICE_INTERFACE_CLASS(vend, prod, cl) \
+       .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \
+                      USB_DEVICE_ID_MATCH_INT_CLASS, \
+       .idVendor = (vend), \
+       .idProduct = (prod), \
+       .bInterfaceClass = (cl)
+
 /**
  * USB_DEVICE_INTERFACE_PROTOCOL - describe a usb device with a specific interface protocol
  * @vend: the 16 bit USB Vendor ID
@@ -1129,8 +1148,8 @@ extern int usb_disabled(void);
  * Note: URB_DIR_IN/OUT is automatically set in usb_submit_urb().
  */
 #define URB_SHORT_NOT_OK       0x0001  /* report short reads as errors */
-#define URB_ISO_ASAP           0x0002  /* iso-only, urb->start_frame
-                                        * ignored */
+#define URB_ISO_ASAP           0x0002  /* iso-only; use the first unexpired
+                                        * slot in the schedule */
 #define URB_NO_TRANSFER_DMA_MAP        0x0004  /* urb->transfer_dma valid on submit */
 #define URB_NO_FSBR            0x0020  /* UHCI-specific */
 #define URB_ZERO_PACKET                0x0040  /* Finish bulk OUT with short packet */
@@ -1309,15 +1328,20 @@ typedef void (*usb_complete_t)(struct urb *);
  * the transfer interval in the endpoint descriptor is logarithmic.
  * Device drivers must convert that value to linear units themselves.)
  *
- * Isochronous URBs normally use the URB_ISO_ASAP transfer flag, telling
- * the host controller to schedule the transfer as soon as bandwidth
- * utilization allows, and then set start_frame to reflect the actual frame
- * selected during submission.  Otherwise drivers must specify the start_frame
- * and handle the case where the transfer can't begin then.  However, drivers
- * won't know how bandwidth is currently allocated, and while they can
- * find the current frame using usb_get_current_frame_number () they can't
- * know the range for that frame number.  (Ranges for frame counter values
- * are HC-specific, and can go from 256 to 65536 frames from "now".)
+ * If an isochronous endpoint queue isn't already running, the host
+ * controller will schedule a new URB to start as soon as bandwidth
+ * utilization allows.  If the queue is running then a new URB will be
+ * scheduled to start in the first transfer slot following the end of the
+ * preceding URB, if that slot has not already expired.  If the slot has
+ * expired (which can happen when IRQ delivery is delayed for a long time),
+ * the scheduling behavior depends on the URB_ISO_ASAP flag.  If the flag
+ * is clear then the URB will be scheduled to start in the expired slot,
+ * implying that some of its packets will not be transferred; if the flag
+ * is set then the URB will be scheduled in the first unexpired slot,
+ * breaking the queue's synchronization.  Upon URB completion, the
+ * start_frame field will be set to the (micro)frame number in which the
+ * transfer was scheduled.  Ranges for frame counter values are HC-specific
+ * and can go from as low as 256 to as high as 65536 frames.
  *
  * Isochronous URBs have a different data transfer model, in part because
  * the quality of service is only "best effort".  Callers provide specially
index f8dda0621800db910be2aa51f134a5139daf0243..b09c37e04a91f64f007a0699cf89d3adc1b97483 100644 (file)
@@ -38,6 +38,7 @@
 #include <linux/version.h>
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
+#include <linux/log2.h>
 
 /*
  * USB function drivers should return USB_GADGET_DELAYED_STATUS if they
@@ -51,6 +52,7 @@
 /* big enough to hold our biggest descriptor */
 #define USB_COMP_EP0_BUFSIZ    1024
 
+#define USB_MS_TO_HS_INTERVAL(x)       (ilog2((x * 1000 / 125)) + 1)
 struct usb_configuration;
 
 /**
@@ -117,7 +119,7 @@ struct usb_configuration;
 struct usb_function {
        const char                      *name;
        struct usb_gadget_strings       **strings;
-       struct usb_descriptor_header    **descriptors;
+       struct usb_descriptor_header    **fs_descriptors;
        struct usb_descriptor_header    **hs_descriptors;
        struct usb_descriptor_header    **ss_descriptors;
 
index c9d09f8b7ff2d66579ee58700658667347ef8094..99238b096f7e5ae4647ec49b14d828263853a4b2 100644 (file)
@@ -29,6 +29,8 @@
  *                     initialization.
  * @port_power_off:    set to 1 if the controller needs to be powered down
  *                     after initialization.
+ * @no_io_watchdog:    set to 1 if the controller does not need the I/O
+ *                     watchdog to run.
  *
  * These are general configuration options for the EHCI controller. All of
  * these options are activating more or less workarounds for some hardware.
@@ -39,8 +41,7 @@ struct usb_ehci_pdata {
        unsigned        has_synopsys_hc_bug:1;
        unsigned        big_endian_desc:1;
        unsigned        big_endian_mmio:1;
-       unsigned        port_power_on:1;
-       unsigned        port_power_off:1;
+       unsigned        no_io_watchdog:1;
 
        /* Turn on all power and clocks */
        int (*power_on)(struct platform_device *pdev);
index fc618d8d1e92e845b00f800b86d64a9c2c040408..639ee45779fb381edb59a0ae70e1d5ffe0f90f7f 100644 (file)
@@ -1,16 +1,8 @@
 #ifndef __EZUSB_H
 #define __EZUSB_H
 
-
-extern int ezusb_writememory(struct usb_device *dev, int address,
-                            unsigned char *data, int length, __u8 bRequest);
-
 extern int ezusb_fx1_set_reset(struct usb_device *dev, unsigned char reset_bit);
-extern int ezusb_fx2_set_reset(struct usb_device *dev, unsigned char reset_bit);
-
 extern int ezusb_fx1_ihex_firmware_download(struct usb_device *dev,
                                            const char *firmware_path);
-extern int ezusb_fx2_ihex_firmware_download(struct usb_device *dev,
-                                           const char *firmware_path);
 
 #endif /* __EZUSB_H */
index 5b6e50888248d044c4f9f277165cc5ad7b9a7ad6..0af6569b8cc60778c619f3a059d4b78ff49f07f4 100644 (file)
@@ -939,6 +939,13 @@ static inline void usb_free_descriptors(struct usb_descriptor_header **v)
        kfree(v);
 }
 
+struct usb_function;
+int usb_assign_descriptors(struct usb_function *f,
+               struct usb_descriptor_header **fs,
+               struct usb_descriptor_header **hs,
+               struct usb_descriptor_header **ss);
+void usb_free_all_descriptors(struct usb_function *f);
+
 /*-------------------------------------------------------------------------*/
 
 /* utility to simplify map/unmap of usb_requests to/from DMA */
index 74e7755168b72c3efed2c39e46a39d7eefc5f858..012f2b7eb2b6b299e21596a9e650487759815dfb 100644 (file)
@@ -25,6 +25,7 @@
  * @big_endian_desc:   BE descriptors
  * @big_endian_mmio:   BE registers
  * @no_big_frame_no:   no big endian frame_no shift
+ * @num_ports:         number of ports
  *
  * These are general configuration options for the OHCI controller. All of
  * these options are activating more or less workarounds for some hardware.
@@ -33,6 +34,7 @@ struct usb_ohci_pdata {
        unsigned        big_endian_desc:1;
        unsigned        big_endian_mmio:1;
        unsigned        no_big_frame_no:1;
+       unsigned int    num_ports;
 
        /* Turn on all power and clocks */
        int (*power_on)(struct platform_device *pdev);