summaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/Kconfig25
-rw-r--r--drivers/usb/Makefile4
-rw-r--r--drivers/usb/atm/Kconfig2
-rw-r--r--drivers/usb/atm/usbatm.c6
-rw-r--r--drivers/usb/c67x00/c67x00-sched.c4
-rw-r--r--drivers/usb/chipidea/Makefile2
-rw-r--r--drivers/usb/chipidea/ci.h19
-rw-r--r--drivers/usb/chipidea/ci13xxx_imx.c12
-rw-r--r--drivers/usb/chipidea/ci13xxx_imx.h3
-rw-r--r--drivers/usb/chipidea/ci13xxx_pci.c6
-rw-r--r--drivers/usb/chipidea/core.c66
-rw-r--r--drivers/usb/chipidea/debug.c888
-rw-r--r--drivers/usb/chipidea/debug.h34
-rw-r--r--drivers/usb/chipidea/udc.c299
-rw-r--r--drivers/usb/chipidea/udc.h4
-rw-r--r--drivers/usb/chipidea/usbmisc_imx.c261
-rw-r--r--drivers/usb/chipidea/usbmisc_imx6q.c162
-rw-r--r--drivers/usb/class/Kconfig6
-rw-r--r--drivers/usb/class/cdc-acm.c61
-rw-r--r--drivers/usb/class/cdc-wdm.c42
-rw-r--r--drivers/usb/class/usbtmc.c26
-rw-r--r--drivers/usb/core/Kconfig36
-rw-r--r--drivers/usb/core/devio.c2
-rw-r--r--drivers/usb/core/driver.c25
-rw-r--r--drivers/usb/core/generic.c2
-rw-r--r--drivers/usb/core/hcd-pci.c235
-rw-r--r--drivers/usb/core/hcd.c18
-rw-r--r--drivers/usb/core/hub.c136
-rw-r--r--drivers/usb/core/port.c5
-rw-r--r--drivers/usb/core/quirks.c16
-rw-r--r--drivers/usb/core/sysfs.c4
-rw-r--r--drivers/usb/core/urb.c5
-rw-r--r--drivers/usb/core/usb-acpi.c17
-rw-r--r--drivers/usb/core/usb.c7
-rw-r--r--drivers/usb/core/usb.h2
-rw-r--r--drivers/usb/dwc3/Kconfig1
-rw-r--r--drivers/usb/dwc3/core.c202
-rw-r--r--drivers/usb/dwc3/core.h72
-rw-r--r--drivers/usb/dwc3/debugfs.c52
-rw-r--r--drivers/usb/dwc3/dwc3-exynos.c100
-rw-r--r--drivers/usb/dwc3/dwc3-omap.c253
-rw-r--r--drivers/usb/dwc3/dwc3-pci.c40
-rw-r--r--drivers/usb/dwc3/ep0.c40
-rw-r--r--drivers/usb/dwc3/gadget.c324
-rw-r--r--drivers/usb/gadget/Kconfig21
-rw-r--r--drivers/usb/gadget/Makefile19
-rw-r--r--drivers/usb/gadget/acm_ms.c15
-rw-r--r--drivers/usb/gadget/amd5536udc.c16
-rw-r--r--drivers/usb/gadget/amd5536udc.h1
-rw-r--r--drivers/usb/gadget/at91_udc.c14
-rw-r--r--drivers/usb/gadget/atmel_usba_udc.c44
-rw-r--r--drivers/usb/gadget/atmel_usba_udc.h6
-rw-r--r--drivers/usb/gadget/bcm63xx_udc.c23
-rw-r--r--drivers/usb/gadget/cdc2.c31
-rw-r--r--drivers/usb/gadget/composite.c6
-rw-r--r--drivers/usb/gadget/configfs.c1003
-rw-r--r--drivers/usb/gadget/dummy_hcd.c19
-rw-r--r--drivers/usb/gadget/ether.c20
-rw-r--r--drivers/usb/gadget/f_acm.c137
-rw-r--r--drivers/usb/gadget/f_ecm.c4
-rw-r--r--drivers/usb/gadget/f_eem.c3
-rw-r--r--drivers/usb/gadget/f_fs.c1
-rw-r--r--drivers/usb/gadget/f_ncm.c4
-rw-r--r--drivers/usb/gadget/f_obex.c227
-rw-r--r--drivers/usb/gadget/f_rndis.c6
-rw-r--r--drivers/usb/gadget/f_serial.c174
-rw-r--r--drivers/usb/gadget/f_sourcesink.c4
-rw-r--r--drivers/usb/gadget/f_subset.c4
-rw-r--r--drivers/usb/gadget/f_uac1.c1
-rw-r--r--drivers/usb/gadget/f_uvc.c262
-rw-r--r--drivers/usb/gadget/f_uvc.h12
-rw-r--r--drivers/usb/gadget/fsl_qe_udc.c18
-rw-r--r--drivers/usb/gadget/fsl_udc_core.c83
-rw-r--r--drivers/usb/gadget/fusb300_udc.c46
-rw-r--r--drivers/usb/gadget/fusb300_udc.h2
-rw-r--r--drivers/usb/gadget/g_ffs.c39
-rw-r--r--drivers/usb/gadget/goku_udc.c20
-rw-r--r--drivers/usb/gadget/goku_udc.h3
-rw-r--r--drivers/usb/gadget/imx_udc.c18
-rw-r--r--drivers/usb/gadget/inode.c1
-rw-r--r--drivers/usb/gadget/lpc32xx_udc.c51
-rw-r--r--drivers/usb/gadget/m66592-udc.c17
-rw-r--r--drivers/usb/gadget/multi.c33
-rw-r--r--drivers/usb/gadget/mv_u3d_core.c65
-rw-r--r--drivers/usb/gadget/mv_udc.h3
-rw-r--r--drivers/usb/gadget/mv_udc_core.c117
-rw-r--r--drivers/usb/gadget/ncm.c13
-rw-r--r--drivers/usb/gadget/net2272.c34
-rw-r--r--drivers/usb/gadget/net2280.c33
-rw-r--r--drivers/usb/gadget/nokia.c95
-rw-r--r--drivers/usb/gadget/omap_udc.c24
-rw-r--r--drivers/usb/gadget/pch_udc.c21
-rw-r--r--drivers/usb/gadget/pxa25x_udc.c20
-rw-r--r--drivers/usb/gadget/pxa27x_udc.c51
-rw-r--r--drivers/usb/gadget/r8a66597-udc.c14
-rw-r--r--drivers/usb/gadget/s3c-hsotg.c78
-rw-r--r--drivers/usb/gadget/s3c-hsudc.c16
-rw-r--r--drivers/usb/gadget/s3c2410_udc.c23
-rw-r--r--drivers/usb/gadget/serial.c59
-rw-r--r--drivers/usb/gadget/u_ether.c32
-rw-r--r--drivers/usb/gadget/u_ether.h27
-rw-r--r--drivers/usb/gadget/u_serial.c2
-rw-r--r--drivers/usb/gadget/u_serial.h1
-rw-r--r--drivers/usb/gadget/u_uac1.c3
-rw-r--r--drivers/usb/gadget/udc-core.c92
-rw-r--r--drivers/usb/gadget/uvc.h3
-rw-r--r--drivers/usb/gadget/uvc_queue.c538
-rw-r--r--drivers/usb/gadget/uvc_queue.h32
-rw-r--r--drivers/usb/gadget/uvc_v4l2.c71
-rw-r--r--drivers/usb/gadget/uvc_video.c31
-rw-r--r--drivers/usb/gadget/zero.c2
-rw-r--r--drivers/usb/host/Kconfig217
-rw-r--r--drivers/usb/host/Makefile6
-rw-r--r--drivers/usb/host/ehci-atmel.c88
-rw-r--r--drivers/usb/host/ehci-dbg.c15
-rw-r--r--drivers/usb/host/ehci-fsl.c9
-rw-r--r--drivers/usb/host/ehci-hcd.c112
-rw-r--r--drivers/usb/host/ehci-hub.c25
-rw-r--r--drivers/usb/host/ehci-msm.c91
-rw-r--r--drivers/usb/host/ehci-mv.c56
-rw-r--r--drivers/usb/host/ehci-mxc.c10
-rw-r--r--drivers/usb/host/ehci-omap.c331
-rw-r--r--drivers/usb/host/ehci-orion.c86
-rw-r--r--drivers/usb/host/ehci-pci.c14
-rw-r--r--drivers/usb/host/ehci-platform.c36
-rw-r--r--drivers/usb/host/ehci-ps3.c1
-rw-r--r--drivers/usb/host/ehci-q.c258
-rw-r--r--drivers/usb/host/ehci-s5p.c180
-rw-r--r--drivers/usb/host/ehci-sched.c42
-rw-r--r--drivers/usb/host/ehci-sh.c5
-rw-r--r--drivers/usb/host/ehci-spear.c119
-rw-r--r--drivers/usb/host/ehci-tegra.c34
-rw-r--r--drivers/usb/host/ehci-timer.c72
-rw-r--r--drivers/usb/host/ehci-vt8500.c150
-rw-r--r--drivers/usb/host/ehci.h16
-rw-r--r--drivers/usb/host/ohci-exynos.c14
-rw-r--r--drivers/usb/host/ohci-hcd.c136
-rw-r--r--drivers/usb/host/ohci-hub.c6
-rw-r--r--drivers/usb/host/ohci-omap3.c24
-rw-r--r--drivers/usb/host/sl811-hcd.c2
-rw-r--r--drivers/usb/host/sl811_cs.c15
-rw-r--r--drivers/usb/host/u132-hcd.c9
-rw-r--r--drivers/usb/host/xhci-hub.c2
-rw-r--r--drivers/usb/host/xhci-mem.c52
-rw-r--r--drivers/usb/host/xhci-pci.c1
-rw-r--r--drivers/usb/host/xhci-ring.c61
-rw-r--r--drivers/usb/host/xhci.c43
-rw-r--r--drivers/usb/host/xhci.h13
-rw-r--r--drivers/usb/image/Kconfig4
-rw-r--r--drivers/usb/misc/Kconfig21
-rw-r--r--drivers/usb/misc/appledisplay.c1
-rw-r--r--drivers/usb/misc/sisusbvga/Kconfig2
-rw-r--r--drivers/usb/misc/sisusbvga/sisusb.c2
-rw-r--r--drivers/usb/misc/usb3503.c13
-rw-r--r--drivers/usb/mon/Kconfig1
-rw-r--r--drivers/usb/musb/Kconfig13
-rw-r--r--drivers/usb/musb/am35x.c8
-rw-r--r--drivers/usb/musb/blackfin.c6
-rw-r--r--drivers/usb/musb/cppi_dma.c17
-rw-r--r--drivers/usb/musb/da8xx.c10
-rw-r--r--drivers/usb/musb/davinci.c4
-rw-r--r--drivers/usb/musb/musb_core.c77
-rw-r--r--drivers/usb/musb/musb_dsps.c14
-rw-r--r--drivers/usb/musb/musb_gadget.c165
-rw-r--r--drivers/usb/musb/musb_gadget_ep0.c6
-rw-r--r--drivers/usb/musb/musb_host.c119
-rw-r--r--drivers/usb/musb/musb_virthub.c4
-rw-r--r--drivers/usb/musb/omap2430.c44
-rw-r--r--drivers/usb/musb/tusb6010.c14
-rw-r--r--drivers/usb/musb/ux500.c106
-rw-r--r--drivers/usb/musb/ux500_dma.c24
-rw-r--r--drivers/usb/otg/Kconfig141
-rw-r--r--drivers/usb/otg/Makefile24
-rw-r--r--drivers/usb/otg/ab8500-usb.c596
-rw-r--r--drivers/usb/phy/Kconfig181
-rw-r--r--drivers/usb/phy/Makefile35
-rw-r--r--drivers/usb/phy/isp1301.c71
-rw-r--r--drivers/usb/phy/phy-ab8500-usb.c924
-rw-r--r--drivers/usb/phy/phy-fsl-usb.c (renamed from drivers/usb/otg/fsl_otg.c)34
-rw-r--r--drivers/usb/phy/phy-fsl-usb.h (renamed from drivers/usb/otg/fsl_otg.h)0
-rw-r--r--drivers/usb/phy/phy-fsm-usb.c (renamed from drivers/usb/otg/otg_fsm.c)4
-rw-r--r--drivers/usb/phy/phy-fsm-usb.h (renamed from drivers/usb/otg/otg_fsm.h)0
-rw-r--r--drivers/usb/phy/phy-gpio-vbus-usb.c (renamed from drivers/usb/otg/gpio_vbus.c)9
-rw-r--r--drivers/usb/phy/phy-isp1301-omap.c (renamed from drivers/usb/otg/isp1301_omap.c)10
-rw-r--r--drivers/usb/phy/phy-isp1301.c162
-rw-r--r--drivers/usb/phy/phy-msm-usb.c (renamed from drivers/usb/otg/msm_otg.c)0
-rw-r--r--drivers/usb/phy/phy-mv-u3d-usb.c (renamed from drivers/usb/phy/mv_u3d_phy.c)4
-rw-r--r--drivers/usb/phy/phy-mv-u3d-usb.h (renamed from drivers/usb/phy/mv_u3d_phy.h)0
-rw-r--r--drivers/usb/phy/phy-mv-usb.c (renamed from drivers/usb/otg/mv_otg.c)30
-rw-r--r--drivers/usb/phy/phy-mv-usb.h (renamed from drivers/usb/otg/mv_otg.h)3
-rw-r--r--drivers/usb/phy/phy-mxs-usb.c (renamed from drivers/usb/otg/mxs-phy.c)41
-rw-r--r--drivers/usb/phy/phy-nop.c (renamed from drivers/usb/otg/nop-usb-xceiv.c)143
-rw-r--r--drivers/usb/phy/phy-omap-control.c (renamed from drivers/usb/phy/omap-control-usb.c)24
-rw-r--r--drivers/usb/phy/phy-omap-usb2.c (renamed from drivers/usb/phy/omap-usb2.c)0
-rw-r--r--drivers/usb/phy/phy-omap-usb3.c (renamed from drivers/usb/phy/omap-usb3.c)8
-rw-r--r--drivers/usb/phy/phy-rcar-usb.c (renamed from drivers/usb/phy/rcar-phy.c)0
-rw-r--r--drivers/usb/phy/phy-samsung-usb.c236
-rw-r--r--drivers/usb/phy/phy-samsung-usb.h327
-rw-r--r--drivers/usb/phy/phy-samsung-usb2.c509
-rw-r--r--drivers/usb/phy/phy-samsung-usb3.c347
-rw-r--r--drivers/usb/phy/phy-tegra-usb.c (renamed from drivers/usb/phy/tegra_usb_phy.c)13
-rw-r--r--drivers/usb/phy/phy-twl4030-usb.c (renamed from drivers/usb/otg/twl4030-usb.c)178
-rw-r--r--drivers/usb/phy/phy-twl6030-usb.c (renamed from drivers/usb/otg/twl6030-usb.c)15
-rw-r--r--drivers/usb/phy/phy-ulpi-viewport.c (renamed from drivers/usb/otg/ulpi_viewport.c)0
-rw-r--r--drivers/usb/phy/phy-ulpi.c (renamed from drivers/usb/otg/ulpi.c)0
-rw-r--r--drivers/usb/phy/phy.c (renamed from drivers/usb/otg/otg.c)74
-rw-r--r--drivers/usb/phy/samsung-usbphy.c930
-rw-r--r--drivers/usb/renesas_usbhs/Kconfig2
-rw-r--r--drivers/usb/renesas_usbhs/fifo.c1
-rw-r--r--drivers/usb/renesas_usbhs/fifo.h2
-rw-r--r--drivers/usb/renesas_usbhs/mod_gadget.c24
-rw-r--r--drivers/usb/serial/Kconfig19
-rw-r--r--drivers/usb/serial/Makefile1
-rw-r--r--drivers/usb/serial/ark3116.c85
-rw-r--r--drivers/usb/serial/bus.c5
-rw-r--r--drivers/usb/serial/ch341.c35
-rw-r--r--drivers/usb/serial/cp210x.c26
-rw-r--r--drivers/usb/serial/cyberjack.c19
-rw-r--r--drivers/usb/serial/cypress_m8.c92
-rw-r--r--drivers/usb/serial/digi_acceleport.c112
-rw-r--r--drivers/usb/serial/f81232.c18
-rw-r--r--drivers/usb/serial/ftdi_sio.c148
-rw-r--r--drivers/usb/serial/ftdi_sio_ids.h11
-rw-r--r--drivers/usb/serial/garmin_gps.c17
-rw-r--r--drivers/usb/serial/generic.c144
-rw-r--r--drivers/usb/serial/io_edgeport.c102
-rw-r--r--drivers/usb/serial/io_tables.h12
-rw-r--r--drivers/usb/serial/io_ti.c97
-rw-r--r--drivers/usb/serial/iuu_phoenix.c21
-rw-r--r--drivers/usb/serial/keyspan.c139
-rw-r--r--drivers/usb/serial/keyspan_pda.c25
-rw-r--r--drivers/usb/serial/kl5kusb105.c30
-rw-r--r--drivers/usb/serial/kobil_sct.c103
-rw-r--r--drivers/usb/serial/mct_u232.c130
-rw-r--r--drivers/usb/serial/metro-usb.c5
-rw-r--r--drivers/usb/serial/mos7720.c76
-rw-r--r--drivers/usb/serial/mos7840.c162
-rw-r--r--drivers/usb/serial/omninet.c81
-rw-r--r--drivers/usb/serial/opticon.c18
-rw-r--r--drivers/usb/serial/option.c22
-rw-r--r--drivers/usb/serial/oti6858.c36
-rw-r--r--drivers/usb/serial/pl2303.c44
-rw-r--r--drivers/usb/serial/qcaux.c1
-rw-r--r--drivers/usb/serial/qcserial.c7
-rw-r--r--drivers/usb/serial/quatech2.c105
-rw-r--r--drivers/usb/serial/sierra.c47
-rw-r--r--drivers/usb/serial/spcp8x5.c300
-rw-r--r--drivers/usb/serial/ssu100.c98
-rw-r--r--drivers/usb/serial/symbolserial.c130
-rw-r--r--drivers/usb/serial/ti_usb_3410_5052.c168
-rw-r--r--drivers/usb/serial/usb-serial.c238
-rw-r--r--drivers/usb/serial/usb_wwan.c25
-rw-r--r--drivers/usb/serial/visor.c16
-rw-r--r--drivers/usb/serial/wishbone-serial.c95
-rw-r--r--drivers/usb/storage/Kconfig7
-rw-r--r--drivers/usb/storage/alauda.c101
-rw-r--r--drivers/usb/storage/cypress_atacb.c18
-rw-r--r--drivers/usb/storage/datafab.c59
-rw-r--r--drivers/usb/storage/debug.c36
-rw-r--r--drivers/usb/storage/debug.h23
-rw-r--r--drivers/usb/storage/ene_ub6250.c86
-rw-r--r--drivers/usb/storage/freecom.c85
-rw-r--r--drivers/usb/storage/initializers.c86
-rw-r--r--drivers/usb/storage/initializers.h4
-rw-r--r--drivers/usb/storage/isd200.c295
-rw-r--r--drivers/usb/storage/jumpshot.c69
-rw-r--r--drivers/usb/storage/karma.c6
-rw-r--r--drivers/usb/storage/onetouch.c4
-rw-r--r--drivers/usb/storage/option_ms.c23
-rw-r--r--drivers/usb/storage/realtek_cr.c128
-rw-r--r--drivers/usb/storage/scsiglue.c13
-rw-r--r--drivers/usb/storage/sddr09.c146
-rw-r--r--drivers/usb/storage/sddr55.c86
-rw-r--r--drivers/usb/storage/shuttle_usbat.c119
-rw-r--r--drivers/usb/storage/sierra_ms.c43
-rw-r--r--drivers/usb/storage/transport.c181
-rw-r--r--drivers/usb/storage/unusual_devs.h344
-rw-r--r--drivers/usb/storage/usb.c117
-rw-r--r--drivers/usb/usb-common.c47
-rw-r--r--drivers/usb/usb-skeleton.c32
-rw-r--r--drivers/usb/wusbcore/Kconfig2
281 files changed, 10668 insertions, 10119 deletions
diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig
index 640ae6c6d2d..92e1dc94ecc 100644
--- a/drivers/usb/Kconfig
+++ b/drivers/usb/Kconfig
@@ -122,9 +122,9 @@ config USB
To compile this driver as a module, choose M here: the
module will be called usbcore.
-source "drivers/usb/core/Kconfig"
+if USB
-source "drivers/usb/dwc3/Kconfig"
+source "drivers/usb/core/Kconfig"
source "drivers/usb/mon/Kconfig"
@@ -134,8 +134,6 @@ source "drivers/usb/host/Kconfig"
source "drivers/usb/musb/Kconfig"
-source "drivers/usb/chipidea/Kconfig"
-
source "drivers/usb/renesas_usbhs/Kconfig"
source "drivers/usb/class/Kconfig"
@@ -144,12 +142,19 @@ source "drivers/usb/storage/Kconfig"
source "drivers/usb/image/Kconfig"
+endif
+
+source "drivers/usb/dwc3/Kconfig"
+
+source "drivers/usb/chipidea/Kconfig"
+
comment "USB port drivers"
- depends on USB
+
+if USB
config USB_USS720
tristate "USS720 parport driver"
- depends on USB && PARPORT
+ depends on PARPORT
select PARPORT_NOT_PC
---help---
This driver is for USB parallel port adapters that use the Lucent
@@ -180,12 +185,12 @@ source "drivers/usb/serial/Kconfig"
source "drivers/usb/misc/Kconfig"
-source "drivers/usb/phy/Kconfig"
-
source "drivers/usb/atm/Kconfig"
-source "drivers/usb/gadget/Kconfig"
+endif # USB
+
+source "drivers/usb/phy/Kconfig"
-source "drivers/usb/otg/Kconfig"
+source "drivers/usb/gadget/Kconfig"
endif # USB_SUPPORT
diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile
index f5ed3d75fa5..c41feba8d5c 100644
--- a/drivers/usb/Makefile
+++ b/drivers/usb/Makefile
@@ -6,8 +6,6 @@
obj-$(CONFIG_USB) += core/
-obj-$(CONFIG_USB_OTG_UTILS) += otg/
-
obj-$(CONFIG_USB_DWC3) += dwc3/
obj-$(CONFIG_USB_MON) += mon/
@@ -46,7 +44,7 @@ obj-$(CONFIG_USB_MICROTEK) += image/
obj-$(CONFIG_USB_SERIAL) += serial/
obj-$(CONFIG_USB) += misc/
-obj-$(CONFIG_USB_COMMON) += phy/
+obj-$(CONFIG_USB_PHY) += phy/
obj-$(CONFIG_EARLY_PRINTK_DBGP) += early/
obj-$(CONFIG_USB_ATM) += atm/
diff --git a/drivers/usb/atm/Kconfig b/drivers/usb/atm/Kconfig
index be0b8daac9c..0f922942a07 100644
--- a/drivers/usb/atm/Kconfig
+++ b/drivers/usb/atm/Kconfig
@@ -4,7 +4,7 @@
menuconfig USB_ATM
tristate "USB DSL modem support"
- depends on USB && ATM
+ depends on ATM
select CRC32
default n
help
diff --git a/drivers/usb/atm/usbatm.c b/drivers/usb/atm/usbatm.c
index 35f10bfe15d..d3527dd8b90 100644
--- a/drivers/usb/atm/usbatm.c
+++ b/drivers/usb/atm/usbatm.c
@@ -672,9 +672,6 @@ static int usbatm_atm_send(struct atm_vcc *vcc, struct sk_buff *skb)
struct usbatm_control *ctrl = UDSL_SKB(skb);
int err;
- vdbg(&instance->usb_intf->dev, "%s called (skb 0x%p, len %u)", __func__,
- skb, skb->len);
-
/* racy disconnection check - fine */
if (!instance || instance->disconnected) {
#ifdef DEBUG
@@ -684,6 +681,9 @@ static int usbatm_atm_send(struct atm_vcc *vcc, struct sk_buff *skb)
goto fail;
}
+ vdbg(&instance->usb_intf->dev, "%s called (skb 0x%p, len %u)", __func__,
+ skb, skb->len);
+
if (vcc->qos.aal != ATM_AAL5) {
atm_rldbg(instance, "%s: unsupported ATM type %d!\n", __func__, vcc->qos.aal);
err = -EINVAL;
diff --git a/drivers/usb/c67x00/c67x00-sched.c b/drivers/usb/c67x00/c67x00-sched.c
index a03fbc15fa9..aa491627a45 100644
--- a/drivers/usb/c67x00/c67x00-sched.c
+++ b/drivers/usb/c67x00/c67x00-sched.c
@@ -100,7 +100,7 @@ struct c67x00_urb_priv {
#define TD_PIDEP_OFFSET 0x04
#define TD_PIDEPMASK_PID 0xF0
#define TD_PIDEPMASK_EP 0x0F
-#define TD_PORTLENMASK_DL 0x02FF
+#define TD_PORTLENMASK_DL 0x03FF
#define TD_PORTLENMASK_PN 0xC000
#define TD_STATUS_OFFSET 0x07
@@ -590,7 +590,7 @@ static int c67x00_create_td(struct c67x00_hcd *c67x00, struct urb *urb,
{
struct c67x00_td *td;
struct c67x00_urb_priv *urbp = urb->hcpriv;
- const __u8 active_flag = 1, retry_cnt = 1;
+ const __u8 active_flag = 1, retry_cnt = 3;
__u8 cmd = 0;
int tt = 0;
diff --git a/drivers/usb/chipidea/Makefile b/drivers/usb/chipidea/Makefile
index d92ca325b10..4ab83e98219 100644
--- a/drivers/usb/chipidea/Makefile
+++ b/drivers/usb/chipidea/Makefile
@@ -17,5 +17,5 @@ ifneq ($(CONFIG_PCI),)
endif
ifneq ($(CONFIG_OF_DEVICE),)
- obj-$(CONFIG_USB_CHIPIDEA) += ci13xxx_imx.o usbmisc_imx6q.o
+ obj-$(CONFIG_USB_CHIPIDEA) += ci13xxx_imx.o usbmisc_imx.o
endif
diff --git a/drivers/usb/chipidea/ci.h b/drivers/usb/chipidea/ci.h
index e25d1263da1..b0a6bce064c 100644
--- a/drivers/usb/chipidea/ci.h
+++ b/drivers/usb/chipidea/ci.h
@@ -21,6 +21,7 @@
/******************************************************************************
* DEFINE
*****************************************************************************/
+#define TD_PAGE_COUNT 5
#define CI13XXX_PAGE_SIZE 4096ul /* page size for TD's */
#define ENDPT_MAX 32
@@ -129,6 +130,7 @@ struct hw_bank {
* @vbus_active: is VBUS active
* @transceiver: pointer to USB PHY, if any
* @hcd: pointer to usb_hcd for ehci host driver
+ * @debugfs: root dentry for this controller in debugfs
*/
struct ci13xxx {
struct device *dev;
@@ -139,7 +141,6 @@ struct ci13xxx {
enum ci_role role;
bool is_otg;
struct work_struct work;
- struct work_struct vbus_work;
struct workqueue_struct *wq;
struct dma_pool *qh_pool;
@@ -165,6 +166,7 @@ struct ci13xxx {
bool global_phy;
struct usb_phy *transceiver;
struct usb_hcd *hcd;
+ struct dentry *debugfs;
};
static inline struct ci_role_driver *ci_role(struct ci13xxx *ci)
@@ -234,19 +236,6 @@ enum ci13xxx_regs {
};
/**
- * ffs_nr: find first (least significant) bit set
- * @x: the word to search
- *
- * This function returns bit number (instead of position)
- */
-static inline int ffs_nr(u32 x)
-{
- int n = ffs(x);
-
- return n ? n-1 : 32;
-}
-
-/**
* hw_read: reads from a hw register
* @reg: register index
* @mask: bitfield mask
@@ -304,7 +293,7 @@ static inline u32 hw_test_and_write(struct ci13xxx *ci, enum ci13xxx_regs reg,
u32 val = hw_read(ci, reg, ~0);
hw_write(ci, reg, mask, data);
- return (val & mask) >> ffs_nr(mask);
+ return (val & mask) >> __ffs(mask);
}
int hw_device_reset(struct ci13xxx *ci, u32 mode);
diff --git a/drivers/usb/chipidea/ci13xxx_imx.c b/drivers/usb/chipidea/ci13xxx_imx.c
index 8c291220be7..8faec9dbbb8 100644
--- a/drivers/usb/chipidea/ci13xxx_imx.c
+++ b/drivers/usb/chipidea/ci13xxx_imx.c
@@ -79,6 +79,9 @@ int usbmisc_get_init_data(struct device *dev, struct usbmisc_usb_device *usbdev)
if (of_find_property(np, "disable-over-current", NULL))
usbdev->disable_oc = 1;
+ if (of_find_property(np, "external-vbus-divider", NULL))
+ usbdev->evdo = 1;
+
return 0;
}
EXPORT_SYMBOL_GPL(usbmisc_get_init_data);
@@ -202,6 +205,15 @@ static int ci13xxx_imx_probe(struct platform_device *pdev)
goto err;
}
+ if (usbmisc_ops && usbmisc_ops->post) {
+ ret = usbmisc_ops->post(&pdev->dev);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "usbmisc post failed, ret=%d\n", ret);
+ goto put_np;
+ }
+ }
+
data->ci_pdev = plat_ci;
platform_set_drvdata(pdev, data);
diff --git a/drivers/usb/chipidea/ci13xxx_imx.h b/drivers/usb/chipidea/ci13xxx_imx.h
index 9cd2e910b1c..550bfa45762 100644
--- a/drivers/usb/chipidea/ci13xxx_imx.h
+++ b/drivers/usb/chipidea/ci13xxx_imx.h
@@ -13,6 +13,8 @@
struct usbmisc_ops {
/* It's called once when probe a usb device */
int (*init)(struct device *dev);
+ /* It's called once after adding a usb device */
+ int (*post)(struct device *dev);
};
struct usbmisc_usb_device {
@@ -20,6 +22,7 @@ struct usbmisc_usb_device {
int index;
unsigned int disable_oc:1; /* over current detect disabled */
+ unsigned int evdo:1; /* set external vbus divider option */
};
int usbmisc_set_ops(const struct usbmisc_ops *ops);
diff --git a/drivers/usb/chipidea/ci13xxx_pci.c b/drivers/usb/chipidea/ci13xxx_pci.c
index 9b227e39299..4e1fc61b9d9 100644
--- a/drivers/usb/chipidea/ci13xxx_pci.c
+++ b/drivers/usb/chipidea/ci13xxx_pci.c
@@ -23,17 +23,17 @@
/******************************************************************************
* PCI block
*****************************************************************************/
-struct ci13xxx_platform_data pci_platdata = {
+static struct ci13xxx_platform_data pci_platdata = {
.name = UDC_DRIVER_NAME,
.capoffset = DEF_CAPOFFSET,
};
-struct ci13xxx_platform_data langwell_pci_platdata = {
+static struct ci13xxx_platform_data langwell_pci_platdata = {
.name = UDC_DRIVER_NAME,
.capoffset = 0,
};
-struct ci13xxx_platform_data penwell_pci_platdata = {
+static struct ci13xxx_platform_data penwell_pci_platdata = {
.name = UDC_DRIVER_NAME,
.capoffset = 0,
.power_budget = 200,
diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c
index 57cae1f897b..450107e5f65 100644
--- a/drivers/usb/chipidea/core.c
+++ b/drivers/usb/chipidea/core.c
@@ -51,15 +51,12 @@
*/
#include <linux/delay.h>
#include <linux/device.h>
-#include <linux/dmapool.h>
#include <linux/dma-mapping.h>
-#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/module.h>
#include <linux/idr.h>
#include <linux/interrupt.h>
#include <linux/io.h>
-#include <linux/irq.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/pm_runtime.h>
@@ -158,7 +155,7 @@ int hw_port_test_set(struct ci13xxx *ci, u8 mode)
if (mode > TEST_MODE_MAX)
return -EINVAL;
- hw_write(ci, OP_PORTSC, PORTSC_PTC, mode << ffs_nr(PORTSC_PTC));
+ hw_write(ci, OP_PORTSC, PORTSC_PTC, mode << __ffs(PORTSC_PTC));
return 0;
}
@@ -169,7 +166,7 @@ int hw_port_test_set(struct ci13xxx *ci, u8 mode)
*/
u8 hw_port_test_get(struct ci13xxx *ci)
{
- return hw_read(ci, OP_PORTSC, PORTSC_PTC) >> ffs_nr(PORTSC_PTC);
+ return hw_read(ci, OP_PORTSC, PORTSC_PTC) >> __ffs(PORTSC_PTC);
}
static int hw_device_init(struct ci13xxx *ci, void __iomem *base)
@@ -181,11 +178,11 @@ static int hw_device_init(struct ci13xxx *ci, void __iomem *base)
ci->hw_bank.cap = ci->hw_bank.abs;
ci->hw_bank.cap += ci->platdata->capoffset;
- ci->hw_bank.op = ci->hw_bank.cap + ioread8(ci->hw_bank.cap);
+ ci->hw_bank.op = ci->hw_bank.cap + (ioread32(ci->hw_bank.cap) & 0xff);
hw_alloc_regmap(ci, false);
reg = hw_read(ci, CAP_HCCPARAMS, HCCPARAMS_LEN) >>
- ffs_nr(HCCPARAMS_LEN);
+ __ffs(HCCPARAMS_LEN);
ci->hw_bank.lpm = reg;
hw_alloc_regmap(ci, !!reg);
ci->hw_bank.size = ci->hw_bank.op - ci->hw_bank.abs;
@@ -193,7 +190,7 @@ static int hw_device_init(struct ci13xxx *ci, void __iomem *base)
ci->hw_bank.size /= sizeof(u32);
reg = hw_read(ci, CAP_DCCPARAMS, DCCPARAMS_DEN) >>
- ffs_nr(DCCPARAMS_DEN);
+ __ffs(DCCPARAMS_DEN);
ci->hw_ep_max = reg * 2; /* cache hw ENDPT_MAX */
if (ci->hw_ep_max > ENDPT_MAX)
@@ -283,38 +280,6 @@ static void ci_role_work(struct work_struct *work)
}
}
-static ssize_t show_role(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- struct ci13xxx *ci = dev_get_drvdata(dev);
-
- return sprintf(buf, "%s\n", ci_role(ci)->name);
-}
-
-static ssize_t store_role(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct ci13xxx *ci = dev_get_drvdata(dev);
- enum ci_role role;
- int ret;
-
- for (role = CI_ROLE_HOST; role < CI_ROLE_END; role++)
- if (ci->roles[role] && !strcmp(buf, ci->roles[role]->name))
- break;
-
- if (role == CI_ROLE_END || role == ci->role)
- return -EINVAL;
-
- ci_role_stop(ci);
- ret = ci_role_start(ci, role);
- if (ret)
- return ret;
-
- return count;
-}
-
-static DEVICE_ATTR(role, S_IRUSR | S_IWUSR, show_role, store_role);
-
static irqreturn_t ci_irq(int irq, void *data)
{
struct ci13xxx *ci = data;
@@ -410,11 +375,9 @@ static int ci_hdrc_probe(struct platform_device *pdev)
return -ENODEV;
}
- base = devm_request_and_ioremap(dev, res);
- if (!base) {
- dev_err(dev, "can't request and ioremap resource\n");
- return -ENOMEM;
- }
+ base = devm_ioremap_resource(dev, res);
+ if (IS_ERR(base))
+ return PTR_ERR(base);
ci = devm_kzalloc(dev, sizeof(*ci), GFP_KERNEL);
if (!ci) {
@@ -489,17 +452,14 @@ static int ci_hdrc_probe(struct platform_device *pdev)
if (ret)
goto stop;
- ret = device_create_file(dev, &dev_attr_role);
- if (ret)
- goto rm_attr;
-
if (ci->is_otg)
hw_write(ci, OP_OTGSC, OTGSC_IDIE, OTGSC_IDIE);
- return ret;
+ ret = dbg_create_files(ci);
+ if (!ret)
+ return 0;
-rm_attr:
- device_remove_file(dev, &dev_attr_role);
+ free_irq(ci->irq, ci);
stop:
ci_role_stop(ci);
rm_wq:
@@ -513,9 +473,9 @@ static int ci_hdrc_remove(struct platform_device *pdev)
{
struct ci13xxx *ci = platform_get_drvdata(pdev);
+ dbg_remove_files(ci);
flush_workqueue(ci->wq);
destroy_workqueue(ci->wq);
- device_remove_file(ci->dev, &dev_attr_role);
free_irq(ci->irq, ci);
ci_role_stop(ci);
diff --git a/drivers/usb/chipidea/debug.c b/drivers/usb/chipidea/debug.c
index a62c4a47d52..36a7063a6cb 100644
--- a/drivers/usb/chipidea/debug.c
+++ b/drivers/usb/chipidea/debug.c
@@ -1,590 +1,126 @@
-#include <linux/delay.h>
-#include <linux/device.h>
-#include <linux/dmapool.h>
-#include <linux/dma-mapping.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/irq.h>
#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/pm_runtime.h>
+#include <linux/device.h>
+#include <linux/types.h>
+#include <linux/spinlock.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <linux/uaccess.h>
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
-#include <linux/usb/otg.h>
-#include <linux/usb/chipidea.h>
#include "ci.h"
#include "udc.h"
#include "bits.h"
#include "debug.h"
-/* Interrupt statistics */
-#define ISR_MASK 0x1F
-static struct isr_statistics {
- u32 test;
- u32 ui;
- u32 uei;
- u32 pci;
- u32 uri;
- u32 sli;
- u32 none;
- struct {
- u32 cnt;
- u32 buf[ISR_MASK+1];
- u32 idx;
- } hndl;
-} isr_statistics;
-
-void dbg_interrupt(u32 intmask)
-{
- if (!intmask) {
- isr_statistics.none++;
- return;
- }
-
- isr_statistics.hndl.buf[isr_statistics.hndl.idx++] = intmask;
- isr_statistics.hndl.idx &= ISR_MASK;
- isr_statistics.hndl.cnt++;
-
- if (USBi_URI & intmask)
- isr_statistics.uri++;
- if (USBi_PCI & intmask)
- isr_statistics.pci++;
- if (USBi_UEI & intmask)
- isr_statistics.uei++;
- if (USBi_UI & intmask)
- isr_statistics.ui++;
- if (USBi_SLI & intmask)
- isr_statistics.sli++;
-}
-
/**
- * hw_register_read: reads all device registers (execute without interruption)
- * @buf: destination buffer
- * @size: buffer size
- *
- * This function returns number of registers read
+ * ci_device_show: prints information about device capabilities and status
*/
-static size_t hw_register_read(struct ci13xxx *ci, u32 *buf, size_t size)
+static int ci_device_show(struct seq_file *s, void *data)
{
- unsigned i;
-
- if (size > ci->hw_bank.size)
- size = ci->hw_bank.size;
-
- for (i = 0; i < size; i++)
- buf[i] = hw_read(ci, i * sizeof(u32), ~0);
-
- return size;
-}
-
-/**
- * hw_register_write: writes to register
- * @addr: register address
- * @data: register value
- *
- * This function returns an error code
- */
-static int hw_register_write(struct ci13xxx *ci, u16 addr, u32 data)
-{
- /* align */
- addr /= sizeof(u32);
-
- if (addr >= ci->hw_bank.size)
- return -EINVAL;
-
- /* align */
- addr *= sizeof(u32);
-
- hw_write(ci, addr, ~0, data);
- return 0;
-}
-
-/**
- * hw_intr_clear: disables interrupt & clears interrupt status (execute without
- * interruption)
- * @n: interrupt bit
- *
- * This function returns an error code
- */
-static int hw_intr_clear(struct ci13xxx *ci, int n)
-{
- if (n >= REG_BITS)
- return -EINVAL;
-
- hw_write(ci, OP_USBINTR, BIT(n), 0);
- hw_write(ci, OP_USBSTS, BIT(n), BIT(n));
- return 0;
-}
-
-/**
- * hw_intr_force: enables interrupt & forces interrupt status (execute without
- * interruption)
- * @n: interrupt bit
- *
- * This function returns an error code
- */
-static int hw_intr_force(struct ci13xxx *ci, int n)
-{
- if (n >= REG_BITS)
- return -EINVAL;
-
- hw_write(ci, CAP_TESTMODE, TESTMODE_FORCE, TESTMODE_FORCE);
- hw_write(ci, OP_USBINTR, BIT(n), BIT(n));
- hw_write(ci, OP_USBSTS, BIT(n), BIT(n));
- hw_write(ci, CAP_TESTMODE, TESTMODE_FORCE, 0);
- return 0;
-}
-
-/**
- * show_device: prints information about device capabilities and status
- *
- * Check "device.h" for details
- */
-static ssize_t show_device(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev);
+ struct ci13xxx *ci = s->private;
struct usb_gadget *gadget = &ci->gadget;
- int n = 0;
- if (attr == NULL || buf == NULL) {
- dev_err(ci->dev, "[%s] EINVAL\n", __func__);
+ seq_printf(s, "speed = %d\n", gadget->speed);
+ seq_printf(s, "max_speed = %d\n", gadget->max_speed);
+ seq_printf(s, "is_otg = %d\n", gadget->is_otg);
+ seq_printf(s, "is_a_peripheral = %d\n", gadget->is_a_peripheral);
+ seq_printf(s, "b_hnp_enable = %d\n", gadget->b_hnp_enable);
+ seq_printf(s, "a_hnp_support = %d\n", gadget->a_hnp_support);
+ seq_printf(s, "a_alt_hnp_support = %d\n", gadget->a_alt_hnp_support);
+ seq_printf(s, "name = %s\n",
+ (gadget->name ? gadget->name : ""));
+
+ if (!ci->driver)
return 0;
- }
-
- n += scnprintf(buf + n, PAGE_SIZE - n, "speed = %d\n",
- gadget->speed);
- n += scnprintf(buf + n, PAGE_SIZE - n, "max_speed = %d\n",
- gadget->max_speed);
- 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",
- gadget->is_a_peripheral);
- n += scnprintf(buf + n, PAGE_SIZE - n, "b_hnp_enable = %d\n",
- gadget->b_hnp_enable);
- n += scnprintf(buf + n, PAGE_SIZE - n, "a_hnp_support = %d\n",
- gadget->a_hnp_support);
- n += scnprintf(buf + n, PAGE_SIZE - n, "a_alt_hnp_support = %d\n",
- gadget->a_alt_hnp_support);
- n += scnprintf(buf + n, PAGE_SIZE - n, "name = %s\n",
- (gadget->name ? gadget->name : ""));
-
- return n;
-}
-static DEVICE_ATTR(device, S_IRUSR, show_device, NULL);
-
-/**
- * show_driver: prints information about attached gadget (if any)
- *
- * Check "device.h" for details
- */
-static ssize_t show_driver(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev);
- struct usb_gadget_driver *driver = ci->driver;
- int n = 0;
-
- if (attr == NULL || buf == NULL) {
- dev_err(dev, "[%s] EINVAL\n", __func__);
- return 0;
- }
-
- if (driver == NULL)
- return scnprintf(buf, PAGE_SIZE,
- "There is no gadget attached!\n");
- n += scnprintf(buf + n, PAGE_SIZE - n, "function = %s\n",
- (driver->function ? driver->function : ""));
- n += scnprintf(buf + n, PAGE_SIZE - n, "max speed = %d\n",
- driver->max_speed);
+ seq_printf(s, "gadget function = %s\n",
+ (ci->driver->function ? ci->driver->function : ""));
+ seq_printf(s, "gadget max speed = %d\n", ci->driver->max_speed);
- return n;
-}
-static DEVICE_ATTR(driver, S_IRUSR, show_driver, NULL);
-
-/* Maximum event message length */
-#define DBG_DATA_MSG 64UL
-
-/* Maximum event messages */
-#define DBG_DATA_MAX 128UL
-
-/* Event buffer descriptor */
-static struct {
- char (buf[DBG_DATA_MAX])[DBG_DATA_MSG]; /* buffer */
- unsigned idx; /* index */
- unsigned tty; /* print to console? */
- rwlock_t lck; /* lock */
-} dbg_data = {
- .idx = 0,
- .tty = 0,
- .lck = __RW_LOCK_UNLOCKED(dbg_data.lck)
-};
-
-/**
- * dbg_dec: decrements debug event index
- * @idx: buffer index
- */
-static void dbg_dec(unsigned *idx)
-{
- *idx = (*idx - 1) & (DBG_DATA_MAX-1);
-}
-
-/**
- * dbg_inc: increments debug event index
- * @idx: buffer index
- */
-static void dbg_inc(unsigned *idx)
-{
- *idx = (*idx + 1) & (DBG_DATA_MAX-1);
-}
-
-/**
- * dbg_print: prints the common part of the event
- * @addr: endpoint address
- * @name: event name
- * @status: status
- * @extra: extra information
- */
-static void dbg_print(u8 addr, const char *name, int status, const char *extra)
-{
- struct timeval tval;
- unsigned int stamp;
- unsigned long flags;
-
- write_lock_irqsave(&dbg_data.lck, flags);
-
- do_gettimeofday(&tval);
- stamp = tval.tv_sec & 0xFFFF; /* 2^32 = 4294967296. Limit to 4096s */
- stamp = stamp * 1000000 + tval.tv_usec;
-
- scnprintf(dbg_data.buf[dbg_data.idx], DBG_DATA_MSG,
- "%04X\t? %02X %-7.7s %4i ?\t%s\n",
- stamp, addr, name, status, extra);
-
- dbg_inc(&dbg_data.idx);
-
- write_unlock_irqrestore(&dbg_data.lck, flags);
-
- if (dbg_data.tty != 0)
- pr_notice("%04X\t? %02X %-7.7s %4i ?\t%s\n",
- stamp, addr, name, status, extra);
-}
-
-/**
- * dbg_done: prints a DONE event
- * @addr: endpoint address
- * @td: transfer descriptor
- * @status: status
- */
-void dbg_done(u8 addr, const u32 token, int status)
-{
- char msg[DBG_DATA_MSG];
-
- scnprintf(msg, sizeof(msg), "%d %02X",
- (int)(token & TD_TOTAL_BYTES) >> ffs_nr(TD_TOTAL_BYTES),
- (int)(token & TD_STATUS) >> ffs_nr(TD_STATUS));
- dbg_print(addr, "DONE", status, msg);
-}
-
-/**
- * dbg_event: prints a generic event
- * @addr: endpoint address
- * @name: event name
- * @status: status
- */
-void dbg_event(u8 addr, const char *name, int status)
-{
- if (name != NULL)
- dbg_print(addr, name, status, "");
-}
-
-/*
- * dbg_queue: prints a QUEUE event
- * @addr: endpoint address
- * @req: USB request
- * @status: status
- */
-void dbg_queue(u8 addr, const struct usb_request *req, int status)
-{
- char msg[DBG_DATA_MSG];
-
- if (req != NULL) {
- scnprintf(msg, sizeof(msg),
- "%d %d", !req->no_interrupt, req->length);
- dbg_print(addr, "QUEUE", status, msg);
- }
-}
-
-/**
- * dbg_setup: prints a SETUP event
- * @addr: endpoint address
- * @req: setup request
- */
-void dbg_setup(u8 addr, const struct usb_ctrlrequest *req)
-{
- char msg[DBG_DATA_MSG];
-
- if (req != NULL) {
- scnprintf(msg, sizeof(msg),
- "%02X %02X %04X %04X %d", req->bRequestType,
- req->bRequest, le16_to_cpu(req->wValue),
- le16_to_cpu(req->wIndex), le16_to_cpu(req->wLength));
- dbg_print(addr, "SETUP", 0, msg);
- }
+ return 0;
}
-/**
- * show_events: displays the event buffer
- *
- * Check "device.h" for details
- */
-static ssize_t show_events(struct device *dev, struct device_attribute *attr,
- char *buf)
+static int ci_device_open(struct inode *inode, struct file *file)
{
- unsigned long flags;
- unsigned i, j, n = 0;
-
- if (attr == NULL || buf == NULL) {
- dev_err(dev->parent, "[%s] EINVAL\n", __func__);
- return 0;
- }
-
- read_lock_irqsave(&dbg_data.lck, flags);
-
- i = dbg_data.idx;
- for (dbg_dec(&i); i != dbg_data.idx; dbg_dec(&i)) {
- n += strlen(dbg_data.buf[i]);
- if (n >= PAGE_SIZE) {
- n -= strlen(dbg_data.buf[i]);
- break;
- }
- }
- for (j = 0, dbg_inc(&i); j < n; dbg_inc(&i))
- j += scnprintf(buf + j, PAGE_SIZE - j,
- "%s", dbg_data.buf[i]);
-
- read_unlock_irqrestore(&dbg_data.lck, flags);
-
- return n;
+ return single_open(file, ci_device_show, inode->i_private);
}
-/**
- * store_events: configure if events are going to be also printed to console
- *
- * Check "device.h" for details
- */
-static ssize_t store_events(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
-{
- unsigned tty;
-
- if (attr == NULL || buf == NULL) {
- dev_err(dev, "[%s] EINVAL\n", __func__);
- goto done;
- }
-
- if (sscanf(buf, "%u", &tty) != 1 || tty > 1) {
- dev_err(dev, "<1|0>: enable|disable console log\n");
- goto done;
- }
-
- dbg_data.tty = tty;
- dev_info(dev, "tty = %u", dbg_data.tty);
-
- done:
- return count;
-}
-static DEVICE_ATTR(events, S_IRUSR | S_IWUSR, show_events, store_events);
+static const struct file_operations ci_device_fops = {
+ .open = ci_device_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
/**
- * show_inters: interrupt status, enable status and historic
- *
- * Check "device.h" for details
+ * ci_port_test_show: reads port test mode
*/
-static ssize_t show_inters(struct device *dev, struct device_attribute *attr,
- char *buf)
+static int ci_port_test_show(struct seq_file *s, void *data)
{
- struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev);
+ struct ci13xxx *ci = s->private;
unsigned long flags;
- u32 intr;
- unsigned i, j, n = 0;
-
- if (attr == NULL || buf == NULL) {
- dev_err(ci->dev, "[%s] EINVAL\n", __func__);
- return 0;
- }
+ unsigned mode;
spin_lock_irqsave(&ci->lock, flags);
-
- /*n += scnprintf(buf + n, PAGE_SIZE - n,
- "status = %08x\n", hw_read_intr_status(ci));
- n += scnprintf(buf + n, PAGE_SIZE - n,
- "enable = %08x\n", hw_read_intr_enable(ci));*/
-
- n += scnprintf(buf + n, PAGE_SIZE - n, "*test = %d\n",
- isr_statistics.test);
- n += scnprintf(buf + n, PAGE_SIZE - n, "? ui = %d\n",
- isr_statistics.ui);
- n += scnprintf(buf + n, PAGE_SIZE - n, "? uei = %d\n",
- isr_statistics.uei);
- n += scnprintf(buf + n, PAGE_SIZE - n, "? pci = %d\n",
- isr_statistics.pci);
- n += scnprintf(buf + n, PAGE_SIZE - n, "? uri = %d\n",
- isr_statistics.uri);
- n += scnprintf(buf + n, PAGE_SIZE - n, "? sli = %d\n",
- isr_statistics.sli);
- n += scnprintf(buf + n, PAGE_SIZE - n, "*none = %d\n",
- isr_statistics.none);
- n += scnprintf(buf + n, PAGE_SIZE - n, "*hndl = %d\n",
- isr_statistics.hndl.cnt);
-
- for (i = isr_statistics.hndl.idx, j = 0; j <= ISR_MASK; j++, i++) {
- i &= ISR_MASK;
- intr = isr_statistics.hndl.buf[i];
-
- if (USBi_UI & intr)
- n += scnprintf(buf + n, PAGE_SIZE - n, "ui ");
- intr &= ~USBi_UI;
- if (USBi_UEI & intr)
- n += scnprintf(buf + n, PAGE_SIZE - n, "uei ");
- intr &= ~USBi_UEI;
- if (USBi_PCI & intr)
- n += scnprintf(buf + n, PAGE_SIZE - n, "pci ");
- intr &= ~USBi_PCI;
- if (USBi_URI & intr)
- n += scnprintf(buf + n, PAGE_SIZE - n, "uri ");
- intr &= ~USBi_URI;
- if (USBi_SLI & intr)
- n += scnprintf(buf + n, PAGE_SIZE - n, "sli ");
- intr &= ~USBi_SLI;
- if (intr)
- n += scnprintf(buf + n, PAGE_SIZE - n, "??? ");
- if (isr_statistics.hndl.buf[i])
- n += scnprintf(buf + n, PAGE_SIZE - n, "\n");
- }
-
+ mode = hw_port_test_get(ci);
spin_unlock_irqrestore(&ci->lock, flags);
- return n;
-}
-
-/**
- * store_inters: enable & force or disable an individual interrutps
- * (to be used for test purposes only)
- *
- * Check "device.h" for details
- */
-static ssize_t store_inters(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev);
- unsigned long flags;
- unsigned en, bit;
-
- if (attr == NULL || buf == NULL) {
- dev_err(ci->dev, "EINVAL\n");
- goto done;
- }
+ seq_printf(s, "mode = %u\n", mode);
- if (sscanf(buf, "%u %u", &en, &bit) != 2 || en > 1) {
- dev_err(ci->dev, "<1|0> <bit>: enable|disable interrupt\n");
- goto done;
- }
-
- spin_lock_irqsave(&ci->lock, flags);
- if (en) {
- if (hw_intr_force(ci, bit))
- dev_err(dev, "invalid bit number\n");
- else
- isr_statistics.test++;
- } else {
- if (hw_intr_clear(ci, bit))
- dev_err(dev, "invalid bit number\n");
- }
- spin_unlock_irqrestore(&ci->lock, flags);
-
- done:
- return count;
+ return 0;
}
-static DEVICE_ATTR(inters, S_IRUSR | S_IWUSR, show_inters, store_inters);
/**
- * show_port_test: reads port test mode
- *
- * Check "device.h" for details
+ * ci_port_test_write: writes port test mode
*/
-static ssize_t show_port_test(struct device *dev,
- struct device_attribute *attr, char *buf)
+static ssize_t ci_port_test_write(struct file *file, const char __user *ubuf,
+ size_t count, loff_t *ppos)
{
- struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev);
+ struct seq_file *s = file->private_data;
+ struct ci13xxx *ci = s->private;
unsigned long flags;
unsigned mode;
+ char buf[32];
+ int ret;
- if (attr == NULL || buf == NULL) {
- dev_err(ci->dev, "EINVAL\n");
- return 0;
- }
+ if (copy_from_user(buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
+ return -EFAULT;
+
+ if (sscanf(buf, "%u", &mode) != 1)
+ return -EINVAL;
spin_lock_irqsave(&ci->lock, flags);
- mode = hw_port_test_get(ci);
+ ret = hw_port_test_set(ci, mode);
spin_unlock_irqrestore(&ci->lock, flags);
- return scnprintf(buf, PAGE_SIZE, "mode = %u\n", mode);
+ return ret ? ret : count;
}
-/**
- * store_port_test: writes port test mode
- *
- * Check "device.h" for details
- */
-static ssize_t store_port_test(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
+static int ci_port_test_open(struct inode *inode, struct file *file)
{
- struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev);
- unsigned long flags;
- unsigned mode;
-
- if (attr == NULL || buf == NULL) {
- dev_err(ci->dev, "[%s] EINVAL\n", __func__);
- goto done;
- }
-
- if (sscanf(buf, "%u", &mode) != 1) {
- dev_err(ci->dev, "<mode>: set port test mode");
- goto done;
- }
-
- spin_lock_irqsave(&ci->lock, flags);
- if (hw_port_test_set(ci, mode))
- dev_err(ci->dev, "invalid mode\n");
- spin_unlock_irqrestore(&ci->lock, flags);
-
- done:
- return count;
+ return single_open(file, ci_port_test_show, inode->i_private);
}
-static DEVICE_ATTR(port_test, S_IRUSR | S_IWUSR,
- show_port_test, store_port_test);
+
+static const struct file_operations ci_port_test_fops = {
+ .open = ci_port_test_open,
+ .write = ci_port_test_write,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
/**
- * show_qheads: DMA contents of all queue heads
- *
- * Check "device.h" for details
+ * ci_qheads_show: DMA contents of all queue heads
*/
-static ssize_t show_qheads(struct device *dev, struct device_attribute *attr,
- char *buf)
+static int ci_qheads_show(struct seq_file *s, void *data)
{
- struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev);
+ struct ci13xxx *ci = s->private;
unsigned long flags;
- unsigned i, j, n = 0;
+ unsigned i, j;
- if (attr == NULL || buf == NULL) {
- dev_err(ci->dev, "[%s] EINVAL\n", __func__);
+ if (ci->role != CI_ROLE_GADGET) {
+ seq_printf(s, "not in gadget mode\n");
return 0;
}
@@ -593,209 +129,173 @@ static ssize_t show_qheads(struct device *dev, struct device_attribute *attr,
struct ci13xxx_ep *mEpRx = &ci->ci13xxx_ep[i];
struct ci13xxx_ep *mEpTx =
&ci->ci13xxx_ep[i + ci->hw_ep_max/2];
- n += scnprintf(buf + n, PAGE_SIZE - n,
- "EP=%02i: RX=%08X TX=%08X\n",
- i, (u32)mEpRx->qh.dma, (u32)mEpTx->qh.dma);
- for (j = 0; j < (sizeof(struct ci13xxx_qh)/sizeof(u32)); j++) {
- n += scnprintf(buf + n, PAGE_SIZE - n,
- " %04X: %08X %08X\n", j,
- *((u32 *)mEpRx->qh.ptr + j),
- *((u32 *)mEpTx->qh.ptr + j));
- }
+ seq_printf(s, "EP=%02i: RX=%08X TX=%08X\n",
+ i, (u32)mEpRx->qh.dma, (u32)mEpTx->qh.dma);
+ for (j = 0; j < (sizeof(struct ci13xxx_qh)/sizeof(u32)); j++)
+ seq_printf(s, " %04X: %08X %08X\n", j,
+ *((u32 *)mEpRx->qh.ptr + j),
+ *((u32 *)mEpTx->qh.ptr + j));
}
spin_unlock_irqrestore(&ci->lock, flags);
- return n;
+ return 0;
+}
+
+static int ci_qheads_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, ci_qheads_show, inode->i_private);
}
-static DEVICE_ATTR(qheads, S_IRUSR, show_qheads, NULL);
+
+static const struct file_operations ci_qheads_fops = {
+ .open = ci_qheads_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
/**
- * show_registers: dumps all registers
- *
- * Check "device.h" for details
+ * ci_requests_show: DMA contents of all requests currently queued (all endpts)
*/
-#define DUMP_ENTRIES 512
-static ssize_t show_registers(struct device *dev,
- struct device_attribute *attr, char *buf)
+static int ci_requests_show(struct seq_file *s, void *data)
{
- struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev);
+ struct ci13xxx *ci = s->private;
unsigned long flags;
- u32 *dump;
- unsigned i, k, n = 0;
-
- if (attr == NULL || buf == NULL) {
- dev_err(ci->dev, "[%s] EINVAL\n", __func__);
- return 0;
- }
+ struct list_head *ptr = NULL;
+ struct ci13xxx_req *req = NULL;
+ unsigned i, j, qsize = sizeof(struct ci13xxx_td)/sizeof(u32);
- dump = kmalloc(sizeof(u32) * DUMP_ENTRIES, GFP_KERNEL);
- if (!dump) {
- dev_err(ci->dev, "%s: out of memory\n", __func__);
+ if (ci->role != CI_ROLE_GADGET) {
+ seq_printf(s, "not in gadget mode\n");
return 0;
}
spin_lock_irqsave(&ci->lock, flags);
- k = hw_register_read(ci, dump, DUMP_ENTRIES);
- spin_unlock_irqrestore(&ci->lock, flags);
+ for (i = 0; i < ci->hw_ep_max; i++)
+ list_for_each(ptr, &ci->ci13xxx_ep[i].qh.queue) {
+ req = list_entry(ptr, struct ci13xxx_req, queue);
- for (i = 0; i < k; i++) {
- n += scnprintf(buf + n, PAGE_SIZE - n,
- "reg[0x%04X] = 0x%08X\n",
- i * (unsigned)sizeof(u32), dump[i]);
- }
- kfree(dump);
+ seq_printf(s, "EP=%02i: TD=%08X %s\n",
+ i % (ci->hw_ep_max / 2), (u32)req->dma,
+ ((i < ci->hw_ep_max/2) ? "RX" : "TX"));
+
+ for (j = 0; j < qsize; j++)
+ seq_printf(s, " %04X: %08X\n", j,
+ *((u32 *)req->ptr + j));
+ }
+ spin_unlock_irqrestore(&ci->lock, flags);
- return n;
+ return 0;
}
-/**
- * store_registers: writes value to register address
- *
- * Check "device.h" for details
- */
-static ssize_t store_registers(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
+static int ci_requests_open(struct inode *inode, struct file *file)
{
- struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev);
- unsigned long addr, data, flags;
+ return single_open(file, ci_requests_show, inode->i_private);
+}
- if (attr == NULL || buf == NULL) {
- dev_err(ci->dev, "[%s] EINVAL\n", __func__);
- goto done;
- }
+static const struct file_operations ci_requests_fops = {
+ .open = ci_requests_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
- if (sscanf(buf, "%li %li", &addr, &data) != 2) {
- dev_err(ci->dev,
- "<addr> <data>: write data to register address\n");
- goto done;
- }
+static int ci_role_show(struct seq_file *s, void *data)
+{
+ struct ci13xxx *ci = s->private;
- spin_lock_irqsave(&ci->lock, flags);
- if (hw_register_write(ci, addr, data))
- dev_err(ci->dev, "invalid address range\n");
- spin_unlock_irqrestore(&ci->lock, flags);
+ seq_printf(s, "%s\n", ci_role(ci)->name);
- done:
- return count;
+ return 0;
}
-static DEVICE_ATTR(registers, S_IRUSR | S_IWUSR,
- show_registers, store_registers);
-/**
- * show_requests: DMA contents of all requests currently queued (all endpts)
- *
- * Check "device.h" for details
- */
-static ssize_t show_requests(struct device *dev, struct device_attribute *attr,
- char *buf)
+static ssize_t ci_role_write(struct file *file, const char __user *ubuf,
+ size_t count, loff_t *ppos)
{
- struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev);
- unsigned long flags;
- struct list_head *ptr = NULL;
- struct ci13xxx_req *req = NULL;
- unsigned i, j, n = 0, qSize = sizeof(struct ci13xxx_td)/sizeof(u32);
-
- if (attr == NULL || buf == NULL) {
- dev_err(ci->dev, "[%s] EINVAL\n", __func__);
- return 0;
- }
+ struct seq_file *s = file->private_data;
+ struct ci13xxx *ci = s->private;
+ enum ci_role role;
+ char buf[8];
+ int ret;
+
+ if (copy_from_user(buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
+ return -EFAULT;
+
+ for (role = CI_ROLE_HOST; role < CI_ROLE_END; role++)
+ if (ci->roles[role] &&
+ !strncmp(buf, ci->roles[role]->name,
+ strlen(ci->roles[role]->name)))
+ break;
- spin_lock_irqsave(&ci->lock, flags);
- for (i = 0; i < ci->hw_ep_max; i++)
- list_for_each(ptr, &ci->ci13xxx_ep[i].qh.queue)
- {
- req = list_entry(ptr, struct ci13xxx_req, queue);
+ if (role == CI_ROLE_END || role == ci->role)
+ return -EINVAL;
- n += scnprintf(buf + n, PAGE_SIZE - n,
- "EP=%02i: TD=%08X %s\n",
- i % ci->hw_ep_max/2, (u32)req->dma,
- ((i < ci->hw_ep_max/2) ? "RX" : "TX"));
+ ci_role_stop(ci);
+ ret = ci_role_start(ci, role);
- for (j = 0; j < qSize; j++)
- n += scnprintf(buf + n, PAGE_SIZE - n,
- " %04X: %08X\n", j,
- *((u32 *)req->ptr + j));
- }
- spin_unlock_irqrestore(&ci->lock, flags);
+ return ret ? ret : count;
+}
- return n;
+static int ci_role_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, ci_role_show, inode->i_private);
}
-static DEVICE_ATTR(requests, S_IRUSR, show_requests, NULL);
+
+static const struct file_operations ci_role_fops = {
+ .open = ci_role_open,
+ .write = ci_role_write,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
/**
* dbg_create_files: initializes the attribute interface
- * @dev: device
+ * @ci: device
*
* This function returns an error code
*/
-int dbg_create_files(struct device *dev)
+int dbg_create_files(struct ci13xxx *ci)
{
- int retval = 0;
-
- if (dev == NULL)
- return -EINVAL;
- retval = device_create_file(dev, &dev_attr_device);
- if (retval)
- goto done;
- retval = device_create_file(dev, &dev_attr_driver);
- if (retval)
- goto rm_device;
- retval = device_create_file(dev, &dev_attr_events);
- if (retval)
- goto rm_driver;
- retval = device_create_file(dev, &dev_attr_inters);
- if (retval)
- goto rm_events;
- retval = device_create_file(dev, &dev_attr_port_test);
- if (retval)
- goto rm_inters;
- retval = device_create_file(dev, &dev_attr_qheads);
- if (retval)
- goto rm_port_test;
- retval = device_create_file(dev, &dev_attr_registers);
- if (retval)
- goto rm_qheads;
- retval = device_create_file(dev, &dev_attr_requests);
- if (retval)
- goto rm_registers;
- return 0;
-
- rm_registers:
- device_remove_file(dev, &dev_attr_registers);
- rm_qheads:
- device_remove_file(dev, &dev_attr_qheads);
- rm_port_test:
- device_remove_file(dev, &dev_attr_port_test);
- rm_inters:
- device_remove_file(dev, &dev_attr_inters);
- rm_events:
- device_remove_file(dev, &dev_attr_events);
- rm_driver:
- device_remove_file(dev, &dev_attr_driver);
- rm_device:
- device_remove_file(dev, &dev_attr_device);
- done:
- return retval;
+ struct dentry *dent;
+
+ ci->debugfs = debugfs_create_dir(dev_name(ci->dev), NULL);
+ if (!ci->debugfs)
+ return -ENOMEM;
+
+ dent = debugfs_create_file("device", S_IRUGO, ci->debugfs, ci,
+ &ci_device_fops);
+ if (!dent)
+ goto err;
+
+ dent = debugfs_create_file("port_test", S_IRUGO | S_IWUSR, ci->debugfs,
+ ci, &ci_port_test_fops);
+ if (!dent)
+ goto err;
+
+ dent = debugfs_create_file("qheads", S_IRUGO, ci->debugfs, ci,
+ &ci_qheads_fops);
+ if (!dent)
+ goto err;
+
+ dent = debugfs_create_file("requests", S_IRUGO, ci->debugfs, ci,
+ &ci_requests_fops);
+ if (!dent)
+ goto err;
+
+ dent = debugfs_create_file("role", S_IRUGO | S_IWUSR, ci->debugfs, ci,
+ &ci_role_fops);
+ if (dent)
+ return 0;
+err:
+ debugfs_remove_recursive(ci->debugfs);
+ return -ENOMEM;
}
/**
* dbg_remove_files: destroys the attribute interface
- * @dev: device
- *
- * This function returns an error code
+ * @ci: device
*/
-int dbg_remove_files(struct device *dev)
+void dbg_remove_files(struct ci13xxx *ci)
{
- if (dev == NULL)
- return -EINVAL;
- device_remove_file(dev, &dev_attr_requests);
- device_remove_file(dev, &dev_attr_registers);
- device_remove_file(dev, &dev_attr_qheads);
- device_remove_file(dev, &dev_attr_port_test);
- device_remove_file(dev, &dev_attr_inters);
- device_remove_file(dev, &dev_attr_events);
- device_remove_file(dev, &dev_attr_driver);
- device_remove_file(dev, &dev_attr_device);
- return 0;
+ debugfs_remove_recursive(ci->debugfs);
}
diff --git a/drivers/usb/chipidea/debug.h b/drivers/usb/chipidea/debug.h
index 80d96865775..7ca6ca0a24a 100644
--- a/drivers/usb/chipidea/debug.h
+++ b/drivers/usb/chipidea/debug.h
@@ -14,42 +14,16 @@
#define __DRIVERS_USB_CHIPIDEA_DEBUG_H
#ifdef CONFIG_USB_CHIPIDEA_DEBUG
-void dbg_interrupt(u32 intmask);
-void dbg_done(u8 addr, const u32 token, int status);
-void dbg_event(u8 addr, const char *name, int status);
-void dbg_queue(u8 addr, const struct usb_request *req, int status);
-void dbg_setup(u8 addr, const struct usb_ctrlrequest *req);
-int dbg_create_files(struct device *dev);
-int dbg_remove_files(struct device *dev);
+int dbg_create_files(struct ci13xxx *ci);
+void dbg_remove_files(struct ci13xxx *ci);
#else
-static inline void dbg_interrupt(u32 intmask)
-{
-}
-
-static inline void dbg_done(u8 addr, const u32 token, int status)
-{
-}
-
-static inline void dbg_event(u8 addr, const char *name, int status)
-{
-}
-
-static inline void dbg_queue(u8 addr, const struct usb_request *req, int status)
-{
-}
-
-static inline void dbg_setup(u8 addr, const struct usb_ctrlrequest *req)
-{
-}
-
-static inline int dbg_create_files(struct device *dev)
+static inline int dbg_create_files(struct ci13xxx *ci)
{
return 0;
}
-static inline int dbg_remove_files(struct device *dev)
+static inline void dbg_remove_files(struct ci13xxx *ci)
{
- return 0;
}
#endif
diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c
index 2f45bba8561..519ead2443c 100644
--- a/drivers/usb/chipidea/udc.c
+++ b/drivers/usb/chipidea/udc.c
@@ -13,14 +13,8 @@
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/dmapool.h>
-#include <linux/dma-mapping.h>
#include <linux/err.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/irq.h>
+#include <linux/irqreturn.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/pm_runtime.h>
@@ -146,7 +140,7 @@ static int hw_ep_enable(struct ci13xxx *ci, int num, int dir, int type)
if (dir) {
mask = ENDPTCTRL_TXT; /* type */
- data = type << ffs_nr(mask);
+ data = type << __ffs(mask);
mask |= ENDPTCTRL_TXS; /* unstall */
mask |= ENDPTCTRL_TXR; /* reset data toggle */
@@ -155,7 +149,7 @@ static int hw_ep_enable(struct ci13xxx *ci, int num, int dir, int type)
data |= ENDPTCTRL_TXE;
} else {
mask = ENDPTCTRL_RXT; /* type */
- data = type << ffs_nr(mask);
+ data = type << __ffs(mask);
mask |= ENDPTCTRL_RXS; /* unstall */
mask |= ENDPTCTRL_RXR; /* reset data toggle */
@@ -305,18 +299,6 @@ static u32 hw_test_and_clear_intr_active(struct ci13xxx *ci)
return reg;
}
-static void hw_enable_vbus_intr(struct ci13xxx *ci)
-{
- hw_write(ci, OP_OTGSC, OTGSC_AVVIS, OTGSC_AVVIS);
- hw_write(ci, OP_OTGSC, OTGSC_AVVIE, OTGSC_AVVIE);
- queue_work(ci->wq, &ci->vbus_work);
-}
-
-static void hw_disable_vbus_intr(struct ci13xxx *ci)
-{
- hw_write(ci, OP_OTGSC, OTGSC_AVVIE, 0);
-}
-
/**
* hw_test_and_clear_setup_guard: test & clear setup guard (execute without
* interruption)
@@ -349,7 +331,7 @@ static int hw_test_and_set_setup_guard(struct ci13xxx *ci)
static void hw_usb_set_address(struct ci13xxx *ci, u8 value)
{
hw_write(ci, OP_DEVICEADDR, DEVICEADDR_USBADR,
- value << ffs_nr(DEVICEADDR_USBADR));
+ value << __ffs(DEVICEADDR_USBADR));
}
/**
@@ -383,16 +365,6 @@ static int hw_usb_reset(struct ci13xxx *ci)
return 0;
}
-static void vbus_work(struct work_struct *work)
-{
- struct ci13xxx *ci = container_of(work, struct ci13xxx, vbus_work);
-
- if (hw_read(ci, OP_OTGSC, OTGSC_AVV))
- usb_gadget_vbus_connect(&ci->gadget);
- else
- usb_gadget_vbus_disconnect(&ci->gadget);
-}
-
/******************************************************************************
* UTIL block
*****************************************************************************/
@@ -432,10 +404,10 @@ static int _hardware_enqueue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq)
return -ENOMEM;
memset(mReq->zptr, 0, sizeof(*mReq->zptr));
- mReq->zptr->next = TD_TERMINATE;
- mReq->zptr->token = TD_STATUS_ACTIVE;
+ mReq->zptr->next = cpu_to_le32(TD_TERMINATE);
+ mReq->zptr->token = cpu_to_le32(TD_STATUS_ACTIVE);
if (!mReq->req.no_interrupt)
- mReq->zptr->token |= TD_IOC;
+ mReq->zptr->token |= cpu_to_le32(TD_IOC);
}
ret = usb_gadget_map_request(&ci->gadget, &mReq->req, mEp->dir);
if (ret)
@@ -446,32 +418,37 @@ static int _hardware_enqueue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq)
* TODO - handle requests which spawns into several TDs
*/
memset(mReq->ptr, 0, sizeof(*mReq->ptr));
- mReq->ptr->token = length << ffs_nr(TD_TOTAL_BYTES);
- mReq->ptr->token &= TD_TOTAL_BYTES;
- mReq->ptr->token |= TD_STATUS_ACTIVE;
+ mReq->ptr->token = cpu_to_le32(length << __ffs(TD_TOTAL_BYTES));
+ mReq->ptr->token &= cpu_to_le32(TD_TOTAL_BYTES);
+ mReq->ptr->token |= cpu_to_le32(TD_STATUS_ACTIVE);
if (mReq->zptr) {
- mReq->ptr->next = mReq->zdma;
+ mReq->ptr->next = cpu_to_le32(mReq->zdma);
} else {
- mReq->ptr->next = TD_TERMINATE;
+ mReq->ptr->next = cpu_to_le32(TD_TERMINATE);
if (!mReq->req.no_interrupt)
- mReq->ptr->token |= TD_IOC;
+ mReq->ptr->token |= cpu_to_le32(TD_IOC);
+ }
+ mReq->ptr->page[0] = cpu_to_le32(mReq->req.dma);
+ for (i = 1; i < TD_PAGE_COUNT; i++) {
+ u32 page = mReq->req.dma + i * CI13XXX_PAGE_SIZE;
+ page &= ~TD_RESERVED_MASK;
+ mReq->ptr->page[i] = cpu_to_le32(page);
}
- mReq->ptr->page[0] = mReq->req.dma;
- for (i = 1; i < 5; i++)
- mReq->ptr->page[i] =
- (mReq->req.dma + i * CI13XXX_PAGE_SIZE) & ~TD_RESERVED_MASK;
+
+ wmb();
if (!list_empty(&mEp->qh.queue)) {
struct ci13xxx_req *mReqPrev;
int n = hw_ep_bit(mEp->num, mEp->dir);
int tmp_stat;
+ u32 next = mReq->dma & TD_ADDR_MASK;
mReqPrev = list_entry(mEp->qh.queue.prev,
struct ci13xxx_req, queue);
if (mReqPrev->zptr)
- mReqPrev->zptr->next = mReq->dma & TD_ADDR_MASK;
+ mReqPrev->zptr->next = cpu_to_le32(next);
else
- mReqPrev->ptr->next = mReq->dma & TD_ADDR_MASK;
+ mReqPrev->ptr->next = cpu_to_le32(next);
wmb();
if (hw_read(ci, OP_ENDPTPRIME, BIT(n)))
goto done;
@@ -485,9 +462,9 @@ static int _hardware_enqueue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq)
}
/* QH configuration */
- mEp->qh.ptr->td.next = mReq->dma; /* TERMINATE = 0 */
- mEp->qh.ptr->td.token &= ~TD_STATUS; /* clear status */
- mEp->qh.ptr->cap |= QH_ZLT;
+ mEp->qh.ptr->td.next = cpu_to_le32(mReq->dma); /* TERMINATE = 0 */
+ mEp->qh.ptr->td.token &=
+ cpu_to_le32(~(TD_STATUS_HALTED|TD_STATUS_ACTIVE));
wmb(); /* synchronize before ep prime */
@@ -506,14 +483,16 @@ done:
*/
static int _hardware_dequeue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq)
{
+ u32 tmptoken = le32_to_cpu(mReq->ptr->token);
+
if (mReq->req.status != -EALREADY)
return -EINVAL;
- if ((TD_STATUS_ACTIVE & mReq->ptr->token) != 0)
+ if ((TD_STATUS_ACTIVE & tmptoken) != 0)
return -EBUSY;
if (mReq->zptr) {
- if ((TD_STATUS_ACTIVE & mReq->zptr->token) != 0)
+ if ((cpu_to_le32(TD_STATUS_ACTIVE) & mReq->zptr->token) != 0)
return -EBUSY;
dma_pool_free(mEp->td_pool, mReq->zptr, mReq->zdma);
mReq->zptr = NULL;
@@ -523,7 +502,7 @@ static int _hardware_dequeue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq)
usb_gadget_unmap_request(&mEp->ci->gadget, &mReq->req, mEp->dir);
- mReq->req.status = mReq->ptr->token & TD_STATUS;
+ mReq->req.status = tmptoken & TD_STATUS;
if ((TD_STATUS_HALTED & mReq->req.status) != 0)
mReq->req.status = -1;
else if ((TD_STATUS_DT_ERR & mReq->req.status) != 0)
@@ -531,8 +510,8 @@ static int _hardware_dequeue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq)
else if ((TD_STATUS_TR_ERR & mReq->req.status) != 0)
mReq->req.status = -1;
- mReq->req.actual = mReq->ptr->token & TD_TOTAL_BYTES;
- mReq->req.actual >>= ffs_nr(TD_TOTAL_BYTES);
+ mReq->req.actual = tmptoken & TD_TOTAL_BYTES;
+ mReq->req.actual >>= __ffs(TD_TOTAL_BYTES);
mReq->req.actual = mReq->req.length - mReq->req.actual;
mReq->req.actual = mReq->req.status ? 0 : mReq->req.actual;
@@ -561,6 +540,12 @@ __acquires(mEp->lock)
struct ci13xxx_req *mReq = \
list_entry(mEp->qh.queue.next,
struct ci13xxx_req, queue);
+
+ if (mReq->zptr) {
+ dma_pool_free(mEp->td_pool, mReq->zptr, mReq->zdma);
+ mReq->zptr = NULL;
+ }
+
list_del_init(&mReq->queue);
mReq->req.status = -ESHUTDOWN;
@@ -629,8 +614,6 @@ __acquires(ci->lock)
{
int retval;
- dbg_event(0xFF, "BUS RST", 0);
-
spin_unlock(&ci->lock);
retval = _gadget_stop_activity(&ci->gadget);
if (retval)
@@ -668,6 +651,59 @@ static void isr_get_status_complete(struct usb_ep *ep, struct usb_request *req)
}
/**
+ * _ep_queue: queues (submits) an I/O request to an endpoint
+ *
+ * Caller must hold lock
+ */
+static int _ep_queue(struct usb_ep *ep, struct usb_request *req,
+ gfp_t __maybe_unused gfp_flags)
+{
+ struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
+ struct ci13xxx_req *mReq = container_of(req, struct ci13xxx_req, req);
+ struct ci13xxx *ci = mEp->ci;
+ int retval = 0;
+
+ if (ep == NULL || req == NULL || mEp->ep.desc == NULL)
+ return -EINVAL;
+
+ if (mEp->type == USB_ENDPOINT_XFER_CONTROL) {
+ if (req->length)
+ mEp = (ci->ep0_dir == RX) ?
+ ci->ep0out : ci->ep0in;
+ if (!list_empty(&mEp->qh.queue)) {
+ _ep_nuke(mEp);
+ retval = -EOVERFLOW;
+ dev_warn(mEp->ci->dev, "endpoint ctrl %X nuked\n",
+ _usb_addr(mEp));
+ }
+ }
+
+ /* first nuke then test link, e.g. previous status has not sent */
+ if (!list_empty(&mReq->queue)) {
+ dev_err(mEp->ci->dev, "request already in queue\n");
+ return -EBUSY;
+ }
+
+ if (req->length > (TD_PAGE_COUNT - 1) * CI13XXX_PAGE_SIZE) {
+ dev_err(mEp->ci->dev, "request bigger than one td\n");
+ return -EMSGSIZE;
+ }
+
+ /* push request */
+ mReq->req.status = -EINPROGRESS;
+ mReq->req.actual = 0;
+
+ retval = _hardware_enqueue(mEp, mReq);
+
+ if (retval == -EALREADY)
+ retval = 0;
+ if (!retval)
+ list_add_tail(&mReq->queue, &mEp->qh.queue);
+
+ return retval;
+}
+
+/**
* isr_get_status_response: get_status request response
* @ci: ci struct
* @setup: setup request packet
@@ -714,9 +750,7 @@ __acquires(mEp->lock)
}
/* else do nothing; reserved for future use */
- spin_unlock(mEp->lock);
- retval = usb_ep_queue(&mEp->ep, req, gfp_flags);
- spin_lock(mEp->lock);
+ retval = _ep_queue(&mEp->ep, req, gfp_flags);
if (retval)
goto err_free_buf;
@@ -763,8 +797,6 @@ isr_setup_status_complete(struct usb_ep *ep, struct usb_request *req)
* This function returns an error code
*/
static int isr_setup_status_phase(struct ci13xxx *ci)
-__releases(mEp->lock)
-__acquires(mEp->lock)
{
int retval;
struct ci13xxx_ep *mEp;
@@ -773,9 +805,7 @@ __acquires(mEp->lock)
ci->status->context = ci;
ci->status->complete = isr_setup_status_complete;
- spin_unlock(mEp->lock);
- retval = usb_ep_queue(&mEp->ep, ci->status, GFP_ATOMIC);
- spin_lock(mEp->lock);
+ retval = _ep_queue(&mEp->ep, ci->status, GFP_ATOMIC);
return retval;
}
@@ -801,7 +831,6 @@ __acquires(mEp->lock)
if (retval < 0)
break;
list_del_init(&mReq->queue);
- dbg_done(_usb_addr(mEp), mReq->ptr->token, retval);
if (mReq->req.complete != NULL) {
spin_unlock(mEp->lock);
if ((mEp->type == USB_ENDPOINT_XFER_CONTROL) &&
@@ -814,8 +843,6 @@ __acquires(mEp->lock)
if (retval == -EBUSY)
retval = 0;
- if (retval < 0)
- dbg_event(_usb_addr(mEp), "DONE", retval);
return retval;
}
@@ -847,8 +874,6 @@ __acquires(ci->lock)
if (err > 0) /* needs status phase */
err = isr_setup_status_phase(ci);
if (err < 0) {
- dbg_event(_usb_addr(mEp),
- "ERROR", err);
spin_unlock(&ci->lock);
if (usb_ep_set_halt(&mEp->ep))
dev_err(ci->dev,
@@ -884,8 +909,6 @@ __acquires(ci->lock)
ci->ep0_dir = (type & USB_DIR_IN) ? TX : RX;
- dbg_setup(_usb_addr(mEp), &req);
-
switch (req.bRequest) {
case USB_REQ_CLEAR_FEATURE:
if (type == (USB_DIR_OUT|USB_RECIP_ENDPOINT) &&
@@ -997,8 +1020,6 @@ delegate:
}
if (err < 0) {
- dbg_event(_usb_addr(mEp), "ERROR", err);
-
spin_unlock(&ci->lock);
if (usb_ep_set_halt(&mEp->ep))
dev_err(ci->dev, "error: ep_set_halt\n");
@@ -1021,6 +1042,7 @@ static int ep_enable(struct usb_ep *ep,
struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
int retval = 0;
unsigned long flags;
+ u32 cap = 0;
if (ep == NULL || desc == NULL)
return -EINVAL;
@@ -1040,20 +1062,15 @@ static int ep_enable(struct usb_ep *ep,
mEp->ep.maxpacket = usb_endpoint_maxp(desc);
- dbg_event(_usb_addr(mEp), "ENABLE", 0);
-
- mEp->qh.ptr->cap = 0;
-
if (mEp->type == USB_ENDPOINT_XFER_CONTROL)
- mEp->qh.ptr->cap |= QH_IOS;
- else if (mEp->type == USB_ENDPOINT_XFER_ISOC)
- mEp->qh.ptr->cap &= ~QH_MULT;
- else
- mEp->qh.ptr->cap &= ~QH_ZLT;
+ cap |= QH_IOS;
+ if (mEp->num)
+ cap |= QH_ZLT;
+ cap |= (mEp->ep.maxpacket << __ffs(QH_MAX_PKT)) & QH_MAX_PKT;
+
+ mEp->qh.ptr->cap = cpu_to_le32(cap);
- mEp->qh.ptr->cap |=
- (mEp->ep.maxpacket << ffs_nr(QH_MAX_PKT)) & QH_MAX_PKT;
- mEp->qh.ptr->td.next |= TD_TERMINATE; /* needed? */
+ mEp->qh.ptr->td.next |= cpu_to_le32(TD_TERMINATE); /* needed? */
/*
* Enable endpoints in the HW other than ep0 as ep0
@@ -1088,8 +1105,6 @@ static int ep_disable(struct usb_ep *ep)
direction = mEp->dir;
do {
- dbg_event(_usb_addr(mEp), "DISABLE", 0);
-
retval |= _ep_nuke(mEp);
retval |= hw_ep_disable(mEp->ci, mEp->num, mEp->dir);
@@ -1129,8 +1144,6 @@ static struct usb_request *ep_alloc_request(struct usb_ep *ep, gfp_t gfp_flags)
}
}
- dbg_event(_usb_addr(mEp), "ALLOC", mReq == NULL);
-
return (mReq == NULL) ? NULL : &mReq->req;
}
@@ -1158,8 +1171,6 @@ static void ep_free_request(struct usb_ep *ep, struct usb_request *req)
dma_pool_free(mEp->td_pool, mReq->ptr, mReq->dma);
kfree(mReq);
- dbg_event(_usb_addr(mEp), "FREE", 0);
-
spin_unlock_irqrestore(mEp->lock, flags);
}
@@ -1172,8 +1183,6 @@ static int ep_queue(struct usb_ep *ep, struct usb_request *req,
gfp_t __maybe_unused gfp_flags)
{
struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
- struct ci13xxx_req *mReq = container_of(req, struct ci13xxx_req, req);
- struct ci13xxx *ci = mEp->ci;
int retval = 0;
unsigned long flags;
@@ -1181,48 +1190,7 @@ static int ep_queue(struct usb_ep *ep, struct usb_request *req,
return -EINVAL;
spin_lock_irqsave(mEp->lock, flags);
-
- if (mEp->type == USB_ENDPOINT_XFER_CONTROL) {
- if (req->length)
- mEp = (ci->ep0_dir == RX) ?
- ci->ep0out : ci->ep0in;
- if (!list_empty(&mEp->qh.queue)) {
- _ep_nuke(mEp);
- retval = -EOVERFLOW;
- dev_warn(mEp->ci->dev, "endpoint ctrl %X nuked\n",
- _usb_addr(mEp));
- }
- }
-
- /* first nuke then test link, e.g. previous status has not sent */
- if (!list_empty(&mReq->queue)) {
- retval = -EBUSY;
- dev_err(mEp->ci->dev, "request already in queue\n");
- goto done;
- }
-
- if (req->length > 4 * CI13XXX_PAGE_SIZE) {
- req->length = 4 * CI13XXX_PAGE_SIZE;
- retval = -EMSGSIZE;
- dev_warn(mEp->ci->dev, "request length truncated\n");
- }
-
- dbg_queue(_usb_addr(mEp), req, retval);
-
- /* push request */
- mReq->req.status = -EINPROGRESS;
- mReq->req.actual = 0;
-
- retval = _hardware_enqueue(mEp, mReq);
-
- if (retval == -EALREADY) {
- dbg_event(_usb_addr(mEp), "QUEUE", retval);
- retval = 0;
- }
- if (!retval)
- list_add_tail(&mReq->queue, &mEp->qh.queue);
-
- done:
+ retval = _ep_queue(ep, req, gfp_flags);
spin_unlock_irqrestore(mEp->lock, flags);
return retval;
}
@@ -1245,8 +1213,6 @@ static int ep_dequeue(struct usb_ep *ep, struct usb_request *req)
spin_lock_irqsave(mEp->lock, flags);
- dbg_event(_usb_addr(mEp), "DEQUEUE", 0);
-
hw_ep_flush(mEp->ci, mEp->num, mEp->dir);
/* pop request */
@@ -1293,7 +1259,6 @@ static int ep_set_halt(struct usb_ep *ep, int value)
direction = mEp->dir;
do {
- dbg_event(_usb_addr(mEp), "HALT", value);
retval |= hw_ep_set_halt(mEp->ci, mEp->num, mEp->dir, value);
if (!value)
@@ -1322,10 +1287,7 @@ static int ep_set_wedge(struct usb_ep *ep)
return -EINVAL;
spin_lock_irqsave(mEp->lock, flags);
-
- dbg_event(_usb_addr(mEp), "WEDGE", 0);
mEp->wedge = 1;
-
spin_unlock_irqrestore(mEp->lock, flags);
return usb_ep_set_halt(ep);
@@ -1348,7 +1310,6 @@ static void ep_fifo_flush(struct usb_ep *ep)
spin_lock_irqsave(mEp->lock, flags);
- dbg_event(_usb_addr(mEp), "FFLUSH", 0);
hw_ep_flush(mEp->ci, mEp->num, mEp->dir);
spin_unlock_irqrestore(mEp->lock, flags);
@@ -1392,7 +1353,6 @@ static int ci13xxx_vbus_session(struct usb_gadget *_gadget, int is_active)
if (is_active) {
pm_runtime_get_sync(&_gadget->dev);
hw_device_reset(ci, USBMODE_CM_DC);
- hw_enable_vbus_intr(ci);
hw_device_state(ci, ci->ep0out->qh.dma);
} else {
hw_device_state(ci, 0);
@@ -1567,10 +1527,8 @@ static int ci13xxx_start(struct usb_gadget *gadget,
pm_runtime_get_sync(&ci->gadget.dev);
if (ci->platdata->flags & CI13XXX_PULLUP_ON_VBUS) {
if (ci->vbus_active) {
- if (ci->platdata->flags & CI13XXX_REGS_SHARED) {
+ if (ci->platdata->flags & CI13XXX_REGS_SHARED)
hw_device_reset(ci, USBMODE_CM_DC);
- hw_enable_vbus_intr(ci);
- }
} else {
pm_runtime_put_sync(&ci->gadget.dev);
goto done;
@@ -1642,7 +1600,6 @@ static irqreturn_t udc_irq(struct ci13xxx *ci)
}
}
intr = hw_test_and_clear_intr_active(ci);
- dbg_interrupt(intr);
if (intr) {
/* order defines priority - do NOT change it */
@@ -1676,29 +1633,12 @@ static irqreturn_t udc_irq(struct ci13xxx *ci)
} else {
retval = IRQ_NONE;
}
-
- intr = hw_read(ci, OP_OTGSC, ~0);
- hw_write(ci, OP_OTGSC, ~0, intr);
-
- if (intr & (OTGSC_AVVIE & OTGSC_AVVIS))
- queue_work(ci->wq, &ci->vbus_work);
-
spin_unlock(&ci->lock);
return retval;
}
/**
- * udc_release: driver release function
- * @dev: device
- *
- * Currently does nothing
- */
-static void udc_release(struct device *dev)
-{
-}
-
-/**
* udc_start: initialize gadget role
* @ci: chipidea controller
*/
@@ -1717,12 +1657,6 @@ static int udc_start(struct ci13xxx *ci)
INIT_LIST_HEAD(&ci->gadget.ep_list);
- dev_set_name(&ci->gadget.dev, "gadget");
- ci->gadget.dev.dma_mask = dev->dma_mask;
- ci->gadget.dev.coherent_dma_mask = dev->coherent_dma_mask;
- ci->gadget.dev.parent = dev;
- ci->gadget.dev.release = udc_release;
-
/* alloc resources */
ci->qh_pool = dma_pool_create("ci13xxx_qh", dev,
sizeof(struct ci13xxx_qh),
@@ -1758,24 +1692,13 @@ static int udc_start(struct ci13xxx *ci)
retval = hw_device_reset(ci, USBMODE_CM_DC);
if (retval)
goto put_transceiver;
- hw_enable_vbus_intr(ci);
- }
-
- retval = device_register(&ci->gadget.dev);
- if (retval) {
- put_device(&ci->gadget.dev);
- goto put_transceiver;
}
- retval = dbg_create_files(&ci->gadget.dev);
- if (retval)
- goto unreg_device;
-
if (!IS_ERR_OR_NULL(ci->transceiver)) {
retval = otg_set_peripheral(ci->transceiver->otg,
&ci->gadget);
if (retval)
- goto remove_dbg;
+ goto put_transceiver;
}
retval = usb_add_gadget_udc(dev, &ci->gadget);
@@ -1795,10 +1718,6 @@ remove_trans:
}
dev_err(dev, "error = %i\n", retval);
-remove_dbg:
- dbg_remove_files(&ci->gadget.dev);
-unreg_device:
- device_unregister(&ci->gadget.dev);
put_transceiver:
if (!IS_ERR_OR_NULL(ci->transceiver) && ci->global_phy)
usb_put_phy(ci->transceiver);
@@ -1821,9 +1740,6 @@ static void udc_stop(struct ci13xxx *ci)
if (ci == NULL)
return;
- hw_disable_vbus_intr(ci);
- cancel_work_sync(&ci->vbus_work);
-
usb_del_gadget_udc(&ci->gadget);
destroy_eps(ci);
@@ -1836,8 +1752,6 @@ static void udc_stop(struct ci13xxx *ci)
if (ci->global_phy)
usb_put_phy(ci->transceiver);
}
- dbg_remove_files(&ci->gadget.dev);
- device_unregister(&ci->gadget.dev);
/* my kobject is dynamic, I swear! */
memset(&ci->gadget, 0, sizeof(ci->gadget));
}
@@ -1864,7 +1778,6 @@ int ci_hdrc_gadget_init(struct ci13xxx *ci)
rdrv->irq = udc_irq;
rdrv->name = "gadget";
ci->roles[CI_ROLE_GADGET] = rdrv;
- INIT_WORK(&ci->vbus_work, vbus_work);
return 0;
}
diff --git a/drivers/usb/chipidea/udc.h b/drivers/usb/chipidea/udc.h
index 4ff2384d7ca..d12e8b59b11 100644
--- a/drivers/usb/chipidea/udc.h
+++ b/drivers/usb/chipidea/udc.h
@@ -40,7 +40,7 @@ struct ci13xxx_td {
#define TD_CURR_OFFSET (0x0FFFUL << 0)
#define TD_FRAME_NUM (0x07FFUL << 0)
#define TD_RESERVED_MASK (0x0FFFUL << 0)
-} __attribute__ ((packed));
+} __attribute__ ((packed, aligned(4)));
/* DMA layout of queue heads */
struct ci13xxx_qh {
@@ -57,7 +57,7 @@ struct ci13xxx_qh {
/* 9 */
u32 RESERVED;
struct usb_ctrlrequest setup;
-} __attribute__ ((packed));
+} __attribute__ ((packed, aligned(4)));
/**
* struct ci13xxx_req - usb request representation
diff --git a/drivers/usb/chipidea/usbmisc_imx.c b/drivers/usb/chipidea/usbmisc_imx.c
new file mode 100644
index 00000000000..714a6bd810e
--- /dev/null
+++ b/drivers/usb/chipidea/usbmisc_imx.c
@@ -0,0 +1,261 @@
+/*
+ * Copyright 2012 Freescale Semiconductor, Inc.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+
+#include "ci13xxx_imx.h"
+
+#define USB_DEV_MAX 4
+
+#define MX25_USB_PHY_CTRL_OFFSET 0x08
+#define MX25_BM_EXTERNAL_VBUS_DIVIDER BIT(23)
+
+#define MX53_USB_OTG_PHY_CTRL_0_OFFSET 0x08
+#define MX53_USB_UH2_CTRL_OFFSET 0x14
+#define MX53_USB_UH3_CTRL_OFFSET 0x18
+#define MX53_BM_OVER_CUR_DIS_H1 BIT(5)
+#define MX53_BM_OVER_CUR_DIS_OTG BIT(8)
+#define MX53_BM_OVER_CUR_DIS_UHx BIT(30)
+
+#define MX6_BM_OVER_CUR_DIS BIT(7)
+
+struct imx_usbmisc {
+ void __iomem *base;
+ spinlock_t lock;
+ struct clk *clk;
+ struct usbmisc_usb_device usbdev[USB_DEV_MAX];
+ const struct usbmisc_ops *ops;
+};
+
+static struct imx_usbmisc *usbmisc;
+
+static struct usbmisc_usb_device *get_usbdev(struct device *dev)
+{
+ int i, ret;
+
+ for (i = 0; i < USB_DEV_MAX; i++) {
+ if (usbmisc->usbdev[i].dev == dev)
+ return &usbmisc->usbdev[i];
+ else if (!usbmisc->usbdev[i].dev)
+ break;
+ }
+
+ if (i >= USB_DEV_MAX)
+ return ERR_PTR(-EBUSY);
+
+ ret = usbmisc_get_init_data(dev, &usbmisc->usbdev[i]);
+ if (ret)
+ return ERR_PTR(ret);
+
+ return &usbmisc->usbdev[i];
+}
+
+static int usbmisc_imx25_post(struct device *dev)
+{
+ struct usbmisc_usb_device *usbdev;
+ void __iomem *reg;
+ unsigned long flags;
+ u32 val;
+
+ usbdev = get_usbdev(dev);
+ if (IS_ERR(usbdev))
+ return PTR_ERR(usbdev);
+
+ reg = usbmisc->base + MX25_USB_PHY_CTRL_OFFSET;
+
+ if (usbdev->evdo) {
+ spin_lock_irqsave(&usbmisc->lock, flags);
+ val = readl(reg);
+ writel(val | MX25_BM_EXTERNAL_VBUS_DIVIDER, reg);
+ spin_unlock_irqrestore(&usbmisc->lock, flags);
+ usleep_range(5000, 10000); /* needed to stabilize voltage */
+ }
+
+ return 0;
+}
+
+static int usbmisc_imx53_init(struct device *dev)
+{
+ struct usbmisc_usb_device *usbdev;
+ void __iomem *reg = NULL;
+ unsigned long flags;
+ u32 val = 0;
+
+ usbdev = get_usbdev(dev);
+ if (IS_ERR(usbdev))
+ return PTR_ERR(usbdev);
+
+ if (usbdev->disable_oc) {
+ spin_lock_irqsave(&usbmisc->lock, flags);
+ switch (usbdev->index) {
+ case 0:
+ reg = usbmisc->base + MX53_USB_OTG_PHY_CTRL_0_OFFSET;
+ val = readl(reg) | MX53_BM_OVER_CUR_DIS_OTG;
+ break;
+ case 1:
+ reg = usbmisc->base + MX53_USB_OTG_PHY_CTRL_0_OFFSET;
+ val = readl(reg) | MX53_BM_OVER_CUR_DIS_H1;
+ break;
+ case 2:
+ reg = usbmisc->base + MX53_USB_UH2_CTRL_OFFSET;
+ val = readl(reg) | MX53_BM_OVER_CUR_DIS_UHx;
+ break;
+ case 3:
+ reg = usbmisc->base + MX53_USB_UH3_CTRL_OFFSET;
+ val = readl(reg) | MX53_BM_OVER_CUR_DIS_UHx;
+ break;
+ }
+ if (reg && val)
+ writel(val, reg);
+ spin_unlock_irqrestore(&usbmisc->lock, flags);
+ }
+
+ return 0;
+}
+
+static int usbmisc_imx6q_init(struct device *dev)
+{
+
+ struct usbmisc_usb_device *usbdev;
+ unsigned long flags;
+ u32 reg;
+
+ usbdev = get_usbdev(dev);
+ if (IS_ERR(usbdev))
+ return PTR_ERR(usbdev);
+
+ if (usbdev->disable_oc) {
+ spin_lock_irqsave(&usbmisc->lock, flags);
+ reg = readl(usbmisc->base + usbdev->index * 4);
+ writel(reg | MX6_BM_OVER_CUR_DIS,
+ usbmisc->base + usbdev->index * 4);
+ spin_unlock_irqrestore(&usbmisc->lock, flags);
+ }
+
+ return 0;
+}
+
+static const struct usbmisc_ops imx25_usbmisc_ops = {
+ .post = usbmisc_imx25_post,
+};
+
+static const struct usbmisc_ops imx53_usbmisc_ops = {
+ .init = usbmisc_imx53_init,
+};
+
+static const struct usbmisc_ops imx6q_usbmisc_ops = {
+ .init = usbmisc_imx6q_init,
+};
+
+static const struct of_device_id usbmisc_imx_dt_ids[] = {
+ {
+ .compatible = "fsl,imx25-usbmisc",
+ .data = &imx25_usbmisc_ops,
+ },
+ {
+ .compatible = "fsl,imx53-usbmisc",
+ .data = &imx53_usbmisc_ops,
+ },
+ {
+ .compatible = "fsl,imx6q-usbmisc",
+ .data = &imx6q_usbmisc_ops,
+ },
+ { /* sentinel */ }
+};
+
+static int usbmisc_imx_probe(struct platform_device *pdev)
+{
+ struct resource *res;
+ struct imx_usbmisc *data;
+ int ret;
+ struct of_device_id *tmp_dev;
+
+ if (usbmisc)
+ return -EBUSY;
+
+ data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ spin_lock_init(&data->lock);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ data->base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(data->base))
+ return PTR_ERR(data->base);
+
+ data->clk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(data->clk)) {
+ dev_err(&pdev->dev,
+ "failed to get clock, err=%ld\n", PTR_ERR(data->clk));
+ return PTR_ERR(data->clk);
+ }
+
+ ret = clk_prepare_enable(data->clk);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "clk_prepare_enable failed, err=%d\n", ret);
+ return ret;
+ }
+
+ tmp_dev = (struct of_device_id *)
+ of_match_device(usbmisc_imx_dt_ids, &pdev->dev);
+ data->ops = (const struct usbmisc_ops *)tmp_dev->data;
+ usbmisc = data;
+ ret = usbmisc_set_ops(data->ops);
+ if (ret) {
+ usbmisc = NULL;
+ clk_disable_unprepare(data->clk);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int usbmisc_imx_remove(struct platform_device *pdev)
+{
+ usbmisc_unset_ops(usbmisc->ops);
+ clk_disable_unprepare(usbmisc->clk);
+ usbmisc = NULL;
+ return 0;
+}
+
+static struct platform_driver usbmisc_imx_driver = {
+ .probe = usbmisc_imx_probe,
+ .remove = usbmisc_imx_remove,
+ .driver = {
+ .name = "usbmisc_imx",
+ .owner = THIS_MODULE,
+ .of_match_table = usbmisc_imx_dt_ids,
+ },
+};
+
+int usbmisc_imx_drv_init(void)
+{
+ return platform_driver_register(&usbmisc_imx_driver);
+}
+subsys_initcall(usbmisc_imx_drv_init);
+
+void usbmisc_imx_drv_exit(void)
+{
+ platform_driver_unregister(&usbmisc_imx_driver);
+}
+module_exit(usbmisc_imx_drv_exit);
+
+MODULE_ALIAS("platform:usbmisc-imx");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("driver for imx usb non-core registers");
+MODULE_AUTHOR("Richard Zhao <richard.zhao@freescale.com>");
diff --git a/drivers/usb/chipidea/usbmisc_imx6q.c b/drivers/usb/chipidea/usbmisc_imx6q.c
deleted file mode 100644
index a1bce391e82..00000000000
--- a/drivers/usb/chipidea/usbmisc_imx6q.c
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * Copyright 2012 Freescale Semiconductor, Inc.
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <linux/module.h>
-#include <linux/of_platform.h>
-#include <linux/clk.h>
-#include <linux/err.h>
-#include <linux/io.h>
-
-#include "ci13xxx_imx.h"
-
-#define USB_DEV_MAX 4
-
-#define BM_OVER_CUR_DIS BIT(7)
-
-struct imx6q_usbmisc {
- void __iomem *base;
- spinlock_t lock;
- struct clk *clk;
- struct usbmisc_usb_device usbdev[USB_DEV_MAX];
-};
-
-static struct imx6q_usbmisc *usbmisc;
-
-static struct usbmisc_usb_device *get_usbdev(struct device *dev)
-{
- int i, ret;
-
- for (i = 0; i < USB_DEV_MAX; i++) {
- if (usbmisc->usbdev[i].dev == dev)
- return &usbmisc->usbdev[i];
- else if (!usbmisc->usbdev[i].dev)
- break;
- }
-
- if (i >= USB_DEV_MAX)
- return ERR_PTR(-EBUSY);
-
- ret = usbmisc_get_init_data(dev, &usbmisc->usbdev[i]);
- if (ret)
- return ERR_PTR(ret);
-
- return &usbmisc->usbdev[i];
-}
-
-static int usbmisc_imx6q_init(struct device *dev)
-{
-
- struct usbmisc_usb_device *usbdev;
- unsigned long flags;
- u32 reg;
-
- usbdev = get_usbdev(dev);
- if (IS_ERR(usbdev))
- return PTR_ERR(usbdev);
-
- if (usbdev->disable_oc) {
- spin_lock_irqsave(&usbmisc->lock, flags);
- reg = readl(usbmisc->base + usbdev->index * 4);
- writel(reg | BM_OVER_CUR_DIS,
- usbmisc->base + usbdev->index * 4);
- spin_unlock_irqrestore(&usbmisc->lock, flags);
- }
-
- return 0;
-}
-
-static const struct usbmisc_ops imx6q_usbmisc_ops = {
- .init = usbmisc_imx6q_init,
-};
-
-static const struct of_device_id usbmisc_imx6q_dt_ids[] = {
- { .compatible = "fsl,imx6q-usbmisc"},
- { /* sentinel */ }
-};
-
-static int usbmisc_imx6q_probe(struct platform_device *pdev)
-{
- struct resource *res;
- struct imx6q_usbmisc *data;
- int ret;
-
- if (usbmisc)
- return -EBUSY;
-
- data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
- if (!data)
- return -ENOMEM;
-
- spin_lock_init(&data->lock);
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- data->base = devm_ioremap_resource(&pdev->dev, res);
- if (IS_ERR(data->base))
- return PTR_ERR(data->base);
-
- data->clk = devm_clk_get(&pdev->dev, NULL);
- if (IS_ERR(data->clk)) {
- dev_err(&pdev->dev,
- "failed to get clock, err=%ld\n", PTR_ERR(data->clk));
- return PTR_ERR(data->clk);
- }
-
- ret = clk_prepare_enable(data->clk);
- if (ret) {
- dev_err(&pdev->dev,
- "clk_prepare_enable failed, err=%d\n", ret);
- return ret;
- }
-
- ret = usbmisc_set_ops(&imx6q_usbmisc_ops);
- if (ret) {
- clk_disable_unprepare(data->clk);
- return ret;
- }
-
- usbmisc = data;
-
- return 0;
-}
-
-static int usbmisc_imx6q_remove(struct platform_device *pdev)
-{
- usbmisc_unset_ops(&imx6q_usbmisc_ops);
- clk_disable_unprepare(usbmisc->clk);
- return 0;
-}
-
-static struct platform_driver usbmisc_imx6q_driver = {
- .probe = usbmisc_imx6q_probe,
- .remove = usbmisc_imx6q_remove,
- .driver = {
- .name = "usbmisc_imx6q",
- .owner = THIS_MODULE,
- .of_match_table = usbmisc_imx6q_dt_ids,
- },
-};
-
-int __init usbmisc_imx6q_drv_init(void)
-{
- return platform_driver_register(&usbmisc_imx6q_driver);
-}
-subsys_initcall(usbmisc_imx6q_drv_init);
-
-void __exit usbmisc_imx6q_drv_exit(void)
-{
- platform_driver_unregister(&usbmisc_imx6q_driver);
-}
-module_exit(usbmisc_imx6q_drv_exit);
-
-MODULE_ALIAS("platform:usbmisc-imx6q");
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("driver for imx6q usb non-core registers");
-MODULE_AUTHOR("Richard Zhao <richard.zhao@freescale.com>");
diff --git a/drivers/usb/class/Kconfig b/drivers/usb/class/Kconfig
index 316aac8e4ca..bb8b73682a7 100644
--- a/drivers/usb/class/Kconfig
+++ b/drivers/usb/class/Kconfig
@@ -2,11 +2,10 @@
# USB Class driver configuration
#
comment "USB Device Class drivers"
- depends on USB
config USB_ACM
tristate "USB Modem (CDC ACM) support"
- depends on USB && TTY
+ depends on TTY
---help---
This driver supports USB modems and ISDN adapters which support the
Communication Device Class Abstract Control Model interface.
@@ -21,7 +20,6 @@ config USB_ACM
config USB_PRINTER
tristate "USB Printer support"
- depends on USB
help
Say Y here if you want to connect a USB printer to your computer's
USB port.
@@ -31,7 +29,6 @@ config USB_PRINTER
config USB_WDM
tristate "USB Wireless Device Management support"
- depends on USB
---help---
This driver supports the WMC Device Management functionality
of cell phones compliant to the CDC WMC specification. You can use
@@ -42,7 +39,6 @@ config USB_WDM
config USB_TMC
tristate "USB Test and Measurement Class support"
- depends on USB
help
Say Y here if you want to connect a USB device that follows
the USB.org specification for USB Test and Measurement devices
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index 8ac25adf31b..171d7a9df3a 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -292,7 +292,6 @@ static void acm_ctrl_irq(struct urb *urb)
{
struct acm *acm = urb->context;
struct usb_cdc_notification *dr = urb->transfer_buffer;
- struct tty_struct *tty;
unsigned char *data;
int newctrl;
int retval;
@@ -327,17 +326,12 @@ static void acm_ctrl_irq(struct urb *urb)
break;
case USB_CDC_NOTIFY_SERIAL_STATE:
- tty = tty_port_tty_get(&acm->port);
newctrl = get_unaligned_le16(data);
- if (tty) {
- if (!acm->clocal &&
- (acm->ctrlin & ~newctrl & ACM_CTRL_DCD)) {
- dev_dbg(&acm->control->dev,
- "%s - calling hangup\n", __func__);
- tty_hangup(tty);
- }
- tty_kref_put(tty);
+ if (!acm->clocal && (acm->ctrlin & ~newctrl & ACM_CTRL_DCD)) {
+ dev_dbg(&acm->control->dev, "%s - calling hangup\n",
+ __func__);
+ tty_port_tty_hangup(&acm->port, false);
}
acm->ctrlin = newctrl;
@@ -475,15 +469,10 @@ static void acm_write_bulk(struct urb *urb)
static void acm_softint(struct work_struct *work)
{
struct acm *acm = container_of(work, struct acm, work);
- struct tty_struct *tty;
dev_vdbg(&acm->data->dev, "%s\n", __func__);
- tty = tty_port_tty_get(&acm->port);
- if (!tty)
- return;
- tty_wakeup(tty);
- tty_kref_put(tty);
+ tty_port_tty_wakeup(&acm->port);
}
/*
@@ -593,7 +582,6 @@ static void acm_port_destruct(struct tty_port *port)
dev_dbg(&acm->control->dev, "%s\n", __func__);
- tty_unregister_device(acm_tty_driver, acm->minor);
acm_release_minor(acm);
usb_put_intf(acm->control);
kfree(acm->country_codes);
@@ -840,14 +828,6 @@ static int acm_tty_ioctl(struct tty_struct *tty,
return rv;
}
-static const __u32 acm_tty_speed[] = {
- 0, 50, 75, 110, 134, 150, 200, 300, 600,
- 1200, 1800, 2400, 4800, 9600, 19200, 38400,
- 57600, 115200, 230400, 460800, 500000, 576000,
- 921600, 1000000, 1152000, 1500000, 2000000,
- 2500000, 3000000, 3500000, 4000000
-};
-
static void acm_tty_set_termios(struct tty_struct *tty,
struct ktermios *termios_old)
{
@@ -977,6 +957,8 @@ static int acm_probe(struct usb_interface *intf,
int num_rx_buf;
int i;
int combined_interfaces = 0;
+ struct device *tty_dev;
+ int rv = -ENOMEM;
/* normal quirks */
quirks = (unsigned long)id->driver_info;
@@ -1339,11 +1321,24 @@ skip_countries:
usb_set_intfdata(data_interface, acm);
usb_get_intf(control_interface);
- tty_port_register_device(&acm->port, acm_tty_driver, minor,
+ tty_dev = tty_port_register_device(&acm->port, acm_tty_driver, minor,
&control_interface->dev);
+ if (IS_ERR(tty_dev)) {
+ rv = PTR_ERR(tty_dev);
+ goto alloc_fail8;
+ }
return 0;
+alloc_fail8:
+ if (acm->country_codes) {
+ device_remove_file(&acm->control->dev,
+ &dev_attr_wCountryCodes);
+ device_remove_file(&acm->control->dev,
+ &dev_attr_iCountryCodeRelDate);
+ }
+ device_remove_file(&acm->control->dev, &dev_attr_bmCapabilities);
alloc_fail7:
+ usb_set_intfdata(intf, NULL);
for (i = 0; i < ACM_NW; i++)
usb_free_urb(acm->wb[i].urb);
alloc_fail6:
@@ -1359,7 +1354,7 @@ alloc_fail2:
acm_release_minor(acm);
kfree(acm);
alloc_fail:
- return -ENOMEM;
+ return rv;
}
static void stop_data_traffic(struct acm *acm)
@@ -1411,6 +1406,8 @@ static void acm_disconnect(struct usb_interface *intf)
stop_data_traffic(acm);
+ tty_unregister_device(acm_tty_driver, acm->minor);
+
usb_free_urb(acm->ctrlurb);
for (i = 0; i < ACM_NW; i++)
usb_free_urb(acm->wb[i].urb);
@@ -1503,15 +1500,9 @@ err_out:
static int acm_reset_resume(struct usb_interface *intf)
{
struct acm *acm = usb_get_intfdata(intf);
- struct tty_struct *tty;
- if (test_bit(ASYNCB_INITIALIZED, &acm->port.flags)) {
- tty = tty_port_tty_get(&acm->port);
- if (tty) {
- tty_hangup(tty);
- tty_kref_put(tty);
- }
- }
+ if (test_bit(ASYNCB_INITIALIZED, &acm->port.flags))
+ tty_port_tty_hangup(&acm->port, false);
return acm_resume(intf);
}
diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c
index 5f0cb417b73..8a230f0ef77 100644
--- a/drivers/usb/class/cdc-wdm.c
+++ b/drivers/usb/class/cdc-wdm.c
@@ -13,6 +13,7 @@
*/
#include <linux/kernel.h>
#include <linux/errno.h>
+#include <linux/ioctl.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/mutex.h>
@@ -56,6 +57,7 @@ MODULE_DEVICE_TABLE (usb, wdm_ids);
#define WDM_RESPONDING 7
#define WDM_SUSPENDING 8
#define WDM_RESETTING 9
+#define WDM_OVERFLOW 10
#define WDM_MAX 16
@@ -155,6 +157,7 @@ static void wdm_in_callback(struct urb *urb)
{
struct wdm_device *desc = urb->context;
int status = urb->status;
+ int length = urb->actual_length;
spin_lock(&desc->iuspin);
clear_bit(WDM_RESPONDING, &desc->flags);
@@ -185,9 +188,17 @@ static void wdm_in_callback(struct urb *urb)
}
desc->rerr = status;
- desc->reslength = urb->actual_length;
- memmove(desc->ubuf + desc->length, desc->inbuf, desc->reslength);
- desc->length += desc->reslength;
+ if (length + desc->length > desc->wMaxCommand) {
+ /* The buffer would overflow */
+ set_bit(WDM_OVERFLOW, &desc->flags);
+ } else {
+ /* we may already be in overflow */
+ if (!test_bit(WDM_OVERFLOW, &desc->flags)) {
+ memmove(desc->ubuf + desc->length, desc->inbuf, length);
+ desc->length += length;
+ desc->reslength = length;
+ }
+ }
skip_error:
wake_up(&desc->wait);
@@ -435,6 +446,11 @@ retry:
rv = -ENODEV;
goto err;
}
+ if (test_bit(WDM_OVERFLOW, &desc->flags)) {
+ clear_bit(WDM_OVERFLOW, &desc->flags);
+ rv = -ENOBUFS;
+ goto err;
+ }
i++;
if (file->f_flags & O_NONBLOCK) {
if (!test_bit(WDM_READ, &desc->flags)) {
@@ -478,6 +494,7 @@ retry:
spin_unlock_irq(&desc->iuspin);
goto retry;
}
+
if (!desc->reslength) { /* zero length read */
dev_dbg(&desc->intf->dev, "%s: zero length - clearing WDM_READ\n", __func__);
clear_bit(WDM_READ, &desc->flags);
@@ -628,6 +645,22 @@ static int wdm_release(struct inode *inode, struct file *file)
return 0;
}
+static long wdm_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ struct wdm_device *desc = file->private_data;
+ int rv = 0;
+
+ switch (cmd) {
+ case IOCTL_WDM_MAX_COMMAND:
+ if (copy_to_user((void __user *)arg, &desc->wMaxCommand, sizeof(desc->wMaxCommand)))
+ rv = -EFAULT;
+ break;
+ default:
+ rv = -ENOTTY;
+ }
+ return rv;
+}
+
static const struct file_operations wdm_fops = {
.owner = THIS_MODULE,
.read = wdm_read,
@@ -636,6 +669,8 @@ static const struct file_operations wdm_fops = {
.flush = wdm_flush,
.release = wdm_release,
.poll = wdm_poll,
+ .unlocked_ioctl = wdm_ioctl,
+ .compat_ioctl = wdm_ioctl,
.llseek = noop_llseek,
};
@@ -1004,6 +1039,7 @@ static int wdm_post_reset(struct usb_interface *intf)
struct wdm_device *desc = wdm_find_device(intf);
int rv;
+ clear_bit(WDM_OVERFLOW, &desc->flags);
clear_bit(WDM_RESETTING, &desc->flags);
rv = recover_from_urb_loss(desc);
mutex_unlock(&desc->wlock);
diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c
index 70d69d06054..4c5506ae5e4 100644
--- a/drivers/usb/class/usbtmc.c
+++ b/drivers/usb/class/usbtmc.c
@@ -718,50 +718,32 @@ exit:
static int usbtmc_ioctl_clear_out_halt(struct usbtmc_device_data *data)
{
- u8 *buffer;
int rv;
- buffer = kmalloc(2, GFP_KERNEL);
- if (!buffer)
- return -ENOMEM;
-
rv = usb_clear_halt(data->usb_dev,
usb_sndbulkpipe(data->usb_dev, data->bulk_out));
if (rv < 0) {
dev_err(&data->usb_dev->dev, "usb_control_msg returned %d\n",
rv);
- goto exit;
+ return rv;
}
- rv = 0;
-
-exit:
- kfree(buffer);
- return rv;
+ return 0;
}
static int usbtmc_ioctl_clear_in_halt(struct usbtmc_device_data *data)
{
- u8 *buffer;
int rv;
- buffer = kmalloc(2, GFP_KERNEL);
- if (!buffer)
- return -ENOMEM;
-
rv = usb_clear_halt(data->usb_dev,
usb_rcvbulkpipe(data->usb_dev, data->bulk_in));
if (rv < 0) {
dev_err(&data->usb_dev->dev, "usb_control_msg returned %d\n",
rv);
- goto exit;
+ return rv;
}
- rv = 0;
-
-exit:
- kfree(buffer);
- return rv;
+ return 0;
}
static int get_capabilities(struct usbtmc_device_data *data)
diff --git a/drivers/usb/core/Kconfig b/drivers/usb/core/Kconfig
index f70c1a1694a..8772b365929 100644
--- a/drivers/usb/core/Kconfig
+++ b/drivers/usb/core/Kconfig
@@ -3,7 +3,6 @@
#
config USB_DEBUG
bool "USB verbose debug messages"
- depends on USB
help
Say Y here if you want the USB core & hub drivers to produce a bunch
of debug messages to the system log. Select this if you are having a
@@ -11,7 +10,6 @@ config USB_DEBUG
config USB_ANNOUNCE_NEW_DEVICES
bool "USB announce new devices"
- depends on USB
default N
help
Say Y here if you want the USB core to always announce the
@@ -25,11 +23,24 @@ config USB_ANNOUNCE_NEW_DEVICES
log, or have any doubts about this, say N here.
comment "Miscellaneous USB options"
- depends on USB
+
+config USB_DEFAULT_PERSIST
+ bool "Enable USB persist by default"
+ default y
+ help
+ Say N here if you don't want USB power session persistance
+ enabled by default. If you say N it will make suspended USB
+ devices that lose power get reenumerated as if they had been
+ unplugged, causing any mounted filesystems to be lost. The
+ persist feature can still be enabled for individual devices
+ through the power/persist sysfs node. See
+ Documentation/usb/persist.txt for more info.
+
+ If you have any questions about this, say Y here, only say N
+ if you know exactly what you are doing.
config USB_DYNAMIC_MINORS
bool "Dynamic USB minor allocation"
- depends on USB
help
If you say Y here, the USB subsystem will use dynamic minor
allocation for any device that uses the USB major number.
@@ -38,25 +49,8 @@ config USB_DYNAMIC_MINORS
If you are unsure about this, say N here.
-config USB_SUSPEND
- bool "USB runtime power management (autosuspend) and wakeup"
- depends on USB && PM_RUNTIME
- help
- If you say Y here, you can use driver calls or the sysfs
- "power/control" file to enable or disable autosuspend for
- individual USB peripherals (see
- Documentation/usb/power-management.txt for more details).
-
- Also, USB "remote wakeup" signaling is supported, whereby some
- USB devices (like keyboards and network adapters) can wake up
- their parent hub. That wakeup cascades up the USB tree, and
- could wake the system from states like suspend-to-RAM.
-
- If you are unsure about this, say N here.
-
config USB_OTG
bool "OTG support"
- depends on USB
depends on USB_SUSPEND
default n
help
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index 8823e98989f..caefc800f29 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -739,6 +739,8 @@ static int check_ctrlrecip(struct dev_state *ps, unsigned int requesttype,
index &= 0xff;
switch (requesttype & USB_RECIP_MASK) {
case USB_RECIP_ENDPOINT:
+ if ((index & ~USB_DIR_IN) == 0)
+ return 0;
ret = findintfep(ps->dev, index);
if (ret >= 0)
ret = checkintf(ps, ret);
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index d938b2b99e3..6eab440e154 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -1196,9 +1196,14 @@ done:
*
* This is the central routine for suspending USB devices. It calls the
* suspend methods for all the interface drivers in @udev and then calls
- * the suspend method for @udev itself. If an error occurs at any stage,
- * all the interfaces which were suspended are resumed so that they remain
- * in the same state as the device.
+ * the suspend method for @udev itself. When the routine is called in
+ * autosuspend, if an error occurs at any stage, all the interfaces
+ * which were suspended are resumed so that they remain in the same
+ * state as the device, but when called from system sleep, all error
+ * from suspend methods of interfaces and the non-root-hub device itself
+ * are simply ignored, so all suspended interfaces are only resumed
+ * to the device's state when @udev is root-hub and its suspend method
+ * returns failure.
*
* Autosuspend requests originating from a child device or an interface
* driver may be made without the protection of @udev's device lock, but
@@ -1248,10 +1253,12 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg)
/* If the suspend failed, resume interfaces that did get suspended */
if (status != 0) {
- msg.event ^= (PM_EVENT_SUSPEND | PM_EVENT_RESUME);
- while (++i < n) {
- intf = udev->actconfig->interface[i];
- usb_resume_interface(udev, intf, msg, 0);
+ if (udev->actconfig) {
+ msg.event ^= (PM_EVENT_SUSPEND | PM_EVENT_RESUME);
+ while (++i < n) {
+ intf = udev->actconfig->interface[i];
+ usb_resume_interface(udev, intf, msg, 0);
+ }
}
/* If the suspend succeeded then prevent any more URB submissions
@@ -1407,7 +1414,7 @@ int usb_resume(struct device *dev, pm_message_t msg)
#endif /* CONFIG_PM */
-#ifdef CONFIG_USB_SUSPEND
+#ifdef CONFIG_PM_RUNTIME
/**
* usb_enable_autosuspend - allow a USB device to be autosuspended
@@ -1775,7 +1782,7 @@ int usb_set_usb2_hardware_lpm(struct usb_device *udev, int enable)
return ret;
}
-#endif /* CONFIG_USB_SUSPEND */
+#endif /* CONFIG_PM_RUNTIME */
struct bus_type usb_bus_type = {
.name = "usb",
diff --git a/drivers/usb/core/generic.c b/drivers/usb/core/generic.c
index 271e761f563..acbfeb0a011 100644
--- a/drivers/usb/core/generic.c
+++ b/drivers/usb/core/generic.c
@@ -169,7 +169,7 @@ static int generic_probe(struct usb_device *udev)
c = usb_choose_configuration(udev);
if (c >= 0) {
err = usb_set_configuration(udev, c);
- if (err) {
+ if (err && err != -ENODEV) {
dev_err(&udev->dev, "can't set config #%d, error %d\n",
c, err);
/* This need not be fatal. The user can try to
diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
index 622b4a48e73..caeb8d6d39f 100644
--- a/drivers/usb/core/hcd-pci.c
+++ b/drivers/usb/core/hcd-pci.c
@@ -37,119 +37,123 @@
/* PCI-based HCs are common, but plenty of non-PCI HCs are used too */
-#ifdef CONFIG_PM_SLEEP
-
-/* Coordinate handoffs between EHCI and companion controllers
- * during system resume
+/*
+ * Coordinate handoffs between EHCI and companion controllers
+ * during EHCI probing and system resume.
*/
-static DEFINE_MUTEX(companions_mutex);
+static DECLARE_RWSEM(companions_rwsem);
#define CL_UHCI PCI_CLASS_SERIAL_USB_UHCI
#define CL_OHCI PCI_CLASS_SERIAL_USB_OHCI
#define CL_EHCI PCI_CLASS_SERIAL_USB_EHCI
-enum companion_action {
- SET_HS_COMPANION, CLEAR_HS_COMPANION, WAIT_FOR_COMPANIONS
-};
+static inline int is_ohci_or_uhci(struct pci_dev *pdev)
+{
+ return pdev->class == CL_OHCI || pdev->class == CL_UHCI;
+}
+
+typedef void (*companion_fn)(struct pci_dev *pdev, struct usb_hcd *hcd,
+ struct pci_dev *companion, struct usb_hcd *companion_hcd);
-static void companion_common(struct pci_dev *pdev, struct usb_hcd *hcd,
- enum companion_action action)
+/* Iterate over PCI devices in the same slot as pdev and call fn for each */
+static void for_each_companion(struct pci_dev *pdev, struct usb_hcd *hcd,
+ companion_fn fn)
{
struct pci_dev *companion;
struct usb_hcd *companion_hcd;
unsigned int slot = PCI_SLOT(pdev->devfn);
- /* Iterate through other PCI functions in the same slot.
- * If pdev is OHCI or UHCI then we are looking for EHCI, and
- * vice versa.
+ /*
+ * Iterate through other PCI functions in the same slot.
+ * If the function's drvdata isn't set then it isn't bound to
+ * a USB host controller driver, so skip it.
*/
companion = NULL;
for_each_pci_dev(companion) {
if (companion->bus != pdev->bus ||
PCI_SLOT(companion->devfn) != slot)
continue;
-
companion_hcd = pci_get_drvdata(companion);
if (!companion_hcd)
continue;
-
- /* For SET_HS_COMPANION, store a pointer to the EHCI bus in
- * the OHCI/UHCI companion bus structure.
- * For CLEAR_HS_COMPANION, clear the pointer to the EHCI bus
- * in the OHCI/UHCI companion bus structure.
- * For WAIT_FOR_COMPANIONS, wait until the OHCI/UHCI
- * companion controllers have fully resumed.
- */
-
- if ((pdev->class == CL_OHCI || pdev->class == CL_UHCI) &&
- companion->class == CL_EHCI) {
- /* action must be SET_HS_COMPANION */
- dev_dbg(&companion->dev, "HS companion for %s\n",
- dev_name(&pdev->dev));
- hcd->self.hs_companion = &companion_hcd->self;
-
- } else if (pdev->class == CL_EHCI &&
- (companion->class == CL_OHCI ||
- companion->class == CL_UHCI)) {
- switch (action) {
- case SET_HS_COMPANION:
- dev_dbg(&pdev->dev, "HS companion for %s\n",
- dev_name(&companion->dev));
- companion_hcd->self.hs_companion = &hcd->self;
- break;
- case CLEAR_HS_COMPANION:
- companion_hcd->self.hs_companion = NULL;
- break;
- case WAIT_FOR_COMPANIONS:
- device_pm_wait_for_dev(&pdev->dev,
- &companion->dev);
- break;
- }
- }
+ fn(pdev, hcd, companion, companion_hcd);
}
}
-static void set_hs_companion(struct pci_dev *pdev, struct usb_hcd *hcd)
+/*
+ * We're about to add an EHCI controller, which will unceremoniously grab
+ * all the port connections away from its companions. To prevent annoying
+ * error messages, lock the companion's root hub and gracefully unconfigure
+ * it beforehand. Leave it locked until the EHCI controller is all set.
+ */
+static void ehci_pre_add(struct pci_dev *pdev, struct usb_hcd *hcd,
+ struct pci_dev *companion, struct usb_hcd *companion_hcd)
{
- mutex_lock(&companions_mutex);
- dev_set_drvdata(&pdev->dev, hcd);
- companion_common(pdev, hcd, SET_HS_COMPANION);
- mutex_unlock(&companions_mutex);
+ struct usb_device *udev;
+
+ if (is_ohci_or_uhci(companion)) {
+ udev = companion_hcd->self.root_hub;
+ usb_lock_device(udev);
+ usb_set_configuration(udev, 0);
+ }
}
-static void clear_hs_companion(struct pci_dev *pdev, struct usb_hcd *hcd)
+/*
+ * Adding the EHCI controller has either succeeded or failed. Set the
+ * companion pointer accordingly, and in either case, reconfigure and
+ * unlock the root hub.
+ */
+static void ehci_post_add(struct pci_dev *pdev, struct usb_hcd *hcd,
+ struct pci_dev *companion, struct usb_hcd *companion_hcd)
{
- mutex_lock(&companions_mutex);
- dev_set_drvdata(&pdev->dev, NULL);
+ struct usb_device *udev;
- /* If pdev is OHCI or UHCI, just clear its hs_companion pointer */
- if (pdev->class == CL_OHCI || pdev->class == CL_UHCI)
- hcd->self.hs_companion = NULL;
+ if (is_ohci_or_uhci(companion)) {
+ if (dev_get_drvdata(&pdev->dev)) { /* Succeeded */
+ dev_dbg(&pdev->dev, "HS companion for %s\n",
+ dev_name(&companion->dev));
+ companion_hcd->self.hs_companion = &hcd->self;
+ }
+ udev = companion_hcd->self.root_hub;
+ usb_set_configuration(udev, 1);
+ usb_unlock_device(udev);
+ }
+}
- /* Otherwise search for companion buses and clear their pointers */
- else
- companion_common(pdev, hcd, CLEAR_HS_COMPANION);
- mutex_unlock(&companions_mutex);
+/*
+ * We just added a non-EHCI controller. Find the EHCI controller to
+ * which it is a companion, and store a pointer to the bus structure.
+ */
+static void non_ehci_add(struct pci_dev *pdev, struct usb_hcd *hcd,
+ struct pci_dev *companion, struct usb_hcd *companion_hcd)
+{
+ if (is_ohci_or_uhci(pdev) && companion->class == CL_EHCI) {
+ dev_dbg(&pdev->dev, "FS/LS companion for %s\n",
+ dev_name(&companion->dev));
+ hcd->self.hs_companion = &companion_hcd->self;
+ }
}
-static void wait_for_companions(struct pci_dev *pdev, struct usb_hcd *hcd)
+/* We are removing an EHCI controller. Clear the companions' pointers. */
+static void ehci_remove(struct pci_dev *pdev, struct usb_hcd *hcd,
+ struct pci_dev *companion, struct usb_hcd *companion_hcd)
{
- /* Only EHCI controllers need to wait.
- * No locking is needed because a controller cannot be resumed
- * while one of its companions is getting unbound.
- */
- if (pdev->class == CL_EHCI)
- companion_common(pdev, hcd, WAIT_FOR_COMPANIONS);
+ if (is_ohci_or_uhci(companion))
+ companion_hcd->self.hs_companion = NULL;
}
-#else /* !CONFIG_PM_SLEEP */
+#ifdef CONFIG_PM
-static inline void set_hs_companion(struct pci_dev *d, struct usb_hcd *h) {}
-static inline void clear_hs_companion(struct pci_dev *d, struct usb_hcd *h) {}
-static inline void wait_for_companions(struct pci_dev *d, struct usb_hcd *h) {}
+/* An EHCI controller must wait for its companions before resuming. */
+static void ehci_wait_for_companions(struct pci_dev *pdev, struct usb_hcd *hcd,
+ struct pci_dev *companion, struct usb_hcd *companion_hcd)
+{
+ if (is_ohci_or_uhci(companion))
+ device_pm_wait_for_dev(&pdev->dev, &companion->dev);
+}
-#endif /* !CONFIG_PM_SLEEP */
+#endif /* CONFIG_PM */
/*-------------------------------------------------------------------------*/
@@ -173,6 +177,7 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
struct hc_driver *driver;
struct usb_hcd *hcd;
int retval;
+ int hcd_irq = 0;
if (usb_disabled())
return -ENODEV;
@@ -187,15 +192,19 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
return -ENODEV;
dev->current_state = PCI_D0;
- /* The xHCI driver supports MSI and MSI-X,
- * so don't fail if the BIOS doesn't provide a legacy IRQ.
+ /*
+ * The xHCI driver has its own irq management
+ * make sure irq setup is not touched for xhci in generic hcd code
*/
- if (!dev->irq && (driver->flags & HCD_MASK) != HCD_USB3) {
- dev_err(&dev->dev,
- "Found HC with no IRQ. Check BIOS/PCI %s setup!\n",
- pci_name(dev));
- retval = -ENODEV;
- goto disable_pci;
+ if ((driver->flags & HCD_MASK) != HCD_USB3) {
+ if (!dev->irq) {
+ dev_err(&dev->dev,
+ "Found HC with no IRQ. Check BIOS/PCI %s setup!\n",
+ pci_name(dev));
+ retval = -ENODEV;
+ goto disable_pci;
+ }
+ hcd_irq = dev->irq;
}
hcd = usb_create_hcd(driver, &dev->dev, pci_name(dev));
@@ -212,7 +221,7 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
driver->description)) {
dev_dbg(&dev->dev, "controller already in use\n");
retval = -EBUSY;
- goto clear_companion;
+ goto put_hcd;
}
hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len);
if (hcd->regs == NULL) {
@@ -239,16 +248,35 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
if (region == PCI_ROM_RESOURCE) {
dev_dbg(&dev->dev, "no i/o regions available\n");
retval = -EBUSY;
- goto clear_companion;
+ goto put_hcd;
}
}
pci_set_master(dev);
- retval = usb_add_hcd(hcd, dev->irq, IRQF_SHARED);
+ /* Note: dev_set_drvdata must be called while holding the rwsem */
+ if (dev->class == CL_EHCI) {
+ down_write(&companions_rwsem);
+ dev_set_drvdata(&dev->dev, hcd);
+ for_each_companion(dev, hcd, ehci_pre_add);
+ retval = usb_add_hcd(hcd, hcd_irq, IRQF_SHARED);
+ if (retval != 0)
+ dev_set_drvdata(&dev->dev, NULL);
+ for_each_companion(dev, hcd, ehci_post_add);
+ up_write(&companions_rwsem);
+ } else {
+ down_read(&companions_rwsem);
+ dev_set_drvdata(&dev->dev, hcd);
+ retval = usb_add_hcd(hcd, hcd_irq, IRQF_SHARED);
+ if (retval != 0)
+ dev_set_drvdata(&dev->dev, NULL);
+ else
+ for_each_companion(dev, hcd, non_ehci_add);
+ up_read(&companions_rwsem);
+ }
+
if (retval != 0)
goto unmap_registers;
- set_hs_companion(dev, hcd);
if (pci_dev_run_wake(dev))
pm_runtime_put_noidle(&dev->dev);
@@ -261,8 +289,7 @@ release_mem_region:
release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
} else
release_region(hcd->rsrc_start, hcd->rsrc_len);
-clear_companion:
- clear_hs_companion(dev, hcd);
+put_hcd:
usb_put_hcd(hcd);
disable_pci:
pci_disable_device(dev);
@@ -305,14 +332,29 @@ void usb_hcd_pci_remove(struct pci_dev *dev)
usb_hcd_irq(0, hcd);
local_irq_enable();
- usb_remove_hcd(hcd);
+ /* Note: dev_set_drvdata must be called while holding the rwsem */
+ if (dev->class == CL_EHCI) {
+ down_write(&companions_rwsem);
+ for_each_companion(dev, hcd, ehci_remove);
+ usb_remove_hcd(hcd);
+ dev_set_drvdata(&dev->dev, NULL);
+ up_write(&companions_rwsem);
+ } else {
+ /* Not EHCI; just clear the companion pointer */
+ down_read(&companions_rwsem);
+ hcd->self.hs_companion = NULL;
+ usb_remove_hcd(hcd);
+ dev_set_drvdata(&dev->dev, NULL);
+ up_read(&companions_rwsem);
+ }
+
if (hcd->driver->flags & HCD_MEMORY) {
iounmap(hcd->regs);
release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
} else {
release_region(hcd->rsrc_start, hcd->rsrc_len);
}
- clear_hs_companion(dev, hcd);
+
usb_put_hcd(hcd);
pci_disable_device(dev);
}
@@ -458,8 +500,15 @@ static int resume_common(struct device *dev, int event)
pci_set_master(pci_dev);
if (hcd->driver->pci_resume && !HCD_DEAD(hcd)) {
- if (event != PM_EVENT_AUTO_RESUME)
- wait_for_companions(pci_dev, hcd);
+
+ /*
+ * Only EHCI controllers have to wait for their companions.
+ * No locking is needed because PCI controller drivers do not
+ * get unbound during system resume.
+ */
+ if (pci_dev->class == CL_EHCI && event != PM_EVENT_AUTO_RESUME)
+ for_each_companion(pci_dev, hcd,
+ ehci_wait_for_companions);
retval = hcd->driver->pci_resume(hcd,
event == PM_EVENT_RESTORE);
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 99b34a30354..d53547d2e4c 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -2125,7 +2125,7 @@ int hcd_bus_resume(struct usb_device *rhdev, pm_message_t msg)
#endif /* CONFIG_PM */
-#ifdef CONFIG_USB_SUSPEND
+#ifdef CONFIG_PM_RUNTIME
/* Workqueue routine for root-hub remote wakeup */
static void hcd_resume_work(struct work_struct *work)
@@ -2160,7 +2160,7 @@ void usb_hcd_resume_root_hub (struct usb_hcd *hcd)
}
EXPORT_SYMBOL_GPL(usb_hcd_resume_root_hub);
-#endif /* CONFIG_USB_SUSPEND */
+#endif /* CONFIG_PM_RUNTIME */
/*-------------------------------------------------------------------------*/
@@ -2336,7 +2336,7 @@ struct usb_hcd *usb_create_shared_hcd(const struct hc_driver *driver,
init_timer(&hcd->rh_timer);
hcd->rh_timer.function = rh_timer_func;
hcd->rh_timer.data = (unsigned long) hcd;
-#ifdef CONFIG_USB_SUSPEND
+#ifdef CONFIG_PM_RUNTIME
INIT_WORK(&hcd->wakeup_work, hcd_resume_work);
#endif
@@ -2412,6 +2412,14 @@ int usb_hcd_is_primary_hcd(struct usb_hcd *hcd)
}
EXPORT_SYMBOL_GPL(usb_hcd_is_primary_hcd);
+int usb_hcd_find_raw_port_number(struct usb_hcd *hcd, int port1)
+{
+ if (!hcd->driver->find_raw_port_number)
+ return port1;
+
+ return hcd->driver->find_raw_port_number(hcd, port1);
+}
+
static int usb_hcd_request_irqs(struct usb_hcd *hcd,
unsigned int irqnum, unsigned long irqflags)
{
@@ -2582,7 +2590,7 @@ error_create_attr_group:
hcd->rh_registered = 0;
spin_unlock_irq(&hcd_root_hub_lock);
-#ifdef CONFIG_USB_SUSPEND
+#ifdef CONFIG_PM_RUNTIME
cancel_work_sync(&hcd->wakeup_work);
#endif
mutex_lock(&usb_bus_list_lock);
@@ -2637,7 +2645,7 @@ void usb_remove_hcd(struct usb_hcd *hcd)
hcd->rh_registered = 0;
spin_unlock_irq (&hcd_root_hub_lock);
-#ifdef CONFIG_USB_SUSPEND
+#ifdef CONFIG_PM_RUNTIME
cancel_work_sync(&hcd->wakeup_work);
#endif
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 5480352f984..feef9351463 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -555,8 +555,9 @@ static int hub_port_status(struct usb_hub *hub, int port1,
mutex_lock(&hub->status_mutex);
ret = get_port_status(hub->hdev, port1, &hub->status->port);
if (ret < 4) {
- dev_err(hub->intfdev,
- "%s failed (err = %d)\n", __func__, ret);
+ if (ret != -ENODEV)
+ dev_err(hub->intfdev,
+ "%s failed (err = %d)\n", __func__, ret);
if (ret >= 0)
ret = -EIO;
} else {
@@ -699,7 +700,7 @@ static void hub_tt_work(struct work_struct *work)
/* drop lock so HCD can concurrently report other TT errors */
spin_unlock_irqrestore (&hub->tt.lock, flags);
status = hub_clear_tt_buffer (hdev, clear->devinfo, clear->tt);
- if (status)
+ if (status && status != -ENODEV)
dev_err (&hdev->dev,
"clear tt %d (%04x) error %d\n",
clear->tt, clear->devinfo, status);
@@ -837,10 +838,11 @@ static int hub_hub_status(struct usb_hub *hub,
mutex_lock(&hub->status_mutex);
ret = get_hub_status(hub->hdev, &hub->status->hub);
- if (ret < 0)
- dev_err (hub->intfdev,
- "%s failed (err = %d)\n", __func__, ret);
- else {
+ if (ret < 0) {
+ if (ret != -ENODEV)
+ dev_err(hub->intfdev,
+ "%s failed (err = %d)\n", __func__, ret);
+ } else {
*status = le16_to_cpu(hub->status->hub.wHubStatus);
*change = le16_to_cpu(hub->status->hub.wHubChange);
ret = 0;
@@ -877,11 +879,8 @@ static int hub_usb3_port_disable(struct usb_hub *hub, int port1)
return -EINVAL;
ret = hub_set_port_link_state(hub, port1, USB_SS_PORT_LS_SS_DISABLED);
- if (ret) {
- dev_err(hub->intfdev, "cannot disable port %d (err = %d)\n",
- port1, ret);
+ if (ret)
return ret;
- }
/* Wait for the link to enter the disabled state. */
for (total_time = 0; ; total_time += HUB_DEBOUNCE_STEP) {
@@ -918,7 +917,7 @@ static int hub_port_disable(struct usb_hub *hub, int port1, int set_state)
ret = usb_clear_port_feature(hdev, port1,
USB_PORT_FEAT_ENABLE);
}
- if (ret)
+ if (ret && ret != -ENODEV)
dev_err(hub->intfdev, "cannot disable port %d (err = %d)\n",
port1, ret);
return ret;
@@ -1317,6 +1316,10 @@ static int hub_configure(struct usb_hub *hub,
message = "hub has too many ports!";
ret = -ENODEV;
goto fail;
+ } else if (hub->descriptor->bNbrPorts == 0) {
+ message = "hub doesn't have any ports!";
+ ret = -ENODEV;
+ goto fail;
}
hdev->maxchild = hub->descriptor->bNbrPorts;
@@ -2192,8 +2195,9 @@ static int usb_enumerate_device(struct usb_device *udev)
if (udev->config == NULL) {
err = usb_get_configuration(udev);
if (err < 0) {
- dev_err(&udev->dev, "can't read configurations, error %d\n",
- err);
+ if (err != -ENODEV)
+ dev_err(&udev->dev, "can't read configurations, error %d\n",
+ err);
return err;
}
}
@@ -2640,14 +2644,16 @@ static int hub_port_reset(struct usb_hub *hub, int port1,
status = set_port_feature(hub->hdev, port1, (warm ?
USB_PORT_FEAT_BH_PORT_RESET :
USB_PORT_FEAT_RESET));
- if (status) {
+ if (status == -ENODEV) {
+ ; /* The hub is gone */
+ } else if (status) {
dev_err(hub->intfdev,
"cannot %sreset port %d (err = %d)\n",
warm ? "warm " : "", port1, status);
} else {
status = hub_port_wait_reset(hub, port1, udev, delay,
warm);
- if (status && status != -ENOTCONN)
+ if (status && status != -ENOTCONN && status != -ENODEV)
dev_dbg(hub->intfdev,
"port_wait_reset: err = %d\n",
status);
@@ -2821,7 +2827,7 @@ void usb_enable_ltm(struct usb_device *udev)
}
EXPORT_SYMBOL_GPL(usb_enable_ltm);
-#ifdef CONFIG_USB_SUSPEND
+#ifdef CONFIG_PM
/*
* usb_disable_function_remotewakeup - disable usb3.0
* device's function remote wakeup
@@ -2880,9 +2886,11 @@ static int usb_disable_function_remotewakeup(struct usb_device *udev)
* Linux (2.6) currently has NO mechanisms to initiate that: no khubd
* timer, no SRP, no requests through sysfs.
*
- * If CONFIG_USB_SUSPEND isn't enabled, devices only really suspend when
- * the root hub for their bus goes into global suspend ... so we don't
- * (falsely) update the device power state to say it suspended.
+ * If Runtime PM isn't enabled or used, non-SuperSpeed devices really get
+ * suspended only when their bus goes into global suspend (i.e., the root
+ * hub is suspended). Nevertheless, we change @udev->state to
+ * USB_STATE_SUSPENDED as this is the device's "logical" state. The actual
+ * upstream port setting is stored in @udev->port_is_suspended.
*
* Returns 0 on success, else negative errno.
*/
@@ -2893,6 +2901,7 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
enum pm_qos_flags_status pm_qos_stat;
int port1 = udev->portnum;
int status;
+ bool really_suspend = true;
/* enable remote wakeup when appropriate; this lets the device
* wake up the upstream hub (including maybe the root hub).
@@ -2949,9 +2958,19 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
/* see 7.1.7.6 */
if (hub_is_superspeed(hub->hdev))
status = hub_set_port_link_state(hub, port1, USB_SS_PORT_LS_U3);
- else
+ else if (PMSG_IS_AUTO(msg))
status = set_port_feature(hub->hdev, port1,
USB_PORT_FEAT_SUSPEND);
+ /*
+ * For system suspend, we do not need to enable the suspend feature
+ * on individual USB-2 ports. The devices will automatically go
+ * into suspend a few ms after the root hub stops sending packets.
+ * The USB 2.0 spec calls this "global suspend".
+ */
+ else {
+ really_suspend = false;
+ status = 0;
+ }
if (status) {
dev_dbg(hub->intfdev, "can't suspend port %d, status %d\n",
port1, status);
@@ -2987,8 +3006,10 @@ 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);
+ if (really_suspend) {
+ udev->port_is_suspended = 1;
+ msleep(10);
+ }
}
/*
@@ -3226,6 +3247,10 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg)
return status;
}
+#endif /* CONFIG_PM */
+
+#ifdef CONFIG_PM_RUNTIME
+
/* caller has locked udev */
int usb_remote_wakeup(struct usb_device *udev)
{
@@ -3242,38 +3267,6 @@ int usb_remote_wakeup(struct usb_device *udev)
return status;
}
-#else /* CONFIG_USB_SUSPEND */
-
-/* When CONFIG_USB_SUSPEND isn't set, we never suspend or resume any ports. */
-
-int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
-{
- return 0;
-}
-
-/* However we may need to do a reset-resume */
-
-int usb_port_resume(struct usb_device *udev, pm_message_t msg)
-{
- struct usb_hub *hub = usb_hub_to_struct_hub(udev->parent);
- int port1 = udev->portnum;
- int status;
- u16 portchange, portstatus;
-
- status = hub_port_status(hub, port1, &portstatus, &portchange);
- status = check_port_resume_type(udev,
- hub, port1, status, portchange, portstatus);
-
- if (status) {
- dev_dbg(&udev->dev, "can't resume, status %d\n", status);
- hub_port_logical_disconnect(hub, port1);
- } else if (udev->reset_resume) {
- dev_dbg(&udev->dev, "reset-resume\n");
- status = usb_reset_and_verify_device(udev);
- }
- return status;
-}
-
#endif
static int check_ports_changed(struct usb_hub *hub)
@@ -4090,9 +4083,9 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
goto fail;
}
if (r) {
- dev_err(&udev->dev,
- "device descriptor read/64, error %d\n",
- r);
+ if (r != -ENODEV)
+ dev_err(&udev->dev, "device descriptor read/64, error %d\n",
+ r);
retval = -EMSGSIZE;
continue;
}
@@ -4112,9 +4105,9 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
msleep(200);
}
if (retval < 0) {
- dev_err(&udev->dev,
- "device not accepting address %d, error %d\n",
- devnum, retval);
+ if (retval != -ENODEV)
+ dev_err(&udev->dev, "device not accepting address %d, error %d\n",
+ devnum, retval);
goto fail;
}
if (udev->speed == USB_SPEED_SUPER) {
@@ -4136,7 +4129,8 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
retval = usb_get_device_descriptor(udev, 8);
if (retval < 8) {
- dev_err(&udev->dev,
+ if (retval != -ENODEV)
+ dev_err(&udev->dev,
"device descriptor read/8, error %d\n",
retval);
if (retval >= 0)
@@ -4190,8 +4184,9 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
retval = usb_get_device_descriptor(udev, USB_DT_DEVICE_SIZE);
if (retval < (signed)sizeof(udev->descriptor)) {
- dev_err(&udev->dev, "device descriptor read/all, error %d\n",
- retval);
+ if (retval != -ENODEV)
+ dev_err(&udev->dev, "device descriptor read/all, error %d\n",
+ retval);
if (retval >= 0)
retval = -ENOMSG;
goto fail;
@@ -4333,7 +4328,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
if (portstatus & USB_PORT_STAT_ENABLE) {
status = 0; /* Nothing to do */
-#ifdef CONFIG_USB_SUSPEND
+#ifdef CONFIG_PM_RUNTIME
} else if (udev->state == USB_STATE_SUSPENDED &&
udev->persist_enabled) {
/* For a suspended device, treat this as a
@@ -4373,7 +4368,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
USB_PORT_STAT_C_ENABLE)) {
status = hub_port_debounce_be_stable(hub, port1);
if (status < 0) {
- if (printk_ratelimit())
+ if (status != -ENODEV && printk_ratelimit())
dev_err(hub_dev, "connect-debounce failed, "
"port %d disabled\n", port1);
portstatus &= ~USB_PORT_STAT_CONNECTION;
@@ -4402,6 +4397,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
else
unit_load = 100;
+ status = 0;
for (i = 0; i < SET_CONFIG_TRIES; i++) {
/* reallocate for each attempt, since references
@@ -4526,9 +4522,11 @@ loop:
}
if (hub->hdev->parent ||
!hcd->driver->port_handed_over ||
- !(hcd->driver->port_handed_over)(hcd, port1))
- dev_err(hub_dev, "unable to enumerate USB device on port %d\n",
- port1);
+ !(hcd->driver->port_handed_over)(hcd, port1)) {
+ if (status != -ENOTCONN && status != -ENODEV)
+ dev_err(hub_dev, "unable to enumerate USB device on port %d\n",
+ port1);
+ }
done:
hub_port_disable(hub, port1, 1);
diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c
index 797f9d51473..b8bad294eeb 100644
--- a/drivers/usb/core/port.c
+++ b/drivers/usb/core/port.c
@@ -67,11 +67,10 @@ static void usb_port_device_release(struct device *dev)
{
struct usb_port *port_dev = to_usb_port(dev);
- dev_pm_qos_hide_flags(dev);
kfree(port_dev);
}
-#ifdef CONFIG_USB_SUSPEND
+#ifdef CONFIG_PM_RUNTIME
static int usb_port_runtime_resume(struct device *dev)
{
struct usb_port *port_dev = to_usb_port(dev);
@@ -139,7 +138,7 @@ static int usb_port_runtime_suspend(struct device *dev)
#endif
static const struct dev_pm_ops usb_port_pm_ops = {
-#ifdef CONFIG_USB_SUSPEND
+#ifdef CONFIG_PM_RUNTIME
.runtime_suspend = usb_port_runtime_suspend,
.runtime_resume = usb_port_runtime_resume,
.runtime_idle = pm_generic_runtime_idle,
diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c
index 3113c1d7144..ab5638d9c70 100644
--- a/drivers/usb/core/quirks.c
+++ b/drivers/usb/core/quirks.c
@@ -201,20 +201,14 @@ void usb_detect_quirks(struct usb_device *udev)
dev_dbg(&udev->dev, "USB quirks for this device: %x\n",
udev->quirks);
- /* For the present, all devices default to USB-PERSIST enabled */
-#if 0 /* was: #ifdef CONFIG_PM */
- /* Hubs are automatically enabled for USB-PERSIST */
- if (udev->descriptor.bDeviceClass == USB_CLASS_HUB)
+#ifdef CONFIG_USB_DEFAULT_PERSIST
+ if (!(udev->quirks & USB_QUIRK_RESET))
udev->persist_enabled = 1;
-
#else
- /* In the absence of PM, we can safely enable USB-PERSIST
- * for all devices. It will affect things like hub resets
- * and EMF-related port disables.
- */
- if (!(udev->quirks & USB_QUIRK_RESET))
+ /* Hubs are automatically enabled for USB-PERSIST */
+ if (udev->descriptor.bDeviceClass == USB_CLASS_HUB)
udev->persist_enabled = 1;
-#endif /* CONFIG_PM */
+#endif /* CONFIG_USB_DEFAULT_PERSIST */
}
void usb_detect_interface_quirks(struct usb_device *udev)
diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
index 3f81a3dc686..aa38db44818 100644
--- a/drivers/usb/core/sysfs.c
+++ b/drivers/usb/core/sysfs.c
@@ -338,7 +338,7 @@ static void remove_persist_attributes(struct device *dev)
#endif /* CONFIG_PM */
-#ifdef CONFIG_USB_SUSPEND
+#ifdef CONFIG_PM_RUNTIME
static ssize_t
show_connected_duration(struct device *dev, struct device_attribute *attr,
@@ -544,7 +544,7 @@ static void remove_power_attributes(struct device *dev)
#define add_power_attributes(dev) 0
#define remove_power_attributes(dev) do {} while (0)
-#endif /* CONFIG_USB_SUSPEND */
+#endif /* CONFIG_PM_RUNTIME */
/* Descriptor fields */
diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
index e0d9d948218..16927fa88fb 100644
--- a/drivers/usb/core/urb.c
+++ b/drivers/usb/core/urb.c
@@ -683,10 +683,13 @@ EXPORT_SYMBOL_GPL(usb_kill_urb);
void usb_poison_urb(struct urb *urb)
{
might_sleep();
- if (!(urb && urb->dev && urb->ep))
+ if (!urb)
return;
atomic_inc(&urb->reject);
+ if (!urb->dev || !urb->ep)
+ return;
+
usb_hcd_unlink_urb(urb, -ENOENT);
wait_event(usb_kill_urb_queue, atomic_read(&urb->use_count) == 0);
}
diff --git a/drivers/usb/core/usb-acpi.c b/drivers/usb/core/usb-acpi.c
index cef4252bb31..255c14464bf 100644
--- a/drivers/usb/core/usb-acpi.c
+++ b/drivers/usb/core/usb-acpi.c
@@ -15,6 +15,7 @@
#include <linux/kernel.h>
#include <linux/acpi.h>
#include <linux/pci.h>
+#include <linux/usb/hcd.h>
#include <acpi/acpi_bus.h>
#include "usb.h"
@@ -188,8 +189,13 @@ static int usb_acpi_find_device(struct device *dev, acpi_handle *handle)
* connected to.
*/
if (!udev->parent) {
- *handle = acpi_get_child(DEVICE_ACPI_HANDLE(&udev->dev),
+ struct usb_hcd *hcd = bus_to_hcd(udev->bus);
+ int raw_port_num;
+
+ raw_port_num = usb_hcd_find_raw_port_number(hcd,
port_num);
+ *handle = acpi_get_child(DEVICE_ACPI_HANDLE(&udev->dev),
+ raw_port_num);
if (!*handle)
return -ENODEV;
} else {
@@ -210,9 +216,14 @@ static int usb_acpi_find_device(struct device *dev, acpi_handle *handle)
return 0;
}
+static bool usb_acpi_bus_match(struct device *dev)
+{
+ return is_usb_device(dev) || is_usb_port(dev);
+}
+
static struct acpi_bus_type usb_acpi_bus = {
- .bus = &usb_bus_type,
- .find_bridge = usb_acpi_find_device,
+ .name = "USB",
+ .match = usb_acpi_bus_match,
.find_device = usb_acpi_find_device,
};
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index f81b9257273..b10da720f2b 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -49,7 +49,7 @@ const char *usbcore_name = "usbcore";
static bool nousb; /* Disable USB when built into kernel image */
-#ifdef CONFIG_USB_SUSPEND
+#ifdef CONFIG_PM_RUNTIME
static int usb_autosuspend_delay = 2; /* Default delay value,
* in seconds */
module_param_named(autosuspend, usb_autosuspend_delay, int, 0644);
@@ -307,7 +307,7 @@ static const struct dev_pm_ops usb_device_pm_ops = {
.thaw = usb_dev_thaw,
.poweroff = usb_dev_poweroff,
.restore = usb_dev_restore,
-#ifdef CONFIG_USB_SUSPEND
+#ifdef CONFIG_PM_RUNTIME
.runtime_suspend = usb_runtime_suspend,
.runtime_resume = usb_runtime_resume,
.runtime_idle = usb_runtime_idle,
@@ -317,7 +317,8 @@ static const struct dev_pm_ops usb_device_pm_ops = {
#endif /* CONFIG_PM */
-static char *usb_devnode(struct device *dev, umode_t *mode)
+static char *usb_devnode(struct device *dev,
+ umode_t *mode, kuid_t *uid, kgid_t *gid)
{
struct usb_device *usb_dev;
diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
index a7f20bde0e5..823857767a1 100644
--- a/drivers/usb/core/usb.h
+++ b/drivers/usb/core/usb.h
@@ -93,7 +93,7 @@ static inline int usb_port_resume(struct usb_device *udev, pm_message_t msg)
#endif
-#ifdef CONFIG_USB_SUSPEND
+#ifdef CONFIG_PM_RUNTIME
extern void usb_autosuspend_device(struct usb_device *udev);
extern int usb_autoresume_device(struct usb_device *udev);
diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig
index 68e9a2c5a01..ea5ee9c21c3 100644
--- a/drivers/usb/dwc3/Kconfig
+++ b/drivers/usb/dwc3/Kconfig
@@ -1,7 +1,6 @@
config USB_DWC3
tristate "DesignWare USB3 DRD Core Support"
depends on (USB || USB_GADGET) && GENERIC_HARDIRQS
- select USB_OTG_UTILS
select USB_XHCI_PLATFORM if USB_SUPPORT && USB_XHCI_HCD
help
Say Y or M here if your system has a Dual Role SuperSpeed
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index 999909451e3..c35d49d39b7 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -140,7 +140,8 @@ static void dwc3_free_one_event_buffer(struct dwc3 *dwc,
* Returns a pointer to the allocated event buffer structure on success
* otherwise ERR_PTR(errno).
*/
-static struct dwc3_event_buffer *dwc3_alloc_one_event_buffer(struct dwc3 *dwc, unsigned length)
+static struct dwc3_event_buffer *dwc3_alloc_one_event_buffer(struct dwc3 *dwc,
+ unsigned length)
{
struct dwc3_event_buffer *evt;
@@ -259,6 +260,17 @@ static void dwc3_event_buffers_cleanup(struct dwc3 *dwc)
}
}
+static void dwc3_core_num_eps(struct dwc3 *dwc)
+{
+ struct dwc3_hwparams *parms = &dwc->hwparams;
+
+ dwc->num_in_eps = DWC3_NUM_IN_EPS(parms);
+ dwc->num_out_eps = DWC3_NUM_EPS(parms) - dwc->num_in_eps;
+
+ dev_vdbg(dwc->dev, "found %d IN and %d OUT endpoints\n",
+ dwc->num_in_eps, dwc->num_out_eps);
+}
+
static void dwc3_cache_hwparams(struct dwc3 *dwc)
{
struct dwc3_hwparams *parms = &dwc->hwparams;
@@ -335,13 +347,9 @@ static int dwc3_core_init(struct dwc3 *dwc)
if (dwc->revision < DWC3_REVISION_190A)
reg |= DWC3_GCTL_U2RSTECN;
- dwc3_writel(dwc->regs, DWC3_GCTL, reg);
+ dwc3_core_num_eps(dwc);
- ret = dwc3_event_buffers_setup(dwc);
- if (ret) {
- dev_err(dwc->dev, "failed to setup event buffers\n");
- goto err0;
- }
+ dwc3_writel(dwc->regs, DWC3_GCTL, reg);
return 0;
@@ -351,8 +359,6 @@ err0:
static void dwc3_core_exit(struct dwc3 *dwc)
{
- dwc3_event_buffers_cleanup(dwc);
-
usb_phy_shutdown(dwc->usb2_phy);
usb_phy_shutdown(dwc->usb3_phy);
}
@@ -428,12 +434,32 @@ static int dwc3_probe(struct platform_device *pdev)
dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3);
}
- if (IS_ERR_OR_NULL(dwc->usb2_phy)) {
+ if (IS_ERR(dwc->usb2_phy)) {
+ ret = PTR_ERR(dwc->usb2_phy);
+
+ /*
+ * if -ENXIO is returned, it means PHY layer wasn't
+ * enabled, so it makes no sense to return -EPROBE_DEFER
+ * in that case, since no PHY driver will ever probe.
+ */
+ if (ret == -ENXIO)
+ return ret;
+
dev_err(dev, "no usb2 phy configured\n");
return -EPROBE_DEFER;
}
- if (IS_ERR_OR_NULL(dwc->usb3_phy)) {
+ if (IS_ERR(dwc->usb3_phy)) {
+ ret = PTR_ERR(dwc->usb2_phy);
+
+ /*
+ * if -ENXIO is returned, it means PHY layer wasn't
+ * enabled, so it makes no sense to return -EPROBE_DEFER
+ * in that case, since no PHY driver will ever probe.
+ */
+ if (ret == -ENXIO)
+ return ret;
+
dev_err(dev, "no usb3 phy configured\n");
return -EPROBE_DEFER;
}
@@ -448,6 +474,10 @@ static int dwc3_probe(struct platform_device *pdev)
dwc->regs_size = resource_size(res);
dwc->dev = dev;
+ dev->dma_mask = dev->parent->dma_mask;
+ dev->dma_parms = dev->parent->dma_parms;
+ dma_set_coherent_mask(dev, dev->parent->coherent_dma_mask);
+
if (!strncmp("super", maximum_speed, 5))
dwc->maximum_speed = DWC3_DCFG_SUPERSPEED;
else if (!strncmp("high", maximum_speed, 4))
@@ -480,7 +510,18 @@ static int dwc3_probe(struct platform_device *pdev)
goto err0;
}
- mode = DWC3_MODE(dwc->hwparams.hwparams0);
+ ret = dwc3_event_buffers_setup(dwc);
+ if (ret) {
+ dev_err(dwc->dev, "failed to setup event buffers\n");
+ goto err1;
+ }
+
+ if (IS_ENABLED(CONFIG_USB_DWC3_HOST))
+ mode = DWC3_MODE_HOST;
+ else if (IS_ENABLED(CONFIG_USB_DWC3_GADGET))
+ mode = DWC3_MODE_DEVICE;
+ else
+ mode = DWC3_MODE_DRD;
switch (mode) {
case DWC3_MODE_DEVICE:
@@ -488,7 +529,7 @@ static int dwc3_probe(struct platform_device *pdev)
ret = dwc3_gadget_init(dwc);
if (ret) {
dev_err(dev, "failed to initialize gadget\n");
- goto err1;
+ goto err2;
}
break;
case DWC3_MODE_HOST:
@@ -496,7 +537,7 @@ static int dwc3_probe(struct platform_device *pdev)
ret = dwc3_host_init(dwc);
if (ret) {
dev_err(dev, "failed to initialize host\n");
- goto err1;
+ goto err2;
}
break;
case DWC3_MODE_DRD:
@@ -504,32 +545,32 @@ static int dwc3_probe(struct platform_device *pdev)
ret = dwc3_host_init(dwc);
if (ret) {
dev_err(dev, "failed to initialize host\n");
- goto err1;
+ goto err2;
}
ret = dwc3_gadget_init(dwc);
if (ret) {
dev_err(dev, "failed to initialize gadget\n");
- goto err1;
+ goto err2;
}
break;
default:
dev_err(dev, "Unsupported mode of operation %d\n", mode);
- goto err1;
+ goto err2;
}
dwc->mode = mode;
ret = dwc3_debugfs_init(dwc);
if (ret) {
dev_err(dev, "failed to initialize debugfs\n");
- goto err2;
+ goto err3;
}
pm_runtime_allow(dev);
return 0;
-err2:
+err3:
switch (mode) {
case DWC3_MODE_DEVICE:
dwc3_gadget_exit(dwc);
@@ -546,6 +587,9 @@ err2:
break;
}
+err2:
+ dwc3_event_buffers_cleanup(dwc);
+
err1:
dwc3_core_exit(dwc);
@@ -583,11 +627,130 @@ static int dwc3_remove(struct platform_device *pdev)
break;
}
+ dwc3_event_buffers_cleanup(dwc);
+ dwc3_free_event_buffers(dwc);
dwc3_core_exit(dwc);
return 0;
}
+#ifdef CONFIG_PM_SLEEP
+static int dwc3_prepare(struct device *dev)
+{
+ struct dwc3 *dwc = dev_get_drvdata(dev);
+ unsigned long flags;
+
+ spin_lock_irqsave(&dwc->lock, flags);
+
+ switch (dwc->mode) {
+ case DWC3_MODE_DEVICE:
+ case DWC3_MODE_DRD:
+ dwc3_gadget_prepare(dwc);
+ /* FALLTHROUGH */
+ case DWC3_MODE_HOST:
+ default:
+ dwc3_event_buffers_cleanup(dwc);
+ break;
+ }
+
+ spin_unlock_irqrestore(&dwc->lock, flags);
+
+ return 0;
+}
+
+static void dwc3_complete(struct device *dev)
+{
+ struct dwc3 *dwc = dev_get_drvdata(dev);
+ unsigned long flags;
+
+ spin_lock_irqsave(&dwc->lock, flags);
+
+ switch (dwc->mode) {
+ case DWC3_MODE_DEVICE:
+ case DWC3_MODE_DRD:
+ dwc3_gadget_complete(dwc);
+ /* FALLTHROUGH */
+ case DWC3_MODE_HOST:
+ default:
+ dwc3_event_buffers_setup(dwc);
+ break;
+ }
+
+ spin_unlock_irqrestore(&dwc->lock, flags);
+}
+
+static int dwc3_suspend(struct device *dev)
+{
+ struct dwc3 *dwc = dev_get_drvdata(dev);
+ unsigned long flags;
+
+ spin_lock_irqsave(&dwc->lock, flags);
+
+ switch (dwc->mode) {
+ case DWC3_MODE_DEVICE:
+ case DWC3_MODE_DRD:
+ dwc3_gadget_suspend(dwc);
+ /* FALLTHROUGH */
+ case DWC3_MODE_HOST:
+ default:
+ /* do nothing */
+ break;
+ }
+
+ dwc->gctl = dwc3_readl(dwc->regs, DWC3_GCTL);
+ spin_unlock_irqrestore(&dwc->lock, flags);
+
+ usb_phy_shutdown(dwc->usb3_phy);
+ usb_phy_shutdown(dwc->usb2_phy);
+
+ return 0;
+}
+
+static int dwc3_resume(struct device *dev)
+{
+ struct dwc3 *dwc = dev_get_drvdata(dev);
+ unsigned long flags;
+
+ usb_phy_init(dwc->usb3_phy);
+ usb_phy_init(dwc->usb2_phy);
+ msleep(100);
+
+ spin_lock_irqsave(&dwc->lock, flags);
+
+ dwc3_writel(dwc->regs, DWC3_GCTL, dwc->gctl);
+
+ switch (dwc->mode) {
+ case DWC3_MODE_DEVICE:
+ case DWC3_MODE_DRD:
+ dwc3_gadget_resume(dwc);
+ /* FALLTHROUGH */
+ case DWC3_MODE_HOST:
+ default:
+ /* do nothing */
+ break;
+ }
+
+ spin_unlock_irqrestore(&dwc->lock, flags);
+
+ pm_runtime_disable(dev);
+ pm_runtime_set_active(dev);
+ pm_runtime_enable(dev);
+
+ return 0;
+}
+
+static const struct dev_pm_ops dwc3_dev_pm_ops = {
+ .prepare = dwc3_prepare,
+ .complete = dwc3_complete,
+
+ SET_SYSTEM_SLEEP_PM_OPS(dwc3_suspend, dwc3_resume)
+};
+
+#define DWC3_PM_OPS &(dwc3_dev_pm_ops)
+#else
+#define DWC3_PM_OPS NULL
+#endif
+
#ifdef CONFIG_OF
static const struct of_device_id of_dwc3_match[] = {
{
@@ -604,6 +767,7 @@ static struct platform_driver dwc3_driver = {
.driver = {
.name = "dwc3",
.of_match_table = of_match_ptr(of_dwc3_match),
+ .pm = DWC3_PM_OPS,
},
};
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index b4175066023..b69d322e3ca 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -154,8 +154,9 @@
/* OTG Registers */
#define DWC3_OCFG 0xcc00
#define DWC3_OCTL 0xcc04
-#define DWC3_OEVTEN 0xcc08
-#define DWC3_OSTS 0xcc0C
+#define DWC3_OEVT 0xcc08
+#define DWC3_OEVTEN 0xcc0C
+#define DWC3_OSTS 0xcc10
/* Bit fields */
@@ -369,6 +370,9 @@ struct dwc3_trb;
* @list: a list of event buffers
* @buf: _THE_ buffer
* @length: size of this buffer
+ * @lpos: event offset
+ * @count: cache of last read event count register
+ * @flags: flags related to this event buffer
* @dma: dma_addr_t
* @dwc: pointer to DWC controller
*/
@@ -376,6 +380,10 @@ struct dwc3_event_buffer {
void *buf;
unsigned length;
unsigned int lpos;
+ unsigned int count;
+ unsigned int flags;
+
+#define DWC3_EVENT_PENDING BIT(0)
dma_addr_t dma;
@@ -487,12 +495,6 @@ enum dwc3_link_state {
DWC3_LINK_STATE_MASK = 0x0f,
};
-enum dwc3_device_state {
- DWC3_DEFAULT_STATE,
- DWC3_ADDRESS_STATE,
- DWC3_CONFIGURED_STATE,
-};
-
/* TRB Length, PCM and Status */
#define DWC3_TRB_SIZE_MASK (0x00ffffff)
#define DWC3_TRB_SIZE_LENGTH(n) ((n) & DWC3_TRB_SIZE_MASK)
@@ -574,6 +576,14 @@ struct dwc3_hwparams {
/* HWPARAMS1 */
#define DWC3_NUM_INT(n) (((n) & (0x3f << 15)) >> 15)
+/* HWPARAMS3 */
+#define DWC3_NUM_IN_EPS_MASK (0x1f << 18)
+#define DWC3_NUM_EPS_MASK (0x3f << 12)
+#define DWC3_NUM_EPS(p) (((p)->hwparams3 & \
+ (DWC3_NUM_EPS_MASK)) >> 12)
+#define DWC3_NUM_IN_EPS(p) (((p)->hwparams3 & \
+ (DWC3_NUM_IN_EPS_MASK)) >> 18)
+
/* HWPARAMS7 */
#define DWC3_RAM1_DEPTH(n) ((n) & 0xffff)
@@ -618,7 +628,6 @@ struct dwc3_scratchpad_array {
* @gadget_driver: pointer to the gadget driver
* @regs: base address for our registers
* @regs_size: address space size
- * @irq: IRQ number
* @num_event_buffers: calculated number of event buffers
* @u1u2: only used on revisions <1.83a for workaround
* @maximum_speed: maximum speed requested (mainly for testing purposes)
@@ -626,6 +635,8 @@ struct dwc3_scratchpad_array {
* @mode: mode of operation
* @usb2_phy: pointer to USB2 PHY
* @usb3_phy: pointer to USB3 PHY
+ * @dcfg: saved contents of DCFG register
+ * @gctl: saved contents of GCTL register
* @is_selfpowered: true when we are selfpowered
* @three_stage_setup: set if we perform a three phase setup
* @ep0_bounced: true when we used bounce buffer
@@ -639,6 +650,8 @@ struct dwc3_scratchpad_array {
* @u2pel: parameter from Set SEL request.
* @u1sel: parameter from Set SEL request.
* @u1pel: parameter from Set SEL request.
+ * @num_out_eps: number of out endpoints
+ * @num_in_eps: number of in endpoints
* @ep0_next_event: hold the next expected event
* @ep0state: state of endpoint zero
* @link_state: link state
@@ -656,8 +669,10 @@ struct dwc3 {
dma_addr_t ep0_trb_addr;
dma_addr_t ep0_bounce_addr;
struct dwc3_request ep0_usb_req;
+
/* device lock */
spinlock_t lock;
+
struct device *dev;
struct platform_device *xhci;
@@ -675,6 +690,10 @@ struct dwc3 {
void __iomem *regs;
size_t regs_size;
+ /* used for suspend/resume */
+ u32 dcfg;
+ u32 gctl;
+
u32 num_event_buffers;
u32 u1u2;
u32 maximum_speed;
@@ -694,6 +713,9 @@ struct dwc3 {
#define DWC3_REVISION_202A 0x5533202a
#define DWC3_REVISION_210A 0x5533210a
#define DWC3_REVISION_220A 0x5533220a
+#define DWC3_REVISION_230A 0x5533230a
+#define DWC3_REVISION_240A 0x5533240a
+#define DWC3_REVISION_250A 0x5533250a
unsigned is_selfpowered:1;
unsigned three_stage_setup:1;
@@ -704,11 +726,11 @@ struct dwc3 {
unsigned delayed_status:1;
unsigned needs_fifo_resize:1;
unsigned resize_fifos:1;
+ unsigned pullups_connected:1;
enum dwc3_ep0_next ep0_next_event;
enum dwc3_ep0_state ep0state;
enum dwc3_link_state link_state;
- enum dwc3_device_state dev_state;
u16 isoch_delay;
u16 u2sel;
@@ -718,6 +740,9 @@ struct dwc3 {
u8 speed;
+ u8 num_out_eps;
+ u8 num_in_eps;
+
void *mem;
struct dwc3_hwparams hwparams;
@@ -884,4 +909,31 @@ static inline void dwc3_gadget_exit(struct dwc3 *dwc)
{ }
#endif
+/* power management interface */
+#if !IS_ENABLED(CONFIG_USB_DWC3_HOST)
+int dwc3_gadget_prepare(struct dwc3 *dwc);
+void dwc3_gadget_complete(struct dwc3 *dwc);
+int dwc3_gadget_suspend(struct dwc3 *dwc);
+int dwc3_gadget_resume(struct dwc3 *dwc);
+#else
+static inline int dwc3_gadget_prepare(struct dwc3 *dwc)
+{
+ return 0;
+}
+
+static inline void dwc3_gadget_complete(struct dwc3 *dwc)
+{
+}
+
+static inline int dwc3_gadget_suspend(struct dwc3 *dwc)
+{
+ return 0;
+}
+
+static inline int dwc3_gadget_resume(struct dwc3 *dwc)
+{
+ return 0;
+}
+#endif /* !IS_ENABLED(CONFIG_USB_DWC3_HOST) */
+
#endif /* __DRIVERS_USB_DWC3_CORE_H */
diff --git a/drivers/usb/dwc3/debugfs.c b/drivers/usb/dwc3/debugfs.c
index 4a752e730c5..9e9f122162f 100644
--- a/drivers/usb/dwc3/debugfs.c
+++ b/drivers/usb/dwc3/debugfs.c
@@ -59,7 +59,7 @@
.offset = DWC3_ ##nm - DWC3_GLOBALS_REGS_START, \
}
-static struct debugfs_reg32 dwc3_regs[] = {
+static const struct debugfs_reg32 dwc3_regs[] = {
dump_register(GSBUSCFG0),
dump_register(GSBUSCFG1),
dump_register(GTXTHRCFG),
@@ -372,6 +372,7 @@ static struct debugfs_reg32 dwc3_regs[] = {
dump_register(OCFG),
dump_register(OCTL),
+ dump_register(OEVT),
dump_register(OEVTEN),
dump_register(OSTS),
};
@@ -577,8 +578,14 @@ static int dwc3_link_state_show(struct seq_file *s, void *unused)
case DWC3_LINK_STATE_LPBK:
seq_printf(s, "Loopback\n");
break;
+ case DWC3_LINK_STATE_RESET:
+ seq_printf(s, "Reset\n");
+ break;
+ case DWC3_LINK_STATE_RESUME:
+ seq_printf(s, "Resume\n");
+ break;
default:
- seq_printf(s, "UNKNOWN %d\n", reg);
+ seq_printf(s, "UNKNOWN %d\n", state);
}
return 0;
@@ -661,28 +668,31 @@ int dwc3_debugfs_init(struct dwc3 *dwc)
goto err1;
}
-#if IS_ENABLED(CONFIG_USB_DWC3_GADGET)
- file = debugfs_create_file("mode", S_IRUGO | S_IWUSR, root,
- dwc, &dwc3_mode_fops);
- if (!file) {
- ret = -ENOMEM;
- goto err1;
- }
-
- file = debugfs_create_file("testmode", S_IRUGO | S_IWUSR, root,
- dwc, &dwc3_testmode_fops);
- if (!file) {
- ret = -ENOMEM;
- goto err1;
+ if (IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE)) {
+ file = debugfs_create_file("mode", S_IRUGO | S_IWUSR, root,
+ dwc, &dwc3_mode_fops);
+ if (!file) {
+ ret = -ENOMEM;
+ goto err1;
+ }
}
- file = debugfs_create_file("link_state", S_IRUGO | S_IWUSR, root,
- dwc, &dwc3_link_state_fops);
- if (!file) {
- ret = -ENOMEM;
- goto err1;
+ if (IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE) ||
+ IS_ENABLED(CONFIG_USB_DWC3_GADGET)) {
+ file = debugfs_create_file("testmode", S_IRUGO | S_IWUSR, root,
+ dwc, &dwc3_testmode_fops);
+ if (!file) {
+ ret = -ENOMEM;
+ goto err1;
+ }
+
+ file = debugfs_create_file("link_state", S_IRUGO | S_IWUSR, root,
+ dwc, &dwc3_link_state_fops);
+ if (!file) {
+ ret = -ENOMEM;
+ goto err1;
+ }
}
-#endif
return 0;
diff --git a/drivers/usb/dwc3/dwc3-exynos.c b/drivers/usb/dwc3/dwc3-exynos.c
index b50da53e9a5..a8afe6e2662 100644
--- a/drivers/usb/dwc3/dwc3-exynos.c
+++ b/drivers/usb/dwc3/dwc3-exynos.c
@@ -22,11 +22,9 @@
#include <linux/usb/otg.h>
#include <linux/usb/nop-usb-xceiv.h>
#include <linux/of.h>
-
-#include "core.h"
+#include <linux/of_platform.h>
struct dwc3_exynos {
- struct platform_device *dwc3;
struct platform_device *usb2_phy;
struct platform_device *usb3_phy;
struct device *dev;
@@ -88,21 +86,30 @@ err1:
return ret;
}
+static int dwc3_exynos_remove_child(struct device *dev, void *unused)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+
+ platform_device_unregister(pdev);
+
+ return 0;
+}
+
static u64 dwc3_exynos_dma_mask = DMA_BIT_MASK(32);
static int dwc3_exynos_probe(struct platform_device *pdev)
{
- struct platform_device *dwc3;
struct dwc3_exynos *exynos;
struct clk *clk;
struct device *dev = &pdev->dev;
+ struct device_node *node = dev->of_node;
int ret = -ENOMEM;
exynos = devm_kzalloc(dev, sizeof(*exynos), GFP_KERNEL);
if (!exynos) {
dev_err(dev, "not enough memory\n");
- return -ENOMEM;
+ goto err1;
}
/*
@@ -110,21 +117,15 @@ static int dwc3_exynos_probe(struct platform_device *pdev)
* 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;
+ if (!dev->dma_mask)
+ dev->dma_mask = &dwc3_exynos_dma_mask;
platform_set_drvdata(pdev, exynos);
ret = dwc3_exynos_register_phys(exynos);
if (ret) {
dev_err(dev, "couldn't register PHYs\n");
- return ret;
- }
-
- dwc3 = platform_device_alloc("dwc3", PLATFORM_DEVID_AUTO);
- if (!dwc3) {
- dev_err(dev, "couldn't allocate dwc3 device\n");
- return -ENOMEM;
+ goto err1;
}
clk = devm_clk_get(dev, "usbdrd30");
@@ -134,37 +135,28 @@ static int dwc3_exynos_probe(struct platform_device *pdev)
goto err1;
}
- dma_set_coherent_mask(&dwc3->dev, dev->coherent_dma_mask);
-
- dwc3->dev.parent = dev;
- dwc3->dev.dma_mask = dev->dma_mask;
- dwc3->dev.dma_parms = dev->dma_parms;
- exynos->dwc3 = dwc3;
exynos->dev = dev;
exynos->clk = clk;
- clk_enable(exynos->clk);
-
- ret = platform_device_add_resources(dwc3, pdev->resource,
- pdev->num_resources);
- if (ret) {
- dev_err(dev, "couldn't add resources to dwc3 device\n");
- goto err2;
- }
-
- ret = platform_device_add(dwc3);
- if (ret) {
- dev_err(dev, "failed to register dwc3 device\n");
+ clk_prepare_enable(exynos->clk);
+
+ if (node) {
+ ret = of_platform_populate(node, NULL, NULL, dev);
+ if (ret) {
+ dev_err(dev, "failed to add dwc3 core\n");
+ goto err2;
+ }
+ } else {
+ dev_err(dev, "no device node, failed to add dwc3 core\n");
+ ret = -ENODEV;
goto err2;
}
return 0;
err2:
- clk_disable(clk);
+ clk_disable_unprepare(clk);
err1:
- platform_device_put(dwc3);
-
return ret;
}
@@ -172,11 +164,11 @@ static int dwc3_exynos_remove(struct platform_device *pdev)
{
struct dwc3_exynos *exynos = platform_get_drvdata(pdev);
- platform_device_unregister(exynos->dwc3);
platform_device_unregister(exynos->usb2_phy);
platform_device_unregister(exynos->usb3_phy);
+ device_for_each_child(&pdev->dev, NULL, dwc3_exynos_remove_child);
- clk_disable(exynos->clk);
+ clk_disable_unprepare(exynos->clk);
return 0;
}
@@ -189,12 +181,46 @@ static const struct of_device_id exynos_dwc3_match[] = {
MODULE_DEVICE_TABLE(of, exynos_dwc3_match);
#endif
+#ifdef CONFIG_PM_SLEEP
+static int dwc3_exynos_suspend(struct device *dev)
+{
+ struct dwc3_exynos *exynos = dev_get_drvdata(dev);
+
+ clk_disable(exynos->clk);
+
+ return 0;
+}
+
+static int dwc3_exynos_resume(struct device *dev)
+{
+ struct dwc3_exynos *exynos = dev_get_drvdata(dev);
+
+ clk_enable(exynos->clk);
+
+ /* runtime set active to reflect active state. */
+ pm_runtime_disable(dev);
+ pm_runtime_set_active(dev);
+ pm_runtime_enable(dev);
+
+ return 0;
+}
+
+static const struct dev_pm_ops dwc3_exynos_dev_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(dwc3_exynos_suspend, dwc3_exynos_resume)
+};
+
+#define DEV_PM_OPS (&dwc3_exynos_dev_pm_ops)
+#else
+#define DEV_PM_OPS NULL
+#endif /* CONFIG_PM_SLEEP */
+
static struct platform_driver dwc3_exynos_driver = {
.probe = dwc3_exynos_probe,
.remove = dwc3_exynos_remove,
.driver = {
.name = "exynos-dwc3",
.of_match_table = of_match_ptr(exynos_dwc3_match),
+ .pm = DEV_PM_OPS,
},
};
diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c
index 22f337f5721..34638b92500 100644
--- a/drivers/usb/dwc3/dwc3-omap.c
+++ b/drivers/usb/dwc3/dwc3-omap.c
@@ -52,9 +52,6 @@
#include <linux/of_platform.h>
#include <linux/usb/otg.h>
-#include <linux/usb/nop-usb-xceiv.h>
-
-#include "core.h"
/*
* All these registers belong to OMAP's Wrapper around the
@@ -119,20 +116,17 @@ struct dwc3_omap {
/* device lock */
spinlock_t lock;
- struct platform_device *usb2_phy;
- struct platform_device *usb3_phy;
struct device *dev;
int irq;
void __iomem *base;
- void *context;
- u32 resource_size;
+ u32 utmi_otg_status;
u32 dma_status:1;
};
-struct dwc3_omap *_omap;
+static struct dwc3_omap *_omap;
static inline u32 dwc3_omap_readl(void __iomem *base, u32 offset)
{
@@ -144,11 +138,14 @@ static inline void dwc3_omap_writel(void __iomem *base, u32 offset, u32 value)
writel(value, base + offset);
}
-void dwc3_omap_mailbox(enum omap_dwc3_vbus_id_status status)
+int dwc3_omap_mailbox(enum omap_dwc3_vbus_id_status status)
{
u32 val;
struct dwc3_omap *omap = _omap;
+ if (!omap)
+ return -EPROBE_DEFER;
+
switch (status) {
case OMAP_DWC3_ID_GROUND:
dev_dbg(omap->dev, "ID GND\n");
@@ -191,63 +188,9 @@ void dwc3_omap_mailbox(enum omap_dwc3_vbus_id_status status)
dev_dbg(omap->dev, "ID float\n");
}
- return;
-}
-EXPORT_SYMBOL_GPL(dwc3_omap_mailbox);
-
-static int dwc3_omap_register_phys(struct dwc3_omap *omap)
-{
- struct nop_usb_xceiv_platform_data pdata;
- struct platform_device *pdev;
- int ret;
-
- memset(&pdata, 0x00, sizeof(pdata));
-
- pdev = platform_device_alloc("nop_usb_xceiv", PLATFORM_DEVID_AUTO);
- if (!pdev)
- return -ENOMEM;
-
- omap->usb2_phy = pdev;
- pdata.type = USB_PHY_TYPE_USB2;
-
- ret = platform_device_add_data(omap->usb2_phy, &pdata, sizeof(pdata));
- if (ret)
- goto err1;
-
- pdev = platform_device_alloc("nop_usb_xceiv", PLATFORM_DEVID_AUTO);
- if (!pdev) {
- ret = -ENOMEM;
- goto err1;
- }
-
- omap->usb3_phy = pdev;
- pdata.type = USB_PHY_TYPE_USB3;
-
- ret = platform_device_add_data(omap->usb3_phy, &pdata, sizeof(pdata));
- if (ret)
- goto err2;
-
- ret = platform_device_add(omap->usb2_phy);
- if (ret)
- goto err2;
-
- ret = platform_device_add(omap->usb3_phy);
- if (ret)
- goto err3;
-
return 0;
-
-err3:
- platform_device_del(omap->usb2_phy);
-
-err2:
- platform_device_put(omap->usb3_phy);
-
-err1:
- platform_device_put(omap->usb2_phy);
-
- return ret;
}
+EXPORT_SYMBOL_GPL(dwc3_omap_mailbox);
static irqreturn_t dwc3_omap_interrupt(int irq, void *_omap)
{
@@ -309,24 +252,57 @@ static int dwc3_omap_remove_core(struct device *dev, void *c)
return 0;
}
+static void dwc3_omap_enable_irqs(struct dwc3_omap *omap)
+{
+ u32 reg;
+
+ /* enable all IRQs */
+ reg = USBOTGSS_IRQO_COREIRQ_ST;
+ dwc3_omap_writel(omap->base, USBOTGSS_IRQENABLE_SET_0, reg);
+
+ reg = (USBOTGSS_IRQ1_OEVT |
+ USBOTGSS_IRQ1_DRVVBUS_RISE |
+ USBOTGSS_IRQ1_CHRGVBUS_RISE |
+ USBOTGSS_IRQ1_DISCHRGVBUS_RISE |
+ USBOTGSS_IRQ1_IDPULLUP_RISE |
+ USBOTGSS_IRQ1_DRVVBUS_FALL |
+ USBOTGSS_IRQ1_CHRGVBUS_FALL |
+ USBOTGSS_IRQ1_DISCHRGVBUS_FALL |
+ USBOTGSS_IRQ1_IDPULLUP_FALL);
+
+ dwc3_omap_writel(omap->base, USBOTGSS_IRQENABLE_SET_1, reg);
+}
+
+static void dwc3_omap_disable_irqs(struct dwc3_omap *omap)
+{
+ /* disable all IRQs */
+ dwc3_omap_writel(omap->base, USBOTGSS_IRQENABLE_SET_1, 0x00);
+ dwc3_omap_writel(omap->base, USBOTGSS_IRQENABLE_SET_0, 0x00);
+}
+
+static u64 dwc3_omap_dma_mask = DMA_BIT_MASK(32);
+
static int dwc3_omap_probe(struct platform_device *pdev)
{
- struct dwc3_omap_data *pdata = pdev->dev.platform_data;
struct device_node *node = pdev->dev.of_node;
struct dwc3_omap *omap;
struct resource *res;
struct device *dev = &pdev->dev;
- int size;
int ret = -ENOMEM;
int irq;
- const u32 *utmi_mode;
+ int utmi_mode = 0;
+
u32 reg;
void __iomem *base;
- void *context;
+
+ if (!node) {
+ dev_err(dev, "device node not found\n");
+ return -EINVAL;
+ }
omap = devm_kzalloc(dev, sizeof(*omap), GFP_KERNEL);
if (!omap) {
@@ -336,13 +312,13 @@ static int dwc3_omap_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, omap);
- irq = platform_get_irq(pdev, 1);
+ irq = platform_get_irq(pdev, 0);
if (irq < 0) {
dev_err(dev, "missing IRQ resource\n");
return -EINVAL;
}
- res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
dev_err(dev, "missing memory base resource\n");
return -EINVAL;
@@ -354,25 +330,12 @@ static int dwc3_omap_probe(struct platform_device *pdev)
return -ENOMEM;
}
- ret = dwc3_omap_register_phys(omap);
- if (ret) {
- dev_err(dev, "couldn't register PHYs\n");
- return ret;
- }
-
- context = devm_kzalloc(dev, resource_size(res), GFP_KERNEL);
- if (!context) {
- dev_err(dev, "couldn't allocate dwc3 context memory\n");
- return -ENOMEM;
- }
-
spin_lock_init(&omap->lock);
- omap->resource_size = resource_size(res);
- omap->context = context;
omap->dev = dev;
omap->irq = irq;
omap->base = base;
+ dev->dma_mask = &dwc3_omap_dma_mask;
/*
* REVISIT if we ever have two instances of the wrapper, we will be
@@ -389,25 +352,17 @@ static int dwc3_omap_probe(struct platform_device *pdev)
reg = dwc3_omap_readl(omap->base, USBOTGSS_UTMI_OTG_STATUS);
- utmi_mode = of_get_property(node, "utmi-mode", &size);
- if (utmi_mode && size == sizeof(*utmi_mode)) {
- reg |= *utmi_mode;
- } else {
- if (!pdata) {
- dev_dbg(dev, "missing platform data\n");
- } else {
- switch (pdata->utmi_mode) {
- case DWC3_OMAP_UTMI_MODE_SW:
- reg |= USBOTGSS_UTMI_OTG_STATUS_SW_MODE;
- break;
- case DWC3_OMAP_UTMI_MODE_HW:
- reg &= ~USBOTGSS_UTMI_OTG_STATUS_SW_MODE;
- break;
- default:
- dev_dbg(dev, "UNKNOWN utmi mode %d\n",
- pdata->utmi_mode);
- }
- }
+ of_property_read_u32(node, "utmi-mode", &utmi_mode);
+
+ switch (utmi_mode) {
+ case DWC3_OMAP_UTMI_MODE_SW:
+ reg |= USBOTGSS_UTMI_OTG_STATUS_SW_MODE;
+ break;
+ case DWC3_OMAP_UTMI_MODE_HW:
+ reg &= ~USBOTGSS_UTMI_OTG_STATUS_SW_MODE;
+ break;
+ default:
+ dev_dbg(dev, "UNKNOWN utmi mode %d\n", utmi_mode);
}
dwc3_omap_writel(omap->base, USBOTGSS_UTMI_OTG_STATUS, reg);
@@ -424,29 +379,12 @@ static int dwc3_omap_probe(struct platform_device *pdev)
return ret;
}
- /* enable all IRQs */
- reg = USBOTGSS_IRQO_COREIRQ_ST;
- dwc3_omap_writel(omap->base, USBOTGSS_IRQENABLE_SET_0, reg);
+ dwc3_omap_enable_irqs(omap);
- reg = (USBOTGSS_IRQ1_OEVT |
- USBOTGSS_IRQ1_DRVVBUS_RISE |
- USBOTGSS_IRQ1_CHRGVBUS_RISE |
- USBOTGSS_IRQ1_DISCHRGVBUS_RISE |
- USBOTGSS_IRQ1_IDPULLUP_RISE |
- USBOTGSS_IRQ1_DRVVBUS_FALL |
- USBOTGSS_IRQ1_CHRGVBUS_FALL |
- USBOTGSS_IRQ1_DISCHRGVBUS_FALL |
- USBOTGSS_IRQ1_IDPULLUP_FALL);
-
- dwc3_omap_writel(omap->base, USBOTGSS_IRQENABLE_SET_1, reg);
-
- if (node) {
- ret = of_platform_populate(node, NULL, NULL, dev);
- if (ret) {
- dev_err(&pdev->dev,
- "failed to add create dwc3 core\n");
- return ret;
- }
+ ret = of_platform_populate(node, NULL, NULL, dev);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to create dwc3 core\n");
+ return ret;
}
return 0;
@@ -456,8 +394,7 @@ static int dwc3_omap_remove(struct platform_device *pdev)
{
struct dwc3_omap *omap = platform_get_drvdata(pdev);
- platform_device_unregister(omap->usb2_phy);
- platform_device_unregister(omap->usb3_phy);
+ dwc3_omap_disable_irqs(omap);
pm_runtime_put_sync(&pdev->dev);
pm_runtime_disable(&pdev->dev);
device_for_each_child(&pdev->dev, NULL, dwc3_omap_remove_core);
@@ -465,20 +402,74 @@ static int dwc3_omap_remove(struct platform_device *pdev)
return 0;
}
-static const struct of_device_id of_dwc3_matach[] = {
+static const struct of_device_id of_dwc3_match[] = {
{
- "ti,dwc3",
+ .compatible = "ti,dwc3"
},
{ },
};
-MODULE_DEVICE_TABLE(of, of_dwc3_matach);
+MODULE_DEVICE_TABLE(of, of_dwc3_match);
+
+#ifdef CONFIG_PM_SLEEP
+static int dwc3_omap_prepare(struct device *dev)
+{
+ struct dwc3_omap *omap = dev_get_drvdata(dev);
+
+ dwc3_omap_disable_irqs(omap);
+
+ return 0;
+}
+
+static void dwc3_omap_complete(struct device *dev)
+{
+ struct dwc3_omap *omap = dev_get_drvdata(dev);
+
+ dwc3_omap_enable_irqs(omap);
+}
+
+static int dwc3_omap_suspend(struct device *dev)
+{
+ struct dwc3_omap *omap = dev_get_drvdata(dev);
+
+ omap->utmi_otg_status = dwc3_omap_readl(omap->base,
+ USBOTGSS_UTMI_OTG_STATUS);
+
+ return 0;
+}
+
+static int dwc3_omap_resume(struct device *dev)
+{
+ struct dwc3_omap *omap = dev_get_drvdata(dev);
+
+ dwc3_omap_writel(omap->base, USBOTGSS_UTMI_OTG_STATUS,
+ omap->utmi_otg_status);
+
+ pm_runtime_disable(dev);
+ pm_runtime_set_active(dev);
+ pm_runtime_enable(dev);
+
+ return 0;
+}
+
+static const struct dev_pm_ops dwc3_omap_dev_pm_ops = {
+ .prepare = dwc3_omap_prepare,
+ .complete = dwc3_omap_complete,
+
+ SET_SYSTEM_SLEEP_PM_OPS(dwc3_omap_suspend, dwc3_omap_resume)
+};
+
+#define DEV_PM_OPS (&dwc3_omap_dev_pm_ops)
+#else
+#define DEV_PM_OPS NULL
+#endif /* CONFIG_PM_SLEEP */
static struct platform_driver dwc3_omap_driver = {
.probe = dwc3_omap_probe,
.remove = dwc3_omap_remove,
.driver = {
.name = "omap-dwc3",
- .of_match_table = of_dwc3_matach,
+ .of_match_table = of_dwc3_match,
+ .pm = DEV_PM_OPS,
},
};
diff --git a/drivers/usb/dwc3/dwc3-pci.c b/drivers/usb/dwc3/dwc3-pci.c
index 7d70f44567d..227d4a7acad 100644
--- a/drivers/usb/dwc3/dwc3-pci.c
+++ b/drivers/usb/dwc3/dwc3-pci.c
@@ -45,8 +45,6 @@
#include <linux/usb/otg.h>
#include <linux/usb/nop-usb-xceiv.h>
-#include "core.h"
-
/* FIXME define these in <linux/pci_ids.h> */
#define PCI_VENDOR_ID_SYNOPSYS 0x16c3
#define PCI_DEVICE_ID_SYNOPSYS_HAPSUSB3 0xabcd
@@ -214,11 +212,49 @@ static DEFINE_PCI_DEVICE_TABLE(dwc3_pci_id_table) = {
};
MODULE_DEVICE_TABLE(pci, dwc3_pci_id_table);
+#ifdef CONFIG_PM
+static int dwc3_pci_suspend(struct device *dev)
+{
+ struct pci_dev *pci = to_pci_dev(dev);
+
+ pci_disable_device(pci);
+
+ return 0;
+}
+
+static int dwc3_pci_resume(struct device *dev)
+{
+ struct pci_dev *pci = to_pci_dev(dev);
+ int ret;
+
+ ret = pci_enable_device(pci);
+ if (ret) {
+ dev_err(dev, "can't re-enable device --> %d\n", ret);
+ return ret;
+ }
+
+ pci_set_master(pci);
+
+ return 0;
+}
+
+static const struct dev_pm_ops dwc3_pci_dev_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(dwc3_pci_suspend, dwc3_pci_resume)
+};
+
+#define DEV_PM_OPS (&dwc3_pci_dev_pm_ops)
+#else
+#define DEV_PM_OPS NULL
+#endif /* CONFIG_PM */
+
static struct pci_driver dwc3_pci_driver = {
.name = "dwc3-pci",
.id_table = dwc3_pci_id_table,
.probe = dwc3_pci_probe,
.remove = dwc3_pci_remove,
+ .driver = {
+ .pm = DEV_PM_OPS,
+ },
};
MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>");
diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
index d7da073a23f..5acbb948b70 100644
--- a/drivers/usb/dwc3/ep0.c
+++ b/drivers/usb/dwc3/ep0.c
@@ -394,10 +394,13 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc,
u32 wIndex;
u32 reg;
int ret;
+ enum usb_device_state state;
wValue = le16_to_cpu(ctrl->wValue);
wIndex = le16_to_cpu(ctrl->wIndex);
recip = ctrl->bRequestType & USB_RECIP_MASK;
+ state = dwc->gadget.state;
+
switch (recip) {
case USB_RECIP_DEVICE:
@@ -409,7 +412,7 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc,
* default control pipe
*/
case USB_DEVICE_U1_ENABLE:
- if (dwc->dev_state != DWC3_CONFIGURED_STATE)
+ if (state != USB_STATE_CONFIGURED)
return -EINVAL;
if (dwc->speed != DWC3_DSTS_SUPERSPEED)
return -EINVAL;
@@ -423,7 +426,7 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc,
break;
case USB_DEVICE_U2_ENABLE:
- if (dwc->dev_state != DWC3_CONFIGURED_STATE)
+ if (state != USB_STATE_CONFIGURED)
return -EINVAL;
if (dwc->speed != DWC3_DSTS_SUPERSPEED)
return -EINVAL;
@@ -493,6 +496,7 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc,
static int dwc3_ep0_set_address(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
{
+ enum usb_device_state state = dwc->gadget.state;
u32 addr;
u32 reg;
@@ -502,7 +506,7 @@ static int dwc3_ep0_set_address(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
return -EINVAL;
}
- if (dwc->dev_state == DWC3_CONFIGURED_STATE) {
+ if (state == USB_STATE_CONFIGURED) {
dev_dbg(dwc->dev, "trying to set address when configured\n");
return -EINVAL;
}
@@ -513,9 +517,9 @@ static int dwc3_ep0_set_address(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
dwc3_writel(dwc->regs, DWC3_DCFG, reg);
if (addr)
- dwc->dev_state = DWC3_ADDRESS_STATE;
+ usb_gadget_set_state(&dwc->gadget, USB_STATE_ADDRESS);
else
- dwc->dev_state = DWC3_DEFAULT_STATE;
+ usb_gadget_set_state(&dwc->gadget, USB_STATE_DEFAULT);
return 0;
}
@@ -532,6 +536,7 @@ static int dwc3_ep0_delegate_req(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
{
+ enum usb_device_state state = dwc->gadget.state;
u32 cfg;
int ret;
u32 reg;
@@ -539,16 +544,18 @@ static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
dwc->start_config_issued = false;
cfg = le16_to_cpu(ctrl->wValue);
- switch (dwc->dev_state) {
- case DWC3_DEFAULT_STATE:
+ switch (state) {
+ case USB_STATE_DEFAULT:
return -EINVAL;
break;
- case DWC3_ADDRESS_STATE:
+ case USB_STATE_ADDRESS:
ret = dwc3_ep0_delegate_req(dwc, ctrl);
/* if the cfg matches and the cfg is non zero */
if (cfg && (!ret || (ret == USB_GADGET_DELAYED_STATUS))) {
- dwc->dev_state = DWC3_CONFIGURED_STATE;
+ usb_gadget_set_state(&dwc->gadget,
+ USB_STATE_CONFIGURED);
+
/*
* Enable transition to U1/U2 state when
* nothing is pending from application.
@@ -562,10 +569,11 @@ static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
}
break;
- case DWC3_CONFIGURED_STATE:
+ case USB_STATE_CONFIGURED:
ret = dwc3_ep0_delegate_req(dwc, ctrl);
if (!cfg)
- dwc->dev_state = DWC3_ADDRESS_STATE;
+ usb_gadget_set_state(&dwc->gadget,
+ USB_STATE_ADDRESS);
break;
default:
ret = -EINVAL;
@@ -620,10 +628,11 @@ static void dwc3_ep0_set_sel_cmpl(struct usb_ep *ep, struct usb_request *req)
static int dwc3_ep0_set_sel(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
{
struct dwc3_ep *dep;
+ enum usb_device_state state = dwc->gadget.state;
u16 wLength;
u16 wValue;
- if (dwc->dev_state == DWC3_DEFAULT_STATE)
+ if (state == USB_STATE_DEFAULT)
return -EINVAL;
wValue = le16_to_cpu(ctrl->wValue);
@@ -891,7 +900,8 @@ static void __dwc3_ep0_do_control_data(struct dwc3 *dwc,
DWC3_TRBCTL_CONTROL_DATA);
} else if (!IS_ALIGNED(req->request.length, dep->endpoint.maxpacket)
&& (dep->number == 0)) {
- u32 transfer_size;
+ u32 transfer_size;
+ u32 maxpacket;
ret = usb_gadget_map_request(&dwc->gadget, &req->request,
dep->number);
@@ -902,8 +912,8 @@ static void __dwc3_ep0_do_control_data(struct dwc3 *dwc,
WARN_ON(req->request.length > DWC3_EP0_BOUNCE_SIZE);
- transfer_size = roundup(req->request.length,
- (u32) dep->endpoint.maxpacket);
+ maxpacket = dep->endpoint.maxpacket;
+ transfer_size = roundup(req->request.length, maxpacket);
dwc->ep0_bounced = true;
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index a04342f6cbf..2b6e7e00120 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -1425,8 +1425,10 @@ static int dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on)
if (dwc->revision >= DWC3_REVISION_194A)
reg &= ~DWC3_DCTL_KEEP_CONNECT;
reg |= DWC3_DCTL_RUN_STOP;
+ dwc->pullups_connected = true;
} else {
reg &= ~DWC3_DCTL_RUN_STOP;
+ dwc->pullups_connected = false;
}
dwc3_writel(dwc->regs, DWC3_DCTL, reg);
@@ -1469,6 +1471,33 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on)
return ret;
}
+static void dwc3_gadget_enable_irq(struct dwc3 *dwc)
+{
+ u32 reg;
+
+ /* Enable all but Start and End of Frame IRQs */
+ reg = (DWC3_DEVTEN_VNDRDEVTSTRCVEDEN |
+ DWC3_DEVTEN_EVNTOVERFLOWEN |
+ DWC3_DEVTEN_CMDCMPLTEN |
+ DWC3_DEVTEN_ERRTICERREN |
+ DWC3_DEVTEN_WKUPEVTEN |
+ DWC3_DEVTEN_ULSTCNGEN |
+ DWC3_DEVTEN_CONNECTDONEEN |
+ DWC3_DEVTEN_USBRSTEN |
+ DWC3_DEVTEN_DISCONNEVTEN);
+
+ dwc3_writel(dwc->regs, DWC3_DEVTEN, reg);
+}
+
+static void dwc3_gadget_disable_irq(struct dwc3 *dwc)
+{
+ /* mask all interrupts */
+ dwc3_writel(dwc->regs, DWC3_DEVTEN, 0x00);
+}
+
+static irqreturn_t dwc3_interrupt(int irq, void *_dwc);
+static irqreturn_t dwc3_thread_interrupt(int irq, void *_dwc);
+
static int dwc3_gadget_start(struct usb_gadget *g,
struct usb_gadget_driver *driver)
{
@@ -1476,6 +1505,7 @@ static int dwc3_gadget_start(struct usb_gadget *g,
struct dwc3_ep *dep;
unsigned long flags;
int ret = 0;
+ int irq;
u32 reg;
spin_lock_irqsave(&dwc->lock, flags);
@@ -1489,7 +1519,6 @@ static int dwc3_gadget_start(struct usb_gadget *g,
}
dwc->gadget_driver = driver;
- dwc->gadget.dev.driver = &driver->driver;
reg = dwc3_readl(dwc->regs, DWC3_DCFG);
reg &= ~(DWC3_DCFG_SPEED_MASK);
@@ -1536,6 +1565,17 @@ static int dwc3_gadget_start(struct usb_gadget *g,
dwc->ep0state = EP0_SETUP_PHASE;
dwc3_ep0_out_start(dwc);
+ irq = platform_get_irq(to_platform_device(dwc->dev), 0);
+ ret = request_threaded_irq(irq, dwc3_interrupt, dwc3_thread_interrupt,
+ IRQF_SHARED | IRQF_ONESHOT, "dwc3", dwc);
+ if (ret) {
+ dev_err(dwc->dev, "failed to request irq #%d --> %d\n",
+ irq, ret);
+ goto err1;
+ }
+
+ dwc3_gadget_enable_irq(dwc);
+
spin_unlock_irqrestore(&dwc->lock, flags);
return 0;
@@ -1554,14 +1594,18 @@ static int dwc3_gadget_stop(struct usb_gadget *g,
{
struct dwc3 *dwc = gadget_to_dwc(g);
unsigned long flags;
+ int irq;
spin_lock_irqsave(&dwc->lock, flags);
+ dwc3_gadget_disable_irq(dwc);
+ irq = platform_get_irq(to_platform_device(dwc->dev), 0);
+ free_irq(irq, dwc);
+
__dwc3_gadget_ep_disable(dwc->eps[0]);
__dwc3_gadget_ep_disable(dwc->eps[1]);
dwc->gadget_driver = NULL;
- dwc->gadget.dev.driver = NULL;
spin_unlock_irqrestore(&dwc->lock, flags);
@@ -1579,14 +1623,15 @@ static const struct usb_gadget_ops dwc3_gadget_ops = {
/* -------------------------------------------------------------------------- */
-static int dwc3_gadget_init_endpoints(struct dwc3 *dwc)
+static int dwc3_gadget_init_hw_endpoints(struct dwc3 *dwc,
+ u8 num, u32 direction)
{
struct dwc3_ep *dep;
- u8 epnum;
+ u8 i;
- INIT_LIST_HEAD(&dwc->gadget.ep_list);
+ for (i = 0; i < num; i++) {
+ u8 epnum = (i << 1) | (!!direction);
- for (epnum = 0; epnum < DWC3_ENDPOINTS_NUM; epnum++) {
dep = kzalloc(sizeof(*dep), GFP_KERNEL);
if (!dep) {
dev_err(dwc->dev, "can't allocate endpoint %d\n",
@@ -1600,6 +1645,7 @@ static int dwc3_gadget_init_endpoints(struct dwc3 *dwc)
snprintf(dep->name, sizeof(dep->name), "ep%d%s", epnum >> 1,
(epnum & 1) ? "in" : "out");
+
dep->endpoint.name = dep->name;
dep->direction = (epnum & 1);
@@ -1630,6 +1676,27 @@ static int dwc3_gadget_init_endpoints(struct dwc3 *dwc)
return 0;
}
+static int dwc3_gadget_init_endpoints(struct dwc3 *dwc)
+{
+ int ret;
+
+ INIT_LIST_HEAD(&dwc->gadget.ep_list);
+
+ ret = dwc3_gadget_init_hw_endpoints(dwc, dwc->num_out_eps, 0);
+ if (ret < 0) {
+ dev_vdbg(dwc->dev, "failed to allocate OUT endpoints\n");
+ return ret;
+ }
+
+ ret = dwc3_gadget_init_hw_endpoints(dwc, dwc->num_in_eps, 1);
+ if (ret < 0) {
+ dev_vdbg(dwc->dev, "failed to allocate IN endpoints\n");
+ return ret;
+ }
+
+ return 0;
+}
+
static void dwc3_gadget_free_endpoints(struct dwc3 *dwc)
{
struct dwc3_ep *dep;
@@ -1637,6 +1704,9 @@ static void dwc3_gadget_free_endpoints(struct dwc3 *dwc)
for (epnum = 0; epnum < DWC3_ENDPOINTS_NUM; epnum++) {
dep = dwc->eps[epnum];
+ if (!dep)
+ continue;
+
dwc3_free_trb_pool(dep);
if (epnum != 0 && epnum != 1)
@@ -1646,12 +1716,8 @@ static void dwc3_gadget_free_endpoints(struct dwc3 *dwc)
}
}
-static void dwc3_gadget_release(struct device *dev)
-{
- dev_dbg(dev, "%s\n", __func__);
-}
-
/* -------------------------------------------------------------------------- */
+
static int __dwc3_cleanup_done_trbs(struct dwc3 *dwc, struct dwc3_ep *dep,
struct dwc3_request *req, struct dwc3_trb *trb,
const struct dwc3_event_depevt *event, int status)
@@ -1975,6 +2041,9 @@ static void dwc3_stop_active_transfers(struct dwc3 *dwc)
struct dwc3_ep *dep;
dep = dwc->eps[epnum];
+ if (!dep)
+ continue;
+
if (!(dep->flags & DWC3_EP_ENABLED))
continue;
@@ -1992,6 +2061,8 @@ static void dwc3_clear_stall_all_ep(struct dwc3 *dwc)
int ret;
dep = dwc->eps[epnum];
+ if (!dep)
+ continue;
if (!(dep->flags & DWC3_EP_STALL))
continue;
@@ -2091,7 +2162,7 @@ static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc)
}
/* after reset -> Default State */
- dwc->dev_state = DWC3_DEFAULT_STATE;
+ usb_gadget_set_state(&dwc->gadget, USB_STATE_DEFAULT);
/* Recent versions support automatic phy suspend and don't need this */
if (dwc->revision < DWC3_REVISION_194A) {
@@ -2159,7 +2230,6 @@ static void dwc3_gadget_phy_suspend(struct dwc3 *dwc, u8 speed)
static void dwc3_gadget_conndone_interrupt(struct dwc3 *dwc)
{
- struct dwc3_gadget_ep_cmd_params params;
struct dwc3_ep *dep;
int ret;
u32 reg;
@@ -2167,8 +2237,6 @@ static void dwc3_gadget_conndone_interrupt(struct dwc3 *dwc)
dev_vdbg(dwc->dev, "%s\n", __func__);
- memset(&params, 0x00, sizeof(params));
-
reg = dwc3_readl(dwc->regs, DWC3_DSTS);
speed = reg & DWC3_DSTS_CONNECTSPD;
dwc->speed = speed;
@@ -2280,6 +2348,34 @@ static void dwc3_gadget_linksts_change_interrupt(struct dwc3 *dwc,
unsigned int evtinfo)
{
enum dwc3_link_state next = evtinfo & DWC3_LINK_STATE_MASK;
+ unsigned int pwropt;
+
+ /*
+ * WORKAROUND: DWC3 < 2.50a have an issue when configured without
+ * Hibernation mode enabled which would show up when device detects
+ * host-initiated U3 exit.
+ *
+ * In that case, device will generate a Link State Change Interrupt
+ * from U3 to RESUME which is only necessary if Hibernation is
+ * configured in.
+ *
+ * There are no functional changes due to such spurious event and we
+ * just need to ignore it.
+ *
+ * Refers to:
+ *
+ * STAR#9000570034 RTL: SS Resume event generated in non-Hibernation
+ * operational mode
+ */
+ pwropt = DWC3_GHWPARAMS1_EN_PWROPT(dwc->hwparams.hwparams1);
+ if ((dwc->revision < DWC3_REVISION_250A) &&
+ (pwropt != DWC3_GHWPARAMS1_EN_PWROPT_HIB)) {
+ if ((dwc->link_state == DWC3_LINK_STATE_U3) &&
+ (next == DWC3_LINK_STATE_RESUME)) {
+ dev_vdbg(dwc->dev, "ignoring transition U3 -> Resume\n");
+ return;
+ }
+ }
/*
* WORKAROUND: DWC3 Revisions <1.83a have an issue which, depending
@@ -2390,40 +2486,73 @@ static void dwc3_process_event_entry(struct dwc3 *dwc,
}
}
+static irqreturn_t dwc3_thread_interrupt(int irq, void *_dwc)
+{
+ struct dwc3 *dwc = _dwc;
+ unsigned long flags;
+ irqreturn_t ret = IRQ_NONE;
+ int i;
+
+ spin_lock_irqsave(&dwc->lock, flags);
+
+ for (i = 0; i < dwc->num_event_buffers; i++) {
+ struct dwc3_event_buffer *evt;
+ int left;
+
+ evt = dwc->ev_buffs[i];
+ left = evt->count;
+
+ if (!(evt->flags & DWC3_EVENT_PENDING))
+ continue;
+
+ while (left > 0) {
+ union dwc3_event event;
+
+ event.raw = *(u32 *) (evt->buf + evt->lpos);
+
+ dwc3_process_event_entry(dwc, &event);
+
+ /*
+ * FIXME we wrap around correctly to the next entry as
+ * almost all entries are 4 bytes in size. There is one
+ * entry which has 12 bytes which is a regular entry
+ * followed by 8 bytes data. ATM I don't know how
+ * things are organized if we get next to the a
+ * boundary so I worry about that once we try to handle
+ * that.
+ */
+ evt->lpos = (evt->lpos + 4) % DWC3_EVENT_BUFFERS_SIZE;
+ left -= 4;
+
+ dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(i), 4);
+ }
+
+ evt->count = 0;
+ evt->flags &= ~DWC3_EVENT_PENDING;
+ ret = IRQ_HANDLED;
+ }
+
+ spin_unlock_irqrestore(&dwc->lock, flags);
+
+ return ret;
+}
+
static irqreturn_t dwc3_process_event_buf(struct dwc3 *dwc, u32 buf)
{
struct dwc3_event_buffer *evt;
- int left;
u32 count;
+ evt = dwc->ev_buffs[buf];
+
count = dwc3_readl(dwc->regs, DWC3_GEVNTCOUNT(buf));
count &= DWC3_GEVNTCOUNT_MASK;
if (!count)
return IRQ_NONE;
- evt = dwc->ev_buffs[buf];
- left = count;
+ evt->count = count;
+ evt->flags |= DWC3_EVENT_PENDING;
- while (left > 0) {
- union dwc3_event event;
-
- event.raw = *(u32 *) (evt->buf + evt->lpos);
-
- dwc3_process_event_entry(dwc, &event);
- /*
- * XXX we wrap around correctly to the next entry as almost all
- * entries are 4 bytes in size. There is one entry which has 12
- * bytes which is a regular entry followed by 8 bytes data. ATM
- * I don't know how things are organized if were get next to the
- * a boundary so I worry about that once we try to handle that.
- */
- evt->lpos = (evt->lpos + 4) % DWC3_EVENT_BUFFERS_SIZE;
- left -= 4;
-
- dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(buf), 4);
- }
-
- return IRQ_HANDLED;
+ return IRQ_WAKE_THREAD;
}
static irqreturn_t dwc3_interrupt(int irq, void *_dwc)
@@ -2438,7 +2567,7 @@ static irqreturn_t dwc3_interrupt(int irq, void *_dwc)
irqreturn_t status;
status = dwc3_process_event_buf(dwc, i);
- if (status == IRQ_HANDLED)
+ if (status == IRQ_WAKE_THREAD)
ret = status;
}
@@ -2457,7 +2586,6 @@ int dwc3_gadget_init(struct dwc3 *dwc)
{
u32 reg;
int ret;
- int irq;
dwc->ctrl_req = dma_alloc_coherent(dwc->dev, sizeof(*dwc->ctrl_req),
&dwc->ctrl_req_addr, GFP_KERNEL);
@@ -2491,19 +2619,10 @@ int dwc3_gadget_init(struct dwc3 *dwc)
goto err3;
}
- dev_set_name(&dwc->gadget.dev, "gadget");
-
dwc->gadget.ops = &dwc3_gadget_ops;
dwc->gadget.max_speed = USB_SPEED_SUPER;
dwc->gadget.speed = USB_SPEED_UNKNOWN;
- dwc->gadget.dev.parent = dwc->dev;
dwc->gadget.sg_supported = true;
-
- dma_set_coherent_mask(&dwc->gadget.dev, dwc->dev->coherent_dma_mask);
-
- dwc->gadget.dev.dma_parms = dwc->dev->dma_parms;
- dwc->gadget.dev.dma_mask = dwc->dev->dma_mask;
- dwc->gadget.dev.release = dwc3_gadget_release;
dwc->gadget.name = "dwc3-gadget";
/*
@@ -2515,60 +2634,24 @@ int dwc3_gadget_init(struct dwc3 *dwc)
if (ret)
goto err4;
- irq = platform_get_irq(to_platform_device(dwc->dev), 0);
-
- ret = request_irq(irq, dwc3_interrupt, IRQF_SHARED,
- "dwc3", dwc);
- if (ret) {
- dev_err(dwc->dev, "failed to request irq #%d --> %d\n",
- irq, ret);
- goto err5;
- }
-
reg = dwc3_readl(dwc->regs, DWC3_DCFG);
reg |= DWC3_DCFG_LPM_CAP;
dwc3_writel(dwc->regs, DWC3_DCFG, reg);
- /* Enable all but Start and End of Frame IRQs */
- reg = (DWC3_DEVTEN_VNDRDEVTSTRCVEDEN |
- DWC3_DEVTEN_EVNTOVERFLOWEN |
- DWC3_DEVTEN_CMDCMPLTEN |
- DWC3_DEVTEN_ERRTICERREN |
- DWC3_DEVTEN_WKUPEVTEN |
- DWC3_DEVTEN_ULSTCNGEN |
- DWC3_DEVTEN_CONNECTDONEEN |
- DWC3_DEVTEN_USBRSTEN |
- DWC3_DEVTEN_DISCONNEVTEN);
- dwc3_writel(dwc->regs, DWC3_DEVTEN, reg);
-
- /* automatic phy suspend only on recent versions */
+ /* Enable USB2 LPM and automatic phy suspend only on recent versions */
if (dwc->revision >= DWC3_REVISION_194A) {
dwc3_gadget_usb2_phy_suspend(dwc, false);
dwc3_gadget_usb3_phy_suspend(dwc, false);
}
- ret = device_register(&dwc->gadget.dev);
- if (ret) {
- dev_err(dwc->dev, "failed to register gadget device\n");
- put_device(&dwc->gadget.dev);
- goto err6;
- }
-
ret = usb_add_gadget_udc(dwc->dev, &dwc->gadget);
if (ret) {
dev_err(dwc->dev, "failed to register udc\n");
- goto err7;
+ goto err5;
}
return 0;
-err7:
- device_unregister(&dwc->gadget.dev);
-
-err6:
- dwc3_writel(dwc->regs, DWC3_DEVTEN, 0x00);
- free_irq(irq, dwc);
-
err5:
dwc3_gadget_free_endpoints(dwc);
@@ -2591,15 +2674,11 @@ err0:
return ret;
}
+/* -------------------------------------------------------------------------- */
+
void dwc3_gadget_exit(struct dwc3 *dwc)
{
- int irq;
-
usb_del_gadget_udc(&dwc->gadget);
- irq = platform_get_irq(to_platform_device(dwc->dev), 0);
-
- dwc3_writel(dwc->regs, DWC3_DEVTEN, 0x00);
- free_irq(irq, dwc);
dwc3_gadget_free_endpoints(dwc);
@@ -2613,6 +2692,63 @@ void dwc3_gadget_exit(struct dwc3 *dwc)
dma_free_coherent(dwc->dev, sizeof(*dwc->ctrl_req),
dwc->ctrl_req, dwc->ctrl_req_addr);
+}
+
+int dwc3_gadget_prepare(struct dwc3 *dwc)
+{
+ if (dwc->pullups_connected)
+ dwc3_gadget_disable_irq(dwc);
+
+ return 0;
+}
+
+void dwc3_gadget_complete(struct dwc3 *dwc)
+{
+ if (dwc->pullups_connected) {
+ dwc3_gadget_enable_irq(dwc);
+ dwc3_gadget_run_stop(dwc, true);
+ }
+}
+
+int dwc3_gadget_suspend(struct dwc3 *dwc)
+{
+ __dwc3_gadget_ep_disable(dwc->eps[0]);
+ __dwc3_gadget_ep_disable(dwc->eps[1]);
+
+ dwc->dcfg = dwc3_readl(dwc->regs, DWC3_DCFG);
+
+ return 0;
+}
+
+int dwc3_gadget_resume(struct dwc3 *dwc)
+{
+ struct dwc3_ep *dep;
+ int ret;
- device_unregister(&dwc->gadget.dev);
+ /* Start with SuperSpeed Default */
+ dwc3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(512);
+
+ dep = dwc->eps[0];
+ ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL, false);
+ if (ret)
+ goto err0;
+
+ dep = dwc->eps[1];
+ ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL, false);
+ if (ret)
+ goto err1;
+
+ /* begin to receive SETUP packets */
+ dwc->ep0state = EP0_SETUP_PHASE;
+ dwc3_ep0_out_start(dwc);
+
+ dwc3_writel(dwc->regs, DWC3_DCFG, dwc->dcfg);
+
+ return 0;
+
+err1:
+ __dwc3_gadget_ep_disable(dwc->eps[0]);
+
+err0:
+ return ret;
}
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index 5a0c541daf8..83300d94a89 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -144,7 +144,9 @@ config USB_AT91
config USB_LPC32XX
tristate "LPC32XX USB Peripheral Controller"
depends on ARCH_LPC32XX
+ depends on USB_PHY
select USB_ISP1301
+ select USB_OTG_UTILS
help
This option selects the USB device controller in the LPC32xx SoC.
@@ -194,8 +196,8 @@ config USB_FUSB300
config USB_OMAP
tristate "OMAP USB Device Controller"
depends on ARCH_OMAP1
+ depends on USB_PHY
select ISP1301_OMAP if MACH_OMAP_H2 || MACH_OMAP_H3 || MACH_OMAP_H4_OTG
- select USB_OTG_UTILS if ARCH_OMAP
help
Many Texas Instruments OMAP processors have flexible full
speed USB device controllers, with support for up to 30
@@ -210,7 +212,6 @@ config USB_OMAP
config USB_PXA25X
tristate "PXA 25x or IXP 4xx"
depends on (ARCH_PXA && PXA25x) || ARCH_IXP4XX
- select USB_OTG_UTILS
help
Intel's PXA 25x series XScale ARM-5TE processors include
an integrated full speed USB 1.1 device controller. The
@@ -258,8 +259,6 @@ config USB_RENESAS_USBHS_UDC
config USB_PXA27X
tristate "PXA 27x"
- depends on ARCH_PXA && (PXA27x || PXA3xx)
- select USB_OTG_UTILS
help
Intel's PXA 27x series XScale ARM v5TE processors include
an integrated full speed USB 1.1 device controller.
@@ -328,9 +327,6 @@ config USB_MV_UDC
config USB_MV_U3D
tristate "MARVELL PXA2128 USB 3.0 controller"
- depends on CPU_MMP3
- select USB_GADGET_DUALSPEED
- select USB_GADGET_SUPERSPEED
help
MARVELL PXA2128 Processor series include a super speed USB3.0 device
controller, which support super speed USB peripheral.
@@ -500,6 +496,7 @@ endmenu
# composite based drivers
config USB_LIBCOMPOSITE
tristate
+ select CONFIGFS_FS
depends on USB_GADGET
config USB_F_ACM
@@ -511,6 +508,12 @@ config USB_F_SS_LB
config USB_U_SERIAL
tristate
+config USB_F_SERIAL
+ tristate
+
+config USB_F_OBEX
+ tristate
+
choice
tristate "USB Gadget Drivers"
default USB_ETH
@@ -765,6 +768,8 @@ config USB_G_SERIAL
depends on TTY
select USB_U_SERIAL
select USB_F_ACM
+ select USB_F_SERIAL
+ select USB_F_OBEX
select USB_LIBCOMPOSITE
help
The Serial Gadget talks to the Linux-USB generic serial driver.
@@ -838,6 +843,7 @@ config USB_G_NOKIA
depends on PHONET
select USB_LIBCOMPOSITE
select USB_U_SERIAL
+ select USB_F_ACM
help
The Nokia composite gadget provides support for acm, obex
and phonet in only one composite gadget driver.
@@ -956,6 +962,7 @@ config USB_G_WEBCAM
tristate "USB Webcam Gadget"
depends on VIDEO_DEV
select USB_LIBCOMPOSITE
+ select VIDEOBUF2_VMALLOC
help
The Webcam Gadget acts as a composite USB Audio and Video Class
device. It provides a userspace API to process UVC control requests
diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
index 97a13c349cc..6afd16659e7 100644
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -6,7 +6,7 @@ ccflags-$(CONFIG_USB_GADGET_DEBUG) := -DDEBUG
obj-$(CONFIG_USB_GADGET) += udc-core.o
obj-$(CONFIG_USB_LIBCOMPOSITE) += libcomposite.o
libcomposite-y := usbstring.o config.o epautoconf.o
-libcomposite-y += composite.o functions.o
+libcomposite-y += composite.o functions.o configfs.o
obj-$(CONFIG_USB_DUMMY_HCD) += dummy_hcd.o
obj-$(CONFIG_USB_NET2272) += net2272.o
obj-$(CONFIG_USB_NET2280) += net2280.o
@@ -35,6 +35,17 @@ mv_udc-y := mv_udc_core.o
obj-$(CONFIG_USB_FUSB300) += fusb300_udc.o
obj-$(CONFIG_USB_MV_U3D) += mv_u3d_core.o
+# USB Functions
+usb_f_acm-y := f_acm.o
+obj-$(CONFIG_USB_F_ACM) += usb_f_acm.o
+usb_f_ss_lb-y := f_loopback.o f_sourcesink.o
+obj-$(CONFIG_USB_F_SS_LB) += usb_f_ss_lb.o
+obj-$(CONFIG_USB_U_SERIAL) += u_serial.o
+usb_f_serial-y := f_serial.o
+obj-$(CONFIG_USB_F_SERIAL) += usb_f_serial.o
+usb_f_obex-y := f_obex.o
+obj-$(CONFIG_USB_F_OBEX) += usb_f_obex.o
+
#
# USB gadget drivers
#
@@ -74,9 +85,3 @@ obj-$(CONFIG_USB_G_WEBCAM) += g_webcam.o
obj-$(CONFIG_USB_G_NCM) += g_ncm.o
obj-$(CONFIG_USB_G_ACM_MS) += g_acm_ms.o
obj-$(CONFIG_USB_GADGET_TARGET) += tcm_usb_gadget.o
-
-# USB Functions
-obj-$(CONFIG_USB_F_ACM) += f_acm.o
-f_ss_lb-y := f_loopback.o f_sourcesink.o
-obj-$(CONFIG_USB_F_SS_LB) += f_ss_lb.o
-obj-$(CONFIG_USB_U_SERIAL) += u_serial.o
diff --git a/drivers/usb/gadget/acm_ms.c b/drivers/usb/gadget/acm_ms.c
index 8f2b0e39153..4b947bb50f6 100644
--- a/drivers/usb/gadget/acm_ms.c
+++ b/drivers/usb/gadget/acm_ms.c
@@ -109,7 +109,6 @@ FSG_MODULE_PARAMETERS(/* no prefix */, fsg_mod_data);
static struct fsg_common fsg_common;
/*-------------------------------------------------------------------------*/
-static unsigned char tty_line;
static struct usb_function *f_acm;
static struct usb_function_instance *f_acm_inst;
/*
@@ -117,7 +116,6 @@ static struct usb_function_instance *f_acm_inst;
*/
static int __init acm_ms_do_config(struct usb_configuration *c)
{
- struct f_serial_opts *opts;
int status;
if (gadget_is_otg(c->cdev->gadget)) {
@@ -129,9 +127,6 @@ static int __init acm_ms_do_config(struct usb_configuration *c)
if (IS_ERR(f_acm_inst))
return PTR_ERR(f_acm_inst);
- opts = container_of(f_acm_inst, struct f_serial_opts, func_inst);
- opts->port_num = tty_line;
-
f_acm = usb_get_function(f_acm_inst);
if (IS_ERR(f_acm)) {
status = PTR_ERR(f_acm);
@@ -171,16 +166,11 @@ static int __init acm_ms_bind(struct usb_composite_dev *cdev)
int status;
void *retp;
- /* set up serial link layer */
- status = gserial_alloc_line(&tty_line);
- if (status < 0)
- return status;
-
/* set up mass storage function */
retp = fsg_common_from_params(&fsg_common, cdev, &fsg_mod_data);
if (IS_ERR(retp)) {
status = PTR_ERR(retp);
- goto fail0;
+ return PTR_ERR(retp);
}
/*
@@ -207,8 +197,6 @@ static int __init acm_ms_bind(struct usb_composite_dev *cdev)
/* error recovery */
fail1:
fsg_common_put(&fsg_common);
-fail0:
- gserial_free_line(tty_line);
return status;
}
@@ -216,7 +204,6 @@ static int __exit acm_ms_unbind(struct usb_composite_dev *cdev)
{
usb_put_function(f_acm);
usb_put_function_instance(f_acm_inst);
- gserial_free_line(tty_line);
return 0;
}
diff --git a/drivers/usb/gadget/amd5536udc.c b/drivers/usb/gadget/amd5536udc.c
index 75973f33a4c..f52dcfe8f54 100644
--- a/drivers/usb/gadget/amd5536udc.c
+++ b/drivers/usb/gadget/amd5536udc.c
@@ -1922,7 +1922,6 @@ static int amd5536_udc_start(struct usb_gadget *g,
driver->driver.bus = NULL;
dev->driver = driver;
- dev->gadget.dev.driver = &driver->driver;
/* Some gadget drivers use both ep0 directions.
* NOTE: to gadget driver, ep0 is just one endpoint...
@@ -1973,7 +1972,6 @@ static int amd5536_udc_stop(struct usb_gadget *g,
shutdown(dev, driver);
spin_unlock_irqrestore(&dev->lock, flags);
- dev->gadget.dev.driver = NULL;
dev->driver = NULL;
/* set SD */
@@ -3080,7 +3078,6 @@ static void udc_pci_remove(struct pci_dev *pdev)
if (dev->active)
pci_disable_device(pdev);
- device_unregister(&dev->gadget.dev);
pci_set_drvdata(pdev, NULL);
udc_remove(dev);
@@ -3245,8 +3242,6 @@ static int udc_pci_probe(
dev->phys_addr = resource;
dev->irq = pdev->irq;
dev->pdev = pdev;
- dev->gadget.dev.parent = &pdev->dev;
- dev->gadget.dev.dma_mask = pdev->dev.dma_mask;
/* general probing */
if (udc_probe(dev) == 0)
@@ -3273,7 +3268,6 @@ static int udc_probe(struct udc *dev)
dev->gadget.ops = &udc_ops;
dev_set_name(&dev->gadget.dev, "gadget");
- dev->gadget.dev.release = gadget_release;
dev->gadget.name = name;
dev->gadget.max_speed = USB_SPEED_HIGH;
@@ -3297,17 +3291,11 @@ static int udc_probe(struct udc *dev)
"driver version: %s(for Geode5536 B1)\n", tmp);
udc = dev;
- retval = usb_add_gadget_udc(&udc->pdev->dev, &dev->gadget);
+ retval = usb_add_gadget_udc_release(&udc->pdev->dev, &dev->gadget,
+ gadget_release);
if (retval)
goto finished;
- retval = device_register(&dev->gadget.dev);
- if (retval) {
- usb_del_gadget_udc(&dev->gadget);
- put_device(&dev->gadget.dev);
- goto finished;
- }
-
/* timer init */
init_timer(&udc_timer);
udc_timer.function = udc_timer_function;
diff --git a/drivers/usb/gadget/amd5536udc.h b/drivers/usb/gadget/amd5536udc.h
index f1bf32e6b8d..6744d3b8310 100644
--- a/drivers/usb/gadget/amd5536udc.h
+++ b/drivers/usb/gadget/amd5536udc.h
@@ -472,7 +472,6 @@ struct udc_request {
/* flags */
unsigned dma_going : 1,
- dma_mapping : 1,
dma_done : 1;
/* phys. address */
dma_addr_t td_phys;
diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c
index 45dd2929a67..a690d64217f 100644
--- a/drivers/usb/gadget/at91_udc.c
+++ b/drivers/usb/gadget/at91_udc.c
@@ -1631,7 +1631,6 @@ static int at91_start(struct usb_gadget *gadget,
udc = container_of(gadget, struct at91_udc, gadget);
udc->driver = driver;
- udc->gadget.dev.driver = &driver->driver;
udc->gadget.dev.of_node = udc->pdev->dev.of_node;
udc->enabled = 1;
udc->selfpowered = 1;
@@ -1652,7 +1651,6 @@ static int at91_stop(struct usb_gadget *gadget,
at91_udp_write(udc, AT91_UDP_IDR, ~0);
spin_unlock_irqrestore(&udc->lock, flags);
- udc->gadget.dev.driver = NULL;
udc->driver = NULL;
DBG("unbound from %s\n", driver->driver.name);
@@ -1780,13 +1778,7 @@ static int at91udc_probe(struct platform_device *pdev)
DBG("clocks missing\n");
retval = -ENODEV;
/* NOTE: we "know" here that refcounts on these are NOPs */
- goto fail0b;
- }
-
- retval = device_register(&udc->gadget.dev);
- if (retval < 0) {
- put_device(&udc->gadget.dev);
- goto fail0b;
+ goto fail1;
}
/* don't do anything until we have both gadget driver and VBUS */
@@ -1857,8 +1849,6 @@ fail3:
fail2:
free_irq(udc->udp_irq, udc);
fail1:
- device_unregister(&udc->gadget.dev);
-fail0b:
iounmap(udc->udp_baseaddr);
fail0a:
if (cpu_is_at91rm9200())
@@ -1892,8 +1882,6 @@ static int __exit at91udc_remove(struct platform_device *pdev)
gpio_free(udc->board.vbus_pin);
}
free_irq(udc->udp_irq, udc);
- device_unregister(&udc->gadget.dev);
-
iounmap(udc->udp_baseaddr);
if (cpu_is_at91rm9200())
diff --git a/drivers/usb/gadget/atmel_usba_udc.c b/drivers/usb/gadget/atmel_usba_udc.c
index b66130c9726..f2a970f75bf 100644
--- a/drivers/usb/gadget/atmel_usba_udc.c
+++ b/drivers/usb/gadget/atmel_usba_udc.c
@@ -489,13 +489,8 @@ request_complete(struct usba_ep *ep, struct usba_request *req, int status)
if (req->req.status == -EINPROGRESS)
req->req.status = status;
- if (req->mapped) {
- dma_unmap_single(
- &udc->pdev->dev, req->req.dma, req->req.length,
- ep->is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
- req->req.dma = DMA_ADDR_INVALID;
- req->mapped = 0;
- }
+ if (req->using_dma)
+ usb_gadget_unmap_request(&udc->gadget, &req->req, ep->is_in);
DBG(DBG_GADGET | DBG_REQ,
"%s: req %p complete: status %d, actual %u\n",
@@ -684,7 +679,6 @@ usba_ep_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags)
return NULL;
INIT_LIST_HEAD(&req->queue);
- req->req.dma = DMA_ADDR_INVALID;
return &req->req;
}
@@ -717,20 +711,11 @@ static int queue_dma(struct usba_udc *udc, struct usba_ep *ep,
return -EINVAL;
}
- req->using_dma = 1;
-
- if (req->req.dma == DMA_ADDR_INVALID) {
- req->req.dma = dma_map_single(
- &udc->pdev->dev, req->req.buf, req->req.length,
- ep->is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
- req->mapped = 1;
- } else {
- dma_sync_single_for_device(
- &udc->pdev->dev, req->req.dma, req->req.length,
- ep->is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
- req->mapped = 0;
- }
+ ret = usb_gadget_map_request(&udc->gadget, &req->req, ep->is_in);
+ if (ret)
+ return ret;
+ req->using_dma = 1;
req->ctrl = USBA_BF(DMA_BUF_LEN, req->req.length)
| USBA_DMA_CH_EN | USBA_DMA_END_BUF_IE
| USBA_DMA_END_TR_EN | USBA_DMA_END_TR_IE;
@@ -1799,7 +1784,6 @@ static int atmel_usba_start(struct usb_gadget *gadget,
udc->devstatus = 1 << USB_DEVICE_SELF_POWERED;
udc->driver = driver;
- udc->gadget.dev.driver = &driver->driver;
spin_unlock_irqrestore(&udc->lock, flags);
clk_enable(udc->pclk);
@@ -1841,7 +1825,6 @@ static int atmel_usba_stop(struct usb_gadget *gadget,
toggle_bias(0);
usba_writel(udc, CTRL, USBA_DISABLE_MASK);
- udc->gadget.dev.driver = NULL;
udc->driver = NULL;
clk_disable(udc->hclk);
@@ -1900,10 +1883,6 @@ static int __init usba_udc_probe(struct platform_device *pdev)
dev_info(&pdev->dev, "FIFO at 0x%08lx mapped at %p\n",
(unsigned long)fifo->start, udc->fifo);
- device_initialize(&udc->gadget.dev);
- udc->gadget.dev.parent = &pdev->dev;
- udc->gadget.dev.dma_mask = pdev->dev.dma_mask;
-
platform_set_drvdata(pdev, udc);
/* Make sure we start from a clean slate */
@@ -1962,12 +1941,6 @@ static int __init usba_udc_probe(struct platform_device *pdev)
}
udc->irq = irq;
- ret = device_add(&udc->gadget.dev);
- if (ret) {
- dev_dbg(&pdev->dev, "Could not add gadget: %d\n", ret);
- goto err_device_add;
- }
-
if (gpio_is_valid(pdata->vbus_pin)) {
if (!gpio_request(pdata->vbus_pin, "atmel_usba_udc")) {
udc->vbus_pin = pdata->vbus_pin;
@@ -2007,9 +1980,6 @@ err_add_udc:
gpio_free(udc->vbus_pin);
}
- device_unregister(&udc->gadget.dev);
-
-err_device_add:
free_irq(irq, udc);
err_request_irq:
kfree(usba_ep);
@@ -2053,8 +2023,6 @@ static int __exit usba_udc_remove(struct platform_device *pdev)
clk_put(udc->hclk);
clk_put(udc->pclk);
- device_unregister(&udc->gadget.dev);
-
return 0;
}
diff --git a/drivers/usb/gadget/atmel_usba_udc.h b/drivers/usb/gadget/atmel_usba_udc.h
index 9791259cbda..d65a61851d3 100644
--- a/drivers/usb/gadget/atmel_usba_udc.h
+++ b/drivers/usb/gadget/atmel_usba_udc.h
@@ -216,12 +216,6 @@
#define EP0_EPT_SIZE USBA_EPT_SIZE_64
#define EP0_NR_BANKS 1
-/*
- * REVISIT: Try to eliminate this value. Can we rely on req->mapped to
- * provide this information?
- */
-#define DMA_ADDR_INVALID (~(dma_addr_t)0)
-
#define FIFO_IOMEM_ID 0
#define CTRL_IOMEM_ID 1
diff --git a/drivers/usb/gadget/bcm63xx_udc.c b/drivers/usb/gadget/bcm63xx_udc.c
index 8cc8253f110..6e6518264c4 100644
--- a/drivers/usb/gadget/bcm63xx_udc.c
+++ b/drivers/usb/gadget/bcm63xx_udc.c
@@ -1819,7 +1819,6 @@ static int bcm63xx_udc_start(struct usb_gadget *gadget,
udc->driver = driver;
driver->driver.bus = NULL;
- udc->gadget.dev.driver = &driver->driver;
udc->gadget.dev.of_node = udc->dev->of_node;
spin_unlock_irqrestore(&udc->lock, flags);
@@ -1841,7 +1840,6 @@ static int bcm63xx_udc_stop(struct usb_gadget *gadget,
spin_lock_irqsave(&udc->lock, flags);
udc->driver = NULL;
- udc->gadget.dev.driver = NULL;
/*
* If we switch the PHY too abruptly after dropping D+, the host
@@ -2306,17 +2304,6 @@ static void bcm63xx_udc_cleanup_debugfs(struct bcm63xx_udc *udc)
***********************************************************************/
/**
- * bcm63xx_udc_gadget_release - Called from device_release().
- * @dev: Unused.
- *
- * We get a warning if this function doesn't exist, but it's empty because
- * we don't have to free any of the memory allocated with the devm_* APIs.
- */
-static void bcm63xx_udc_gadget_release(struct device *dev)
-{
-}
-
-/**
* bcm63xx_udc_probe - Initialize a new instance of the UDC.
* @pdev: Platform device struct from the bcm63xx BSP code.
*
@@ -2368,13 +2355,9 @@ static int bcm63xx_udc_probe(struct platform_device *pdev)
spin_lock_init(&udc->lock);
INIT_WORK(&udc->ep0_wq, bcm63xx_ep0_process);
- dev_set_name(&udc->gadget.dev, "gadget");
udc->gadget.ops = &bcm63xx_udc_ops;
udc->gadget.name = dev_name(dev);
- udc->gadget.dev.parent = dev;
- udc->gadget.dev.release = bcm63xx_udc_gadget_release;
- udc->gadget.dev.dma_mask = dev->dma_mask;
if (!pd->use_fullspeed && !use_fullspeed)
udc->gadget.max_speed = USB_SPEED_HIGH;
@@ -2414,17 +2397,12 @@ static int bcm63xx_udc_probe(struct platform_device *pdev)
}
}
- rc = device_register(&udc->gadget.dev);
- if (rc)
- goto out_uninit;
-
bcm63xx_udc_init_debugfs(udc);
rc = usb_add_gadget_udc(dev, &udc->gadget);
if (!rc)
return 0;
bcm63xx_udc_cleanup_debugfs(udc);
- device_unregister(&udc->gadget.dev);
out_uninit:
bcm63xx_uninit_udc_hw(udc);
return rc;
@@ -2440,7 +2418,6 @@ static int bcm63xx_udc_remove(struct platform_device *pdev)
bcm63xx_udc_cleanup_debugfs(udc);
usb_del_gadget_udc(&udc->gadget);
- device_unregister(&udc->gadget.dev);
BUG_ON(udc->driver);
platform_set_drvdata(pdev, NULL);
diff --git a/drivers/usb/gadget/cdc2.c b/drivers/usb/gadget/cdc2.c
index a7d6f702675..2c525518276 100644
--- a/drivers/usb/gadget/cdc2.c
+++ b/drivers/usb/gadget/cdc2.c
@@ -103,18 +103,16 @@ static struct usb_gadget_strings *dev_strings[] = {
};
static u8 hostaddr[ETH_ALEN];
-
+static struct eth_dev *the_dev;
/*-------------------------------------------------------------------------*/
static struct usb_function *f_acm;
static struct usb_function_instance *fi_serial;
-static unsigned char tty_line;
/*
* We _always_ have both CDC ECM and CDC ACM functions.
*/
static int __init cdc_do_config(struct usb_configuration *c)
{
- struct f_serial_opts *opts;
int status;
if (gadget_is_otg(c->cdev->gadget)) {
@@ -122,7 +120,7 @@ static int __init cdc_do_config(struct usb_configuration *c)
c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
}
- status = ecm_bind_config(c, hostaddr);
+ status = ecm_bind_config(c, hostaddr, the_dev);
if (status < 0)
return status;
@@ -130,12 +128,11 @@ static int __init cdc_do_config(struct usb_configuration *c)
if (IS_ERR(fi_serial))
return PTR_ERR(fi_serial);
- opts = container_of(fi_serial, struct f_serial_opts, func_inst);
- opts->port_num = tty_line;
-
f_acm = usb_get_function(fi_serial);
- if (IS_ERR(f_acm))
+ if (IS_ERR(f_acm)) {
+ status = PTR_ERR(f_acm);
goto err_func_acm;
+ }
status = usb_add_function(c, f_acm);
if (status)
@@ -169,14 +166,9 @@ static int __init cdc_bind(struct usb_composite_dev *cdev)
}
/* set up network link layer */
- status = gether_setup(cdev->gadget, hostaddr);
- if (status < 0)
- return status;
-
- /* set up serial link layer */
- status = gserial_alloc_line(&tty_line);
- if (status < 0)
- goto fail0;
+ the_dev = gether_setup(cdev->gadget, hostaddr);
+ if (IS_ERR(the_dev))
+ return PTR_ERR(the_dev);
/* Allocate string descriptor numbers ... note that string
* contents can be overridden by the composite_dev glue.
@@ -200,9 +192,7 @@ static int __init cdc_bind(struct usb_composite_dev *cdev)
return 0;
fail1:
- gserial_free_line(tty_line);
-fail0:
- gether_cleanup();
+ gether_cleanup(the_dev);
return status;
}
@@ -210,8 +200,7 @@ static int __exit cdc_unbind(struct usb_composite_dev *cdev)
{
usb_put_function(f_acm);
usb_put_function_instance(fi_serial);
- gserial_free_line(tty_line);
- gether_cleanup();
+ gether_cleanup(the_dev);
return 0;
}
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index 7c821de8ce3..55f4df60f32 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -1637,6 +1637,7 @@ void composite_dev_cleanup(struct usb_composite_dev *cdev)
kfree(cdev->req->buf);
usb_ep_free_request(cdev->gadget->ep0, cdev->req);
}
+ cdev->next_string_id = 0;
device_remove_file(&cdev->gadget->dev, &dev_attr_suspended);
}
@@ -1757,10 +1758,7 @@ static const struct usb_gadget_driver composite_driver_template = {
/**
* usb_composite_probe() - register a composite driver
* @driver: the driver to register
- * @bind: the callback used to allocate resources that are shared across the
- * whole device, such as string IDs, and add its configurations using
- * @usb_add_config(). This may fail by returning a negative errno
- * value; it should return zero on successful initialization.
+ *
* Context: single threaded during gadget setup
*
* This function is used to register drivers using the composite driver
diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c
new file mode 100644
index 00000000000..3d5cfc9c2c7
--- /dev/null
+++ b/drivers/usb/gadget/configfs.c
@@ -0,0 +1,1003 @@
+#include <linux/configfs.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/device.h>
+#include <linux/usb/composite.h>
+#include <linux/usb/gadget_configfs.h>
+
+int check_user_usb_string(const char *name,
+ struct usb_gadget_strings *stringtab_dev)
+{
+ unsigned primary_lang;
+ unsigned sub_lang;
+ u16 num;
+ int ret;
+
+ ret = kstrtou16(name, 0, &num);
+ if (ret)
+ return ret;
+
+ primary_lang = num & 0x3ff;
+ sub_lang = num >> 10;
+
+ /* simple sanity check for valid langid */
+ switch (primary_lang) {
+ case 0:
+ case 0x62 ... 0xfe:
+ case 0x100 ... 0x3ff:
+ return -EINVAL;
+ }
+ if (!sub_lang)
+ return -EINVAL;
+
+ stringtab_dev->language = num;
+ return 0;
+}
+
+#define MAX_NAME_LEN 40
+#define MAX_USB_STRING_LANGS 2
+
+struct gadget_info {
+ struct config_group group;
+ struct config_group functions_group;
+ struct config_group configs_group;
+ struct config_group strings_group;
+ struct config_group *default_groups[4];
+
+ struct mutex lock;
+ struct usb_gadget_strings *gstrings[MAX_USB_STRING_LANGS + 1];
+ struct list_head string_list;
+ struct list_head available_func;
+
+ const char *udc_name;
+#ifdef CONFIG_USB_OTG
+ struct usb_otg_descriptor otg;
+#endif
+ struct usb_composite_driver composite;
+ struct usb_composite_dev cdev;
+};
+
+struct config_usb_cfg {
+ struct config_group group;
+ struct config_group strings_group;
+ struct config_group *default_groups[2];
+ struct list_head string_list;
+ struct usb_configuration c;
+ struct list_head func_list;
+ struct usb_gadget_strings *gstrings[MAX_USB_STRING_LANGS + 1];
+};
+
+struct gadget_strings {
+ struct usb_gadget_strings stringtab_dev;
+ struct usb_string strings[USB_GADGET_FIRST_AVAIL_IDX];
+ char *manufacturer;
+ char *product;
+ char *serialnumber;
+
+ struct config_group group;
+ struct list_head list;
+};
+
+struct gadget_config_name {
+ struct usb_gadget_strings stringtab_dev;
+ struct usb_string strings;
+ char *configuration;
+
+ struct config_group group;
+ struct list_head list;
+};
+
+static int usb_string_copy(const char *s, char **s_copy)
+{
+ int ret;
+ char *str;
+ char *copy = *s_copy;
+ ret = strlen(s);
+ if (ret > 126)
+ return -EOVERFLOW;
+
+ str = kstrdup(s, GFP_KERNEL);
+ if (!str)
+ return -ENOMEM;
+ if (str[ret - 1] == '\n')
+ str[ret - 1] = '\0';
+ kfree(copy);
+ *s_copy = str;
+ return 0;
+}
+
+CONFIGFS_ATTR_STRUCT(gadget_info);
+CONFIGFS_ATTR_STRUCT(config_usb_cfg);
+
+#define GI_DEVICE_DESC_ITEM_ATTR(name) \
+ static struct gadget_info_attribute gadget_cdev_desc_##name = \
+ __CONFIGFS_ATTR(name, S_IRUGO | S_IWUSR, \
+ gadget_dev_desc_##name##_show, \
+ gadget_dev_desc_##name##_store)
+
+#define GI_DEVICE_DESC_SIMPLE_R_u8(__name) \
+ static ssize_t gadget_dev_desc_##__name##_show(struct gadget_info *gi, \
+ char *page) \
+{ \
+ return sprintf(page, "0x%02x\n", gi->cdev.desc.__name); \
+}
+
+#define GI_DEVICE_DESC_SIMPLE_R_u16(__name) \
+ static ssize_t gadget_dev_desc_##__name##_show(struct gadget_info *gi, \
+ char *page) \
+{ \
+ return sprintf(page, "0x%04x\n", le16_to_cpup(&gi->cdev.desc.__name)); \
+}
+
+
+#define GI_DEVICE_DESC_SIMPLE_W_u8(_name) \
+ static ssize_t gadget_dev_desc_##_name##_store(struct gadget_info *gi, \
+ const char *page, size_t len) \
+{ \
+ u8 val; \
+ int ret; \
+ ret = kstrtou8(page, 0, &val); \
+ if (ret) \
+ return ret; \
+ gi->cdev.desc._name = val; \
+ return len; \
+}
+
+#define GI_DEVICE_DESC_SIMPLE_W_u16(_name) \
+ static ssize_t gadget_dev_desc_##_name##_store(struct gadget_info *gi, \
+ const char *page, size_t len) \
+{ \
+ u16 val; \
+ int ret; \
+ ret = kstrtou16(page, 0, &val); \
+ if (ret) \
+ return ret; \
+ gi->cdev.desc._name = cpu_to_le16p(&val); \
+ return len; \
+}
+
+#define GI_DEVICE_DESC_SIMPLE_RW(_name, _type) \
+ GI_DEVICE_DESC_SIMPLE_R_##_type(_name) \
+ GI_DEVICE_DESC_SIMPLE_W_##_type(_name)
+
+GI_DEVICE_DESC_SIMPLE_R_u16(bcdUSB);
+GI_DEVICE_DESC_SIMPLE_RW(bDeviceClass, u8);
+GI_DEVICE_DESC_SIMPLE_RW(bDeviceSubClass, u8);
+GI_DEVICE_DESC_SIMPLE_RW(bDeviceProtocol, u8);
+GI_DEVICE_DESC_SIMPLE_RW(bMaxPacketSize0, u8);
+GI_DEVICE_DESC_SIMPLE_RW(idVendor, u16);
+GI_DEVICE_DESC_SIMPLE_RW(idProduct, u16);
+GI_DEVICE_DESC_SIMPLE_R_u16(bcdDevice);
+
+static ssize_t is_valid_bcd(u16 bcd_val)
+{
+ if ((bcd_val & 0xf) > 9)
+ return -EINVAL;
+ if (((bcd_val >> 4) & 0xf) > 9)
+ return -EINVAL;
+ if (((bcd_val >> 8) & 0xf) > 9)
+ return -EINVAL;
+ if (((bcd_val >> 12) & 0xf) > 9)
+ return -EINVAL;
+ return 0;
+}
+
+static ssize_t gadget_dev_desc_bcdDevice_store(struct gadget_info *gi,
+ const char *page, size_t len)
+{
+ u16 bcdDevice;
+ int ret;
+
+ ret = kstrtou16(page, 0, &bcdDevice);
+ if (ret)
+ return ret;
+ ret = is_valid_bcd(bcdDevice);
+ if (ret)
+ return ret;
+
+ gi->cdev.desc.bcdDevice = cpu_to_le16(bcdDevice);
+ return len;
+}
+
+static ssize_t gadget_dev_desc_bcdUSB_store(struct gadget_info *gi,
+ const char *page, size_t len)
+{
+ u16 bcdUSB;
+ int ret;
+
+ ret = kstrtou16(page, 0, &bcdUSB);
+ if (ret)
+ return ret;
+ ret = is_valid_bcd(bcdUSB);
+ if (ret)
+ return ret;
+
+ gi->cdev.desc.bcdUSB = cpu_to_le16(bcdUSB);
+ return len;
+}
+
+static ssize_t gadget_dev_desc_UDC_show(struct gadget_info *gi, char *page)
+{
+ return sprintf(page, "%s\n", gi->udc_name ?: "");
+}
+
+static int unregister_gadget(struct gadget_info *gi)
+{
+ int ret;
+
+ if (!gi->udc_name)
+ return -ENODEV;
+
+ ret = usb_gadget_unregister_driver(&gi->composite.gadget_driver);
+ if (ret)
+ return ret;
+ kfree(gi->udc_name);
+ gi->udc_name = NULL;
+ return 0;
+}
+
+static ssize_t gadget_dev_desc_UDC_store(struct gadget_info *gi,
+ const char *page, size_t len)
+{
+ char *name;
+ int ret;
+
+ name = kstrdup(page, GFP_KERNEL);
+ if (!name)
+ return -ENOMEM;
+ if (name[len - 1] == '\n')
+ name[len - 1] = '\0';
+
+ mutex_lock(&gi->lock);
+
+ if (!strlen(name)) {
+ ret = unregister_gadget(gi);
+ if (ret)
+ goto err;
+ } else {
+ if (gi->udc_name) {
+ ret = -EBUSY;
+ goto err;
+ }
+ ret = udc_attach_driver(name, &gi->composite.gadget_driver);
+ if (ret)
+ goto err;
+ gi->udc_name = name;
+ }
+ mutex_unlock(&gi->lock);
+ return len;
+err:
+ kfree(name);
+ mutex_unlock(&gi->lock);
+ return ret;
+}
+
+GI_DEVICE_DESC_ITEM_ATTR(bDeviceClass);
+GI_DEVICE_DESC_ITEM_ATTR(bDeviceSubClass);
+GI_DEVICE_DESC_ITEM_ATTR(bDeviceProtocol);
+GI_DEVICE_DESC_ITEM_ATTR(bMaxPacketSize0);
+GI_DEVICE_DESC_ITEM_ATTR(idVendor);
+GI_DEVICE_DESC_ITEM_ATTR(idProduct);
+GI_DEVICE_DESC_ITEM_ATTR(bcdDevice);
+GI_DEVICE_DESC_ITEM_ATTR(bcdUSB);
+GI_DEVICE_DESC_ITEM_ATTR(UDC);
+
+static struct configfs_attribute *gadget_root_attrs[] = {
+ &gadget_cdev_desc_bDeviceClass.attr,
+ &gadget_cdev_desc_bDeviceSubClass.attr,
+ &gadget_cdev_desc_bDeviceProtocol.attr,
+ &gadget_cdev_desc_bMaxPacketSize0.attr,
+ &gadget_cdev_desc_idVendor.attr,
+ &gadget_cdev_desc_idProduct.attr,
+ &gadget_cdev_desc_bcdDevice.attr,
+ &gadget_cdev_desc_bcdUSB.attr,
+ &gadget_cdev_desc_UDC.attr,
+ NULL,
+};
+
+static inline struct gadget_info *to_gadget_info(struct config_item *item)
+{
+ return container_of(to_config_group(item), struct gadget_info, group);
+}
+
+static inline struct gadget_strings *to_gadget_strings(struct config_item *item)
+{
+ return container_of(to_config_group(item), struct gadget_strings,
+ group);
+}
+
+static inline struct gadget_config_name *to_gadget_config_name(
+ struct config_item *item)
+{
+ return container_of(to_config_group(item), struct gadget_config_name,
+ group);
+}
+
+static inline struct config_usb_cfg *to_config_usb_cfg(struct config_item *item)
+{
+ return container_of(to_config_group(item), struct config_usb_cfg,
+ group);
+}
+
+static inline struct usb_function_instance *to_usb_function_instance(
+ struct config_item *item)
+{
+ return container_of(to_config_group(item),
+ struct usb_function_instance, group);
+}
+
+static void gadget_info_attr_release(struct config_item *item)
+{
+ struct gadget_info *gi = to_gadget_info(item);
+
+ WARN_ON(!list_empty(&gi->cdev.configs));
+ WARN_ON(!list_empty(&gi->string_list));
+ WARN_ON(!list_empty(&gi->available_func));
+ kfree(gi->composite.gadget_driver.function);
+ kfree(gi);
+}
+
+CONFIGFS_ATTR_OPS(gadget_info);
+
+static struct configfs_item_operations gadget_root_item_ops = {
+ .release = gadget_info_attr_release,
+ .show_attribute = gadget_info_attr_show,
+ .store_attribute = gadget_info_attr_store,
+};
+
+static void gadget_config_attr_release(struct config_item *item)
+{
+ struct config_usb_cfg *cfg = to_config_usb_cfg(item);
+
+ WARN_ON(!list_empty(&cfg->c.functions));
+ list_del(&cfg->c.list);
+ kfree(cfg->c.label);
+ kfree(cfg);
+}
+
+static int config_usb_cfg_link(
+ struct config_item *usb_cfg_ci,
+ struct config_item *usb_func_ci)
+{
+ struct config_usb_cfg *cfg = to_config_usb_cfg(usb_cfg_ci);
+ struct usb_composite_dev *cdev = cfg->c.cdev;
+ struct gadget_info *gi = container_of(cdev, struct gadget_info, cdev);
+
+ struct config_group *group = to_config_group(usb_func_ci);
+ struct usb_function_instance *fi = container_of(group,
+ struct usb_function_instance, group);
+ struct usb_function_instance *a_fi;
+ struct usb_function *f;
+ int ret;
+
+ mutex_lock(&gi->lock);
+ /*
+ * Make sure this function is from within our _this_ gadget and not
+ * from another gadget or a random directory.
+ * Also a function instance can only be linked once.
+ */
+ list_for_each_entry(a_fi, &gi->available_func, cfs_list) {
+ if (a_fi == fi)
+ break;
+ }
+ if (a_fi != fi) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ list_for_each_entry(f, &cfg->func_list, list) {
+ if (f->fi == fi) {
+ ret = -EEXIST;
+ goto out;
+ }
+ }
+
+ f = usb_get_function(fi);
+ if (IS_ERR(f)) {
+ ret = PTR_ERR(f);
+ goto out;
+ }
+
+ /* stash the function until we bind it to the gadget */
+ list_add_tail(&f->list, &cfg->func_list);
+ ret = 0;
+out:
+ mutex_unlock(&gi->lock);
+ return ret;
+}
+
+static int config_usb_cfg_unlink(
+ struct config_item *usb_cfg_ci,
+ struct config_item *usb_func_ci)
+{
+ struct config_usb_cfg *cfg = to_config_usb_cfg(usb_cfg_ci);
+ struct usb_composite_dev *cdev = cfg->c.cdev;
+ struct gadget_info *gi = container_of(cdev, struct gadget_info, cdev);
+
+ struct config_group *group = to_config_group(usb_func_ci);
+ struct usb_function_instance *fi = container_of(group,
+ struct usb_function_instance, group);
+ struct usb_function *f;
+
+ /*
+ * ideally I would like to forbid to unlink functions while a gadget is
+ * bound to an UDC. Since this isn't possible at the moment, we simply
+ * force an unbind, the function is available here and then we can
+ * remove the function.
+ */
+ mutex_lock(&gi->lock);
+ if (gi->udc_name)
+ unregister_gadget(gi);
+ WARN_ON(gi->udc_name);
+
+ list_for_each_entry(f, &cfg->func_list, list) {
+ if (f->fi == fi) {
+ list_del(&f->list);
+ usb_put_function(f);
+ mutex_unlock(&gi->lock);
+ return 0;
+ }
+ }
+ mutex_unlock(&gi->lock);
+ WARN(1, "Unable to locate function to unbind\n");
+ return 0;
+}
+
+CONFIGFS_ATTR_OPS(config_usb_cfg);
+
+static struct configfs_item_operations gadget_config_item_ops = {
+ .release = gadget_config_attr_release,
+ .show_attribute = config_usb_cfg_attr_show,
+ .store_attribute = config_usb_cfg_attr_store,
+ .allow_link = config_usb_cfg_link,
+ .drop_link = config_usb_cfg_unlink,
+};
+
+
+static ssize_t gadget_config_desc_MaxPower_show(struct config_usb_cfg *cfg,
+ char *page)
+{
+ return sprintf(page, "%u\n", cfg->c.MaxPower);
+}
+
+static ssize_t gadget_config_desc_MaxPower_store(struct config_usb_cfg *cfg,
+ const char *page, size_t len)
+{
+ u16 val;
+ int ret;
+ ret = kstrtou16(page, 0, &val);
+ if (ret)
+ return ret;
+ if (DIV_ROUND_UP(val, 8) > 0xff)
+ return -ERANGE;
+ cfg->c.MaxPower = val;
+ return len;
+}
+
+static ssize_t gadget_config_desc_bmAttributes_show(struct config_usb_cfg *cfg,
+ char *page)
+{
+ return sprintf(page, "0x%02x\n", cfg->c.bmAttributes);
+}
+
+static ssize_t gadget_config_desc_bmAttributes_store(struct config_usb_cfg *cfg,
+ const char *page, size_t len)
+{
+ u8 val;
+ int ret;
+ ret = kstrtou8(page, 0, &val);
+ if (ret)
+ return ret;
+ if (!(val & USB_CONFIG_ATT_ONE))
+ return -EINVAL;
+ if (val & ~(USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER |
+ USB_CONFIG_ATT_WAKEUP))
+ return -EINVAL;
+ cfg->c.bmAttributes = val;
+ return len;
+}
+
+#define CFG_CONFIG_DESC_ITEM_ATTR(name) \
+ static struct config_usb_cfg_attribute gadget_usb_cfg_##name = \
+ __CONFIGFS_ATTR(name, S_IRUGO | S_IWUSR, \
+ gadget_config_desc_##name##_show, \
+ gadget_config_desc_##name##_store)
+
+CFG_CONFIG_DESC_ITEM_ATTR(MaxPower);
+CFG_CONFIG_DESC_ITEM_ATTR(bmAttributes);
+
+static struct configfs_attribute *gadget_config_attrs[] = {
+ &gadget_usb_cfg_MaxPower.attr,
+ &gadget_usb_cfg_bmAttributes.attr,
+ NULL,
+};
+
+static struct config_item_type gadget_config_type = {
+ .ct_item_ops = &gadget_config_item_ops,
+ .ct_attrs = gadget_config_attrs,
+ .ct_owner = THIS_MODULE,
+};
+
+static struct config_item_type gadget_root_type = {
+ .ct_item_ops = &gadget_root_item_ops,
+ .ct_attrs = gadget_root_attrs,
+ .ct_owner = THIS_MODULE,
+};
+
+static void composite_init_dev(struct usb_composite_dev *cdev)
+{
+ spin_lock_init(&cdev->lock);
+ INIT_LIST_HEAD(&cdev->configs);
+ INIT_LIST_HEAD(&cdev->gstrings);
+}
+
+static struct config_group *function_make(
+ struct config_group *group,
+ const char *name)
+{
+ struct gadget_info *gi;
+ struct usb_function_instance *fi;
+ char buf[MAX_NAME_LEN];
+ char *func_name;
+ char *instance_name;
+ int ret;
+
+ ret = snprintf(buf, MAX_NAME_LEN, "%s", name);
+ if (ret >= MAX_NAME_LEN)
+ return ERR_PTR(-ENAMETOOLONG);
+
+ func_name = buf;
+ instance_name = strchr(func_name, '.');
+ if (!instance_name) {
+ pr_err("Unable to locate . in FUNC.INSTANCE\n");
+ return ERR_PTR(-EINVAL);
+ }
+ *instance_name = '\0';
+ instance_name++;
+
+ fi = usb_get_function_instance(func_name);
+ if (IS_ERR(fi))
+ return ERR_PTR(PTR_ERR(fi));
+
+ ret = config_item_set_name(&fi->group.cg_item, name);
+ if (ret) {
+ usb_put_function_instance(fi);
+ return ERR_PTR(ret);
+ }
+
+ gi = container_of(group, struct gadget_info, functions_group);
+
+ mutex_lock(&gi->lock);
+ list_add_tail(&fi->cfs_list, &gi->available_func);
+ mutex_unlock(&gi->lock);
+ return &fi->group;
+}
+
+static void function_drop(
+ struct config_group *group,
+ struct config_item *item)
+{
+ struct usb_function_instance *fi = to_usb_function_instance(item);
+ struct gadget_info *gi;
+
+ gi = container_of(group, struct gadget_info, functions_group);
+
+ mutex_lock(&gi->lock);
+ list_del(&fi->cfs_list);
+ mutex_unlock(&gi->lock);
+ config_item_put(item);
+}
+
+static struct configfs_group_operations functions_ops = {
+ .make_group = &function_make,
+ .drop_item = &function_drop,
+};
+
+static struct config_item_type functions_type = {
+ .ct_group_ops = &functions_ops,
+ .ct_owner = THIS_MODULE,
+};
+
+CONFIGFS_ATTR_STRUCT(gadget_config_name);
+GS_STRINGS_RW(gadget_config_name, configuration);
+
+static struct configfs_attribute *gadget_config_name_langid_attrs[] = {
+ &gadget_config_name_configuration.attr,
+ NULL,
+};
+
+static void gadget_config_name_attr_release(struct config_item *item)
+{
+ struct gadget_config_name *cn = to_gadget_config_name(item);
+
+ kfree(cn->configuration);
+
+ list_del(&cn->list);
+ kfree(cn);
+}
+
+USB_CONFIG_STRING_RW_OPS(gadget_config_name);
+USB_CONFIG_STRINGS_LANG(gadget_config_name, config_usb_cfg);
+
+static struct config_group *config_desc_make(
+ struct config_group *group,
+ const char *name)
+{
+ struct gadget_info *gi;
+ struct config_usb_cfg *cfg;
+ char buf[MAX_NAME_LEN];
+ char *num_str;
+ u8 num;
+ int ret;
+
+ gi = container_of(group, struct gadget_info, configs_group);
+ ret = snprintf(buf, MAX_NAME_LEN, "%s", name);
+ if (ret >= MAX_NAME_LEN)
+ return ERR_PTR(-ENAMETOOLONG);
+
+ num_str = strchr(buf, '.');
+ if (!num_str) {
+ pr_err("Unable to locate . in name.bConfigurationValue\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ *num_str = '\0';
+ num_str++;
+
+ if (!strlen(buf))
+ return ERR_PTR(-EINVAL);
+
+ ret = kstrtou8(num_str, 0, &num);
+ if (ret)
+ return ERR_PTR(ret);
+
+ cfg = kzalloc(sizeof(*cfg), GFP_KERNEL);
+ if (!cfg)
+ return ERR_PTR(-ENOMEM);
+ cfg->c.label = kstrdup(buf, GFP_KERNEL);
+ if (!cfg->c.label) {
+ ret = -ENOMEM;
+ goto err;
+ }
+ cfg->c.bConfigurationValue = num;
+ cfg->c.MaxPower = CONFIG_USB_GADGET_VBUS_DRAW;
+ cfg->c.bmAttributes = USB_CONFIG_ATT_ONE;
+ INIT_LIST_HEAD(&cfg->string_list);
+ INIT_LIST_HEAD(&cfg->func_list);
+
+ cfg->group.default_groups = cfg->default_groups;
+ cfg->default_groups[0] = &cfg->strings_group;
+
+ config_group_init_type_name(&cfg->group, name,
+ &gadget_config_type);
+ config_group_init_type_name(&cfg->strings_group, "strings",
+ &gadget_config_name_strings_type);
+
+ ret = usb_add_config_only(&gi->cdev, &cfg->c);
+ if (ret)
+ goto err;
+
+ return &cfg->group;
+err:
+ kfree(cfg->c.label);
+ kfree(cfg);
+ return ERR_PTR(ret);
+}
+
+static void config_desc_drop(
+ struct config_group *group,
+ struct config_item *item)
+{
+ config_item_put(item);
+}
+
+static struct configfs_group_operations config_desc_ops = {
+ .make_group = &config_desc_make,
+ .drop_item = &config_desc_drop,
+};
+
+static struct config_item_type config_desc_type = {
+ .ct_group_ops = &config_desc_ops,
+ .ct_owner = THIS_MODULE,
+};
+
+CONFIGFS_ATTR_STRUCT(gadget_strings);
+GS_STRINGS_RW(gadget_strings, manufacturer);
+GS_STRINGS_RW(gadget_strings, product);
+GS_STRINGS_RW(gadget_strings, serialnumber);
+
+static struct configfs_attribute *gadget_strings_langid_attrs[] = {
+ &gadget_strings_manufacturer.attr,
+ &gadget_strings_product.attr,
+ &gadget_strings_serialnumber.attr,
+ NULL,
+};
+
+static void gadget_strings_attr_release(struct config_item *item)
+{
+ struct gadget_strings *gs = to_gadget_strings(item);
+
+ kfree(gs->manufacturer);
+ kfree(gs->product);
+ kfree(gs->serialnumber);
+
+ list_del(&gs->list);
+ kfree(gs);
+}
+
+USB_CONFIG_STRING_RW_OPS(gadget_strings);
+USB_CONFIG_STRINGS_LANG(gadget_strings, gadget_info);
+
+static int configfs_do_nothing(struct usb_composite_dev *cdev)
+{
+ WARN_ON(1);
+ return -EINVAL;
+}
+
+int composite_dev_prepare(struct usb_composite_driver *composite,
+ struct usb_composite_dev *dev);
+
+static void purge_configs_funcs(struct gadget_info *gi)
+{
+ struct usb_configuration *c;
+
+ list_for_each_entry(c, &gi->cdev.configs, list) {
+ struct usb_function *f, *tmp;
+ struct config_usb_cfg *cfg;
+
+ cfg = container_of(c, struct config_usb_cfg, c);
+
+ list_for_each_entry_safe(f, tmp, &c->functions, list) {
+
+ list_move_tail(&f->list, &cfg->func_list);
+ if (f->unbind) {
+ dev_err(&gi->cdev.gadget->dev, "unbind function"
+ " '%s'/%p\n", f->name, f);
+ f->unbind(c, f);
+ }
+ }
+ c->next_interface_id = 0;
+ c->superspeed = 0;
+ c->highspeed = 0;
+ c->fullspeed = 0;
+ }
+}
+
+static int configfs_composite_bind(struct usb_gadget *gadget,
+ struct usb_gadget_driver *gdriver)
+{
+ struct usb_composite_driver *composite = to_cdriver(gdriver);
+ struct gadget_info *gi = container_of(composite,
+ struct gadget_info, composite);
+ struct usb_composite_dev *cdev = &gi->cdev;
+ struct usb_configuration *c;
+ struct usb_string *s;
+ unsigned i;
+ int ret;
+
+ /* the gi->lock is hold by the caller */
+ cdev->gadget = gadget;
+ set_gadget_data(gadget, cdev);
+ ret = composite_dev_prepare(composite, cdev);
+ if (ret)
+ return ret;
+ /* and now the gadget bind */
+ ret = -EINVAL;
+
+ if (list_empty(&gi->cdev.configs)) {
+ pr_err("Need atleast one configuration in %s.\n",
+ gi->composite.name);
+ goto err_comp_cleanup;
+ }
+
+
+ list_for_each_entry(c, &gi->cdev.configs, list) {
+ struct config_usb_cfg *cfg;
+
+ cfg = container_of(c, struct config_usb_cfg, c);
+ if (list_empty(&cfg->func_list)) {
+ pr_err("Config %s/%d of %s needs atleast one function.\n",
+ c->label, c->bConfigurationValue,
+ gi->composite.name);
+ goto err_comp_cleanup;
+ }
+ }
+
+ /* init all strings */
+ if (!list_empty(&gi->string_list)) {
+ struct gadget_strings *gs;
+
+ i = 0;
+ list_for_each_entry(gs, &gi->string_list, list) {
+
+ gi->gstrings[i] = &gs->stringtab_dev;
+ gs->stringtab_dev.strings = gs->strings;
+ gs->strings[USB_GADGET_MANUFACTURER_IDX].s =
+ gs->manufacturer;
+ gs->strings[USB_GADGET_PRODUCT_IDX].s = gs->product;
+ gs->strings[USB_GADGET_SERIAL_IDX].s = gs->serialnumber;
+ i++;
+ }
+ gi->gstrings[i] = NULL;
+ s = usb_gstrings_attach(&gi->cdev, gi->gstrings,
+ USB_GADGET_FIRST_AVAIL_IDX);
+ if (IS_ERR(s))
+ goto err_comp_cleanup;
+
+ gi->cdev.desc.iManufacturer = s[USB_GADGET_MANUFACTURER_IDX].id;
+ gi->cdev.desc.iProduct = s[USB_GADGET_PRODUCT_IDX].id;
+ gi->cdev.desc.iSerialNumber = s[USB_GADGET_SERIAL_IDX].id;
+ }
+
+ /* Go through all configs, attach all functions */
+ list_for_each_entry(c, &gi->cdev.configs, list) {
+ struct config_usb_cfg *cfg;
+ struct usb_function *f;
+ struct usb_function *tmp;
+ struct gadget_config_name *cn;
+
+ cfg = container_of(c, struct config_usb_cfg, c);
+ if (!list_empty(&cfg->string_list)) {
+ i = 0;
+ list_for_each_entry(cn, &cfg->string_list, list) {
+ cfg->gstrings[i] = &cn->stringtab_dev;
+ cn->stringtab_dev.strings = &cn->strings;
+ cn->strings.s = cn->configuration;
+ i++;
+ }
+ cfg->gstrings[i] = NULL;
+ s = usb_gstrings_attach(&gi->cdev, cfg->gstrings, 1);
+ if (IS_ERR(s))
+ goto err_comp_cleanup;
+ c->iConfiguration = s[0].id;
+ }
+
+ list_for_each_entry_safe(f, tmp, &cfg->func_list, list) {
+ list_del(&f->list);
+ ret = usb_add_function(c, f);
+ if (ret)
+ goto err_purge_funcs;
+ }
+ usb_ep_autoconfig_reset(cdev->gadget);
+ }
+ usb_ep_autoconfig_reset(cdev->gadget);
+ return 0;
+
+err_purge_funcs:
+ purge_configs_funcs(gi);
+err_comp_cleanup:
+ composite_dev_cleanup(cdev);
+ return ret;
+}
+
+static void configfs_composite_unbind(struct usb_gadget *gadget)
+{
+ struct usb_composite_dev *cdev;
+ struct gadget_info *gi;
+
+ /* the gi->lock is hold by the caller */
+
+ cdev = get_gadget_data(gadget);
+ gi = container_of(cdev, struct gadget_info, cdev);
+
+ purge_configs_funcs(gi);
+ composite_dev_cleanup(cdev);
+ usb_ep_autoconfig_reset(cdev->gadget);
+ cdev->gadget = NULL;
+ set_gadget_data(gadget, NULL);
+}
+
+static const struct usb_gadget_driver configfs_driver_template = {
+ .bind = configfs_composite_bind,
+ .unbind = configfs_composite_unbind,
+
+ .setup = composite_setup,
+ .disconnect = composite_disconnect,
+
+ .max_speed = USB_SPEED_SUPER,
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "configfs-gadget",
+ },
+};
+
+static struct config_group *gadgets_make(
+ struct config_group *group,
+ const char *name)
+{
+ struct gadget_info *gi;
+
+ gi = kzalloc(sizeof(*gi), GFP_KERNEL);
+ if (!gi)
+ return ERR_PTR(-ENOMEM);
+
+ gi->group.default_groups = gi->default_groups;
+ gi->group.default_groups[0] = &gi->functions_group;
+ gi->group.default_groups[1] = &gi->configs_group;
+ gi->group.default_groups[2] = &gi->strings_group;
+
+ config_group_init_type_name(&gi->functions_group, "functions",
+ &functions_type);
+ config_group_init_type_name(&gi->configs_group, "configs",
+ &config_desc_type);
+ config_group_init_type_name(&gi->strings_group, "strings",
+ &gadget_strings_strings_type);
+
+ gi->composite.bind = configfs_do_nothing;
+ gi->composite.unbind = configfs_do_nothing;
+ gi->composite.suspend = NULL;
+ gi->composite.resume = NULL;
+ gi->composite.max_speed = USB_SPEED_SUPER;
+
+ mutex_init(&gi->lock);
+ INIT_LIST_HEAD(&gi->string_list);
+ INIT_LIST_HEAD(&gi->available_func);
+
+ composite_init_dev(&gi->cdev);
+ gi->cdev.desc.bLength = USB_DT_DEVICE_SIZE;
+ gi->cdev.desc.bDescriptorType = USB_DT_DEVICE;
+ gi->cdev.desc.bcdDevice = cpu_to_le16(get_default_bcdDevice());
+
+ gi->composite.gadget_driver = configfs_driver_template;
+
+ gi->composite.gadget_driver.function = kstrdup(name, GFP_KERNEL);
+ gi->composite.name = gi->composite.gadget_driver.function;
+
+ if (!gi->composite.gadget_driver.function)
+ goto err;
+
+#ifdef CONFIG_USB_OTG
+ gi->otg.bLength = sizeof(struct usb_otg_descriptor);
+ gi->otg.bDescriptorType = USB_DT_OTG;
+ gi->otg.bmAttributes = USB_OTG_SRP | USB_OTG_HNP;
+#endif
+
+ config_group_init_type_name(&gi->group, name,
+ &gadget_root_type);
+ return &gi->group;
+err:
+ kfree(gi);
+ return ERR_PTR(-ENOMEM);
+}
+
+static void gadgets_drop(struct config_group *group, struct config_item *item)
+{
+ config_item_put(item);
+}
+
+static struct configfs_group_operations gadgets_ops = {
+ .make_group = &gadgets_make,
+ .drop_item = &gadgets_drop,
+};
+
+static struct config_item_type gadgets_type = {
+ .ct_group_ops = &gadgets_ops,
+ .ct_owner = THIS_MODULE,
+};
+
+static struct configfs_subsystem gadget_subsys = {
+ .su_group = {
+ .cg_item = {
+ .ci_namebuf = "usb_gadget",
+ .ci_type = &gadgets_type,
+ },
+ },
+ .su_mutex = __MUTEX_INITIALIZER(gadget_subsys.su_mutex),
+};
+
+static int __init gadget_cfs_init(void)
+{
+ int ret;
+
+ config_group_init(&gadget_subsys.su_group);
+
+ ret = configfs_register_subsystem(&gadget_subsys);
+ return ret;
+}
+module_init(gadget_cfs_init);
+
+static void __exit gadget_cfs_exit(void)
+{
+ configfs_unregister_subsystem(&gadget_subsys);
+}
+module_exit(gadget_cfs_exit);
diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
index 8cf0c0f6fa1..a792e322f4f 100644
--- a/drivers/usb/gadget/dummy_hcd.c
+++ b/drivers/usb/gadget/dummy_hcd.c
@@ -912,7 +912,6 @@ static int dummy_udc_start(struct usb_gadget *g,
dum->devstatus = 0;
dum->driver = driver;
- dum->gadget.dev.driver = &driver->driver;
dev_dbg(udc_dev(dum), "binding gadget driver '%s'\n",
driver->driver.name);
return 0;
@@ -927,7 +926,6 @@ static int dummy_udc_stop(struct usb_gadget *g,
dev_dbg(udc_dev(dum), "unregister gadget driver '%s'\n",
driver->driver.name);
- dum->gadget.dev.driver = NULL;
dum->driver = NULL;
return 0;
@@ -937,11 +935,6 @@ static int dummy_udc_stop(struct usb_gadget *g,
/* The gadget structure is stored inside the hcd structure and will be
* released along with it. */
-static void dummy_gadget_release(struct device *dev)
-{
- return;
-}
-
static void init_dummy_udc_hw(struct dummy *dum)
{
int i;
@@ -984,15 +977,7 @@ static int dummy_udc_probe(struct platform_device *pdev)
dum->gadget.ops = &dummy_ops;
dum->gadget.max_speed = USB_SPEED_SUPER;
- dev_set_name(&dum->gadget.dev, "gadget");
dum->gadget.dev.parent = &pdev->dev;
- dum->gadget.dev.release = dummy_gadget_release;
- rc = device_register(&dum->gadget.dev);
- if (rc < 0) {
- put_device(&dum->gadget.dev);
- return rc;
- }
-
init_dummy_udc_hw(dum);
rc = usb_add_gadget_udc(&pdev->dev, &dum->gadget);
@@ -1008,7 +993,6 @@ static int dummy_udc_probe(struct platform_device *pdev)
err_dev:
usb_del_gadget_udc(&dum->gadget);
err_udc:
- device_unregister(&dum->gadget.dev);
return rc;
}
@@ -1019,7 +1003,6 @@ static int dummy_udc_remove(struct platform_device *pdev)
usb_del_gadget_udc(&dum->gadget);
platform_set_drvdata(pdev, NULL);
device_remove_file(&dum->gadget.dev, &dev_attr_function);
- device_unregister(&dum->gadget.dev);
return 0;
}
@@ -1923,7 +1906,7 @@ done:
}
/* usb 3.0 root hub device descriptor */
-struct {
+static struct {
struct usb_bos_descriptor bos;
struct usb_ss_cap_descriptor ss_cap;
} __packed usb3_bos_desc = {
diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c
index 18c3f423706..56c8ecae9bc 100644
--- a/drivers/usb/gadget/ether.c
+++ b/drivers/usb/gadget/ether.c
@@ -207,7 +207,7 @@ static struct usb_gadget_strings *dev_strings[] = {
};
static u8 hostaddr[ETH_ALEN];
-
+static struct eth_dev *the_dev;
/*-------------------------------------------------------------------------*/
/*
@@ -224,7 +224,7 @@ static int __init rndis_do_config(struct usb_configuration *c)
c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
}
- return rndis_bind_config(c, hostaddr);
+ return rndis_bind_config(c, hostaddr, the_dev);
}
static struct usb_configuration rndis_config_driver = {
@@ -257,11 +257,11 @@ static int __init eth_do_config(struct usb_configuration *c)
}
if (use_eem)
- return eem_bind_config(c);
+ return eem_bind_config(c, the_dev);
else if (can_support_ecm(c->cdev->gadget))
- return ecm_bind_config(c, hostaddr);
+ return ecm_bind_config(c, hostaddr, the_dev);
else
- return geth_bind_config(c, hostaddr);
+ return geth_bind_config(c, hostaddr, the_dev);
}
static struct usb_configuration eth_config_driver = {
@@ -279,9 +279,9 @@ static int __init eth_bind(struct usb_composite_dev *cdev)
int status;
/* set up network link layer */
- status = gether_setup(cdev->gadget, hostaddr);
- if (status < 0)
- return status;
+ the_dev = gether_setup(cdev->gadget, hostaddr);
+ if (IS_ERR(the_dev))
+ return PTR_ERR(the_dev);
/* set up main config label and device descriptor */
if (use_eem) {
@@ -338,13 +338,13 @@ static int __init eth_bind(struct usb_composite_dev *cdev)
return 0;
fail:
- gether_cleanup();
+ gether_cleanup(the_dev);
return status;
}
static int __exit eth_unbind(struct usb_composite_dev *cdev)
{
- gether_cleanup();
+ gether_cleanup(the_dev);
return 0;
}
diff --git a/drivers/usb/gadget/f_acm.c b/drivers/usb/gadget/f_acm.c
index 1ae180baa59..4b7e33e5d9c 100644
--- a/drivers/usb/gadget/f_acm.c
+++ b/drivers/usb/gadget/f_acm.c
@@ -715,13 +715,31 @@ fail:
return status;
}
-static struct f_acm *acm_alloc_basic_func(void)
+static void acm_unbind(struct usb_configuration *c, struct usb_function *f)
+{
+ struct f_acm *acm = func_to_acm(f);
+
+ acm_string_defs[0].id = 0;
+ usb_free_all_descriptors(f);
+ if (acm->notify_req)
+ gs_free_req(acm->notify, acm->notify_req);
+}
+
+static void acm_free_func(struct usb_function *f)
+{
+ struct f_acm *acm = func_to_acm(f);
+
+ kfree(acm);
+}
+
+static struct usb_function *acm_alloc_func(struct usb_function_instance *fi)
{
- struct f_acm *acm;
+ struct f_serial_opts *opts;
+ struct f_acm *acm;
acm = kzalloc(sizeof(*acm), GFP_KERNEL);
if (!acm)
- return NULL;
+ return ERR_PTR(-ENOMEM);
spin_lock_init(&acm->lock);
@@ -730,109 +748,100 @@ static struct f_acm *acm_alloc_basic_func(void)
acm->port.send_break = acm_send_break;
acm->port.func.name = "acm";
+ acm->port.func.strings = acm_strings;
/* descriptors are per-instance copies */
acm->port.func.bind = acm_bind;
acm->port.func.set_alt = acm_set_alt;
acm->port.func.setup = acm_setup;
acm->port.func.disable = acm_disable;
- return acm;
+ opts = container_of(fi, struct f_serial_opts, func_inst);
+ acm->port_num = opts->port_num;
+ acm->port.func.unbind = acm_unbind;
+ acm->port.func.free_func = acm_free_func;
+
+ return &acm->port.func;
}
-#ifdef USB_FACM_INCLUDED
-static void
-acm_old_unbind(struct usb_configuration *c, struct usb_function *f)
+static inline struct f_serial_opts *to_f_serial_opts(struct config_item *item)
{
- struct f_acm *acm = func_to_acm(f);
-
- usb_free_all_descriptors(f);
- if (acm->notify_req)
- gs_free_req(acm->notify, acm->notify_req);
- kfree(acm);
+ return container_of(to_config_group(item), struct f_serial_opts,
+ func_inst.group);
}
-/**
- * acm_bind_config - add a CDC ACM function to a configuration
- * @c: the configuration to support the CDC ACM instance
- * @port_num: /dev/ttyGS* port this interface will use
- * Context: single threaded during gadget setup
- *
- * Returns zero on success, else negative errno.
- *
- */
-int acm_bind_config(struct usb_configuration *c, u8 port_num)
+CONFIGFS_ATTR_STRUCT(f_serial_opts);
+static ssize_t f_acm_attr_show(struct config_item *item,
+ struct configfs_attribute *attr,
+ char *page)
{
- struct f_acm *acm;
- int status;
-
- /* allocate and initialize one new instance */
- acm = acm_alloc_basic_func();
- if (!acm)
- return -ENOMEM;
-
- acm->port_num = port_num;
- acm->port.func.unbind = acm_old_unbind;
-
- status = usb_add_function(c, &acm->port.func);
- if (status)
- kfree(acm);
- return status;
+ struct f_serial_opts *opts = to_f_serial_opts(item);
+ struct f_serial_opts_attribute *f_serial_opts_attr =
+ container_of(attr, struct f_serial_opts_attribute, attr);
+ ssize_t ret = 0;
+
+ if (f_serial_opts_attr->show)
+ ret = f_serial_opts_attr->show(opts, page);
+ return ret;
}
-#else
-
-static void acm_unbind(struct usb_configuration *c, struct usb_function *f)
+static void acm_attr_release(struct config_item *item)
{
- struct f_acm *acm = func_to_acm(f);
+ struct f_serial_opts *opts = to_f_serial_opts(item);
- acm_string_defs[0].id = 0;
- usb_free_all_descriptors(f);
- if (acm->notify_req)
- gs_free_req(acm->notify, acm->notify_req);
+ usb_put_function_instance(&opts->func_inst);
}
-static void acm_free_func(struct usb_function *f)
-{
- struct f_acm *acm = func_to_acm(f);
+static struct configfs_item_operations acm_item_ops = {
+ .release = acm_attr_release,
+ .show_attribute = f_acm_attr_show,
+};
- kfree(acm);
+static ssize_t f_acm_port_num_show(struct f_serial_opts *opts, char *page)
+{
+ return sprintf(page, "%u\n", opts->port_num);
}
-static struct usb_function *acm_alloc_func(struct usb_function_instance *fi)
-{
- struct f_serial_opts *opts;
- struct f_acm *acm;
+static struct f_serial_opts_attribute f_acm_port_num =
+ __CONFIGFS_ATTR_RO(port_num, f_acm_port_num_show);
- acm = acm_alloc_basic_func();
- if (!acm)
- return ERR_PTR(-ENOMEM);
- opts = container_of(fi, struct f_serial_opts, func_inst);
- acm->port_num = opts->port_num;
- acm->port.func.unbind = acm_unbind;
- acm->port.func.free_func = acm_free_func;
+static struct configfs_attribute *acm_attrs[] = {
+ &f_acm_port_num.attr,
+ NULL,
+};
- return &acm->port.func;
-}
+static struct config_item_type acm_func_type = {
+ .ct_item_ops = &acm_item_ops,
+ .ct_attrs = acm_attrs,
+ .ct_owner = THIS_MODULE,
+};
static void acm_free_instance(struct usb_function_instance *fi)
{
struct f_serial_opts *opts;
opts = container_of(fi, struct f_serial_opts, func_inst);
+ gserial_free_line(opts->port_num);
kfree(opts);
}
static struct usb_function_instance *acm_alloc_instance(void)
{
struct f_serial_opts *opts;
+ int ret;
opts = kzalloc(sizeof(*opts), GFP_KERNEL);
if (!opts)
return ERR_PTR(-ENOMEM);
opts->func_inst.free_func_inst = acm_free_instance;
+ ret = gserial_alloc_line(&opts->port_num);
+ if (ret) {
+ kfree(opts);
+ return ERR_PTR(ret);
+ }
+ config_group_init_type_name(&opts->func_inst.group, "",
+ &acm_func_type);
return &opts->func_inst;
}
DECLARE_USB_FUNCTION_INIT(acm, acm_alloc_instance, acm_alloc_func);
MODULE_LICENSE("GPL");
-#endif
diff --git a/drivers/usb/gadget/f_ecm.c b/drivers/usb/gadget/f_ecm.c
index 83420a310fb..d893d692907 100644
--- a/drivers/usb/gadget/f_ecm.c
+++ b/drivers/usb/gadget/f_ecm.c
@@ -824,7 +824,8 @@ ecm_unbind(struct usb_configuration *c, struct usb_function *f)
* for calling @gether_cleanup() before module unload.
*/
int
-ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
+ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
+ struct eth_dev *dev)
{
struct f_ecm *ecm;
int status;
@@ -852,6 +853,7 @@ ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
snprintf(ecm->ethaddr, sizeof ecm->ethaddr, "%pm", ethaddr);
ecm_string_defs[1].s = ecm->ethaddr;
+ ecm->port.ioport = dev;
ecm->port.cdc_filter = DEFAULT_FILTER;
ecm->port.func.name = "cdc_ethernet";
diff --git a/drivers/usb/gadget/f_eem.c b/drivers/usb/gadget/f_eem.c
index cf0ebee8556..f4e0bbef602 100644
--- a/drivers/usb/gadget/f_eem.c
+++ b/drivers/usb/gadget/f_eem.c
@@ -528,7 +528,7 @@ error:
* Caller must have called @gether_setup(). Caller is also responsible
* for calling @gether_cleanup() before module unload.
*/
-int __init eem_bind_config(struct usb_configuration *c)
+int __init eem_bind_config(struct usb_configuration *c, struct eth_dev *dev)
{
struct f_eem *eem;
int status;
@@ -549,6 +549,7 @@ int __init eem_bind_config(struct usb_configuration *c)
if (!eem)
return -ENOMEM;
+ eem->port.ioport = dev;
eem->port.cdc_filter = DEFAULT_FILTER;
eem->port.func.name = "cdc_eem";
diff --git a/drivers/usb/gadget/f_fs.c b/drivers/usb/gadget/f_fs.c
index 38388d7844f..c377ff84bf2 100644
--- a/drivers/usb/gadget/f_fs.c
+++ b/drivers/usb/gadget/f_fs.c
@@ -1235,6 +1235,7 @@ static struct file_system_type ffs_fs_type = {
.mount = ffs_fs_mount,
.kill_sb = ffs_fs_kill_sb,
};
+MODULE_ALIAS_FS("functionfs");
/* Driver's main init/cleanup functions *************************************/
diff --git a/drivers/usb/gadget/f_ncm.c b/drivers/usb/gadget/f_ncm.c
index 5e7557e23ec..ee19bc8d004 100644
--- a/drivers/usb/gadget/f_ncm.c
+++ b/drivers/usb/gadget/f_ncm.c
@@ -1287,7 +1287,8 @@ ncm_unbind(struct usb_configuration *c, struct usb_function *f)
* Caller must have called @gether_setup(). Caller is also responsible
* for calling @gether_cleanup() before module unload.
*/
-int __init ncm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
+int __init ncm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
+ struct eth_dev *dev)
{
struct f_ncm *ncm;
int status;
@@ -1321,6 +1322,7 @@ int __init ncm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
spin_lock_init(&ncm->lock);
ncm_reset_values(ncm);
+ ncm->port.ioport = dev;
ncm->port.is_fixed = true;
ncm->port.func.name = "cdc_network";
diff --git a/drivers/usb/gadget/f_obex.c b/drivers/usb/gadget/f_obex.c
index 36a004563b8..8aa2be5329b 100644
--- a/drivers/usb/gadget/f_obex.c
+++ b/drivers/usb/gadget/f_obex.c
@@ -72,7 +72,7 @@ static struct usb_gadget_strings *obex_strings[] = {
/*-------------------------------------------------------------------------*/
-static struct usb_interface_descriptor obex_control_intf __initdata = {
+static struct usb_interface_descriptor obex_control_intf = {
.bLength = sizeof(obex_control_intf),
.bDescriptorType = USB_DT_INTERFACE,
.bInterfaceNumber = 0,
@@ -83,7 +83,7 @@ static struct usb_interface_descriptor obex_control_intf __initdata = {
.bInterfaceSubClass = USB_CDC_SUBCLASS_OBEX,
};
-static struct usb_interface_descriptor obex_data_nop_intf __initdata = {
+static struct usb_interface_descriptor obex_data_nop_intf = {
.bLength = sizeof(obex_data_nop_intf),
.bDescriptorType = USB_DT_INTERFACE,
.bInterfaceNumber = 1,
@@ -93,7 +93,7 @@ static struct usb_interface_descriptor obex_data_nop_intf __initdata = {
.bInterfaceClass = USB_CLASS_CDC_DATA,
};
-static struct usb_interface_descriptor obex_data_intf __initdata = {
+static struct usb_interface_descriptor obex_data_intf = {
.bLength = sizeof(obex_data_intf),
.bDescriptorType = USB_DT_INTERFACE,
.bInterfaceNumber = 2,
@@ -103,14 +103,14 @@ static struct usb_interface_descriptor obex_data_intf __initdata = {
.bInterfaceClass = USB_CLASS_CDC_DATA,
};
-static struct usb_cdc_header_desc obex_cdc_header_desc __initdata = {
+static struct usb_cdc_header_desc obex_cdc_header_desc = {
.bLength = sizeof(obex_cdc_header_desc),
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubType = USB_CDC_HEADER_TYPE,
.bcdCDC = cpu_to_le16(0x0120),
};
-static struct usb_cdc_union_desc obex_cdc_union_desc __initdata = {
+static struct usb_cdc_union_desc obex_cdc_union_desc = {
.bLength = sizeof(obex_cdc_union_desc),
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubType = USB_CDC_UNION_TYPE,
@@ -118,7 +118,7 @@ static struct usb_cdc_union_desc obex_cdc_union_desc __initdata = {
.bSlaveInterface0 = 2,
};
-static struct usb_cdc_obex_desc obex_desc __initdata = {
+static struct usb_cdc_obex_desc obex_desc = {
.bLength = sizeof(obex_desc),
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubType = USB_CDC_OBEX_TYPE,
@@ -127,7 +127,7 @@ static struct usb_cdc_obex_desc obex_desc __initdata = {
/* High-Speed Support */
-static struct usb_endpoint_descriptor obex_hs_ep_out_desc __initdata = {
+static struct usb_endpoint_descriptor obex_hs_ep_out_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
@@ -136,7 +136,7 @@ static struct usb_endpoint_descriptor obex_hs_ep_out_desc __initdata = {
.wMaxPacketSize = cpu_to_le16(512),
};
-static struct usb_endpoint_descriptor obex_hs_ep_in_desc __initdata = {
+static struct usb_endpoint_descriptor obex_hs_ep_in_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
@@ -145,7 +145,7 @@ static struct usb_endpoint_descriptor obex_hs_ep_in_desc __initdata = {
.wMaxPacketSize = cpu_to_le16(512),
};
-static struct usb_descriptor_header *hs_function[] __initdata = {
+static struct usb_descriptor_header *hs_function[] = {
(struct usb_descriptor_header *) &obex_control_intf,
(struct usb_descriptor_header *) &obex_cdc_header_desc,
(struct usb_descriptor_header *) &obex_desc,
@@ -160,7 +160,7 @@ static struct usb_descriptor_header *hs_function[] __initdata = {
/* Full-Speed Support */
-static struct usb_endpoint_descriptor obex_fs_ep_in_desc __initdata = {
+static struct usb_endpoint_descriptor obex_fs_ep_in_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
@@ -168,7 +168,7 @@ static struct usb_endpoint_descriptor obex_fs_ep_in_desc __initdata = {
.bmAttributes = USB_ENDPOINT_XFER_BULK,
};
-static struct usb_endpoint_descriptor obex_fs_ep_out_desc __initdata = {
+static struct usb_endpoint_descriptor obex_fs_ep_out_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
@@ -176,7 +176,7 @@ static struct usb_endpoint_descriptor obex_fs_ep_out_desc __initdata = {
.bmAttributes = USB_ENDPOINT_XFER_BULK,
};
-static struct usb_descriptor_header *fs_function[] __initdata = {
+static struct usb_descriptor_header *fs_function[] = {
(struct usb_descriptor_header *) &obex_control_intf,
(struct usb_descriptor_header *) &obex_cdc_header_desc,
(struct usb_descriptor_header *) &obex_desc,
@@ -290,14 +290,43 @@ static void obex_disconnect(struct gserial *g)
/*-------------------------------------------------------------------------*/
-static int __init
-obex_bind(struct usb_configuration *c, struct usb_function *f)
+/* Some controllers can't support CDC OBEX ... */
+static inline bool can_support_obex(struct usb_configuration *c)
+{
+ /* Since the first interface is a NOP, we can ignore the
+ * issue of multi-interface support on most controllers.
+ *
+ * Altsettings are mandatory, however...
+ */
+ if (!gadget_supports_altsettings(c->cdev->gadget))
+ return false;
+
+ /* everything else is *probably* fine ... */
+ return true;
+}
+
+static int obex_bind(struct usb_configuration *c, struct usb_function *f)
{
struct usb_composite_dev *cdev = c->cdev;
struct f_obex *obex = func_to_obex(f);
int status;
struct usb_ep *ep;
+ if (!can_support_obex(c))
+ return -EINVAL;
+
+ if (obex_string_defs[OBEX_CTRL_IDX].id == 0) {
+ status = usb_string_ids_tab(c->cdev, obex_string_defs);
+ if (status < 0)
+ return status;
+ obex_control_intf.iInterface =
+ obex_string_defs[OBEX_CTRL_IDX].id;
+
+ status = obex_string_defs[OBEX_DATA_IDX].id;
+ obex_data_nop_intf.iInterface = status;
+ obex_data_intf.iInterface = status;
+ }
+
/* allocate instance-specific interface IDs, and patch descriptors */
status = usb_interface_id(c, f);
@@ -319,6 +348,7 @@ obex_bind(struct usb_configuration *c, struct usb_function *f)
/* allocate instance-specific endpoints */
+ status = -ENODEV;
ep = usb_ep_autoconfig(cdev->gadget, &obex_fs_ep_in_desc);
if (!ep)
goto fail;
@@ -376,29 +406,16 @@ fail:
return status;
}
+#ifdef USBF_OBEX_INCLUDED
+
static void
-obex_unbind(struct usb_configuration *c, struct usb_function *f)
+obex_old_unbind(struct usb_configuration *c, struct usb_function *f)
{
obex_string_defs[OBEX_CTRL_IDX].id = 0;
usb_free_all_descriptors(f);
kfree(func_to_obex(f));
}
-/* Some controllers can't support CDC OBEX ... */
-static inline bool can_support_obex(struct usb_configuration *c)
-{
- /* Since the first interface is a NOP, we can ignore the
- * issue of multi-interface support on most controllers.
- *
- * Altsettings are mandatory, however...
- */
- if (!gadget_supports_altsettings(c->cdev->gadget))
- return false;
-
- /* everything else is *probably* fine ... */
- return true;
-}
-
/**
* obex_bind_config - add a CDC OBEX function to a configuration
* @c: the configuration to support the CDC OBEX instance
@@ -412,21 +429,6 @@ int __init obex_bind_config(struct usb_configuration *c, u8 port_num)
struct f_obex *obex;
int status;
- if (!can_support_obex(c))
- return -EINVAL;
-
- if (obex_string_defs[OBEX_CTRL_IDX].id == 0) {
- status = usb_string_ids_tab(c->cdev, obex_string_defs);
- if (status < 0)
- return status;
- obex_control_intf.iInterface =
- obex_string_defs[OBEX_CTRL_IDX].id;
-
- status = obex_string_defs[OBEX_DATA_IDX].id;
- obex_data_nop_intf.iInterface = status;
- obex_data_intf.iInterface = status;
- }
-
/* allocate and initialize one new instance */
obex = kzalloc(sizeof *obex, GFP_KERNEL);
if (!obex)
@@ -441,7 +443,7 @@ int __init obex_bind_config(struct usb_configuration *c, u8 port_num)
obex->port.func.strings = obex_strings;
/* descriptors are per-instance copies */
obex->port.func.bind = obex_bind;
- obex->port.func.unbind = obex_unbind;
+ obex->port.func.unbind = obex_old_unbind;
obex->port.func.set_alt = obex_set_alt;
obex->port.func.get_alt = obex_get_alt;
obex->port.func.disable = obex_disable;
@@ -453,5 +455,138 @@ int __init obex_bind_config(struct usb_configuration *c, u8 port_num)
return status;
}
+#else
+
+static inline struct f_serial_opts *to_f_serial_opts(struct config_item *item)
+{
+ return container_of(to_config_group(item), struct f_serial_opts,
+ func_inst.group);
+}
+
+CONFIGFS_ATTR_STRUCT(f_serial_opts);
+static ssize_t f_obex_attr_show(struct config_item *item,
+ struct configfs_attribute *attr,
+ char *page)
+{
+ struct f_serial_opts *opts = to_f_serial_opts(item);
+ struct f_serial_opts_attribute *f_serial_opts_attr =
+ container_of(attr, struct f_serial_opts_attribute, attr);
+ ssize_t ret = 0;
+
+ if (f_serial_opts_attr->show)
+ ret = f_serial_opts_attr->show(opts, page);
+
+ return ret;
+}
+
+static void obex_attr_release(struct config_item *item)
+{
+ struct f_serial_opts *opts = to_f_serial_opts(item);
+
+ usb_put_function_instance(&opts->func_inst);
+}
+
+static struct configfs_item_operations obex_item_ops = {
+ .release = obex_attr_release,
+ .show_attribute = f_obex_attr_show,
+};
+
+static ssize_t f_obex_port_num_show(struct f_serial_opts *opts, char *page)
+{
+ return sprintf(page, "%u\n", opts->port_num);
+}
+
+static struct f_serial_opts_attribute f_obex_port_num =
+ __CONFIGFS_ATTR_RO(port_num, f_obex_port_num_show);
+
+static struct configfs_attribute *acm_attrs[] = {
+ &f_obex_port_num.attr,
+ NULL,
+};
+
+static struct config_item_type obex_func_type = {
+ .ct_item_ops = &obex_item_ops,
+ .ct_attrs = acm_attrs,
+ .ct_owner = THIS_MODULE,
+};
+
+static void obex_free_inst(struct usb_function_instance *f)
+{
+ struct f_serial_opts *opts;
+
+ opts = container_of(f, struct f_serial_opts, func_inst);
+ gserial_free_line(opts->port_num);
+ kfree(opts);
+}
+
+static struct usb_function_instance *obex_alloc_inst(void)
+{
+ struct f_serial_opts *opts;
+ int ret;
+
+ opts = kzalloc(sizeof(*opts), GFP_KERNEL);
+ if (!opts)
+ return ERR_PTR(-ENOMEM);
+
+ opts->func_inst.free_func_inst = obex_free_inst;
+ ret = gserial_alloc_line(&opts->port_num);
+ if (ret) {
+ kfree(opts);
+ return ERR_PTR(ret);
+ }
+ config_group_init_type_name(&opts->func_inst.group, "",
+ &obex_func_type);
+
+ return &opts->func_inst;
+}
+
+static void obex_free(struct usb_function *f)
+{
+ struct f_obex *obex;
+
+ obex = func_to_obex(f);
+ kfree(obex);
+}
+
+static void obex_unbind(struct usb_configuration *c, struct usb_function *f)
+{
+ obex_string_defs[OBEX_CTRL_IDX].id = 0;
+ usb_free_all_descriptors(f);
+}
+
+struct usb_function *obex_alloc(struct usb_function_instance *fi)
+{
+ struct f_obex *obex;
+ struct f_serial_opts *opts;
+
+ /* allocate and initialize one new instance */
+ obex = kzalloc(sizeof(*obex), GFP_KERNEL);
+ if (!obex)
+ return ERR_PTR(-ENOMEM);
+
+ opts = container_of(fi, struct f_serial_opts, func_inst);
+
+ obex->port_num = opts->port_num;
+
+ obex->port.connect = obex_connect;
+ obex->port.disconnect = obex_disconnect;
+
+ obex->port.func.name = "obex";
+ obex->port.func.strings = obex_strings;
+ /* descriptors are per-instance copies */
+ obex->port.func.bind = obex_bind;
+ obex->port.func.unbind = obex_unbind;
+ obex->port.func.set_alt = obex_set_alt;
+ obex->port.func.get_alt = obex_get_alt;
+ obex->port.func.disable = obex_disable;
+ obex->port.func.free_func = obex_free;
+
+ return &obex->port.func;
+}
+
+DECLARE_USB_FUNCTION_INIT(obex, obex_alloc_inst, obex_alloc);
+
+#endif
+
MODULE_AUTHOR("Felipe Balbi");
MODULE_LICENSE("GPL");
diff --git a/drivers/usb/gadget/f_rndis.c b/drivers/usb/gadget/f_rndis.c
index 71beeb83355..36e8c44d8e5 100644
--- a/drivers/usb/gadget/f_rndis.c
+++ b/drivers/usb/gadget/f_rndis.c
@@ -447,14 +447,13 @@ static void rndis_response_complete(struct usb_ep *ep, struct usb_request *req)
static void rndis_command_complete(struct usb_ep *ep, struct usb_request *req)
{
struct f_rndis *rndis = req->context;
- struct usb_composite_dev *cdev = rndis->port.func.config->cdev;
int status;
/* received RNDIS command from USB_CDC_SEND_ENCAPSULATED_COMMAND */
// spin_lock(&dev->lock);
status = rndis_msg_parser(rndis->config, (u8 *) req->buf);
if (status < 0)
- ERROR(cdev, "RNDIS command error %d, %d/%d\n",
+ pr_err("RNDIS command error %d, %d/%d\n",
status, req->actual, req->length);
// spin_unlock(&dev->lock);
}
@@ -814,7 +813,7 @@ static inline bool can_support_rndis(struct usb_configuration *c)
int
rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
- u32 vendorID, const char *manufacturer)
+ u32 vendorID, const char *manufacturer, struct eth_dev *dev)
{
struct f_rndis *rndis;
int status;
@@ -847,6 +846,7 @@ rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
rndis->vendorID = vendorID;
rndis->manufacturer = manufacturer;
+ rndis->port.ioport = dev;
/* RNDIS activates when the host changes this filter */
rndis->port.cdc_filter = 0;
diff --git a/drivers/usb/gadget/f_serial.c b/drivers/usb/gadget/f_serial.c
index da33cfb3031..981113c9924 100644
--- a/drivers/usb/gadget/f_serial.c
+++ b/drivers/usb/gadget/f_serial.c
@@ -12,6 +12,7 @@
#include <linux/slab.h>
#include <linux/kernel.h>
+#include <linux/module.h>
#include <linux/device.h>
#include "u_serial.h"
@@ -42,7 +43,7 @@ static inline struct f_gser *func_to_gser(struct usb_function *f)
/* interface descriptor: */
-static struct usb_interface_descriptor gser_interface_desc __initdata = {
+static struct usb_interface_descriptor gser_interface_desc = {
.bLength = USB_DT_INTERFACE_SIZE,
.bDescriptorType = USB_DT_INTERFACE,
/* .bInterfaceNumber = DYNAMIC */
@@ -55,21 +56,21 @@ static struct usb_interface_descriptor gser_interface_desc __initdata = {
/* full speed support: */
-static struct usb_endpoint_descriptor gser_fs_in_desc __initdata = {
+static struct usb_endpoint_descriptor gser_fs_in_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = USB_DIR_IN,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
};
-static struct usb_endpoint_descriptor gser_fs_out_desc __initdata = {
+static struct usb_endpoint_descriptor gser_fs_out_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = USB_DIR_OUT,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
};
-static struct usb_descriptor_header *gser_fs_function[] __initdata = {
+static struct usb_descriptor_header *gser_fs_function[] = {
(struct usb_descriptor_header *) &gser_interface_desc,
(struct usb_descriptor_header *) &gser_fs_in_desc,
(struct usb_descriptor_header *) &gser_fs_out_desc,
@@ -78,47 +79,47 @@ static struct usb_descriptor_header *gser_fs_function[] __initdata = {
/* high speed support: */
-static struct usb_endpoint_descriptor gser_hs_in_desc __initdata = {
+static struct usb_endpoint_descriptor gser_hs_in_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = cpu_to_le16(512),
};
-static struct usb_endpoint_descriptor gser_hs_out_desc __initdata = {
+static struct usb_endpoint_descriptor gser_hs_out_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = cpu_to_le16(512),
};
-static struct usb_descriptor_header *gser_hs_function[] __initdata = {
+static struct usb_descriptor_header *gser_hs_function[] = {
(struct usb_descriptor_header *) &gser_interface_desc,
(struct usb_descriptor_header *) &gser_hs_in_desc,
(struct usb_descriptor_header *) &gser_hs_out_desc,
NULL,
};
-static struct usb_endpoint_descriptor gser_ss_in_desc __initdata = {
+static struct usb_endpoint_descriptor gser_ss_in_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = cpu_to_le16(1024),
};
-static struct usb_endpoint_descriptor gser_ss_out_desc __initdata = {
+static struct usb_endpoint_descriptor gser_ss_out_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = cpu_to_le16(1024),
};
-static struct usb_ss_ep_comp_descriptor gser_ss_bulk_comp_desc __initdata = {
+static struct usb_ss_ep_comp_descriptor gser_ss_bulk_comp_desc = {
.bLength = sizeof gser_ss_bulk_comp_desc,
.bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
};
-static struct usb_descriptor_header *gser_ss_function[] __initdata = {
+static struct usb_descriptor_header *gser_ss_function[] = {
(struct usb_descriptor_header *) &gser_interface_desc,
(struct usb_descriptor_header *) &gser_ss_in_desc,
(struct usb_descriptor_header *) &gser_ss_bulk_comp_desc,
@@ -183,14 +184,25 @@ static void gser_disable(struct usb_function *f)
/* serial function driver setup/binding */
-static int __init
-gser_bind(struct usb_configuration *c, struct usb_function *f)
+static int gser_bind(struct usb_configuration *c, struct usb_function *f)
{
struct usb_composite_dev *cdev = c->cdev;
struct f_gser *gser = func_to_gser(f);
int status;
struct usb_ep *ep;
+ /* REVISIT might want instance-specific strings to help
+ * distinguish instances ...
+ */
+
+ /* maybe allocate device-global string ID */
+ if (gser_string_defs[0].id == 0) {
+ status = usb_string_id(c->cdev);
+ if (status < 0)
+ return status;
+ gser_string_defs[0].id = status;
+ }
+
/* allocate instance-specific interface IDs */
status = usb_interface_id(c, f);
if (status < 0)
@@ -246,44 +258,115 @@ fail:
return status;
}
-static void
-gser_unbind(struct usb_configuration *c, struct usb_function *f)
+static inline struct f_serial_opts *to_f_serial_opts(struct config_item *item)
{
- usb_free_all_descriptors(f);
- kfree(func_to_gser(f));
+ return container_of(to_config_group(item), struct f_serial_opts,
+ func_inst.group);
}
-/**
- * gser_bind_config - add a generic serial function to a configuration
- * @c: the configuration to support the serial instance
- * @port_num: /dev/ttyGS* port this interface will use
- * Context: single threaded during gadget setup
- *
- * Returns zero on success, else negative errno.
- */
-int __init gser_bind_config(struct usb_configuration *c, u8 port_num)
+CONFIGFS_ATTR_STRUCT(f_serial_opts);
+static ssize_t f_serial_attr_show(struct config_item *item,
+ struct configfs_attribute *attr,
+ char *page)
{
- struct f_gser *gser;
- int status;
+ struct f_serial_opts *opts = to_f_serial_opts(item);
+ struct f_serial_opts_attribute *f_serial_opts_attr =
+ container_of(attr, struct f_serial_opts_attribute, attr);
+ ssize_t ret = 0;
- /* REVISIT might want instance-specific strings to help
- * distinguish instances ...
- */
+ if (f_serial_opts_attr->show)
+ ret = f_serial_opts_attr->show(opts, page);
- /* maybe allocate device-global string ID */
- if (gser_string_defs[0].id == 0) {
- status = usb_string_id(c->cdev);
- if (status < 0)
- return status;
- gser_string_defs[0].id = status;
+ return ret;
+}
+
+static void serial_attr_release(struct config_item *item)
+{
+ struct f_serial_opts *opts = to_f_serial_opts(item);
+
+ usb_put_function_instance(&opts->func_inst);
+}
+
+static struct configfs_item_operations serial_item_ops = {
+ .release = serial_attr_release,
+ .show_attribute = f_serial_attr_show,
+};
+
+static ssize_t f_serial_port_num_show(struct f_serial_opts *opts, char *page)
+{
+ return sprintf(page, "%u\n", opts->port_num);
+}
+
+static struct f_serial_opts_attribute f_serial_port_num =
+ __CONFIGFS_ATTR_RO(port_num, f_serial_port_num_show);
+
+static struct configfs_attribute *acm_attrs[] = {
+ &f_serial_port_num.attr,
+ NULL,
+};
+
+static struct config_item_type serial_func_type = {
+ .ct_item_ops = &serial_item_ops,
+ .ct_attrs = acm_attrs,
+ .ct_owner = THIS_MODULE,
+};
+
+static void gser_free_inst(struct usb_function_instance *f)
+{
+ struct f_serial_opts *opts;
+
+ opts = container_of(f, struct f_serial_opts, func_inst);
+ gserial_free_line(opts->port_num);
+ kfree(opts);
+}
+
+static struct usb_function_instance *gser_alloc_inst(void)
+{
+ struct f_serial_opts *opts;
+ int ret;
+
+ opts = kzalloc(sizeof(*opts), GFP_KERNEL);
+ if (!opts)
+ return ERR_PTR(-ENOMEM);
+
+ opts->func_inst.free_func_inst = gser_free_inst;
+ ret = gserial_alloc_line(&opts->port_num);
+ if (ret) {
+ kfree(opts);
+ return ERR_PTR(ret);
}
+ config_group_init_type_name(&opts->func_inst.group, "",
+ &serial_func_type);
+
+ return &opts->func_inst;
+}
+
+static void gser_free(struct usb_function *f)
+{
+ struct f_gser *serial;
+
+ serial = func_to_gser(f);
+ kfree(serial);
+}
+
+static void gser_unbind(struct usb_configuration *c, struct usb_function *f)
+{
+ usb_free_all_descriptors(f);
+}
+
+struct usb_function *gser_alloc(struct usb_function_instance *fi)
+{
+ struct f_gser *gser;
+ struct f_serial_opts *opts;
/* allocate and initialize one new instance */
- gser = kzalloc(sizeof *gser, GFP_KERNEL);
+ gser = kzalloc(sizeof(*gser), GFP_KERNEL);
if (!gser)
- return -ENOMEM;
+ return ERR_PTR(-ENOMEM);
- gser->port_num = port_num;
+ opts = container_of(fi, struct f_serial_opts, func_inst);
+
+ gser->port_num = opts->port_num;
gser->port.func.name = "gser";
gser->port.func.strings = gser_strings;
@@ -291,9 +374,12 @@ int __init gser_bind_config(struct usb_configuration *c, u8 port_num)
gser->port.func.unbind = gser_unbind;
gser->port.func.set_alt = gser_set_alt;
gser->port.func.disable = gser_disable;
+ gser->port.func.free_func = gser_free;
- status = usb_add_function(c, &gser->port.func);
- if (status)
- kfree(gser);
- return status;
+ return &gser->port.func;
}
+
+DECLARE_USB_FUNCTION_INIT(gser, gser_alloc_inst, gser_alloc);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Al Borchers");
+MODULE_AUTHOR("David Brownell");
diff --git a/drivers/usb/gadget/f_sourcesink.c b/drivers/usb/gadget/f_sourcesink.c
index 41adf3ef96c..a8895859a22 100644
--- a/drivers/usb/gadget/f_sourcesink.c
+++ b/drivers/usb/gadget/f_sourcesink.c
@@ -898,7 +898,7 @@ static struct usb_function *source_sink_alloc_func(
return &ss->function;
}
-static void acm_free_instance(struct usb_function_instance *fi)
+static void source_sink_free_instance(struct usb_function_instance *fi)
{
struct f_ss_opts *ss_opts;
@@ -913,7 +913,7 @@ static struct usb_function_instance *source_sink_alloc_inst(void)
ss_opts = kzalloc(sizeof(*ss_opts), GFP_KERNEL);
if (!ss_opts)
return ERR_PTR(-ENOMEM);
- ss_opts->func_inst.free_func_inst = acm_free_instance;
+ ss_opts->func_inst.free_func_inst = source_sink_free_instance;
return &ss_opts->func_inst;
}
DECLARE_USB_FUNCTION(SourceSink, source_sink_alloc_inst,
diff --git a/drivers/usb/gadget/f_subset.c b/drivers/usb/gadget/f_subset.c
index f172bd152fb..185d6f5e4e4 100644
--- a/drivers/usb/gadget/f_subset.c
+++ b/drivers/usb/gadget/f_subset.c
@@ -380,7 +380,8 @@ geth_unbind(struct usb_configuration *c, struct usb_function *f)
* Caller must have called @gether_setup(). Caller is also responsible
* for calling @gether_cleanup() before module unload.
*/
-int geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
+int geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
+ struct eth_dev *dev)
{
struct f_gether *geth;
int status;
@@ -406,6 +407,7 @@ int geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
snprintf(geth->ethaddr, sizeof geth->ethaddr, "%pm", ethaddr);
geth_string_defs[1].s = geth->ethaddr;
+ geth->port.ioport = dev;
geth->port.cdc_filter = DEFAULT_FILTER;
geth->port.func.name = "cdc_subset";
diff --git a/drivers/usb/gadget/f_uac1.c b/drivers/usb/gadget/f_uac1.c
index f570e667a64..fa8ea4ea00c 100644
--- a/drivers/usb/gadget/f_uac1.c
+++ b/drivers/usb/gadget/f_uac1.c
@@ -418,6 +418,7 @@ static int audio_get_intf_req(struct usb_function *f,
req->context = audio;
req->complete = f_audio_complete;
+ len = min_t(size_t, sizeof(value), len);
memcpy(req->buf, &value, len);
return len;
diff --git a/drivers/usb/gadget/f_uvc.c b/drivers/usb/gadget/f_uvc.c
index 92efd6ec48a..38dcedddc52 100644
--- a/drivers/usb/gadget/f_uvc.c
+++ b/drivers/usb/gadget/f_uvc.c
@@ -33,19 +33,15 @@ unsigned int uvc_gadget_trace_param;
/*-------------------------------------------------------------------------*/
/* module parameters specific to the Video streaming endpoint */
-static unsigned streaming_interval = 1;
+static unsigned int streaming_interval = 1;
module_param(streaming_interval, uint, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(streaming_interval, "1 - 16");
-static unsigned streaming_maxpacket = 1024;
+static unsigned int streaming_maxpacket = 1024;
module_param(streaming_maxpacket, uint, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(streaming_maxpacket, "0 - 1023 (fs), 0 - 1024 (hs/ss)");
+MODULE_PARM_DESC(streaming_maxpacket, "1 - 1023 (FS), 1 - 3072 (hs/ss)");
-static unsigned streaming_mult;
-module_param(streaming_mult, uint, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(streaming_mult, "0 - 2 (hs/ss only)");
-
-static unsigned streaming_maxburst;
+static unsigned int streaming_maxburst;
module_param(streaming_maxburst, uint, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(streaming_maxburst, "0 - 15 (ss only)");
@@ -55,13 +51,11 @@ MODULE_PARM_DESC(streaming_maxburst, "0 - 15 (ss only)");
/* string IDs are assigned dynamically */
-#define UVC_STRING_ASSOCIATION_IDX 0
-#define UVC_STRING_CONTROL_IDX 1
-#define UVC_STRING_STREAMING_IDX 2
+#define UVC_STRING_CONTROL_IDX 0
+#define UVC_STRING_STREAMING_IDX 1
static struct usb_string uvc_en_us_strings[] = {
- [UVC_STRING_ASSOCIATION_IDX].s = "UVC Camera",
- [UVC_STRING_CONTROL_IDX].s = "Video Control",
+ [UVC_STRING_CONTROL_IDX].s = "UVC Camera",
[UVC_STRING_STREAMING_IDX].s = "Video Streaming",
{ }
};
@@ -79,7 +73,7 @@ static struct usb_gadget_strings *uvc_function_strings[] = {
#define UVC_INTF_VIDEO_CONTROL 0
#define UVC_INTF_VIDEO_STREAMING 1
-#define STATUS_BYTECOUNT 16 /* 16 bytes status */
+#define UVC_STATUS_MAX_PACKET_SIZE 16 /* 16 bytes status */
static struct usb_interface_assoc_descriptor uvc_iad __initdata = {
.bLength = sizeof(uvc_iad),
@@ -104,20 +98,29 @@ static struct usb_interface_descriptor uvc_control_intf __initdata = {
.iInterface = 0,
};
-static struct usb_endpoint_descriptor uvc_fs_control_ep __initdata = {
+static struct usb_endpoint_descriptor uvc_control_ep __initdata = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = USB_DIR_IN,
.bmAttributes = USB_ENDPOINT_XFER_INT,
- .wMaxPacketSize = cpu_to_le16(STATUS_BYTECOUNT),
+ .wMaxPacketSize = cpu_to_le16(UVC_STATUS_MAX_PACKET_SIZE),
.bInterval = 8,
};
+static struct usb_ss_ep_comp_descriptor uvc_ss_control_comp __initdata = {
+ .bLength = sizeof(uvc_ss_control_comp),
+ .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
+ /* The following 3 values can be tweaked if necessary. */
+ .bMaxBurst = 0,
+ .bmAttributes = 0,
+ .wBytesPerInterval = cpu_to_le16(UVC_STATUS_MAX_PACKET_SIZE),
+};
+
static struct uvc_control_endpoint_descriptor uvc_control_cs_ep __initdata = {
.bLength = UVC_DT_CONTROL_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_CS_ENDPOINT,
.bDescriptorSubType = UVC_EP_INTERRUPT,
- .wMaxTransferSize = cpu_to_le16(STATUS_BYTECOUNT),
+ .wMaxTransferSize = cpu_to_le16(UVC_STATUS_MAX_PACKET_SIZE),
};
static struct usb_interface_descriptor uvc_streaming_intf_alt0 __initdata = {
@@ -144,63 +147,53 @@ static struct usb_interface_descriptor uvc_streaming_intf_alt1 __initdata = {
.iInterface = 0,
};
-static struct usb_endpoint_descriptor uvc_fs_streaming_ep = {
+static struct usb_endpoint_descriptor uvc_fs_streaming_ep __initdata = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = USB_DIR_IN,
- .bmAttributes = USB_ENDPOINT_XFER_ISOC,
- .wMaxPacketSize = cpu_to_le16(512),
- .bInterval = 1,
+ .bmAttributes = USB_ENDPOINT_SYNC_ASYNC
+ | USB_ENDPOINT_XFER_ISOC,
+ /* The wMaxPacketSize and bInterval values will be initialized from
+ * module parameters.
+ */
+ .wMaxPacketSize = 0,
+ .bInterval = 0,
};
-static struct usb_endpoint_descriptor uvc_hs_streaming_ep = {
+static struct usb_endpoint_descriptor uvc_hs_streaming_ep __initdata = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = USB_DIR_IN,
- .bmAttributes = USB_ENDPOINT_XFER_ISOC,
- .wMaxPacketSize = cpu_to_le16(1024),
- .bInterval = 1,
-};
-
-/* super speed support */
-static struct usb_endpoint_descriptor uvc_ss_control_ep __initdata = {
- .bLength = USB_DT_ENDPOINT_SIZE,
- .bDescriptorType = USB_DT_ENDPOINT,
-
- .bEndpointAddress = USB_DIR_IN,
- .bmAttributes = USB_ENDPOINT_XFER_INT,
- .wMaxPacketSize = cpu_to_le16(STATUS_BYTECOUNT),
- .bInterval = 8,
-};
-
-static struct usb_ss_ep_comp_descriptor uvc_ss_control_comp __initdata = {
- .bLength = sizeof uvc_ss_control_comp,
- .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
-
- /* the following 3 values can be tweaked if necessary */
- /* .bMaxBurst = 0, */
- /* .bmAttributes = 0, */
- .wBytesPerInterval = cpu_to_le16(STATUS_BYTECOUNT),
+ .bmAttributes = USB_ENDPOINT_SYNC_ASYNC
+ | USB_ENDPOINT_XFER_ISOC,
+ /* The wMaxPacketSize and bInterval values will be initialized from
+ * module parameters.
+ */
+ .wMaxPacketSize = 0,
+ .bInterval = 0,
};
static struct usb_endpoint_descriptor uvc_ss_streaming_ep __initdata = {
- .bLength = USB_DT_ENDPOINT_SIZE,
- .bDescriptorType = USB_DT_ENDPOINT,
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
- .bEndpointAddress = USB_DIR_IN,
- .bmAttributes = USB_ENDPOINT_XFER_ISOC,
- .wMaxPacketSize = cpu_to_le16(1024),
- .bInterval = 4,
+ .bEndpointAddress = USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_SYNC_ASYNC
+ | USB_ENDPOINT_XFER_ISOC,
+ /* The wMaxPacketSize and bInterval values will be initialized from
+ * module parameters.
+ */
+ .wMaxPacketSize = 0,
+ .bInterval = 0,
};
-static struct usb_ss_ep_comp_descriptor uvc_ss_streaming_comp = {
- .bLength = sizeof uvc_ss_streaming_comp,
- .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
-
- /* the following 3 values can be tweaked if necessary */
- .bMaxBurst = 0,
- .bmAttributes = 0,
- .wBytesPerInterval = cpu_to_le16(1024),
+static struct usb_ss_ep_comp_descriptor uvc_ss_streaming_comp __initdata = {
+ .bLength = sizeof(uvc_ss_streaming_comp),
+ .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
+ /* The following 3 values can be tweaked if necessary. */
+ .bMaxBurst = 0,
+ .bmAttributes = 0,
+ .wBytesPerInterval = cpu_to_le16(1024),
};
static const struct usb_descriptor_header * const uvc_fs_streaming[] = {
@@ -273,6 +266,13 @@ uvc_function_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
return 0;
}
+void uvc_function_setup_continue(struct uvc_device *uvc)
+{
+ struct usb_composite_dev *cdev = uvc->func.config->cdev;
+
+ usb_composite_setup_continue(cdev);
+}
+
static int
uvc_function_get_alt(struct usb_function *f, unsigned interface)
{
@@ -335,7 +335,7 @@ uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt)
v4l2_event_queue(uvc->vdev, &v4l2_event);
uvc->state = UVC_STATE_CONNECTED;
- break;
+ return 0;
case 1:
if (uvc->state != UVC_STATE_CONNECTED)
@@ -352,15 +352,11 @@ uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt)
memset(&v4l2_event, 0, sizeof(v4l2_event));
v4l2_event.type = UVC_EVENT_STREAMON;
v4l2_event_queue(uvc->vdev, &v4l2_event);
-
- uvc->state = UVC_STATE_STREAMING;
- break;
+ return USB_GADGET_DELAYED_STATUS;
default:
return -EINVAL;
}
-
- return 0;
}
static void
@@ -454,7 +450,6 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed)
const struct uvc_descriptor_header * const *uvc_streaming_cls;
const struct usb_descriptor_header * const *uvc_streaming_std;
const struct usb_descriptor_header * const *src;
- static struct usb_endpoint_descriptor *uvc_control_ep;
struct usb_descriptor_header **dst;
struct usb_descriptor_header **hdr;
unsigned int control_size;
@@ -468,14 +463,12 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed)
uvc_control_desc = uvc->desc.ss_control;
uvc_streaming_cls = uvc->desc.ss_streaming;
uvc_streaming_std = uvc_ss_streaming;
- uvc_control_ep = &uvc_ss_control_ep;
break;
case USB_SPEED_HIGH:
uvc_control_desc = uvc->desc.fs_control;
uvc_streaming_cls = uvc->desc.hs_streaming;
uvc_streaming_std = uvc_hs_streaming;
- uvc_control_ep = &uvc_fs_control_ep;
break;
case USB_SPEED_FULL:
@@ -483,7 +476,6 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed)
uvc_control_desc = uvc->desc.fs_control;
uvc_streaming_cls = uvc->desc.fs_streaming;
uvc_streaming_std = uvc_fs_streaming;
- uvc_control_ep = &uvc_fs_control_ep;
break;
}
@@ -494,6 +486,7 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed)
* Class-specific UVC control descriptors
* uvc_control_ep
* uvc_control_cs_ep
+ * uvc_ss_control_comp (for SS only)
* uvc_streaming_intf_alt0
* Class-specific UVC streaming descriptors
* uvc_{fs|hs}_streaming
@@ -503,7 +496,7 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed)
control_size = 0;
streaming_size = 0;
bytes = uvc_iad.bLength + uvc_control_intf.bLength
- + uvc_control_ep->bLength + uvc_control_cs_ep.bLength
+ + uvc_control_ep.bLength + uvc_control_cs_ep.bLength
+ uvc_streaming_intf_alt0.bLength;
if (speed == USB_SPEED_SUPER) {
@@ -514,13 +507,13 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed)
}
for (src = (const struct usb_descriptor_header **)uvc_control_desc;
- *src; ++src) {
+ *src; ++src) {
control_size += (*src)->bLength;
bytes += (*src)->bLength;
n_desc++;
}
for (src = (const struct usb_descriptor_header **)uvc_streaming_cls;
- *src; ++src) {
+ *src; ++src) {
streaming_size += (*src)->bLength;
bytes += (*src)->bLength;
n_desc++;
@@ -549,7 +542,7 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed)
uvc_control_header->bInCollection = 1;
uvc_control_header->baInterfaceNr[0] = uvc->streaming_intf;
- UVC_COPY_DESCRIPTOR(mem, dst, uvc_control_ep);
+ UVC_COPY_DESCRIPTOR(mem, dst, &uvc_control_ep);
if (speed == USB_SPEED_SUPER)
UVC_COPY_DESCRIPTOR(mem, dst, &uvc_ss_control_comp);
@@ -560,8 +553,7 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed)
UVC_COPY_DESCRIPTORS(mem, dst,
(const struct usb_descriptor_header**)uvc_streaming_cls);
uvc_streaming_header->wTotalLength = cpu_to_le16(streaming_size);
- uvc_streaming_header->bEndpointAddress =
- uvc_fs_streaming_ep.bEndpointAddress;
+ uvc_streaming_header->bEndpointAddress = uvc->video.ep->address;
UVC_COPY_DESCRIPTORS(mem, dst, uvc_streaming_std);
@@ -581,7 +573,7 @@ uvc_function_unbind(struct usb_configuration *c, struct usb_function *f)
uvc->control_ep->driver_data = NULL;
uvc->video.ep->driver_data = NULL;
- uvc_en_us_strings[UVC_STRING_ASSOCIATION_IDX].id = 0;
+ uvc_en_us_strings[UVC_STRING_CONTROL_IDX].id = 0;
usb_ep_free_request(cdev->gadget->ep0, uvc->control_req);
kfree(uvc->control_buf);
@@ -595,31 +587,52 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f)
{
struct usb_composite_dev *cdev = c->cdev;
struct uvc_device *uvc = to_uvc(f);
+ unsigned int max_packet_mult;
+ unsigned int max_packet_size;
struct usb_ep *ep;
int ret = -EINVAL;
INFO(cdev, "uvc_function_bind\n");
- /* sanity check the streaming endpoint module parameters */
- if (streaming_interval < 1)
- streaming_interval = 1;
- if (streaming_interval > 16)
- streaming_interval = 16;
- if (streaming_mult > 2)
- streaming_mult = 2;
- if (streaming_maxburst > 15)
- streaming_maxburst = 15;
-
- /*
- * fill in the FS video streaming specific descriptors from the
- * module parameters
+ /* Sanity check the streaming endpoint module parameters.
*/
- uvc_fs_streaming_ep.wMaxPacketSize = streaming_maxpacket > 1023 ?
- 1023 : streaming_maxpacket;
+ streaming_interval = clamp(streaming_interval, 1U, 16U);
+ streaming_maxpacket = clamp(streaming_maxpacket, 1U, 3072U);
+ streaming_maxburst = min(streaming_maxburst, 15U);
+
+ /* Fill in the FS/HS/SS Video Streaming specific descriptors from the
+ * module parameters.
+ *
+ * NOTE: We assume that the user knows what they are doing and won't
+ * give parameters that their UDC doesn't support.
+ */
+ if (streaming_maxpacket <= 1024) {
+ max_packet_mult = 1;
+ max_packet_size = streaming_maxpacket;
+ } else if (streaming_maxpacket <= 2048) {
+ max_packet_mult = 2;
+ max_packet_size = streaming_maxpacket / 2;
+ } else {
+ max_packet_mult = 3;
+ max_packet_size = streaming_maxpacket / 3;
+ }
+
+ uvc_fs_streaming_ep.wMaxPacketSize = min(streaming_maxpacket, 1023U);
uvc_fs_streaming_ep.bInterval = streaming_interval;
+ uvc_hs_streaming_ep.wMaxPacketSize = max_packet_size;
+ uvc_hs_streaming_ep.wMaxPacketSize |= ((max_packet_mult - 1) << 11);
+ uvc_hs_streaming_ep.bInterval = streaming_interval;
+
+ uvc_ss_streaming_ep.wMaxPacketSize = max_packet_size;
+ uvc_ss_streaming_ep.bInterval = streaming_interval;
+ uvc_ss_streaming_comp.bmAttributes = max_packet_mult - 1;
+ uvc_ss_streaming_comp.bMaxBurst = streaming_maxburst;
+ uvc_ss_streaming_comp.wBytesPerInterval =
+ max_packet_size * max_packet_mult * streaming_maxburst;
+
/* Allocate endpoints. */
- ep = usb_ep_autoconfig(cdev->gadget, &uvc_fs_control_ep);
+ ep = usb_ep_autoconfig(cdev->gadget, &uvc_control_ep);
if (!ep) {
INFO(cdev, "Unable to allocate control EP\n");
goto error;
@@ -627,7 +640,14 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f)
uvc->control_ep = ep;
ep->driver_data = uvc;
- ep = usb_ep_autoconfig(cdev->gadget, &uvc_fs_streaming_ep);
+ if (gadget_is_superspeed(c->cdev->gadget))
+ ep = usb_ep_autoconfig_ss(cdev->gadget, &uvc_ss_streaming_ep,
+ &uvc_ss_streaming_comp);
+ else if (gadget_is_dualspeed(cdev->gadget))
+ ep = usb_ep_autoconfig(cdev->gadget, &uvc_hs_streaming_ep);
+ else
+ ep = usb_ep_autoconfig(cdev->gadget, &uvc_fs_streaming_ep);
+
if (!ep) {
INFO(cdev, "Unable to allocate streaming EP\n");
goto error;
@@ -635,6 +655,10 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f)
uvc->video.ep = ep;
ep->driver_data = uvc;
+ uvc_fs_streaming_ep.bEndpointAddress = uvc->video.ep->address;
+ uvc_hs_streaming_ep.bEndpointAddress = uvc->video.ep->address;
+ uvc_ss_streaming_ep.bEndpointAddress = uvc->video.ep->address;
+
/* Allocate interface IDs. */
if ((ret = usb_interface_id(c, f)) < 0)
goto error;
@@ -648,37 +672,6 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f)
uvc_streaming_intf_alt1.bInterfaceNumber = ret;
uvc->streaming_intf = ret;
- /* sanity check the streaming endpoint module parameters */
- if (streaming_maxpacket > 1024)
- streaming_maxpacket = 1024;
- /*
- * Fill in the HS descriptors from the module parameters for the Video
- * Streaming endpoint.
- * NOTE: We assume that the user knows what they are doing and won't
- * give parameters that their UDC doesn't support.
- */
- uvc_hs_streaming_ep.wMaxPacketSize = streaming_maxpacket;
- uvc_hs_streaming_ep.wMaxPacketSize |= streaming_mult << 11;
- uvc_hs_streaming_ep.bInterval = streaming_interval;
- uvc_hs_streaming_ep.bEndpointAddress =
- uvc_fs_streaming_ep.bEndpointAddress;
-
- /*
- * Fill in the SS descriptors from the module parameters for the Video
- * Streaming endpoint.
- * NOTE: We assume that the user knows what they are doing and won't
- * give parameters that their UDC doesn't support.
- */
- uvc_ss_streaming_ep.wMaxPacketSize = streaming_maxpacket;
- uvc_ss_streaming_ep.bInterval = streaming_interval;
- uvc_ss_streaming_comp.bmAttributes = streaming_mult;
- uvc_ss_streaming_comp.bMaxBurst = streaming_maxburst;
- uvc_ss_streaming_comp.wBytesPerInterval =
- streaming_maxpacket * (streaming_mult + 1) *
- (streaming_maxburst + 1);
- uvc_ss_streaming_ep.bEndpointAddress =
- uvc_fs_streaming_ep.bEndpointAddress;
-
/* Copy descriptors */
f->fs_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_FULL);
if (gadget_is_dualspeed(cdev->gadget))
@@ -775,23 +768,23 @@ uvc_bind_config(struct usb_configuration *c,
/* Validate the descriptors. */
if (fs_control == NULL || fs_control[0] == NULL ||
- fs_control[0]->bDescriptorSubType != UVC_VC_HEADER)
+ fs_control[0]->bDescriptorSubType != UVC_VC_HEADER)
goto error;
if (ss_control == NULL || ss_control[0] == NULL ||
- ss_control[0]->bDescriptorSubType != UVC_VC_HEADER)
+ ss_control[0]->bDescriptorSubType != UVC_VC_HEADER)
goto error;
if (fs_streaming == NULL || fs_streaming[0] == NULL ||
- fs_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER)
+ fs_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER)
goto error;
if (hs_streaming == NULL || hs_streaming[0] == NULL ||
- hs_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER)
+ hs_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER)
goto error;
if (ss_streaming == NULL || ss_streaming[0] == NULL ||
- ss_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER)
+ ss_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER)
goto error;
uvc->desc.fs_control = fs_control;
@@ -800,13 +793,16 @@ uvc_bind_config(struct usb_configuration *c,
uvc->desc.hs_streaming = hs_streaming;
uvc->desc.ss_streaming = ss_streaming;
- /* Allocate string descriptor numbers. */
- if (uvc_en_us_strings[UVC_STRING_ASSOCIATION_IDX].id == 0) {
+ /* String descriptors are global, we only need to allocate string IDs
+ * for the first UVC function. UVC functions beyond the first (if any)
+ * will reuse the same IDs.
+ */
+ if (uvc_en_us_strings[UVC_STRING_CONTROL_IDX].id == 0) {
ret = usb_string_ids_tab(c->cdev, uvc_en_us_strings);
if (ret)
goto error;
uvc_iad.iFunction =
- uvc_en_us_strings[UVC_STRING_ASSOCIATION_IDX].id;
+ uvc_en_us_strings[UVC_STRING_CONTROL_IDX].id;
uvc_control_intf.iInterface =
uvc_en_us_strings[UVC_STRING_CONTROL_IDX].id;
ret = uvc_en_us_strings[UVC_STRING_STREAMING_IDX].id;
diff --git a/drivers/usb/gadget/f_uvc.h b/drivers/usb/gadget/f_uvc.h
index c3d258d3018..ec52752f732 100644
--- a/drivers/usb/gadget/f_uvc.h
+++ b/drivers/usb/gadget/f_uvc.h
@@ -16,12 +16,12 @@
#include <linux/usb/composite.h>
#include <linux/usb/video.h>
-extern int uvc_bind_config(struct usb_configuration *c,
- const struct uvc_descriptor_header * const *fs_control,
- const struct uvc_descriptor_header * const *hs_control,
- const struct uvc_descriptor_header * const *fs_streaming,
- const struct uvc_descriptor_header * const *hs_streaming,
- const struct uvc_descriptor_header * const *ss_streaming);
+int uvc_bind_config(struct usb_configuration *c,
+ const struct uvc_descriptor_header * const *fs_control,
+ const struct uvc_descriptor_header * const *hs_control,
+ const struct uvc_descriptor_header * const *fs_streaming,
+ const struct uvc_descriptor_header * const *hs_streaming,
+ const struct uvc_descriptor_header * const *ss_streaming);
#endif /* _F_UVC_H_ */
diff --git a/drivers/usb/gadget/fsl_qe_udc.c b/drivers/usb/gadget/fsl_qe_udc.c
index 034477ce77c..9a7ee3347e4 100644
--- a/drivers/usb/gadget/fsl_qe_udc.c
+++ b/drivers/usb/gadget/fsl_qe_udc.c
@@ -2296,7 +2296,6 @@ static int fsl_qe_start(struct usb_gadget *gadget,
driver->driver.bus = NULL;
/* hook up the driver */
udc->driver = driver;
- udc->gadget.dev.driver = &driver->driver;
udc->gadget.speed = driver->max_speed;
/* Enable IRQ reg and Set usbcmd reg EN bit */
@@ -2338,7 +2337,6 @@ static int fsl_qe_stop(struct usb_gadget *gadget,
nuke(loop_ep, -ESHUTDOWN);
spin_unlock_irqrestore(&udc->lock, flags);
- udc->gadget.dev.driver = NULL;
udc->driver = NULL;
dev_info(udc->dev, "unregistered gadget driver '%s'\r\n",
@@ -2523,12 +2521,6 @@ static int qe_udc_probe(struct platform_device *ofdev)
/* name: Identifies the controller hardware type. */
udc->gadget.name = driver_name;
-
- device_initialize(&udc->gadget.dev);
-
- dev_set_name(&udc->gadget.dev, "gadget");
-
- udc->gadget.dev.release = qe_udc_release;
udc->gadget.dev.parent = &ofdev->dev;
/* initialize qe_ep struct */
@@ -2592,22 +2584,17 @@ static int qe_udc_probe(struct platform_device *ofdev)
goto err5;
}
- ret = device_add(&udc->gadget.dev);
+ ret = usb_add_gadget_udc_release(&ofdev->dev, &udc->gadget,
+ qe_udc_release);
if (ret)
goto err6;
- ret = usb_add_gadget_udc(&ofdev->dev, &udc->gadget);
- if (ret)
- goto err7;
-
dev_set_drvdata(&ofdev->dev, udc);
dev_info(udc->dev,
"%s USB controller initialized as device\n",
(udc->soc_type == PORT_QE) ? "QE" : "CPM");
return 0;
-err7:
- device_unregister(&udc->gadget.dev);
err6:
free_irq(udc->usb_irq, udc);
err5:
@@ -2702,7 +2689,6 @@ static int qe_udc_remove(struct platform_device *ofdev)
iounmap(udc->usb_regs);
- device_unregister(&udc->gadget.dev);
/* wait for release() of gadget.dev to free udc */
wait_for_completion(&done);
diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c
index 04d5fef1440..7c2a101d19a 100644
--- a/drivers/usb/gadget/fsl_udc_core.c
+++ b/drivers/usb/gadget/fsl_udc_core.c
@@ -185,20 +185,7 @@ static void done(struct fsl_ep *ep, struct fsl_req *req, int status)
dma_pool_free(udc->td_pool, curr_td, curr_td->td_dma);
}
- if (req->mapped) {
- dma_unmap_single(ep->udc->gadget.dev.parent,
- req->req.dma, req->req.length,
- ep_is_in(ep)
- ? DMA_TO_DEVICE
- : DMA_FROM_DEVICE);
- req->req.dma = DMA_ADDR_INVALID;
- req->mapped = 0;
- } else
- dma_sync_single_for_cpu(ep->udc->gadget.dev.parent,
- req->req.dma, req->req.length,
- ep_is_in(ep)
- ? DMA_TO_DEVICE
- : DMA_FROM_DEVICE);
+ usb_gadget_unmap_request(&ep->udc->gadget, &req->req, ep_is_in(ep));
if (status && (status != -ESHUTDOWN))
VDBG("complete %s req %p stat %d len %u/%u",
@@ -888,6 +875,7 @@ fsl_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
struct fsl_req *req = container_of(_req, struct fsl_req, req);
struct fsl_udc *udc;
unsigned long flags;
+ int ret;
/* catch various bogus parameters */
if (!_req || !req->req.complete || !req->req.buf
@@ -910,22 +898,9 @@ fsl_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
req->ep = ep;
- /* map virtual address to hardware */
- if (req->req.dma == DMA_ADDR_INVALID) {
- req->req.dma = dma_map_single(ep->udc->gadget.dev.parent,
- req->req.buf,
- req->req.length, ep_is_in(ep)
- ? DMA_TO_DEVICE
- : DMA_FROM_DEVICE);
- req->mapped = 1;
- } else {
- dma_sync_single_for_device(ep->udc->gadget.dev.parent,
- req->req.dma, req->req.length,
- ep_is_in(ep)
- ? DMA_TO_DEVICE
- : DMA_FROM_DEVICE);
- req->mapped = 0;
- }
+ ret = usb_gadget_map_request(&ep->udc->gadget, &req->req, ep_is_in(ep));
+ if (ret)
+ return ret;
req->req.status = -EINPROGRESS;
req->req.actual = 0;
@@ -1290,6 +1265,7 @@ static int ep0_prime_status(struct fsl_udc *udc, int direction)
{
struct fsl_req *req = udc->status_req;
struct fsl_ep *ep;
+ int ret;
if (direction == EP_DIR_IN)
udc->ep0_dir = USB_DIR_IN;
@@ -1307,10 +1283,9 @@ static int ep0_prime_status(struct fsl_udc *udc, int direction)
req->req.complete = NULL;
req->dtd_count = 0;
- req->req.dma = dma_map_single(ep->udc->gadget.dev.parent,
- req->req.buf, req->req.length,
- ep_is_in(ep) ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
- req->mapped = 1;
+ ret = usb_gadget_map_request(&ep->udc->gadget, &req->req, ep_is_in(ep));
+ if (ret)
+ return ret;
if (fsl_req_to_dtd(req, GFP_ATOMIC) == 0)
fsl_queue_td(ep, req);
@@ -1353,6 +1328,7 @@ static void ch9getstatus(struct fsl_udc *udc, u8 request_type, u16 value,
u16 tmp = 0; /* Status, cpu endian */
struct fsl_req *req;
struct fsl_ep *ep;
+ int ret;
ep = &udc->eps[0];
@@ -1390,10 +1366,9 @@ static void ch9getstatus(struct fsl_udc *udc, u8 request_type, u16 value,
req->req.complete = NULL;
req->dtd_count = 0;
- req->req.dma = dma_map_single(ep->udc->gadget.dev.parent,
- req->req.buf, req->req.length,
- ep_is_in(ep) ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
- req->mapped = 1;
+ ret = usb_gadget_map_request(&ep->udc->gadget, &req->req, ep_is_in(ep));
+ if (ret)
+ goto stall;
/* prime the data phase */
if ((fsl_req_to_dtd(req, GFP_ATOMIC) == 0))
@@ -1964,7 +1939,6 @@ static int fsl_udc_start(struct usb_gadget *g,
driver->driver.bus = NULL;
/* hook up the driver */
udc_controller->driver = driver;
- udc_controller->gadget.dev.driver = &driver->driver;
spin_unlock_irqrestore(&udc_controller->lock, flags);
if (!IS_ERR_OR_NULL(udc_controller->transceiver)) {
@@ -1980,7 +1954,6 @@ static int fsl_udc_start(struct usb_gadget *g,
if (retval < 0) {
ERR("can't bind to transceiver\n");
driver->unbind(&udc_controller->gadget);
- udc_controller->gadget.dev.driver = 0;
udc_controller->driver = 0;
return retval;
}
@@ -2023,7 +1996,6 @@ static int fsl_udc_stop(struct usb_gadget *g,
nuke(loop_ep, -ESHUTDOWN);
spin_unlock_irqrestore(&udc_controller->lock, flags);
- udc_controller->gadget.dev.driver = NULL;
udc_controller->driver = NULL;
return 0;
@@ -2521,12 +2493,7 @@ static int __init fsl_udc_probe(struct platform_device *pdev)
/* Setup gadget.dev and register with kernel */
dev_set_name(&udc_controller->gadget.dev, "gadget");
- udc_controller->gadget.dev.release = fsl_udc_release;
- udc_controller->gadget.dev.parent = &pdev->dev;
udc_controller->gadget.dev.of_node = pdev->dev.of_node;
- ret = device_register(&udc_controller->gadget.dev);
- if (ret < 0)
- goto err_free_irq;
if (!IS_ERR_OR_NULL(udc_controller->transceiver))
udc_controller->gadget.is_otg = 1;
@@ -2559,10 +2526,11 @@ static int __init fsl_udc_probe(struct platform_device *pdev)
DTD_ALIGNMENT, UDC_DMA_BOUNDARY);
if (udc_controller->td_pool == NULL) {
ret = -ENOMEM;
- goto err_unregister;
+ goto err_free_irq;
}
- ret = usb_add_gadget_udc(&pdev->dev, &udc_controller->gadget);
+ ret = usb_add_gadget_udc_release(&pdev->dev, &udc_controller->gadget,
+ fsl_udc_release);
if (ret)
goto err_del_udc;
@@ -2571,8 +2539,6 @@ static int __init fsl_udc_probe(struct platform_device *pdev)
err_del_udc:
dma_pool_destroy(udc_controller->td_pool);
-err_unregister:
- device_unregister(&udc_controller->gadget.dev);
err_free_irq:
free_irq(udc_controller->irq, udc_controller);
err_iounmap:
@@ -2622,7 +2588,6 @@ static int __exit fsl_udc_remove(struct platform_device *pdev)
if (pdata->operating_mode == FSL_USB2_DR_DEVICE)
release_mem_region(res->start, resource_size(res));
- device_unregister(&udc_controller->gadget.dev);
/* free udc --wait for the release() finished */
wait_for_completion(&done);
@@ -2747,21 +2712,7 @@ static struct platform_driver udc_driver = {
},
};
-static int __init udc_init(void)
-{
- printk(KERN_INFO "%s (%s)\n", driver_desc, DRIVER_VERSION);
- return platform_driver_probe(&udc_driver, fsl_udc_probe);
-}
-
-module_init(udc_init);
-
-static void __exit udc_exit(void)
-{
- platform_driver_unregister(&udc_driver);
- printk(KERN_WARNING "%s unregistered\n", driver_desc);
-}
-
-module_exit(udc_exit);
+module_platform_driver_probe(udc_driver, fsl_udc_probe);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_AUTHOR(DRIVER_AUTHOR);
diff --git a/drivers/usb/gadget/fusb300_udc.c b/drivers/usb/gadget/fusb300_udc.c
index 066cb89376d..cec8871b77f 100644
--- a/drivers/usb/gadget/fusb300_udc.c
+++ b/drivers/usb/gadget/fusb300_udc.c
@@ -394,7 +394,7 @@ static void fusb300_clear_epnstall(struct fusb300 *fusb300, u8 ep)
if (reg & FUSB300_EPSET0_STL) {
printk(KERN_DEBUG "EP%d stall... Clear!!\n", ep);
- reg &= ~FUSB300_EPSET0_STL;
+ reg |= FUSB300_EPSET0_STL_CLR;
iowrite32(reg, fusb300->reg + FUSB300_OFFSET_EPSET0(ep));
}
}
@@ -930,33 +930,33 @@ static void fusb300_wait_idma_finished(struct fusb300_ep *ep)
fusb300_clear_int(ep->fusb300, FUSB300_OFFSET_IGR0,
FUSB300_IGR0_EPn_PRD_INT(ep->epnum));
+ return;
+
IDMA_RESET:
- fusb300_clear_int(ep->fusb300, FUSB300_OFFSET_IGER0,
- FUSB300_IGER0_EEPn_PRD_INT(ep->epnum));
+ reg = ioread32(ep->fusb300->reg + FUSB300_OFFSET_IGER0);
+ reg &= ~FUSB300_IGER0_EEPn_PRD_INT(ep->epnum);
+ iowrite32(reg, ep->fusb300->reg + FUSB300_OFFSET_IGER0);
}
-static void fusb300_set_idma(struct fusb300_ep *ep,
+static void fusb300_set_idma(struct fusb300_ep *ep,
struct fusb300_request *req)
{
- dma_addr_t d;
-
- d = dma_map_single(NULL, req->req.buf, req->req.length, DMA_TO_DEVICE);
+ int ret;
- if (dma_mapping_error(NULL, d)) {
- printk(KERN_DEBUG "dma_mapping_error\n");
+ ret = usb_gadget_map_request(&ep->fusb300->gadget,
+ &req->req, DMA_TO_DEVICE);
+ if (ret)
return;
- }
-
- dma_sync_single_for_device(NULL, d, req->req.length, DMA_TO_DEVICE);
fusb300_enable_bit(ep->fusb300, FUSB300_OFFSET_IGER0,
FUSB300_IGER0_EEPn_PRD_INT(ep->epnum));
- fusb300_fill_idma_prdtbl(ep, d, req->req.length);
+ fusb300_fill_idma_prdtbl(ep, req->req.dma, req->req.length);
/* check idma is done */
fusb300_wait_idma_finished(ep);
- dma_unmap_single(NULL, d, req->req.length, DMA_TO_DEVICE);
+ usb_gadget_unmap_request(&ep->fusb300->gadget,
+ &req->req, DMA_TO_DEVICE);
}
static void in_ep_fifo_handler(struct fusb300_ep *ep)
@@ -1316,7 +1316,6 @@ static int fusb300_udc_start(struct usb_gadget *g,
/* hook up the driver */
driver->driver.bus = NULL;
fusb300->driver = driver;
- fusb300->gadget.dev.driver = &driver->driver;
return 0;
}
@@ -1327,7 +1326,6 @@ static int fusb300_udc_stop(struct usb_gadget *g,
struct fusb300 *fusb300 = to_fusb300(g);
driver->unbind(&fusb300->gadget);
- fusb300->gadget.dev.driver = NULL;
init_controller(fusb300);
fusb300->driver = NULL;
@@ -1422,14 +1420,7 @@ static int __init fusb300_probe(struct platform_device *pdev)
fusb300->gadget.ops = &fusb300_gadget_ops;
- device_initialize(&fusb300->gadget.dev);
-
- dev_set_name(&fusb300->gadget.dev, "gadget");
-
fusb300->gadget.max_speed = USB_SPEED_HIGH;
- fusb300->gadget.dev.parent = &pdev->dev;
- fusb300->gadget.dev.dma_mask = pdev->dev.dma_mask;
- fusb300->gadget.dev.release = pdev->dev.release;
fusb300->gadget.name = udc_name;
fusb300->reg = reg;
@@ -1478,19 +1469,10 @@ static int __init fusb300_probe(struct platform_device *pdev)
if (ret)
goto err_add_udc;
- ret = device_add(&fusb300->gadget.dev);
- if (ret) {
- pr_err("device_add error (%d)\n", ret);
- goto err_add_device;
- }
-
dev_info(&pdev->dev, "version %s\n", DRIVER_VERSION);
return 0;
-err_add_device:
- usb_del_gadget_udc(&fusb300->gadget);
-
err_add_udc:
fusb300_free_request(&fusb300->ep[0]->ep, fusb300->ep0_req);
diff --git a/drivers/usb/gadget/fusb300_udc.h b/drivers/usb/gadget/fusb300_udc.h
index 6ba444ae8dd..ae811d8d38b 100644
--- a/drivers/usb/gadget/fusb300_udc.h
+++ b/drivers/usb/gadget/fusb300_udc.h
@@ -111,8 +111,8 @@
/*
* * EPn Setting 0 (EPn_SET0, offset = 020H+(n-1)*30H, n=1~15 )
* */
+#define FUSB300_EPSET0_STL_CLR (1 << 3)
#define FUSB300_EPSET0_CLRSEQNUM (1 << 2)
-#define FUSB300_EPSET0_EPn_TX0BYTE (1 << 1)
#define FUSB300_EPSET0_STL (1 << 0)
/*
diff --git a/drivers/usb/gadget/g_ffs.c b/drivers/usb/gadget/g_ffs.c
index 3953dd4d718..787a78e92aa 100644
--- a/drivers/usb/gadget/g_ffs.c
+++ b/drivers/usb/gadget/g_ffs.c
@@ -13,7 +13,6 @@
#define pr_fmt(fmt) "g_ffs: " fmt
#include <linux/module.h>
-
/*
* kbuild is not very cooperative with respect to linking separately
* compiled library objects into one module. So for now we won't use
@@ -38,13 +37,16 @@
# include "u_ether.c"
static u8 gfs_hostaddr[ETH_ALEN];
+static struct eth_dev *the_dev;
# ifdef CONFIG_USB_FUNCTIONFS_ETH
-static int eth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]);
+static int eth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
+ struct eth_dev *dev);
# endif
#else
-# define gether_cleanup() do { } while (0)
-# define gether_setup(gadget, hostaddr) ((int)0)
+# define the_dev NULL
+# define gether_cleanup(dev) do { } while (0)
# define gfs_hostaddr NULL
+struct eth_dev;
#endif
#include "f_fs.c"
@@ -137,7 +139,8 @@ static struct usb_gadget_strings *gfs_dev_strings[] = {
struct gfs_configuration {
struct usb_configuration c;
- int (*eth)(struct usb_configuration *c, u8 *ethaddr);
+ int (*eth)(struct usb_configuration *c, u8 *ethaddr,
+ struct eth_dev *dev);
} gfs_configurations[] = {
#ifdef CONFIG_USB_FUNCTIONFS_RNDIS
{
@@ -346,10 +349,13 @@ static int gfs_bind(struct usb_composite_dev *cdev)
if (missing_funcs)
return -ENODEV;
-
- ret = gether_setup(cdev->gadget, gfs_hostaddr);
- if (unlikely(ret < 0))
+#if defined CONFIG_USB_FUNCTIONFS_ETH || defined CONFIG_USB_FUNCTIONFS_RNDIS
+ the_dev = gether_setup(cdev->gadget, gfs_hostaddr);
+#endif
+ if (IS_ERR(the_dev)) {
+ ret = PTR_ERR(the_dev);
goto error_quick;
+ }
gfs_ether_setup = true;
ret = usb_string_ids_tab(cdev, gfs_strings);
@@ -357,7 +363,7 @@ static int gfs_bind(struct usb_composite_dev *cdev)
goto error;
gfs_dev_desc.iProduct = gfs_strings[USB_GADGET_PRODUCT_IDX].id;
- for (i = func_num; --i; ) {
+ for (i = func_num; i--; ) {
ret = functionfs_bind(ffs_tab[i].ffs_data, cdev);
if (unlikely(ret < 0)) {
while (++i < func_num)
@@ -386,7 +392,7 @@ error_unbind:
for (i = 0; i < func_num; i++)
functionfs_unbind(ffs_tab[i].ffs_data);
error:
- gether_cleanup();
+ gether_cleanup(the_dev);
error_quick:
gfs_ether_setup = false;
return ret;
@@ -410,10 +416,10 @@ static int gfs_unbind(struct usb_composite_dev *cdev)
* do...?
*/
if (gfs_ether_setup)
- gether_cleanup();
+ gether_cleanup(the_dev);
gfs_ether_setup = false;
- for (i = func_num; --i; )
+ for (i = func_num; i--; )
if (ffs_tab[i].ffs_data)
functionfs_unbind(ffs_tab[i].ffs_data);
@@ -440,7 +446,7 @@ static int gfs_do_config(struct usb_configuration *c)
}
if (gc->eth) {
- ret = gc->eth(c, gfs_hostaddr);
+ ret = gc->eth(c, gfs_hostaddr, the_dev);
if (unlikely(ret < 0))
return ret;
}
@@ -469,11 +475,12 @@ static int gfs_do_config(struct usb_configuration *c)
#ifdef CONFIG_USB_FUNCTIONFS_ETH
-static int eth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
+static int eth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
+ struct eth_dev *dev)
{
return can_support_ecm(c->cdev->gadget)
- ? ecm_bind_config(c, ethaddr)
- : geth_bind_config(c, ethaddr);
+ ? ecm_bind_config(c, ethaddr, dev)
+ : geth_bind_config(c, ethaddr, dev);
}
#endif
diff --git a/drivers/usb/gadget/goku_udc.c b/drivers/usb/gadget/goku_udc.c
index 85742d4c67d..991aba390d9 100644
--- a/drivers/usb/gadget/goku_udc.c
+++ b/drivers/usb/gadget/goku_udc.c
@@ -51,8 +51,6 @@
#define DRIVER_DESC "TC86C001 USB Device Controller"
#define DRIVER_VERSION "30-Oct 2003"
-#define DMA_ADDR_INVALID (~(dma_addr_t)0)
-
static const char driver_name [] = "goku_udc";
static const char driver_desc [] = DRIVER_DESC;
@@ -275,7 +273,6 @@ goku_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags)
if (!req)
return NULL;
- req->req.dma = DMA_ADDR_INVALID;
INIT_LIST_HEAD(&req->queue);
return &req->req;
}
@@ -1354,7 +1351,6 @@ static int goku_udc_start(struct usb_gadget *g,
/* hook up the driver */
driver->driver.bus = NULL;
dev->driver = driver;
- dev->gadget.dev.driver = &driver->driver;
/*
* then enable host detection and ep0; and we're ready
@@ -1394,7 +1390,6 @@ static int goku_udc_stop(struct usb_gadget *g,
dev->driver = NULL;
stop_activity(dev, driver);
spin_unlock_irqrestore(&dev->lock, flags);
- dev->gadget.dev.driver = NULL;
return 0;
}
@@ -1716,8 +1711,6 @@ static void goku_remove(struct pci_dev *pdev)
pci_resource_len (pdev, 0));
if (dev->enabled)
pci_disable_device(pdev);
- if (dev->registered)
- device_unregister(&dev->gadget.dev);
pci_set_drvdata(pdev, NULL);
dev->regs = NULL;
@@ -1756,10 +1749,6 @@ static int goku_probe(struct pci_dev *pdev, const struct pci_device_id *id)
dev->gadget.max_speed = USB_SPEED_FULL;
/* the "gadget" abstracts/virtualizes the controller */
- dev_set_name(&dev->gadget.dev, "gadget");
- dev->gadget.dev.parent = &pdev->dev;
- dev->gadget.dev.dma_mask = pdev->dev.dma_mask;
- dev->gadget.dev.release = gadget_release;
dev->gadget.name = driver_name;
/* now all the pci goodies ... */
@@ -1810,13 +1799,8 @@ static int goku_probe(struct pci_dev *pdev, const struct pci_device_id *id)
create_proc_read_entry(proc_node_name, 0, NULL, udc_proc_read, dev);
#endif
- retval = device_register(&dev->gadget.dev);
- if (retval) {
- put_device(&dev->gadget.dev);
- goto err;
- }
- dev->registered = 1;
- retval = usb_add_gadget_udc(&pdev->dev, &dev->gadget);
+ retval = usb_add_gadget_udc_release(&pdev->dev, &dev->gadget,
+ gadget_release);
if (retval)
goto err;
diff --git a/drivers/usb/gadget/goku_udc.h b/drivers/usb/gadget/goku_udc.h
index b4470d2b1d8..86d2adafe14 100644
--- a/drivers/usb/gadget/goku_udc.h
+++ b/drivers/usb/gadget/goku_udc.h
@@ -250,8 +250,7 @@ struct goku_udc {
got_region:1,
req_config:1,
configured:1,
- enabled:1,
- registered:1;
+ enabled:1;
/* pci state used to access those endpoints */
struct pci_dev *pdev;
diff --git a/drivers/usb/gadget/imx_udc.c b/drivers/usb/gadget/imx_udc.c
index 8efd7555fa2..b5cebd6b0d7 100644
--- a/drivers/usb/gadget/imx_udc.c
+++ b/drivers/usb/gadget/imx_udc.c
@@ -1334,16 +1334,10 @@ static int imx_udc_start(struct usb_gadget *gadget,
struct usb_gadget_driver *driver)
{
struct imx_udc_struct *imx_usb;
- int retval;
imx_usb = container_of(gadget, struct imx_udc_struct, gadget);
/* first hook up the driver ... */
imx_usb->driver = driver;
- imx_usb->gadget.dev.driver = &driver->driver;
-
- retval = device_add(&imx_usb->gadget.dev);
- if (retval)
- goto fail;
D_INI(imx_usb->dev, "<%s> registered gadget driver '%s'\n",
__func__, driver->driver.name);
@@ -1351,10 +1345,6 @@ static int imx_udc_start(struct usb_gadget *gadget,
imx_udc_enable(imx_usb);
return 0;
-fail:
- imx_usb->driver = NULL;
- imx_usb->gadget.dev.driver = NULL;
- return retval;
}
static int imx_udc_stop(struct usb_gadget *gadget,
@@ -1367,11 +1357,8 @@ static int imx_udc_stop(struct usb_gadget *gadget,
imx_udc_disable(imx_usb);
del_timer(&imx_usb->timer);
- imx_usb->gadget.dev.driver = NULL;
imx_usb->driver = NULL;
- device_del(&imx_usb->gadget.dev);
-
D_INI(imx_usb->dev, "<%s> unregistered gadget driver '%s'\n",
__func__, driver->driver.name);
@@ -1472,11 +1459,6 @@ static int __init imx_udc_probe(struct platform_device *pdev)
imx_usb->clk = clk;
imx_usb->dev = &pdev->dev;
- device_initialize(&imx_usb->gadget.dev);
-
- imx_usb->gadget.dev.parent = &pdev->dev;
- imx_usb->gadget.dev.dma_mask = pdev->dev.dma_mask;
-
platform_set_drvdata(pdev, imx_usb);
usb_init_data(imx_usb);
diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c
index 8ac840f25ba..e2b2e9cf254 100644
--- a/drivers/usb/gadget/inode.c
+++ b/drivers/usb/gadget/inode.c
@@ -2105,6 +2105,7 @@ static struct file_system_type gadgetfs_type = {
.mount = gadgetfs_mount,
.kill_sb = gadgetfs_kill_sb,
};
+MODULE_ALIAS_FS("gadgetfs");
/*----------------------------------------------------------------------*/
diff --git a/drivers/usb/gadget/lpc32xx_udc.c b/drivers/usb/gadget/lpc32xx_udc.c
index aa04089d689..b943d8cdfbf 100644
--- a/drivers/usb/gadget/lpc32xx_udc.c
+++ b/drivers/usb/gadget/lpc32xx_udc.c
@@ -1469,23 +1469,7 @@ static void done(struct lpc32xx_ep *ep, struct lpc32xx_request *req, int status)
status = req->req.status;
if (ep->lep) {
- enum dma_data_direction direction;
-
- if (ep->is_in)
- direction = DMA_TO_DEVICE;
- else
- direction = DMA_FROM_DEVICE;
-
- if (req->mapped) {
- dma_unmap_single(ep->udc->gadget.dev.parent,
- req->req.dma, req->req.length,
- direction);
- req->req.dma = 0;
- req->mapped = 0;
- } else
- dma_sync_single_for_cpu(ep->udc->gadget.dev.parent,
- req->req.dma, req->req.length,
- direction);
+ usb_gadget_unmap_request(&udc->gadget, &req->req, ep->is_in);
/* Free DDs */
udc_dd_free(udc, req->dd_desc_ptr);
@@ -1841,26 +1825,11 @@ static int lpc32xx_ep_queue(struct usb_ep *_ep,
}
if (ep->lep) {
- enum dma_data_direction direction;
struct lpc32xx_usbd_dd_gad *dd;
- /* Map DMA pointer */
- if (ep->is_in)
- direction = DMA_TO_DEVICE;
- else
- direction = DMA_FROM_DEVICE;
-
- if (req->req.dma == 0) {
- req->req.dma = dma_map_single(
- ep->udc->gadget.dev.parent,
- req->req.buf, req->req.length, direction);
- req->mapped = 1;
- } else {
- dma_sync_single_for_device(
- ep->udc->gadget.dev.parent, req->req.dma,
- req->req.length, direction);
- req->mapped = 0;
- }
+ status = usb_gadget_map_request(&udc->gadget, _req, ep->is_in);
+ if (status)
+ return status;
/* For the request, build a list of DDs */
dd = udc_dd_alloc(udc);
@@ -2977,7 +2946,6 @@ static int lpc32xx_start(struct usb_gadget *gadget,
}
udc->driver = driver;
- udc->gadget.dev.driver = &driver->driver;
udc->gadget.dev.of_node = udc->dev->of_node;
udc->enabled = 1;
udc->selfpowered = 1;
@@ -3026,7 +2994,6 @@ static int lpc32xx_stop(struct usb_gadget *gadget,
}
udc->enabled = 0;
- udc->gadget.dev.driver = NULL;
udc->driver = NULL;
return 0;
@@ -3248,12 +3215,6 @@ static int __init lpc32xx_udc_probe(struct platform_device *pdev)
udc_disable(udc);
udc_reinit(udc);
- retval = device_register(&udc->gadget.dev);
- if (retval < 0) {
- dev_err(udc->dev, "Device registration failure\n");
- goto dev_register_fail;
- }
-
/* Request IRQs - low and high priority USB device IRQs are routed to
* the same handler, while the DMA interrupt is routed elsewhere */
retval = request_irq(udc->udp_irq[IRQ_USB_LP], lpc32xx_usb_lp_irq,
@@ -3320,8 +3281,6 @@ irq_dev_fail:
irq_hp_fail:
free_irq(udc->udp_irq[IRQ_USB_LP], udc);
irq_lp_fail:
- device_unregister(&udc->gadget.dev);
-dev_register_fail:
dma_pool_destroy(udc->dd_cache);
dma_alloc_fail:
dma_free_coherent(&pdev->dev, UDCA_BUFF_SIZE,
@@ -3376,8 +3335,6 @@ static int lpc32xx_udc_remove(struct platform_device *pdev)
free_irq(udc->udp_irq[IRQ_USB_HP], udc);
free_irq(udc->udp_irq[IRQ_USB_LP], udc);
- device_unregister(&udc->gadget.dev);
-
clk_disable(udc->usb_otg_clk);
clk_put(udc->usb_otg_clk);
clk_disable(udc->usb_slv_clk);
diff --git a/drivers/usb/gadget/m66592-udc.c b/drivers/usb/gadget/m66592-udc.c
index c1b8c2dd808..866ef099924 100644
--- a/drivers/usb/gadget/m66592-udc.c
+++ b/drivers/usb/gadget/m66592-udc.c
@@ -1471,7 +1471,6 @@ static int m66592_udc_start(struct usb_gadget *g,
/* hook up the driver */
driver->driver.bus = NULL;
m66592->driver = driver;
- m66592->gadget.dev.driver = &driver->driver;
m66592_bset(m66592, M66592_VBSE | M66592_URST, M66592_INTENB0);
if (m66592_read(m66592, M66592_INTSTS0) & M66592_VBSTS) {
@@ -1494,7 +1493,6 @@ static int m66592_udc_stop(struct usb_gadget *g,
m66592_bclr(m66592, M66592_VBSE | M66592_URST, M66592_INTENB0);
driver->unbind(&m66592->gadget);
- m66592->gadget.dev.driver = NULL;
init_controller(m66592);
disable_controller(m66592);
@@ -1538,7 +1536,6 @@ static int __exit m66592_remove(struct platform_device *pdev)
struct m66592 *m66592 = dev_get_drvdata(&pdev->dev);
usb_del_gadget_udc(&m66592->gadget);
- device_del(&m66592->gadget.dev);
del_timer_sync(&m66592->timer);
iounmap(m66592->reg);
@@ -1608,12 +1605,7 @@ static int __init m66592_probe(struct platform_device *pdev)
dev_set_drvdata(&pdev->dev, m66592);
m66592->gadget.ops = &m66592_gadget_ops;
- device_initialize(&m66592->gadget.dev);
- dev_set_name(&m66592->gadget.dev, "gadget");
m66592->gadget.max_speed = USB_SPEED_HIGH;
- m66592->gadget.dev.parent = &pdev->dev;
- m66592->gadget.dev.dma_mask = pdev->dev.dma_mask;
- m66592->gadget.dev.release = pdev->dev.release;
m66592->gadget.name = udc_name;
init_timer(&m66592->timer);
@@ -1674,12 +1666,6 @@ static int __init m66592_probe(struct platform_device *pdev)
init_controller(m66592);
- ret = device_add(&m66592->gadget.dev);
- if (ret) {
- pr_err("device_add error (%d)\n", ret);
- goto err_device_add;
- }
-
ret = usb_add_gadget_udc(&pdev->dev, &m66592->gadget);
if (ret)
goto err_add_udc;
@@ -1688,9 +1674,6 @@ static int __init m66592_probe(struct platform_device *pdev)
return 0;
err_add_udc:
- device_del(&m66592->gadget.dev);
-
-err_device_add:
m66592_free_request(&m66592->ep[0].ep, m66592->ep0_req);
clean_up3:
diff --git a/drivers/usb/gadget/multi.c b/drivers/usb/gadget/multi.c
index 20bbbf917fc..4a45e80c6e3 100644
--- a/drivers/usb/gadget/multi.c
+++ b/drivers/usb/gadget/multi.c
@@ -135,8 +135,8 @@ static struct fsg_common fsg_common;
static u8 hostaddr[ETH_ALEN];
-static unsigned char tty_line;
static struct usb_function_instance *fi_acm;
+static struct eth_dev *the_dev;
/********** RNDIS **********/
@@ -152,13 +152,15 @@ static __init int rndis_do_config(struct usb_configuration *c)
c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
}
- ret = rndis_bind_config(c, hostaddr);
+ ret = rndis_bind_config(c, hostaddr, the_dev);
if (ret < 0)
return ret;
f_acm_rndis = usb_get_function(fi_acm);
- if (IS_ERR(f_acm_rndis))
+ if (IS_ERR(f_acm_rndis)) {
+ ret = PTR_ERR(f_acm_rndis);
goto err_func_acm;
+ }
ret = usb_add_function(c, f_acm_rndis);
if (ret)
@@ -214,7 +216,7 @@ static __init int cdc_do_config(struct usb_configuration *c)
c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
}
- ret = ecm_bind_config(c, hostaddr);
+ ret = ecm_bind_config(c, hostaddr, the_dev);
if (ret < 0)
return ret;
@@ -269,7 +271,6 @@ static int cdc_config_register(struct usb_composite_dev *cdev)
static int __ref multi_bind(struct usb_composite_dev *cdev)
{
struct usb_gadget *gadget = cdev->gadget;
- struct f_serial_opts *opts;
int status;
if (!can_support_ecm(cdev->gadget)) {
@@ -279,24 +280,17 @@ static int __ref multi_bind(struct usb_composite_dev *cdev)
}
/* set up network link layer */
- status = gether_setup(cdev->gadget, hostaddr);
- if (status < 0)
- return status;
+ the_dev = gether_setup(cdev->gadget, hostaddr);
+ if (IS_ERR(the_dev))
+ return PTR_ERR(the_dev);
/* set up serial link layer */
- status = gserial_alloc_line(&tty_line);
- if (status < 0)
- goto fail0;
-
fi_acm = usb_get_function_instance("acm");
if (IS_ERR(fi_acm)) {
status = PTR_ERR(fi_acm);
- goto fail0dot5;
+ goto fail0;
}
- opts = container_of(fi_acm, struct f_serial_opts, func_inst);
- opts->port_num = tty_line;
-
/* set up mass storage function */
{
void *retp;
@@ -334,10 +328,8 @@ fail2:
fsg_common_put(&fsg_common);
fail1:
usb_put_function_instance(fi_acm);
-fail0dot5:
- gserial_free_line(tty_line);
fail0:
- gether_cleanup();
+ gether_cleanup(the_dev);
return status;
}
@@ -350,8 +342,7 @@ static int __exit multi_unbind(struct usb_composite_dev *cdev)
usb_put_function(f_acm_rndis);
#endif
usb_put_function_instance(fi_acm);
- gserial_free_line(tty_line);
- gether_cleanup();
+ gether_cleanup(the_dev);
return 0;
}
diff --git a/drivers/usb/gadget/mv_u3d_core.c b/drivers/usb/gadget/mv_u3d_core.c
index b5cea273c95..58288e9cf72 100644
--- a/drivers/usb/gadget/mv_u3d_core.c
+++ b/drivers/usb/gadget/mv_u3d_core.c
@@ -30,9 +30,6 @@
#include <linux/platform_device.h>
#include <linux/platform_data/mv_usb.h>
#include <linux/clk.h>
-#include <asm/system.h>
-#include <asm/unaligned.h>
-#include <asm/byteorder.h>
#include "mv_u3d.h"
@@ -125,7 +122,7 @@ static int mv_u3d_process_ep_req(struct mv_u3d *u3d, int index,
struct mv_u3d_trb *curr_trb;
dma_addr_t cur_deq_lo;
struct mv_u3d_ep_context *curr_ep_context;
- int trb_complete, actual, remaining_length;
+ int trb_complete, actual, remaining_length = 0;
int direction, ep_num;
int retval = 0;
u32 tmp, status, length;
@@ -189,6 +186,8 @@ static int mv_u3d_process_ep_req(struct mv_u3d *u3d, int index,
*/
static
void mv_u3d_done(struct mv_u3d_ep *ep, struct mv_u3d_req *req, int status)
+ __releases(&ep->udc->lock)
+ __acquires(&ep->udc->lock)
{
struct mv_u3d *u3d = (struct mv_u3d *)ep->u3d;
@@ -812,19 +811,19 @@ mv_u3d_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
return 0;
}
- dev_dbg(u3d->dev, "%s: %s, req: 0x%x\n",
- __func__, _ep->name, (u32)req);
+ dev_dbg(u3d->dev, "%s: %s, req: 0x%p\n",
+ __func__, _ep->name, req);
/* catch various bogus parameters */
if (!req->req.complete || !req->req.buf
|| !list_empty(&req->queue)) {
dev_err(u3d->dev,
- "%s, bad params, _req: 0x%x,"
- "req->req.complete: 0x%x, req->req.buf: 0x%x,"
+ "%s, bad params, _req: 0x%p,"
+ "req->req.complete: 0x%p, req->req.buf: 0x%p,"
"list_empty: 0x%x\n",
- __func__, (u32)_req,
- (u32)req->req.complete, (u32)req->req.buf,
- (u32)list_empty(&req->queue));
+ __func__, _req,
+ req->req.complete, req->req.buf,
+ list_empty(&req->queue));
return -EINVAL;
}
if (unlikely(!ep->ep.desc)) {
@@ -905,7 +904,7 @@ static int mv_u3d_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)
struct mv_u3d_req, queue);
/* Point first TRB of next request to the EP context. */
- iowrite32((u32) next_req->trb_head,
+ iowrite32((unsigned long) next_req->trb_head,
&ep_context->trb_addr_lo);
} else {
struct mv_u3d_ep_context *ep_context;
@@ -1264,7 +1263,6 @@ static int mv_u3d_start(struct usb_gadget *g,
/* hook up the driver ... */
driver->driver.bus = NULL;
u3d->driver = driver;
- u3d->gadget.dev.driver = &driver->driver;
u3d->ep0_dir = USB_DIR_OUT;
@@ -1302,7 +1300,6 @@ static int mv_u3d_stop(struct usb_gadget *g,
spin_unlock_irqrestore(&u3d->lock, flags);
- u3d->gadget.dev.driver = NULL;
u3d->driver = NULL;
return 0;
@@ -1525,6 +1522,8 @@ static int mv_u3d_is_set_configuration(struct usb_ctrlrequest *setup)
static void mv_u3d_handle_setup_packet(struct mv_u3d *u3d, u8 ep_num,
struct usb_ctrlrequest *setup)
+ __releases(&u3c->lock)
+ __acquires(&u3c->lock)
{
bool delegate = false;
@@ -1758,11 +1757,6 @@ static irqreturn_t mv_u3d_irq(int irq, void *dev)
return IRQ_HANDLED;
}
-static void mv_u3d_gadget_release(struct device *dev)
-{
- dev_dbg(dev, "%s\n", __func__);
-}
-
static int mv_u3d_remove(struct platform_device *dev)
{
struct mv_u3d *u3d = platform_get_drvdata(dev);
@@ -1792,8 +1786,6 @@ static int mv_u3d_remove(struct platform_device *dev)
clk_put(u3d->clk);
- device_unregister(&u3d->gadget.dev);
-
platform_set_drvdata(dev, NULL);
kfree(u3d);
@@ -1829,7 +1821,7 @@ static int mv_u3d_probe(struct platform_device *dev)
u3d->dev = &dev->dev;
u3d->vbus = pdata->vbus;
- u3d->clk = clk_get(&dev->dev, pdata->clkname[0]);
+ u3d->clk = clk_get(&dev->dev, NULL);
if (IS_ERR(u3d->clk)) {
retval = PTR_ERR(u3d->clk);
goto err_get_clk;
@@ -1849,8 +1841,9 @@ static int mv_u3d_probe(struct platform_device *dev)
retval = -EBUSY;
goto err_map_cap_regs;
} else {
- dev_dbg(&dev->dev, "cap_regs address: 0x%x/0x%x\n",
- (unsigned int)r->start, (unsigned int)u3d->cap_regs);
+ dev_dbg(&dev->dev, "cap_regs address: 0x%lx/0x%lx\n",
+ (unsigned long) r->start,
+ (unsigned long) u3d->cap_regs);
}
/* we will access controller register, so enable the u3d controller */
@@ -1864,10 +1857,10 @@ static int mv_u3d_probe(struct platform_device *dev)
}
}
- u3d->op_regs = (struct mv_u3d_op_regs __iomem *)((u32)u3d->cap_regs
+ u3d->op_regs = (struct mv_u3d_op_regs __iomem *)(u3d->cap_regs
+ MV_U3D_USB3_OP_REGS_OFFSET);
- u3d->vuc_regs = (struct mv_u3d_vuc_regs __iomem *)((u32)u3d->cap_regs
+ u3d->vuc_regs = (struct mv_u3d_vuc_regs __iomem *)(u3d->cap_regs
+ ioread32(&u3d->cap_regs->vuoff));
u3d->max_eps = 16;
@@ -1957,16 +1950,8 @@ static int mv_u3d_probe(struct platform_device *dev)
u3d->gadget.speed = USB_SPEED_UNKNOWN; /* speed */
/* the "gadget" abstracts/virtualizes the controller */
- dev_set_name(&u3d->gadget.dev, "gadget");
- u3d->gadget.dev.parent = &dev->dev;
- u3d->gadget.dev.dma_mask = dev->dev.dma_mask;
- u3d->gadget.dev.release = mv_u3d_gadget_release;
u3d->gadget.name = driver_name; /* gadget name */
- retval = device_register(&u3d->gadget.dev);
- if (retval)
- goto err_register_gadget_device;
-
mv_u3d_eps_init(u3d);
/* external vbus detection */
@@ -1991,8 +1976,6 @@ static int mv_u3d_probe(struct platform_device *dev)
return 0;
err_unregister:
- device_unregister(&u3d->gadget.dev);
-err_register_gadget_device:
free_irq(u3d->irq, &dev->dev);
err_request_irq:
err_get_irq:
@@ -2021,7 +2004,7 @@ err_pdata:
return retval;
}
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
static int mv_u3d_suspend(struct device *dev)
{
struct mv_u3d *u3d = dev_get_drvdata(dev);
@@ -2064,10 +2047,10 @@ static int mv_u3d_resume(struct device *dev)
return 0;
}
-
-SIMPLE_DEV_PM_OPS(mv_u3d_pm_ops, mv_u3d_suspend, mv_u3d_resume);
#endif
+static SIMPLE_DEV_PM_OPS(mv_u3d_pm_ops, mv_u3d_suspend, mv_u3d_resume);
+
static void mv_u3d_shutdown(struct platform_device *dev)
{
struct mv_u3d *u3d = dev_get_drvdata(&dev->dev);
@@ -2080,14 +2063,12 @@ static void mv_u3d_shutdown(struct platform_device *dev)
static struct platform_driver mv_u3d_driver = {
.probe = mv_u3d_probe,
- .remove = __exit_p(mv_u3d_remove),
+ .remove = mv_u3d_remove,
.shutdown = mv_u3d_shutdown,
.driver = {
.owner = THIS_MODULE,
.name = "mv-u3d",
-#ifdef CONFIG_PM
.pm = &mv_u3d_pm_ops,
-#endif
},
};
diff --git a/drivers/usb/gadget/mv_udc.h b/drivers/usb/gadget/mv_udc.h
index 9073436d8b2..be77f207dba 100644
--- a/drivers/usb/gadget/mv_udc.h
+++ b/drivers/usb/gadget/mv_udc.h
@@ -222,8 +222,7 @@ struct mv_udc {
struct mv_usb_platform_data *pdata;
/* some SOC has mutiple clock sources for USB*/
- unsigned int clknum;
- struct clk *clk[0];
+ struct clk *clk;
};
/* endpoint data structure */
diff --git a/drivers/usb/gadget/mv_udc_core.c b/drivers/usb/gadget/mv_udc_core.c
index c8cf959057f..c2a57023e46 100644
--- a/drivers/usb/gadget/mv_udc_core.c
+++ b/drivers/usb/gadget/mv_udc_core.c
@@ -212,6 +212,8 @@ static int process_ep_req(struct mv_udc *udc, int index,
* request is still in progress.
*/
static void done(struct mv_ep *ep, struct mv_req *req, int status)
+ __releases(&ep->udc->lock)
+ __acquires(&ep->udc->lock)
{
struct mv_udc *udc = NULL;
unsigned char stopped = ep->stopped;
@@ -237,18 +239,7 @@ static void done(struct mv_ep *ep, struct mv_req *req, int status)
dma_pool_free(udc->dtd_pool, curr_td, curr_td->td_dma);
}
- if (req->mapped) {
- dma_unmap_single(ep->udc->gadget.dev.parent,
- req->req.dma, req->req.length,
- ((ep_dir(ep) == EP_DIR_IN) ?
- DMA_TO_DEVICE : DMA_FROM_DEVICE));
- req->req.dma = DMA_ADDR_INVALID;
- req->mapped = 0;
- } else
- dma_sync_single_for_cpu(ep->udc->gadget.dev.parent,
- req->req.dma, req->req.length,
- ((ep_dir(ep) == EP_DIR_IN) ?
- DMA_TO_DEVICE : DMA_FROM_DEVICE));
+ usb_gadget_unmap_request(&udc->gadget, &req->req, ep_dir(ep));
if (status && (status != -ESHUTDOWN))
dev_info(&udc->dev->dev, "complete %s req %p stat %d len %u/%u",
@@ -732,21 +723,9 @@ mv_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
req->ep = ep;
/* map virtual address to hardware */
- if (req->req.dma == DMA_ADDR_INVALID) {
- req->req.dma = dma_map_single(ep->udc->gadget.dev.parent,
- req->req.buf,
- req->req.length, ep_dir(ep)
- ? DMA_TO_DEVICE
- : DMA_FROM_DEVICE);
- req->mapped = 1;
- } else {
- dma_sync_single_for_device(ep->udc->gadget.dev.parent,
- req->req.dma, req->req.length,
- ep_dir(ep)
- ? DMA_TO_DEVICE
- : DMA_FROM_DEVICE);
- req->mapped = 0;
- }
+ retval = usb_gadget_map_request(&udc->gadget, _req, ep_dir(ep));
+ if (retval)
+ return retval;
req->req.status = -EINPROGRESS;
req->req.actual = 0;
@@ -780,18 +759,7 @@ mv_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
return 0;
err_unmap_dma:
- if (req->mapped) {
- dma_unmap_single(ep->udc->gadget.dev.parent,
- req->req.dma, req->req.length,
- ((ep_dir(ep) == EP_DIR_IN) ?
- DMA_TO_DEVICE : DMA_FROM_DEVICE));
- req->req.dma = DMA_ADDR_INVALID;
- req->mapped = 0;
- } else
- dma_sync_single_for_cpu(ep->udc->gadget.dev.parent,
- req->req.dma, req->req.length,
- ((ep_dir(ep) == EP_DIR_IN) ?
- DMA_TO_DEVICE : DMA_FROM_DEVICE));
+ usb_gadget_unmap_request(&udc->gadget, _req, ep_dir(ep));
return retval;
}
@@ -1006,18 +974,12 @@ static struct usb_ep_ops mv_ep_ops = {
static void udc_clock_enable(struct mv_udc *udc)
{
- unsigned int i;
-
- for (i = 0; i < udc->clknum; i++)
- clk_prepare_enable(udc->clk[i]);
+ clk_prepare_enable(udc->clk);
}
static void udc_clock_disable(struct mv_udc *udc)
{
- unsigned int i;
-
- for (i = 0; i < udc->clknum; i++)
- clk_disable_unprepare(udc->clk[i]);
+ clk_disable_unprepare(udc->clk);
}
static void udc_stop(struct mv_udc *udc)
@@ -1386,7 +1348,6 @@ static int mv_udc_start(struct usb_gadget *gadget,
/* hook up the driver ... */
driver->driver.bus = NULL;
udc->driver = driver;
- udc->gadget.dev.driver = &driver->driver;
udc->usb_state = USB_STATE_ATTACHED;
udc->ep0_state = WAIT_FOR_SETUP;
@@ -1401,7 +1362,6 @@ static int mv_udc_start(struct usb_gadget *gadget,
dev_err(&udc->dev->dev,
"unable to register peripheral to otg\n");
udc->driver = NULL;
- udc->gadget.dev.driver = NULL;
return retval;
}
}
@@ -1437,7 +1397,6 @@ static int mv_udc_stop(struct usb_gadget *gadget,
spin_unlock_irqrestore(&udc->lock, flags);
/* unbind gadget driver */
- udc->gadget.dev.driver = NULL;
udc->driver = NULL;
return 0;
@@ -1528,14 +1487,7 @@ udc_prime_status(struct mv_udc *udc, u8 direction, u16 status, bool empty)
return 0;
out:
- if (req->mapped) {
- dma_unmap_single(ep->udc->gadget.dev.parent,
- req->req.dma, req->req.length,
- ((ep_dir(ep) == EP_DIR_IN) ?
- DMA_TO_DEVICE : DMA_FROM_DEVICE));
- req->req.dma = DMA_ADDR_INVALID;
- req->mapped = 0;
- }
+ usb_gadget_unmap_request(&udc->gadget, &req->req, ep_dir(ep));
return retval;
}
@@ -1695,6 +1647,8 @@ out:
static void handle_setup_packet(struct mv_udc *udc, u8 ep_num,
struct usb_ctrlrequest *setup)
+ __releases(&ep->udc->lock)
+ __acquires(&ep->udc->lock)
{
bool delegate = false;
@@ -1891,7 +1845,7 @@ static void irq_process_tr_complete(struct mv_udc *udc)
}
}
-void irq_process_reset(struct mv_udc *udc)
+static void irq_process_reset(struct mv_udc *udc)
{
u32 tmp;
unsigned int loops;
@@ -2138,8 +2092,6 @@ static int mv_udc_remove(struct platform_device *pdev)
mv_udc_disable(udc);
- device_unregister(&udc->gadget.dev);
-
/* free dev, wait for the release() finished */
wait_for_completion(udc->done);
@@ -2151,7 +2103,6 @@ static int mv_udc_probe(struct platform_device *pdev)
struct mv_usb_platform_data *pdata = pdev->dev.platform_data;
struct mv_udc *udc;
int retval = 0;
- int clk_i = 0;
struct resource *r;
size_t size;
@@ -2160,8 +2111,7 @@ static int mv_udc_probe(struct platform_device *pdev)
return -ENODEV;
}
- size = sizeof(*udc) + sizeof(struct clk *) * pdata->clknum;
- udc = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
+ udc = devm_kzalloc(&pdev->dev, sizeof(*udc), GFP_KERNEL);
if (udc == NULL) {
dev_err(&pdev->dev, "failed to allocate memory for udc\n");
return -ENOMEM;
@@ -2173,26 +2123,24 @@ static int mv_udc_probe(struct platform_device *pdev)
udc->dev = pdev;
-#ifdef CONFIG_USB_OTG_UTILS
if (pdata->mode == MV_USB_MODE_OTG) {
udc->transceiver = devm_usb_get_phy(&pdev->dev,
USB_PHY_TYPE_USB2);
- if (IS_ERR_OR_NULL(udc->transceiver)) {
+ if (IS_ERR(udc->transceiver)) {
+ retval = PTR_ERR(udc->transceiver);
+
+ if (retval == -ENXIO)
+ return retval;
+
udc->transceiver = NULL;
- return -ENODEV;
+ return -EPROBE_DEFER;
}
}
-#endif
- udc->clknum = pdata->clknum;
- for (clk_i = 0; clk_i < udc->clknum; clk_i++) {
- udc->clk[clk_i] = devm_clk_get(&pdev->dev,
- pdata->clkname[clk_i]);
- if (IS_ERR(udc->clk[clk_i])) {
- retval = PTR_ERR(udc->clk[clk_i]);
- return retval;
- }
- }
+ /* udc only have one sysclk. */
+ udc->clk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(udc->clk))
+ return PTR_ERR(udc->clk);
r = platform_get_resource_byname(udc->dev, IORESOURCE_MEM, "capregs");
if (r == NULL) {
@@ -2311,16 +2259,8 @@ static int mv_udc_probe(struct platform_device *pdev)
udc->gadget.max_speed = USB_SPEED_HIGH; /* support dual speed */
/* the "gadget" abstracts/virtualizes the controller */
- dev_set_name(&udc->gadget.dev, "gadget");
- udc->gadget.dev.parent = &pdev->dev;
- udc->gadget.dev.dma_mask = pdev->dev.dma_mask;
- udc->gadget.dev.release = gadget_release;
udc->gadget.name = driver_name; /* gadget name */
- retval = device_register(&udc->gadget.dev);
- if (retval)
- goto err_destroy_dma;
-
eps_init(udc);
/* VBUS detect: we can disable/enable clock on demand.*/
@@ -2342,7 +2282,7 @@ static int mv_udc_probe(struct platform_device *pdev)
if (!udc->qwork) {
dev_err(&pdev->dev, "cannot create workqueue\n");
retval = -ENOMEM;
- goto err_unregister;
+ goto err_destroy_dma;
}
INIT_WORK(&udc->vbus_work, mv_udc_vbus_work);
@@ -2358,7 +2298,8 @@ static int mv_udc_probe(struct platform_device *pdev)
else
udc->vbus_active = 1;
- retval = usb_add_gadget_udc(&pdev->dev, &udc->gadget);
+ retval = usb_add_gadget_udc_release(&pdev->dev, &udc->gadget,
+ gadget_release);
if (retval)
goto err_create_workqueue;
@@ -2370,8 +2311,6 @@ static int mv_udc_probe(struct platform_device *pdev)
err_create_workqueue:
destroy_workqueue(udc->qwork);
-err_unregister:
- device_unregister(&udc->gadget.dev);
err_destroy_dma:
dma_pool_destroy(udc->dtd_pool);
err_free_dma:
diff --git a/drivers/usb/gadget/ncm.c b/drivers/usb/gadget/ncm.c
index a22ad9af056..3b02fd4649c 100644
--- a/drivers/usb/gadget/ncm.c
+++ b/drivers/usb/gadget/ncm.c
@@ -111,6 +111,7 @@ static struct usb_gadget_strings *dev_strings[] = {
NULL,
};
+struct eth_dev *the_dev;
static u8 hostaddr[ETH_ALEN];
/*-------------------------------------------------------------------------*/
@@ -124,7 +125,7 @@ static int __init ncm_do_config(struct usb_configuration *c)
c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
}
- return ncm_bind_config(c, hostaddr);
+ return ncm_bind_config(c, hostaddr, the_dev);
}
static struct usb_configuration ncm_config_driver = {
@@ -143,9 +144,9 @@ static int __init gncm_bind(struct usb_composite_dev *cdev)
int status;
/* set up network link layer */
- status = gether_setup(cdev->gadget, hostaddr);
- if (status < 0)
- return status;
+ the_dev = gether_setup(cdev->gadget, hostaddr);
+ if (IS_ERR(the_dev))
+ return PTR_ERR(the_dev);
/* Allocate string descriptor numbers ... note that string
* contents can be overridden by the composite_dev glue.
@@ -168,13 +169,13 @@ static int __init gncm_bind(struct usb_composite_dev *cdev)
return 0;
fail:
- gether_cleanup();
+ gether_cleanup(the_dev);
return status;
}
static int __exit gncm_unbind(struct usb_composite_dev *cdev)
{
- gether_cleanup();
+ gether_cleanup(the_dev);
return 0;
}
diff --git a/drivers/usb/gadget/net2272.c b/drivers/usb/gadget/net2272.c
index d226058e3b8..f1e50a3e322 100644
--- a/drivers/usb/gadget/net2272.c
+++ b/drivers/usb/gadget/net2272.c
@@ -58,8 +58,7 @@ static const char * const ep_name[] = {
"ep-a", "ep-b", "ep-c",
};
-#define DMA_ADDR_INVALID (~(dma_addr_t)0)
-#ifdef CONFIG_USB_GADGET_NET2272_DMA
+#ifdef CONFIG_USB_NET2272_DMA
/*
* use_dma: the NET2272 can use an external DMA controller.
* Note that since there is no generic DMA api, some functions,
@@ -341,7 +340,6 @@ net2272_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags)
if (!req)
return NULL;
- req->req.dma = DMA_ADDR_INVALID;
INIT_LIST_HEAD(&req->queue);
return &req->req;
@@ -913,7 +911,7 @@ net2272_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
}
}
}
- if (likely(req != 0))
+ if (likely(req))
list_add_tail(&req->queue, &ep->queue);
if (likely(!list_empty(&ep->queue)))
@@ -1467,7 +1465,6 @@ static int net2272_start(struct usb_gadget *_gadget,
dev->softconnect = 1;
driver->driver.bus = NULL;
dev->driver = driver;
- dev->gadget.dev.driver = &driver->driver;
/* ... then enable host detection and ep0; and we're ready
* for set_configuration as well as eventual disconnect.
@@ -1495,6 +1492,13 @@ stop_activity(struct net2272 *dev, struct usb_gadget_driver *driver)
for (i = 0; i < 4; ++i)
net2272_dequeue_all(&dev->ep[i]);
+ /* report disconnect; the driver is already quiesced */
+ if (driver) {
+ spin_unlock(&dev->lock);
+ driver->disconnect(&dev->gadget);
+ spin_lock(&dev->lock);
+ }
+
net2272_usb_reinit(dev);
}
@@ -1510,7 +1514,6 @@ static int net2272_stop(struct usb_gadget *_gadget,
stop_activity(dev, driver);
spin_unlock_irqrestore(&dev->lock, flags);
- dev->gadget.dev.driver = NULL;
dev->driver = NULL;
dev_dbg(dev->dev, "unregistered driver '%s'\n", driver->driver.name);
@@ -1542,7 +1545,7 @@ net2272_handle_dma(struct net2272_ep *ep)
| (ep->dev->dma_eot_polarity << EOT_POLARITY)
| (ep->dev->dma_dack_polarity << DACK_POLARITY)
| (ep->dev->dma_dreq_polarity << DREQ_POLARITY)
- | ((ep->dma >> 1) << DMA_ENDPOINT_SELECT));
+ | (ep->dma << DMA_ENDPOINT_SELECT));
ep->dev->dma_busy = 0;
@@ -1615,7 +1618,7 @@ net2272_handle_ep(struct net2272_ep *ep)
ep->irqs++;
dev_vdbg(ep->dev->dev, "%s ack ep_stat0 %02x, ep_stat1 %02x, req %p\n",
- ep->ep.name, stat0, stat1, req ? &req->req : 0);
+ ep->ep.name, stat0, stat1, req ? &req->req : NULL);
net2272_ep_write(ep, EP_STAT0, stat0 &
~((1 << NAK_OUT_PACKETS)
@@ -2209,7 +2212,6 @@ net2272_remove(struct net2272 *dev)
free_irq(dev->irq, dev);
iounmap(dev->base_addr);
- device_unregister(&dev->gadget.dev);
device_remove_file(dev->dev, &dev_attr_registers);
dev_info(dev->dev, "unbind\n");
@@ -2236,10 +2238,6 @@ static struct net2272 *net2272_probe_init(struct device *dev, unsigned int irq)
ret->gadget.max_speed = USB_SPEED_HIGH;
/* the "gadget" abstracts/virtualizes the controller */
- dev_set_name(&ret->gadget.dev, "gadget");
- ret->gadget.dev.parent = dev;
- ret->gadget.dev.dma_mask = dev->dma_mask;
- ret->gadget.dev.release = net2272_gadget_release;
ret->gadget.name = driver_name;
return ret;
@@ -2275,14 +2273,12 @@ net2272_probe_fin(struct net2272 *dev, unsigned int irqflags)
dma_mode_string());
dev_info(dev->dev, "version: %s\n", driver_vers);
- ret = device_register(&dev->gadget.dev);
- if (ret)
- goto err_irq;
ret = device_create_file(dev->dev, &dev_attr_registers);
if (ret)
- goto err_dev_reg;
+ goto err_irq;
- ret = usb_add_gadget_udc(dev->dev, &dev->gadget);
+ ret = usb_add_gadget_udc_release(dev->dev, &dev->gadget,
+ net2272_gadget_release);
if (ret)
goto err_add_udc;
@@ -2290,8 +2286,6 @@ net2272_probe_fin(struct net2272 *dev, unsigned int irqflags)
err_add_udc:
device_remove_file(dev->dev, &dev_attr_registers);
- err_dev_reg:
- device_unregister(&dev->gadget.dev);
err_irq:
free_irq(dev->irq, dev);
err:
diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c
index a1b650e1133..fbd006ab31d 100644
--- a/drivers/usb/gadget/net2280.c
+++ b/drivers/usb/gadget/net2280.c
@@ -65,7 +65,6 @@
#define DRIVER_DESC "PLX NET228x USB Peripheral Controller"
#define DRIVER_VERSION "2005 Sept 27"
-#define DMA_ADDR_INVALID (~(dma_addr_t)0)
#define EP_DONTUSE 13 /* nonzero */
#define USE_RDK_LEDS /* GPIO pins control three LEDs */
@@ -406,7 +405,6 @@ net2280_alloc_request (struct usb_ep *_ep, gfp_t gfp_flags)
if (!req)
return NULL;
- req->req.dma = DMA_ADDR_INVALID;
INIT_LIST_HEAD (&req->queue);
/* this dma descriptor may be swapped with the previous dummy */
@@ -420,7 +418,6 @@ net2280_alloc_request (struct usb_ep *_ep, gfp_t gfp_flags)
return NULL;
}
td->dmacount = 0; /* not VALID */
- td->dmaaddr = cpu_to_le32 (DMA_ADDR_INVALID);
td->dmadesc = td->dmaaddr;
req->td = td;
}
@@ -1896,7 +1893,6 @@ static int net2280_start(struct usb_gadget *_gadget,
dev->softconnect = 1;
driver->driver.bus = NULL;
dev->driver = driver;
- dev->gadget.dev.driver = &driver->driver;
retval = device_create_file (&dev->pdev->dev, &dev_attr_function);
if (retval) goto err_unbind;
@@ -1924,8 +1920,6 @@ static int net2280_start(struct usb_gadget *_gadget,
err_func:
device_remove_file (&dev->pdev->dev, &dev_attr_function);
err_unbind:
- driver->unbind (&dev->gadget);
- dev->gadget.dev.driver = NULL;
dev->driver = NULL;
return retval;
}
@@ -1946,6 +1940,13 @@ stop_activity (struct net2280 *dev, struct usb_gadget_driver *driver)
for (i = 0; i < 7; i++)
nuke (&dev->ep [i]);
+ /* report disconnect; the driver is already quiesced */
+ if (driver) {
+ spin_unlock(&dev->lock);
+ driver->disconnect(&dev->gadget);
+ spin_lock(&dev->lock);
+ }
+
usb_reinit (dev);
}
@@ -1961,7 +1962,6 @@ static int net2280_stop(struct usb_gadget *_gadget,
stop_activity (dev, driver);
spin_unlock_irqrestore (&dev->lock, flags);
- dev->gadget.dev.driver = NULL;
dev->driver = NULL;
net2280_led_active (dev, 0);
@@ -2066,7 +2066,7 @@ static void handle_ep_small (struct net2280_ep *ep)
return;
/* manual DMA queue advance after short OUT */
- if (likely (ep->dma != 0)) {
+ if (likely (ep->dma)) {
if (t & (1 << SHORT_PACKET_TRANSFERRED_INTERRUPT)) {
u32 count;
int stopped = ep->stopped;
@@ -2324,7 +2324,7 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat)
/* hw handles device and interface status */
if (u.r.bRequestType != (USB_DIR_IN|USB_RECIP_ENDPOINT))
goto delegate;
- if ((e = get_ep_by_addr (dev, w_index)) == 0
+ if ((e = get_ep_by_addr (dev, w_index)) == NULL
|| w_length > 2)
goto do_stall;
@@ -2352,7 +2352,7 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat)
if (w_value != USB_ENDPOINT_HALT
|| w_length != 0)
goto do_stall;
- if ((e = get_ep_by_addr (dev, w_index)) == 0)
+ if ((e = get_ep_by_addr (dev, w_index)) == NULL)
goto do_stall;
if (e->wedged) {
VDEBUG(dev, "%s wedged, halt not cleared\n",
@@ -2374,7 +2374,7 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat)
if (w_value != USB_ENDPOINT_HALT
|| w_length != 0)
goto do_stall;
- if ((e = get_ep_by_addr (dev, w_index)) == 0)
+ if ((e = get_ep_by_addr (dev, w_index)) == NULL)
goto do_stall;
if (e->ep.name == ep0name)
goto do_stall;
@@ -2679,7 +2679,6 @@ static void net2280_remove (struct pci_dev *pdev)
pci_resource_len (pdev, 0));
if (dev->enabled)
pci_disable_device (pdev);
- device_unregister (&dev->gadget.dev);
device_remove_file (&pdev->dev, &dev_attr_registers);
pci_set_drvdata (pdev, NULL);
@@ -2711,10 +2710,6 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id)
dev->gadget.max_speed = USB_SPEED_HIGH;
/* the "gadget" abstracts/virtualizes the controller */
- dev_set_name(&dev->gadget.dev, "gadget");
- dev->gadget.dev.parent = &pdev->dev;
- dev->gadget.dev.dma_mask = pdev->dev.dma_mask;
- dev->gadget.dev.release = gadget_release;
dev->gadget.name = driver_name;
/* now all the pci goodies ... */
@@ -2796,7 +2791,6 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id)
goto done;
}
td->dmacount = 0; /* not VALID */
- td->dmaaddr = cpu_to_le32 (DMA_ADDR_INVALID);
td->dmadesc = td->dmaaddr;
dev->ep [i].dummy = td;
}
@@ -2823,12 +2817,11 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id)
use_dma
? (use_dma_chaining ? "chaining" : "enabled")
: "disabled");
- retval = device_register (&dev->gadget.dev);
- if (retval) goto done;
retval = device_create_file (&pdev->dev, &dev_attr_registers);
if (retval) goto done;
- retval = usb_add_gadget_udc(&pdev->dev, &dev->gadget);
+ retval = usb_add_gadget_udc_release(&pdev->dev, &dev->gadget,
+ gadget_release);
if (retval)
goto done;
return 0;
diff --git a/drivers/usb/gadget/nokia.c b/drivers/usb/gadget/nokia.c
index def37403989..3b344b41a16 100644
--- a/drivers/usb/gadget/nokia.c
+++ b/drivers/usb/gadget/nokia.c
@@ -37,11 +37,9 @@
* the runtime footprint, and giving us at least some parts of what
* a "gcc --combine ... part1.c part2.c part3.c ... " build would.
*/
-#define USB_FACM_INCLUDED
-#include "f_acm.c"
+#define USBF_OBEX_INCLUDED
#include "f_ecm.c"
#include "f_obex.c"
-#include "f_serial.c"
#include "f_phonet.c"
#include "u_ether.c"
@@ -98,20 +96,40 @@ MODULE_AUTHOR("Felipe Balbi");
MODULE_LICENSE("GPL");
/*-------------------------------------------------------------------------*/
-
+static struct usb_function *f_acm_cfg1;
+static struct usb_function *f_acm_cfg2;
static u8 hostaddr[ETH_ALEN];
+static struct eth_dev *the_dev;
enum {
TTY_PORT_OBEX0,
TTY_PORT_OBEX1,
- TTY_PORT_ACM,
TTY_PORTS_MAX,
};
static unsigned char tty_lines[TTY_PORTS_MAX];
+static struct usb_configuration nokia_config_500ma_driver = {
+ .label = "Bus Powered",
+ .bConfigurationValue = 1,
+ /* .iConfiguration = DYNAMIC */
+ .bmAttributes = USB_CONFIG_ATT_ONE,
+ .MaxPower = 500,
+};
+
+static struct usb_configuration nokia_config_100ma_driver = {
+ .label = "Self Powered",
+ .bConfigurationValue = 2,
+ /* .iConfiguration = DYNAMIC */
+ .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
+ .MaxPower = 100,
+};
+
+static struct usb_function_instance *fi_acm;
+
static int __init nokia_bind_config(struct usb_configuration *c)
{
+ struct usb_function *f_acm;
int status = 0;
status = phonet_bind_config(c);
@@ -126,33 +144,32 @@ static int __init nokia_bind_config(struct usb_configuration *c)
if (status)
printk(KERN_DEBUG "could not bind obex config %d\n", 0);
- status = acm_bind_config(c, tty_lines[TTY_PORT_ACM]);
- if (status)
- printk(KERN_DEBUG "could not bind acm config\n");
+ f_acm = usb_get_function(fi_acm);
+ if (IS_ERR(f_acm))
+ return PTR_ERR(f_acm);
- status = ecm_bind_config(c, hostaddr);
+ status = usb_add_function(c, f_acm);
if (status)
- printk(KERN_DEBUG "could not bind ecm config\n");
+ goto err_conf;
+
+ status = ecm_bind_config(c, hostaddr, the_dev);
+ if (status) {
+ pr_debug("could not bind ecm config %d\n", status);
+ goto err_ecm;
+ }
+ if (c == &nokia_config_500ma_driver)
+ f_acm_cfg1 = f_acm;
+ else
+ f_acm_cfg2 = f_acm;
return status;
+err_ecm:
+ usb_remove_function(c, f_acm);
+err_conf:
+ usb_put_function(f_acm);
+ return status;
}
-static struct usb_configuration nokia_config_500ma_driver = {
- .label = "Bus Powered",
- .bConfigurationValue = 1,
- /* .iConfiguration = DYNAMIC */
- .bmAttributes = USB_CONFIG_ATT_ONE,
- .MaxPower = 500,
-};
-
-static struct usb_configuration nokia_config_100ma_driver = {
- .label = "Self Powered",
- .bConfigurationValue = 2,
- /* .iConfiguration = DYNAMIC */
- .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
- .MaxPower = 100,
-};
-
static int __init nokia_bind(struct usb_composite_dev *cdev)
{
struct usb_gadget *gadget = cdev->gadget;
@@ -169,9 +186,11 @@ static int __init nokia_bind(struct usb_composite_dev *cdev)
goto err_ether;
}
- status = gether_setup(cdev->gadget, hostaddr);
- if (status < 0)
+ the_dev = gether_setup(cdev->gadget, hostaddr);
+ if (IS_ERR(the_dev)) {
+ status = PTR_ERR(the_dev);
goto err_ether;
+ }
status = usb_string_ids_tab(cdev, strings_dev);
if (status < 0)
@@ -185,24 +204,32 @@ static int __init nokia_bind(struct usb_composite_dev *cdev)
if (!gadget_supports_altsettings(gadget))
goto err_usb;
+ fi_acm = usb_get_function_instance("acm");
+ if (IS_ERR(fi_acm))
+ goto err_usb;
+
/* finally register the configuration */
status = usb_add_config(cdev, &nokia_config_500ma_driver,
nokia_bind_config);
if (status < 0)
- goto err_usb;
+ goto err_acm_inst;
status = usb_add_config(cdev, &nokia_config_100ma_driver,
nokia_bind_config);
if (status < 0)
- goto err_usb;
+ goto err_put_cfg1;
usb_composite_overwrite_options(cdev, &coverwrite);
dev_info(&gadget->dev, "%s\n", NOKIA_LONG_NAME);
return 0;
+err_put_cfg1:
+ usb_put_function(f_acm_cfg1);
+err_acm_inst:
+ usb_put_function_instance(fi_acm);
err_usb:
- gether_cleanup();
+ gether_cleanup(the_dev);
err_ether:
cur_line--;
while (cur_line >= 0)
@@ -217,12 +244,15 @@ static int __exit nokia_unbind(struct usb_composite_dev *cdev)
{
int i;
+ usb_put_function(f_acm_cfg1);
+ usb_put_function(f_acm_cfg2);
+ usb_put_function_instance(fi_acm);
gphonet_cleanup();
for (i = 0; i < TTY_PORTS_MAX; i++)
gserial_free_line(tty_lines[i]);
- gether_cleanup();
+ gether_cleanup(the_dev);
return 0;
}
@@ -247,4 +277,3 @@ static void __exit nokia_cleanup(void)
usb_composite_unregister(&nokia_driver);
}
module_exit(nokia_cleanup);
-
diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c
index 06be85c2b23..b8ed74a823c 100644
--- a/drivers/usb/gadget/omap_udc.c
+++ b/drivers/usb/gadget/omap_udc.c
@@ -62,6 +62,7 @@
#define DRIVER_VERSION "4 October 2004"
#define OMAP_DMA_USB_W2FC_TX0 29
+#define OMAP_DMA_USB_W2FC_RX0 26
/*
* The OMAP UDC needs _very_ early endpoint setup: before enabling the
@@ -1310,7 +1311,7 @@ static int omap_pullup(struct usb_gadget *gadget, int is_on)
}
static int omap_udc_start(struct usb_gadget *g,
- struct usb_gadget_driver *driver)
+ struct usb_gadget_driver *driver);
static int omap_udc_stop(struct usb_gadget *g,
struct usb_gadget_driver *driver);
@@ -2066,7 +2067,6 @@ static int omap_udc_start(struct usb_gadget *g,
/* hook up the driver */
driver->driver.bus = NULL;
udc->driver = driver;
- udc->gadget.dev.driver = &driver->driver;
spin_unlock_irqrestore(&udc->lock, flags);
if (udc->dc_clk != NULL)
@@ -2082,7 +2082,6 @@ static int omap_udc_start(struct usb_gadget *g,
ERR("can't bind to transceiver\n");
if (driver->unbind) {
driver->unbind(&udc->gadget);
- udc->gadget.dev.driver = NULL;
udc->driver = NULL;
}
goto done;
@@ -2128,7 +2127,6 @@ static int omap_udc_stop(struct usb_gadget *g,
udc_quiesce(udc);
spin_unlock_irqrestore(&udc->lock, flags);
- udc->gadget.dev.driver = NULL;
udc->driver = NULL;
if (udc->dc_clk != NULL)
@@ -2630,14 +2628,6 @@ omap_udc_setup(struct platform_device *odev, struct usb_phy *xceiv)
udc->gadget.speed = USB_SPEED_UNKNOWN;
udc->gadget.max_speed = USB_SPEED_FULL;
udc->gadget.name = driver_name;
-
- device_initialize(&udc->gadget.dev);
- dev_set_name(&udc->gadget.dev, "gadget");
- udc->gadget.dev.release = omap_udc_release;
- udc->gadget.dev.parent = &odev->dev;
- if (use_dma)
- udc->gadget.dev.dma_mask = odev->dev.dma_mask;
-
udc->transceiver = xceiv;
/* ep0 is special; put it right after the SETUP buffer */
@@ -2911,14 +2901,13 @@ bad_on_1710:
}
create_proc_file();
- status = device_add(&udc->gadget.dev);
+ status = usb_add_gadget_udc_release(&pdev->dev, &udc->gadget,
+ omap_udc_release);
if (status)
goto cleanup4;
- status = usb_add_gadget_udc(&pdev->dev, &udc->gadget);
- if (!status)
- return status;
- /* If fail, fall through */
+ return 0;
+
cleanup4:
remove_proc_file();
@@ -2989,7 +2978,6 @@ static int omap_udc_remove(struct platform_device *pdev)
release_mem_region(pdev->resource[0].start,
pdev->resource[0].end - pdev->resource[0].start + 1);
- device_unregister(&udc->gadget.dev);
wait_for_completion(&done);
return 0;
diff --git a/drivers/usb/gadget/pch_udc.c b/drivers/usb/gadget/pch_udc.c
index a787a8ef672..24174e1d156 100644
--- a/drivers/usb/gadget/pch_udc.c
+++ b/drivers/usb/gadget/pch_udc.c
@@ -358,7 +358,6 @@ struct pch_udc_dev {
prot_stall:1,
irq_registered:1,
mem_region:1,
- registered:1,
suspended:1,
connected:1,
vbus_session:1,
@@ -1441,6 +1440,8 @@ static void pch_vbus_gpio_free(struct pch_udc_dev *dev)
*/
static void complete_req(struct pch_udc_ep *ep, struct pch_udc_request *req,
int status)
+ __releases(&dev->lock)
+ __acquires(&dev->lock)
{
struct pch_udc_dev *dev;
unsigned halted = ep->halted;
@@ -2382,6 +2383,8 @@ static void pch_udc_svc_control_in(struct pch_udc_dev *dev)
* @dev: Reference to the device structure
*/
static void pch_udc_svc_control_out(struct pch_udc_dev *dev)
+ __releases(&dev->lock)
+ __acquires(&dev->lock)
{
u32 stat;
int setup_supported;
@@ -2989,7 +2992,6 @@ static int pch_udc_start(struct usb_gadget *g,
driver->driver.bus = NULL;
dev->driver = driver;
- dev->gadget.dev.driver = &driver->driver;
/* get ready for ep0 traffic */
pch_udc_setup_ep0(dev);
@@ -3010,7 +3012,6 @@ static int pch_udc_stop(struct usb_gadget *g,
pch_udc_disable_interrupts(dev, UDC_DEVINT_MSK);
/* Assures that there are no pending requests with this driver */
- dev->gadget.dev.driver = NULL;
dev->driver = NULL;
dev->connected = 0;
@@ -3078,8 +3079,6 @@ static void pch_udc_remove(struct pci_dev *pdev)
pci_resource_len(pdev, PCH_UDC_PCI_BAR));
if (dev->active)
pci_disable_device(pdev);
- if (dev->registered)
- device_unregister(&dev->gadget.dev);
kfree(dev);
pci_set_drvdata(pdev, NULL);
}
@@ -3196,21 +3195,13 @@ static int pch_udc_probe(struct pci_dev *pdev,
if (retval)
goto finished;
- dev_set_name(&dev->gadget.dev, "gadget");
- dev->gadget.dev.parent = &pdev->dev;
- dev->gadget.dev.dma_mask = pdev->dev.dma_mask;
- dev->gadget.dev.release = gadget_release;
dev->gadget.name = KBUILD_MODNAME;
dev->gadget.max_speed = USB_SPEED_HIGH;
- retval = device_register(&dev->gadget.dev);
- if (retval)
- goto finished;
- dev->registered = 1;
-
/* Put the device in disconnected state till a driver is bound */
pch_udc_set_disconnect(dev);
- retval = usb_add_gadget_udc(&pdev->dev, &dev->gadget);
+ retval = usb_add_gadget_udc_release(&pdev->dev, &dev->gadget,
+ gadget_release);
if (retval)
goto finished;
return 0;
diff --git a/drivers/usb/gadget/pxa25x_udc.c b/drivers/usb/gadget/pxa25x_udc.c
index 2bbcdce942d..ef47495dec8 100644
--- a/drivers/usb/gadget/pxa25x_udc.c
+++ b/drivers/usb/gadget/pxa25x_udc.c
@@ -1263,16 +1263,8 @@ static int pxa25x_udc_start(struct usb_gadget *g,
/* first hook up the driver ... */
dev->driver = driver;
- dev->gadget.dev.driver = &driver->driver;
dev->pullup = 1;
- retval = device_add (&dev->gadget.dev);
- if (retval) {
- dev->driver = NULL;
- dev->gadget.dev.driver = NULL;
- return retval;
- }
-
/* ... then enable host detection and ep0; and we're ready
* for set_configuration as well as eventual disconnect.
*/
@@ -1310,6 +1302,10 @@ stop_activity(struct pxa25x_udc *dev, struct usb_gadget_driver *driver)
}
del_timer_sync(&dev->timer);
+ /* report disconnect; the driver is already quiesced */
+ if (driver)
+ driver->disconnect(&dev->gadget);
+
/* re-init driver-visible data structures */
udc_reinit(dev);
}
@@ -1328,10 +1324,8 @@ static int pxa25x_udc_stop(struct usb_gadget*g,
if (!IS_ERR_OR_NULL(dev->transceiver))
(void) otg_set_peripheral(dev->transceiver->otg, NULL);
- dev->gadget.dev.driver = NULL;
dev->driver = NULL;
- device_del (&dev->gadget.dev);
dump_state(dev);
return 0;
@@ -2142,10 +2136,6 @@ static int __init pxa25x_udc_probe(struct platform_device *pdev)
dev->timer.function = udc_watchdog;
dev->timer.data = (unsigned long) dev;
- device_initialize(&dev->gadget.dev);
- dev->gadget.dev.parent = &pdev->dev;
- dev->gadget.dev.dma_mask = pdev->dev.dma_mask;
-
the_controller = dev;
platform_set_drvdata(pdev, dev);
@@ -2217,10 +2207,10 @@ static int __exit pxa25x_udc_remove(struct platform_device *pdev)
{
struct pxa25x_udc *dev = platform_get_drvdata(pdev);
- usb_del_gadget_udc(&dev->gadget);
if (dev->driver)
return -EBUSY;
+ usb_del_gadget_udc(&dev->gadget);
dev->pullup = 0;
pullup(dev);
diff --git a/drivers/usb/gadget/pxa27x_udc.c b/drivers/usb/gadget/pxa27x_udc.c
index f7d25795821..6b4c7d95853 100644
--- a/drivers/usb/gadget/pxa27x_udc.c
+++ b/drivers/usb/gadget/pxa27x_udc.c
@@ -24,14 +24,12 @@
#include <linux/gpio.h>
#include <linux/slab.h>
#include <linux/prefetch.h>
-
-#include <asm/byteorder.h>
-#include <mach/hardware.h>
+#include <linux/byteorder/generic.h>
+#include <linux/platform_data/pxa2xx_udc.h>
#include <linux/usb.h>
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
-#include <mach/udc.h>
#include "pxa27x_udc.h"
@@ -611,7 +609,7 @@ static void inc_ep_stats_bytes(struct pxa_ep *ep, int count, int is_in)
*
* Find the physical pxa27x ep, and setup its UDCCR
*/
-static __init void pxa_ep_setup(struct pxa_ep *ep)
+static void pxa_ep_setup(struct pxa_ep *ep)
{
u32 new_udccr;
@@ -633,7 +631,7 @@ static __init void pxa_ep_setup(struct pxa_ep *ep)
*
* Setup all pxa physical endpoints, except ep0
*/
-static __init void pxa_eps_setup(struct pxa_udc *dev)
+static void pxa_eps_setup(struct pxa_udc *dev)
{
unsigned int i;
@@ -1718,7 +1716,7 @@ static void udc_disable(struct pxa_udc *udc)
* Initializes gadget endpoint list, endpoints locks. No action is taken
* on the hardware.
*/
-static __init void udc_init_data(struct pxa_udc *dev)
+static void udc_init_data(struct pxa_udc *dev)
{
int i;
struct pxa_ep *ep;
@@ -1811,14 +1809,8 @@ static int pxa27x_udc_start(struct usb_gadget *g,
/* first hook up the driver ... */
udc->driver = driver;
- udc->gadget.dev.driver = &driver->driver;
dplus_pullup(udc, 1);
- retval = device_add(&udc->gadget.dev);
- if (retval) {
- dev_err(udc->dev, "device_add error %d\n", retval);
- goto fail;
- }
if (!IS_ERR_OR_NULL(udc->transceiver)) {
retval = otg_set_peripheral(udc->transceiver->otg,
&udc->gadget);
@@ -1834,7 +1826,6 @@ static int pxa27x_udc_start(struct usb_gadget *g,
fail:
udc->driver = NULL;
- udc->gadget.dev.driver = NULL;
return retval;
}
@@ -1876,8 +1867,6 @@ static int pxa27x_udc_stop(struct usb_gadget *g,
udc->driver = NULL;
- device_del(&udc->gadget.dev);
-
if (!IS_ERR_OR_NULL(udc->transceiver))
return otg_set_peripheral(udc->transceiver->otg, NULL);
return 0;
@@ -2419,7 +2408,7 @@ static struct pxa_udc memory = {
* Perform basic init : allocates udc clock, creates sysfs files, requests
* irq.
*/
-static int __init pxa_udc_probe(struct platform_device *pdev)
+static int pxa_udc_probe(struct platform_device *pdev)
{
struct resource *regs;
struct pxa_udc *udc = &memory;
@@ -2462,9 +2451,6 @@ static int __init pxa_udc_probe(struct platform_device *pdev)
goto err_map;
}
- device_initialize(&udc->gadget.dev);
- udc->gadget.dev.parent = &pdev->dev;
- udc->gadget.dev.dma_mask = NULL;
udc->vbus_sensed = 0;
the_controller = udc;
@@ -2480,12 +2466,15 @@ static int __init pxa_udc_probe(struct platform_device *pdev)
driver_name, udc->irq, retval);
goto err_irq;
}
+
retval = usb_add_gadget_udc(&pdev->dev, &udc->gadget);
if (retval)
goto err_add_udc;
pxa_init_debugfs(udc);
+
return 0;
+
err_add_udc:
free_irq(udc->irq, udc);
err_irq:
@@ -2501,7 +2490,7 @@ err_clk:
* pxa_udc_remove - removes the udc device driver
* @_dev: platform device
*/
-static int __exit pxa_udc_remove(struct platform_device *_dev)
+static int pxa_udc_remove(struct platform_device *_dev)
{
struct pxa_udc *udc = platform_get_drvdata(_dev);
int gpio = udc->mach->gpio_pullup;
@@ -2619,7 +2608,8 @@ static struct platform_driver udc_driver = {
.name = "pxa27x-udc",
.owner = THIS_MODULE,
},
- .remove = __exit_p(pxa_udc_remove),
+ .probe = pxa_udc_probe,
+ .remove = pxa_udc_remove,
.shutdown = pxa_udc_shutdown,
#ifdef CONFIG_PM
.suspend = pxa_udc_suspend,
@@ -2627,22 +2617,7 @@ static struct platform_driver udc_driver = {
#endif
};
-static int __init udc_init(void)
-{
- if (!cpu_is_pxa27x() && !cpu_is_pxa3xx())
- return -ENODEV;
-
- printk(KERN_INFO "%s: version %s\n", driver_name, DRIVER_VERSION);
- return platform_driver_probe(&udc_driver, pxa_udc_probe);
-}
-module_init(udc_init);
-
-
-static void __exit udc_exit(void)
-{
- platform_driver_unregister(&udc_driver);
-}
-module_exit(udc_exit);
+module_platform_driver(udc_driver);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_AUTHOR("Robert Jarzmik");
diff --git a/drivers/usb/gadget/r8a66597-udc.c b/drivers/usb/gadget/r8a66597-udc.c
index f46a1b77ce3..0b742d17184 100644
--- a/drivers/usb/gadget/r8a66597-udc.c
+++ b/drivers/usb/gadget/r8a66597-udc.c
@@ -1837,7 +1837,6 @@ static int __exit r8a66597_remove(struct platform_device *pdev)
clk_put(r8a66597->clk);
}
- device_unregister(&r8a66597->gadget.dev);
kfree(r8a66597);
return 0;
}
@@ -1915,17 +1914,8 @@ static int __init r8a66597_probe(struct platform_device *pdev)
r8a66597->irq_sense_low = irq_trigger == IRQF_TRIGGER_LOW;
r8a66597->gadget.ops = &r8a66597_gadget_ops;
- dev_set_name(&r8a66597->gadget.dev, "gadget");
r8a66597->gadget.max_speed = USB_SPEED_HIGH;
- r8a66597->gadget.dev.parent = &pdev->dev;
- r8a66597->gadget.dev.dma_mask = pdev->dev.dma_mask;
- r8a66597->gadget.dev.release = pdev->dev.release;
r8a66597->gadget.name = udc_name;
- ret = device_register(&r8a66597->gadget.dev);
- if (ret < 0) {
- dev_err(&pdev->dev, "device_register failed\n");
- goto clean_up;
- }
init_timer(&r8a66597->timer);
r8a66597->timer.function = r8a66597_timer;
@@ -1939,7 +1929,7 @@ static int __init r8a66597_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "cannot get clock \"%s\"\n",
clk_name);
ret = PTR_ERR(r8a66597->clk);
- goto clean_up_dev;
+ goto clean_up;
}
clk_enable(r8a66597->clk);
}
@@ -2007,8 +1997,6 @@ clean_up2:
clk_disable(r8a66597->clk);
clk_put(r8a66597->clk);
}
-clean_up_dev:
- device_unregister(&r8a66597->gadget.dev);
clean_up:
if (r8a66597) {
if (r8a66597->sudmac_reg)
diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c
index c26564f29a2..a3cdc32115d 100644
--- a/drivers/usb/gadget/s3c-hsotg.c
+++ b/drivers/usb/gadget/s3c-hsotg.c
@@ -39,8 +39,6 @@
#include "s3c-hsotg.h"
-#define DMA_ADDR_INVALID (~((dma_addr_t)0))
-
static const char * const s3c_hsotg_supply_names[] = {
"vusb_d", /* digital USB supply, 1.2V */
"vusb_a", /* analog USB supply, 1.1V */
@@ -405,7 +403,6 @@ static struct usb_request *s3c_hsotg_ep_alloc_request(struct usb_ep *ep,
INIT_LIST_HEAD(&req->queue);
- req->req.dma = DMA_ADDR_INVALID;
return &req->req;
}
@@ -435,24 +432,12 @@ static void s3c_hsotg_unmap_dma(struct s3c_hsotg *hsotg,
struct s3c_hsotg_req *hs_req)
{
struct usb_request *req = &hs_req->req;
- enum dma_data_direction dir;
-
- dir = hs_ep->dir_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
/* ignore this if we're not moving any data */
if (hs_req->req.length == 0)
return;
- if (hs_req->mapped) {
- /* we mapped this, so unmap and remove the dma */
-
- dma_unmap_single(hsotg->dev, req->dma, req->length, dir);
-
- req->dma = DMA_ADDR_INVALID;
- hs_req->mapped = 0;
- } else {
- dma_sync_single_for_cpu(hsotg->dev, req->dma, req->length, dir);
- }
+ usb_gadget_unmap_request(&hsotg->gadget, hs_req, hs_ep->dir_in);
}
/**
@@ -852,37 +837,16 @@ static int s3c_hsotg_map_dma(struct s3c_hsotg *hsotg,
struct s3c_hsotg_ep *hs_ep,
struct usb_request *req)
{
- enum dma_data_direction dir;
struct s3c_hsotg_req *hs_req = our_req(req);
-
- dir = hs_ep->dir_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+ int ret;
/* if the length is zero, ignore the DMA data */
if (hs_req->req.length == 0)
return 0;
- if (req->dma == DMA_ADDR_INVALID) {
- dma_addr_t dma;
-
- dma = dma_map_single(hsotg->dev, req->buf, req->length, dir);
-
- if (unlikely(dma_mapping_error(hsotg->dev, dma)))
- goto dma_error;
-
- if (dma & 3) {
- dev_err(hsotg->dev, "%s: unaligned dma buffer\n",
- __func__);
-
- dma_unmap_single(hsotg->dev, dma, req->length, dir);
- return -EINVAL;
- }
-
- hs_req->mapped = 1;
- req->dma = dma;
- } else {
- dma_sync_single_for_cpu(hsotg->dev, req->dma, req->length, dir);
- hs_req->mapped = 0;
- }
+ ret = usb_gadget_map_request(&hsotg->gadget, req, hs_ep->dir_in);
+ if (ret)
+ goto dma_error;
return 0;
@@ -2961,9 +2925,7 @@ static int s3c_hsotg_udc_start(struct usb_gadget *gadget,
driver->driver.bus = NULL;
hsotg->driver = driver;
- hsotg->gadget.dev.driver = &driver->driver;
hsotg->gadget.dev.of_node = hsotg->dev->of_node;
- hsotg->gadget.dev.dma_mask = hsotg->dev->dma_mask;
hsotg->gadget.speed = USB_SPEED_UNKNOWN;
ret = regulator_bulk_enable(ARRAY_SIZE(hsotg->supplies),
@@ -2979,7 +2941,6 @@ static int s3c_hsotg_udc_start(struct usb_gadget *gadget,
err:
hsotg->driver = NULL;
- hsotg->gadget.dev.driver = NULL;
return ret;
}
@@ -3014,7 +2975,6 @@ static int s3c_hsotg_udc_stop(struct usb_gadget *gadget,
hsotg->driver = NULL;
hsotg->gadget.speed = USB_SPEED_UNKNOWN;
- hsotg->gadget.dev.driver = NULL;
spin_unlock_irqrestore(&hsotg->lock, flags);
@@ -3484,16 +3444,6 @@ static void s3c_hsotg_delete_debug(struct s3c_hsotg *hsotg)
}
/**
- * s3c_hsotg_release - release callback for hsotg device
- * @dev: Device to for which release is called
- *
- * Nothing to do as the resource is allocated using devm_ API.
- */
-static void s3c_hsotg_release(struct device *dev)
-{
-}
-
-/**
* s3c_hsotg_probe - probe function for hsotg driver
* @pdev: The platform information for the driver
*/
@@ -3517,7 +3467,7 @@ static int s3c_hsotg_probe(struct platform_device *pdev)
}
phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
- if (IS_ERR_OR_NULL(phy)) {
+ if (IS_ERR(phy)) {
/* Fallback for pdata */
plat = pdev->dev.platform_data;
if (!plat) {
@@ -3567,18 +3517,10 @@ static int s3c_hsotg_probe(struct platform_device *pdev)
dev_info(dev, "regs %p, irq %d\n", hsotg->regs, hsotg->irq);
- device_initialize(&hsotg->gadget.dev);
-
- dev_set_name(&hsotg->gadget.dev, "gadget");
-
hsotg->gadget.max_speed = USB_SPEED_HIGH;
hsotg->gadget.ops = &s3c_hsotg_gadget_ops;
hsotg->gadget.name = dev_name(dev);
- hsotg->gadget.dev.parent = dev;
- hsotg->gadget.dev.dma_mask = dev->dma_mask;
- hsotg->gadget.dev.release = s3c_hsotg_release;
-
/* reset the system */
clk_prepare_enable(hsotg->clk);
@@ -3658,12 +3600,6 @@ static int s3c_hsotg_probe(struct platform_device *pdev)
s3c_hsotg_phy_disable(hsotg);
- ret = device_add(&hsotg->gadget.dev);
- if (ret) {
- put_device(&hsotg->gadget.dev);
- goto err_ep_mem;
- }
-
ret = usb_add_gadget_udc(&pdev->dev, &hsotg->gadget);
if (ret)
goto err_ep_mem;
@@ -3702,10 +3638,8 @@ static int s3c_hsotg_remove(struct platform_device *pdev)
}
s3c_hsotg_phy_disable(hsotg);
-
clk_disable_unprepare(hsotg->clk);
- device_unregister(&hsotg->gadget.dev);
return 0;
}
diff --git a/drivers/usb/gadget/s3c-hsudc.c b/drivers/usb/gadget/s3c-hsudc.c
index 458965a1b13..b1f0771fbd3 100644
--- a/drivers/usb/gadget/s3c-hsudc.c
+++ b/drivers/usb/gadget/s3c-hsudc.c
@@ -283,7 +283,6 @@ static void s3c_hsudc_nuke_ep(struct s3c_hsudc_ep *hsep, int status)
/**
* s3c_hsudc_stop_activity - Stop activity on all endpoints.
* @hsudc: Device controller for which EP activity is to be stopped.
- * @driver: Reference to the gadget driver which is currently active.
*
* All the endpoints are stopped and any pending transfer requests if any on
* the endpoint are terminated.
@@ -1154,7 +1153,6 @@ static int s3c_hsudc_start(struct usb_gadget *gadget,
return -EBUSY;
hsudc->driver = driver;
- hsudc->gadget.dev.driver = &driver->driver;
ret = regulator_bulk_enable(ARRAY_SIZE(hsudc->supplies),
hsudc->supplies);
@@ -1190,7 +1188,6 @@ err_otg:
regulator_bulk_disable(ARRAY_SIZE(hsudc->supplies), hsudc->supplies);
err_supplies:
hsudc->driver = NULL;
- hsudc->gadget.dev.driver = NULL;
return ret;
}
@@ -1208,7 +1205,6 @@ static int s3c_hsudc_stop(struct usb_gadget *gadget,
spin_lock_irqsave(&hsudc->lock, flags);
hsudc->driver = NULL;
- hsudc->gadget.dev.driver = NULL;
hsudc->gadget.speed = USB_SPEED_UNKNOWN;
s3c_hsudc_uninit_phy();
@@ -1303,15 +1299,10 @@ static int s3c_hsudc_probe(struct platform_device *pdev)
spin_lock_init(&hsudc->lock);
- dev_set_name(&hsudc->gadget.dev, "gadget");
-
hsudc->gadget.max_speed = USB_SPEED_HIGH;
hsudc->gadget.ops = &s3c_hsudc_gadget_ops;
hsudc->gadget.name = dev_name(dev);
- hsudc->gadget.dev.parent = dev;
- hsudc->gadget.dev.dma_mask = dev->dma_mask;
hsudc->gadget.ep0 = &hsudc->ep[0].ep;
-
hsudc->gadget.is_otg = 0;
hsudc->gadget.is_a_peripheral = 0;
hsudc->gadget.speed = USB_SPEED_UNKNOWN;
@@ -1345,12 +1336,6 @@ static int s3c_hsudc_probe(struct platform_device *pdev)
disable_irq(hsudc->irq);
local_irq_enable();
- ret = device_register(&hsudc->gadget.dev);
- if (ret) {
- put_device(&hsudc->gadget.dev);
- goto err_add_device;
- }
-
ret = usb_add_gadget_udc(&pdev->dev, &hsudc->gadget);
if (ret)
goto err_add_udc;
@@ -1359,7 +1344,6 @@ static int s3c_hsudc_probe(struct platform_device *pdev)
return 0;
err_add_udc:
- device_unregister(&hsudc->gadget.dev);
err_add_device:
clk_disable(hsudc->uclk);
err_res:
diff --git a/drivers/usb/gadget/s3c2410_udc.c b/drivers/usb/gadget/s3c2410_udc.c
index fc07b438128..d0e75e1b3cc 100644
--- a/drivers/usb/gadget/s3c2410_udc.c
+++ b/drivers/usb/gadget/s3c2410_udc.c
@@ -1668,31 +1668,17 @@ static void s3c2410_udc_enable(struct s3c2410_udc *dev)
static int s3c2410_udc_start(struct usb_gadget *g,
struct usb_gadget_driver *driver)
{
- struct s3c2410_udc *udc = to_s3c2410(g)
- int retval;
+ struct s3c2410_udc *udc = to_s3c2410(g);
dprintk(DEBUG_NORMAL, "%s() '%s'\n", __func__, driver->driver.name);
/* Hook the driver */
udc->driver = driver;
- udc->gadget.dev.driver = &driver->driver;
-
- /* Bind the driver */
- retval = device_add(&udc->gadget.dev);
- if (retval) {
- dev_err(&udc->gadget.dev, "Error in device_add() : %d\n", retval);
- goto register_error;
- }
/* Enable udc */
s3c2410_udc_enable(udc);
return 0;
-
-register_error:
- udc->driver = NULL;
- udc->gadget.dev.driver = NULL;
- return retval;
}
static int s3c2410_udc_stop(struct usb_gadget *g,
@@ -1700,7 +1686,6 @@ static int s3c2410_udc_stop(struct usb_gadget *g,
{
struct s3c2410_udc *udc = to_s3c2410(g);
- device_del(&udc->gadget.dev);
udc->driver = NULL;
/* Disable udc */
@@ -1838,10 +1823,6 @@ static int s3c2410_udc_probe(struct platform_device *pdev)
goto err_mem;
}
- device_initialize(&udc->gadget.dev);
- udc->gadget.dev.parent = &pdev->dev;
- udc->gadget.dev.dma_mask = pdev->dev.dma_mask;
-
the_controller = udc;
platform_set_drvdata(pdev, udc);
@@ -1947,10 +1928,10 @@ static int s3c2410_udc_remove(struct platform_device *pdev)
dev_dbg(&pdev->dev, "%s()\n", __func__);
- usb_del_gadget_udc(&udc->gadget);
if (udc->driver)
return -EBUSY;
+ usb_del_gadget_udc(&udc->gadget);
debugfs_remove(udc->regs_info);
if (udc_info && !udc_info->udc_command &&
diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c
index 68d7bb06ebc..1f5f978d35d 100644
--- a/drivers/usb/gadget/serial.c
+++ b/drivers/usb/gadget/serial.c
@@ -12,6 +12,7 @@
#include <linux/kernel.h>
#include <linux/device.h>
+#include <linux/module.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
@@ -28,18 +29,6 @@
#define GS_VERSION_NAME GS_LONG_NAME " " GS_VERSION_STR
/*-------------------------------------------------------------------------*/
-
-/*
- * Kbuild is not very cooperative with respect to linking separately
- * compiled library objects into one module. So for now we won't use
- * separate compilation ... ensuring init/exit sections work to shrink
- * the runtime footprint, and giving us at least some parts of what
- * a "gcc --combine ... part1.c part2.c part3.c ... " build would.
- */
-#include "f_obex.c"
-#include "f_serial.c"
-
-/*-------------------------------------------------------------------------*/
USB_GADGET_COMPOSITE_OPTIONS();
/* Thanks to NetChip Technologies for donating this product ID.
@@ -126,27 +115,6 @@ module_param(n_ports, uint, 0);
MODULE_PARM_DESC(n_ports, "number of ports to create, default=1");
/*-------------------------------------------------------------------------*/
-static unsigned char tty_lines[MAX_U_SERIAL_PORTS];
-
-static int __init serial_bind_obex_config(struct usb_configuration *c)
-{
- unsigned i;
- int status = 0;
-
- for (i = 0; i < n_ports && status == 0; i++)
- status = obex_bind_config(c, tty_lines[i]);
- return status;
-}
-
-static int __init serial_bind_gser_config(struct usb_configuration *c)
-{
- unsigned i;
- int status = 0;
-
- for (i = 0; i < n_ports && status == 0; i++)
- status = gser_bind_config(c, tty_lines[i]);
- return status;
-}
static struct usb_configuration serial_config_driver = {
/* .label = f(use_acm) */
@@ -169,15 +137,12 @@ static int serial_register_ports(struct usb_composite_dev *cdev,
goto out;
for (i = 0; i < n_ports; i++) {
- struct f_serial_opts *opts;
fi_serial[i] = usb_get_function_instance(f_name);
if (IS_ERR(fi_serial[i])) {
ret = PTR_ERR(fi_serial[i]);
goto fail;
}
- opts = container_of(fi_serial[i], struct f_serial_opts, func_inst);
- opts->port_num = tty_lines[i];
f_serial[i] = usb_get_function(fi_serial[i]);
if (IS_ERR(f_serial[i])) {
@@ -212,13 +177,6 @@ out:
static int __init gs_bind(struct usb_composite_dev *cdev)
{
int status;
- int cur_line;
-
- for (cur_line = 0; cur_line < n_ports; cur_line++) {
- status = gserial_alloc_line(&tty_lines[cur_line]);
- if (status)
- goto fail;
- }
/* Allocate string descriptor numbers ... note that string
* contents can be overridden by the composite_dev glue.
@@ -243,11 +201,12 @@ static int __init gs_bind(struct usb_composite_dev *cdev)
"acm");
usb_ep_autoconfig_reset(cdev->gadget);
} else if (use_obex)
- status = usb_add_config(cdev, &serial_config_driver,
- serial_bind_obex_config);
- else
- status = usb_add_config(cdev, &serial_config_driver,
- serial_bind_gser_config);
+ status = serial_register_ports(cdev, &serial_config_driver,
+ "obex");
+ else {
+ status = serial_register_ports(cdev, &serial_config_driver,
+ "gser");
+ }
if (status < 0)
goto fail;
@@ -257,9 +216,6 @@ static int __init gs_bind(struct usb_composite_dev *cdev)
return 0;
fail:
- cur_line--;
- while (cur_line >= 0)
- gserial_free_line(tty_lines[cur_line--]);
return status;
}
@@ -270,7 +226,6 @@ static int gs_unbind(struct usb_composite_dev *cdev)
for (i = 0; i < n_ports; i++) {
usb_put_function(f_serial[i]);
usb_put_function_instance(fi_serial[i]);
- gserial_free_line(tty_lines[i]);
}
return 0;
}
diff --git a/drivers/usb/gadget/u_ether.c b/drivers/usb/gadget/u_ether.c
index a0aa721d8b2..4b76124ce96 100644
--- a/drivers/usb/gadget/u_ether.c
+++ b/drivers/usb/gadget/u_ether.c
@@ -50,7 +50,6 @@
struct eth_dev {
/* lock is held while accessing port_usb
- * or updating its backlink port_usb->ioport
*/
spinlock_t lock;
struct gether *port_usb;
@@ -729,8 +728,6 @@ static int get_ether_addr(const char *str, u8 *dev_addr)
return 1;
}
-static struct eth_dev *the_dev;
-
static const struct net_device_ops eth_netdev_ops = {
.ndo_open = eth_open,
.ndo_stop = eth_stop,
@@ -758,19 +755,16 @@ static struct device_type gadget_type = {
*
* Returns negative errno, or zero on success
*/
-int gether_setup_name(struct usb_gadget *g, u8 ethaddr[ETH_ALEN],
+struct eth_dev *gether_setup_name(struct usb_gadget *g, u8 ethaddr[ETH_ALEN],
const char *netname)
{
struct eth_dev *dev;
struct net_device *net;
int status;
- if (the_dev)
- return -EBUSY;
-
net = alloc_etherdev(sizeof *dev);
if (!net)
- return -ENOMEM;
+ return ERR_PTR(-ENOMEM);
dev = netdev_priv(net);
spin_lock_init(&dev->lock);
@@ -807,12 +801,11 @@ int gether_setup_name(struct usb_gadget *g, u8 ethaddr[ETH_ALEN],
if (status < 0) {
dev_dbg(&g->dev, "register_netdev failed, %d\n", status);
free_netdev(net);
+ dev = ERR_PTR(status);
} else {
INFO(dev, "MAC %pM\n", net->dev_addr);
INFO(dev, "HOST MAC %pM\n", dev->host_mac);
- the_dev = dev;
-
/* two kinds of host-initiated state changes:
* - iff DATA transfer is active, carrier is "on"
* - tx queueing enabled if open *and* carrier is "on"
@@ -820,7 +813,7 @@ int gether_setup_name(struct usb_gadget *g, u8 ethaddr[ETH_ALEN],
netif_carrier_off(net);
}
- return status;
+ return dev;
}
/**
@@ -829,19 +822,16 @@ int gether_setup_name(struct usb_gadget *g, u8 ethaddr[ETH_ALEN],
*
* This is called to free all resources allocated by @gether_setup().
*/
-void gether_cleanup(void)
+void gether_cleanup(struct eth_dev *dev)
{
- if (!the_dev)
+ if (!dev)
return;
- unregister_netdev(the_dev->net);
- flush_work(&the_dev->work);
- free_netdev(the_dev->net);
-
- the_dev = NULL;
+ unregister_netdev(dev->net);
+ flush_work(&dev->work);
+ free_netdev(dev->net);
}
-
/**
* gether_connect - notify network layer that USB link is active
* @link: the USB link, set up with endpoints, descriptors matching
@@ -860,7 +850,7 @@ void gether_cleanup(void)
*/
struct net_device *gether_connect(struct gether *link)
{
- struct eth_dev *dev = the_dev;
+ struct eth_dev *dev = link->ioport;
int result = 0;
if (!dev)
@@ -895,7 +885,6 @@ struct net_device *gether_connect(struct gether *link)
spin_lock(&dev->lock);
dev->port_usb = link;
- link->ioport = dev;
if (netif_running(dev->net)) {
if (link->open)
link->open(link);
@@ -989,6 +978,5 @@ void gether_disconnect(struct gether *link)
spin_lock(&dev->lock);
dev->port_usb = NULL;
- link->ioport = NULL;
spin_unlock(&dev->lock);
}
diff --git a/drivers/usb/gadget/u_ether.h b/drivers/usb/gadget/u_ether.h
index 6f4a1623d85..02522338a70 100644
--- a/drivers/usb/gadget/u_ether.h
+++ b/drivers/usb/gadget/u_ether.h
@@ -21,6 +21,7 @@
#include "gadget_chips.h"
+struct eth_dev;
/*
* This represents the USB side of an "ethernet" link, managed by a USB
@@ -70,7 +71,7 @@ struct gether {
|USB_CDC_PACKET_TYPE_DIRECTED)
/* variant of gether_setup that allows customizing network device name */
-int gether_setup_name(struct usb_gadget *g, u8 ethaddr[ETH_ALEN],
+struct eth_dev *gether_setup_name(struct usb_gadget *g, u8 ethaddr[ETH_ALEN],
const char *netname);
/* netdev setup/teardown as directed by the gadget driver */
@@ -86,12 +87,13 @@ int gether_setup_name(struct usb_gadget *g, u8 ethaddr[ETH_ALEN],
*
* Returns negative errno, or zero on success
*/
-static inline int gether_setup(struct usb_gadget *g, u8 ethaddr[ETH_ALEN])
+static inline struct eth_dev *gether_setup(struct usb_gadget *g,
+ u8 ethaddr[ETH_ALEN])
{
return gether_setup_name(g, ethaddr, "usb");
}
-void gether_cleanup(void);
+void gether_cleanup(struct eth_dev *dev);
/* connect/disconnect is handled by individual functions */
struct net_device *gether_connect(struct gether *);
@@ -111,21 +113,24 @@ static inline bool can_support_ecm(struct usb_gadget *gadget)
}
/* each configuration may bind one instance of an ethernet link */
-int geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]);
-int ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]);
-int ncm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]);
-int eem_bind_config(struct usb_configuration *c);
+int geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
+ struct eth_dev *dev);
+int ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
+ struct eth_dev *dev);
+int ncm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
+ struct eth_dev *dev);
+int eem_bind_config(struct usb_configuration *c, struct eth_dev *dev);
#ifdef USB_ETH_RNDIS
int rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
- u32 vendorID, const char *manufacturer);
+ u32 vendorID, const char *manufacturer, struct eth_dev *dev);
#else
static inline int
rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
- u32 vendorID, const char *manufacturer)
+ u32 vendorID, const char *manufacturer, struct eth_dev *dev)
{
return 0;
}
@@ -145,9 +150,9 @@ rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
* for calling @gether_cleanup() before module unload.
*/
static inline int rndis_bind_config(struct usb_configuration *c,
- u8 ethaddr[ETH_ALEN])
+ u8 ethaddr[ETH_ALEN], struct eth_dev *dev)
{
- return rndis_bind_config_vendor(c, ethaddr, 0, NULL);
+ return rndis_bind_config_vendor(c, ethaddr, 0, NULL, dev);
}
diff --git a/drivers/usb/gadget/u_serial.c b/drivers/usb/gadget/u_serial.c
index c5034d9c946..b369292d4b9 100644
--- a/drivers/usb/gadget/u_serial.c
+++ b/drivers/usb/gadget/u_serial.c
@@ -136,7 +136,7 @@ static struct portmaster {
pr_debug(fmt, ##arg)
#endif /* pr_vdebug */
#else
-#ifndef pr_vdebig
+#ifndef pr_vdebug
#define pr_vdebug(fmt, arg...) \
({ if (0) pr_debug(fmt, ##arg); })
#endif /* pr_vdebug */
diff --git a/drivers/usb/gadget/u_serial.h b/drivers/usb/gadget/u_serial.h
index 66ce73a0050..c20210c0bab 100644
--- a/drivers/usb/gadget/u_serial.h
+++ b/drivers/usb/gadget/u_serial.h
@@ -65,7 +65,6 @@ int gserial_connect(struct gserial *, u8 port_num);
void gserial_disconnect(struct gserial *);
/* functions are bound to configurations by a config or gadget driver */
-int acm_bind_config(struct usb_configuration *c, u8 port_num);
int gser_bind_config(struct usb_configuration *c, u8 port_num);
int obex_bind_config(struct usb_configuration *c, u8 port_num);
diff --git a/drivers/usb/gadget/u_uac1.c b/drivers/usb/gadget/u_uac1.c
index e0c5e88e03e..c7d460f4339 100644
--- a/drivers/usb/gadget/u_uac1.c
+++ b/drivers/usb/gadget/u_uac1.c
@@ -240,8 +240,11 @@ static int gaudio_open_snd_dev(struct gaudio *card)
snd = &card->playback;
snd->filp = filp_open(fn_play, O_WRONLY, 0);
if (IS_ERR(snd->filp)) {
+ int ret = PTR_ERR(snd->filp);
+
ERROR(card, "No such PCM playback device: %s\n", fn_play);
snd->filp = NULL;
+ return ret;
}
pcm_file = snd->filp->private_data;
snd->substream = pcm_file->substream;
diff --git a/drivers/usb/gadget/udc-core.c b/drivers/usb/gadget/udc-core.c
index 2a9cd369f71..ffd8fa54110 100644
--- a/drivers/usb/gadget/udc-core.c
+++ b/drivers/usb/gadget/udc-core.c
@@ -101,6 +101,16 @@ EXPORT_SYMBOL_GPL(usb_gadget_unmap_request);
/* ------------------------------------------------------------------------- */
+void usb_gadget_set_state(struct usb_gadget *gadget,
+ enum usb_device_state state)
+{
+ gadget->state = state;
+ sysfs_notify(&gadget->dev.kobj, NULL, "status");
+}
+EXPORT_SYMBOL_GPL(usb_gadget_set_state);
+
+/* ------------------------------------------------------------------------- */
+
/**
* usb_gadget_udc_start - tells usb device controller to start up
* @gadget: The gadget we want to get started
@@ -156,15 +166,23 @@ static void usb_udc_release(struct device *dev)
}
static const struct attribute_group *usb_udc_attr_groups[];
+
+static void usb_udc_nop_release(struct device *dev)
+{
+ dev_vdbg(dev, "%s\n", __func__);
+}
+
/**
- * usb_add_gadget_udc - adds a new gadget to the udc class driver list
- * @parent: the parent device to this udc. Usually the controller
- * driver's device.
- * @gadget: the gadget to be added to the list
+ * usb_add_gadget_udc_release - adds a new gadget to the udc class driver list
+ * @parent: the parent device to this udc. Usually the controller driver's
+ * device.
+ * @gadget: the gadget to be added to the list.
+ * @release: a gadget release function.
*
* Returns zero on success, negative errno otherwise.
*/
-int usb_add_gadget_udc(struct device *parent, struct usb_gadget *gadget)
+int usb_add_gadget_udc_release(struct device *parent, struct usb_gadget *gadget,
+ void (*release)(struct device *dev))
{
struct usb_udc *udc;
int ret = -ENOMEM;
@@ -173,6 +191,22 @@ int usb_add_gadget_udc(struct device *parent, struct usb_gadget *gadget)
if (!udc)
goto err1;
+ dev_set_name(&gadget->dev, "gadget");
+ gadget->dev.parent = parent;
+
+ dma_set_coherent_mask(&gadget->dev, parent->coherent_dma_mask);
+ gadget->dev.dma_parms = parent->dma_parms;
+ gadget->dev.dma_mask = parent->dma_mask;
+
+ if (release)
+ gadget->dev.release = release;
+ else
+ gadget->dev.release = usb_udc_nop_release;
+
+ ret = device_register(&gadget->dev);
+ if (ret)
+ goto err2;
+
device_initialize(&udc->dev);
udc->dev.release = usb_udc_release;
udc->dev.class = udc_class;
@@ -180,7 +214,7 @@ int usb_add_gadget_udc(struct device *parent, struct usb_gadget *gadget)
udc->dev.parent = parent;
ret = dev_set_name(&udc->dev, "%s", kobject_name(&parent->kobj));
if (ret)
- goto err2;
+ goto err3;
udc->gadget = gadget;
@@ -189,21 +223,42 @@ int usb_add_gadget_udc(struct device *parent, struct usb_gadget *gadget)
ret = device_add(&udc->dev);
if (ret)
- goto err3;
+ goto err4;
+
+ usb_gadget_set_state(gadget, USB_STATE_NOTATTACHED);
mutex_unlock(&udc_lock);
return 0;
-err3:
+
+err4:
list_del(&udc->list);
mutex_unlock(&udc_lock);
-err2:
+err3:
put_device(&udc->dev);
+err2:
+ put_device(&gadget->dev);
+ kfree(udc);
+
err1:
return ret;
}
+EXPORT_SYMBOL_GPL(usb_add_gadget_udc_release);
+
+/**
+ * usb_add_gadget_udc - adds a new gadget to the udc class driver list
+ * @parent: the parent device to this udc. Usually the controller
+ * driver's device.
+ * @gadget: the gadget to be added to the list
+ *
+ * Returns zero on success, negative errno otherwise.
+ */
+int usb_add_gadget_udc(struct device *parent, struct usb_gadget *gadget)
+{
+ return usb_add_gadget_udc_release(parent, gadget, NULL);
+}
EXPORT_SYMBOL_GPL(usb_add_gadget_udc);
static void usb_gadget_remove_driver(struct usb_udc *udc)
@@ -216,10 +271,11 @@ static void usb_gadget_remove_driver(struct usb_udc *udc)
usb_gadget_disconnect(udc->gadget);
udc->driver->disconnect(udc->gadget);
udc->driver->unbind(udc->gadget);
- usb_gadget_udc_stop(udc->gadget, udc->driver);
+ usb_gadget_udc_stop(udc->gadget, NULL);
udc->driver = NULL;
udc->dev.driver = NULL;
+ udc->gadget->dev.driver = NULL;
}
/**
@@ -254,6 +310,7 @@ found:
kobject_uevent(&udc->dev.kobj, KOBJ_REMOVE);
device_unregister(&udc->dev);
+ device_unregister(&gadget->dev);
}
EXPORT_SYMBOL_GPL(usb_del_gadget_udc);
@@ -268,6 +325,7 @@ static int udc_bind_to_driver(struct usb_udc *udc, struct usb_gadget_driver *dri
udc->driver = driver;
udc->dev.driver = &driver->driver;
+ udc->gadget->dev.driver = &driver->driver;
ret = driver->bind(udc->gadget, driver);
if (ret)
@@ -286,6 +344,7 @@ err1:
udc->driver->function, ret);
udc->driver = NULL;
udc->dev.driver = NULL;
+ udc->gadget->dev.driver = NULL;
return ret;
}
@@ -395,6 +454,16 @@ static ssize_t usb_udc_softconn_store(struct device *dev,
}
static DEVICE_ATTR(soft_connect, S_IWUSR, NULL, usb_udc_softconn_store);
+static ssize_t usb_gadget_state_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct usb_udc *udc = container_of(dev, struct usb_udc, dev);
+ struct usb_gadget *gadget = udc->gadget;
+
+ return sprintf(buf, "%s\n", usb_state_string(gadget->state));
+}
+static DEVICE_ATTR(state, S_IRUGO, usb_gadget_state_show, NULL);
+
#define USB_UDC_SPEED_ATTR(name, param) \
ssize_t usb_udc_##param##_show(struct device *dev, \
struct device_attribute *attr, char *buf) \
@@ -403,7 +472,7 @@ ssize_t usb_udc_##param##_show(struct device *dev, \
return snprintf(buf, PAGE_SIZE, "%s\n", \
usb_speed_string(udc->gadget->param)); \
} \
-static DEVICE_ATTR(name, S_IRUSR, usb_udc_##param##_show, NULL)
+static DEVICE_ATTR(name, S_IRUGO, usb_udc_##param##_show, NULL)
static USB_UDC_SPEED_ATTR(current_speed, speed);
static USB_UDC_SPEED_ATTR(maximum_speed, max_speed);
@@ -428,6 +497,7 @@ static USB_UDC_ATTR(a_alt_hnp_support);
static struct attribute *usb_udc_attrs[] = {
&dev_attr_srp.attr,
&dev_attr_soft_connect.attr,
+ &dev_attr_state.attr,
&dev_attr_current_speed.attr,
&dev_attr_maximum_speed.attr,
diff --git a/drivers/usb/gadget/uvc.h b/drivers/usb/gadget/uvc.h
index 93b0c119111..817e9e19cec 100644
--- a/drivers/usb/gadget/uvc.h
+++ b/drivers/usb/gadget/uvc.h
@@ -98,8 +98,6 @@ extern unsigned int uvc_gadget_trace_param;
#define DRIVER_VERSION "0.1.0"
#define DRIVER_VERSION_NUMBER KERNEL_VERSION(0, 1, 0)
-#define DMA_ADDR_INVALID (~(dma_addr_t)0)
-
#define UVC_NUM_REQUESTS 4
#define UVC_MAX_REQUEST_SIZE 64
#define UVC_MAX_EVENTS 4
@@ -190,6 +188,7 @@ struct uvc_file_handle
* Functions
*/
+extern void uvc_function_setup_continue(struct uvc_device *uvc);
extern void uvc_endpoint_stream(struct uvc_device *dev);
extern void uvc_function_connect(struct uvc_device *uvc);
diff --git a/drivers/usb/gadget/uvc_queue.c b/drivers/usb/gadget/uvc_queue.c
index 104ae9c8125..7ce27e35550 100644
--- a/drivers/usb/gadget/uvc_queue.c
+++ b/drivers/usb/gadget/uvc_queue.c
@@ -10,6 +10,7 @@
* (at your option) any later version.
*/
+#include <linux/atomic.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/list.h>
@@ -18,7 +19,8 @@
#include <linux/videodev2.h>
#include <linux/vmalloc.h>
#include <linux/wait.h>
-#include <linux/atomic.h>
+
+#include <media/videobuf2-vmalloc.h>
#include "uvc.h"
@@ -28,330 +30,175 @@
* Video queues is initialized by uvc_queue_init(). The function performs
* basic initialization of the uvc_video_queue struct and never fails.
*
- * Video buffer allocation and freeing are performed by uvc_alloc_buffers and
- * uvc_free_buffers respectively. The former acquires the video queue lock,
- * while the later must be called with the lock held (so that allocation can
- * free previously allocated buffers). Trying to free buffers that are mapped
- * to user space will return -EBUSY.
- *
- * Video buffers are managed using two queues. However, unlike most USB video
- * drivers that use an in queue and an out queue, we use a main queue to hold
- * all queued buffers (both 'empty' and 'done' buffers), and an irq queue to
- * hold empty buffers. This design (copied from video-buf) minimizes locking
- * in interrupt, as only one queue is shared between interrupt and user
- * contexts.
- *
- * Use cases
- * ---------
- *
- * Unless stated otherwise, all operations that modify the irq buffers queue
- * are protected by the irq spinlock.
- *
- * 1. The user queues the buffers, starts streaming and dequeues a buffer.
- *
- * The buffers are added to the main and irq queues. Both operations are
- * protected by the queue lock, and the later is protected by the irq
- * spinlock as well.
- *
- * The completion handler fetches a buffer from the irq queue and fills it
- * with video data. If no buffer is available (irq queue empty), the handler
- * returns immediately.
- *
- * When the buffer is full, the completion handler removes it from the irq
- * queue, marks it as ready (UVC_BUF_STATE_DONE) and wakes its wait queue.
- * At that point, any process waiting on the buffer will be woken up. If a
- * process tries to dequeue a buffer after it has been marked ready, the
- * dequeing will succeed immediately.
- *
- * 2. Buffers are queued, user is waiting on a buffer and the device gets
- * disconnected.
- *
- * When the device is disconnected, the kernel calls the completion handler
- * with an appropriate status code. The handler marks all buffers in the
- * irq queue as being erroneous (UVC_BUF_STATE_ERROR) and wakes them up so
- * that any process waiting on a buffer gets woken up.
- *
- * Waking up up the first buffer on the irq list is not enough, as the
- * process waiting on the buffer might restart the dequeue operation
- * immediately.
- *
+ * Video buffers are managed by videobuf2. The driver uses a mutex to protect
+ * the videobuf2 queue operations by serializing calls to videobuf2 and a
+ * spinlock to protect the IRQ queue that holds the buffers to be processed by
+ * the driver.
*/
-static void
-uvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type)
-{
- mutex_init(&queue->mutex);
- spin_lock_init(&queue->irqlock);
- INIT_LIST_HEAD(&queue->mainqueue);
- INIT_LIST_HEAD(&queue->irqqueue);
- queue->type = type;
-}
-
-/*
- * Free the video buffers.
- *
- * This function must be called with the queue lock held.
+/* -----------------------------------------------------------------------------
+ * videobuf2 queue operations
*/
-static int uvc_free_buffers(struct uvc_video_queue *queue)
+
+static int uvc_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+ unsigned int *nbuffers, unsigned int *nplanes,
+ unsigned int sizes[], void *alloc_ctxs[])
{
- unsigned int i;
+ struct uvc_video_queue *queue = vb2_get_drv_priv(vq);
+ struct uvc_video *video = container_of(queue, struct uvc_video, queue);
- for (i = 0; i < queue->count; ++i) {
- if (queue->buffer[i].vma_use_count != 0)
- return -EBUSY;
- }
+ if (*nbuffers > UVC_MAX_VIDEO_BUFFERS)
+ *nbuffers = UVC_MAX_VIDEO_BUFFERS;
- if (queue->count) {
- vfree(queue->mem);
- queue->count = 0;
- }
+ *nplanes = 1;
+
+ sizes[0] = video->imagesize;
return 0;
}
-/*
- * Allocate the video buffers.
- *
- * Pages are reserved to make sure they will not be swapped, as they will be
- * filled in the URB completion handler.
- *
- * Buffers will be individually mapped, so they must all be page aligned.
- */
-static int
-uvc_alloc_buffers(struct uvc_video_queue *queue, unsigned int nbuffers,
- unsigned int buflength)
+static int uvc_buffer_prepare(struct vb2_buffer *vb)
{
- unsigned int bufsize = PAGE_ALIGN(buflength);
- unsigned int i;
- void *mem = NULL;
- int ret;
+ struct uvc_video_queue *queue = vb2_get_drv_priv(vb->vb2_queue);
+ struct uvc_buffer *buf = container_of(vb, struct uvc_buffer, buf);
- if (nbuffers > UVC_MAX_VIDEO_BUFFERS)
- nbuffers = UVC_MAX_VIDEO_BUFFERS;
+ if (vb->v4l2_buf.type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
+ vb2_get_plane_payload(vb, 0) > vb2_plane_size(vb, 0)) {
+ uvc_trace(UVC_TRACE_CAPTURE, "[E] Bytes used out of bounds.\n");
+ return -EINVAL;
+ }
- mutex_lock(&queue->mutex);
+ if (unlikely(queue->flags & UVC_QUEUE_DISCONNECTED))
+ return -ENODEV;
- if ((ret = uvc_free_buffers(queue)) < 0)
- goto done;
+ buf->state = UVC_BUF_STATE_QUEUED;
+ buf->mem = vb2_plane_vaddr(vb, 0);
+ buf->length = vb2_plane_size(vb, 0);
+ if (vb->v4l2_buf.type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ buf->bytesused = 0;
+ else
+ buf->bytesused = vb2_get_plane_payload(vb, 0);
- /* Bail out if no buffers should be allocated. */
- if (nbuffers == 0)
- goto done;
+ return 0;
+}
- /* Decrement the number of buffers until allocation succeeds. */
- for (; nbuffers > 0; --nbuffers) {
- mem = vmalloc_32(nbuffers * bufsize);
- if (mem != NULL)
- break;
- }
+static void uvc_buffer_queue(struct vb2_buffer *vb)
+{
+ struct uvc_video_queue *queue = vb2_get_drv_priv(vb->vb2_queue);
+ struct uvc_buffer *buf = container_of(vb, struct uvc_buffer, buf);
+ unsigned long flags;
- if (mem == NULL) {
- ret = -ENOMEM;
- goto done;
- }
+ spin_lock_irqsave(&queue->irqlock, flags);
- for (i = 0; i < nbuffers; ++i) {
- memset(&queue->buffer[i], 0, sizeof queue->buffer[i]);
- queue->buffer[i].buf.index = i;
- queue->buffer[i].buf.m.offset = i * bufsize;
- queue->buffer[i].buf.length = buflength;
- queue->buffer[i].buf.type = queue->type;
- queue->buffer[i].buf.sequence = 0;
- queue->buffer[i].buf.field = V4L2_FIELD_NONE;
- queue->buffer[i].buf.memory = V4L2_MEMORY_MMAP;
- queue->buffer[i].buf.flags = 0;
- init_waitqueue_head(&queue->buffer[i].wait);
+ if (likely(!(queue->flags & UVC_QUEUE_DISCONNECTED))) {
+ list_add_tail(&buf->queue, &queue->irqqueue);
+ } else {
+ /* If the device is disconnected return the buffer to userspace
+ * directly. The next QBUF call will fail with -ENODEV.
+ */
+ buf->state = UVC_BUF_STATE_ERROR;
+ vb2_buffer_done(&buf->buf, VB2_BUF_STATE_ERROR);
}
- queue->mem = mem;
- queue->count = nbuffers;
- queue->buf_size = bufsize;
- ret = nbuffers;
-
-done:
- mutex_unlock(&queue->mutex);
- return ret;
+ spin_unlock_irqrestore(&queue->irqlock, flags);
}
-static void __uvc_query_buffer(struct uvc_buffer *buf,
- struct v4l2_buffer *v4l2_buf)
-{
- memcpy(v4l2_buf, &buf->buf, sizeof *v4l2_buf);
-
- if (buf->vma_use_count)
- v4l2_buf->flags |= V4L2_BUF_FLAG_MAPPED;
-
- switch (buf->state) {
- case UVC_BUF_STATE_ERROR:
- case UVC_BUF_STATE_DONE:
- v4l2_buf->flags |= V4L2_BUF_FLAG_DONE;
- break;
- case UVC_BUF_STATE_QUEUED:
- case UVC_BUF_STATE_ACTIVE:
- v4l2_buf->flags |= V4L2_BUF_FLAG_QUEUED;
- break;
- case UVC_BUF_STATE_IDLE:
- default:
- break;
- }
-}
+static struct vb2_ops uvc_queue_qops = {
+ .queue_setup = uvc_queue_setup,
+ .buf_prepare = uvc_buffer_prepare,
+ .buf_queue = uvc_buffer_queue,
+};
-static int
-uvc_query_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *v4l2_buf)
+static int uvc_queue_init(struct uvc_video_queue *queue,
+ enum v4l2_buf_type type)
{
- int ret = 0;
+ int ret;
- mutex_lock(&queue->mutex);
- if (v4l2_buf->index >= queue->count) {
- ret = -EINVAL;
- goto done;
- }
+ queue->queue.type = type;
+ queue->queue.io_modes = VB2_MMAP | VB2_USERPTR;
+ queue->queue.drv_priv = queue;
+ queue->queue.buf_struct_size = sizeof(struct uvc_buffer);
+ queue->queue.ops = &uvc_queue_qops;
+ queue->queue.mem_ops = &vb2_vmalloc_memops;
+ ret = vb2_queue_init(&queue->queue);
+ if (ret)
+ return ret;
+
+ mutex_init(&queue->mutex);
+ spin_lock_init(&queue->irqlock);
+ INIT_LIST_HEAD(&queue->irqqueue);
+ queue->flags = 0;
- __uvc_query_buffer(&queue->buffer[v4l2_buf->index], v4l2_buf);
+ return 0;
+}
-done:
+/*
+ * Free the video buffers.
+ */
+static void uvc_free_buffers(struct uvc_video_queue *queue)
+{
+ mutex_lock(&queue->mutex);
+ vb2_queue_release(&queue->queue);
mutex_unlock(&queue->mutex);
- return ret;
}
/*
- * Queue a video buffer. Attempting to queue a buffer that has already been
- * queued will return -EINVAL.
+ * Allocate the video buffers.
*/
-static int
-uvc_queue_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *v4l2_buf)
+static int uvc_alloc_buffers(struct uvc_video_queue *queue,
+ struct v4l2_requestbuffers *rb)
{
- struct uvc_buffer *buf;
- unsigned long flags;
- int ret = 0;
+ int ret;
- uvc_trace(UVC_TRACE_CAPTURE, "Queuing buffer %u.\n", v4l2_buf->index);
+ mutex_lock(&queue->mutex);
+ ret = vb2_reqbufs(&queue->queue, rb);
+ mutex_unlock(&queue->mutex);
- if (v4l2_buf->type != queue->type ||
- v4l2_buf->memory != V4L2_MEMORY_MMAP) {
- uvc_trace(UVC_TRACE_CAPTURE, "[E] Invalid buffer type (%u) "
- "and/or memory (%u).\n", v4l2_buf->type,
- v4l2_buf->memory);
- return -EINVAL;
- }
+ return ret ? ret : rb->count;
+}
- mutex_lock(&queue->mutex);
- if (v4l2_buf->index >= queue->count) {
- uvc_trace(UVC_TRACE_CAPTURE, "[E] Out of range index.\n");
- ret = -EINVAL;
- goto done;
- }
+static int uvc_query_buffer(struct uvc_video_queue *queue,
+ struct v4l2_buffer *buf)
+{
+ int ret;
- buf = &queue->buffer[v4l2_buf->index];
- if (buf->state != UVC_BUF_STATE_IDLE) {
- uvc_trace(UVC_TRACE_CAPTURE, "[E] Invalid buffer state "
- "(%u).\n", buf->state);
- ret = -EINVAL;
- goto done;
- }
+ mutex_lock(&queue->mutex);
+ ret = vb2_querybuf(&queue->queue, buf);
+ mutex_unlock(&queue->mutex);
- if (v4l2_buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
- v4l2_buf->bytesused > buf->buf.length) {
- uvc_trace(UVC_TRACE_CAPTURE, "[E] Bytes used out of bounds.\n");
- ret = -EINVAL;
- goto done;
- }
+ return ret;
+}
- if (v4l2_buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
- buf->buf.bytesused = 0;
- else
- buf->buf.bytesused = v4l2_buf->bytesused;
+static int uvc_queue_buffer(struct uvc_video_queue *queue,
+ struct v4l2_buffer *buf)
+{
+ unsigned long flags;
+ int ret;
+ mutex_lock(&queue->mutex);
+ ret = vb2_qbuf(&queue->queue, buf);
spin_lock_irqsave(&queue->irqlock, flags);
- if (queue->flags & UVC_QUEUE_DISCONNECTED) {
- spin_unlock_irqrestore(&queue->irqlock, flags);
- ret = -ENODEV;
- goto done;
- }
- buf->state = UVC_BUF_STATE_QUEUED;
-
ret = (queue->flags & UVC_QUEUE_PAUSED) != 0;
queue->flags &= ~UVC_QUEUE_PAUSED;
-
- list_add_tail(&buf->stream, &queue->mainqueue);
- list_add_tail(&buf->queue, &queue->irqqueue);
spin_unlock_irqrestore(&queue->irqlock, flags);
-
-done:
mutex_unlock(&queue->mutex);
- return ret;
-}
-static int uvc_queue_waiton(struct uvc_buffer *buf, int nonblocking)
-{
- if (nonblocking) {
- return (buf->state != UVC_BUF_STATE_QUEUED &&
- buf->state != UVC_BUF_STATE_ACTIVE)
- ? 0 : -EAGAIN;
- }
-
- return wait_event_interruptible(buf->wait,
- buf->state != UVC_BUF_STATE_QUEUED &&
- buf->state != UVC_BUF_STATE_ACTIVE);
+ return ret;
}
/*
* Dequeue a video buffer. If nonblocking is false, block until a buffer is
* available.
*/
-static int
-uvc_dequeue_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *v4l2_buf,
- int nonblocking)
+static int uvc_dequeue_buffer(struct uvc_video_queue *queue,
+ struct v4l2_buffer *buf, int nonblocking)
{
- struct uvc_buffer *buf;
- int ret = 0;
-
- if (v4l2_buf->type != queue->type ||
- v4l2_buf->memory != V4L2_MEMORY_MMAP) {
- uvc_trace(UVC_TRACE_CAPTURE, "[E] Invalid buffer type (%u) "
- "and/or memory (%u).\n", v4l2_buf->type,
- v4l2_buf->memory);
- return -EINVAL;
- }
+ int ret;
mutex_lock(&queue->mutex);
- if (list_empty(&queue->mainqueue)) {
- uvc_trace(UVC_TRACE_CAPTURE, "[E] Empty buffer queue.\n");
- ret = -EINVAL;
- goto done;
- }
-
- buf = list_first_entry(&queue->mainqueue, struct uvc_buffer, stream);
- if ((ret = uvc_queue_waiton(buf, nonblocking)) < 0)
- goto done;
-
- uvc_trace(UVC_TRACE_CAPTURE, "Dequeuing buffer %u (%u, %u bytes).\n",
- buf->buf.index, buf->state, buf->buf.bytesused);
-
- switch (buf->state) {
- case UVC_BUF_STATE_ERROR:
- uvc_trace(UVC_TRACE_CAPTURE, "[W] Corrupted data "
- "(transmission error).\n");
- ret = -EIO;
- case UVC_BUF_STATE_DONE:
- buf->state = UVC_BUF_STATE_IDLE;
- break;
-
- case UVC_BUF_STATE_IDLE:
- case UVC_BUF_STATE_QUEUED:
- case UVC_BUF_STATE_ACTIVE:
- default:
- uvc_trace(UVC_TRACE_CAPTURE, "[E] Invalid buffer state %u "
- "(driver bug?).\n", buf->state);
- ret = -EINVAL;
- goto done;
- }
-
- list_del(&buf->stream);
- __uvc_query_buffer(buf, v4l2_buf);
-
-done:
+ ret = vb2_dqbuf(&queue->queue, buf, nonblocking);
mutex_unlock(&queue->mutex);
+
return ret;
}
@@ -361,105 +208,47 @@ done:
* This function implements video queue polling and is intended to be used by
* the device poll handler.
*/
-static unsigned int
-uvc_queue_poll(struct uvc_video_queue *queue, struct file *file,
- poll_table *wait)
+static unsigned int uvc_queue_poll(struct uvc_video_queue *queue,
+ struct file *file, poll_table *wait)
{
- struct uvc_buffer *buf;
- unsigned int mask = 0;
+ unsigned int ret;
mutex_lock(&queue->mutex);
- if (list_empty(&queue->mainqueue))
- goto done;
-
- buf = list_first_entry(&queue->mainqueue, struct uvc_buffer, stream);
-
- poll_wait(file, &buf->wait, wait);
- if (buf->state == UVC_BUF_STATE_DONE ||
- buf->state == UVC_BUF_STATE_ERROR)
- mask |= POLLOUT | POLLWRNORM;
-
-done:
+ ret = vb2_poll(&queue->queue, file, wait);
mutex_unlock(&queue->mutex);
- return mask;
-}
-/*
- * VMA operations.
- */
-static void uvc_vm_open(struct vm_area_struct *vma)
-{
- struct uvc_buffer *buffer = vma->vm_private_data;
- buffer->vma_use_count++;
+ return ret;
}
-static void uvc_vm_close(struct vm_area_struct *vma)
+static int uvc_queue_mmap(struct uvc_video_queue *queue,
+ struct vm_area_struct *vma)
{
- struct uvc_buffer *buffer = vma->vm_private_data;
- buffer->vma_use_count--;
-}
+ int ret;
-static struct vm_operations_struct uvc_vm_ops = {
- .open = uvc_vm_open,
- .close = uvc_vm_close,
-};
+ mutex_lock(&queue->mutex);
+ ret = vb2_mmap(&queue->queue, vma);
+ mutex_unlock(&queue->mutex);
+
+ return ret;
+}
+#ifndef CONFIG_MMU
/*
- * Memory-map a buffer.
+ * Get unmapped area.
*
- * This function implements video buffer memory mapping and is intended to be
- * used by the device mmap handler.
+ * NO-MMU arch need this function to make mmap() work correctly.
*/
-static int
-uvc_queue_mmap(struct uvc_video_queue *queue, struct vm_area_struct *vma)
+static unsigned long uvc_queue_get_unmapped_area(struct uvc_video_queue *queue,
+ unsigned long pgoff)
{
- struct uvc_buffer *uninitialized_var(buffer);
- struct page *page;
- unsigned long addr, start, size;
- unsigned int i;
- int ret = 0;
-
- start = vma->vm_start;
- size = vma->vm_end - vma->vm_start;
+ unsigned long ret;
mutex_lock(&queue->mutex);
-
- for (i = 0; i < queue->count; ++i) {
- buffer = &queue->buffer[i];
- if ((buffer->buf.m.offset >> PAGE_SHIFT) == vma->vm_pgoff)
- break;
- }
-
- if (i == queue->count || size != queue->buf_size) {
- ret = -EINVAL;
- goto done;
- }
-
- /*
- * VM_IO marks the area as being an mmaped region for I/O to a
- * device. It also prevents the region from being core dumped.
- */
- vma->vm_flags |= VM_IO;
-
- addr = (unsigned long)queue->mem + buffer->buf.m.offset;
- while (size > 0) {
- page = vmalloc_to_page((void *)addr);
- if ((ret = vm_insert_page(vma, start, page)) < 0)
- goto done;
-
- start += PAGE_SIZE;
- addr += PAGE_SIZE;
- size -= PAGE_SIZE;
- }
-
- vma->vm_ops = &uvc_vm_ops;
- vma->vm_private_data = buffer;
- uvc_vm_open(vma);
-
-done:
+ ret = vb2_get_unmapped_area(&queue->queue, 0, 0, pgoff, 0);
mutex_unlock(&queue->mutex);
return ret;
}
+#endif
/*
* Cancel the video buffers queue.
@@ -484,7 +273,7 @@ static void uvc_queue_cancel(struct uvc_video_queue *queue, int disconnect)
queue);
list_del(&buf->queue);
buf->state = UVC_BUF_STATE_ERROR;
- wake_up(&buf->wait);
+ vb2_buffer_done(&buf->buf, VB2_BUF_STATE_ERROR);
}
/* This must be protected by the irqlock spinlock to avoid race
* conditions between uvc_queue_buffer and the disconnection event that
@@ -516,26 +305,33 @@ static void uvc_queue_cancel(struct uvc_video_queue *queue, int disconnect)
*/
static int uvc_queue_enable(struct uvc_video_queue *queue, int enable)
{
- unsigned int i;
+ unsigned long flags;
int ret = 0;
mutex_lock(&queue->mutex);
if (enable) {
- if (uvc_queue_streaming(queue)) {
- ret = -EBUSY;
+ ret = vb2_streamon(&queue->queue, queue->queue.type);
+ if (ret < 0)
goto done;
- }
+
queue->sequence = 0;
- queue->flags |= UVC_QUEUE_STREAMING;
queue->buf_used = 0;
} else {
- uvc_queue_cancel(queue, 0);
- INIT_LIST_HEAD(&queue->mainqueue);
+ ret = vb2_streamoff(&queue->queue, queue->queue.type);
+ if (ret < 0)
+ goto done;
- for (i = 0; i < queue->count; ++i)
- queue->buffer[i].state = UVC_BUF_STATE_IDLE;
+ spin_lock_irqsave(&queue->irqlock, flags);
+ INIT_LIST_HEAD(&queue->irqqueue);
- queue->flags &= ~UVC_QUEUE_STREAMING;
+ /*
+ * FIXME: We need to clear the DISCONNECTED flag to ensure that
+ * applications will be able to queue buffers for the next
+ * streaming run. However, clearing it here doesn't guarantee
+ * that the device will be reconnected in the meantime.
+ */
+ queue->flags &= ~UVC_QUEUE_DISCONNECTED;
+ spin_unlock_irqrestore(&queue->irqlock, flags);
}
done:
@@ -544,15 +340,15 @@ done:
}
/* called with &queue_irqlock held.. */
-static struct uvc_buffer *
-uvc_queue_next_buffer(struct uvc_video_queue *queue, struct uvc_buffer *buf)
+static struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue,
+ struct uvc_buffer *buf)
{
struct uvc_buffer *nextbuf;
if ((queue->flags & UVC_QUEUE_DROP_INCOMPLETE) &&
- buf->buf.length != buf->buf.bytesused) {
+ buf->length != buf->bytesused) {
buf->state = UVC_BUF_STATE_QUEUED;
- buf->buf.bytesused = 0;
+ vb2_set_plane_payload(&buf->buf, 0, 0);
return buf;
}
@@ -563,10 +359,18 @@ uvc_queue_next_buffer(struct uvc_video_queue *queue, struct uvc_buffer *buf)
else
nextbuf = NULL;
- buf->buf.sequence = queue->sequence++;
- do_gettimeofday(&buf->buf.timestamp);
+ /*
+ * FIXME: with videobuf2, the sequence number or timestamp fields
+ * are valid only for video capture devices and the UVC gadget usually
+ * is a video output device. Keeping these until the specs are clear on
+ * this aspect.
+ */
+ buf->buf.v4l2_buf.sequence = queue->sequence++;
+ do_gettimeofday(&buf->buf.v4l2_buf.timestamp);
+
+ vb2_set_plane_payload(&buf->buf, 0, buf->bytesused);
+ vb2_buffer_done(&buf->buf, VB2_BUF_STATE_DONE);
- wake_up(&buf->wait);
return nextbuf;
}
diff --git a/drivers/usb/gadget/uvc_queue.h b/drivers/usb/gadget/uvc_queue.h
index 1812a8ecc5d..8e76ce982f1 100644
--- a/drivers/usb/gadget/uvc_queue.h
+++ b/drivers/usb/gadget/uvc_queue.h
@@ -6,6 +6,7 @@
#include <linux/kernel.h>
#include <linux/poll.h>
#include <linux/videodev2.h>
+#include <media/videobuf2-core.h>
/* Maximum frame size in bytes, for sanity checking. */
#define UVC_MAX_FRAME_SIZE (16*1024*1024)
@@ -25,42 +26,35 @@ enum uvc_buffer_state {
};
struct uvc_buffer {
- unsigned long vma_use_count;
- struct list_head stream;
-
- /* Touched by interrupt handler. */
- struct v4l2_buffer buf;
+ struct vb2_buffer buf;
struct list_head queue;
- wait_queue_head_t wait;
+
enum uvc_buffer_state state;
+ void *mem;
+ unsigned int length;
+ unsigned int bytesused;
};
-#define UVC_QUEUE_STREAMING (1 << 0)
-#define UVC_QUEUE_DISCONNECTED (1 << 1)
-#define UVC_QUEUE_DROP_INCOMPLETE (1 << 2)
-#define UVC_QUEUE_PAUSED (1 << 3)
+#define UVC_QUEUE_DISCONNECTED (1 << 0)
+#define UVC_QUEUE_DROP_INCOMPLETE (1 << 1)
+#define UVC_QUEUE_PAUSED (1 << 2)
struct uvc_video_queue {
- enum v4l2_buf_type type;
+ struct vb2_queue queue;
+ struct mutex mutex; /* Protects queue */
- void *mem;
unsigned int flags;
__u32 sequence;
- unsigned int count;
- unsigned int buf_size;
unsigned int buf_used;
- struct uvc_buffer buffer[UVC_MAX_VIDEO_BUFFERS];
- struct mutex mutex; /* protects buffers and mainqueue */
- spinlock_t irqlock; /* protects irqqueue */
- struct list_head mainqueue;
+ spinlock_t irqlock; /* Protects flags and irqqueue */
struct list_head irqqueue;
};
static inline int uvc_queue_streaming(struct uvc_video_queue *queue)
{
- return queue->flags & UVC_QUEUE_STREAMING;
+ return vb2_is_streaming(&queue->queue);
}
#endif /* __KERNEL__ */
diff --git a/drivers/usb/gadget/uvc_v4l2.c b/drivers/usb/gadget/uvc_v4l2.c
index 2ca9386d655..ad48e81155e 100644
--- a/drivers/usb/gadget/uvc_v4l2.c
+++ b/drivers/usb/gadget/uvc_v4l2.c
@@ -41,9 +41,8 @@ uvc_send_response(struct uvc_device *uvc, struct uvc_request_data *data)
req->length = min_t(unsigned int, uvc->event_length, data->length);
req->zero = data->length < uvc->event_length;
- req->dma = DMA_ADDR_INVALID;
- memcpy(req->buf, data->data, data->length);
+ memcpy(req->buf, data->data, req->length);
return usb_ep_queue(cdev->gadget->ep0, req, GFP_KERNEL);
}
@@ -148,16 +147,13 @@ uvc_v4l2_release(struct file *file)
uvc_function_disconnect(uvc);
uvc_video_enable(video, 0);
- mutex_lock(&video->queue.mutex);
- if (uvc_free_buffers(&video->queue) < 0)
- printk(KERN_ERR "uvc_v4l2_release: Unable to free "
- "buffers.\n");
- mutex_unlock(&video->queue.mutex);
+ uvc_free_buffers(&video->queue);
file->private_data = NULL;
v4l2_fh_del(&handle->vfh);
v4l2_fh_exit(&handle->vfh);
kfree(handle);
+
return 0;
}
@@ -178,9 +174,9 @@ uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
struct v4l2_capability *cap = arg;
memset(cap, 0, sizeof *cap);
- strncpy(cap->driver, "g_uvc", sizeof(cap->driver));
- strncpy(cap->card, cdev->gadget->name, sizeof(cap->card));
- strncpy(cap->bus_info, dev_name(&cdev->gadget->dev),
+ strlcpy(cap->driver, "g_uvc", sizeof(cap->driver));
+ strlcpy(cap->card, cdev->gadget->name, sizeof(cap->card));
+ strlcpy(cap->bus_info, dev_name(&cdev->gadget->dev),
sizeof cap->bus_info);
cap->version = DRIVER_VERSION_NUMBER;
cap->capabilities = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING;
@@ -192,7 +188,7 @@ uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
{
struct v4l2_format *fmt = arg;
- if (fmt->type != video->queue.type)
+ if (fmt->type != video->queue.queue.type)
return -EINVAL;
return uvc_v4l2_get_format(video, fmt);
@@ -202,7 +198,7 @@ uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
{
struct v4l2_format *fmt = arg;
- if (fmt->type != video->queue.type)
+ if (fmt->type != video->queue.queue.type)
return -EINVAL;
return uvc_v4l2_set_format(video, fmt);
@@ -213,16 +209,13 @@ uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
{
struct v4l2_requestbuffers *rb = arg;
- if (rb->type != video->queue.type ||
- rb->memory != V4L2_MEMORY_MMAP)
+ if (rb->type != video->queue.queue.type)
return -EINVAL;
- ret = uvc_alloc_buffers(&video->queue, rb->count,
- video->imagesize);
+ ret = uvc_alloc_buffers(&video->queue, rb);
if (ret < 0)
return ret;
- rb->count = ret;
ret = 0;
break;
}
@@ -231,9 +224,6 @@ uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
{
struct v4l2_buffer *buf = arg;
- if (buf->type != video->queue.type)
- return -EINVAL;
-
return uvc_query_buffer(&video->queue, buf);
}
@@ -251,24 +241,36 @@ uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
{
int *type = arg;
- if (*type != video->queue.type)
+ if (*type != video->queue.queue.type)
return -EINVAL;
- return uvc_video_enable(video, 1);
+ /* Enable UVC video. */
+ ret = uvc_video_enable(video, 1);
+ if (ret < 0)
+ return ret;
+
+ /*
+ * Complete the alternate setting selection setup phase now that
+ * userspace is ready to provide video frames.
+ */
+ uvc_function_setup_continue(uvc);
+ uvc->state = UVC_STATE_STREAMING;
+
+ return 0;
}
case VIDIOC_STREAMOFF:
{
int *type = arg;
- if (*type != video->queue.type)
+ if (*type != video->queue.queue.type)
return -EINVAL;
return uvc_video_enable(video, 0);
}
/* Events */
- case VIDIOC_DQEVENT:
+ case VIDIOC_DQEVENT:
{
struct v4l2_event *event = arg;
@@ -333,17 +335,21 @@ uvc_v4l2_poll(struct file *file, poll_table *wait)
{
struct video_device *vdev = video_devdata(file);
struct uvc_device *uvc = video_get_drvdata(vdev);
- struct uvc_file_handle *handle = to_uvc_file_handle(file->private_data);
- unsigned int mask = 0;
- poll_wait(file, &handle->vfh.wait, wait);
- if (v4l2_event_pending(&handle->vfh))
- mask |= POLLPRI;
+ return uvc_queue_poll(&uvc->video.queue, file, wait);
+}
- mask |= uvc_queue_poll(&uvc->video.queue, file, wait);
+#ifndef CONFIG_MMU
+static unsigned long uvc_v4l2_get_unmapped_area(struct file *file,
+ unsigned long addr, unsigned long len, unsigned long pgoff,
+ unsigned long flags)
+{
+ struct video_device *vdev = video_devdata(file);
+ struct uvc_device *uvc = video_get_drvdata(vdev);
- return mask;
+ return uvc_queue_get_unmapped_area(&uvc->video.queue, pgoff);
}
+#endif
static struct v4l2_file_operations uvc_v4l2_fops = {
.owner = THIS_MODULE,
@@ -352,5 +358,8 @@ static struct v4l2_file_operations uvc_v4l2_fops = {
.ioctl = uvc_v4l2_ioctl,
.mmap = uvc_v4l2_mmap,
.poll = uvc_v4l2_poll,
+#ifndef CONFIG_MMU
+ .get_unmapped_area = uvc_v4l2_get_unmapped_area,
+#endif
};
diff --git a/drivers/usb/gadget/uvc_video.c b/drivers/usb/gadget/uvc_video.c
index b0e53a8ea4f..71e896d4c5a 100644
--- a/drivers/usb/gadget/uvc_video.c
+++ b/drivers/usb/gadget/uvc_video.c
@@ -32,7 +32,7 @@ uvc_video_encode_header(struct uvc_video *video, struct uvc_buffer *buf,
data[0] = 2;
data[1] = UVC_STREAM_EOH | video->fid;
- if (buf->buf.bytesused - video->queue.buf_used <= len - 2)
+ if (buf->bytesused - video->queue.buf_used <= len - 2)
data[1] |= UVC_STREAM_EOF;
return 2;
@@ -47,8 +47,8 @@ uvc_video_encode_data(struct uvc_video *video, struct uvc_buffer *buf,
void *mem;
/* Copy video data to the USB buffer. */
- mem = queue->mem + buf->buf.m.offset + queue->buf_used;
- nbytes = min((unsigned int)len, buf->buf.bytesused - queue->buf_used);
+ mem = buf->mem + queue->buf_used;
+ nbytes = min((unsigned int)len, buf->bytesused - queue->buf_used);
memcpy(data, mem, nbytes);
queue->buf_used += nbytes;
@@ -82,7 +82,7 @@ uvc_video_encode_bulk(struct usb_request *req, struct uvc_video *video,
req->length = video->req_size - len;
req->zero = video->payload_size == video->max_payload_size;
- if (buf->buf.bytesused == video->queue.buf_used) {
+ if (buf->bytesused == video->queue.buf_used) {
video->queue.buf_used = 0;
buf->state = UVC_BUF_STATE_DONE;
uvc_queue_next_buffer(&video->queue, buf);
@@ -92,7 +92,7 @@ uvc_video_encode_bulk(struct usb_request *req, struct uvc_video *video,
}
if (video->payload_size == video->max_payload_size ||
- buf->buf.bytesused == video->queue.buf_used)
+ buf->bytesused == video->queue.buf_used)
video->payload_size = 0;
}
@@ -115,7 +115,7 @@ uvc_video_encode_isoc(struct usb_request *req, struct uvc_video *video,
req->length = video->req_size - len;
- if (buf->buf.bytesused == video->queue.buf_used) {
+ if (buf->bytesused == video->queue.buf_used) {
video->queue.buf_used = 0;
buf->state = UVC_BUF_STATE_DONE;
uvc_queue_next_buffer(&video->queue, buf);
@@ -161,6 +161,7 @@ static void
uvc_video_complete(struct usb_ep *ep, struct usb_request *req)
{
struct uvc_video *video = req->context;
+ struct uvc_video_queue *queue = &video->queue;
struct uvc_buffer *buf;
unsigned long flags;
int ret;
@@ -169,13 +170,15 @@ uvc_video_complete(struct usb_ep *ep, struct usb_request *req)
case 0:
break;
- case -ESHUTDOWN:
+ case -ESHUTDOWN: /* disconnect from host. */
printk(KERN_INFO "VS request cancelled.\n");
+ uvc_queue_cancel(queue, 1);
goto requeue;
default:
printk(KERN_INFO "VS request completed with status %d.\n",
req->status);
+ uvc_queue_cancel(queue, 0);
goto requeue;
}
@@ -229,13 +232,18 @@ uvc_video_free_requests(struct uvc_video *video)
static int
uvc_video_alloc_requests(struct uvc_video *video)
{
+ unsigned int req_size;
unsigned int i;
int ret = -ENOMEM;
BUG_ON(video->req_size);
+ req_size = video->ep->maxpacket
+ * max_t(unsigned int, video->ep->maxburst, 1)
+ * (video->ep->mult + 1);
+
for (i = 0; i < UVC_NUM_REQUESTS; ++i) {
- video->req_buffer[i] = kmalloc(video->ep->maxpacket, GFP_KERNEL);
+ video->req_buffer[i] = kmalloc(req_size, GFP_KERNEL);
if (video->req_buffer[i] == NULL)
goto error;
@@ -245,14 +253,14 @@ uvc_video_alloc_requests(struct uvc_video *video)
video->req[i]->buf = video->req_buffer[i];
video->req[i]->length = 0;
- video->req[i]->dma = DMA_ADDR_INVALID;
video->req[i]->complete = uvc_video_complete;
video->req[i]->context = video;
list_add_tail(&video->req[i]->list, &video->req_free);
}
- video->req_size = video->ep->maxpacket;
+ video->req_size = req_size;
+
return 0;
error:
@@ -309,7 +317,8 @@ uvc_video_pump(struct uvc_video *video)
video->encode(req, video, buf);
/* Queue the USB request */
- if ((ret = usb_ep_queue(video->ep, req, GFP_KERNEL)) < 0) {
+ ret = usb_ep_queue(video->ep, req, GFP_ATOMIC);
+ if (ret < 0) {
printk(KERN_INFO "Failed to queue request (%d)\n", ret);
usb_ep_set_halt(video->ep);
spin_unlock_irqrestore(&video->queue.irqlock, flags);
diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c
index 685fa681cb6..2cd6262e8b7 100644
--- a/drivers/usb/gadget/zero.c
+++ b/drivers/usb/gadget/zero.c
@@ -368,8 +368,10 @@ static int zero_unbind(struct usb_composite_dev *cdev)
del_timer_sync(&autoresume_timer);
if (!IS_ERR_OR_NULL(func_ss))
usb_put_function(func_ss);
+ usb_put_function_instance(func_inst_ss);
if (!IS_ERR_OR_NULL(func_lb))
usb_put_function(func_lb);
+ usb_put_function_instance(func_inst_lb);
return 0;
}
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index c59a1126926..de94f269906 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -2,11 +2,9 @@
# USB Host Controller Drivers
#
comment "USB Host Controller Drivers"
- depends on USB
config USB_C67X00_HCD
tristate "Cypress C67x00 HCD support"
- depends on USB
help
The Cypress C67x00 (EZ-Host/EZ-OTG) chips are dual-role
host/peripheral/OTG USB controllers.
@@ -19,7 +17,7 @@ config USB_C67X00_HCD
config USB_XHCI_HCD
tristate "xHCI HCD (USB 3.0) support"
- depends on USB && USB_ARCH_HAS_XHCI
+ depends on USB_ARCH_HAS_XHCI
---help---
The eXtensible Host Controller Interface (xHCI) is standard for USB 3.0
"SuperSpeed" host controller hardware.
@@ -27,13 +25,13 @@ config USB_XHCI_HCD
To compile this driver as a module, choose M here: the
module will be called xhci-hcd.
+if USB_XHCI_HCD
+
config USB_XHCI_PLATFORM
tristate
- depends on USB_XHCI_HCD
config USB_XHCI_HCD_DEBUGGING
bool "Debugging for the xHCI host controller"
- depends on USB_XHCI_HCD
---help---
Say 'Y' to turn on debugging for the xHCI host controller driver.
This will spew debugging output, even in interrupt context.
@@ -41,9 +39,11 @@ config USB_XHCI_HCD_DEBUGGING
If unsure, say N.
+endif # USB_XHCI_HCD
+
config USB_EHCI_HCD
tristate "EHCI HCD (USB 2.0) support"
- depends on USB && USB_ARCH_HAS_EHCI
+ depends on USB_ARCH_HAS_EHCI
---help---
The Enhanced Host Controller Interface (EHCI) is standard for USB 2.0
"high speed" (480 Mbit/sec, 60 Mbyte/sec) host controller hardware.
@@ -95,14 +95,19 @@ config USB_EHCI_TT_NEWSCHED
If unsure, say Y.
+config USB_FSL_MPH_DR_OF
+ tristate
+
+if USB_EHCI_HCD
+
config USB_EHCI_PCI
tristate
- depends on USB_EHCI_HCD && PCI
+ depends on 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
+ depends on MSP_HAS_USB
default n
select USB_EHCI_BIG_ENDIAN_DESC
select USB_EHCI_BIG_ENDIAN_MMIO
@@ -112,22 +117,13 @@ config USB_EHCI_HCD_PMC_MSP
config USB_EHCI_BIG_ENDIAN_MMIO
bool
- depends on USB_EHCI_HCD && (PPC_CELLEB || PPC_PS3 || 440EPX || \
- ARCH_IXP4XX || XPS_USB_HCD_XILINX || \
- PPC_MPC512x || CPU_CAVIUM_OCTEON || \
- PMC_MSP || SPARC_LEON || MIPS_SEAD3)
- default y
config USB_EHCI_BIG_ENDIAN_DESC
bool
- depends on USB_EHCI_HCD && (440EPX || ARCH_IXP4XX || XPS_USB_HCD_XILINX || \
- PPC_MPC512x || PMC_MSP || SPARC_LEON || \
- MIPS_SEAD3)
- default y
config XPS_USB_HCD_XILINX
bool "Use Xilinx usb host EHCI controller core"
- depends on USB_EHCI_HCD && (PPC32 || MICROBLAZE)
+ depends on (PPC32 || MICROBLAZE)
select USB_EHCI_BIG_ENDIAN_DESC
select USB_EHCI_BIG_ENDIAN_MMIO
---help---
@@ -136,12 +132,9 @@ config XPS_USB_HCD_XILINX
support both high speed and full speed devices, or high speed
devices only.
-config USB_FSL_MPH_DR_OF
- tristate
-
config USB_EHCI_FSL
bool "Support for Freescale PPC on-chip EHCI USB controller"
- depends on USB_EHCI_HCD && FSL_SOC
+ depends on FSL_SOC
select USB_EHCI_ROOT_HUB_TT
select USB_FSL_MPH_DR_OF if OF
---help---
@@ -149,22 +142,53 @@ config USB_EHCI_FSL
config USB_EHCI_MXC
tristate "Support for Freescale i.MX on-chip EHCI USB controller"
- depends on USB_EHCI_HCD && ARCH_MXC
+ depends on ARCH_MXC
select USB_EHCI_ROOT_HUB_TT
---help---
Variation of ARC USB block used in some Freescale chips.
config USB_EHCI_HCD_OMAP
- bool "EHCI support for OMAP3 and later chips"
- depends on USB_EHCI_HCD && ARCH_OMAP
+ tristate "EHCI support for OMAP3 and later chips"
+ depends on ARCH_OMAP
default y
---help---
Enables support for the on-chip EHCI controller on
OMAP3 and later chips.
+ If your system uses a PHY on the USB port, you will need to
+ enable USB_PHY and the appropriate PHY driver as well. Most
+ boards need the NOP_USB_XCEIV PHY driver.
+
+config USB_EHCI_HCD_ORION
+ tristate "Support for Marvell EBU on-chip EHCI USB controller"
+ depends on USB_EHCI_HCD && PLAT_ORION
+ default y
+ ---help---
+ Enables support for the on-chip EHCI controller on Marvell's
+ embedded ARM SoCs, including Orion, Kirkwood, Dove, Armada XP,
+ Armada 370. This is different from the EHCI implementation
+ on Marvell's mobile PXA and MMP SoC, see "EHCI support for
+ Marvell PXA/MMP USB controller" for those.
+
+config USB_EHCI_HCD_SPEAR
+ tristate "Support for ST SPEAr on-chip EHCI USB controller"
+ depends on USB_EHCI_HCD && PLAT_SPEAR
+ default y
+ ---help---
+ Enables support for the on-chip EHCI controller on
+ ST SPEAr chips.
+
+config USB_EHCI_HCD_AT91
+ tristate "Support for Atmel on-chip EHCI USB controller"
+ depends on USB_EHCI_HCD && ARCH_AT91
+ default y
+ ---help---
+ Enables support for the on-chip EHCI controller on
+ Atmel chips.
config USB_EHCI_MSM
- bool "Support for MSM on-chip EHCI USB controller"
- depends on USB_EHCI_HCD && ARCH_MSM
+ tristate "Support for Qualcomm QSD/MSM on-chip EHCI USB controller"
+ depends on ARCH_MSM
+ depends on USB_PHY
select USB_EHCI_ROOT_HUB_TT
select USB_MSM_OTG
---help---
@@ -177,15 +201,16 @@ config USB_EHCI_MSM
config USB_EHCI_TEGRA
boolean "NVIDIA Tegra HCD support"
- depends on USB_EHCI_HCD && ARCH_TEGRA
+ depends on ARCH_TEGRA
select USB_EHCI_ROOT_HUB_TT
+ select USB_PHY
help
This driver enables support for the internal USB Host Controllers
found in NVIDIA Tegra SoCs. The controllers are EHCI compliant.
config USB_EHCI_HCD_PPC_OF
bool "EHCI support for PPC USB controller on OF platform bus"
- depends on USB_EHCI_HCD && PPC_OF
+ depends on PPC_OF
default y
---help---
Enables support for the USB controller present on the PowerPC
@@ -193,35 +218,40 @@ config USB_EHCI_HCD_PPC_OF
config USB_EHCI_SH
bool "EHCI support for SuperH USB controller"
- depends on USB_EHCI_HCD && SUPERH
+ depends on SUPERH
---help---
Enables support for the on-chip EHCI controller on the SuperH.
If you use the PCI EHCI controller, this option is not necessary.
config USB_EHCI_S5P
- boolean "S5P EHCI support"
- depends on USB_EHCI_HCD && PLAT_S5P
+ tristate "EHCI support for Samsung S5P/EXYNOS SoC Series"
+ depends on PLAT_S5P
help
- Enable support for the S5P SOC's on-chip EHCI controller.
+ Enable support for the Samsung S5Pxxxx and Exynos3/4/5 SOC's
+ on-chip EHCI controller.
config USB_EHCI_MV
- bool "EHCI support for Marvell on-chip controller"
- depends on USB_EHCI_HCD && (ARCH_PXA || ARCH_MMP)
+ bool "EHCI support for Marvell PXA/MMP USB controller"
+ depends on (ARCH_PXA || ARCH_MMP)
select USB_EHCI_ROOT_HUB_TT
---help---
Enables support for Marvell (including PXA and MMP series) on-chip
USB SPH and OTG controller. SPH is a single port host, and it can
only be EHCI host. OTG is controller that can switch to host mode.
+ Note that this driver will not work on Marvell's other EHCI
+ controller used by the EBU-type SoCs including Orion, Kirkwood,
+ Dova, Armada 370 and Armada XP. See "Support for Marvell EBU
+ on-chip EHCI USB controller" for those.
config USB_W90X900_EHCI
bool "W90X900(W90P910) EHCI support"
- depends on USB_EHCI_HCD && ARCH_W90X900
+ depends on ARCH_W90X900
---help---
Enables support for the W90X900 USB controller
config USB_CNS3XXX_EHCI
bool "Cavium CNS3XXX EHCI Module (DEPRECATED)"
- depends on USB_EHCI_HCD && ARCH_CNS3XXX
+ depends on ARCH_CNS3XXX
select USB_EHCI_HCD_PLATFORM
---help---
This option is deprecated now and the driver was removed, use
@@ -233,7 +263,7 @@ config USB_CNS3XXX_EHCI
config USB_EHCI_ATH79
bool "EHCI support for AR7XXX/AR9XXX SoCs (DEPRECATED)"
- depends on USB_EHCI_HCD && (SOC_AR71XX || SOC_AR724X || SOC_AR913X || SOC_AR933X)
+ depends on (SOC_AR71XX || SOC_AR724X || SOC_AR913X || SOC_AR933X)
select USB_EHCI_ROOT_HUB_TT
select USB_EHCI_HCD_PLATFORM
default y
@@ -244,9 +274,31 @@ config USB_EHCI_ATH79
Enables support for the built-in EHCI controller present
on the Atheros AR7XXX/AR9XXX SoCs.
+config USB_EHCI_HCD_PLATFORM
+ tristate "Generic EHCI driver for a platform device"
+ default n
+ ---help---
+ Adds an EHCI host driver for a generic platform device, which
+ provides a memory space and an irq.
+
+ If unsure, say N.
+
+config USB_OCTEON_EHCI
+ bool "Octeon on-chip EHCI support"
+ depends on CPU_CAVIUM_OCTEON
+ default n
+ select USB_EHCI_BIG_ENDIAN_MMIO
+ help
+ Enable support for the Octeon II SOC's on-chip EHCI
+ controller. It is needed for high-speed (480Mbit/sec)
+ USB 2.0 device support. All CN6XXX based chips with USB are
+ supported.
+
+endif # USB_EHCI_HCD
+
config USB_OXU210HP_HCD
tristate "OXU210HP HCD support"
- depends on USB && GENERIC_HARDIRQS
+ depends on GENERIC_HARDIRQS
---help---
The OXU210HP is an USB host/OTG/device controller. Enable this
option if your board has this chip. If unsure, say N.
@@ -259,7 +311,6 @@ config USB_OXU210HP_HCD
config USB_ISP116X_HCD
tristate "ISP116X HCD support"
- depends on USB
---help---
The ISP1160 and ISP1161 chips are USB host controllers. Enable this
option if your board has this chip. If unsure, say N.
@@ -271,7 +322,6 @@ config USB_ISP116X_HCD
config USB_ISP1760_HCD
tristate "ISP 1760 HCD support"
- depends on USB
---help---
The ISP1760 chip is a USB 2.0 host controller.
@@ -286,7 +336,6 @@ config USB_ISP1760_HCD
config USB_ISP1362_HCD
tristate "ISP1362 HCD support"
- depends on USB
default N
---help---
Supports the Philips ISP1362 chip as a host controller
@@ -298,9 +347,8 @@ config USB_ISP1362_HCD
config USB_OHCI_HCD
tristate "OHCI HCD support"
- depends on USB && USB_ARCH_HAS_OHCI
+ depends on USB_ARCH_HAS_OHCI
select ISP1301_OMAP if MACH_OMAP_H2 || MACH_OMAP_H3
- select USB_OTG_UTILS if ARCH_OMAP
depends on USB_ISP1301 || !ARCH_LPC32XX
---help---
The Open Host Controller Interface (OHCI) is a standard for accessing
@@ -315,16 +363,18 @@ config USB_OHCI_HCD
To compile this driver as a module, choose M here: the
module will be called ohci-hcd.
+if USB_OHCI_HCD
+
config USB_OHCI_HCD_OMAP1
bool "OHCI support for OMAP1/2 chips"
- depends on USB_OHCI_HCD && ARCH_OMAP1
+ depends on ARCH_OMAP1
default y
---help---
Enables support for the OHCI controller on OMAP1/2 chips.
config USB_OHCI_HCD_OMAP3
bool "OHCI support for OMAP3 and later chips"
- depends on USB_OHCI_HCD && (ARCH_OMAP3 || ARCH_OMAP4)
+ depends on (ARCH_OMAP3 || ARCH_OMAP4)
default y
---help---
Enables support for the on-chip OHCI controller on
@@ -332,7 +382,7 @@ config USB_OHCI_HCD_OMAP3
config USB_OHCI_ATH79
bool "USB OHCI support for the Atheros AR71XX/AR7240 SoCs (DEPRECATED)"
- depends on USB_OHCI_HCD && (SOC_AR71XX || SOC_AR724X)
+ depends on (SOC_AR71XX || SOC_AR724X)
select USB_OHCI_HCD_PLATFORM
default y
help
@@ -344,7 +394,7 @@ config USB_OHCI_ATH79
config USB_OHCI_HCD_PPC_OF_BE
bool "OHCI support for OF platform bus (big endian)"
- depends on USB_OHCI_HCD && PPC_OF
+ depends on PPC_OF
select USB_OHCI_BIG_ENDIAN_DESC
select USB_OHCI_BIG_ENDIAN_MMIO
---help---
@@ -353,7 +403,7 @@ config USB_OHCI_HCD_PPC_OF_BE
config USB_OHCI_HCD_PPC_OF_LE
bool "OHCI support for OF platform bus (little endian)"
- depends on USB_OHCI_HCD && PPC_OF
+ depends on PPC_OF
select USB_OHCI_LITTLE_ENDIAN
---help---
Enables support for little-endian USB controllers present on the
@@ -361,12 +411,12 @@ config USB_OHCI_HCD_PPC_OF_LE
config USB_OHCI_HCD_PPC_OF
bool
- depends on USB_OHCI_HCD && PPC_OF
+ depends on PPC_OF
default USB_OHCI_HCD_PPC_OF_BE || USB_OHCI_HCD_PPC_OF_LE
config USB_OHCI_HCD_PCI
bool "OHCI support for PCI-bus USB controllers"
- depends on USB_OHCI_HCD && PCI && (STB03xxx || PPC_MPC52xx || USB_OHCI_HCD_PPC_OF)
+ depends on PCI && (STB03xxx || PPC_MPC52xx || USB_OHCI_HCD_PPC_OF)
default y
select USB_OHCI_LITTLE_ENDIAN
---help---
@@ -375,7 +425,7 @@ config USB_OHCI_HCD_PCI
config USB_OHCI_HCD_SSB
bool "OHCI support for Broadcom SSB OHCI core (DEPRECATED)"
- depends on USB_OHCI_HCD && (SSB = y || SSB = USB_OHCI_HCD)
+ depends on (SSB = y || SSB = USB_OHCI_HCD)
select USB_HCD_SSB
select USB_OHCI_HCD_PLATFORM
default n
@@ -393,7 +443,7 @@ config USB_OHCI_HCD_SSB
config USB_OHCI_SH
bool "OHCI support for SuperH USB controller (DEPRECATED)"
- depends on USB_OHCI_HCD && SUPERH
+ depends on SUPERH
select USB_OHCI_HCD_PLATFORM
---help---
This option is deprecated now and the driver was removed, use
@@ -404,13 +454,13 @@ config USB_OHCI_SH
config USB_OHCI_EXYNOS
boolean "OHCI support for Samsung EXYNOS SoC Series"
- depends on USB_OHCI_HCD && ARCH_EXYNOS
+ depends on ARCH_EXYNOS
help
Enable support for the Samsung Exynos SOC's on-chip OHCI controller.
config USB_CNS3XXX_OHCI
bool "Cavium CNS3XXX OHCI Module (DEPRECATED)"
- depends on USB_OHCI_HCD && ARCH_CNS3XXX
+ depends on ARCH_CNS3XXX
select USB_OHCI_HCD_PLATFORM
---help---
This option is deprecated now and the driver was removed, use
@@ -421,7 +471,6 @@ config USB_CNS3XXX_OHCI
config USB_OHCI_HCD_PLATFORM
bool "Generic OHCI driver for a platform device"
- depends on USB_OHCI_HCD
default n
---help---
Adds an OHCI host driver for a generic platform device, which
@@ -429,35 +478,36 @@ config USB_OHCI_HCD_PLATFORM
If unsure, say N.
-config USB_EHCI_HCD_PLATFORM
- tristate "Generic EHCI driver for a platform device"
- depends on USB_EHCI_HCD
- default n
- ---help---
- Adds an EHCI host driver for a generic platform device, which
- provides a memory space and an irq.
+config USB_OCTEON_OHCI
+ bool "Octeon on-chip OHCI support"
+ depends on CPU_CAVIUM_OCTEON
+ default USB_OCTEON_EHCI
+ select USB_OHCI_BIG_ENDIAN_MMIO
+ select USB_OHCI_LITTLE_ENDIAN
+ help
+ Enable support for the Octeon II SOC's on-chip OHCI
+ controller. It is needed for low-speed USB 1.0 device
+ support. All CN6XXX based chips with USB are supported.
- If unsure, say N.
config USB_OHCI_BIG_ENDIAN_DESC
bool
- depends on USB_OHCI_HCD
default n
config USB_OHCI_BIG_ENDIAN_MMIO
bool
- depends on USB_OHCI_HCD
default n
config USB_OHCI_LITTLE_ENDIAN
bool
- depends on USB_OHCI_HCD
default n if STB03xxx || PPC_MPC52xx
default y
+endif # USB_OHCI_HCD
+
config USB_UHCI_HCD
tristate "UHCI HCD (most Intel and VIA) support"
- depends on USB && (PCI || SPARC_LEON || ARCH_VT8500)
+ depends on PCI || SPARC_LEON || ARCH_VT8500
---help---
The Universal Host Controller Interface is a standard by Intel for
accessing the USB hardware in the PC (which is also called the USB
@@ -497,7 +547,7 @@ config USB_UHCI_BIG_ENDIAN_DESC
config USB_FHCI_HCD
tristate "Freescale QE USB Host Controller support"
- depends on USB && OF_GPIO && QE_GPIO && QUICC_ENGINE
+ depends on OF_GPIO && QE_GPIO && QUICC_ENGINE
select FSL_GTM
select QE_USB
help
@@ -514,7 +564,7 @@ config FHCI_DEBUG
config USB_U132_HCD
tristate "Elan U132 Adapter Host Controller"
- depends on USB && USB_FTDI_ELAN
+ depends on USB_FTDI_ELAN
default M
help
The U132 adapter is a USB to CardBus adapter specifically designed
@@ -542,7 +592,6 @@ config USB_U132_HCD
config USB_SL811_HCD
tristate "SL811HS HCD support"
- depends on USB
help
The SL811HS is a single-port USB controller that supports either
host side or peripheral side roles. Enable this option if your
@@ -574,7 +623,6 @@ config USB_SL811_CS
config USB_R8A66597_HCD
tristate "R8A66597 HCD support"
- depends on USB
help
The R8A66597 is a USB 2.0 host and peripheral controller.
@@ -586,7 +634,6 @@ config USB_R8A66597_HCD
config USB_RENESAS_USBHS_HCD
tristate "Renesas USBHS HCD support"
- depends on USB
depends on USB_RENESAS_USBHS
help
The Renesas USBHS is a USB 2.0 host and peripheral controller.
@@ -611,7 +658,7 @@ config USB_WHCI_HCD
config USB_HWA_HCD
tristate "Host Wire Adapter (HWA) driver"
- depends on USB && UWB
+ depends on UWB
select USB_WUSB
select UWB_HWA
help
@@ -625,7 +672,7 @@ config USB_HWA_HCD
config USB_IMX21_HCD
tristate "i.MX21 HCD support"
- depends on USB && ARM && ARCH_MXC
+ depends on ARM && ARCH_MXC
help
This driver enables support for the on-chip USB host in the
i.MX21 processor.
@@ -633,27 +680,7 @@ config USB_IMX21_HCD
To compile this driver as a module, choose M here: the
module will be called "imx21-hcd".
-config USB_OCTEON_EHCI
- bool "Octeon on-chip EHCI support"
- depends on USB && USB_EHCI_HCD && CPU_CAVIUM_OCTEON
- default n
- select USB_EHCI_BIG_ENDIAN_MMIO
- help
- Enable support for the Octeon II SOC's on-chip EHCI
- controller. It is needed for high-speed (480Mbit/sec)
- USB 2.0 device support. All CN6XXX based chips with USB are
- supported.
-config USB_OCTEON_OHCI
- bool "Octeon on-chip OHCI support"
- depends on USB && USB_OHCI_HCD && CPU_CAVIUM_OCTEON
- default USB_OCTEON_EHCI
- select USB_OHCI_BIG_ENDIAN_MMIO
- select USB_OHCI_LITTLE_ENDIAN
- help
- Enable support for the Octeon II SOC's on-chip OHCI
- controller. It is needed for low-speed USB 1.0 device
- support. All CN6XXX based chips with USB are supported.
config USB_OCTEON2_COMMON
bool
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index 001fbff2fde..4fb73c156d7 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -27,6 +27,12 @@ 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_EHCI_MXC) += ehci-mxc.o
+obj-$(CONFIG_USB_EHCI_HCD_OMAP) += ehci-omap.o
+obj-$(CONFIG_USB_EHCI_HCD_ORION) += ehci-orion.o
+obj-$(CONFIG_USB_EHCI_HCD_SPEAR) += ehci-spear.o
+obj-$(CONFIG_USB_EHCI_S5P) += ehci-s5p.o
+obj-$(CONFIG_USB_EHCI_HCD_AT91) += ehci-atmel.o
+obj-$(CONFIG_USB_EHCI_MSM) += ehci-msm.o
obj-$(CONFIG_USB_OXU210HP_HCD) += oxu210hp-hcd.o
obj-$(CONFIG_USB_ISP116X_HCD) += isp116x-hcd.o
diff --git a/drivers/usb/host/ehci-atmel.c b/drivers/usb/host/ehci-atmel.c
index f3beac4d06b..66420097c24 100644
--- a/drivers/usb/host/ehci-atmel.c
+++ b/drivers/usb/host/ehci-atmel.c
@@ -12,9 +12,22 @@
*/
#include <linux/clk.h>
-#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/usb.h>
+#include <linux/usb/hcd.h>
+
+#include "ehci.h"
+
+#define DRIVER_DESC "EHCI Atmel driver"
+
+static const char hcd_name[] = "ehci-atmel";
+static struct hc_driver __read_mostly ehci_atmel_hc_driver;
/* interface and function clocks */
static struct clk *iclk, *fclk;
@@ -50,51 +63,6 @@ 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);
-
- /* registers start at offset 0x0 */
- ehci->caps = hcd->regs;
-
- return ehci_setup(hcd);
-}
-
-static const struct hc_driver ehci_atmel_hc_driver = {
- .description = hcd_name,
- .product_desc = "Atmel EHCI UHP HS",
- .hcd_priv_size = sizeof(struct ehci_hcd),
-
- /* generic hardware linkage */
- .irq = ehci_irq,
- .flags = HCD_MEMORY | HCD_USB2,
-
- /* basic lifecycle operations */
- .reset = ehci_atmel_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 u64 at91_ehci_dma_mask = DMA_BIT_MASK(32);
static int ehci_atmel_drv_probe(struct platform_device *pdev)
@@ -102,6 +70,7 @@ static int ehci_atmel_drv_probe(struct platform_device *pdev)
struct usb_hcd *hcd;
const struct hc_driver *driver = &ehci_atmel_hc_driver;
struct resource *res;
+ struct ehci_hcd *ehci;
int irq;
int retval;
@@ -162,6 +131,10 @@ static int ehci_atmel_drv_probe(struct platform_device *pdev)
goto fail_request_resource;
}
+ ehci = hcd_to_ehci(hcd);
+ /* registers start at offset 0x0 */
+ ehci->caps = hcd->regs;
+
atmel_start_ehci(pdev);
retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
@@ -185,7 +158,6 @@ static int ehci_atmel_drv_remove(struct platform_device *pdev)
{
struct usb_hcd *hcd = platform_get_drvdata(pdev);
- ehci_shutdown(hcd);
usb_remove_hcd(hcd);
usb_put_hcd(hcd);
@@ -213,3 +185,25 @@ static struct platform_driver ehci_atmel_driver = {
.of_match_table = of_match_ptr(atmel_ehci_dt_ids),
},
};
+
+static int __init ehci_atmel_init(void)
+{
+ if (usb_disabled())
+ return -ENODEV;
+
+ pr_info("%s: " DRIVER_DESC "\n", hcd_name);
+ ehci_init_driver(&ehci_atmel_hc_driver, NULL);
+ return platform_driver_register(&ehci_atmel_driver);
+}
+module_init(ehci_atmel_init);
+
+static void __exit ehci_atmel_cleanup(void)
+{
+ platform_driver_unregister(&ehci_atmel_driver);
+}
+module_exit(ehci_atmel_cleanup);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_ALIAS("platform:atmel-ehci");
+MODULE_AUTHOR("Nicolas Ferre");
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c
index 70b496dc18a..5429d2645bb 100644
--- a/drivers/usb/host/ehci-dbg.c
+++ b/drivers/usb/host/ehci-dbg.c
@@ -510,14 +510,16 @@ static ssize_t fill_async_buffer(struct debug_buffer *buf)
spin_lock_irqsave (&ehci->lock, flags);
for (qh = ehci->async->qh_next.qh; size > 0 && qh; qh = qh->qh_next.qh)
qh_lines (ehci, qh, &next, &size);
- if (ehci->async_unlink && size > 0) {
+ if (!list_empty(&ehci->async_unlink) && size > 0) {
temp = scnprintf(next, size, "\nunlink =\n");
size -= temp;
next += temp;
- for (qh = ehci->async_unlink; size > 0 && qh;
- qh = qh->unlink_next)
- qh_lines (ehci, qh, &next, &size);
+ list_for_each_entry(qh, &ehci->async_unlink, unlink_node) {
+ if (size <= 0)
+ break;
+ qh_lines(ehci, qh, &next, &size);
+ }
}
spin_unlock_irqrestore (&ehci->lock, flags);
@@ -814,9 +816,10 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf)
}
}
- if (ehci->async_unlink) {
+ if (!list_empty(&ehci->async_unlink)) {
temp = scnprintf(next, size, "async unlink qh %p\n",
- ehci->async_unlink);
+ list_first_entry(&ehci->async_unlink,
+ struct ehci_qh, unlink_node));
size -= temp;
next += temp;
}
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
index d81d2fcbff1..3be3df233a0 100644
--- a/drivers/usb/host/ehci-fsl.c
+++ b/drivers/usb/host/ehci-fsl.c
@@ -370,6 +370,15 @@ static int ehci_fsl_setup(struct usb_hcd *hcd)
/* EHCI registers start at offset 0x100 */
ehci->caps = hcd->regs + 0x100;
+#ifdef CONFIG_PPC_83xx
+ /*
+ * Deal with MPC834X that need port power to be cycled after the power
+ * fault condition is removed. Otherwise the state machine does not
+ * reflect PORTSC[CSC] correctly.
+ */
+ ehci->need_oc_pp_cycle = 1;
+#endif
+
hcd->has_tt = 1;
retval = ehci_setup(hcd);
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index b416a3fc995..312fc10da3c 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -302,6 +302,7 @@ static void ehci_quiesce (struct ehci_hcd *ehci)
static void end_unlink_async(struct ehci_hcd *ehci);
static void unlink_empty_async(struct ehci_hcd *ehci);
+static void unlink_empty_async_suspended(struct ehci_hcd *ehci);
static void ehci_work(struct ehci_hcd *ehci);
static void start_unlink_intr(struct ehci_hcd *ehci, struct ehci_qh *qh);
static void end_unlink_intr(struct ehci_hcd *ehci, struct ehci_qh *qh);
@@ -481,6 +482,9 @@ static int ehci_init(struct usb_hcd *hcd)
* periodic_size can shrink by USBCMD update if hcc_params allows.
*/
ehci->periodic_size = DEFAULT_I_TDPS;
+ INIT_LIST_HEAD(&ehci->async_unlink);
+ INIT_LIST_HEAD(&ehci->async_idle);
+ INIT_LIST_HEAD(&ehci->intr_unlink);
INIT_LIST_HEAD(&ehci->intr_qh_list);
INIT_LIST_HEAD(&ehci->cached_itd_list);
INIT_LIST_HEAD(&ehci->cached_sitd_list);
@@ -669,9 +673,6 @@ int ehci_setup(struct usb_hcd *hcd)
if (retval)
return retval;
- if (ehci_is_TDI(ehci))
- tdi_reset(ehci);
-
ehci_reset(ehci);
return 0;
@@ -748,17 +749,15 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
/* guard against (alleged) silicon errata */
if (cmd & CMD_IAAD)
ehci_dbg(ehci, "IAA with IAAD still set?\n");
- if (ehci->async_iaa) {
+ if (ehci->iaa_in_progress)
COUNT(ehci->stats.iaa);
- end_unlink_async(ehci);
- } else
- ehci_dbg(ehci, "IAA with nothing unlinked?\n");
+ end_unlink_async(ehci);
}
/* remote wakeup [4.3.1] */
if (status & STS_PCD) {
unsigned i = HCS_N_PORTS (ehci->hcs_params);
- u32 ppcd = 0;
+ u32 ppcd = ~0;
/* kick root hub later */
pcd_status = status;
@@ -775,7 +774,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
int pstatus;
/* leverage per-port change bits feature */
- if (ehci->has_ppcd && !(ppcd & (1 << i)))
+ if (!(ppcd & (1 << i)))
continue;
pstatus = ehci_readl(ehci,
&ehci->regs->port_status[i]);
@@ -897,17 +896,24 @@ static int ehci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
if (rc)
goto done;
- switch (usb_pipetype (urb->pipe)) {
- // case PIPE_CONTROL:
- // case PIPE_BULK:
- default:
+ if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
+ /*
+ * We don't expedite dequeue for isochronous URBs.
+ * Just wait until they complete normally or their
+ * time slot expires.
+ */
+ } else {
qh = (struct ehci_qh *) urb->hcpriv;
- if (!qh)
- break;
+ qh->exception = 1;
switch (qh->qh_state) {
case QH_STATE_LINKED:
+ if (usb_pipetype(urb->pipe) == PIPE_INTERRUPT)
+ start_unlink_intr(ehci, qh);
+ else
+ start_unlink_async(ehci, qh);
+ break;
case QH_STATE_COMPLETING:
- start_unlink_async(ehci, qh);
+ qh->dequeue_during_giveback = 1;
break;
case QH_STATE_UNLINK:
case QH_STATE_UNLINK_WAIT:
@@ -918,33 +924,6 @@ static int ehci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
qh_completions(ehci, qh);
break;
}
- break;
-
- case PIPE_INTERRUPT:
- qh = (struct ehci_qh *) urb->hcpriv;
- if (!qh)
- break;
- switch (qh->qh_state) {
- case QH_STATE_LINKED:
- case QH_STATE_COMPLETING:
- start_unlink_intr(ehci, qh);
- break;
- case QH_STATE_IDLE:
- qh_completions (ehci, qh);
- break;
- default:
- ehci_dbg (ehci, "bogus qh %p state %d\n",
- qh, qh->qh_state);
- goto done;
- }
- break;
-
- case PIPE_ISOCHRONOUS:
- // itd or sitd ...
-
- // wait till next completion, do it then.
- // completion irqs can wait up to 1024 msec,
- break;
}
done:
spin_unlock_irqrestore (&ehci->lock, flags);
@@ -985,6 +964,7 @@ rescan:
goto done;
}
+ qh->exception = 1;
if (ehci->rh_state < EHCI_RH_RUNNING)
qh->qh_state = QH_STATE_IDLE;
switch (qh->qh_state) {
@@ -1053,13 +1033,12 @@ ehci_endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep)
usb_settoggle(qh->dev, epnum, is_out, 0);
if (!list_empty(&qh->qtd_list)) {
WARN_ONCE(1, "clear_halt for a busy endpoint\n");
- } else if (qh->qh_state == QH_STATE_LINKED ||
- qh->qh_state == QH_STATE_COMPLETING) {
-
+ } else {
/* The toggle value in the QH can't be updated
* while the QH is active. Unlink it now;
* re-linking will call qh_refresh().
*/
+ qh->exception = 1;
if (eptype == USB_ENDPOINT_XFER_BULK)
start_unlink_async(ehci, qh);
else
@@ -1252,11 +1231,6 @@ MODULE_LICENSE ("GPL");
#define PLATFORM_DRIVER ehci_hcd_sh_driver
#endif
-#ifdef CONFIG_USB_EHCI_HCD_OMAP
-#include "ehci-omap.c"
-#define PLATFORM_DRIVER ehci_hcd_omap_driver
-#endif
-
#ifdef CONFIG_PPC_PS3
#include "ehci-ps3.c"
#define PS3_SYSTEM_BUS_DRIVER ps3_ehci_driver
@@ -1272,41 +1246,16 @@ MODULE_LICENSE ("GPL");
#define XILINX_OF_PLATFORM_DRIVER ehci_hcd_xilinx_of_driver
#endif
-#ifdef CONFIG_PLAT_ORION
-#include "ehci-orion.c"
-#define PLATFORM_DRIVER ehci_orion_driver
-#endif
-
#ifdef CONFIG_USB_W90X900_EHCI
#include "ehci-w90x900.c"
#define PLATFORM_DRIVER ehci_hcd_w90x900_driver
#endif
-#ifdef CONFIG_ARCH_AT91
-#include "ehci-atmel.c"
-#define PLATFORM_DRIVER ehci_atmel_driver
-#endif
-
#ifdef CONFIG_USB_OCTEON_EHCI
#include "ehci-octeon.c"
#define PLATFORM_DRIVER ehci_octeon_driver
#endif
-#ifdef CONFIG_ARCH_VT8500
-#include "ehci-vt8500.c"
-#define PLATFORM_DRIVER vt8500_ehci_driver
-#endif
-
-#ifdef CONFIG_PLAT_SPEAR
-#include "ehci-spear.c"
-#define PLATFORM_DRIVER spear_ehci_hcd_driver
-#endif
-
-#ifdef CONFIG_USB_EHCI_MSM
-#include "ehci-msm.c"
-#define PLATFORM_DRIVER ehci_msm_driver
-#endif
-
#ifdef CONFIG_TILE_USB
#include "ehci-tilegx.c"
#define PLATFORM_DRIVER ehci_hcd_tilegx_driver
@@ -1322,11 +1271,6 @@ MODULE_LICENSE ("GPL");
#define PLATFORM_DRIVER tegra_ehci_driver
#endif
-#ifdef CONFIG_USB_EHCI_S5P
-#include "ehci-s5p.c"
-#define PLATFORM_DRIVER s5p_ehci_driver
-#endif
-
#ifdef CONFIG_SPARC_LEON
#include "ehci-grlib.c"
#define PLATFORM_DRIVER ehci_grlib_driver
@@ -1346,6 +1290,12 @@ MODULE_LICENSE ("GPL");
!IS_ENABLED(CONFIG_USB_EHCI_HCD_PLATFORM) && \
!IS_ENABLED(CONFIG_USB_CHIPIDEA_HOST) && \
!IS_ENABLED(CONFIG_USB_EHCI_MXC) && \
+ !IS_ENABLED(CONFIG_USB_EHCI_HCD_OMAP) && \
+ !IS_ENABLED(CONFIG_USB_EHCI_HCD_ORION) && \
+ !IS_ENABLED(CONFIG_USB_EHCI_HCD_SPEAR) && \
+ !IS_ENABLED(CONFIG_USB_EHCI_S5P) && \
+ !IS_ENABLED(CONFIG_USB_EHCI_HCD_AT91) && \
+ !IS_ENABLED(CONFIG_USB_EHCI_MSM) && \
!defined(PLATFORM_DRIVER) && \
!defined(PS3_SYSTEM_BUS_DRIVER) && \
!defined(OF_PLATFORM_DRIVER) && \
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index 4d3b294f203..9ab4a4d9768 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -328,7 +328,7 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
ehci->rh_state = EHCI_RH_SUSPENDED;
end_unlink_async(ehci);
- unlink_empty_async(ehci);
+ unlink_empty_async_suspended(ehci);
ehci_handle_intr_unlinks(ehci);
end_free_itds(ehci);
@@ -464,7 +464,7 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
while (i--) {
temp = ehci_readl(ehci, &ehci->regs->port_status [i]);
if (test_bit(i, &resume_needed)) {
- temp &= ~(PORT_RWC_BITS | PORT_RESUME);
+ temp &= ~(PORT_RWC_BITS | PORT_SUSPEND | PORT_RESUME);
ehci_writel(ehci, temp, &ehci->regs->port_status [i]);
ehci_vdbg (ehci, "resumed port %d\n", i + 1);
}
@@ -590,7 +590,7 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf)
u32 mask;
int ports, i, retval = 1;
unsigned long flags;
- u32 ppcd = 0;
+ u32 ppcd = ~0;
/* init status to no-changes */
buf [0] = 0;
@@ -628,9 +628,10 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf)
for (i = 0; i < ports; i++) {
/* leverage per-port change bits feature */
- if (ehci->has_ppcd && !(ppcd & (1 << i)))
- continue;
- temp = ehci_readl(ehci, &ehci->regs->port_status [i]);
+ if (ppcd & (1 << i))
+ temp = ehci_readl(ehci, &ehci->regs->port_status[i]);
+ else
+ temp = 0;
/*
* Return status information even for ports with OWNER set.
@@ -839,7 +840,8 @@ static int ehci_hub_control (
* power switching; they're allowed to just limit the
* current. khubd will turn the power back on.
*/
- if ((temp & PORT_OC) && HCS_PPC(ehci->hcs_params)) {
+ if (((temp & PORT_OC) || (ehci->need_oc_pp_cycle))
+ && HCS_PPC(ehci->hcs_params)) {
ehci_writel(ehci,
temp & ~(PORT_RWC_BITS | PORT_POWER),
status_reg);
@@ -870,10 +872,9 @@ static int ehci_hub_control (
usb_hcd_end_port_resume(&hcd->self, wIndex);
/* stop resume signaling */
- temp = ehci_readl(ehci, status_reg);
- ehci_writel(ehci,
- temp & ~(PORT_RWC_BITS | PORT_RESUME),
- status_reg);
+ temp &= ~(PORT_RWC_BITS |
+ PORT_SUSPEND | PORT_RESUME);
+ ehci_writel(ehci, temp, status_reg);
clear_bit(wIndex, &ehci->resuming_ports);
retval = handshake(ehci, status_reg,
PORT_RESUME, 0, 2000 /* 2msec */);
@@ -883,7 +884,7 @@ static int ehci_hub_control (
wIndex + 1, retval);
goto error;
}
- temp &= ~(PORT_SUSPEND|PORT_RESUME|(3<<10));
+ temp = ehci_readl(ehci, status_reg);
}
}
diff --git a/drivers/usb/host/ehci-msm.c b/drivers/usb/host/ehci-msm.c
index 88a49c87e74..0f717dc688b 100644
--- a/drivers/usb/host/ehci-msm.c
+++ b/drivers/usb/host/ehci-msm.c
@@ -22,16 +22,26 @@
* along with this program; if not, you can find it at http://www.fsf.org
*/
-#include <linux/platform_device.h>
#include <linux/clk.h>
#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
-
#include <linux/usb/otg.h>
#include <linux/usb/msm_hsusb_hw.h>
+#include <linux/usb.h>
+#include <linux/usb/hcd.h>
+
+#include "ehci.h"
#define MSM_USB_BASE (hcd->regs)
+#define DRIVER_DESC "Qualcomm On-Chip EHCI Host Controller"
+
+static const char hcd_name[] = "ehci-msm";
+static struct hc_driver __read_mostly msm_hc_driver;
static struct usb_phy *phy;
static int ehci_msm_reset(struct usb_hcd *hcd)
@@ -56,52 +66,6 @@ static int ehci_msm_reset(struct usb_hcd *hcd)
return 0;
}
-static struct hc_driver msm_hc_driver = {
- .description = hcd_name,
- .product_desc = "Qualcomm On-Chip EHCI Host Controller",
- .hcd_priv_size = sizeof(struct ehci_hcd),
-
- /*
- * generic hardware linkage
- */
- .irq = ehci_irq,
- .flags = HCD_USB2 | HCD_MEMORY,
-
- .reset = ehci_msm_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,
- .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,
- .relinquish_port = ehci_relinquish_port,
- .port_handed_over = ehci_port_handed_over,
-
- /*
- * PM support
- */
- .bus_suspend = ehci_bus_suspend,
- .bus_resume = ehci_bus_resume,
-};
-
static int ehci_msm_probe(struct platform_device *pdev)
{
struct usb_hcd *hcd;
@@ -145,7 +109,7 @@ static int ehci_msm_probe(struct platform_device *pdev)
* management.
*/
phy = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2);
- if (IS_ERR_OR_NULL(phy)) {
+ if (IS_ERR(phy)) {
dev_err(&pdev->dev, "unable to find transceiver\n");
ret = -ENODEV;
goto put_hcd;
@@ -165,6 +129,8 @@ static int ehci_msm_probe(struct platform_device *pdev)
pm_runtime_no_callbacks(&pdev->dev);
pm_runtime_enable(&pdev->dev);
+ /* FIXME: need to call usb_add_hcd() here? */
+
return 0;
put_hcd:
@@ -183,6 +149,8 @@ static int ehci_msm_remove(struct platform_device *pdev)
otg_set_host(phy->otg, NULL);
+ /* FIXME: need to call usb_remove_hcd() here? */
+
usb_put_hcd(hcd);
return 0;
@@ -226,3 +194,28 @@ static struct platform_driver ehci_msm_driver = {
.pm = &ehci_msm_dev_pm_ops,
},
};
+
+static const struct ehci_driver_overrides msm_overrides __initdata = {
+ .reset = ehci_msm_reset,
+};
+
+static int __init ehci_msm_init(void)
+{
+ if (usb_disabled())
+ return -ENODEV;
+
+ pr_info("%s: " DRIVER_DESC "\n", hcd_name);
+ ehci_init_driver(&msm_hc_driver, &msm_overrides);
+ return platform_driver_register(&ehci_msm_driver);
+}
+module_init(ehci_msm_init);
+
+static void __exit ehci_msm_cleanup(void)
+{
+ platform_driver_unregister(&ehci_msm_driver);
+}
+module_exit(ehci_msm_cleanup);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_ALIAS("platform:msm-ehci");
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/host/ehci-mv.c b/drivers/usb/host/ehci-mv.c
index 3065809546b..402062973f0 100644
--- a/drivers/usb/host/ehci-mv.c
+++ b/drivers/usb/host/ehci-mv.c
@@ -33,25 +33,17 @@ struct ehci_hcd_mv {
struct mv_usb_platform_data *pdata;
- /* clock source and total clock number */
- unsigned int clknum;
- struct clk *clk[0];
+ struct clk *clk;
};
static void ehci_clock_enable(struct ehci_hcd_mv *ehci_mv)
{
- unsigned int i;
-
- for (i = 0; i < ehci_mv->clknum; i++)
- clk_prepare_enable(ehci_mv->clk[i]);
+ clk_prepare_enable(ehci_mv->clk);
}
static void ehci_clock_disable(struct ehci_hcd_mv *ehci_mv)
{
- unsigned int i;
-
- for (i = 0; i < ehci_mv->clknum; i++)
- clk_disable_unprepare(ehci_mv->clk[i]);
+ clk_disable_unprepare(ehci_mv->clk);
}
static int mv_ehci_enable(struct ehci_hcd_mv *ehci_mv)
@@ -144,9 +136,8 @@ static int mv_ehci_probe(struct platform_device *pdev)
struct ehci_hcd *ehci;
struct ehci_hcd_mv *ehci_mv;
struct resource *r;
- int clk_i, retval = -ENODEV;
+ int retval = -ENODEV;
u32 offset;
- size_t size;
if (!pdata) {
dev_err(&pdev->dev, "missing platform_data\n");
@@ -160,8 +151,7 @@ static int mv_ehci_probe(struct platform_device *pdev)
if (!hcd)
return -ENOMEM;
- size = sizeof(*ehci_mv) + sizeof(struct clk *) * pdata->clknum;
- ehci_mv = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
+ ehci_mv = devm_kzalloc(&pdev->dev, sizeof(*ehci_mv), GFP_KERNEL);
if (ehci_mv == NULL) {
dev_err(&pdev->dev, "cannot allocate ehci_hcd_mv\n");
retval = -ENOMEM;
@@ -172,16 +162,11 @@ static int mv_ehci_probe(struct platform_device *pdev)
ehci_mv->pdata = pdata;
ehci_mv->hcd = hcd;
- ehci_mv->clknum = pdata->clknum;
- for (clk_i = 0; clk_i < ehci_mv->clknum; clk_i++) {
- ehci_mv->clk[clk_i] =
- devm_clk_get(&pdev->dev, pdata->clkname[clk_i]);
- if (IS_ERR(ehci_mv->clk[clk_i])) {
- dev_err(&pdev->dev, "error get clck \"%s\"\n",
- pdata->clkname[clk_i]);
- retval = PTR_ERR(ehci_mv->clk[clk_i]);
- goto err_clear_drvdata;
- }
+ ehci_mv->clk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(ehci_mv->clk)) {
+ dev_err(&pdev->dev, "error getting clock\n");
+ retval = PTR_ERR(ehci_mv->clk);
+ goto err_clear_drvdata;
}
r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phyregs");
@@ -225,7 +210,7 @@ static int mv_ehci_probe(struct platform_device *pdev)
(void __iomem *) ((unsigned long) ehci_mv->cap_regs + offset);
hcd->rsrc_start = r->start;
- hcd->rsrc_len = r->end - r->start + 1;
+ hcd->rsrc_len = resource_size(r);
hcd->regs = ehci_mv->op_regs;
hcd->irq = platform_get_irq(pdev, 0);
@@ -240,12 +225,16 @@ static int mv_ehci_probe(struct platform_device *pdev)
ehci_mv->mode = pdata->mode;
if (ehci_mv->mode == MV_USB_MODE_OTG) {
-#ifdef CONFIG_USB_OTG_UTILS
ehci_mv->otg = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2);
- if (IS_ERR_OR_NULL(ehci_mv->otg)) {
- dev_err(&pdev->dev,
- "unable to find transceiver\n");
- retval = -ENODEV;
+ if (IS_ERR(ehci_mv->otg)) {
+ retval = PTR_ERR(ehci_mv->otg);
+
+ if (retval == -ENXIO)
+ dev_info(&pdev->dev, "MV_USB_MODE_OTG "
+ "must have CONFIG_USB_PHY enabled\n");
+ else
+ dev_err(&pdev->dev,
+ "unable to find transceiver\n");
goto err_disable_clk;
}
@@ -258,11 +247,6 @@ static int mv_ehci_probe(struct platform_device *pdev)
}
/* otg will enable clock before use as host */
mv_ehci_disable(ehci_mv);
-#else
- dev_info(&pdev->dev, "MV_USB_MODE_OTG "
- "must have CONFIG_USB_OTG_UTILS enabled\n");
- goto err_disable_clk;
-#endif
} else {
if (pdata->set_vbus)
pdata->set_vbus(1);
diff --git a/drivers/usb/host/ehci-mxc.c b/drivers/usb/host/ehci-mxc.c
index e9301fb97ea..c369767b00e 100644
--- a/drivers/usb/host/ehci-mxc.c
+++ b/drivers/usb/host/ehci-mxc.c
@@ -28,11 +28,7 @@
#include <linux/slab.h>
#include <linux/usb.h>
#include <linux/usb/hcd.h>
-
#include <linux/platform_data/usb-ehci-mxc.h>
-
-#include <asm/mach-types.h>
-
#include "ehci.h"
#define DRIVER_DESC "Freescale On-Chip EHCI Host driver"
@@ -47,7 +43,7 @@ struct ehci_mxc_priv {
static struct hc_driver __read_mostly ehci_mxc_hc_driver;
-static const struct ehci_driver_overrides ehci_mxc_overrides __initdata = {
+static const struct ehci_driver_overrides ehci_mxc_overrides __initconst = {
.extra_priv_size = sizeof(struct ehci_mxc_priv),
};
@@ -61,8 +57,6 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct ehci_hcd *ehci;
- dev_info(&pdev->dev, "initializing i.MX USB Controller\n");
-
if (!pdata) {
dev_err(dev, "No platform data given, bailing out.\n");
return -EINVAL;
@@ -178,7 +172,7 @@ err_alloc:
return ret;
}
-static int __exit ehci_mxc_drv_remove(struct platform_device *pdev)
+static int ehci_mxc_drv_remove(struct platform_device *pdev)
{
struct mxc_usbh_platform_data *pdata = pdev->dev.platform_data;
struct usb_hcd *hcd = platform_get_drvdata(pdev);
diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c
index 0555ee42d7c..3d1491b5f36 100644
--- a/drivers/usb/host/ehci-omap.c
+++ b/drivers/usb/host/ehci-omap.c
@@ -4,10 +4,11 @@
* Bus Glue for the EHCI controllers in OMAP3/4
* Tested on several OMAP3 boards, and OMAP4 Pandaboard
*
- * Copyright (C) 2007-2011 Texas Instruments, Inc.
+ * Copyright (C) 2007-2013 Texas Instruments, Inc.
* Author: Vikram Pandita <vikram.pandita@ti.com>
* Author: Anand Gadiyar <gadiyar@ti.com>
* Author: Keshava Munegowda <keshava_mgowda@ti.com>
+ * Author: Roger Quadros <rogerq@ti.com>
*
* Copyright (C) 2009 Nokia Corporation
* Contact: Felipe Balbi <felipe.balbi@nokia.com>
@@ -28,21 +29,23 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
- * TODO (last updated Feb 27, 2010):
- * - add kernel-doc
- * - enable AUTOIDLE
- * - add suspend/resume
- * - add HSIC and TLL support
- * - convert to use hwmod and runtime PM
*/
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/io.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/usb/ulpi.h>
-#include <linux/regulator/consumer.h>
#include <linux/pm_runtime.h>
#include <linux/gpio.h>
#include <linux/clk.h>
+#include <linux/usb.h>
+#include <linux/usb/hcd.h>
+#include <linux/of.h>
+#include <linux/dma-mapping.h>
+
+#include "ehci.h"
#include <linux/platform_data/usb-omap.h>
@@ -57,10 +60,16 @@
#define EHCI_INSNREG05_ULPI_EXTREGADD_SHIFT 8
#define EHCI_INSNREG05_ULPI_WRDATA_SHIFT 0
-/*-------------------------------------------------------------------------*/
+#define DRIVER_DESC "OMAP-EHCI Host Controller driver"
+
+static const char hcd_name[] = "ehci-omap";
-static const struct hc_driver ehci_omap_hc_driver;
+/*-------------------------------------------------------------------------*/
+struct omap_hcd {
+ struct usb_phy *phy[OMAP3_HS_USB_PORTS]; /* one PHY for each port */
+ int nports;
+};
static inline void ehci_write(void __iomem *base, u32 reg, u32 val)
{
@@ -72,99 +81,16 @@ static inline u32 ehci_read(void __iomem *base, u32 reg)
return __raw_readl(base + reg);
}
+/* configure so an HC device and id are always provided */
+/* always called with process context; sleeping is OK */
-static void omap_ehci_soft_phy_reset(struct usb_hcd *hcd, u8 port)
-{
- unsigned long timeout = jiffies + msecs_to_jiffies(1000);
- unsigned reg = 0;
-
- reg = ULPI_FUNC_CTRL_RESET
- /* FUNCTION_CTRL_SET register */
- | (ULPI_SET(ULPI_FUNC_CTRL) << EHCI_INSNREG05_ULPI_REGADD_SHIFT)
- /* Write */
- | (2 << EHCI_INSNREG05_ULPI_OPSEL_SHIFT)
- /* PORTn */
- | ((port + 1) << EHCI_INSNREG05_ULPI_PORTSEL_SHIFT)
- /* start ULPI access*/
- | (1 << EHCI_INSNREG05_ULPI_CONTROL_SHIFT);
-
- ehci_write(hcd->regs, EHCI_INSNREG05_ULPI, reg);
-
- /* Wait for ULPI access completion */
- while ((ehci_read(hcd->regs, EHCI_INSNREG05_ULPI)
- & (1 << EHCI_INSNREG05_ULPI_CONTROL_SHIFT))) {
- cpu_relax();
-
- if (time_after(jiffies, timeout)) {
- dev_dbg(hcd->self.controller,
- "phy reset operation timed out\n");
- break;
- }
- }
-}
-
-static int omap_ehci_init(struct usb_hcd *hcd)
-{
- struct ehci_hcd *ehci = hcd_to_ehci(hcd);
- int rc;
- struct usbhs_omap_platform_data *pdata;
-
- pdata = hcd->self.controller->platform_data;
-
- /* Hold PHYs in reset while initializing EHCI controller */
- if (pdata->phy_reset) {
- if (gpio_is_valid(pdata->reset_gpio_port[0]))
- gpio_set_value_cansleep(pdata->reset_gpio_port[0], 0);
-
- if (gpio_is_valid(pdata->reset_gpio_port[1]))
- gpio_set_value_cansleep(pdata->reset_gpio_port[1], 0);
-
- /* Hold the PHY in RESET for enough time till DIR is high */
- udelay(10);
- }
-
- /* Soft reset the PHY using PHY reset command over ULPI */
- if (pdata->port_mode[0] == OMAP_EHCI_PORT_MODE_PHY)
- omap_ehci_soft_phy_reset(hcd, 0);
- if (pdata->port_mode[1] == OMAP_EHCI_PORT_MODE_PHY)
- omap_ehci_soft_phy_reset(hcd, 1);
-
- /* we know this is the memory we want, no need to ioremap again */
- ehci->caps = hcd->regs;
-
- rc = ehci_setup(hcd);
-
- if (pdata->phy_reset) {
- /* Hold the PHY in RESET for enough time till
- * PHY is settled and ready
- */
- udelay(10);
-
- if (gpio_is_valid(pdata->reset_gpio_port[0]))
- gpio_set_value_cansleep(pdata->reset_gpio_port[0], 1);
-
- if (gpio_is_valid(pdata->reset_gpio_port[1]))
- gpio_set_value_cansleep(pdata->reset_gpio_port[1], 1);
- }
-
- return rc;
-}
+static struct hc_driver __read_mostly ehci_omap_hc_driver;
-static void disable_put_regulator(
- struct usbhs_omap_platform_data *pdata)
-{
- int i;
-
- for (i = 0 ; i < OMAP3_HS_USB_PORTS ; i++) {
- if (pdata->regulator[i]) {
- regulator_disable(pdata->regulator[i]);
- regulator_put(pdata->regulator[i]);
- }
- }
-}
+static const struct ehci_driver_overrides ehci_omap_overrides __initdata = {
+ .extra_priv_size = sizeof(struct omap_hcd),
+};
-/* configure so an HC device and id are always provided */
-/* always called with process context; sleeping is OK */
+static u64 omap_ehci_dma_mask = DMA_BIT_MASK(32);
/**
* ehci_hcd_omap_probe - initialize TI-based HCDs
@@ -175,15 +101,15 @@ static void disable_put_regulator(
*/
static int ehci_hcd_omap_probe(struct platform_device *pdev)
{
- struct device *dev = &pdev->dev;
- struct usbhs_omap_platform_data *pdata = dev->platform_data;
- struct resource *res;
- struct usb_hcd *hcd;
- void __iomem *regs;
- int ret = -ENODEV;
- int irq;
- int i;
- char supply[7];
+ struct device *dev = &pdev->dev;
+ struct usbhs_omap_platform_data *pdata = dev->platform_data;
+ struct resource *res;
+ struct usb_hcd *hcd;
+ void __iomem *regs;
+ int ret = -ENODEV;
+ int irq;
+ int i;
+ struct omap_hcd *omap;
if (usb_disabled())
return -ENODEV;
@@ -193,52 +119,74 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)
return -ENODEV;
}
- irq = platform_get_irq_byname(pdev, "ehci-irq");
- if (irq < 0) {
- dev_err(dev, "EHCI irq failed\n");
- return -ENODEV;
+ /* For DT boot, get platform data from parent. i.e. usbhshost */
+ if (dev->of_node) {
+ pdata = dev->parent->platform_data;
+ dev->platform_data = pdata;
}
- res = platform_get_resource_byname(pdev,
- IORESOURCE_MEM, "ehci");
- if (!res) {
- dev_err(dev, "UHH EHCI get resource failed\n");
+ if (!pdata) {
+ dev_err(dev, "Missing platform data\n");
return -ENODEV;
}
- regs = ioremap(res->start, resource_size(res));
- if (!regs) {
- dev_err(dev, "UHH EHCI ioremap failed\n");
- return -ENOMEM;
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ dev_err(dev, "EHCI irq failed\n");
+ return -ENODEV;
}
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ regs = devm_ioremap_resource(dev, res);
+ if (IS_ERR(regs))
+ return PTR_ERR(regs);
+
+ /*
+ * 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 have dma capability bindings this can go away.
+ */
+ if (!pdev->dev.dma_mask)
+ pdev->dev.dma_mask = &omap_ehci_dma_mask;
+
hcd = usb_create_hcd(&ehci_omap_hc_driver, dev,
dev_name(dev));
if (!hcd) {
- dev_err(dev, "failed to create hcd with err %d\n", ret);
- ret = -ENOMEM;
- goto err_io;
+ dev_err(dev, "Failed to create HCD\n");
+ return -ENOMEM;
}
hcd->rsrc_start = res->start;
hcd->rsrc_len = resource_size(res);
hcd->regs = regs;
-
- /* get ehci regulator and enable */
- for (i = 0 ; i < OMAP3_HS_USB_PORTS ; i++) {
- if (pdata->port_mode[i] != OMAP_EHCI_PORT_MODE_PHY) {
- pdata->regulator[i] = NULL;
- continue;
- }
- snprintf(supply, sizeof(supply), "hsusb%d", i);
- pdata->regulator[i] = regulator_get(dev, supply);
- if (IS_ERR(pdata->regulator[i])) {
- pdata->regulator[i] = NULL;
- dev_dbg(dev,
- "failed to get ehci port%d regulator\n", i);
- } else {
- regulator_enable(pdata->regulator[i]);
+ hcd_to_ehci(hcd)->caps = regs;
+
+ omap = (struct omap_hcd *)hcd_to_ehci(hcd)->priv;
+ omap->nports = pdata->nports;
+
+ platform_set_drvdata(pdev, hcd);
+
+ /* get the PHY devices if needed */
+ for (i = 0 ; i < omap->nports ; i++) {
+ struct usb_phy *phy;
+
+ /* get the PHY device */
+ if (dev->of_node)
+ phy = devm_usb_get_phy_by_phandle(dev, "phys", i);
+ else
+ phy = devm_usb_get_phy_dev(dev, i);
+ if (IS_ERR(phy)) {
+ /* Don't bail out if PHY is not absolutely necessary */
+ if (pdata->port_mode[i] != OMAP_EHCI_PORT_MODE_PHY)
+ continue;
+
+ ret = PTR_ERR(phy);
+ dev_err(dev, "Can't get PHY device for port %d: %d\n",
+ i, ret);
+ goto err_phy;
}
+
+ omap->phy[i] = phy;
}
pm_runtime_enable(dev);
@@ -262,16 +210,34 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)
goto err_pm_runtime;
}
+ /*
+ * Bring PHYs out of reset.
+ * Even though HSIC mode is a PHY-less mode, the reset
+ * line exists between the chips and can be modelled
+ * as a PHY device for reset control.
+ */
+ for (i = 0; i < omap->nports; i++) {
+ if (!omap->phy[i])
+ continue;
+
+ usb_phy_init(omap->phy[i]);
+ /* bring PHY out of suspend */
+ usb_phy_set_suspend(omap->phy[i], 0);
+ }
return 0;
err_pm_runtime:
- disable_put_regulator(pdata);
pm_runtime_put_sync(dev);
+
+err_phy:
+ for (i = 0; i < omap->nports; i++) {
+ if (omap->phy[i])
+ usb_phy_shutdown(omap->phy[i]);
+ }
+
usb_put_hcd(hcd);
-err_io:
- iounmap(regs);
return ret;
}
@@ -286,14 +252,19 @@ err_io:
*/
static int ehci_hcd_omap_remove(struct platform_device *pdev)
{
- struct device *dev = &pdev->dev;
- struct usb_hcd *hcd = dev_get_drvdata(dev);
+ struct device *dev = &pdev->dev;
+ struct usb_hcd *hcd = dev_get_drvdata(dev);
+ struct omap_hcd *omap = (struct omap_hcd *)hcd_to_ehci(hcd)->priv;
+ int i;
usb_remove_hcd(hcd);
- disable_put_regulator(dev->platform_data);
- iounmap(hcd->regs);
- usb_put_hcd(hcd);
+ for (i = 0; i < omap->nports; i++) {
+ if (omap->phy[i])
+ usb_phy_shutdown(omap->phy[i]);
+ }
+
+ usb_put_hcd(hcd);
pm_runtime_put_sync(dev);
pm_runtime_disable(dev);
@@ -308,6 +279,13 @@ static void ehci_hcd_omap_shutdown(struct platform_device *pdev)
hcd->driver->shutdown(hcd);
}
+static const struct of_device_id omap_ehci_dt_ids[] = {
+ { .compatible = "ti,ehci-omap" },
+ { }
+};
+
+MODULE_DEVICE_TABLE(of, omap_ehci_dt_ids);
+
static struct platform_driver ehci_hcd_omap_driver = {
.probe = ehci_hcd_omap_probe,
.remove = ehci_hcd_omap_remove,
@@ -315,56 +293,35 @@ static struct platform_driver ehci_hcd_omap_driver = {
/*.suspend = ehci_hcd_omap_suspend, */
/*.resume = ehci_hcd_omap_resume, */
.driver = {
- .name = "ehci-omap",
+ .name = hcd_name,
+ .of_match_table = of_match_ptr(omap_ehci_dt_ids),
}
};
/*-------------------------------------------------------------------------*/
-static const struct hc_driver ehci_omap_hc_driver = {
- .description = hcd_name,
- .product_desc = "OMAP-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 = omap_ehci_init,
- .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,
+static int __init ehci_omap_init(void)
+{
+ if (usb_disabled())
+ return -ENODEV;
- /*
- * scheduling support
- */
- .get_frame_number = ehci_get_frame,
+ pr_info("%s: " DRIVER_DESC "\n", hcd_name);
- /*
- * 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,
+ ehci_init_driver(&ehci_omap_hc_driver, &ehci_omap_overrides);
+ return platform_driver_register(&ehci_hcd_omap_driver);
+}
+module_init(ehci_omap_init);
- .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
-};
+static void __exit ehci_omap_cleanup(void)
+{
+ platform_driver_unregister(&ehci_hcd_omap_driver);
+}
+module_exit(ehci_omap_cleanup);
MODULE_ALIAS("platform:ehci-omap");
MODULE_AUTHOR("Texas Instruments, Inc.");
MODULE_AUTHOR("Felipe Balbi <felipe.balbi@nokia.com>");
+MODULE_AUTHOR("Roger Quadros <rogerq@ti.com>");
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/host/ehci-orion.c b/drivers/usb/host/ehci-orion.c
index 914a3ecfb5d..54c57948515 100644
--- a/drivers/usb/host/ehci-orion.c
+++ b/drivers/usb/host/ehci-orion.c
@@ -17,6 +17,12 @@
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_irq.h>
+#include <linux/usb.h>
+#include <linux/usb/hcd.h>
+#include <linux/io.h>
+#include <linux/dma-mapping.h>
+
+#include "ehci.h"
#define rdl(off) __raw_readl(hcd->regs + (off))
#define wrl(off, val) __raw_writel((val), hcd->regs + (off))
@@ -34,6 +40,12 @@
#define USB_PHY_IVREF_CTRL 0x440
#define USB_PHY_TST_GRP_CTRL 0x450
+#define DRIVER_DESC "EHCI orion driver"
+
+static const char hcd_name[] = "ehci-orion";
+
+static struct hc_driver __read_mostly ehci_orion_hc_driver;
+
/*
* Implement Orion USB controller specification guidelines
*/
@@ -104,51 +116,6 @@ static void orion_usb_phy_v1_setup(struct usb_hcd *hcd)
wrl(USB_MODE, 0x13);
}
-static const struct hc_driver ehci_orion_hc_driver = {
- .description = hcd_name,
- .product_desc = "Marvell Orion EHCI",
- .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,
-
- /*
- * 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 void
ehci_orion_conf_mbus_windows(struct usb_hcd *hcd,
const struct mbus_dram_target_info *dram)
@@ -305,7 +272,7 @@ err1:
return err;
}
-static int __exit ehci_orion_drv_remove(struct platform_device *pdev)
+static int ehci_orion_drv_remove(struct platform_device *pdev)
{
struct usb_hcd *hcd = platform_get_drvdata(pdev);
struct clk *clk;
@@ -323,8 +290,6 @@ static int __exit ehci_orion_drv_remove(struct platform_device *pdev)
return 0;
}
-MODULE_ALIAS("platform:orion-ehci");
-
static const struct of_device_id ehci_orion_dt_ids[] = {
{ .compatible = "marvell,orion-ehci", },
{},
@@ -333,7 +298,7 @@ MODULE_DEVICE_TABLE(of, ehci_orion_dt_ids);
static struct platform_driver ehci_orion_driver = {
.probe = ehci_orion_drv_probe,
- .remove = __exit_p(ehci_orion_drv_remove),
+ .remove = ehci_orion_drv_remove,
.shutdown = usb_hcd_platform_shutdown,
.driver = {
.name = "orion-ehci",
@@ -341,3 +306,26 @@ static struct platform_driver ehci_orion_driver = {
.of_match_table = of_match_ptr(ehci_orion_dt_ids),
},
};
+
+static int __init ehci_orion_init(void)
+{
+ if (usb_disabled())
+ return -ENODEV;
+
+ pr_info("%s: " DRIVER_DESC "\n", hcd_name);
+
+ ehci_init_driver(&ehci_orion_hc_driver, NULL);
+ return platform_driver_register(&ehci_orion_driver);
+}
+module_init(ehci_orion_init);
+
+static void __exit ehci_orion_cleanup(void)
+{
+ platform_driver_unregister(&ehci_orion_driver);
+}
+module_exit(ehci_orion_cleanup);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_ALIAS("platform:orion-ehci");
+MODULE_AUTHOR("Tzachi Perelstein");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
index 170b9399e09..595d210655b 100644
--- a/drivers/usb/host/ehci-pci.c
+++ b/drivers/usb/host/ehci-pci.c
@@ -292,17 +292,7 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
}
}
-#ifdef CONFIG_USB_SUSPEND
- /* REVISIT: the controller works fine for wakeup iff the root hub
- * itself is "globally" suspended, but usbcore currently doesn't
- * understand such things.
- *
- * System suspend currently expects to be able to suspend the entire
- * device tree, device-at-a-time. If we failed selective suspend
- * reports, system suspend would fail; so the root hub code must claim
- * success. That's lying to usbcore, and it matters for runtime
- * PM scenarios with selective suspend and remote wakeup...
- */
+#ifdef CONFIG_PM_RUNTIME
if (ehci->no_selective_suspend && device_can_wakeup(&pdev->dev))
ehci_warn(ehci, "selective suspend/wakeup unavailable\n");
#endif
@@ -385,7 +375,7 @@ static int ehci_pci_resume(struct usb_hcd *hcd, bool hibernated)
static struct hc_driver __read_mostly ehci_pci_hc_driver;
-static const struct ehci_driver_overrides pci_overrides __initdata = {
+static const struct ehci_driver_overrides pci_overrides __initconst = {
.reset = ehci_pci_setup,
};
diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c
index ca750639054..f47f2594c9d 100644
--- a/drivers/usb/host/ehci-platform.c
+++ b/drivers/usb/host/ehci-platform.c
@@ -18,11 +18,13 @@
*
* Licensed under the GNU/GPL. See COPYING for details.
*/
+#include <linux/dma-mapping.h>
#include <linux/err.h>
#include <linux/kernel.h>
#include <linux/hrtimer.h>
#include <linux/io.h>
#include <linux/module.h>
+#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/usb.h>
#include <linux/usb/hcd.h>
@@ -58,26 +60,36 @@ static int ehci_platform_reset(struct usb_hcd *hcd)
static struct hc_driver __read_mostly ehci_platform_hc_driver;
-static const struct ehci_driver_overrides platform_overrides __initdata = {
+static const struct ehci_driver_overrides platform_overrides __initconst = {
.reset = ehci_platform_reset,
};
+static struct usb_ehci_pdata ehci_platform_defaults;
+
static int ehci_platform_probe(struct platform_device *dev)
{
struct usb_hcd *hcd;
struct resource *res_mem;
- struct usb_ehci_pdata *pdata = dev->dev.platform_data;
+ struct usb_ehci_pdata *pdata;
int irq;
int err = -ENOMEM;
- if (!pdata) {
- WARN_ON(1);
- return -ENODEV;
- }
-
if (usb_disabled())
return -ENODEV;
+ /*
+ * use reasonable defaults so platforms don't have to provide these.
+ * with DT probing on ARM, none of these are set.
+ */
+ if (!dev->dev.platform_data)
+ dev->dev.platform_data = &ehci_platform_defaults;
+ if (!dev->dev.dma_mask)
+ dev->dev.dma_mask = &dev->dev.coherent_dma_mask;
+ if (!dev->dev.coherent_dma_mask)
+ dev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
+
+ pdata = dev->dev.platform_data;
+
irq = platform_get_irq(dev, 0);
if (irq < 0) {
dev_err(&dev->dev, "no irq provided");
@@ -139,6 +151,9 @@ static int ehci_platform_remove(struct platform_device *dev)
if (pdata->power_off)
pdata->power_off(dev);
+ if (pdata == &ehci_platform_defaults)
+ dev->dev.platform_data = NULL;
+
return 0;
}
@@ -183,6 +198,12 @@ static int ehci_platform_resume(struct device *dev)
#define ehci_platform_resume NULL
#endif /* CONFIG_PM */
+static const struct of_device_id vt8500_ehci_ids[] = {
+ { .compatible = "via,vt8500-ehci", },
+ { .compatible = "wm,prizm-ehci", },
+ {}
+};
+
static const struct platform_device_id ehci_platform_table[] = {
{ "ehci-platform", 0 },
{ }
@@ -203,6 +224,7 @@ static struct platform_driver ehci_platform_driver = {
.owner = THIS_MODULE,
.name = "ehci-platform",
.pm = &ehci_platform_pm_ops,
+ .of_match_table = of_match_ptr(vt8500_ehci_ids),
}
};
diff --git a/drivers/usb/host/ehci-ps3.c b/drivers/usb/host/ehci-ps3.c
index df5925a4f0d..fd983771b02 100644
--- a/drivers/usb/host/ehci-ps3.c
+++ b/drivers/usb/host/ehci-ps3.c
@@ -221,7 +221,6 @@ static int ps3_ehci_remove(struct ps3_system_bus_device *dev)
tmp = hcd->irq;
- ehci_shutdown(hcd);
usb_remove_hcd(hcd);
ps3_system_bus_set_drvdata(dev, NULL);
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
index fd252f0cfb3..d34b399b78e 100644
--- a/drivers/usb/host/ehci-q.c
+++ b/drivers/usb/host/ehci-q.c
@@ -90,7 +90,7 @@ qh_update (struct ehci_hcd *ehci, struct ehci_qh *qh, struct ehci_qtd *qtd)
struct ehci_qh_hw *hw = qh->hw;
/* writes to an active overlay are unsafe */
- BUG_ON(qh->qh_state != QH_STATE_IDLE);
+ WARN_ON(qh->qh_state != QH_STATE_IDLE);
hw->hw_qtd_next = QTD_NEXT(ehci, qtd->qtd_dma);
hw->hw_alt_next = EHCI_LIST_END(ehci);
@@ -123,26 +123,19 @@ qh_refresh (struct ehci_hcd *ehci, struct ehci_qh *qh)
{
struct ehci_qtd *qtd;
- if (list_empty (&qh->qtd_list))
- qtd = qh->dummy;
- else {
- qtd = list_entry (qh->qtd_list.next,
- struct ehci_qtd, qtd_list);
- /*
- * first qtd may already be partially processed.
- * If we come here during unlink, the QH overlay region
- * might have reference to the just unlinked qtd. The
- * qtd is updated in qh_completions(). Update the QH
- * overlay here.
- */
- if (cpu_to_hc32(ehci, qtd->qtd_dma) == qh->hw->hw_current) {
- qh->hw->hw_qtd_next = qtd->hw_next;
- qtd = NULL;
- }
- }
+ qtd = list_entry(qh->qtd_list.next, struct ehci_qtd, qtd_list);
- if (qtd)
- qh_update (ehci, qh, qtd);
+ /*
+ * first qtd may already be partially processed.
+ * If we come here during unlink, the QH overlay region
+ * might have reference to the just unlinked qtd. The
+ * qtd is updated in qh_completions(). Update the QH
+ * overlay here.
+ */
+ if (qh->hw->hw_token & ACTIVE_BIT(ehci))
+ qh->hw->hw_qtd_next = qtd->hw_next;
+ else
+ qh_update(ehci, qh, qtd);
}
/*-------------------------------------------------------------------------*/
@@ -299,8 +292,8 @@ static int qh_schedule (struct ehci_hcd *ehci, struct ehci_qh *qh);
/*
* Process and free completed qtds for a qh, returning URBs to drivers.
- * Chases up to qh->hw_current. Returns number of completions called,
- * indicating how much "real" work we did.
+ * Chases up to qh->hw_current. Returns nonzero if the caller should
+ * unlink qh.
*/
static unsigned
qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
@@ -309,13 +302,9 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
struct list_head *entry, *tmp;
int last_status;
int stopped;
- unsigned count = 0;
u8 state;
struct ehci_qh_hw *hw = qh->hw;
- if (unlikely (list_empty (&qh->qtd_list)))
- return count;
-
/* completions (or tasks on other cpus) must never clobber HALT
* till we've gone through and cleaned everything up, even when
* they add urbs to this qh's queue or mark them for unlinking.
@@ -333,7 +322,7 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
rescan:
last = NULL;
last_status = -EINPROGRESS;
- qh->needs_rescan = 0;
+ qh->dequeue_during_giveback = 0;
/* remove de-activated QTDs from front of queue.
* after faults (including short reads), cleanup this urb
@@ -352,7 +341,6 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
if (last) {
if (likely (last->urb != urb)) {
ehci_urb_done(ehci, last->urb, last_status);
- count++;
last_status = -EINPROGRESS;
}
ehci_qtd_free (ehci, last);
@@ -449,11 +437,19 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
else if (last_status == -EINPROGRESS && !urb->unlinked)
continue;
- /* qh unlinked; token in overlay may be most current */
- if (state == QH_STATE_IDLE
- && cpu_to_hc32(ehci, qtd->qtd_dma)
- == hw->hw_current) {
+ /*
+ * If this was the active qtd when the qh was unlinked
+ * and the overlay's token is active, then the overlay
+ * hasn't been written back to the qtd yet so use its
+ * token instead of the qtd's. After the qtd is
+ * processed and removed, the overlay won't be valid
+ * any more.
+ */
+ if (state == QH_STATE_IDLE &&
+ qh->qtd_list.next == &qtd->qtd_list &&
+ (hw->hw_token & ACTIVE_BIT(ehci))) {
token = hc32_to_cpu(ehci, hw->hw_token);
+ hw->hw_token &= ~ACTIVE_BIT(ehci);
/* An unlink may leave an incomplete
* async transaction in the TT buffer.
@@ -518,23 +514,16 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
/* last urb's completion might still need calling */
if (likely (last != NULL)) {
ehci_urb_done(ehci, last->urb, last_status);
- count++;
ehci_qtd_free (ehci, last);
}
/* Do we need to rescan for URBs dequeued during a giveback? */
- if (unlikely(qh->needs_rescan)) {
+ if (unlikely(qh->dequeue_during_giveback)) {
/* If the QH is already unlinked, do the rescan now. */
if (state == QH_STATE_IDLE)
goto rescan;
- /* Otherwise we have to wait until the QH is fully unlinked.
- * Our caller will start an unlink if qh->needs_rescan is
- * set. But if an unlink has already started, nothing needs
- * to be done.
- */
- if (state != QH_STATE_LINKED)
- qh->needs_rescan = 0;
+ /* Otherwise the caller must unlink the QH. */
}
/* restore original state; caller must unlink or relink */
@@ -543,33 +532,23 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
/* be sure the hardware's done with the qh before refreshing
* it after fault cleanup, or recovering from silicon wrongly
* overlaying the dummy qtd (which reduces DMA chatter).
+ *
+ * We won't refresh a QH that's linked (after the HC
+ * stopped the queue). That avoids a race:
+ * - HC reads first part of QH;
+ * - CPU updates that first part and the token;
+ * - HC reads rest of that QH, including token
+ * Result: HC gets an inconsistent image, and then
+ * DMAs to/from the wrong memory (corrupting it).
+ *
+ * That should be rare for interrupt transfers,
+ * except maybe high bandwidth ...
*/
- if (stopped != 0 || hw->hw_qtd_next == EHCI_LIST_END(ehci)) {
- switch (state) {
- case QH_STATE_IDLE:
- qh_refresh(ehci, qh);
- break;
- case QH_STATE_LINKED:
- /* We won't refresh a QH that's linked (after the HC
- * stopped the queue). That avoids a race:
- * - HC reads first part of QH;
- * - CPU updates that first part and the token;
- * - HC reads rest of that QH, including token
- * Result: HC gets an inconsistent image, and then
- * DMAs to/from the wrong memory (corrupting it).
- *
- * That should be rare for interrupt transfers,
- * except maybe high bandwidth ...
- */
-
- /* Tell the caller to start an unlink */
- qh->needs_rescan = 1;
- break;
- /* otherwise, unlink already started */
- }
- }
+ if (stopped != 0 || hw->hw_qtd_next == EHCI_LIST_END(ehci))
+ qh->exception = 1;
- return count;
+ /* Let the caller know if the QH needs to be unlinked. */
+ return qh->exception;
}
/*-------------------------------------------------------------------------*/
@@ -949,14 +928,13 @@ done:
/* NOTE: if (PIPE_INTERRUPT) { scheduler sets s-mask } */
- /* init as live, toggle clear, advance to dummy */
+ /* init as live, toggle clear */
qh->qh_state = QH_STATE_IDLE;
hw = qh->hw;
hw->hw_info1 = cpu_to_hc32(ehci, info1);
hw->hw_info2 = cpu_to_hc32(ehci, info2);
qh->is_out = !is_input;
usb_settoggle (urb->dev, usb_pipeendpoint (urb->pipe), !is_input, 1);
- qh_refresh (ehci, qh);
return qh;
}
@@ -980,8 +958,9 @@ static void disable_async(struct ehci_hcd *ehci)
if (--ehci->async_count)
return;
- /* The async schedule and async_unlink list are supposed to be empty */
- WARN_ON(ehci->async->qh_next.qh || ehci->async_unlink);
+ /* The async schedule and unlink lists are supposed to be empty */
+ WARN_ON(ehci->async->qh_next.qh || !list_empty(&ehci->async_unlink) ||
+ !list_empty(&ehci->async_idle));
/* Don't turn off the schedule until ASS is 1 */
ehci_poll_ASS(ehci);
@@ -1012,8 +991,9 @@ static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
head->qh_next.qh = qh;
head->hw->hw_next = dma;
- qh->xacterrs = 0;
qh->qh_state = QH_STATE_LINKED;
+ qh->xacterrs = 0;
+ qh->exception = 0;
/* qtd completions reported later by interrupt */
enable_async(ehci);
@@ -1170,12 +1150,8 @@ static void single_unlink_async(struct ehci_hcd *ehci, struct ehci_qh *qh)
struct ehci_qh *prev;
/* Add to the end of the list of QHs waiting for the next IAAD */
- qh->qh_state = QH_STATE_UNLINK;
- if (ehci->async_unlink)
- ehci->async_unlink_last->unlink_next = qh;
- else
- ehci->async_unlink = qh;
- ehci->async_unlink_last = qh;
+ qh->qh_state = QH_STATE_UNLINK_WAIT;
+ list_add_tail(&qh->unlink_node, &ehci->async_unlink);
/* Unlink it from the schedule */
prev = ehci->async;
@@ -1188,34 +1164,19 @@ static void single_unlink_async(struct ehci_hcd *ehci, struct ehci_qh *qh)
ehci->qh_scan_next = qh->qh_next.qh;
}
-static void start_iaa_cycle(struct ehci_hcd *ehci, bool nested)
+static void start_iaa_cycle(struct ehci_hcd *ehci)
{
- /*
- * Do nothing if an IAA cycle is already running or
- * if one will be started shortly.
- */
- if (ehci->async_iaa || ehci->async_unlinking)
+ /* Do nothing if an IAA cycle is already running */
+ if (ehci->iaa_in_progress)
return;
+ ehci->iaa_in_progress = true;
/* If the controller isn't running, we don't have to wait for it */
if (unlikely(ehci->rh_state < EHCI_RH_RUNNING)) {
-
- /* Do all the waiting QHs */
- ehci->async_iaa = ehci->async_unlink;
- ehci->async_unlink = NULL;
-
- if (!nested) /* Avoid recursion */
- end_unlink_async(ehci);
+ end_unlink_async(ehci);
/* Otherwise start a new IAA cycle */
} else if (likely(ehci->rh_state == EHCI_RH_RUNNING)) {
- struct ehci_qh *qh;
-
- /* Do only the first waiting QH (nVidia bug?) */
- qh = ehci->async_unlink;
- ehci->async_iaa = qh;
- ehci->async_unlink = qh->unlink_next;
- qh->unlink_next = NULL;
/* Make sure the unlinks are all visible to the hardware */
wmb();
@@ -1232,36 +1193,73 @@ static void start_iaa_cycle(struct ehci_hcd *ehci, bool nested)
static void end_unlink_async(struct ehci_hcd *ehci)
{
struct ehci_qh *qh;
+ bool early_exit;
if (ehci->has_synopsys_hc_bug)
ehci_writel(ehci, (u32) ehci->async->qh_dma,
&ehci->regs->async_next);
+ /* The current IAA cycle has ended */
+ ehci->iaa_in_progress = false;
+
+ if (list_empty(&ehci->async_unlink))
+ return;
+ qh = list_first_entry(&ehci->async_unlink, struct ehci_qh,
+ unlink_node); /* QH whose IAA cycle just ended */
+
+ /*
+ * If async_unlinking is set then this routine is already running,
+ * either on the stack or on another CPU.
+ */
+ early_exit = ehci->async_unlinking;
+
+ /* If the controller isn't running, process all the waiting QHs */
+ if (ehci->rh_state < EHCI_RH_RUNNING)
+ list_splice_tail_init(&ehci->async_unlink, &ehci->async_idle);
+
+ /*
+ * Intel (?) bug: The HC can write back the overlay region even
+ * after the IAA interrupt occurs. In self-defense, always go
+ * through two IAA cycles for each QH.
+ */
+ else if (qh->qh_state == QH_STATE_UNLINK_WAIT) {
+ qh->qh_state = QH_STATE_UNLINK;
+ early_exit = true;
+ }
+
+ /* Otherwise process only the first waiting QH (NVIDIA bug?) */
+ else
+ list_move_tail(&qh->unlink_node, &ehci->async_idle);
+
+ /* Start a new IAA cycle if any QHs are waiting for it */
+ if (!list_empty(&ehci->async_unlink))
+ start_iaa_cycle(ehci);
+
+ /*
+ * Don't allow nesting or concurrent calls,
+ * or wait for the second IAA cycle for the next QH.
+ */
+ if (early_exit)
+ return;
+
/* Process the idle QHs */
- restart:
ehci->async_unlinking = true;
- while (ehci->async_iaa) {
- qh = ehci->async_iaa;
- ehci->async_iaa = qh->unlink_next;
- qh->unlink_next = NULL;
+ while (!list_empty(&ehci->async_idle)) {
+ qh = list_first_entry(&ehci->async_idle, struct ehci_qh,
+ unlink_node);
+ list_del(&qh->unlink_node);
qh->qh_state = QH_STATE_IDLE;
qh->qh_next.qh = NULL;
- qh_completions(ehci, qh);
+ if (!list_empty(&qh->qtd_list))
+ qh_completions(ehci, qh);
if (!list_empty(&qh->qtd_list) &&
ehci->rh_state == EHCI_RH_RUNNING)
qh_link_async(ehci, qh);
disable_async(ehci);
}
ehci->async_unlinking = false;
-
- /* Start a new IAA cycle if any QHs are waiting for it */
- if (ehci->async_unlink) {
- start_iaa_cycle(ehci, true);
- if (unlikely(ehci->rh_state < EHCI_RH_RUNNING))
- goto restart;
- }
}
static void start_unlink_async(struct ehci_hcd *ehci, struct ehci_qh *qh);
@@ -1270,7 +1268,6 @@ static void unlink_empty_async(struct ehci_hcd *ehci)
{
struct ehci_qh *qh;
struct ehci_qh *qh_to_unlink = NULL;
- bool check_unlinks_later = false;
int count = 0;
/* Find the last async QH which has been empty for a timer cycle */
@@ -1278,15 +1275,13 @@ static void unlink_empty_async(struct ehci_hcd *ehci)
if (list_empty(&qh->qtd_list) &&
qh->qh_state == QH_STATE_LINKED) {
++count;
- if (qh->unlink_cycle == ehci->async_unlink_cycle)
- check_unlinks_later = true;
- else
+ if (qh->unlink_cycle != ehci->async_unlink_cycle)
qh_to_unlink = qh;
}
}
/* If nothing else is being unlinked, unlink the last empty QH */
- if (!ehci->async_iaa && !ehci->async_unlink && qh_to_unlink) {
+ if (list_empty(&ehci->async_unlink) && qh_to_unlink) {
start_unlink_async(ehci, qh_to_unlink);
--count;
}
@@ -1298,24 +1293,30 @@ static void unlink_empty_async(struct ehci_hcd *ehci)
}
}
+/* The root hub is suspended; unlink all the async QHs */
+static void __maybe_unused unlink_empty_async_suspended(struct ehci_hcd *ehci)
+{
+ struct ehci_qh *qh;
+
+ while (ehci->async->qh_next.qh) {
+ qh = ehci->async->qh_next.qh;
+ WARN_ON(!list_empty(&qh->qtd_list));
+ single_unlink_async(ehci, qh);
+ }
+ start_iaa_cycle(ehci);
+}
+
/* makes sure the async qh will become idle */
/* caller must own ehci->lock */
static void start_unlink_async(struct ehci_hcd *ehci, struct ehci_qh *qh)
{
- /*
- * If the QH isn't linked then there's nothing we can do
- * unless we were called during a giveback, in which case
- * qh_completions() has to deal with it.
- */
- if (qh->qh_state != QH_STATE_LINKED) {
- if (qh->qh_state == QH_STATE_COMPLETING)
- qh->needs_rescan = 1;
+ /* If the QH isn't linked then there's nothing we can do. */
+ if (qh->qh_state != QH_STATE_LINKED)
return;
- }
single_unlink_async(ehci, qh);
- start_iaa_cycle(ehci, false);
+ start_iaa_cycle(ehci);
}
/*-------------------------------------------------------------------------*/
@@ -1329,7 +1330,7 @@ static void scan_async (struct ehci_hcd *ehci)
while (ehci->qh_scan_next) {
qh = ehci->qh_scan_next;
ehci->qh_scan_next = qh->qh_next.qh;
- rescan:
+
/* clean any finished work for this qh */
if (!list_empty(&qh->qtd_list)) {
int temp;
@@ -1342,14 +1343,13 @@ static void scan_async (struct ehci_hcd *ehci)
* in single_unlink_async().
*/
temp = qh_completions(ehci, qh);
- if (qh->needs_rescan) {
+ if (unlikely(temp)) {
start_unlink_async(ehci, qh);
} else if (list_empty(&qh->qtd_list)
&& qh->qh_state == QH_STATE_LINKED) {
qh->unlink_cycle = ehci->async_unlink_cycle;
check_unlinks_later = true;
- } else if (temp != 0)
- goto rescan;
+ }
}
}
diff --git a/drivers/usb/host/ehci-s5p.c b/drivers/usb/host/ehci-s5p.c
index 20ebf6a8b7f..635775278c7 100644
--- a/drivers/usb/host/ehci-s5p.c
+++ b/drivers/usb/host/ehci-s5p.c
@@ -13,13 +13,23 @@
*/
#include <linux/clk.h>
+#include <linux/dma-mapping.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
#include <linux/of.h>
-#include <linux/platform_device.h>
#include <linux/of_gpio.h>
+#include <linux/platform_device.h>
#include <linux/platform_data/usb-ehci-s5p.h>
#include <linux/usb/phy.h>
#include <linux/usb/samsung_usb_phy.h>
-#include <plat/usb-phy.h>
+#include <linux/usb.h>
+#include <linux/usb/hcd.h>
+#include <linux/usb/otg.h>
+
+#include "ehci.h"
+
+#define DRIVER_DESC "EHCI s5p driver"
#define EHCI_INSNREG00(base) (base + 0x90)
#define EHCI_INSNREG00_ENA_INCR16 (0x1 << 25)
@@ -30,82 +40,35 @@
(EHCI_INSNREG00_ENA_INCR16 | EHCI_INSNREG00_ENA_INCR8 | \
EHCI_INSNREG00_ENA_INCR4 | EHCI_INSNREG00_ENA_INCRX_ALIGN)
+static const char hcd_name[] = "ehci-s5p";
+static struct hc_driver __read_mostly s5p_ehci_hc_driver;
+
struct s5p_ehci_hcd {
- struct device *dev;
- struct usb_hcd *hcd;
struct clk *clk;
struct usb_phy *phy;
struct usb_otg *otg;
struct s5p_ehci_platdata *pdata;
};
-static const struct hc_driver s5p_ehci_hc_driver = {
- .description = hcd_name,
- .product_desc = "S5P EHCI Host Controller",
- .hcd_priv_size = sizeof(struct ehci_hcd),
-
- .irq = ehci_irq,
- .flags = HCD_MEMORY | HCD_USB2,
-
- .reset = ehci_setup,
- .start = ehci_run,
- .stop = ehci_stop,
- .shutdown = ehci_shutdown,
-
- .get_frame_number = ehci_get_frame,
-
- .urb_enqueue = ehci_urb_enqueue,
- .urb_dequeue = ehci_urb_dequeue,
- .endpoint_disable = ehci_endpoint_disable,
- .endpoint_reset = ehci_endpoint_reset,
-
- .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 void s5p_ehci_phy_enable(struct s5p_ehci_hcd *s5p_ehci)
-{
- struct platform_device *pdev = to_platform_device(s5p_ehci->dev);
-
- if (s5p_ehci->phy)
- usb_phy_init(s5p_ehci->phy);
- else if (s5p_ehci->pdata->phy_init)
- s5p_ehci->pdata->phy_init(pdev, USB_PHY_TYPE_HOST);
-}
-
-static void s5p_ehci_phy_disable(struct s5p_ehci_hcd *s5p_ehci)
-{
- struct platform_device *pdev = to_platform_device(s5p_ehci->dev);
-
- if (s5p_ehci->phy)
- usb_phy_shutdown(s5p_ehci->phy);
- else if (s5p_ehci->pdata->phy_exit)
- s5p_ehci->pdata->phy_exit(pdev, USB_PHY_TYPE_HOST);
-}
+#define to_s5p_ehci(hcd) (struct s5p_ehci_hcd *)(hcd_to_ehci(hcd)->priv)
static void s5p_setup_vbus_gpio(struct platform_device *pdev)
{
+ struct device *dev = &pdev->dev;
int err;
int gpio;
- if (!pdev->dev.of_node)
+ if (!dev->of_node)
return;
- gpio = of_get_named_gpio(pdev->dev.of_node,
- "samsung,vbus-gpio", 0);
+ gpio = of_get_named_gpio(dev->of_node, "samsung,vbus-gpio", 0);
if (!gpio_is_valid(gpio))
return;
- err = gpio_request_one(gpio, GPIOF_OUT_INIT_HIGH, "ehci_vbus_gpio");
+ err = devm_gpio_request_one(dev, gpio, GPIOF_OUT_INIT_HIGH,
+ "ehci_vbus_gpio");
if (err)
- dev_err(&pdev->dev, "can't request ehci vbus gpio %d", gpio);
+ dev_err(dev, "can't request ehci vbus gpio %d", gpio);
}
static u64 ehci_s5p_dma_mask = DMA_BIT_MASK(32);
@@ -133,13 +96,15 @@ static int s5p_ehci_probe(struct platform_device *pdev)
s5p_setup_vbus_gpio(pdev);
- s5p_ehci = devm_kzalloc(&pdev->dev, sizeof(struct s5p_ehci_hcd),
- GFP_KERNEL);
- if (!s5p_ehci)
+ hcd = usb_create_hcd(&s5p_ehci_hc_driver,
+ &pdev->dev, dev_name(&pdev->dev));
+ if (!hcd) {
+ dev_err(&pdev->dev, "Unable to create HCD\n");
return -ENOMEM;
-
+ }
+ s5p_ehci = to_s5p_ehci(hcd);
phy = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2);
- if (IS_ERR_OR_NULL(phy)) {
+ if (IS_ERR(phy)) {
/* Fallback to pdata */
if (!pdata) {
dev_warn(&pdev->dev, "no platform data or transceiver defined\n");
@@ -152,16 +117,6 @@ static int s5p_ehci_probe(struct platform_device *pdev)
s5p_ehci->otg = phy->otg;
}
- s5p_ehci->dev = &pdev->dev;
-
- hcd = usb_create_hcd(&s5p_ehci_hc_driver, &pdev->dev,
- dev_name(&pdev->dev));
- if (!hcd) {
- dev_err(&pdev->dev, "Unable to create HCD\n");
- return -ENOMEM;
- }
-
- s5p_ehci->hcd = hcd;
s5p_ehci->clk = devm_clk_get(&pdev->dev, "usbhost");
if (IS_ERR(s5p_ehci->clk)) {
@@ -198,9 +153,12 @@ static int s5p_ehci_probe(struct platform_device *pdev)
}
if (s5p_ehci->otg)
- s5p_ehci->otg->set_host(s5p_ehci->otg, &s5p_ehci->hcd->self);
+ s5p_ehci->otg->set_host(s5p_ehci->otg, &hcd->self);
- s5p_ehci_phy_enable(s5p_ehci);
+ if (s5p_ehci->phy)
+ usb_phy_init(s5p_ehci->phy);
+ else if (s5p_ehci->pdata->phy_init)
+ s5p_ehci->pdata->phy_init(pdev, USB_PHY_TYPE_HOST);
ehci = hcd_to_ehci(hcd);
ehci->caps = hcd->regs;
@@ -214,12 +172,15 @@ static int s5p_ehci_probe(struct platform_device *pdev)
goto fail_add_hcd;
}
- platform_set_drvdata(pdev, s5p_ehci);
+ platform_set_drvdata(pdev, hcd);
return 0;
fail_add_hcd:
- s5p_ehci_phy_disable(s5p_ehci);
+ if (s5p_ehci->phy)
+ usb_phy_shutdown(s5p_ehci->phy);
+ else if (s5p_ehci->pdata->phy_exit)
+ s5p_ehci->pdata->phy_exit(pdev, USB_PHY_TYPE_HOST);
fail_io:
clk_disable_unprepare(s5p_ehci->clk);
fail_clk:
@@ -229,15 +190,18 @@ fail_clk:
static int s5p_ehci_remove(struct platform_device *pdev)
{
- struct s5p_ehci_hcd *s5p_ehci = platform_get_drvdata(pdev);
- struct usb_hcd *hcd = s5p_ehci->hcd;
+ struct usb_hcd *hcd = platform_get_drvdata(pdev);
+ struct s5p_ehci_hcd *s5p_ehci = to_s5p_ehci(hcd);
usb_remove_hcd(hcd);
if (s5p_ehci->otg)
- s5p_ehci->otg->set_host(s5p_ehci->otg, &s5p_ehci->hcd->self);
+ s5p_ehci->otg->set_host(s5p_ehci->otg, &hcd->self);
- s5p_ehci_phy_disable(s5p_ehci);
+ if (s5p_ehci->phy)
+ usb_phy_shutdown(s5p_ehci->phy);
+ else if (s5p_ehci->pdata->phy_exit)
+ s5p_ehci->pdata->phy_exit(pdev, USB_PHY_TYPE_HOST);
clk_disable_unprepare(s5p_ehci->clk);
@@ -248,8 +212,7 @@ static int s5p_ehci_remove(struct platform_device *pdev)
static void s5p_ehci_shutdown(struct platform_device *pdev)
{
- struct s5p_ehci_hcd *s5p_ehci = platform_get_drvdata(pdev);
- struct usb_hcd *hcd = s5p_ehci->hcd;
+ struct usb_hcd *hcd = platform_get_drvdata(pdev);
if (hcd->driver->shutdown)
hcd->driver->shutdown(hcd);
@@ -258,17 +221,22 @@ static void s5p_ehci_shutdown(struct platform_device *pdev)
#ifdef CONFIG_PM
static int s5p_ehci_suspend(struct device *dev)
{
- struct s5p_ehci_hcd *s5p_ehci = dev_get_drvdata(dev);
- struct usb_hcd *hcd = s5p_ehci->hcd;
+ struct usb_hcd *hcd = dev_get_drvdata(dev);
+ struct s5p_ehci_hcd *s5p_ehci = to_s5p_ehci(hcd);
+ struct platform_device *pdev = to_platform_device(dev);
+
bool do_wakeup = device_may_wakeup(dev);
int rc;
rc = ehci_suspend(hcd, do_wakeup);
if (s5p_ehci->otg)
- s5p_ehci->otg->set_host(s5p_ehci->otg, &s5p_ehci->hcd->self);
+ s5p_ehci->otg->set_host(s5p_ehci->otg, &hcd->self);
- s5p_ehci_phy_disable(s5p_ehci);
+ if (s5p_ehci->phy)
+ usb_phy_shutdown(s5p_ehci->phy);
+ else if (s5p_ehci->pdata->phy_exit)
+ s5p_ehci->pdata->phy_exit(pdev, USB_PHY_TYPE_HOST);
clk_disable_unprepare(s5p_ehci->clk);
@@ -277,15 +245,19 @@ static int s5p_ehci_suspend(struct device *dev)
static int s5p_ehci_resume(struct device *dev)
{
- struct s5p_ehci_hcd *s5p_ehci = dev_get_drvdata(dev);
- struct usb_hcd *hcd = s5p_ehci->hcd;
+ struct usb_hcd *hcd = dev_get_drvdata(dev);
+ struct s5p_ehci_hcd *s5p_ehci = to_s5p_ehci(hcd);
+ struct platform_device *pdev = to_platform_device(dev);
clk_prepare_enable(s5p_ehci->clk);
if (s5p_ehci->otg)
- s5p_ehci->otg->set_host(s5p_ehci->otg, &s5p_ehci->hcd->self);
+ s5p_ehci->otg->set_host(s5p_ehci->otg, &hcd->self);
- s5p_ehci_phy_enable(s5p_ehci);
+ if (s5p_ehci->phy)
+ usb_phy_init(s5p_ehci->phy);
+ else if (s5p_ehci->pdata->phy_init)
+ s5p_ehci->pdata->phy_init(pdev, USB_PHY_TYPE_HOST);
/* DMA burst Enable */
writel(EHCI_INSNREG00_ENABLE_DMA_BURST, EHCI_INSNREG00(hcd->regs));
@@ -322,5 +294,29 @@ static struct platform_driver s5p_ehci_driver = {
.of_match_table = of_match_ptr(exynos_ehci_match),
}
};
+static const struct ehci_driver_overrides s5p_overrides __initdata = {
+ .extra_priv_size = sizeof(struct s5p_ehci_hcd),
+};
+
+static int __init ehci_s5p_init(void)
+{
+ if (usb_disabled())
+ return -ENODEV;
+
+ pr_info("%s: " DRIVER_DESC "\n", hcd_name);
+ ehci_init_driver(&s5p_ehci_hc_driver, &s5p_overrides);
+ return platform_driver_register(&s5p_ehci_driver);
+}
+module_init(ehci_s5p_init);
+
+static void __exit ehci_s5p_cleanup(void)
+{
+ platform_driver_unregister(&s5p_ehci_driver);
+}
+module_exit(ehci_s5p_cleanup);
+MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_ALIAS("platform:s5p-ehci");
+MODULE_AUTHOR("Jingoo Han");
+MODULE_AUTHOR("Joonyoung Shim");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
index b476daf49f6..acff5b8f6e8 100644
--- a/drivers/usb/host/ehci-sched.c
+++ b/drivers/usb/host/ehci-sched.c
@@ -539,6 +539,7 @@ static void qh_link_periodic(struct ehci_hcd *ehci, struct ehci_qh *qh)
}
qh->qh_state = QH_STATE_LINKED;
qh->xacterrs = 0;
+ qh->exception = 0;
/* update per-qh bandwidth for usbfs */
ehci_to_hcd(ehci)->self.bandwidth_allocated += qh->period
@@ -602,15 +603,9 @@ static void qh_unlink_periodic(struct ehci_hcd *ehci, struct ehci_qh *qh)
static void start_unlink_intr(struct ehci_hcd *ehci, struct ehci_qh *qh)
{
- /* If the QH isn't linked then there's nothing we can do
- * unless we were called during a giveback, in which case
- * qh_completions() has to deal with it.
- */
- if (qh->qh_state != QH_STATE_LINKED) {
- if (qh->qh_state == QH_STATE_COMPLETING)
- qh->needs_rescan = 1;
+ /* If the QH isn't linked then there's nothing we can do. */
+ if (qh->qh_state != QH_STATE_LINKED)
return;
- }
qh_unlink_periodic (ehci, qh);
@@ -625,17 +620,13 @@ static void start_unlink_intr(struct ehci_hcd *ehci, struct ehci_qh *qh)
qh->unlink_cycle = ehci->intr_unlink_cycle;
/* New entries go at the end of the intr_unlink list */
- if (ehci->intr_unlink)
- ehci->intr_unlink_last->unlink_next = qh;
- else
- ehci->intr_unlink = qh;
- ehci->intr_unlink_last = qh;
+ list_add_tail(&qh->unlink_node, &ehci->intr_unlink);
if (ehci->intr_unlinking)
; /* Avoid recursive calls */
else if (ehci->rh_state < EHCI_RH_RUNNING)
ehci_handle_intr_unlinks(ehci);
- else if (ehci->intr_unlink == qh) {
+ else if (ehci->intr_unlink.next == &qh->unlink_node) {
ehci_enable_event(ehci, EHCI_HRTIMER_UNLINK_INTR, true);
++ehci->intr_unlink_cycle;
}
@@ -649,7 +640,8 @@ static void end_unlink_intr(struct ehci_hcd *ehci, struct ehci_qh *qh)
qh->qh_state = QH_STATE_IDLE;
hw->hw_next = EHCI_LIST_END(ehci);
- qh_completions(ehci, qh);
+ if (!list_empty(&qh->qtd_list))
+ qh_completions(ehci, qh);
/* reschedule QH iff another request is queued */
if (!list_empty(&qh->qtd_list) && ehci->rh_state == EHCI_RH_RUNNING) {
@@ -792,7 +784,6 @@ static int qh_schedule(struct ehci_hcd *ehci, struct ehci_qh *qh)
unsigned frame; /* 0..(qh->period - 1), or NO_FRAME */
struct ehci_qh_hw *hw = qh->hw;
- qh_refresh(ehci, qh);
hw->hw_next = EHCI_LIST_END(ehci);
frame = qh->start;
@@ -844,8 +835,6 @@ static int qh_schedule(struct ehci_hcd *ehci, struct ehci_qh *qh)
} else
ehci_dbg (ehci, "reused qh %p schedule\n", qh);
- /* stuff into the periodic schedule */
- qh_link_periodic(ehci, qh);
done:
return status;
}
@@ -891,6 +880,12 @@ static int intr_submit (
qh = qh_append_tds(ehci, urb, qtd_list, epnum, &urb->ep->hcpriv);
BUG_ON (qh == NULL);
+ /* stuff into the periodic schedule */
+ if (qh->qh_state == QH_STATE_IDLE) {
+ qh_refresh(ehci, qh);
+ qh_link_periodic(ehci, qh);
+ }
+
/* ... update usbfs periodic stats */
ehci_to_hcd(ehci)->self.bandwidth_int_reqs++;
@@ -911,7 +906,7 @@ static void scan_intr(struct ehci_hcd *ehci)
list_for_each_entry_safe(qh, ehci->qh_scan_next, &ehci->intr_qh_list,
intr_node) {
- rescan:
+
/* clean any finished work for this qh */
if (!list_empty(&qh->qtd_list)) {
int temp;
@@ -924,12 +919,9 @@ static void scan_intr(struct ehci_hcd *ehci)
* in qh_unlink_periodic().
*/
temp = qh_completions(ehci, qh);
- if (unlikely(qh->needs_rescan ||
- (list_empty(&qh->qtd_list) &&
- qh->qh_state == QH_STATE_LINKED)))
+ if (unlikely(temp || (list_empty(&qh->qtd_list) &&
+ qh->qh_state == QH_STATE_LINKED)))
start_unlink_intr(ehci, qh);
- else if (temp != 0)
- goto rescan;
}
}
}
@@ -1214,6 +1206,7 @@ itd_urb_transaction (
memset (itd, 0, sizeof *itd);
itd->itd_dma = itd_dma;
+ itd->frame = 9999; /* an invalid value */
list_add (&itd->itd_list, &sched->td_list);
}
spin_unlock_irqrestore (&ehci->lock, flags);
@@ -1915,6 +1908,7 @@ sitd_urb_transaction (
memset (sitd, 0, sizeof *sitd);
sitd->sitd_dma = sitd_dma;
+ sitd->frame = 9999; /* an invalid value */
list_add (&sitd->sitd_list, &iso_sched->td_list);
}
diff --git a/drivers/usb/host/ehci-sh.c b/drivers/usb/host/ehci-sh.c
index 3565a300f40..b44d716ddc8 100644
--- a/drivers/usb/host/ehci-sh.c
+++ b/drivers/usb/host/ehci-sh.c
@@ -77,7 +77,6 @@ static const struct hc_driver ehci_sh_hc_driver = {
static int ehci_hcd_sh_probe(struct platform_device *pdev)
{
- const struct hc_driver *driver = &ehci_sh_hc_driver;
struct resource *res;
struct ehci_sh_priv *priv;
struct ehci_sh_platdata *pdata;
@@ -170,7 +169,7 @@ fail_create_hcd:
return ret;
}
-static int __exit ehci_hcd_sh_remove(struct platform_device *pdev)
+static int ehci_hcd_sh_remove(struct platform_device *pdev)
{
struct ehci_sh_priv *priv = platform_get_drvdata(pdev);
struct usb_hcd *hcd = priv->hcd;
@@ -196,7 +195,7 @@ static void ehci_hcd_sh_shutdown(struct platform_device *pdev)
static struct platform_driver ehci_hcd_sh_driver = {
.probe = ehci_hcd_sh_probe,
- .remove = __exit_p(ehci_hcd_sh_remove),
+ .remove = ehci_hcd_sh_remove,
.shutdown = ehci_hcd_sh_shutdown,
.driver = {
.name = "sh_ehci",
diff --git a/drivers/usb/host/ehci-spear.c b/drivers/usb/host/ehci-spear.c
index 466c1bb5b96..61ecfb3d52f 100644
--- a/drivers/usb/host/ehci-spear.c
+++ b/drivers/usb/host/ehci-spear.c
@@ -1,5 +1,5 @@
/*
-* Driver for EHCI HCD on SPEAR SOC
+* Driver for EHCI HCD on SPEAr SOC
*
* Copyright (C) 2010 ST Micro Electronics,
* Deepak Sikri <deepak.sikri@st.com>
@@ -12,73 +12,32 @@
*/
#include <linux/clk.h>
+#include <linux/dma-mapping.h>
+#include <linux/io.h>
#include <linux/jiffies.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/pm.h>
+#include <linux/usb.h>
+#include <linux/usb/hcd.h>
-struct spear_ehci {
- struct ehci_hcd ehci;
- struct clk *clk;
-};
-
-#define to_spear_ehci(hcd) (struct spear_ehci *)hcd_to_ehci(hcd)
+#include "ehci.h"
-static void spear_start_ehci(struct spear_ehci *ehci)
-{
- clk_prepare_enable(ehci->clk);
-}
+#define DRIVER_DESC "EHCI SPEAr driver"
-static void spear_stop_ehci(struct spear_ehci *ehci)
-{
- clk_disable_unprepare(ehci->clk);
-}
+static const char hcd_name[] = "SPEAr-ehci";
-static int ehci_spear_setup(struct usb_hcd *hcd)
-{
- struct ehci_hcd *ehci = hcd_to_ehci(hcd);
-
- /* registers start at offset 0x0 */
- ehci->caps = hcd->regs;
+struct spear_ehci {
+ struct clk *clk;
+};
- return ehci_setup(hcd);
-}
+#define to_spear_ehci(hcd) (struct spear_ehci *)(hcd_to_ehci(hcd)->priv)
-static const struct hc_driver ehci_spear_hc_driver = {
- .description = hcd_name,
- .product_desc = "SPEAr EHCI",
- .hcd_priv_size = sizeof(struct spear_ehci),
-
- /* generic hardware linkage */
- .irq = ehci_irq,
- .flags = HCD_MEMORY | HCD_USB2,
-
- /* basic lifecycle operations */
- .reset = ehci_spear_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 ehci_spear_hc_driver;
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
static int ehci_spear_drv_suspend(struct device *dev)
{
struct usb_hcd *hcd = dev_get_drvdata(dev);
@@ -94,7 +53,7 @@ static int ehci_spear_drv_resume(struct device *dev)
ehci_resume(hcd, false);
return 0;
}
-#endif /* CONFIG_PM */
+#endif /* CONFIG_PM_SLEEP */
static SIMPLE_DEV_PM_OPS(ehci_spear_pm_ops, ehci_spear_drv_suspend,
ehci_spear_drv_resume);
@@ -104,7 +63,7 @@ static u64 spear_ehci_dma_mask = DMA_BIT_MASK(32);
static int spear_ehci_hcd_drv_probe(struct platform_device *pdev)
{
struct usb_hcd *hcd ;
- struct spear_ehci *ehci;
+ struct spear_ehci *sehci;
struct resource *res;
struct clk *usbh_clk;
const struct hc_driver *driver = &ehci_spear_hc_driver;
@@ -161,10 +120,13 @@ static int spear_ehci_hcd_drv_probe(struct platform_device *pdev)
goto err_put_hcd;
}
- ehci = (struct spear_ehci *)hcd_to_ehci(hcd);
- ehci->clk = usbh_clk;
+ sehci = to_spear_ehci(hcd);
+ sehci->clk = usbh_clk;
+
+ /* registers start at offset 0x0 */
+ hcd_to_ehci(hcd)->caps = hcd->regs;
- spear_start_ehci(ehci);
+ clk_prepare_enable(sehci->clk);
retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
if (retval)
goto err_stop_ehci;
@@ -172,7 +134,7 @@ static int spear_ehci_hcd_drv_probe(struct platform_device *pdev)
return retval;
err_stop_ehci:
- spear_stop_ehci(ehci);
+ clk_disable_unprepare(sehci->clk);
err_put_hcd:
usb_put_hcd(hcd);
fail:
@@ -184,7 +146,7 @@ fail:
static int spear_ehci_hcd_drv_remove(struct platform_device *pdev)
{
struct usb_hcd *hcd = platform_get_drvdata(pdev);
- struct spear_ehci *ehci_p = to_spear_ehci(hcd);
+ struct spear_ehci *sehci = to_spear_ehci(hcd);
if (!hcd)
return 0;
@@ -192,8 +154,8 @@ static int spear_ehci_hcd_drv_remove(struct platform_device *pdev)
BUG();
usb_remove_hcd(hcd);
- if (ehci_p->clk)
- spear_stop_ehci(ehci_p);
+ if (sehci->clk)
+ clk_disable_unprepare(sehci->clk);
usb_put_hcd(hcd);
return 0;
@@ -216,4 +178,29 @@ static struct platform_driver spear_ehci_hcd_driver = {
}
};
+static const struct ehci_driver_overrides spear_overrides __initdata = {
+ .extra_priv_size = sizeof(struct spear_ehci),
+};
+
+static int __init ehci_spear_init(void)
+{
+ if (usb_disabled())
+ return -ENODEV;
+
+ pr_info("%s: " DRIVER_DESC "\n", hcd_name);
+
+ ehci_init_driver(&ehci_spear_hc_driver, &spear_overrides);
+ return platform_driver_register(&spear_ehci_hcd_driver);
+}
+module_init(ehci_spear_init);
+
+static void __exit ehci_spear_cleanup(void)
+{
+ platform_driver_unregister(&spear_ehci_hcd_driver);
+}
+module_exit(ehci_spear_cleanup);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_ALIAS("platform:spear-ehci");
+MODULE_AUTHOR("Deepak Sikri");
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c
index 568aecc7075..e3eddc31ac8 100644
--- a/drivers/usb/host/ehci-tegra.c
+++ b/drivers/usb/host/ehci-tegra.c
@@ -28,6 +28,7 @@
#include <linux/pm_runtime.h>
#include <linux/usb/ehci_def.h>
#include <linux/usb/tegra_usb_phy.h>
+#include <linux/clk/tegra.h>
#define TEGRA_USB_BASE 0xC5000000
#define TEGRA_USB2_BASE 0xC5004000
@@ -610,7 +611,7 @@ static const struct dev_pm_ops tegra_ehci_pm_ops = {
/* Bits of PORTSC1, which will get cleared by writing 1 into them */
#define TEGRA_PORTSC1_RWC_BITS (PORT_CSC | PORT_PEC | PORT_OCC)
-void tegra_ehci_set_pts(struct usb_phy *x, u8 pts_val)
+static void tegra_ehci_set_pts(struct usb_phy *x, u8 pts_val)
{
unsigned long val;
struct usb_hcd *hcd = bus_to_hcd(x->otg->host);
@@ -621,9 +622,8 @@ void tegra_ehci_set_pts(struct usb_phy *x, u8 pts_val)
val |= TEGRA_USB_PORTSC1_PTS(pts_val & 3);
writel(val, base + TEGRA_USB_PORTSC1);
}
-EXPORT_SYMBOL_GPL(tegra_ehci_set_pts);
-void tegra_ehci_set_phcd(struct usb_phy *x, bool enable)
+static void tegra_ehci_set_phcd(struct usb_phy *x, bool enable)
{
unsigned long val;
struct usb_hcd *hcd = bus_to_hcd(x->otg->host);
@@ -636,7 +636,6 @@ void tegra_ehci_set_phcd(struct usb_phy *x, bool enable)
val &= ~TEGRA_USB_PORTSC1_PHCD;
writel(val, base + TEGRA_USB_PORTSC1);
}
-EXPORT_SYMBOL_GPL(tegra_ehci_set_phcd);
static u64 tegra_ehci_dma_mask = DMA_BIT_MASK(32);
@@ -691,6 +690,10 @@ static int tegra_ehci_probe(struct platform_device *pdev)
if (err)
goto fail_clk;
+ tegra_periph_reset_assert(tegra->clk);
+ udelay(1);
+ tegra_periph_reset_deassert(tegra->clk);
+
tegra->needs_double_reset = of_property_read_bool(pdev->dev.of_node,
"nvidia,needs-double-reset");
@@ -733,7 +736,9 @@ static int tegra_ehci_probe(struct platform_device *pdev)
tegra->phy = tegra_usb_phy_open(&pdev->dev, instance, hcd->regs,
pdata->phy_config,
- TEGRA_USB_PHY_MODE_HOST);
+ TEGRA_USB_PHY_MODE_HOST,
+ tegra_ehci_set_pts,
+ tegra_ehci_set_phcd);
if (IS_ERR(tegra->phy)) {
dev_err(&pdev->dev, "Failed to open USB phy\n");
err = -ENXIO;
@@ -755,7 +760,7 @@ static int tegra_ehci_probe(struct platform_device *pdev)
err = usb_phy_set_suspend(hcd->phy, 0);
if (err) {
dev_err(&pdev->dev, "Failed to power on the phy\n");
- goto fail;
+ goto fail_phy;
}
tegra->host_resumed = 1;
@@ -765,17 +770,17 @@ static int tegra_ehci_probe(struct platform_device *pdev)
if (!irq) {
dev_err(&pdev->dev, "Failed to get IRQ\n");
err = -ENODEV;
- goto fail;
+ goto fail_phy;
}
-#ifdef CONFIG_USB_OTG_UTILS
if (pdata->operating_mode == TEGRA_USB_OTG) {
tegra->transceiver =
devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2);
- if (!IS_ERR_OR_NULL(tegra->transceiver))
+ if (!IS_ERR(tegra->transceiver))
otg_set_host(tegra->transceiver->otg, &hcd->self);
+ } else {
+ tegra->transceiver = ERR_PTR(-ENODEV);
}
-#endif
err = usb_add_hcd(hcd, irq, IRQF_SHARED);
if (err) {
@@ -794,10 +799,9 @@ static int tegra_ehci_probe(struct platform_device *pdev)
return err;
fail:
-#ifdef CONFIG_USB_OTG_UTILS
- if (!IS_ERR_OR_NULL(tegra->transceiver))
+ if (!IS_ERR(tegra->transceiver))
otg_set_host(tegra->transceiver->otg, NULL);
-#endif
+fail_phy:
usb_phy_shutdown(hcd->phy);
fail_io:
clk_disable_unprepare(tegra->clk);
@@ -815,10 +819,8 @@ static int tegra_ehci_remove(struct platform_device *pdev)
pm_runtime_disable(&pdev->dev);
pm_runtime_put_noidle(&pdev->dev);
-#ifdef CONFIG_USB_OTG_UTILS
- if (!IS_ERR_OR_NULL(tegra->transceiver))
+ if (!IS_ERR(tegra->transceiver))
otg_set_host(tegra->transceiver->otg, NULL);
-#endif
usb_phy_shutdown(hcd->phy);
usb_remove_hcd(hcd);
diff --git a/drivers/usb/host/ehci-timer.c b/drivers/usb/host/ehci-timer.c
index 20dbdcbe9b0..11e5b32f73e 100644
--- a/drivers/usb/host/ehci-timer.c
+++ b/drivers/usb/host/ehci-timer.c
@@ -113,8 +113,8 @@ static void ehci_poll_ASS(struct ehci_hcd *ehci)
if (want != actual) {
- /* Poll again later, but give up after about 20 ms */
- if (ehci->ASS_poll_count++ < 20) {
+ /* Poll again later, but give up after about 2-4 ms */
+ if (ehci->ASS_poll_count++ < 2) {
ehci_enable_event(ehci, EHCI_HRTIMER_POLL_ASS, true);
return;
}
@@ -159,8 +159,8 @@ static void ehci_poll_PSS(struct ehci_hcd *ehci)
if (want != actual) {
- /* Poll again later, but give up after about 20 ms */
- if (ehci->PSS_poll_count++ < 20) {
+ /* Poll again later, but give up after about 2-4 ms */
+ if (ehci->PSS_poll_count++ < 2) {
ehci_enable_event(ehci, EHCI_HRTIMER_POLL_PSS, true);
return;
}
@@ -229,18 +229,19 @@ static void ehci_handle_intr_unlinks(struct ehci_hcd *ehci)
* process all the QHs on the list.
*/
ehci->intr_unlinking = true;
- while (ehci->intr_unlink) {
- struct ehci_qh *qh = ehci->intr_unlink;
+ while (!list_empty(&ehci->intr_unlink)) {
+ struct ehci_qh *qh;
+ qh = list_first_entry(&ehci->intr_unlink, struct ehci_qh,
+ unlink_node);
if (!stopped && qh->unlink_cycle == ehci->intr_unlink_cycle)
break;
- ehci->intr_unlink = qh->unlink_next;
- qh->unlink_next = NULL;
+ list_del(&qh->unlink_node);
end_unlink_intr(ehci, qh);
}
/* Handle remaining entries later */
- if (ehci->intr_unlink) {
+ if (!list_empty(&ehci->intr_unlink)) {
ehci_enable_event(ehci, EHCI_HRTIMER_UNLINK_INTR, true);
++ehci->intr_unlink_cycle;
}
@@ -295,8 +296,7 @@ static void end_free_itds(struct ehci_hcd *ehci)
/* Handle lost (or very late) IAA interrupts */
static void ehci_iaa_watchdog(struct ehci_hcd *ehci)
{
- if (ehci->rh_state != EHCI_RH_RUNNING)
- return;
+ u32 cmd, status;
/*
* Lost IAA irqs wedge things badly; seen first with a vt8235.
@@ -304,34 +304,32 @@ static void ehci_iaa_watchdog(struct ehci_hcd *ehci)
* (a) SMP races against real IAA firing and retriggering, and
* (b) clean HC shutdown, when IAA watchdog was pending.
*/
- if (ehci->async_iaa) {
- u32 cmd, status;
-
- /* If we get here, IAA is *REALLY* late. It's barely
- * conceivable that the system is so busy that CMD_IAAD
- * is still legitimately set, so let's be sure it's
- * clear before we read STS_IAA. (The HC should clear
- * CMD_IAAD when it sets STS_IAA.)
- */
- cmd = ehci_readl(ehci, &ehci->regs->command);
-
- /*
- * If IAA is set here it either legitimately triggered
- * after the watchdog timer expired (_way_ late, so we'll
- * still count it as lost) ... or a silicon erratum:
- * - VIA seems to set IAA without triggering the IRQ;
- * - IAAD potentially cleared without setting IAA.
- */
- status = ehci_readl(ehci, &ehci->regs->status);
- if ((status & STS_IAA) || !(cmd & CMD_IAAD)) {
- COUNT(ehci->stats.lost_iaa);
- ehci_writel(ehci, STS_IAA, &ehci->regs->status);
- }
+ if (!ehci->iaa_in_progress || ehci->rh_state != EHCI_RH_RUNNING)
+ return;
+
+ /* If we get here, IAA is *REALLY* late. It's barely
+ * conceivable that the system is so busy that CMD_IAAD
+ * is still legitimately set, so let's be sure it's
+ * clear before we read STS_IAA. (The HC should clear
+ * CMD_IAAD when it sets STS_IAA.)
+ */
+ cmd = ehci_readl(ehci, &ehci->regs->command);
- ehci_vdbg(ehci, "IAA watchdog: status %x cmd %x\n",
- status, cmd);
- end_unlink_async(ehci);
+ /*
+ * If IAA is set here it either legitimately triggered
+ * after the watchdog timer expired (_way_ late, so we'll
+ * still count it as lost) ... or a silicon erratum:
+ * - VIA seems to set IAA without triggering the IRQ;
+ * - IAAD potentially cleared without setting IAA.
+ */
+ status = ehci_readl(ehci, &ehci->regs->status);
+ if ((status & STS_IAA) || !(cmd & CMD_IAAD)) {
+ COUNT(ehci->stats.lost_iaa);
+ ehci_writel(ehci, STS_IAA, &ehci->regs->status);
}
+
+ ehci_dbg(ehci, "IAA watchdog: status %x cmd %x\n", status, cmd);
+ end_unlink_async(ehci);
}
diff --git a/drivers/usb/host/ehci-vt8500.c b/drivers/usb/host/ehci-vt8500.c
deleted file mode 100644
index 7ecf709610b..00000000000
--- a/drivers/usb/host/ehci-vt8500.c
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * drivers/usb/host/ehci-vt8500.c
- *
- * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
- *
- * Based on ehci-au1xxx.c
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-
-#include <linux/err.h>
-#include <linux/of.h>
-#include <linux/platform_device.h>
-
-static const struct hc_driver vt8500_ehci_hc_driver = {
- .description = hcd_name,
- .product_desc = "VT8500 EHCI",
- .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,
-
- /*
- * 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 u64 vt8500_ehci_dma_mask = DMA_BIT_MASK(32);
-
-static int vt8500_ehci_drv_probe(struct platform_device *pdev)
-{
- struct usb_hcd *hcd;
- struct ehci_hcd *ehci;
- struct resource *res;
- int ret;
-
- if (usb_disabled())
- return -ENODEV;
-
- /*
- * 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 have dma capability bindings this can go away.
- */
- if (!pdev->dev.dma_mask)
- pdev->dev.dma_mask = &vt8500_ehci_dma_mask;
-
- if (pdev->resource[1].flags != IORESOURCE_IRQ) {
- pr_debug("resource[1] is not IORESOURCE_IRQ");
- return -ENOMEM;
- }
- hcd = usb_create_hcd(&vt8500_ehci_hc_driver, &pdev->dev, "VT8500");
- 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_ioremap_resource(&pdev->dev, res);
- if (IS_ERR(hcd->regs)) {
- ret = PTR_ERR(hcd->regs);
- goto err1;
- }
-
- ehci = hcd_to_ehci(hcd);
- ehci->caps = hcd->regs;
-
- ret = usb_add_hcd(hcd, pdev->resource[1].start,
- IRQF_SHARED);
- if (ret == 0) {
- platform_set_drvdata(pdev, hcd);
- return ret;
- }
-
-err1:
- usb_put_hcd(hcd);
- return ret;
-}
-
-static int vt8500_ehci_drv_remove(struct platform_device *pdev)
-{
- struct usb_hcd *hcd = platform_get_drvdata(pdev);
-
- usb_remove_hcd(hcd);
- usb_put_hcd(hcd);
- platform_set_drvdata(pdev, NULL);
-
- return 0;
-}
-
-static const struct of_device_id vt8500_ehci_ids[] = {
- { .compatible = "via,vt8500-ehci", },
- { .compatible = "wm,prizm-ehci", },
- {}
-};
-
-static struct platform_driver vt8500_ehci_driver = {
- .probe = vt8500_ehci_drv_probe,
- .remove = vt8500_ehci_drv_remove,
- .shutdown = usb_hcd_platform_shutdown,
- .driver = {
- .name = "vt8500-ehci",
- .owner = THIS_MODULE,
- .of_match_table = of_match_ptr(vt8500_ehci_ids),
- }
-};
-
-MODULE_ALIAS("platform:vt8500-ehci");
-MODULE_DEVICE_TABLE(of, vt8500_ehci_ids);
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index 36c3a821059..7c978b23520 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -121,6 +121,7 @@ struct ehci_hcd { /* one per controller */
bool scanning:1;
bool need_rescan:1;
bool intr_unlinking:1;
+ bool iaa_in_progress:1;
bool async_unlinking:1;
bool shutdown:1;
struct ehci_qh *qh_scan_next;
@@ -128,9 +129,8 @@ struct ehci_hcd { /* one per controller */
/* async schedule support */
struct ehci_qh *async;
struct ehci_qh *dummy; /* For AMD quirk use */
- struct ehci_qh *async_unlink;
- struct ehci_qh *async_unlink_last;
- struct ehci_qh *async_iaa;
+ struct list_head async_unlink;
+ struct list_head async_idle;
unsigned async_unlink_cycle;
unsigned async_count; /* async activity count */
@@ -143,8 +143,7 @@ struct ehci_hcd { /* one per controller */
unsigned i_thresh; /* uframes HC might cache */
union ehci_shadow *pshadow; /* mirror hw periodic table */
- struct ehci_qh *intr_unlink;
- struct ehci_qh *intr_unlink_last;
+ struct list_head intr_unlink;
unsigned intr_unlink_cycle;
unsigned now_frame; /* frame from HC hardware */
unsigned last_iso_frame; /* last frame scanned for iso */
@@ -200,6 +199,7 @@ struct ehci_hcd { /* one per controller */
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) */
+ unsigned need_oc_pp_cycle:1; /* MPC834X port power */
/* required for usb32 quirk */
#define OHCI_CTRL_HCFS (3 << 6)
@@ -380,11 +380,10 @@ struct ehci_qh {
struct list_head qtd_list; /* sw qtd list */
struct list_head intr_node; /* list of intr QHs */
struct ehci_qtd *dummy;
- struct ehci_qh *unlink_next; /* next on unlink list */
+ struct list_head unlink_node;
unsigned unlink_cycle;
- u8 needs_rescan; /* Dequeue during giveback */
u8 qh_state;
#define QH_STATE_LINKED 1 /* HC sees this */
#define QH_STATE_UNLINK 2 /* HC may still see this */
@@ -407,6 +406,9 @@ struct ehci_qh {
struct usb_device *dev; /* access to TT */
unsigned is_out:1; /* bulk or intr OUT */
unsigned clearing_tt:1; /* Clear-TT-Buf in progress */
+ unsigned dequeue_during_giveback:1;
+ unsigned exception:1; /* got a fault, or an unlink
+ was requested */
};
/*-------------------------------------------------------------------------*/
diff --git a/drivers/usb/host/ohci-exynos.c b/drivers/usb/host/ohci-exynos.c
index e3b7e85120e..114583a8e92 100644
--- a/drivers/usb/host/ohci-exynos.c
+++ b/drivers/usb/host/ohci-exynos.c
@@ -17,7 +17,6 @@
#include <linux/platform_data/usb-exynos.h>
#include <linux/usb/phy.h>
#include <linux/usb/samsung_usb_phy.h>
-#include <plat/usb-phy.h>
struct exynos_ohci_hcd {
struct device *dev;
@@ -34,7 +33,7 @@ static void exynos_ohci_phy_enable(struct exynos_ohci_hcd *exynos_ohci)
if (exynos_ohci->phy)
usb_phy_init(exynos_ohci->phy);
- else if (exynos_ohci->pdata->phy_init)
+ else if (exynos_ohci->pdata && exynos_ohci->pdata->phy_init)
exynos_ohci->pdata->phy_init(pdev, USB_PHY_TYPE_HOST);
}
@@ -44,7 +43,7 @@ static void exynos_ohci_phy_disable(struct exynos_ohci_hcd *exynos_ohci)
if (exynos_ohci->phy)
usb_phy_shutdown(exynos_ohci->phy);
- else if (exynos_ohci->pdata->phy_exit)
+ else if (exynos_ohci->pdata && exynos_ohci->pdata->phy_exit)
exynos_ohci->pdata->phy_exit(pdev, USB_PHY_TYPE_HOST);
}
@@ -127,8 +126,12 @@ static int exynos_ohci_probe(struct platform_device *pdev)
if (!exynos_ohci)
return -ENOMEM;
+ if (of_device_is_compatible(pdev->dev.of_node,
+ "samsung,exynos5440-ohci"))
+ goto skip_phy;
+
phy = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2);
- if (IS_ERR_OR_NULL(phy)) {
+ if (IS_ERR(phy)) {
/* Fallback to pdata */
if (!pdata) {
dev_warn(&pdev->dev, "no platform data or transceiver defined\n");
@@ -141,6 +144,8 @@ static int exynos_ohci_probe(struct platform_device *pdev)
exynos_ohci->otg = phy->otg;
}
+skip_phy:
+
exynos_ohci->dev = &pdev->dev;
hcd = usb_create_hcd(&exynos_ohci_hc_driver, &pdev->dev,
@@ -311,6 +316,7 @@ static const struct dev_pm_ops exynos_ohci_pm_ops = {
#ifdef CONFIG_OF
static const struct of_device_id exynos_ohci_match[] = {
{ .compatible = "samsung,exynos4210-ohci" },
+ { .compatible = "samsung,exynos5440-ohci" },
{},
};
MODULE_DEVICE_TABLE(of, exynos_ohci_match);
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index 180a2b01db5..9e6de9586ae 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -1102,12 +1102,12 @@ MODULE_LICENSE ("GPL");
#if defined(CONFIG_ARCH_S3C24XX) || defined(CONFIG_ARCH_S3C64XX)
#include "ohci-s3c2410.c"
-#define PLATFORM_DRIVER ohci_hcd_s3c2410_driver
+#define S3C2410_PLATFORM_DRIVER ohci_hcd_s3c2410_driver
#endif
#ifdef CONFIG_USB_OHCI_EXYNOS
#include "ohci-exynos.c"
-#define PLATFORM_DRIVER exynos_ohci_driver
+#define EXYNOS_PLATFORM_DRIVER exynos_ohci_driver
#endif
#ifdef CONFIG_USB_OHCI_HCD_OMAP1
@@ -1127,25 +1127,24 @@ MODULE_LICENSE ("GPL");
#ifdef CONFIG_ARCH_EP93XX
#include "ohci-ep93xx.c"
-#define PLATFORM_DRIVER ohci_hcd_ep93xx_driver
+#define EP93XX_PLATFORM_DRIVER ohci_hcd_ep93xx_driver
#endif
#ifdef CONFIG_ARCH_AT91
#include "ohci-at91.c"
-#define PLATFORM_DRIVER ohci_hcd_at91_driver
+#define AT91_PLATFORM_DRIVER ohci_hcd_at91_driver
#endif
#ifdef CONFIG_ARCH_LPC32XX
#include "ohci-nxp.c"
-#define PLATFORM_DRIVER usb_hcd_nxp_driver
+#define NXP_PLATFORM_DRIVER usb_hcd_nxp_driver
#endif
#ifdef CONFIG_ARCH_DAVINCI_DA8XX
#include "ohci-da8xx.c"
-#define PLATFORM_DRIVER ohci_hcd_da8xx_driver
+#define DAVINCI_PLATFORM_DRIVER ohci_hcd_da8xx_driver
#endif
-
#ifdef CONFIG_USB_OHCI_HCD_PPC_OF
#include "ohci-ppc-of.c"
#define OF_PLATFORM_DRIVER ohci_hcd_ppc_of_driver
@@ -1153,7 +1152,7 @@ MODULE_LICENSE ("GPL");
#ifdef CONFIG_PLAT_SPEAR
#include "ohci-spear.c"
-#define PLATFORM_DRIVER spear_ohci_hcd_driver
+#define SPEAR_PLATFORM_DRIVER spear_ohci_hcd_driver
#endif
#ifdef CONFIG_PPC_PS3
@@ -1199,7 +1198,14 @@ MODULE_LICENSE ("GPL");
!defined(SA1111_DRIVER) && \
!defined(PS3_SYSTEM_BUS_DRIVER) && \
!defined(SM501_OHCI_DRIVER) && \
- !defined(TMIO_OHCI_DRIVER)
+ !defined(TMIO_OHCI_DRIVER) && \
+ !defined(S3C2410_PLATFORM_DRIVER) && \
+ !defined(EXYNOS_PLATFORM_DRIVER) && \
+ !defined(EP93XX_PLATFORM_DRIVER) && \
+ !defined(AT91_PLATFORM_DRIVER) && \
+ !defined(NXP_PLATFORM_DRIVER) && \
+ !defined(DAVINCI_PLATFORM_DRIVER) && \
+ !defined(SPEAR_PLATFORM_DRIVER)
#error "missing bus glue for ohci-hcd"
#endif
@@ -1277,9 +1283,79 @@ static int __init ohci_hcd_mod_init(void)
goto error_tmio;
#endif
+#ifdef S3C2410_PLATFORM_DRIVER
+ retval = platform_driver_register(&S3C2410_PLATFORM_DRIVER);
+ if (retval < 0)
+ goto error_s3c2410;
+#endif
+
+#ifdef EXYNOS_PLATFORM_DRIVER
+ retval = platform_driver_register(&EXYNOS_PLATFORM_DRIVER);
+ if (retval < 0)
+ goto error_exynos;
+#endif
+
+#ifdef EP93XX_PLATFORM_DRIVER
+ retval = platform_driver_register(&EP93XX_PLATFORM_DRIVER);
+ if (retval < 0)
+ goto error_ep93xx;
+#endif
+
+#ifdef AT91_PLATFORM_DRIVER
+ retval = platform_driver_register(&AT91_PLATFORM_DRIVER);
+ if (retval < 0)
+ goto error_at91;
+#endif
+
+#ifdef NXP_PLATFORM_DRIVER
+ retval = platform_driver_register(&NXP_PLATFORM_DRIVER);
+ if (retval < 0)
+ goto error_nxp;
+#endif
+
+#ifdef DAVINCI_PLATFORM_DRIVER
+ retval = platform_driver_register(&DAVINCI_PLATFORM_DRIVER);
+ if (retval < 0)
+ goto error_davinci;
+#endif
+
+#ifdef SPEAR_PLATFORM_DRIVER
+ retval = platform_driver_register(&SPEAR_PLATFORM_DRIVER);
+ if (retval < 0)
+ goto error_spear;
+#endif
+
return retval;
/* Error path */
+#ifdef SPEAR_PLATFORM_DRIVER
+ platform_driver_unregister(&SPEAR_PLATFORM_DRIVER);
+ error_spear:
+#endif
+#ifdef DAVINCI_PLATFORM_DRIVER
+ platform_driver_unregister(&DAVINCI_PLATFORM_DRIVER);
+ error_davinci:
+#endif
+#ifdef NXP_PLATFORM_DRIVER
+ platform_driver_unregister(&NXP_PLATFORM_DRIVER);
+ error_nxp:
+#endif
+#ifdef AT91_PLATFORM_DRIVER
+ platform_driver_unregister(&AT91_PLATFORM_DRIVER);
+ error_at91:
+#endif
+#ifdef EP93XX_PLATFORM_DRIVER
+ platform_driver_unregister(&EP93XX_PLATFORM_DRIVER);
+ error_ep93xx:
+#endif
+#ifdef EXYNOS_PLATFORM_DRIVER
+ platform_driver_unregister(&EXYNOS_PLATFORM_DRIVER);
+ error_exynos:
+#endif
+#ifdef S3C2410_PLATFORM_DRIVER
+ platform_driver_unregister(&S3C2410_PLATFORM_DRIVER);
+ error_s3c2410:
+#endif
#ifdef TMIO_OHCI_DRIVER
platform_driver_unregister(&TMIO_OHCI_DRIVER);
error_tmio:
@@ -1300,17 +1376,17 @@ static int __init ohci_hcd_mod_init(void)
platform_driver_unregister(&OF_PLATFORM_DRIVER);
error_of_platform:
#endif
-#ifdef PLATFORM_DRIVER
- platform_driver_unregister(&PLATFORM_DRIVER);
- error_platform:
+#ifdef OMAP3_PLATFORM_DRIVER
+ platform_driver_unregister(&OMAP3_PLATFORM_DRIVER);
+ error_omap3_platform:
#endif
#ifdef OMAP1_PLATFORM_DRIVER
platform_driver_unregister(&OMAP1_PLATFORM_DRIVER);
error_omap1_platform:
#endif
-#ifdef OMAP3_PLATFORM_DRIVER
- platform_driver_unregister(&OMAP3_PLATFORM_DRIVER);
- error_omap3_platform:
+#ifdef PLATFORM_DRIVER
+ platform_driver_unregister(&PLATFORM_DRIVER);
+ error_platform:
#endif
#ifdef PS3_SYSTEM_BUS_DRIVER
ps3_ohci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);
@@ -1329,6 +1405,27 @@ module_init(ohci_hcd_mod_init);
static void __exit ohci_hcd_mod_exit(void)
{
+#ifdef SPEAR_PLATFORM_DRIVER
+ platform_driver_unregister(&SPEAR_PLATFORM_DRIVER);
+#endif
+#ifdef DAVINCI_PLATFORM_DRIVER
+ platform_driver_unregister(&DAVINCI_PLATFORM_DRIVER);
+#endif
+#ifdef NXP_PLATFORM_DRIVER
+ platform_driver_unregister(&NXP_PLATFORM_DRIVER);
+#endif
+#ifdef AT91_PLATFORM_DRIVER
+ platform_driver_unregister(&AT91_PLATFORM_DRIVER);
+#endif
+#ifdef EP93XX_PLATFORM_DRIVER
+ platform_driver_unregister(&EP93XX_PLATFORM_DRIVER);
+#endif
+#ifdef EXYNOS_PLATFORM_DRIVER
+ platform_driver_unregister(&EXYNOS_PLATFORM_DRIVER);
+#endif
+#ifdef S3C2410_PLATFORM_DRIVER
+ platform_driver_unregister(&S3C2410_PLATFORM_DRIVER);
+#endif
#ifdef TMIO_OHCI_DRIVER
platform_driver_unregister(&TMIO_OHCI_DRIVER);
#endif
@@ -1344,12 +1441,15 @@ static void __exit ohci_hcd_mod_exit(void)
#ifdef OF_PLATFORM_DRIVER
platform_driver_unregister(&OF_PLATFORM_DRIVER);
#endif
-#ifdef PLATFORM_DRIVER
- platform_driver_unregister(&PLATFORM_DRIVER);
-#endif
#ifdef OMAP3_PLATFORM_DRIVER
platform_driver_unregister(&OMAP3_PLATFORM_DRIVER);
#endif
+#ifdef OMAP1_PLATFORM_DRIVER
+ platform_driver_unregister(&OMAP1_PLATFORM_DRIVER);
+#endif
+#ifdef PLATFORM_DRIVER
+ platform_driver_unregister(&PLATFORM_DRIVER);
+#endif
#ifdef PS3_SYSTEM_BUS_DRIVER
ps3_ohci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);
#endif
diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
index db09dae7b55..60ff4220e8b 100644
--- a/drivers/usb/host/ohci-hub.c
+++ b/drivers/usb/host/ohci-hub.c
@@ -580,14 +580,8 @@ static int ohci_start_port_reset (struct usb_hcd *hcd, unsigned port)
/* See usb 7.1.7.5: root hubs must issue at least 50 msec reset signaling,
* not necessarily continuous ... to guard against resume signaling.
- * The short timeout is safe for non-root hubs, and is backward-compatible
- * with earlier Linux hosts.
*/
-#ifdef CONFIG_USB_SUSPEND
#define PORT_RESET_MSEC 50
-#else
-#define PORT_RESET_MSEC 10
-#endif
/* this timer value might be vendor-specific ... */
#define PORT_RESET_HW_MSEC 10
diff --git a/drivers/usb/host/ohci-omap3.c b/drivers/usb/host/ohci-omap3.c
index eb35d963023..ddfc31427bc 100644
--- a/drivers/usb/host/ohci-omap3.c
+++ b/drivers/usb/host/ohci-omap3.c
@@ -31,6 +31,8 @@
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
+#include <linux/of.h>
+#include <linux/dma-mapping.h>
/*-------------------------------------------------------------------------*/
@@ -112,6 +114,8 @@ static const struct hc_driver ohci_omap3_hc_driver = {
/*-------------------------------------------------------------------------*/
+static u64 omap_ohci_dma_mask = DMA_BIT_MASK(32);
+
/*
* configure so an HC device and id are always provided
* always called with process context; sleeping is OK
@@ -141,14 +145,13 @@ static int ohci_hcd_omap3_probe(struct platform_device *pdev)
return -ENODEV;
}
- irq = platform_get_irq_byname(pdev, "ohci-irq");
+ irq = platform_get_irq(pdev, 0);
if (irq < 0) {
dev_err(dev, "OHCI irq failed\n");
return -ENODEV;
}
- res = platform_get_resource_byname(pdev,
- IORESOURCE_MEM, "ohci");
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
dev_err(dev, "UHH OHCI get resource failed\n");
return -ENOMEM;
@@ -160,6 +163,13 @@ static int ohci_hcd_omap3_probe(struct platform_device *pdev)
return -ENOMEM;
}
+ /*
+ * 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 have dma capability bindings this can go away.
+ */
+ if (!pdev->dev.dma_mask)
+ pdev->dev.dma_mask = &omap_ohci_dma_mask;
hcd = usb_create_hcd(&ohci_omap3_hc_driver, dev,
dev_name(dev));
@@ -229,12 +239,20 @@ static void ohci_hcd_omap3_shutdown(struct platform_device *pdev)
hcd->driver->shutdown(hcd);
}
+static const struct of_device_id omap_ohci_dt_ids[] = {
+ { .compatible = "ti,ohci-omap3" },
+ { }
+};
+
+MODULE_DEVICE_TABLE(of, omap_ohci_dt_ids);
+
static struct platform_driver ohci_hcd_omap3_driver = {
.probe = ohci_hcd_omap3_probe,
.remove = ohci_hcd_omap3_remove,
.shutdown = ohci_hcd_omap3_shutdown,
.driver = {
.name = "ohci-omap3",
+ .of_match_table = of_match_ptr(omap_ohci_dt_ids),
},
};
diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c
index d62f0404baa..15ed7e8d887 100644
--- a/drivers/usb/host/sl811-hcd.c
+++ b/drivers/usb/host/sl811-hcd.c
@@ -1755,7 +1755,7 @@ sl811h_probe(struct platform_device *dev)
/* for this device there's no useful distinction between the controller
* and its root hub, except that the root hub only gets direct PM calls
- * when CONFIG_USB_SUSPEND is enabled.
+ * when CONFIG_PM_RUNTIME is enabled.
*/
static int
diff --git a/drivers/usb/host/sl811_cs.c b/drivers/usb/host/sl811_cs.c
index 3b6f50eaec9..469564e57a5 100644
--- a/drivers/usb/host/sl811_cs.c
+++ b/drivers/usb/host/sl811_cs.c
@@ -200,17 +200,4 @@ static struct pcmcia_driver sl811_cs_driver = {
.remove = sl811_cs_detach,
.id_table = sl811_ids,
};
-
-/*====================================================================*/
-
-static int __init init_sl811_cs(void)
-{
- return pcmcia_register_driver(&sl811_cs_driver);
-}
-module_init(init_sl811_cs);
-
-static void __exit exit_sl811_cs(void)
-{
- pcmcia_unregister_driver(&sl811_cs_driver);
-}
-module_exit(exit_sl811_cs);
+module_pcmcia_driver(sl811_cs_driver);
diff --git a/drivers/usb/host/u132-hcd.c b/drivers/usb/host/u132-hcd.c
index 5efdffe3236..5c124bf5d01 100644
--- a/drivers/usb/host/u132-hcd.c
+++ b/drivers/usb/host/u132-hcd.c
@@ -3141,10 +3141,11 @@ static int u132_probe(struct platform_device *pdev)
#ifdef CONFIG_PM
-/* for this device there's no useful distinction between the controller
-* and its root hub, except that the root hub only gets direct PM calls
-* when CONFIG_USB_SUSPEND is enabled.
-*/
+/*
+ * for this device there's no useful distinction between the controller
+ * and its root hub, except that the root hub only gets direct PM calls
+ * when CONFIG_PM_RUNTIME is enabled.
+ */
static int u132_suspend(struct platform_device *pdev, pm_message_t state)
{
struct usb_hcd *hcd = platform_get_drvdata(pdev);
diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
index 68914429482..187a3ec1069 100644
--- a/drivers/usb/host/xhci-hub.c
+++ b/drivers/usb/host/xhci-hub.c
@@ -1075,7 +1075,7 @@ int xhci_bus_suspend(struct usb_hcd *hcd)
set_bit(port_index, &bus_state->bus_suspended);
}
/* USB core sets remote wake mask for USB 3.0 hubs,
- * including the USB 3.0 roothub, but only if CONFIG_USB_SUSPEND
+ * including the USB 3.0 roothub, but only if CONFIG_PM_RUNTIME
* is enabled, so also enable remote wake here.
*/
if (hcd->self.root_hub->do_remote_wakeup) {
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index 35616ffbe3a..965b539bc47 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -51,7 +51,7 @@ static struct xhci_segment *xhci_segment_alloc(struct xhci_hcd *xhci,
return NULL;
}
- memset(seg->trbs, 0, SEGMENT_SIZE);
+ memset(seg->trbs, 0, TRB_SEGMENT_SIZE);
/* If the cycle state is 0, set the cycle bit to 1 for all the TRBs */
if (cycle_state == 0) {
for (i = 0; i < TRBS_PER_SEGMENT; i++)
@@ -467,7 +467,7 @@ struct xhci_ring *xhci_dma_to_transfer_ring(
{
if (ep->ep_state & EP_HAS_STREAMS)
return radix_tree_lookup(&ep->stream_info->trb_address_map,
- address >> SEGMENT_SHIFT);
+ address >> TRB_SEGMENT_SHIFT);
return ep->ring;
}
@@ -478,7 +478,7 @@ static struct xhci_ring *dma_to_stream_ring(
u64 address)
{
return radix_tree_lookup(&stream_info->trb_address_map,
- address >> SEGMENT_SHIFT);
+ address >> TRB_SEGMENT_SHIFT);
}
#endif /* CONFIG_USB_XHCI_HCD_DEBUGGING */
@@ -514,7 +514,7 @@ static int xhci_test_radix_tree(struct xhci_hcd *xhci,
cur_ring = stream_info->stream_rings[cur_stream];
for (addr = cur_ring->first_seg->dma;
- addr < cur_ring->first_seg->dma + SEGMENT_SIZE;
+ addr < cur_ring->first_seg->dma + TRB_SEGMENT_SIZE;
addr += trb_size) {
mapped_ring = dma_to_stream_ring(stream_info, addr);
if (cur_ring != mapped_ring) {
@@ -662,7 +662,7 @@ struct xhci_stream_info *xhci_alloc_stream_info(struct xhci_hcd *xhci,
cur_stream, (unsigned long long) addr);
key = (unsigned long)
- (cur_ring->first_seg->dma >> SEGMENT_SHIFT);
+ (cur_ring->first_seg->dma >> TRB_SEGMENT_SHIFT);
ret = radix_tree_insert(&stream_info->trb_address_map,
key, cur_ring);
if (ret) {
@@ -693,7 +693,7 @@ cleanup_rings:
if (cur_ring) {
addr = cur_ring->first_seg->dma;
radix_tree_delete(&stream_info->trb_address_map,
- addr >> SEGMENT_SHIFT);
+ addr >> TRB_SEGMENT_SHIFT);
xhci_ring_free(xhci, cur_ring);
stream_info->stream_rings[cur_stream] = NULL;
}
@@ -764,7 +764,7 @@ void xhci_free_stream_info(struct xhci_hcd *xhci,
if (cur_ring) {
addr = cur_ring->first_seg->dma;
radix_tree_delete(&stream_info->trb_address_map,
- addr >> SEGMENT_SHIFT);
+ addr >> TRB_SEGMENT_SHIFT);
xhci_ring_free(xhci, cur_ring);
stream_info->stream_rings[cur_stream] = NULL;
}
@@ -1022,44 +1022,24 @@ void xhci_copy_ep0_dequeue_into_input_ctx(struct xhci_hcd *xhci,
* is attached to (or the roothub port its ancestor hub is attached to). All we
* know is the index of that port under either the USB 2.0 or the USB 3.0
* roothub, but that doesn't give us the real index into the HW port status
- * registers. Scan through the xHCI roothub port array, looking for the Nth
- * entry of the correct port speed. Return the port number of that entry.
+ * registers. Call xhci_find_raw_port_number() to get real index.
*/
static u32 xhci_find_real_port_number(struct xhci_hcd *xhci,
struct usb_device *udev)
{
struct usb_device *top_dev;
- unsigned int num_similar_speed_ports;
- unsigned int faked_port_num;
- int i;
+ struct usb_hcd *hcd;
+
+ if (udev->speed == USB_SPEED_SUPER)
+ hcd = xhci->shared_hcd;
+ else
+ hcd = xhci->main_hcd;
for (top_dev = udev; top_dev->parent && top_dev->parent->parent;
top_dev = top_dev->parent)
/* Found device below root hub */;
- faked_port_num = top_dev->portnum;
- for (i = 0, num_similar_speed_ports = 0;
- i < HCS_MAX_PORTS(xhci->hcs_params1); i++) {
- u8 port_speed = xhci->port_array[i];
-
- /*
- * Skip ports that don't have known speeds, or have duplicate
- * Extended Capabilities port speed entries.
- */
- if (port_speed == 0 || port_speed == DUPLICATE_ENTRY)
- continue;
- /*
- * USB 3.0 ports are always under a USB 3.0 hub. USB 2.0 and
- * 1.1 ports are under the USB 2.0 hub. If the port speed
- * matches the device speed, it's a similar speed port.
- */
- if ((port_speed == 0x03) == (udev->speed == USB_SPEED_SUPER))
- num_similar_speed_ports++;
- if (num_similar_speed_ports == faked_port_num)
- /* Roothub ports are numbered from 1 to N */
- return i+1;
- }
- return 0;
+ return xhci_find_raw_port_number(hcd, top_dev->portnum);
}
/* Setup an xHCI virtual device for a Set Address command */
@@ -2325,7 +2305,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
* so we pick the greater alignment need.
*/
xhci->segment_pool = dma_pool_create("xHCI ring segments", dev,
- SEGMENT_SIZE, 64, xhci->page_size);
+ TRB_SEGMENT_SIZE, 64, xhci->page_size);
/* See Table 46 and Note on Figure 55 */
xhci->device_pool = dma_pool_create("xHCI input/output contexts", dev,
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index af259e0ec17..1a30c380043 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -313,6 +313,7 @@ static const struct hc_driver xhci_pci_hc_driver = {
.set_usb2_hw_lpm = xhci_set_usb2_hardware_lpm,
.enable_usb3_lpm_timeout = xhci_enable_usb3_lpm_timeout,
.disable_usb3_lpm_timeout = xhci_disable_usb3_lpm_timeout,
+ .find_raw_port_number = xhci_find_raw_port_number,
};
/*-------------------------------------------------------------------------*/
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 88287546530..1969c001b3f 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -1599,14 +1599,20 @@ static void handle_port_status(struct xhci_hcd *xhci,
max_ports = HCS_MAX_PORTS(xhci->hcs_params1);
if ((port_id <= 0) || (port_id > max_ports)) {
xhci_warn(xhci, "Invalid port id %d\n", port_id);
- bogus_port_status = true;
- goto cleanup;
+ inc_deq(xhci, xhci->event_ring);
+ return;
}
/* Figure out which usb_hcd this port is attached to:
* is it a USB 3.0 port or a USB 2.0/1.1 port?
*/
major_revision = xhci->port_array[port_id - 1];
+
+ /* Find the right roothub. */
+ hcd = xhci_to_hcd(xhci);
+ if ((major_revision == 0x03) != (hcd->speed == HCD_USB3))
+ hcd = xhci->shared_hcd;
+
if (major_revision == 0) {
xhci_warn(xhci, "Event for port %u not in "
"Extended Capabilities, ignoring.\n",
@@ -1629,10 +1635,6 @@ static void handle_port_status(struct xhci_hcd *xhci,
* into the index into the ports on the correct split roothub, and the
* correct bus_state structure.
*/
- /* Find the right roothub. */
- hcd = xhci_to_hcd(xhci);
- if ((major_revision == 0x03) != (hcd->speed == HCD_USB3))
- hcd = xhci->shared_hcd;
bus_state = &xhci->bus_state[hcd_index(hcd)];
if (hcd->speed == HCD_USB3)
port_array = xhci->usb3_ports;
@@ -2027,8 +2029,8 @@ static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_td *td,
if (event_trb != ep_ring->dequeue &&
event_trb != td->last_trb)
td->urb->actual_length =
- td->urb->transfer_buffer_length
- - TRB_LEN(le32_to_cpu(event->transfer_len));
+ td->urb->transfer_buffer_length -
+ EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));
else
td->urb->actual_length = 0;
@@ -2060,7 +2062,7 @@ static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_td *td,
/* Maybe the event was for the data stage? */
td->urb->actual_length =
td->urb->transfer_buffer_length -
- TRB_LEN(le32_to_cpu(event->transfer_len));
+ EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));
xhci_dbg(xhci, "Waiting for status "
"stage event\n");
return 0;
@@ -2096,7 +2098,7 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td,
/* handle completion code */
switch (trb_comp_code) {
case COMP_SUCCESS:
- if (TRB_LEN(le32_to_cpu(event->transfer_len)) == 0) {
+ if (EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)) == 0) {
frame->status = 0;
break;
}
@@ -2141,7 +2143,7 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td,
len += TRB_LEN(le32_to_cpu(cur_trb->generic.field[2]));
}
len += TRB_LEN(le32_to_cpu(cur_trb->generic.field[2])) -
- TRB_LEN(le32_to_cpu(event->transfer_len));
+ EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));
if (trb_comp_code != COMP_STOP_INVAL) {
frame->actual_length = len;
@@ -2199,7 +2201,7 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td,
case COMP_SUCCESS:
/* Double check that the HW transferred everything. */
if (event_trb != td->last_trb ||
- TRB_LEN(le32_to_cpu(event->transfer_len)) != 0) {
+ EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)) != 0) {
xhci_warn(xhci, "WARN Successful completion "
"on short TX\n");
if (td->urb->transfer_flags & URB_SHORT_NOT_OK)
@@ -2227,18 +2229,18 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td,
"%d bytes untransferred\n",
td->urb->ep->desc.bEndpointAddress,
td->urb->transfer_buffer_length,
- TRB_LEN(le32_to_cpu(event->transfer_len)));
+ EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)));
/* Fast path - was this the last TRB in the TD for this URB? */
if (event_trb == td->last_trb) {
- if (TRB_LEN(le32_to_cpu(event->transfer_len)) != 0) {
+ if (EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)) != 0) {
td->urb->actual_length =
td->urb->transfer_buffer_length -
- TRB_LEN(le32_to_cpu(event->transfer_len));
+ EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));
if (td->urb->transfer_buffer_length <
td->urb->actual_length) {
xhci_warn(xhci, "HC gave bad length "
"of %d bytes left\n",
- TRB_LEN(le32_to_cpu(event->transfer_len)));
+ EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)));
td->urb->actual_length = 0;
if (td->urb->transfer_flags & URB_SHORT_NOT_OK)
*status = -EREMOTEIO;
@@ -2280,7 +2282,7 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td,
if (trb_comp_code != COMP_STOP_INVAL)
td->urb->actual_length +=
TRB_LEN(le32_to_cpu(cur_trb->generic.field[2])) -
- TRB_LEN(le32_to_cpu(event->transfer_len));
+ EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));
}
return finish_td(xhci, td, event_trb, event, ep, status, false);
@@ -2368,7 +2370,7 @@ static int handle_tx_event(struct xhci_hcd *xhci,
* transfer type
*/
case COMP_SUCCESS:
- if (TRB_LEN(le32_to_cpu(event->transfer_len)) == 0)
+ if (EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)) == 0)
break;
if (xhci->quirks & XHCI_TRUST_TX_LENGTH)
trb_comp_code = COMP_SHORT_TX;
@@ -2461,14 +2463,21 @@ static int handle_tx_event(struct xhci_hcd *xhci,
* TD list.
*/
if (list_empty(&ep_ring->td_list)) {
- xhci_warn(xhci, "WARN Event TRB for slot %d ep %d "
- "with no TDs queued?\n",
- TRB_TO_SLOT_ID(le32_to_cpu(event->flags)),
- ep_index);
- xhci_dbg(xhci, "Event TRB with TRB type ID %u\n",
- (le32_to_cpu(event->flags) &
- TRB_TYPE_BITMASK)>>10);
- xhci_print_trb_offsets(xhci, (union xhci_trb *) event);
+ /*
+ * A stopped endpoint may generate an extra completion
+ * event if the device was suspended. Don't print
+ * warnings.
+ */
+ if (!(trb_comp_code == COMP_STOP ||
+ trb_comp_code == COMP_STOP_INVAL)) {
+ xhci_warn(xhci, "WARN Event TRB for slot %d ep %d with no TDs queued?\n",
+ TRB_TO_SLOT_ID(le32_to_cpu(event->flags)),
+ ep_index);
+ xhci_dbg(xhci, "Event TRB with TRB type ID %u\n",
+ (le32_to_cpu(event->flags) &
+ TRB_TYPE_BITMASK)>>10);
+ xhci_print_trb_offsets(xhci, (union xhci_trb *) event);
+ }
if (ep->skip) {
ep->skip = false;
xhci_dbg(xhci, "td_list is empty while skip "
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index f1f01a834ba..b4aa79d154b 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -350,7 +350,7 @@ static int xhci_try_enable_msi(struct usb_hcd *hcd)
* generate interrupts. Don't even try to enable MSI.
*/
if (xhci->quirks & XHCI_BROKEN_MSI)
- return 0;
+ goto legacy_irq;
/* unregister the legacy interrupt */
if (hcd->irq)
@@ -371,6 +371,7 @@ static int xhci_try_enable_msi(struct usb_hcd *hcd)
return -EINVAL;
}
+ legacy_irq:
/* fall back to legacy interrupt*/
ret = request_irq(pdev->irq, &usb_hcd_irq, IRQF_SHARED,
hcd->irq_descr, hcd);
@@ -416,9 +417,9 @@ static void compliance_mode_recovery(unsigned long arg)
* Compliance Mode Detected. Letting USB Core
* handle the Warm Reset
*/
- xhci_dbg(xhci, "Compliance Mode Detected->Port %d!\n",
+ xhci_dbg(xhci, "Compliance mode detected->port %d\n",
i + 1);
- xhci_dbg(xhci, "Attempting Recovery routine!\n");
+ xhci_dbg(xhci, "Attempting compliance mode recovery\n");
hcd = xhci->shared_hcd;
if (hcd->state == HC_STATE_SUSPENDED)
@@ -456,7 +457,7 @@ static void compliance_mode_recovery_timer_init(struct xhci_hcd *xhci)
set_timer_slack(&xhci->comp_mode_recovery_timer,
msecs_to_jiffies(COMP_MODE_RCVRY_MSECS));
add_timer(&xhci->comp_mode_recovery_timer);
- xhci_dbg(xhci, "Compliance Mode Recovery Timer Initialized.\n");
+ xhci_dbg(xhci, "Compliance mode recovery timer initialized\n");
}
/*
@@ -732,8 +733,11 @@ void xhci_stop(struct usb_hcd *hcd)
/* Deleting Compliance Mode Recovery Timer */
if ((xhci->quirks & XHCI_COMP_MODE_QUIRK) &&
- (!(xhci_all_ports_seen_u0(xhci))))
+ (!(xhci_all_ports_seen_u0(xhci)))) {
del_timer_sync(&xhci->comp_mode_recovery_timer);
+ xhci_dbg(xhci, "%s: compliance mode recovery timer deleted\n",
+ __func__);
+ }
if (xhci->quirks & XHCI_AMD_PLL_FIX)
usb_amd_dev_put();
@@ -929,7 +933,8 @@ int xhci_suspend(struct xhci_hcd *xhci)
if ((xhci->quirks & XHCI_COMP_MODE_QUIRK) &&
(!(xhci_all_ports_seen_u0(xhci)))) {
del_timer_sync(&xhci->comp_mode_recovery_timer);
- xhci_dbg(xhci, "Compliance Mode Recovery Timer Deleted!\n");
+ xhci_dbg(xhci, "%s: compliance mode recovery timer deleted\n",
+ __func__);
}
/* step 5: remove core well power */
@@ -3778,7 +3783,29 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev)
return 0;
}
-#ifdef CONFIG_USB_SUSPEND
+/*
+ * Transfer the port index into real index in the HW port status
+ * registers. Caculate offset between the port's PORTSC register
+ * and port status base. Divide the number of per port register
+ * to get the real index. The raw port number bases 1.
+ */
+int xhci_find_raw_port_number(struct usb_hcd *hcd, int port1)
+{
+ struct xhci_hcd *xhci = hcd_to_xhci(hcd);
+ __le32 __iomem *base_addr = &xhci->op_regs->port_status_base;
+ __le32 __iomem *addr;
+ int raw_port;
+
+ if (hcd->speed != HCD_USB3)
+ addr = xhci->usb2_ports[port1 - 1];
+ else
+ addr = xhci->usb3_ports[port1 - 1];
+
+ raw_port = (addr - base_addr)/NUM_PORT_REGS + 1;
+ return raw_port;
+}
+
+#ifdef CONFIG_PM_RUNTIME
/* BESL to HIRD Encoding array for USB2 LPM */
static int xhci_besl_encoding[16] = {125, 150, 200, 300, 400, 500, 1000, 2000,
@@ -4028,7 +4055,7 @@ int xhci_update_device(struct usb_hcd *hcd, struct usb_device *udev)
return 0;
}
-#endif /* CONFIG_USB_SUSPEND */
+#endif /* CONFIG_PM_RUNTIME */
/*---------------------- USB 3.0 Link PM functions ------------------------*/
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index f791bd0aee6..29c978e3713 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -206,8 +206,8 @@ struct xhci_op_regs {
/* bits 12:31 are reserved (and should be preserved on writes). */
/* IMAN - Interrupt Management Register */
-#define IMAN_IP (1 << 1)
-#define IMAN_IE (1 << 0)
+#define IMAN_IE (1 << 1)
+#define IMAN_IP (1 << 0)
/* USBSTS - USB status - status bitmasks */
/* HC not running - set to 1 when run/stop bit is cleared. */
@@ -972,6 +972,10 @@ struct xhci_transfer_event {
__le32 flags;
};
+/* Transfer event TRB length bit mask */
+/* bits 0:23 */
+#define EVENT_TRB_LEN(p) ((p) & 0xffffff)
+
/** Transfer Event bit fields **/
#define TRB_TO_EP_ID(p) (((p) >> 16) & 0x1f)
@@ -1234,8 +1238,8 @@ union xhci_trb {
#define TRBS_PER_SEGMENT 64
/* Allow two commands + a link TRB, along with any reserved command TRBs */
#define MAX_RSVD_CMD_TRBS (TRBS_PER_SEGMENT - 3)
-#define SEGMENT_SIZE (TRBS_PER_SEGMENT*16)
-#define SEGMENT_SHIFT (__ffs(SEGMENT_SIZE))
+#define TRB_SEGMENT_SIZE (TRBS_PER_SEGMENT*16)
+#define TRB_SEGMENT_SHIFT (ilog2(TRB_SEGMENT_SIZE))
/* TRB buffer pointers can't cross 64KB boundaries */
#define TRB_MAX_BUFF_SHIFT 16
#define TRB_MAX_BUFF_SIZE (1 << TRB_MAX_BUFF_SHIFT)
@@ -1829,6 +1833,7 @@ void xhci_test_and_clear_bit(struct xhci_hcd *xhci, __le32 __iomem **port_array,
int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex,
char *buf, u16 wLength);
int xhci_hub_status_data(struct usb_hcd *hcd, char *buf);
+int xhci_find_raw_port_number(struct usb_hcd *hcd, int port1);
#ifdef CONFIG_PM
int xhci_bus_suspend(struct usb_hcd *hcd);
diff --git a/drivers/usb/image/Kconfig b/drivers/usb/image/Kconfig
index 33350f9dd34..320d368c8da 100644
--- a/drivers/usb/image/Kconfig
+++ b/drivers/usb/image/Kconfig
@@ -2,11 +2,9 @@
# USB Imaging devices configuration
#
comment "USB Imaging devices"
- depends on USB
config USB_MDC800
tristate "USB Mustek MDC800 Digital Camera support"
- depends on USB
---help---
Say Y here if you want to connect this type of still camera to
your computer's USB port. This driver can be used with gphoto 0.4.3
@@ -19,7 +17,7 @@ config USB_MDC800
config USB_MICROTEK
tristate "Microtek X6USB scanner support"
- depends on USB && SCSI
+ depends on SCSI
help
Say Y here if you want support for the Microtek X6USB and
possibly the Phantom 336CX, Phantom C6 and ScanMaker V6U(S)L.
diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig
index 3b1a3f4ec5e..a51e7d6afda 100644
--- a/drivers/usb/misc/Kconfig
+++ b/drivers/usb/misc/Kconfig
@@ -2,11 +2,9 @@
# USB Miscellaneous driver configuration
#
comment "USB Miscellaneous drivers"
- depends on USB
config USB_EMI62
tristate "EMI 6|2m USB Audio interface support"
- depends on USB
---help---
This driver loads firmware to Emagic EMI 6|2m low latency USB
Audio and Midi interface.
@@ -21,7 +19,6 @@ config USB_EMI62
config USB_EMI26
tristate "EMI 2|6 USB Audio interface support"
- depends on USB
---help---
This driver loads firmware to Emagic EMI 2|6 low latency USB
Audio interface.
@@ -34,7 +31,6 @@ config USB_EMI26
config USB_ADUTUX
tristate "ADU devices from Ontrak Control Systems"
- depends on USB
help
Say Y if you want to use an ADU device from Ontrak Control
Systems.
@@ -44,7 +40,6 @@ config USB_ADUTUX
config USB_SEVSEG
tristate "USB 7-Segment LED Display"
- depends on USB
help
Say Y here if you have a USB 7-Segment Display by Delcom
@@ -53,7 +48,6 @@ config USB_SEVSEG
config USB_RIO500
tristate "USB Diamond Rio500 support"
- depends on USB
help
Say Y here if you want to connect a USB Rio500 mp3 player to your
computer's USB port. Please read <file:Documentation/usb/rio.txt>
@@ -64,7 +58,6 @@ config USB_RIO500
config USB_LEGOTOWER
tristate "USB Lego Infrared Tower support"
- depends on USB
help
Say Y here if you want to connect a USB Lego Infrared Tower to your
computer's USB port.
@@ -77,7 +70,6 @@ config USB_LEGOTOWER
config USB_LCD
tristate "USB LCD driver support"
- depends on USB
help
Say Y here if you want to connect an USBLCD to your computer's
USB port. The USBLCD is a small USB interface board for
@@ -89,7 +81,6 @@ config USB_LCD
config USB_LED
tristate "USB LED driver support"
- depends on USB
help
Say Y here if you want to connect an USBLED device to your
computer's USB port.
@@ -99,7 +90,6 @@ config USB_LED
config USB_CYPRESS_CY7C63
tristate "Cypress CY7C63xxx USB driver support"
- depends on USB
help
Say Y here if you want to connect a Cypress CY7C63xxx
micro controller to your computer's USB port. Currently this
@@ -113,7 +103,6 @@ config USB_CYPRESS_CY7C63
config USB_CYTHERM
tristate "Cypress USB thermometer driver support"
- depends on USB
help
Say Y here if you want to connect a Cypress USB thermometer
device to your computer's USB port. This device is also known
@@ -126,7 +115,6 @@ config USB_CYTHERM
config USB_IDMOUSE
tristate "Siemens ID USB Mouse Fingerprint sensor support"
- depends on USB
help
Say Y here if you want to use the fingerprint sensor on
the Siemens ID Mouse. There is also a Siemens ID Mouse
@@ -140,7 +128,6 @@ config USB_IDMOUSE
config USB_FTDI_ELAN
tristate "Elan PCMCIA CardBus Adapter USB Client"
- depends on USB
default M
help
ELAN's Uxxx series of adapters are USB to PCMCIA CardBus adapters.
@@ -164,7 +151,6 @@ config USB_FTDI_ELAN
config USB_APPLEDISPLAY
tristate "Apple Cinema Display support"
- depends on USB
select BACKLIGHT_LCD_SUPPORT
select BACKLIGHT_CLASS_DEVICE
help
@@ -175,7 +161,6 @@ source "drivers/usb/misc/sisusbvga/Kconfig"
config USB_LD
tristate "USB LD driver"
- depends on USB
help
This driver is for generic USB devices that use interrupt transfers,
like LD Didactic's USB devices.
@@ -185,7 +170,6 @@ config USB_LD
config USB_TRANCEVIBRATOR
tristate "PlayStation 2 Trance Vibrator driver support"
- depends on USB
help
Say Y here if you want to connect a PlayStation 2 Trance Vibrator
device to your computer's USB port.
@@ -195,7 +179,6 @@ config USB_TRANCEVIBRATOR
config USB_IOWARRIOR
tristate "IO Warrior driver support"
- depends on USB
help
Say Y here if you want to support the IO Warrior devices from Code
Mercenaries. This includes support for the following devices:
@@ -209,7 +192,6 @@ config USB_IOWARRIOR
config USB_TEST
tristate "USB testing driver"
- depends on USB
help
This driver is for testing host controller software. It is used
with specialized device firmware for regression and stress testing,
@@ -220,7 +202,6 @@ config USB_TEST
config USB_ISIGHTFW
tristate "iSight firmware loading support"
- depends on USB
select FW_LOADER
help
This driver loads firmware for USB Apple iSight cameras, allowing
@@ -233,7 +214,6 @@ config USB_ISIGHTFW
config USB_YUREX
tristate "USB YUREX driver support"
- depends on USB
help
Say Y here if you want to connect a YUREX to your computer's
USB port. The YUREX is a leg-shakes sensor. See
@@ -246,7 +226,6 @@ config USB_YUREX
config USB_EZUSB_FX2
tristate "Functions for loading firmware on EZUSB chips"
- depends on USB
help
Say Y here if you need EZUSB device support.
(Cypress FX/FX2/FX2LP microcontrollers)
diff --git a/drivers/usb/misc/appledisplay.c b/drivers/usb/misc/appledisplay.c
index 0fc6e5fc745..ba6a5d6e618 100644
--- a/drivers/usb/misc/appledisplay.c
+++ b/drivers/usb/misc/appledisplay.c
@@ -63,6 +63,7 @@ static const struct usb_device_id appledisplay_table[] = {
{ APPLEDISPLAY_DEVICE(0x9219) },
{ APPLEDISPLAY_DEVICE(0x921c) },
{ APPLEDISPLAY_DEVICE(0x921d) },
+ { APPLEDISPLAY_DEVICE(0x9236) },
/* Terminating entry */
{ }
diff --git a/drivers/usb/misc/sisusbvga/Kconfig b/drivers/usb/misc/sisusbvga/Kconfig
index 30ea7ca6846..0d03a520048 100644
--- a/drivers/usb/misc/sisusbvga/Kconfig
+++ b/drivers/usb/misc/sisusbvga/Kconfig
@@ -1,7 +1,7 @@
config USB_SISUSBVGA
tristate "USB 2.0 SVGA dongle support (Net2280/SiS315)"
- depends on USB && (USB_MUSB_HDRC || USB_EHCI_HCD)
+ depends on (USB_MUSB_HDRC || USB_EHCI_HCD)
---help---
Say Y here if you intend to attach a USB2VGA dongle based on a
Net2280 and a SiS315 chip.
diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c
index dd573abd2d1..c21386ec5d3 100644
--- a/drivers/usb/misc/sisusbvga/sisusb.c
+++ b/drivers/usb/misc/sisusbvga/sisusb.c
@@ -3084,7 +3084,7 @@ static int sisusb_probe(struct usb_interface *intf,
/* Allocate memory for our private */
if (!(sisusb = kzalloc(sizeof(*sisusb), GFP_KERNEL))) {
- dev_err(&sisusb->sisusb_dev->dev, "Failed to allocate memory for private data\n");
+ dev_err(&dev->dev, "Failed to allocate memory for private data\n");
return -ENOMEM;
}
kref_init(&sisusb->kref);
diff --git a/drivers/usb/misc/usb3503.c b/drivers/usb/misc/usb3503.c
index f713f6aeb6e..d3a1cce1bf9 100644
--- a/drivers/usb/misc/usb3503.c
+++ b/drivers/usb/misc/usb3503.c
@@ -307,18 +307,7 @@ static struct i2c_driver usb3503_driver = {
.id_table = usb3503_id,
};
-static int __init usb3503_init(void)
-{
- return i2c_add_driver(&usb3503_driver);
-}
-
-static void __exit usb3503_exit(void)
-{
- i2c_del_driver(&usb3503_driver);
-}
-
-module_init(usb3503_init);
-module_exit(usb3503_exit);
+module_i2c_driver(usb3503_driver);
MODULE_AUTHOR("Dongjin Kim <tobetter@gmail.com>");
MODULE_DESCRIPTION("USB3503 USB HUB driver");
diff --git a/drivers/usb/mon/Kconfig b/drivers/usb/mon/Kconfig
index 635745f57fb..5c6ffa2a612 100644
--- a/drivers/usb/mon/Kconfig
+++ b/drivers/usb/mon/Kconfig
@@ -4,7 +4,6 @@
config USB_MON
tristate "USB Monitor"
- depends on USB
help
If you select this option, a component which captures the USB traffic
between peripheral-specific drivers and HC drivers will be built.
diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig
index 45b19e2c60b..06f8d29af1e 100644
--- a/drivers/usb/musb/Kconfig
+++ b/drivers/usb/musb/Kconfig
@@ -6,13 +6,7 @@
# (M)HDRC = (Multipoint) Highspeed Dual-Role Controller
config USB_MUSB_HDRC
tristate 'Inventra Highspeed Dual Role Controller (TI, ADI, ...)'
- depends on USB && USB_GADGET
- select NOP_USB_XCEIV if (ARCH_DAVINCI || MACH_OMAP3EVM || BLACKFIN)
- select NOP_USB_XCEIV if (SOC_TI81XX || SOC_AM33XX)
- select TWL4030_USB if MACH_OMAP_3430SDP
- select TWL6030_USB if MACH_OMAP_4430SDP || MACH_OMAP4_PANDA
- select OMAP_CONTROL_USB if MACH_OMAP_4430SDP || MACH_OMAP4_PANDA
- select USB_OTG_UTILS
+ depends on USB_GADGET
help
Say Y here if your system has a dual role high speed USB
controller based on the Mentor Graphics silicon IP. Then
@@ -39,10 +33,12 @@ choice
config USB_MUSB_DAVINCI
tristate "DaVinci"
depends on ARCH_DAVINCI_DMx
+ depends on BROKEN
config USB_MUSB_DA8XX
tristate "DA8xx/OMAP-L1x"
depends on ARCH_DAVINCI_DA8XX
+ depends on BROKEN
config USB_MUSB_TUSB6010
tristate "TUSB6010"
@@ -58,7 +54,6 @@ config USB_MUSB_AM35X
config USB_MUSB_DSPS
tristate "TI DSPS platforms"
- depends on SOC_TI81XX || SOC_AM33XX
config USB_MUSB_BLACKFIN
tristate "Blackfin"
@@ -66,12 +61,12 @@ config USB_MUSB_BLACKFIN
config USB_MUSB_UX500
tristate "U8500 and U5500"
- depends on (ARCH_U8500 && AB8500_USB)
endchoice
choice
prompt 'MUSB DMA mode'
+ default MUSB_PIO_ONLY if ARCH_MULTIPLATFORM
default USB_UX500_DMA if USB_MUSB_UX500
default USB_INVENTRA_DMA if USB_MUSB_OMAP2PLUS || USB_MUSB_BLACKFIN
default USB_TI_CPPI_DMA if USB_MUSB_DAVINCI
diff --git a/drivers/usb/musb/am35x.c b/drivers/usb/musb/am35x.c
index 59eea219034..2231850c062 100644
--- a/drivers/usb/musb/am35x.c
+++ b/drivers/usb/musb/am35x.c
@@ -149,7 +149,7 @@ static void otg_timer(unsigned long _musb)
*/
devctl = musb_readb(mregs, MUSB_DEVCTL);
dev_dbg(musb->controller, "Poll devctl %02x (%s)\n", devctl,
- otg_state_string(musb->xceiv->state));
+ usb_otg_state_string(musb->xceiv->state));
spin_lock_irqsave(&musb->lock, flags);
switch (musb->xceiv->state) {
@@ -195,7 +195,7 @@ static void am35x_musb_try_idle(struct musb *musb, unsigned long timeout)
if (musb->is_active || (musb->a_wait_bcon == 0 &&
musb->xceiv->state == OTG_STATE_A_WAIT_BCON)) {
dev_dbg(musb->controller, "%s active, deleting timer\n",
- otg_state_string(musb->xceiv->state));
+ usb_otg_state_string(musb->xceiv->state));
del_timer(&otg_workaround);
last_timer = jiffies;
return;
@@ -208,7 +208,7 @@ static void am35x_musb_try_idle(struct musb *musb, unsigned long timeout)
last_timer = timeout;
dev_dbg(musb->controller, "%s inactive, starting idle timer for %u ms\n",
- otg_state_string(musb->xceiv->state),
+ usb_otg_state_string(musb->xceiv->state),
jiffies_to_msecs(timeout - jiffies));
mod_timer(&otg_workaround, timeout);
}
@@ -298,7 +298,7 @@ static irqreturn_t am35x_musb_interrupt(int irq, void *hci)
/* NOTE: this must complete power-on within 100 ms. */
dev_dbg(musb->controller, "VBUS %s (%s)%s, devctl %02x\n",
drvvbus ? "on" : "off",
- otg_state_string(musb->xceiv->state),
+ usb_otg_state_string(musb->xceiv->state),
err ? " ERROR" : "",
devctl);
ret = IRQ_HANDLED;
diff --git a/drivers/usb/musb/blackfin.c b/drivers/usb/musb/blackfin.c
index dbb31b30c7f..5e63b160db0 100644
--- a/drivers/usb/musb/blackfin.c
+++ b/drivers/usb/musb/blackfin.c
@@ -280,13 +280,13 @@ static void musb_conn_timer_handler(unsigned long _musb)
break;
default:
dev_dbg(musb->controller, "%s state not handled\n",
- otg_state_string(musb->xceiv->state));
+ usb_otg_state_string(musb->xceiv->state));
break;
}
spin_unlock_irqrestore(&musb->lock, flags);
dev_dbg(musb->controller, "state is %s\n",
- otg_state_string(musb->xceiv->state));
+ usb_otg_state_string(musb->xceiv->state));
}
static void bfin_musb_enable(struct musb *musb)
@@ -307,7 +307,7 @@ static void bfin_musb_set_vbus(struct musb *musb, int is_on)
dev_dbg(musb->controller, "VBUS %s, devctl %02x "
/* otg %3x conf %08x prcm %08x */ "\n",
- otg_state_string(musb->xceiv->state),
+ usb_otg_state_string(musb->xceiv->state),
musb_readb(musb->mregs, MUSB_DEVCTL));
}
diff --git a/drivers/usb/musb/cppi_dma.c b/drivers/usb/musb/cppi_dma.c
index f522000e8f0..9db211ee15b 100644
--- a/drivers/usb/musb/cppi_dma.c
+++ b/drivers/usb/musb/cppi_dma.c
@@ -435,7 +435,6 @@ cppi_rndis_update(struct cppi_channel *c, int is_rx,
}
}
-#ifdef CONFIG_USB_MUSB_DEBUG
static void cppi_dump_rxbd(const char *tag, struct cppi_descriptor *bd)
{
pr_debug("RXBD/%s %08x: "
@@ -444,21 +443,16 @@ static void cppi_dump_rxbd(const char *tag, struct cppi_descriptor *bd)
bd->hw_next, bd->hw_bufp, bd->hw_off_len,
bd->hw_options);
}
-#endif
static void cppi_dump_rxq(int level, const char *tag, struct cppi_channel *rx)
{
-#ifdef CONFIG_USB_MUSB_DEBUG
struct cppi_descriptor *bd;
- if (!_dbg_level(level))
- return;
cppi_dump_rx(level, rx, tag);
if (rx->last_processed)
cppi_dump_rxbd("last", rx->last_processed);
for (bd = rx->head; bd; bd = bd->next)
cppi_dump_rxbd("active", bd);
-#endif
}
@@ -784,6 +778,7 @@ cppi_next_rx_segment(struct musb *musb, struct cppi_channel *rx, int onepacket)
void __iomem *tibase = musb->ctrl_base;
int is_rndis = 0;
struct cppi_rx_stateram __iomem *rx_ram = rx->state_ram;
+ struct cppi_descriptor *d;
if (onepacket) {
/* almost every USB driver, host or peripheral side */
@@ -897,14 +892,8 @@ cppi_next_rx_segment(struct musb *musb, struct cppi_channel *rx, int onepacket)
bd->hw_options |= CPPI_SOP_SET;
tail->hw_options |= CPPI_EOP_SET;
-#ifdef CONFIG_USB_MUSB_DEBUG
- if (_dbg_level(5)) {
- struct cppi_descriptor *d;
-
- for (d = rx->head; d; d = d->next)
- cppi_dump_rxbd("S", d);
- }
-#endif
+ for (d = rx->head; d; d = d->next)
+ cppi_dump_rxbd("S", d);
/* in case the preceding transfer left some state... */
tail = rx->last_processed;
diff --git a/drivers/usb/musb/da8xx.c b/drivers/usb/musb/da8xx.c
index 7c71769d71f..b903b744a22 100644
--- a/drivers/usb/musb/da8xx.c
+++ b/drivers/usb/musb/da8xx.c
@@ -198,7 +198,7 @@ static void otg_timer(unsigned long _musb)
*/
devctl = musb_readb(mregs, MUSB_DEVCTL);
dev_dbg(musb->controller, "Poll devctl %02x (%s)\n", devctl,
- otg_state_string(musb->xceiv->state));
+ usb_otg_state_string(musb->xceiv->state));
spin_lock_irqsave(&musb->lock, flags);
switch (musb->xceiv->state) {
@@ -267,7 +267,7 @@ static void da8xx_musb_try_idle(struct musb *musb, unsigned long timeout)
if (musb->is_active || (musb->a_wait_bcon == 0 &&
musb->xceiv->state == OTG_STATE_A_WAIT_BCON)) {
dev_dbg(musb->controller, "%s active, deleting timer\n",
- otg_state_string(musb->xceiv->state));
+ usb_otg_state_string(musb->xceiv->state));
del_timer(&otg_workaround);
last_timer = jiffies;
return;
@@ -280,7 +280,7 @@ static void da8xx_musb_try_idle(struct musb *musb, unsigned long timeout)
last_timer = timeout;
dev_dbg(musb->controller, "%s inactive, starting idle timer for %u ms\n",
- otg_state_string(musb->xceiv->state),
+ usb_otg_state_string(musb->xceiv->state),
jiffies_to_msecs(timeout - jiffies));
mod_timer(&otg_workaround, timeout);
}
@@ -327,7 +327,7 @@ static irqreturn_t da8xx_musb_interrupt(int irq, void *hci)
u8 devctl = musb_readb(mregs, MUSB_DEVCTL);
int err;
- err = musb->int_usb & USB_INTR_VBUSERROR;
+ err = musb->int_usb & MUSB_INTR_VBUSERROR;
if (err) {
/*
* The Mentor core doesn't debounce VBUS as needed
@@ -360,7 +360,7 @@ static irqreturn_t da8xx_musb_interrupt(int irq, void *hci)
dev_dbg(musb->controller, "VBUS %s (%s)%s, devctl %02x\n",
drvvbus ? "on" : "off",
- otg_state_string(musb->xceiv->state),
+ usb_otg_state_string(musb->xceiv->state),
err ? " ERROR" : "",
devctl);
ret = IRQ_HANDLED;
diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c
index e040d910373..bea6cc35471 100644
--- a/drivers/usb/musb/davinci.c
+++ b/drivers/usb/musb/davinci.c
@@ -215,7 +215,7 @@ static void otg_timer(unsigned long _musb)
*/
devctl = musb_readb(mregs, MUSB_DEVCTL);
dev_dbg(musb->controller, "poll devctl %02x (%s)\n", devctl,
- otg_state_string(musb->xceiv->state));
+ usb_otg_state_string(musb->xceiv->state));
spin_lock_irqsave(&musb->lock, flags);
switch (musb->xceiv->state) {
@@ -349,7 +349,7 @@ static irqreturn_t davinci_musb_interrupt(int irq, void *__hci)
davinci_musb_source_power(musb, drvvbus, 0);
dev_dbg(musb->controller, "VBUS %s (%s)%s, devctl %02x\n",
drvvbus ? "on" : "off",
- otg_state_string(musb->xceiv->state),
+ usb_otg_state_string(musb->xceiv->state),
err ? " ERROR" : "",
devctl);
retval = IRQ_HANDLED;
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index 60b41cc28da..37a261a6bb6 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -372,13 +372,13 @@ static void musb_otg_timer_func(unsigned long data)
case OTG_STATE_A_SUSPEND:
case OTG_STATE_A_WAIT_BCON:
dev_dbg(musb->controller, "HNP: %s timeout\n",
- otg_state_string(musb->xceiv->state));
+ usb_otg_state_string(musb->xceiv->state));
musb_platform_set_vbus(musb, 0);
musb->xceiv->state = OTG_STATE_A_WAIT_VFALL;
break;
default:
dev_dbg(musb->controller, "HNP: Unhandled mode %s\n",
- otg_state_string(musb->xceiv->state));
+ usb_otg_state_string(musb->xceiv->state));
}
musb->ignore_disconnect = 0;
spin_unlock_irqrestore(&musb->lock, flags);
@@ -393,13 +393,14 @@ void musb_hnp_stop(struct musb *musb)
void __iomem *mbase = musb->mregs;
u8 reg;
- dev_dbg(musb->controller, "HNP: stop from %s\n", otg_state_string(musb->xceiv->state));
+ dev_dbg(musb->controller, "HNP: stop from %s\n",
+ usb_otg_state_string(musb->xceiv->state));
switch (musb->xceiv->state) {
case OTG_STATE_A_PERIPHERAL:
musb_g_disconnect(musb);
dev_dbg(musb->controller, "HNP: back to %s\n",
- otg_state_string(musb->xceiv->state));
+ usb_otg_state_string(musb->xceiv->state));
break;
case OTG_STATE_B_HOST:
dev_dbg(musb->controller, "HNP: Disabling HR\n");
@@ -413,7 +414,7 @@ void musb_hnp_stop(struct musb *musb)
break;
default:
dev_dbg(musb->controller, "HNP: Stopping in unknown state %s\n",
- otg_state_string(musb->xceiv->state));
+ usb_otg_state_string(musb->xceiv->state));
}
/*
@@ -451,7 +452,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
*/
if (int_usb & MUSB_INTR_RESUME) {
handled = IRQ_HANDLED;
- dev_dbg(musb->controller, "RESUME (%s)\n", otg_state_string(musb->xceiv->state));
+ dev_dbg(musb->controller, "RESUME (%s)\n", usb_otg_state_string(musb->xceiv->state));
if (devctl & MUSB_DEVCTL_HM) {
void __iomem *mbase = musb->mregs;
@@ -493,7 +494,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
default:
WARNING("bogus %s RESUME (%s)\n",
"host",
- otg_state_string(musb->xceiv->state));
+ usb_otg_state_string(musb->xceiv->state));
}
} else {
switch (musb->xceiv->state) {
@@ -522,7 +523,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
default:
WARNING("bogus %s RESUME (%s)\n",
"peripheral",
- otg_state_string(musb->xceiv->state));
+ usb_otg_state_string(musb->xceiv->state));
}
}
}
@@ -538,7 +539,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
}
dev_dbg(musb->controller, "SESSION_REQUEST (%s)\n",
- otg_state_string(musb->xceiv->state));
+ usb_otg_state_string(musb->xceiv->state));
/* IRQ arrives from ID pin sense or (later, if VBUS power
* is removed) SRP. responses are time critical:
@@ -602,8 +603,9 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
break;
}
- dev_dbg(musb->controller, "VBUS_ERROR in %s (%02x, %s), retry #%d, port1 %08x\n",
- otg_state_string(musb->xceiv->state),
+ dev_printk(ignore ? KERN_DEBUG : KERN_ERR, musb->controller,
+ "VBUS_ERROR in %s (%02x, %s), retry #%d, port1 %08x\n",
+ usb_otg_state_string(musb->xceiv->state),
devctl,
({ char *s;
switch (devctl & MUSB_DEVCTL_VBUS) {
@@ -628,7 +630,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
if (int_usb & MUSB_INTR_SUSPEND) {
dev_dbg(musb->controller, "SUSPEND (%s) devctl %02x\n",
- otg_state_string(musb->xceiv->state), devctl);
+ usb_otg_state_string(musb->xceiv->state), devctl);
handled = IRQ_HANDLED;
switch (musb->xceiv->state) {
@@ -745,12 +747,12 @@ b_host:
usb_hcd_resume_root_hub(hcd);
dev_dbg(musb->controller, "CONNECT (%s) devctl %02x\n",
- otg_state_string(musb->xceiv->state), devctl);
+ usb_otg_state_string(musb->xceiv->state), devctl);
}
if ((int_usb & MUSB_INTR_DISCONNECT) && !musb->ignore_disconnect) {
dev_dbg(musb->controller, "DISCONNECT (%s) as %s, devctl %02x\n",
- otg_state_string(musb->xceiv->state),
+ usb_otg_state_string(musb->xceiv->state),
MUSB_MODE(musb), devctl);
handled = IRQ_HANDLED;
@@ -787,7 +789,7 @@ b_host:
break;
default:
WARNING("unhandled DISCONNECT transition (%s)\n",
- otg_state_string(musb->xceiv->state));
+ usb_otg_state_string(musb->xceiv->state));
break;
}
}
@@ -813,7 +815,7 @@ b_host:
}
} else {
dev_dbg(musb->controller, "BUS RESET as %s\n",
- otg_state_string(musb->xceiv->state));
+ usb_otg_state_string(musb->xceiv->state));
switch (musb->xceiv->state) {
case OTG_STATE_A_SUSPEND:
/* We need to ignore disconnect on suspend
@@ -826,7 +828,7 @@ b_host:
case OTG_STATE_A_WAIT_BCON: /* OPT TD.4.7-900ms */
/* never use invalid T(a_wait_bcon) */
dev_dbg(musb->controller, "HNP: in %s, %d msec timeout\n",
- otg_state_string(musb->xceiv->state),
+ usb_otg_state_string(musb->xceiv->state),
TA_WAIT_BCON(musb));
mod_timer(&musb->otg_timer, jiffies
+ msecs_to_jiffies(TA_WAIT_BCON(musb)));
@@ -838,7 +840,7 @@ b_host:
break;
case OTG_STATE_B_WAIT_ACON:
dev_dbg(musb->controller, "HNP: RESET (%s), to b_peripheral\n",
- otg_state_string(musb->xceiv->state));
+ usb_otg_state_string(musb->xceiv->state));
musb->xceiv->state = OTG_STATE_B_PERIPHERAL;
musb_g_reset(musb);
break;
@@ -850,7 +852,7 @@ b_host:
break;
default:
dev_dbg(musb->controller, "Unhandled BUS RESET as %s\n",
- otg_state_string(musb->xceiv->state));
+ usb_otg_state_string(musb->xceiv->state));
}
}
}
@@ -1624,8 +1626,6 @@ EXPORT_SYMBOL_GPL(musb_dma_completion);
/*-------------------------------------------------------------------------*/
-#ifdef CONFIG_SYSFS
-
static ssize_t
musb_mode_show(struct device *dev, struct device_attribute *attr, char *buf)
{
@@ -1634,7 +1634,7 @@ musb_mode_show(struct device *dev, struct device_attribute *attr, char *buf)
int ret = -EINVAL;
spin_lock_irqsave(&musb->lock, flags);
- ret = sprintf(buf, "%s\n", otg_state_string(musb->xceiv->state));
+ ret = sprintf(buf, "%s\n", usb_otg_state_string(musb->xceiv->state));
spin_unlock_irqrestore(&musb->lock, flags);
return ret;
@@ -1742,8 +1742,6 @@ static const struct attribute_group musb_attr_group = {
.attrs = musb_attributes,
};
-#endif /* sysfs */
-
/* Only used to provide driver mode change events */
static void musb_irq_work(struct work_struct *data)
{
@@ -1955,9 +1953,13 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
musb_write_ulpi_buscontrol(musb->mregs, busctl);
}
- MUSB_DEV_MODE(musb);
- musb->xceiv->otg->default_a = 0;
- musb->xceiv->state = OTG_STATE_B_IDLE;
+ if (musb->xceiv->otg->default_a) {
+ MUSB_HST_MODE(musb);
+ musb->xceiv->state = OTG_STATE_A_IDLE;
+ } else {
+ MUSB_DEV_MODE(musb);
+ musb->xceiv->state = OTG_STATE_B_IDLE;
+ }
status = musb_gadget_setup(musb);
@@ -1968,11 +1970,9 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
if (status < 0)
goto fail4;
-#ifdef CONFIG_SYSFS
status = sysfs_create_group(&musb->controller->kobj, &musb_attr_group);
if (status)
goto fail5;
-#endif
pm_runtime_put(musb->controller);
@@ -2014,7 +2014,6 @@ static int musb_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
int irq = platform_get_irq_byname(pdev, "mc");
- int status;
struct resource *iomem;
void __iomem *base;
@@ -2022,24 +2021,17 @@ static int musb_probe(struct platform_device *pdev)
if (!iomem || irq <= 0)
return -ENODEV;
- base = ioremap(iomem->start, resource_size(iomem));
- if (!base) {
- dev_err(dev, "ioremap failed\n");
- return -ENOMEM;
- }
+ base = devm_ioremap_resource(dev, iomem);
+ if (IS_ERR(base))
+ return PTR_ERR(base);
- status = musb_init_controller(dev, irq, base);
- if (status < 0)
- iounmap(base);
-
- return status;
+ return musb_init_controller(dev, irq, base);
}
static int musb_remove(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct musb *musb = dev_to_musb(dev);
- void __iomem *ctrl_base = musb->ctrl_base;
/* this gets called on rmmod.
* - Host mode: host may still be active
@@ -2050,7 +2042,6 @@ static int musb_remove(struct platform_device *pdev)
musb_shutdown(pdev);
musb_free(musb);
- iounmap(ctrl_base);
device_init_wakeup(dev, 0);
#ifndef CONFIG_MUSB_PIO_ONLY
dma_set_mask(dev, *dev->parent->dma_mask);
@@ -2299,8 +2290,6 @@ static int __init musb_init(void)
if (usb_disabled())
return 0;
- pr_info("%s: version " MUSB_VERSION ", ?dma?, otg (peripheral+host)\n",
- musb_driver_name);
return platform_driver_register(&musb_driver);
}
module_init(musb_init);
diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c
index 6bb89715b63..3a18e44e939 100644
--- a/drivers/usb/musb/musb_dsps.c
+++ b/drivers/usb/musb/musb_dsps.c
@@ -38,6 +38,7 @@
#include <linux/module.h>
#include <linux/usb/nop-usb-xceiv.h>
#include <linux/platform_data/usb-omap.h>
+#include <linux/sizes.h>
#include <linux/of.h>
#include <linux/of_device.h>
@@ -224,7 +225,7 @@ static void otg_timer(unsigned long _musb)
*/
devctl = dsps_readb(mregs, MUSB_DEVCTL);
dev_dbg(musb->controller, "Poll devctl %02x (%s)\n", devctl,
- otg_state_string(musb->xceiv->state));
+ usb_otg_state_string(musb->xceiv->state));
spin_lock_irqsave(&musb->lock, flags);
switch (musb->xceiv->state) {
@@ -273,7 +274,7 @@ static void dsps_musb_try_idle(struct musb *musb, unsigned long timeout)
if (musb->is_active || (musb->a_wait_bcon == 0 &&
musb->xceiv->state == OTG_STATE_A_WAIT_BCON)) {
dev_dbg(musb->controller, "%s active, deleting timer\n",
- otg_state_string(musb->xceiv->state));
+ usb_otg_state_string(musb->xceiv->state));
del_timer(&glue->timer[pdev->id]);
glue->last_timer[pdev->id] = jiffies;
return;
@@ -288,7 +289,7 @@ static void dsps_musb_try_idle(struct musb *musb, unsigned long timeout)
glue->last_timer[pdev->id] = timeout;
dev_dbg(musb->controller, "%s inactive, starting idle timer for %u ms\n",
- otg_state_string(musb->xceiv->state),
+ usb_otg_state_string(musb->xceiv->state),
jiffies_to_msecs(timeout - jiffies));
mod_timer(&glue->timer[pdev->id], timeout);
}
@@ -334,7 +335,7 @@ static irqreturn_t dsps_interrupt(int irq, void *hci)
* value but DEVCTL.BDEVICE is invalid without DEVCTL.SESSION set.
* Also, DRVVBUS pulses for SRP (but not at 5V) ...
*/
- if (usbintr & MUSB_INTR_BABBLE)
+ if (is_host_active(musb) && usbintr & MUSB_INTR_BABBLE)
pr_info("CAUTION: musb: Babble Interrupt Occurred\n");
if (usbintr & ((1 << wrp->drvvbus) << wrp->usb_shift)) {
@@ -377,7 +378,7 @@ static irqreturn_t dsps_interrupt(int irq, void *hci)
/* NOTE: this must complete power-on within 100 ms. */
dev_dbg(musb->controller, "VBUS %s (%s)%s, devctl %02x\n",
drvvbus ? "on" : "off",
- otg_state_string(musb->xceiv->state),
+ usb_otg_state_string(musb->xceiv->state),
err ? " ERROR" : "",
devctl);
ret = IRQ_HANDLED;
@@ -596,14 +597,13 @@ err0:
static int dsps_probe(struct platform_device *pdev)
{
- struct device_node *np = pdev->dev.of_node;
const struct of_device_id *match;
const struct dsps_musb_wrapper *wrp;
struct dsps_glue *glue;
struct resource *iomem;
int ret, i;
- match = of_match_node(musb_dsps_of_match, np);
+ match = of_match_node(musb_dsps_of_match, pdev->dev.of_node);
if (!match) {
dev_err(&pdev->dev, "fail to get matching of_match struct\n");
ret = -EINVAL;
diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c
index be18537c5f1..ba7092349fa 100644
--- a/drivers/usb/musb/musb_gadget.c
+++ b/drivers/usb/musb/musb_gadget.c
@@ -46,48 +46,6 @@
#include "musb_core.h"
-/* MUSB PERIPHERAL status 3-mar-2006:
- *
- * - EP0 seems solid. It passes both USBCV and usbtest control cases.
- * Minor glitches:
- *
- * + remote wakeup to Linux hosts work, but saw USBCV failures;
- * in one test run (operator error?)
- * + endpoint halt tests -- in both usbtest and usbcv -- seem
- * to break when dma is enabled ... is something wrongly
- * clearing SENDSTALL?
- *
- * - Mass storage behaved ok when last tested. Network traffic patterns
- * (with lots of short transfers etc) need retesting; they turn up the
- * worst cases of the DMA, since short packets are typical but are not
- * required.
- *
- * - TX/IN
- * + both pio and dma behave in with network and g_zero tests
- * + no cppi throughput issues other than no-hw-queueing
- * + failed with FLAT_REG (DaVinci)
- * + seems to behave with double buffering, PIO -and- CPPI
- * + with gadgetfs + AIO, requests got lost?
- *
- * - RX/OUT
- * + both pio and dma behave in with network and g_zero tests
- * + dma is slow in typical case (short_not_ok is clear)
- * + double buffering ok with PIO
- * + double buffering *FAILS* with CPPI, wrong data bytes sometimes
- * + request lossage observed with gadgetfs
- *
- * - ISO not tested ... might work, but only weakly isochronous
- *
- * - Gadget driver disabling of softconnect during bind() is ignored; so
- * drivers can't hold off host requests until userspace is ready.
- * (Workaround: they can turn it off later.)
- *
- * - PORTABILITY (assumes PIO works):
- * + DaVinci, basically works with cppi dma
- * + OMAP 2430, ditto with mentor dma
- * + TUSB 6010, platform-specific dma in the works
- */
-
/* ----------------------------------------------------------------------- */
#define is_buffer_mapped(req) (is_dma_capable() && \
@@ -141,7 +99,9 @@ static inline void map_dma_buffer(struct musb_request *request,
static inline void unmap_dma_buffer(struct musb_request *request,
struct musb *musb)
{
- if (!is_buffer_mapped(request))
+ struct musb_ep *musb_ep = request->ep;
+
+ if (!is_buffer_mapped(request) || !musb_ep->dma)
return;
if (request->request.dma == DMA_ADDR_INVALID) {
@@ -195,7 +155,10 @@ __acquires(ep->musb->lock)
ep->busy = 1;
spin_unlock(&musb->lock);
- unmap_dma_buffer(req, musb);
+
+ if (!dma_mapping_error(&musb->g.dev, request->dma))
+ unmap_dma_buffer(req, musb);
+
if (request->status == 0)
dev_dbg(musb->controller, "%s done request %p, %d/%d\n",
ep->end_point.name, request,
@@ -275,41 +238,6 @@ static inline int max_ep_writesize(struct musb *musb, struct musb_ep *ep)
return ep->packet_sz;
}
-
-#ifdef CONFIG_USB_INVENTRA_DMA
-
-/* Peripheral tx (IN) using Mentor DMA works as follows:
- Only mode 0 is used for transfers <= wPktSize,
- mode 1 is used for larger transfers,
-
- One of the following happens:
- - Host sends IN token which causes an endpoint interrupt
- -> TxAvail
- -> if DMA is currently busy, exit.
- -> if queue is non-empty, txstate().
-
- - Request is queued by the gadget driver.
- -> if queue was previously empty, txstate()
-
- txstate()
- -> start
- /\ -> setup DMA
- | (data is transferred to the FIFO, then sent out when
- | IN token(s) are recd from Host.
- | -> DMA interrupt on completion
- | calls TxAvail.
- | -> stop DMA, ~DMAENAB,
- | -> set TxPktRdy for last short pkt or zlp
- | -> Complete Request
- | -> Continue next request (call txstate)
- |___________________________________|
-
- * Non-Mentor DMA engines can of course work differently, such as by
- * upleveling from irq-per-packet to irq-per-buffer.
- */
-
-#endif
-
/*
* An endpoint is transmitting data. This can be called either from
* the IRQ routine or from ep.queue() to kickstart a request on an
@@ -616,37 +544,6 @@ void musb_g_tx(struct musb *musb, u8 epnum)
/* ------------------------------------------------------------ */
-#ifdef CONFIG_USB_INVENTRA_DMA
-
-/* Peripheral rx (OUT) using Mentor DMA works as follows:
- - Only mode 0 is used.
-
- - Request is queued by the gadget class driver.
- -> if queue was previously empty, rxstate()
-
- - Host sends OUT token which causes an endpoint interrupt
- /\ -> RxReady
- | -> if request queued, call rxstate
- | /\ -> setup DMA
- | | -> DMA interrupt on completion
- | | -> RxReady
- | | -> stop DMA
- | | -> ack the read
- | | -> if data recd = max expected
- | | by the request, or host
- | | sent a short packet,
- | | complete the request,
- | | and start the next one.
- | |_____________________________________|
- | else just wait for the host
- | to send the next OUT token.
- |__________________________________________________|
-
- * Non-Mentor DMA engines can of course work differently.
- */
-
-#endif
-
/*
* Context: controller locked, IRQs blocked, endpoint selected
*/
@@ -735,7 +632,7 @@ static void rxstate(struct musb *musb, struct musb_request *req)
struct dma_controller *c;
struct dma_channel *channel;
int use_dma = 0;
- int transfer_size;
+ unsigned int transfer_size;
c = musb->dma_controller;
channel = musb_ep->dma;
@@ -777,10 +674,11 @@ static void rxstate(struct musb *musb, struct musb_request *req)
csr | MUSB_RXCSR_DMAMODE);
musb_writew(epio, MUSB_RXCSR, csr);
- transfer_size = min(request->length - request->actual,
+ transfer_size = min_t(unsigned int,
+ request->length -
+ request->actual,
channel->max_len);
musb_ep->dma->desired_mode = 1;
-
} else {
if (!musb_ep->hb_mult &&
musb_ep->hw_ep->rx_double_buffered)
@@ -810,7 +708,7 @@ static void rxstate(struct musb *musb, struct musb_request *req)
struct dma_controller *c;
struct dma_channel *channel;
- int transfer_size = 0;
+ unsigned int transfer_size = 0;
c = musb->dma_controller;
channel = musb_ep->dma;
@@ -819,11 +717,13 @@ static void rxstate(struct musb *musb, struct musb_request *req)
if (fifo_count < musb_ep->packet_sz)
transfer_size = fifo_count;
else if (request->short_not_ok)
- transfer_size = min(request->length -
+ transfer_size = min_t(unsigned int,
+ request->length -
request->actual,
channel->max_len);
else
- transfer_size = min(request->length -
+ transfer_size = min_t(unsigned int,
+ request->length -
request->actual,
(unsigned)fifo_count);
@@ -1676,7 +1576,7 @@ static int musb_gadget_wakeup(struct usb_gadget *gadget)
goto done;
default:
dev_dbg(musb->controller, "Unhandled wake: %s\n",
- otg_state_string(musb->xceiv->state));
+ usb_otg_state_string(musb->xceiv->state));
goto done;
}
@@ -1796,13 +1696,6 @@ static const struct usb_gadget_ops musb_gadget_operations = {
* all peripheral ports are external...
*/
-static void musb_gadget_release(struct device *dev)
-{
- /* kref_put(WHAT) */
- dev_dbg(dev, "%s\n", __func__);
-}
-
-
static void
init_peripheral_ep(struct musb *musb, struct musb_ep *ep, u8 epnum, int is_in)
{
@@ -1887,12 +1780,7 @@ int musb_gadget_setup(struct musb *musb)
musb->g.speed = USB_SPEED_UNKNOWN;
/* this "gadget" abstracts/virtualizes the controller */
- dev_set_name(&musb->g.dev, "gadget");
- musb->g.dev.parent = musb->controller;
- musb->g.dev.dma_mask = musb->controller->dma_mask;
- musb->g.dev.release = musb_gadget_release;
musb->g.name = musb_driver_name;
-
musb->g.is_otg = 1;
musb_g_init_endpoints(musb);
@@ -1900,11 +1788,6 @@ int musb_gadget_setup(struct musb *musb)
musb->is_active = 0;
musb_platform_try_idle(musb, 0);
- status = device_register(&musb->g.dev);
- if (status != 0) {
- put_device(&musb->g.dev);
- return status;
- }
status = usb_add_gadget_udc(musb->controller, &musb->g);
if (status)
goto err;
@@ -1919,8 +1802,6 @@ err:
void musb_gadget_cleanup(struct musb *musb)
{
usb_del_gadget_udc(&musb->g);
- if (musb->g.dev.parent)
- device_unregister(&musb->g.dev);
}
/*
@@ -1972,9 +1853,8 @@ static int musb_gadget_start(struct usb_gadget *g,
goto err;
}
- if ((musb->xceiv->last_event == USB_EVENT_ID)
- && otg->set_vbus)
- otg_set_vbus(otg, 1);
+ if (musb->xceiv->last_event == USB_EVENT_ID)
+ musb_platform_set_vbus(musb, 1);
hcd->self.uses_pio_for_control = 1;
@@ -2058,6 +1938,7 @@ static int musb_gadget_stop(struct usb_gadget *g,
dev_dbg(musb->controller, "unregistering driver %s\n", driver->function);
musb->is_active = 0;
+ musb->gadget_driver = NULL;
musb_platform_try_idle(musb, 0);
spin_unlock_irqrestore(&musb->lock, flags);
@@ -2094,7 +1975,7 @@ void musb_g_resume(struct musb *musb)
break;
default:
WARNING("unhandled RESUME transition (%s)\n",
- otg_state_string(musb->xceiv->state));
+ usb_otg_state_string(musb->xceiv->state));
}
}
@@ -2124,7 +2005,7 @@ void musb_g_suspend(struct musb *musb)
* A_PERIPHERAL may need care too
*/
WARNING("unhandled SUSPEND transition (%s)\n",
- otg_state_string(musb->xceiv->state));
+ usb_otg_state_string(musb->xceiv->state));
}
}
@@ -2158,7 +2039,7 @@ void musb_g_disconnect(struct musb *musb)
switch (musb->xceiv->state) {
default:
dev_dbg(musb->controller, "Unhandled disconnect %s, setting a_idle\n",
- otg_state_string(musb->xceiv->state));
+ usb_otg_state_string(musb->xceiv->state));
musb->xceiv->state = OTG_STATE_A_IDLE;
MUSB_HST_MODE(musb);
break;
diff --git a/drivers/usb/musb/musb_gadget_ep0.c b/drivers/usb/musb/musb_gadget_ep0.c
index c9c1ac4e075..2af45a0c893 100644
--- a/drivers/usb/musb/musb_gadget_ep0.c
+++ b/drivers/usb/musb/musb_gadget_ep0.c
@@ -505,8 +505,10 @@ static void ep0_rxstate(struct musb *musb)
req->status = -EOVERFLOW;
count = len;
}
- musb_read_fifo(&musb->endpoints[0], count, buf);
- req->actual += count;
+ if (count > 0) {
+ musb_read_fifo(&musb->endpoints[0], count, buf);
+ req->actual += count;
+ }
csr = MUSB_CSR0_P_SVDRXPKTRDY;
if (count < 64 || req->actual == req->length) {
musb->ep0_state = MUSB_EP0_STAGE_STATUSIN;
diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c
index 1ce1fcf3f3e..8914dec49f0 100644
--- a/drivers/usb/musb/musb_host.c
+++ b/drivers/usb/musb/musb_host.c
@@ -2453,7 +2453,7 @@ static int musb_bus_suspend(struct usb_hcd *hcd)
if (musb->is_active) {
WARNING("trying to suspend as %s while active\n",
- otg_state_string(musb->xceiv->state));
+ usb_otg_state_string(musb->xceiv->state));
return -EBUSY;
} else
return 0;
@@ -2465,6 +2465,118 @@ static int musb_bus_resume(struct usb_hcd *hcd)
return 0;
}
+
+#ifndef CONFIG_MUSB_PIO_ONLY
+
+#define MUSB_USB_DMA_ALIGN 4
+
+struct musb_temp_buffer {
+ void *kmalloc_ptr;
+ void *old_xfer_buffer;
+ u8 data[0];
+};
+
+static void musb_free_temp_buffer(struct urb *urb)
+{
+ enum dma_data_direction dir;
+ struct musb_temp_buffer *temp;
+
+ if (!(urb->transfer_flags & URB_ALIGNED_TEMP_BUFFER))
+ return;
+
+ dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
+
+ temp = container_of(urb->transfer_buffer, struct musb_temp_buffer,
+ data);
+
+ if (dir == DMA_FROM_DEVICE) {
+ memcpy(temp->old_xfer_buffer, temp->data,
+ urb->transfer_buffer_length);
+ }
+ urb->transfer_buffer = temp->old_xfer_buffer;
+ kfree(temp->kmalloc_ptr);
+
+ urb->transfer_flags &= ~URB_ALIGNED_TEMP_BUFFER;
+}
+
+static int musb_alloc_temp_buffer(struct urb *urb, gfp_t mem_flags)
+{
+ enum dma_data_direction dir;
+ struct musb_temp_buffer *temp;
+ void *kmalloc_ptr;
+ size_t kmalloc_size;
+
+ if (urb->num_sgs || urb->sg ||
+ urb->transfer_buffer_length == 0 ||
+ !((uintptr_t)urb->transfer_buffer & (MUSB_USB_DMA_ALIGN - 1)))
+ return 0;
+
+ dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
+
+ /* Allocate a buffer with enough padding for alignment */
+ kmalloc_size = urb->transfer_buffer_length +
+ sizeof(struct musb_temp_buffer) + MUSB_USB_DMA_ALIGN - 1;
+
+ kmalloc_ptr = kmalloc(kmalloc_size, mem_flags);
+ if (!kmalloc_ptr)
+ return -ENOMEM;
+
+ /* Position our struct temp_buffer such that data is aligned */
+ temp = PTR_ALIGN(kmalloc_ptr, MUSB_USB_DMA_ALIGN);
+
+
+ temp->kmalloc_ptr = kmalloc_ptr;
+ temp->old_xfer_buffer = urb->transfer_buffer;
+ if (dir == DMA_TO_DEVICE)
+ memcpy(temp->data, urb->transfer_buffer,
+ urb->transfer_buffer_length);
+ urb->transfer_buffer = temp->data;
+
+ urb->transfer_flags |= URB_ALIGNED_TEMP_BUFFER;
+
+ return 0;
+}
+
+static int musb_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
+ gfp_t mem_flags)
+{
+ struct musb *musb = hcd_to_musb(hcd);
+ int ret;
+
+ /*
+ * The DMA engine in RTL1.8 and above cannot handle
+ * DMA addresses that are not aligned to a 4 byte boundary.
+ * For such engine implemented (un)map_urb_for_dma hooks.
+ * Do not use these hooks for RTL<1.8
+ */
+ if (musb->hwvers < MUSB_HWVERS_1800)
+ return usb_hcd_map_urb_for_dma(hcd, urb, mem_flags);
+
+ ret = musb_alloc_temp_buffer(urb, mem_flags);
+ if (ret)
+ return ret;
+
+ ret = usb_hcd_map_urb_for_dma(hcd, urb, mem_flags);
+ if (ret)
+ musb_free_temp_buffer(urb);
+
+ return ret;
+}
+
+static void musb_unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb)
+{
+ struct musb *musb = hcd_to_musb(hcd);
+
+ usb_hcd_unmap_urb_for_dma(hcd, urb);
+
+ /* Do not use this hook for RTL<1.8 (see description above) */
+ if (musb->hwvers < MUSB_HWVERS_1800)
+ return;
+
+ musb_free_temp_buffer(urb);
+}
+#endif /* !CONFIG_MUSB_PIO_ONLY */
+
const struct hc_driver musb_hc_driver = {
.description = "musb-hcd",
.product_desc = "MUSB HDRC host driver",
@@ -2484,6 +2596,11 @@ const struct hc_driver musb_hc_driver = {
.urb_dequeue = musb_urb_dequeue,
.endpoint_disable = musb_h_disable,
+#ifndef CONFIG_MUSB_PIO_ONLY
+ .map_urb_for_dma = musb_map_urb_for_dma,
+ .unmap_urb_for_dma = musb_unmap_urb_for_dma,
+#endif
+
.hub_status_data = musb_hub_status_data,
.hub_control = musb_hub_control,
.bus_suspend = musb_bus_suspend,
diff --git a/drivers/usb/musb/musb_virthub.c b/drivers/usb/musb/musb_virthub.c
index f70579154de..ef7d11045f5 100644
--- a/drivers/usb/musb/musb_virthub.c
+++ b/drivers/usb/musb/musb_virthub.c
@@ -95,7 +95,7 @@ static void musb_port_suspend(struct musb *musb, bool do_suspend)
break;
default:
dev_dbg(musb->controller, "bogus rh suspend? %s\n",
- otg_state_string(musb->xceiv->state));
+ usb_otg_state_string(musb->xceiv->state));
}
} else if (power & MUSB_POWER_SUSPENDM) {
power &= ~MUSB_POWER_SUSPENDM;
@@ -203,7 +203,7 @@ void musb_root_disconnect(struct musb *musb)
break;
default:
dev_dbg(musb->controller, "host disconnect (%s)\n",
- otg_state_string(musb->xceiv->state));
+ usb_otg_state_string(musb->xceiv->state));
}
}
diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c
index 1762354fe79..3551f1a30c6 100644
--- a/drivers/usb/musb/omap2430.c
+++ b/drivers/usb/musb/omap2430.c
@@ -51,7 +51,7 @@ struct omap2430_glue {
};
#define glue_to_musb(g) platform_get_drvdata(g->musb)
-struct omap2430_glue *_glue;
+static struct omap2430_glue *_glue;
static struct timer_list musb_idle_timer;
@@ -117,7 +117,7 @@ static void omap2430_musb_try_idle(struct musb *musb, unsigned long timeout)
if (musb->is_active || ((musb->a_wait_bcon == 0)
&& (musb->xceiv->state == OTG_STATE_A_WAIT_BCON))) {
dev_dbg(musb->controller, "%s active, deleting timer\n",
- otg_state_string(musb->xceiv->state));
+ usb_otg_state_string(musb->xceiv->state));
del_timer(&musb_idle_timer);
last_timer = jiffies;
return;
@@ -134,7 +134,7 @@ static void omap2430_musb_try_idle(struct musb *musb, unsigned long timeout)
last_timer = timeout;
dev_dbg(musb->controller, "%s inactive, for idle timer for %lu ms\n",
- otg_state_string(musb->xceiv->state),
+ usb_otg_state_string(musb->xceiv->state),
(unsigned long)jiffies_to_msecs(timeout - jiffies));
mod_timer(&musb_idle_timer, timeout);
}
@@ -174,8 +174,7 @@ static void omap2430_musb_set_vbus(struct musb *musb, int is_on)
}
}
- if (otg->set_vbus)
- otg_set_vbus(otg, 1);
+ otg_set_vbus(otg, 1);
} else {
musb->is_active = 1;
otg->default_a = 1;
@@ -200,7 +199,7 @@ static void omap2430_musb_set_vbus(struct musb *musb, int is_on)
dev_dbg(musb->controller, "VBUS %s, devctl %02x "
/* otg %3x conf %08x prcm %08x */ "\n",
- otg_state_string(musb->xceiv->state),
+ usb_otg_state_string(musb->xceiv->state),
musb_readb(musb->mregs, MUSB_DEVCTL));
}
@@ -237,9 +236,13 @@ void omap_musb_mailbox(enum omap_musb_vbus_id_status status)
{
struct omap2430_glue *glue = _glue;
- if (glue && glue_to_musb(glue)) {
- glue->status = status;
- } else {
+ if (!glue) {
+ pr_err("%s: musb core is not yet initialized\n", __func__);
+ return;
+ }
+ glue->status = status;
+
+ if (!glue_to_musb(glue)) {
pr_err("%s: musb core is not yet ready\n", __func__);
return;
}
@@ -288,14 +291,14 @@ static void omap_musb_set_mailbox(struct omap2430_glue *glue)
musb->xceiv->last_event = USB_EVENT_NONE;
if (musb->gadget_driver) {
+ omap2430_musb_set_vbus(musb, 0);
pm_runtime_mark_last_busy(dev);
pm_runtime_put_autosuspend(dev);
}
- if (data->interface_type == MUSB_INTERFACE_UTMI) {
- if (musb->xceiv->otg->set_vbus)
- otg_set_vbus(musb->xceiv->otg, 0);
- }
+ if (data->interface_type == MUSB_INTERFACE_UTMI)
+ otg_set_vbus(musb->xceiv->otg, 0);
+
omap_control_usb_set_mode(glue->control_otghs,
USB_MODE_DISCONNECT);
break;
@@ -351,7 +354,12 @@ static int omap2430_musb_init(struct musb *musb)
else
musb->xceiv = devm_usb_get_phy_dev(dev, 0);
- if (IS_ERR_OR_NULL(musb->xceiv)) {
+ if (IS_ERR(musb->xceiv)) {
+ status = PTR_ERR(musb->xceiv);
+
+ if (status == -ENXIO)
+ return status;
+
pr_err("HS USB OTG: no transceiver configured\n");
return -EPROBE_DEFER;
}
@@ -389,6 +397,8 @@ static int omap2430_musb_init(struct musb *musb)
if (glue->status != OMAP_MUSB_UNKNOWN)
omap_musb_set_mailbox(glue);
+ usb_phy_init(musb->xceiv);
+
pm_runtime_put_noidle(musb->controller);
return 0;
@@ -522,10 +532,10 @@ static int omap2430_probe(struct platform_device *pdev)
}
of_property_read_u32(np, "mode", (u32 *)&pdata->mode);
- of_property_read_u32(np, "interface_type",
+ of_property_read_u32(np, "interface-type",
(u32 *)&data->interface_type);
- of_property_read_u32(np, "num_eps", (u32 *)&config->num_eps);
- of_property_read_u32(np, "ram_bits", (u32 *)&config->ram_bits);
+ of_property_read_u32(np, "num-eps", (u32 *)&config->num_eps);
+ of_property_read_u32(np, "ram-bits", (u32 *)&config->ram_bits);
of_property_read_u32(np, "power", (u32 *)&pdata->power);
config->multipoint = of_property_read_bool(np, "multipoint");
pdata->has_mailbox = of_property_read_bool(np,
diff --git a/drivers/usb/musb/tusb6010.c b/drivers/usb/musb/tusb6010.c
index 464bd23cccd..7369ba33c94 100644
--- a/drivers/usb/musb/tusb6010.c
+++ b/drivers/usb/musb/tusb6010.c
@@ -423,7 +423,7 @@ static void musb_do_idle(unsigned long _musb)
&& (musb->idle_timeout == 0
|| time_after(jiffies, musb->idle_timeout))) {
dev_dbg(musb->controller, "Nothing connected %s, turning off VBUS\n",
- otg_state_string(musb->xceiv->state));
+ usb_otg_state_string(musb->xceiv->state));
}
/* FALLTHROUGH */
case OTG_STATE_A_IDLE:
@@ -478,7 +478,7 @@ static void tusb_musb_try_idle(struct musb *musb, unsigned long timeout)
if (musb->is_active || ((musb->a_wait_bcon == 0)
&& (musb->xceiv->state == OTG_STATE_A_WAIT_BCON))) {
dev_dbg(musb->controller, "%s active, deleting timer\n",
- otg_state_string(musb->xceiv->state));
+ usb_otg_state_string(musb->xceiv->state));
del_timer(&musb_idle_timer);
last_timer = jiffies;
return;
@@ -495,7 +495,7 @@ static void tusb_musb_try_idle(struct musb *musb, unsigned long timeout)
last_timer = timeout;
dev_dbg(musb->controller, "%s inactive, for idle timer for %lu ms\n",
- otg_state_string(musb->xceiv->state),
+ usb_otg_state_string(musb->xceiv->state),
(unsigned long)jiffies_to_msecs(timeout - jiffies));
mod_timer(&musb_idle_timer, timeout);
}
@@ -571,7 +571,7 @@ static void tusb_musb_set_vbus(struct musb *musb, int is_on)
musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
dev_dbg(musb->controller, "VBUS %s, devctl %02x otg %3x conf %08x prcm %08x\n",
- otg_state_string(musb->xceiv->state),
+ usb_otg_state_string(musb->xceiv->state),
musb_readb(musb->mregs, MUSB_DEVCTL),
musb_readl(tbase, TUSB_DEV_OTG_STAT),
conf, prcm);
@@ -678,13 +678,13 @@ tusb_otg_ints(struct musb *musb, u32 int_src, void __iomem *tbase)
musb->is_active = 0;
}
dev_dbg(musb->controller, "vbus change, %s, otg %03x\n",
- otg_state_string(musb->xceiv->state), otg_stat);
+ usb_otg_state_string(musb->xceiv->state), otg_stat);
idle_timeout = jiffies + (1 * HZ);
schedule_work(&musb->irq_work);
} else /* A-dev state machine */ {
dev_dbg(musb->controller, "vbus change, %s, otg %03x\n",
- otg_state_string(musb->xceiv->state), otg_stat);
+ usb_otg_state_string(musb->xceiv->state), otg_stat);
switch (musb->xceiv->state) {
case OTG_STATE_A_IDLE:
@@ -733,7 +733,7 @@ tusb_otg_ints(struct musb *musb, u32 int_src, void __iomem *tbase)
u8 devctl;
dev_dbg(musb->controller, "%s timer, %03x\n",
- otg_state_string(musb->xceiv->state), otg_stat);
+ usb_otg_state_string(musb->xceiv->state), otg_stat);
switch (musb->xceiv->state) {
case OTG_STATE_A_WAIT_VRISE:
diff --git a/drivers/usb/musb/ux500.c b/drivers/usb/musb/ux500.c
index 13a39291376..2c80004e0a8 100644
--- a/drivers/usb/musb/ux500.c
+++ b/drivers/usb/musb/ux500.c
@@ -26,6 +26,7 @@
#include <linux/err.h>
#include <linux/io.h>
#include <linux/platform_device.h>
+#include <linux/usb/musb-ux500.h>
#include "musb_core.h"
@@ -36,6 +37,98 @@ struct ux500_glue {
};
#define glue_to_musb(g) platform_get_drvdata(g->musb)
+static void ux500_musb_set_vbus(struct musb *musb, int is_on)
+{
+ u8 devctl;
+ unsigned long timeout = jiffies + msecs_to_jiffies(1000);
+ /* HDRC controls CPEN, but beware current surges during device
+ * connect. They can trigger transient overcurrent conditions
+ * that must be ignored.
+ */
+
+ devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
+
+ if (is_on) {
+ if (musb->xceiv->state == OTG_STATE_A_IDLE) {
+ /* start the session */
+ devctl |= MUSB_DEVCTL_SESSION;
+ musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
+ /*
+ * Wait for the musb to set as A device to enable the
+ * VBUS
+ */
+ while (musb_readb(musb->mregs, MUSB_DEVCTL) & 0x80) {
+
+ if (time_after(jiffies, timeout)) {
+ dev_err(musb->controller,
+ "configured as A device timeout");
+ break;
+ }
+ }
+
+ } else {
+ musb->is_active = 1;
+ musb->xceiv->otg->default_a = 1;
+ musb->xceiv->state = OTG_STATE_A_WAIT_VRISE;
+ devctl |= MUSB_DEVCTL_SESSION;
+ MUSB_HST_MODE(musb);
+ }
+ } else {
+ musb->is_active = 0;
+
+ /* NOTE: we're skipping A_WAIT_VFALL -> A_IDLE and jumping
+ * right to B_IDLE...
+ */
+ musb->xceiv->otg->default_a = 0;
+ devctl &= ~MUSB_DEVCTL_SESSION;
+ MUSB_DEV_MODE(musb);
+ }
+ musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
+
+ /*
+ * Devctl values will be updated after vbus goes below
+ * session_valid. The time taken depends on the capacitance
+ * on VBUS line. The max discharge time can be upto 1 sec
+ * as per the spec. Typically on our platform, it is 200ms
+ */
+ if (!is_on)
+ mdelay(200);
+
+ dev_dbg(musb->controller, "VBUS %s, devctl %02x\n",
+ usb_otg_state_string(musb->xceiv->state),
+ musb_readb(musb->mregs, MUSB_DEVCTL));
+}
+
+static int musb_otg_notifications(struct notifier_block *nb,
+ unsigned long event, void *unused)
+{
+ struct musb *musb = container_of(nb, struct musb, nb);
+
+ dev_dbg(musb->controller, "musb_otg_notifications %ld %s\n",
+ event, usb_otg_state_string(musb->xceiv->state));
+
+ switch (event) {
+ case UX500_MUSB_ID:
+ dev_dbg(musb->controller, "ID GND\n");
+ ux500_musb_set_vbus(musb, 1);
+ break;
+ case UX500_MUSB_VBUS:
+ dev_dbg(musb->controller, "VBUS Connect\n");
+ break;
+ case UX500_MUSB_NONE:
+ dev_dbg(musb->controller, "VBUS Disconnect\n");
+ if (is_host_active(musb))
+ ux500_musb_set_vbus(musb, 0);
+ else
+ musb->xceiv->state = OTG_STATE_B_IDLE;
+ break;
+ default:
+ dev_dbg(musb->controller, "ID float\n");
+ return NOTIFY_DONE;
+ }
+ return NOTIFY_OK;
+}
+
static irqreturn_t ux500_musb_interrupt(int irq, void *__hci)
{
unsigned long flags;
@@ -58,12 +151,21 @@ static irqreturn_t ux500_musb_interrupt(int irq, void *__hci)
static int ux500_musb_init(struct musb *musb)
{
+ int status;
+
musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
if (IS_ERR_OR_NULL(musb->xceiv)) {
pr_err("HS USB OTG: no transceiver configured\n");
return -EPROBE_DEFER;
}
+ musb->nb.notifier_call = musb_otg_notifications;
+ status = usb_register_notifier(musb->xceiv, &musb->nb);
+ if (status < 0) {
+ dev_dbg(musb->controller, "notification register failed\n");
+ return status;
+ }
+
musb->isr = ux500_musb_interrupt;
return 0;
@@ -71,6 +173,8 @@ static int ux500_musb_init(struct musb *musb)
static int ux500_musb_exit(struct musb *musb)
{
+ usb_unregister_notifier(musb->xceiv, &musb->nb);
+
usb_put_phy(musb->xceiv);
return 0;
@@ -79,6 +183,8 @@ static int ux500_musb_exit(struct musb *musb)
static const struct musb_platform_ops ux500_ops = {
.init = ux500_musb_init,
.exit = ux500_musb_exit,
+
+ .set_vbus = ux500_musb_set_vbus,
};
static int ux500_probe(struct platform_device *pdev)
diff --git a/drivers/usb/musb/ux500_dma.c b/drivers/usb/musb/ux500_dma.c
index 039e567dd3b..33812064114 100644
--- a/drivers/usb/musb/ux500_dma.c
+++ b/drivers/usb/musb/ux500_dma.c
@@ -1,7 +1,7 @@
/*
* drivers/usb/musb/ux500_dma.c
*
- * U8500 and U5500 DMA support code
+ * U8500 DMA support code
*
* Copyright (C) 2009 STMicroelectronics
* Copyright (C) 2011 ST-Ericsson SA
@@ -30,6 +30,7 @@
#include <linux/dma-mapping.h>
#include <linux/dmaengine.h>
#include <linux/pfn.h>
+#include <linux/sizes.h>
#include <linux/platform_data/usb-musb-ux500.h>
#include "musb_core.h"
@@ -56,7 +57,7 @@ struct ux500_dma_controller {
};
/* Work function invoked from DMA callback to handle rx transfers. */
-void ux500_dma_callback(void *private_data)
+static void ux500_dma_callback(void *private_data)
{
struct dma_channel *channel = private_data;
struct ux500_dma_channel *ux500_channel = channel->private_data;
@@ -93,8 +94,9 @@ static bool ux500_configure_channel(struct dma_channel *channel,
struct musb *musb = ux500_channel->controller->private_data;
dev_dbg(musb->controller,
- "packet_sz=%d, mode=%d, dma_addr=0x%x, len=%d is_tx=%d\n",
- packet_sz, mode, dma_addr, len, ux500_channel->is_tx);
+ "packet_sz=%d, mode=%d, dma_addr=0x%llu, len=%d is_tx=%d\n",
+ packet_sz, mode, (unsigned long long) dma_addr,
+ len, ux500_channel->is_tx);
ux500_channel->cur_len = len;
@@ -191,7 +193,7 @@ static int ux500_dma_is_compatible(struct dma_channel *channel,
u16 maxpacket, void *buf, u32 length)
{
if ((maxpacket & 0x3) ||
- ((int)buf & 0x3) ||
+ ((unsigned long int) buf & 0x3) ||
(length < 512) ||
(length & 0x3))
return false;
@@ -372,12 +374,17 @@ struct dma_controller *dma_controller_create(struct musb *musb, void __iomem *ba
controller = kzalloc(sizeof(*controller), GFP_KERNEL);
if (!controller)
- return NULL;
+ goto kzalloc_fail;
controller->private_data = musb;
/* Save physical address for DMA controller. */
iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!iomem) {
+ dev_err(musb->controller, "no memory resource defined\n");
+ goto plat_get_fail;
+ }
+
controller->phy_base = (dma_addr_t) iomem->start;
controller->controller.start = ux500_dma_controller_start;
@@ -389,4 +396,9 @@ struct dma_controller *dma_controller_create(struct musb *musb, void __iomem *ba
controller->controller.is_compatible = ux500_dma_is_compatible;
return &controller->controller;
+
+plat_get_fail:
+ kfree(controller);
+kzalloc_fail:
+ return NULL;
}
diff --git a/drivers/usb/otg/Kconfig b/drivers/usb/otg/Kconfig
deleted file mode 100644
index 37962c99ff1..00000000000
--- a/drivers/usb/otg/Kconfig
+++ /dev/null
@@ -1,141 +0,0 @@
-#
-# USB OTG infrastructure may be needed for peripheral-only, host-only,
-# or OTG-capable configurations when OTG transceivers or controllers
-# are used.
-#
-
-comment "OTG and related infrastructure"
-
-config USB_OTG_UTILS
- bool
- help
- Select this to make sure the build includes objects from
- the OTG infrastructure directory.
-
-if USB || USB_GADGET
-
-#
-# USB Transceiver Drivers
-#
-config USB_GPIO_VBUS
- tristate "GPIO based peripheral-only VBUS sensing 'transceiver'"
- depends on GENERIC_GPIO
- select USB_OTG_UTILS
- help
- Provides simple GPIO VBUS sensing for controllers with an
- internal transceiver via the usb_phy interface, and
- optionally control of a D+ pullup GPIO as well as a VBUS
- current limit regulator.
-
-config ISP1301_OMAP
- tristate "Philips ISP1301 with OMAP OTG"
- depends on I2C && ARCH_OMAP_OTG
- select USB_OTG_UTILS
- help
- If you say yes here you get support for the Philips ISP1301
- USB-On-The-Go transceiver working with the OMAP OTG controller.
- The ISP1301 is a full speed USB transceiver which is used in
- products including H2, H3, and H4 development boards for Texas
- Instruments OMAP processors.
-
- This driver can also be built as a module. If so, the module
- will be called isp1301_omap.
-
-config USB_ULPI
- bool "Generic ULPI Transceiver Driver"
- depends on ARM
- select USB_OTG_UTILS
- help
- Enable this to support ULPI connected USB OTG transceivers which
- are likely found on embedded boards.
-
-config USB_ULPI_VIEWPORT
- bool
- depends on USB_ULPI
- help
- Provides read/write operations to the ULPI phy register set for
- controllers with a viewport register (e.g. Chipidea/ARC controllers).
-
-config TWL4030_USB
- tristate "TWL4030 USB Transceiver Driver"
- depends on TWL4030_CORE && REGULATOR_TWL4030 && USB_MUSB_OMAP2PLUS
- select USB_OTG_UTILS
- help
- Enable this to support the USB OTG transceiver on TWL4030
- family chips (including the TWL5030 and TPS659x0 devices).
- This transceiver supports high and full speed devices plus,
- in host mode, low speed.
-
-config TWL6030_USB
- tristate "TWL6030 USB Transceiver Driver"
- depends on TWL4030_CORE && OMAP_USB2 && USB_MUSB_OMAP2PLUS
- select USB_OTG_UTILS
- help
- Enable this to support the USB OTG transceiver on TWL6030
- family chips. This TWL6030 transceiver has the VBUS and ID GND
- and OTG SRP events capabilities. For all other transceiver functionality
- UTMI PHY is embedded in OMAP4430. The internal PHY configurations APIs
- are hooked to this driver through platform_data structure.
- The definition of internal PHY APIs are in the mach-omap2 layer.
-
-config NOP_USB_XCEIV
- tristate "NOP USB Transceiver Driver"
- select USB_OTG_UTILS
- help
- This driver is to be used by all the usb transceiver which are either
- built-in with usb ip or which are autonomous and doesn't require any
- phy programming such as ISP1x04 etc.
-
-config USB_MSM_OTG
- tristate "OTG support for Qualcomm on-chip USB controller"
- depends on (USB || USB_GADGET) && ARCH_MSM
- select USB_OTG_UTILS
- help
- Enable this to support the USB OTG transceiver on MSM chips. It
- handles PHY initialization, clock management, and workarounds
- required after resetting the hardware and power management.
- This driver is required even for peripheral only or host only
- mode configurations.
- This driver is not supported on boards like trout which
- has an external PHY.
-
-config AB8500_USB
- tristate "AB8500 USB Transceiver Driver"
- depends on AB8500_CORE
- select USB_OTG_UTILS
- help
- Enable this to support the USB OTG transceiver in AB8500 chip.
- This transceiver supports high and full speed devices plus,
- in host mode, low speed.
-
-config FSL_USB2_OTG
- bool "Freescale USB OTG Transceiver Driver"
- depends on USB_EHCI_FSL && USB_FSL_USB2 && USB_SUSPEND
- select USB_OTG
- select USB_OTG_UTILS
- help
- Enable this to support Freescale USB OTG transceiver.
-
-config USB_MXS_PHY
- tristate "Freescale MXS USB PHY support"
- depends on ARCH_MXC || ARCH_MXS
- select STMP_DEVICE
- select USB_OTG_UTILS
- help
- Enable this to support the Freescale MXS USB PHY.
-
- MXS Phy is used by some of the i.MX SoCs, for example imx23/28/6x.
-
-config USB_MV_OTG
- tristate "Marvell USB OTG support"
- depends on USB_EHCI_MV && USB_MV_UDC && USB_SUSPEND
- select USB_OTG
- select USB_OTG_UTILS
- help
- Say Y here if you want to build Marvell USB OTG transciever
- driver in kernel (including PXA and MMP series). This driver
- implements role switch between EHCI host driver and gadget driver.
-
- To compile this driver as a module, choose M here.
-
-endif # USB || OTG
diff --git a/drivers/usb/otg/Makefile b/drivers/usb/otg/Makefile
deleted file mode 100644
index a844b8d35d1..00000000000
--- a/drivers/usb/otg/Makefile
+++ /dev/null
@@ -1,24 +0,0 @@
-#
-# OTG infrastructure and transceiver drivers
-#
-
-ccflags-$(CONFIG_USB_DEBUG) := -DDEBUG
-ccflags-$(CONFIG_USB_GADGET_DEBUG) += -DDEBUG
-
-# infrastructure
-obj-$(CONFIG_USB_OTG_UTILS) += otg.o
-
-# transceiver drivers
-obj-$(CONFIG_USB_GPIO_VBUS) += gpio_vbus.o
-obj-$(CONFIG_ISP1301_OMAP) += isp1301_omap.o
-obj-$(CONFIG_TWL4030_USB) += twl4030-usb.o
-obj-$(CONFIG_TWL6030_USB) += twl6030-usb.o
-obj-$(CONFIG_NOP_USB_XCEIV) += nop-usb-xceiv.o
-obj-$(CONFIG_USB_ULPI) += ulpi.o
-obj-$(CONFIG_USB_ULPI_VIEWPORT) += ulpi_viewport.o
-obj-$(CONFIG_USB_MSM_OTG) += msm_otg.o
-obj-$(CONFIG_AB8500_USB) += ab8500-usb.o
-fsl_usb2_otg-objs := fsl_otg.o otg_fsm.o
-obj-$(CONFIG_FSL_USB2_OTG) += fsl_usb2_otg.o
-obj-$(CONFIG_USB_MXS_PHY) += mxs-phy.o
-obj-$(CONFIG_USB_MV_OTG) += mv_otg.o
diff --git a/drivers/usb/otg/ab8500-usb.c b/drivers/usb/otg/ab8500-usb.c
deleted file mode 100644
index 2d86f26a018..00000000000
--- a/drivers/usb/otg/ab8500-usb.c
+++ /dev/null
@@ -1,596 +0,0 @@
-/*
- * drivers/usb/otg/ab8500_usb.c
- *
- * USB transceiver driver for AB8500 chip
- *
- * Copyright (C) 2010 ST-Ericsson AB
- * Mian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.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; either version 2 of the License, or
- * (at your option) any later version.
- *
- * 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.
- *
- */
-
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/usb/otg.h>
-#include <linux/slab.h>
-#include <linux/notifier.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/mfd/abx500.h>
-#include <linux/mfd/abx500/ab8500.h>
-
-#define AB8500_MAIN_WD_CTRL_REG 0x01
-#define AB8500_USB_LINE_STAT_REG 0x80
-#define AB8500_USB_PHY_CTRL_REG 0x8A
-
-#define AB8500_BIT_OTG_STAT_ID (1 << 0)
-#define AB8500_BIT_PHY_CTRL_HOST_EN (1 << 0)
-#define AB8500_BIT_PHY_CTRL_DEVICE_EN (1 << 1)
-#define AB8500_BIT_WD_CTRL_ENABLE (1 << 0)
-#define AB8500_BIT_WD_CTRL_KICK (1 << 1)
-
-#define AB8500_V1x_LINK_STAT_WAIT (HZ/10)
-#define AB8500_WD_KICK_DELAY_US 100 /* usec */
-#define AB8500_WD_V11_DISABLE_DELAY_US 100 /* usec */
-#define AB8500_WD_V10_DISABLE_DELAY_MS 100 /* ms */
-
-/* Usb line status register */
-enum ab8500_usb_link_status {
- USB_LINK_NOT_CONFIGURED = 0,
- USB_LINK_STD_HOST_NC,
- USB_LINK_STD_HOST_C_NS,
- USB_LINK_STD_HOST_C_S,
- USB_LINK_HOST_CHG_NM,
- USB_LINK_HOST_CHG_HS,
- USB_LINK_HOST_CHG_HS_CHIRP,
- USB_LINK_DEDICATED_CHG,
- USB_LINK_ACA_RID_A,
- USB_LINK_ACA_RID_B,
- USB_LINK_ACA_RID_C_NM,
- USB_LINK_ACA_RID_C_HS,
- USB_LINK_ACA_RID_C_HS_CHIRP,
- USB_LINK_HM_IDGND,
- USB_LINK_RESERVED,
- USB_LINK_NOT_VALID_LINK
-};
-
-struct ab8500_usb {
- struct usb_phy phy;
- struct device *dev;
- int irq_num_id_rise;
- int irq_num_id_fall;
- int irq_num_vbus_rise;
- int irq_num_vbus_fall;
- int irq_num_link_status;
- unsigned vbus_draw;
- struct delayed_work dwork;
- struct work_struct phy_dis_work;
- unsigned long link_status_wait;
- int rev;
-};
-
-static inline struct ab8500_usb *phy_to_ab(struct usb_phy *x)
-{
- return container_of(x, struct ab8500_usb, phy);
-}
-
-static void ab8500_usb_wd_workaround(struct ab8500_usb *ab)
-{
- abx500_set_register_interruptible(ab->dev,
- AB8500_SYS_CTRL2_BLOCK,
- AB8500_MAIN_WD_CTRL_REG,
- AB8500_BIT_WD_CTRL_ENABLE);
-
- udelay(AB8500_WD_KICK_DELAY_US);
-
- abx500_set_register_interruptible(ab->dev,
- AB8500_SYS_CTRL2_BLOCK,
- AB8500_MAIN_WD_CTRL_REG,
- (AB8500_BIT_WD_CTRL_ENABLE
- | AB8500_BIT_WD_CTRL_KICK));
-
- if (ab->rev > 0x10) /* v1.1 v2.0 */
- udelay(AB8500_WD_V11_DISABLE_DELAY_US);
- else /* v1.0 */
- msleep(AB8500_WD_V10_DISABLE_DELAY_MS);
-
- abx500_set_register_interruptible(ab->dev,
- AB8500_SYS_CTRL2_BLOCK,
- AB8500_MAIN_WD_CTRL_REG,
- 0);
-}
-
-static void ab8500_usb_phy_ctrl(struct ab8500_usb *ab, bool sel_host,
- bool enable)
-{
- u8 ctrl_reg;
- abx500_get_register_interruptible(ab->dev,
- AB8500_USB,
- AB8500_USB_PHY_CTRL_REG,
- &ctrl_reg);
- if (sel_host) {
- if (enable)
- ctrl_reg |= AB8500_BIT_PHY_CTRL_HOST_EN;
- else
- ctrl_reg &= ~AB8500_BIT_PHY_CTRL_HOST_EN;
- } else {
- if (enable)
- ctrl_reg |= AB8500_BIT_PHY_CTRL_DEVICE_EN;
- else
- ctrl_reg &= ~AB8500_BIT_PHY_CTRL_DEVICE_EN;
- }
-
- abx500_set_register_interruptible(ab->dev,
- AB8500_USB,
- AB8500_USB_PHY_CTRL_REG,
- ctrl_reg);
-
- /* Needed to enable the phy.*/
- if (enable)
- ab8500_usb_wd_workaround(ab);
-}
-
-#define ab8500_usb_host_phy_en(ab) ab8500_usb_phy_ctrl(ab, true, true)
-#define ab8500_usb_host_phy_dis(ab) ab8500_usb_phy_ctrl(ab, true, false)
-#define ab8500_usb_peri_phy_en(ab) ab8500_usb_phy_ctrl(ab, false, true)
-#define ab8500_usb_peri_phy_dis(ab) ab8500_usb_phy_ctrl(ab, false, false)
-
-static int ab8500_usb_link_status_update(struct ab8500_usb *ab)
-{
- u8 reg;
- enum ab8500_usb_link_status lsts;
- void *v = NULL;
- enum usb_phy_events event;
-
- abx500_get_register_interruptible(ab->dev,
- AB8500_USB,
- AB8500_USB_LINE_STAT_REG,
- &reg);
-
- lsts = (reg >> 3) & 0x0F;
-
- switch (lsts) {
- case USB_LINK_NOT_CONFIGURED:
- case USB_LINK_RESERVED:
- case USB_LINK_NOT_VALID_LINK:
- /* TODO: Disable regulators. */
- ab8500_usb_host_phy_dis(ab);
- ab8500_usb_peri_phy_dis(ab);
- ab->phy.state = OTG_STATE_B_IDLE;
- ab->phy.otg->default_a = false;
- ab->vbus_draw = 0;
- event = USB_EVENT_NONE;
- break;
-
- case USB_LINK_STD_HOST_NC:
- case USB_LINK_STD_HOST_C_NS:
- case USB_LINK_STD_HOST_C_S:
- case USB_LINK_HOST_CHG_NM:
- case USB_LINK_HOST_CHG_HS:
- case USB_LINK_HOST_CHG_HS_CHIRP:
- if (ab->phy.otg->gadget) {
- /* TODO: Enable regulators. */
- ab8500_usb_peri_phy_en(ab);
- v = ab->phy.otg->gadget;
- }
- event = USB_EVENT_VBUS;
- break;
-
- case USB_LINK_HM_IDGND:
- if (ab->phy.otg->host) {
- /* TODO: Enable regulators. */
- ab8500_usb_host_phy_en(ab);
- v = ab->phy.otg->host;
- }
- ab->phy.state = OTG_STATE_A_IDLE;
- ab->phy.otg->default_a = true;
- event = USB_EVENT_ID;
- break;
-
- case USB_LINK_ACA_RID_A:
- case USB_LINK_ACA_RID_B:
- /* TODO */
- case USB_LINK_ACA_RID_C_NM:
- case USB_LINK_ACA_RID_C_HS:
- case USB_LINK_ACA_RID_C_HS_CHIRP:
- case USB_LINK_DEDICATED_CHG:
- /* TODO: vbus_draw */
- event = USB_EVENT_CHARGER;
- break;
- }
-
- atomic_notifier_call_chain(&ab->phy.notifier, event, v);
-
- return 0;
-}
-
-static void ab8500_usb_delayed_work(struct work_struct *work)
-{
- struct ab8500_usb *ab = container_of(work, struct ab8500_usb,
- dwork.work);
-
- ab8500_usb_link_status_update(ab);
-}
-
-static irqreturn_t ab8500_usb_v1x_common_irq(int irq, void *data)
-{
- struct ab8500_usb *ab = (struct ab8500_usb *) data;
-
- /* Wait for link status to become stable. */
- schedule_delayed_work(&ab->dwork, ab->link_status_wait);
-
- return IRQ_HANDLED;
-}
-
-static irqreturn_t ab8500_usb_v1x_vbus_fall_irq(int irq, void *data)
-{
- struct ab8500_usb *ab = (struct ab8500_usb *) data;
-
- /* Link status will not be updated till phy is disabled. */
- ab8500_usb_peri_phy_dis(ab);
-
- /* Wait for link status to become stable. */
- schedule_delayed_work(&ab->dwork, ab->link_status_wait);
-
- return IRQ_HANDLED;
-}
-
-static irqreturn_t ab8500_usb_v20_irq(int irq, void *data)
-{
- struct ab8500_usb *ab = (struct ab8500_usb *) data;
-
- ab8500_usb_link_status_update(ab);
-
- return IRQ_HANDLED;
-}
-
-static void ab8500_usb_phy_disable_work(struct work_struct *work)
-{
- struct ab8500_usb *ab = container_of(work, struct ab8500_usb,
- phy_dis_work);
-
- if (!ab->phy.otg->host)
- ab8500_usb_host_phy_dis(ab);
-
- if (!ab->phy.otg->gadget)
- ab8500_usb_peri_phy_dis(ab);
-}
-
-static int ab8500_usb_set_power(struct usb_phy *phy, unsigned mA)
-{
- struct ab8500_usb *ab;
-
- if (!phy)
- return -ENODEV;
-
- ab = phy_to_ab(phy);
-
- ab->vbus_draw = mA;
-
- if (mA)
- atomic_notifier_call_chain(&ab->phy.notifier,
- USB_EVENT_ENUMERATED, ab->phy.otg->gadget);
- return 0;
-}
-
-/* TODO: Implement some way for charging or other drivers to read
- * ab->vbus_draw.
- */
-
-static int ab8500_usb_set_suspend(struct usb_phy *x, int suspend)
-{
- /* TODO */
- return 0;
-}
-
-static int ab8500_usb_set_peripheral(struct usb_otg *otg,
- struct usb_gadget *gadget)
-{
- struct ab8500_usb *ab;
-
- if (!otg)
- return -ENODEV;
-
- ab = phy_to_ab(otg->phy);
-
- /* Some drivers call this function in atomic context.
- * Do not update ab8500 registers directly till this
- * is fixed.
- */
-
- if (!gadget) {
- /* TODO: Disable regulators. */
- otg->gadget = NULL;
- schedule_work(&ab->phy_dis_work);
- } else {
- otg->gadget = gadget;
- otg->phy->state = OTG_STATE_B_IDLE;
-
- /* Phy will not be enabled if cable is already
- * plugged-in. Schedule to enable phy.
- * Use same delay to avoid any race condition.
- */
- schedule_delayed_work(&ab->dwork, ab->link_status_wait);
- }
-
- return 0;
-}
-
-static int ab8500_usb_set_host(struct usb_otg *otg, struct usb_bus *host)
-{
- struct ab8500_usb *ab;
-
- if (!otg)
- return -ENODEV;
-
- ab = phy_to_ab(otg->phy);
-
- /* Some drivers call this function in atomic context.
- * Do not update ab8500 registers directly till this
- * is fixed.
- */
-
- if (!host) {
- /* TODO: Disable regulators. */
- otg->host = NULL;
- schedule_work(&ab->phy_dis_work);
- } else {
- otg->host = host;
- /* Phy will not be enabled if cable is already
- * plugged-in. Schedule to enable phy.
- * Use same delay to avoid any race condition.
- */
- schedule_delayed_work(&ab->dwork, ab->link_status_wait);
- }
-
- return 0;
-}
-
-static void ab8500_usb_irq_free(struct ab8500_usb *ab)
-{
- if (ab->rev < 0x20) {
- free_irq(ab->irq_num_id_rise, ab);
- free_irq(ab->irq_num_id_fall, ab);
- free_irq(ab->irq_num_vbus_rise, ab);
- free_irq(ab->irq_num_vbus_fall, ab);
- } else {
- free_irq(ab->irq_num_link_status, ab);
- }
-}
-
-static int ab8500_usb_v1x_res_setup(struct platform_device *pdev,
- struct ab8500_usb *ab)
-{
- int err;
-
- ab->irq_num_id_rise = platform_get_irq_byname(pdev, "ID_WAKEUP_R");
- if (ab->irq_num_id_rise < 0) {
- dev_err(&pdev->dev, "ID rise irq not found\n");
- return ab->irq_num_id_rise;
- }
- err = request_threaded_irq(ab->irq_num_id_rise, NULL,
- ab8500_usb_v1x_common_irq,
- IRQF_NO_SUSPEND | IRQF_SHARED,
- "usb-id-rise", ab);
- if (err < 0) {
- dev_err(ab->dev, "request_irq failed for ID rise irq\n");
- goto fail0;
- }
-
- ab->irq_num_id_fall = platform_get_irq_byname(pdev, "ID_WAKEUP_F");
- if (ab->irq_num_id_fall < 0) {
- dev_err(&pdev->dev, "ID fall irq not found\n");
- return ab->irq_num_id_fall;
- }
- err = request_threaded_irq(ab->irq_num_id_fall, NULL,
- ab8500_usb_v1x_common_irq,
- IRQF_NO_SUSPEND | IRQF_SHARED,
- "usb-id-fall", ab);
- if (err < 0) {
- dev_err(ab->dev, "request_irq failed for ID fall irq\n");
- goto fail1;
- }
-
- ab->irq_num_vbus_rise = platform_get_irq_byname(pdev, "VBUS_DET_R");
- if (ab->irq_num_vbus_rise < 0) {
- dev_err(&pdev->dev, "VBUS rise irq not found\n");
- return ab->irq_num_vbus_rise;
- }
- err = request_threaded_irq(ab->irq_num_vbus_rise, NULL,
- ab8500_usb_v1x_common_irq,
- IRQF_NO_SUSPEND | IRQF_SHARED,
- "usb-vbus-rise", ab);
- if (err < 0) {
- dev_err(ab->dev, "request_irq failed for Vbus rise irq\n");
- goto fail2;
- }
-
- ab->irq_num_vbus_fall = platform_get_irq_byname(pdev, "VBUS_DET_F");
- if (ab->irq_num_vbus_fall < 0) {
- dev_err(&pdev->dev, "VBUS fall irq not found\n");
- return ab->irq_num_vbus_fall;
- }
- err = request_threaded_irq(ab->irq_num_vbus_fall, NULL,
- ab8500_usb_v1x_vbus_fall_irq,
- IRQF_NO_SUSPEND | IRQF_SHARED,
- "usb-vbus-fall", ab);
- if (err < 0) {
- dev_err(ab->dev, "request_irq failed for Vbus fall irq\n");
- goto fail3;
- }
-
- return 0;
-fail3:
- free_irq(ab->irq_num_vbus_rise, ab);
-fail2:
- free_irq(ab->irq_num_id_fall, ab);
-fail1:
- free_irq(ab->irq_num_id_rise, ab);
-fail0:
- return err;
-}
-
-static int ab8500_usb_v2_res_setup(struct platform_device *pdev,
- struct ab8500_usb *ab)
-{
- int err;
-
- ab->irq_num_link_status = platform_get_irq_byname(pdev,
- "USB_LINK_STATUS");
- if (ab->irq_num_link_status < 0) {
- dev_err(&pdev->dev, "Link status irq not found\n");
- return ab->irq_num_link_status;
- }
-
- err = request_threaded_irq(ab->irq_num_link_status, NULL,
- ab8500_usb_v20_irq,
- IRQF_NO_SUSPEND | IRQF_SHARED,
- "usb-link-status", ab);
- if (err < 0) {
- dev_err(ab->dev,
- "request_irq failed for link status irq\n");
- return err;
- }
-
- return 0;
-}
-
-static int ab8500_usb_probe(struct platform_device *pdev)
-{
- struct ab8500_usb *ab;
- struct usb_otg *otg;
- int err;
- int rev;
-
- rev = abx500_get_chip_id(&pdev->dev);
- if (rev < 0) {
- dev_err(&pdev->dev, "Chip id read failed\n");
- return rev;
- } else if (rev < 0x10) {
- dev_err(&pdev->dev, "Unsupported AB8500 chip\n");
- return -ENODEV;
- }
-
- ab = kzalloc(sizeof *ab, GFP_KERNEL);
- if (!ab)
- return -ENOMEM;
-
- otg = kzalloc(sizeof *otg, GFP_KERNEL);
- if (!otg) {
- kfree(ab);
- return -ENOMEM;
- }
-
- ab->dev = &pdev->dev;
- ab->rev = rev;
- ab->phy.dev = ab->dev;
- ab->phy.otg = otg;
- ab->phy.label = "ab8500";
- ab->phy.set_suspend = ab8500_usb_set_suspend;
- ab->phy.set_power = ab8500_usb_set_power;
- ab->phy.state = OTG_STATE_UNDEFINED;
-
- otg->phy = &ab->phy;
- otg->set_host = ab8500_usb_set_host;
- otg->set_peripheral = ab8500_usb_set_peripheral;
-
- platform_set_drvdata(pdev, ab);
-
- ATOMIC_INIT_NOTIFIER_HEAD(&ab->phy.notifier);
-
- /* v1: Wait for link status to become stable.
- * all: Updates form set_host and set_peripheral as they are atomic.
- */
- INIT_DELAYED_WORK(&ab->dwork, ab8500_usb_delayed_work);
-
- /* all: Disable phy when called from set_host and set_peripheral */
- INIT_WORK(&ab->phy_dis_work, ab8500_usb_phy_disable_work);
-
- if (ab->rev < 0x20) {
- err = ab8500_usb_v1x_res_setup(pdev, ab);
- ab->link_status_wait = AB8500_V1x_LINK_STAT_WAIT;
- } else {
- err = ab8500_usb_v2_res_setup(pdev, ab);
- }
-
- if (err < 0)
- goto fail0;
-
- err = usb_add_phy(&ab->phy, USB_PHY_TYPE_USB2);
- if (err) {
- dev_err(&pdev->dev, "Can't register transceiver\n");
- goto fail1;
- }
-
- dev_info(&pdev->dev, "AB8500 usb driver initialized\n");
-
- return 0;
-fail1:
- ab8500_usb_irq_free(ab);
-fail0:
- kfree(otg);
- kfree(ab);
- return err;
-}
-
-static int ab8500_usb_remove(struct platform_device *pdev)
-{
- struct ab8500_usb *ab = platform_get_drvdata(pdev);
-
- ab8500_usb_irq_free(ab);
-
- cancel_delayed_work_sync(&ab->dwork);
-
- cancel_work_sync(&ab->phy_dis_work);
-
- usb_remove_phy(&ab->phy);
-
- ab8500_usb_host_phy_dis(ab);
- ab8500_usb_peri_phy_dis(ab);
-
- platform_set_drvdata(pdev, NULL);
-
- kfree(ab->phy.otg);
- kfree(ab);
-
- return 0;
-}
-
-static struct platform_driver ab8500_usb_driver = {
- .probe = ab8500_usb_probe,
- .remove = ab8500_usb_remove,
- .driver = {
- .name = "ab8500-usb",
- .owner = THIS_MODULE,
- },
-};
-
-static int __init ab8500_usb_init(void)
-{
- return platform_driver_register(&ab8500_usb_driver);
-}
-subsys_initcall(ab8500_usb_init);
-
-static void __exit ab8500_usb_exit(void)
-{
- platform_driver_unregister(&ab8500_usb_driver);
-}
-module_exit(ab8500_usb_exit);
-
-MODULE_ALIAS("platform:ab8500_usb");
-MODULE_AUTHOR("ST-Ericsson AB");
-MODULE_DESCRIPTION("AB8500 usb transceiver driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig
index 65217a59006..aab2ab2fbc9 100644
--- a/drivers/usb/phy/Kconfig
+++ b/drivers/usb/phy/Kconfig
@@ -1,13 +1,74 @@
#
# Physical Layer USB driver configuration
#
-comment "USB Physical Layer drivers"
- depends on USB || USB_GADGET
+menuconfig USB_PHY
+ bool "USB Physical Layer drivers"
+ help
+ USB controllers (those which are host, device or DRD) need a
+ device to handle the physical layer signalling, commonly called
+ a PHY.
+
+ The following drivers add support for such PHY devices.
+
+if USB_PHY
+
+#
+# USB Transceiver Drivers
+#
+config AB8500_USB
+ tristate "AB8500 USB Transceiver Driver"
+ depends on AB8500_CORE
+ help
+ Enable this to support the USB OTG transceiver in AB8500 chip.
+ This transceiver supports high and full speed devices plus,
+ in host mode, low speed.
+
+config FSL_USB2_OTG
+ bool "Freescale USB OTG Transceiver Driver"
+ depends on USB_EHCI_FSL && USB_FSL_USB2 && USB_SUSPEND
+ select USB_OTG
+ help
+ Enable this to support Freescale USB OTG transceiver.
+
+config ISP1301_OMAP
+ tristate "Philips ISP1301 with OMAP OTG"
+ depends on I2C && ARCH_OMAP_OTG
+ help
+ If you say yes here you get support for the Philips ISP1301
+ USB-On-The-Go transceiver working with the OMAP OTG controller.
+ The ISP1301 is a full speed USB transceiver which is used in
+ products including H2, H3, and H4 development boards for Texas
+ Instruments OMAP processors.
+
+ This driver can also be built as a module. If so, the module
+ will be called isp1301_omap.
+
+config MV_U3D_PHY
+ bool "Marvell USB 3.0 PHY controller Driver"
+ depends on CPU_MMP3
+ help
+ Enable this to support Marvell USB 3.0 phy controller for Marvell
+ SoC.
+
+config NOP_USB_XCEIV
+ tristate "NOP USB Transceiver Driver"
+ help
+ This driver is to be used by all the usb transceiver which are either
+ built-in with usb ip or which are autonomous and doesn't require any
+ phy programming such as ISP1x04 etc.
+
+config OMAP_CONTROL_USB
+ tristate "OMAP CONTROL USB Driver"
+ help
+ Enable this to add support for the USB part present in the control
+ module. This driver has API to power on the USB2 PHY and to write to
+ the mailbox. The mailbox is present only in omap4 and the register to
+ power on the USB2 PHY is present in OMAP4 and OMAP5. OMAP5 has an
+ additional register to power on USB3 PHY.
config OMAP_USB2
tristate "OMAP USB2 PHY Driver"
depends on ARCH_OMAP2PLUS
- select USB_OTG_UTILS
select OMAP_CONTROL_USB
help
Enable this to support the transceiver that is part of SOC. This
@@ -17,7 +78,6 @@ config OMAP_USB2
config OMAP_USB3
tristate "OMAP USB3 PHY Driver"
- select USB_OTG_UTILS
select OMAP_CONTROL_USB
help
Enable this to support the USB3 PHY that is part of SOC. This
@@ -25,19 +85,61 @@ config OMAP_USB3
This driver interacts with the "OMAP Control USB Driver" to power
on/off the PHY.
-config OMAP_CONTROL_USB
- tristate "OMAP CONTROL USB Driver"
+config SAMSUNG_USBPHY
+ tristate "Samsung USB PHY Driver"
help
- Enable this to add support for the USB part present in the control
- module. This driver has API to power on the USB2 PHY and to write to
- the mailbox. The mailbox is present only in omap4 and the register to
- power on the USB2 PHY is present in OMAP4 and OMAP5. OMAP5 has an
- additional register to power on USB3 PHY.
+ Enable this to support Samsung USB phy helper driver for Samsung SoCs.
+ This driver provides common interface to interact, for Samsung USB 2.0 PHY
+ driver and later for Samsung USB 3.0 PHY driver.
+
+config SAMSUNG_USB2PHY
+ tristate "Samsung USB 2.0 PHY controller Driver"
+ select SAMSUNG_USBPHY
+ help
+ Enable this to support Samsung USB 2.0 (High Speed) PHY controller
+ driver for Samsung SoCs.
+
+config SAMSUNG_USB3PHY
+ tristate "Samsung USB 3.0 PHY controller Driver"
+ select SAMSUNG_USBPHY
+ help
+ Enable this to support Samsung USB 3.0 (Super Speed) phy controller
+ for samsung SoCs.
+
+config TWL4030_USB
+ tristate "TWL4030 USB Transceiver Driver"
+ depends on TWL4030_CORE && REGULATOR_TWL4030 && USB_MUSB_OMAP2PLUS
+ help
+ Enable this to support the USB OTG transceiver on TWL4030
+ family chips (including the TWL5030 and TPS659x0 devices).
+ This transceiver supports high and full speed devices plus,
+ in host mode, low speed.
+
+config TWL6030_USB
+ tristate "TWL6030 USB Transceiver Driver"
+ depends on TWL4030_CORE && OMAP_USB2 && USB_MUSB_OMAP2PLUS
+ help
+ Enable this to support the USB OTG transceiver on TWL6030
+ family chips. This TWL6030 transceiver has the VBUS and ID GND
+ and OTG SRP events capabilities. For all other transceiver functionality
+ UTMI PHY is embedded in OMAP4430. The internal PHY configurations APIs
+ are hooked to this driver through platform_data structure.
+ The definition of internal PHY APIs are in the mach-omap2 layer.
+
+config USB_GPIO_VBUS
+ tristate "GPIO based peripheral-only VBUS sensing 'transceiver'"
+ depends on GENERIC_GPIO
+ help
+ Provides simple GPIO VBUS sensing for controllers with an
+ internal transceiver via the usb_phy interface, and
+ optionally control of a D+ pullup GPIO as well as a VBUS
+ current limit regulator.
config USB_ISP1301
tristate "NXP ISP1301 USB transceiver support"
depends on USB || USB_GADGET
depends on I2C
+ select USB_OTG_UTILS
help
Say Y here to add support for the NXP ISP1301 USB transceiver driver.
This chip is typically used as USB transceiver for USB host, gadget
@@ -46,18 +148,41 @@ config USB_ISP1301
To compile this driver as a module, choose M here: the
module will be called isp1301.
-config MV_U3D_PHY
- bool "Marvell USB 3.0 PHY controller Driver"
- depends on USB_MV_U3D
- select USB_OTG_UTILS
+config USB_MSM_OTG
+ tristate "OTG support for Qualcomm on-chip USB controller"
+ depends on (USB || USB_GADGET) && ARCH_MSM
help
- Enable this to support Marvell USB 3.0 phy controller for Marvell
- SoC.
+ Enable this to support the USB OTG transceiver on MSM chips. It
+ handles PHY initialization, clock management, and workarounds
+ required after resetting the hardware and power management.
+ This driver is required even for peripheral only or host only
+ mode configurations.
+ This driver is not supported on boards like trout which
+ has an external PHY.
+
+config USB_MV_OTG
+ tristate "Marvell USB OTG support"
+ depends on USB_EHCI_MV && USB_MV_UDC && USB_SUSPEND
+ select USB_OTG
+ help
+ Say Y here if you want to build Marvell USB OTG transciever
+ driver in kernel (including PXA and MMP series). This driver
+ implements role switch between EHCI host driver and gadget driver.
+
+ To compile this driver as a module, choose M here.
+
+config USB_MXS_PHY
+ tristate "Freescale MXS USB PHY support"
+ depends on ARCH_MXC || ARCH_MXS
+ select STMP_DEVICE
+ help
+ Enable this to support the Freescale MXS USB PHY.
+
+ MXS Phy is used by some of the i.MX SoCs, for example imx23/28/6x.
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.
@@ -66,10 +191,18 @@ config USB_RCAR_PHY
To compile this driver as a module, choose M here: the
module will be called rcar-phy.
-config SAMSUNG_USBPHY
- bool "Samsung USB PHY controller Driver"
- depends on USB_S3C_HSOTG || USB_EHCI_S5P || USB_OHCI_EXYNOS
- select USB_OTG_UTILS
+config USB_ULPI
+ bool "Generic ULPI Transceiver Driver"
+ depends on ARM
+ help
+ Enable this to support ULPI connected USB OTG transceivers which
+ are likely found on embedded boards.
+
+config USB_ULPI_VIEWPORT
+ bool
+ depends on USB_ULPI
help
- Enable this to support Samsung USB phy controller for samsung
- SoCs.
+ Provides read/write operations to the ULPI phy register set for
+ controllers with a viewport register (e.g. Chipidea/ARC controllers).
+
+endif # USB_PHY
diff --git a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile
index b13faa193e0..a9169cb1e6f 100644
--- a/drivers/usb/phy/Makefile
+++ b/drivers/usb/phy/Makefile
@@ -4,11 +4,30 @@
ccflags-$(CONFIG_USB_DEBUG) := -DDEBUG
-obj-$(CONFIG_OMAP_USB2) += omap-usb2.o
-obj-$(CONFIG_OMAP_USB3) += omap-usb3.o
-obj-$(CONFIG_OMAP_CONTROL_USB) += omap-control-usb.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
-obj-$(CONFIG_SAMSUNG_USBPHY) += samsung-usbphy.o
+obj-$(CONFIG_USB_PHY) += phy.o
+
+# transceiver drivers, keep the list sorted
+
+obj-$(CONFIG_AB8500_USB) += phy-ab8500-usb.o
+phy-fsl-usb2-objs := phy-fsl-usb.o phy-fsm-usb.o
+obj-$(CONFIG_FSL_USB2_OTG) += phy-fsl-usb2.o
+obj-$(CONFIG_ISP1301_OMAP) += phy-isp1301-omap.o
+obj-$(CONFIG_MV_U3D_PHY) += phy-mv-u3d-usb.o
+obj-$(CONFIG_NOP_USB_XCEIV) += phy-nop.o
+obj-$(CONFIG_OMAP_CONTROL_USB) += phy-omap-control.o
+obj-$(CONFIG_OMAP_USB2) += phy-omap-usb2.o
+obj-$(CONFIG_OMAP_USB3) += phy-omap-usb3.o
+obj-$(CONFIG_SAMSUNG_USBPHY) += phy-samsung-usb.o
+obj-$(CONFIG_SAMSUNG_USB2PHY) += phy-samsung-usb2.o
+obj-$(CONFIG_SAMSUNG_USB3PHY) += phy-samsung-usb3.o
+obj-$(CONFIG_TWL4030_USB) += phy-twl4030-usb.o
+obj-$(CONFIG_TWL6030_USB) += phy-twl6030-usb.o
+obj-$(CONFIG_USB_EHCI_TEGRA) += phy-tegra-usb.o
+obj-$(CONFIG_USB_GPIO_VBUS) += phy-gpio-vbus-usb.o
+obj-$(CONFIG_USB_ISP1301) += phy-isp1301.o
+obj-$(CONFIG_USB_MSM_OTG) += phy-msm-usb.o
+obj-$(CONFIG_USB_MV_OTG) += phy-mv-usb.o
+obj-$(CONFIG_USB_MXS_PHY) += phy-mxs-usb.o
+obj-$(CONFIG_USB_RCAR_PHY) += phy-rcar-usb.o
+obj-$(CONFIG_USB_ULPI) += phy-ulpi.o
+obj-$(CONFIG_USB_ULPI_VIEWPORT) += phy-ulpi-viewport.o
diff --git a/drivers/usb/phy/isp1301.c b/drivers/usb/phy/isp1301.c
deleted file mode 100644
index 18dbf7e3760..00000000000
--- a/drivers/usb/phy/isp1301.c
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * NXP ISP1301 USB transceiver driver
- *
- * Copyright (C) 2012 Roland Stigge
- *
- * Author: Roland Stigge <stigge@antcom.de>
- *
- * 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/module.h>
-#include <linux/i2c.h>
-
-#define DRV_NAME "isp1301"
-
-static const struct i2c_device_id isp1301_id[] = {
- { "isp1301", 0 },
- { }
-};
-
-static struct i2c_client *isp1301_i2c_client;
-
-static int isp1301_probe(struct i2c_client *client,
- const struct i2c_device_id *i2c_id)
-{
- isp1301_i2c_client = client;
- return 0;
-}
-
-static int isp1301_remove(struct i2c_client *client)
-{
- return 0;
-}
-
-static struct i2c_driver isp1301_driver = {
- .driver = {
- .name = DRV_NAME,
- },
- .probe = isp1301_probe,
- .remove = isp1301_remove,
- .id_table = isp1301_id,
-};
-
-module_i2c_driver(isp1301_driver);
-
-static int match(struct device *dev, void *data)
-{
- struct device_node *node = (struct device_node *)data;
- return (dev->of_node == node) &&
- (dev->driver == &isp1301_driver.driver);
-}
-
-struct i2c_client *isp1301_get_client(struct device_node *node)
-{
- if (node) { /* reference of ISP1301 I2C node via DT */
- struct device *dev = bus_find_device(&i2c_bus_type, NULL,
- node, match);
- if (!dev)
- return NULL;
- return to_i2c_client(dev);
- } else { /* non-DT: only one ISP1301 chip supported */
- return isp1301_i2c_client;
- }
-}
-EXPORT_SYMBOL_GPL(isp1301_get_client);
-
-MODULE_AUTHOR("Roland Stigge <stigge@antcom.de>");
-MODULE_DESCRIPTION("NXP ISP1301 USB transceiver driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/usb/phy/phy-ab8500-usb.c b/drivers/usb/phy/phy-ab8500-usb.c
new file mode 100644
index 00000000000..4acef26a2ef
--- /dev/null
+++ b/drivers/usb/phy/phy-ab8500-usb.c
@@ -0,0 +1,924 @@
+/*
+ * drivers/usb/otg/ab8500_usb.c
+ *
+ * USB transceiver driver for AB8500 chip
+ *
+ * Copyright (C) 2010 ST-Ericsson AB
+ * Mian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/usb/otg.h>
+#include <linux/slab.h>
+#include <linux/notifier.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/mfd/abx500.h>
+#include <linux/mfd/abx500/ab8500.h>
+#include <linux/usb/musb-ux500.h>
+#include <linux/regulator/consumer.h>
+#include <linux/pinctrl/consumer.h>
+
+/* Bank AB8500_SYS_CTRL2_BLOCK */
+#define AB8500_MAIN_WD_CTRL_REG 0x01
+
+/* Bank AB8500_USB */
+#define AB8500_USB_LINE_STAT_REG 0x80
+#define AB8505_USB_LINE_STAT_REG 0x94
+#define AB8500_USB_PHY_CTRL_REG 0x8A
+
+/* Bank AB8500_DEVELOPMENT */
+#define AB8500_BANK12_ACCESS 0x00
+
+/* Bank AB8500_DEBUG */
+#define AB8500_USB_PHY_TUNE1 0x05
+#define AB8500_USB_PHY_TUNE2 0x06
+#define AB8500_USB_PHY_TUNE3 0x07
+
+#define AB8500_BIT_OTG_STAT_ID (1 << 0)
+#define AB8500_BIT_PHY_CTRL_HOST_EN (1 << 0)
+#define AB8500_BIT_PHY_CTRL_DEVICE_EN (1 << 1)
+#define AB8500_BIT_WD_CTRL_ENABLE (1 << 0)
+#define AB8500_BIT_WD_CTRL_KICK (1 << 1)
+
+#define AB8500_WD_KICK_DELAY_US 100 /* usec */
+#define AB8500_WD_V11_DISABLE_DELAY_US 100 /* usec */
+#define AB8500_V20_31952_DISABLE_DELAY_US 100 /* usec */
+
+/* Usb line status register */
+enum ab8500_usb_link_status {
+ USB_LINK_NOT_CONFIGURED_8500 = 0,
+ USB_LINK_STD_HOST_NC_8500,
+ USB_LINK_STD_HOST_C_NS_8500,
+ USB_LINK_STD_HOST_C_S_8500,
+ USB_LINK_HOST_CHG_NM_8500,
+ USB_LINK_HOST_CHG_HS_8500,
+ USB_LINK_HOST_CHG_HS_CHIRP_8500,
+ USB_LINK_DEDICATED_CHG_8500,
+ USB_LINK_ACA_RID_A_8500,
+ USB_LINK_ACA_RID_B_8500,
+ USB_LINK_ACA_RID_C_NM_8500,
+ USB_LINK_ACA_RID_C_HS_8500,
+ USB_LINK_ACA_RID_C_HS_CHIRP_8500,
+ USB_LINK_HM_IDGND_8500,
+ USB_LINK_RESERVED_8500,
+ USB_LINK_NOT_VALID_LINK_8500,
+};
+
+enum ab8505_usb_link_status {
+ USB_LINK_NOT_CONFIGURED_8505 = 0,
+ USB_LINK_STD_HOST_NC_8505,
+ USB_LINK_STD_HOST_C_NS_8505,
+ USB_LINK_STD_HOST_C_S_8505,
+ USB_LINK_CDP_8505,
+ USB_LINK_RESERVED0_8505,
+ USB_LINK_RESERVED1_8505,
+ USB_LINK_DEDICATED_CHG_8505,
+ USB_LINK_ACA_RID_A_8505,
+ USB_LINK_ACA_RID_B_8505,
+ USB_LINK_ACA_RID_C_NM_8505,
+ USB_LINK_RESERVED2_8505,
+ USB_LINK_RESERVED3_8505,
+ USB_LINK_HM_IDGND_8505,
+ USB_LINK_CHARGERPORT_NOT_OK_8505,
+ USB_LINK_CHARGER_DM_HIGH_8505,
+ USB_LINK_PHYEN_NO_VBUS_NO_IDGND_8505,
+ USB_LINK_STD_UPSTREAM_NO_IDGNG_NO_VBUS_8505,
+ USB_LINK_STD_UPSTREAM_8505,
+ USB_LINK_CHARGER_SE1_8505,
+ USB_LINK_CARKIT_CHGR_1_8505,
+ USB_LINK_CARKIT_CHGR_2_8505,
+ USB_LINK_ACA_DOCK_CHGR_8505,
+ USB_LINK_SAMSUNG_BOOT_CBL_PHY_EN_8505,
+ USB_LINK_SAMSUNG_BOOT_CBL_PHY_DISB_8505,
+ USB_LINK_SAMSUNG_UART_CBL_PHY_EN_8505,
+ USB_LINK_SAMSUNG_UART_CBL_PHY_DISB_8505,
+ USB_LINK_MOTOROLA_FACTORY_CBL_PHY_EN_8505,
+};
+
+enum ab8500_usb_mode {
+ USB_IDLE = 0,
+ USB_PERIPHERAL,
+ USB_HOST,
+ USB_DEDICATED_CHG
+};
+
+struct ab8500_usb {
+ struct usb_phy phy;
+ struct device *dev;
+ struct ab8500 *ab8500;
+ unsigned vbus_draw;
+ struct work_struct phy_dis_work;
+ enum ab8500_usb_mode mode;
+ struct regulator *v_ape;
+ struct regulator *v_musb;
+ struct regulator *v_ulpi;
+ int saved_v_ulpi;
+ int previous_link_status_state;
+ struct pinctrl *pinctrl;
+ struct pinctrl_state *pins_sleep;
+};
+
+static inline struct ab8500_usb *phy_to_ab(struct usb_phy *x)
+{
+ return container_of(x, struct ab8500_usb, phy);
+}
+
+static void ab8500_usb_wd_workaround(struct ab8500_usb *ab)
+{
+ abx500_set_register_interruptible(ab->dev,
+ AB8500_SYS_CTRL2_BLOCK,
+ AB8500_MAIN_WD_CTRL_REG,
+ AB8500_BIT_WD_CTRL_ENABLE);
+
+ udelay(AB8500_WD_KICK_DELAY_US);
+
+ abx500_set_register_interruptible(ab->dev,
+ AB8500_SYS_CTRL2_BLOCK,
+ AB8500_MAIN_WD_CTRL_REG,
+ (AB8500_BIT_WD_CTRL_ENABLE
+ | AB8500_BIT_WD_CTRL_KICK));
+
+ udelay(AB8500_WD_V11_DISABLE_DELAY_US);
+
+ abx500_set_register_interruptible(ab->dev,
+ AB8500_SYS_CTRL2_BLOCK,
+ AB8500_MAIN_WD_CTRL_REG,
+ 0);
+}
+
+static void ab8500_usb_regulator_enable(struct ab8500_usb *ab)
+{
+ int ret, volt;
+
+ ret = regulator_enable(ab->v_ape);
+ if (ret)
+ dev_err(ab->dev, "Failed to enable v-ape\n");
+
+ if (!is_ab8500_2p0_or_earlier(ab->ab8500)) {
+ ab->saved_v_ulpi = regulator_get_voltage(ab->v_ulpi);
+ if (ab->saved_v_ulpi < 0)
+ dev_err(ab->dev, "Failed to get v_ulpi voltage\n");
+
+ ret = regulator_set_voltage(ab->v_ulpi, 1300000, 1350000);
+ if (ret < 0)
+ dev_err(ab->dev, "Failed to set the Vintcore to 1.3V, ret=%d\n",
+ ret);
+
+ ret = regulator_set_optimum_mode(ab->v_ulpi, 28000);
+ if (ret < 0)
+ dev_err(ab->dev, "Failed to set optimum mode (ret=%d)\n",
+ ret);
+ }
+
+ ret = regulator_enable(ab->v_ulpi);
+ if (ret)
+ dev_err(ab->dev, "Failed to enable vddulpivio18\n");
+
+ if (!is_ab8500_2p0_or_earlier(ab->ab8500)) {
+ volt = regulator_get_voltage(ab->v_ulpi);
+ if ((volt != 1300000) && (volt != 1350000))
+ dev_err(ab->dev, "Vintcore is not set to 1.3V volt=%d\n",
+ volt);
+ }
+
+ ret = regulator_enable(ab->v_musb);
+ if (ret)
+ dev_err(ab->dev, "Failed to enable musb_1v8\n");
+}
+
+static void ab8500_usb_regulator_disable(struct ab8500_usb *ab)
+{
+ int ret;
+
+ regulator_disable(ab->v_musb);
+
+ regulator_disable(ab->v_ulpi);
+
+ /* USB is not the only consumer of Vintcore, restore old settings */
+ if (!is_ab8500_2p0_or_earlier(ab->ab8500)) {
+ if (ab->saved_v_ulpi > 0) {
+ ret = regulator_set_voltage(ab->v_ulpi,
+ ab->saved_v_ulpi, ab->saved_v_ulpi);
+ if (ret < 0)
+ dev_err(ab->dev, "Failed to set the Vintcore to %duV, ret=%d\n",
+ ab->saved_v_ulpi, ret);
+ }
+
+ ret = regulator_set_optimum_mode(ab->v_ulpi, 0);
+ if (ret < 0)
+ dev_err(ab->dev, "Failed to set optimum mode (ret=%d)\n",
+ ret);
+ }
+
+ regulator_disable(ab->v_ape);
+}
+
+static void ab8500_usb_wd_linkstatus(struct ab8500_usb *ab, u8 bit)
+{
+ /* Workaround for v2.0 bug # 31952 */
+ if (is_ab8500_2p0(ab->ab8500)) {
+ abx500_mask_and_set_register_interruptible(ab->dev,
+ AB8500_USB, AB8500_USB_PHY_CTRL_REG,
+ bit, bit);
+ udelay(AB8500_V20_31952_DISABLE_DELAY_US);
+ }
+}
+
+static void ab8500_usb_phy_enable(struct ab8500_usb *ab, bool sel_host)
+{
+ u8 bit;
+ bit = sel_host ? AB8500_BIT_PHY_CTRL_HOST_EN :
+ AB8500_BIT_PHY_CTRL_DEVICE_EN;
+
+ /* mux and configure USB pins to DEFAULT state */
+ ab->pinctrl = pinctrl_get_select(ab->dev, PINCTRL_STATE_DEFAULT);
+ if (IS_ERR(ab->pinctrl))
+ dev_err(ab->dev, "could not get/set default pinstate\n");
+
+ ab8500_usb_regulator_enable(ab);
+
+ abx500_mask_and_set_register_interruptible(ab->dev,
+ AB8500_USB, AB8500_USB_PHY_CTRL_REG,
+ bit, bit);
+}
+
+static void ab8500_usb_phy_disable(struct ab8500_usb *ab, bool sel_host)
+{
+ u8 bit;
+ bit = sel_host ? AB8500_BIT_PHY_CTRL_HOST_EN :
+ AB8500_BIT_PHY_CTRL_DEVICE_EN;
+
+ ab8500_usb_wd_linkstatus(ab, bit);
+
+ abx500_mask_and_set_register_interruptible(ab->dev,
+ AB8500_USB, AB8500_USB_PHY_CTRL_REG,
+ bit, 0);
+
+ /* Needed to disable the phy.*/
+ ab8500_usb_wd_workaround(ab);
+
+ ab8500_usb_regulator_disable(ab);
+
+ if (!IS_ERR(ab->pinctrl)) {
+ /* configure USB pins to SLEEP state */
+ ab->pins_sleep = pinctrl_lookup_state(ab->pinctrl,
+ PINCTRL_STATE_SLEEP);
+
+ if (IS_ERR(ab->pins_sleep))
+ dev_dbg(ab->dev, "could not get sleep pinstate\n");
+ else if (pinctrl_select_state(ab->pinctrl, ab->pins_sleep))
+ dev_err(ab->dev, "could not set pins to sleep state\n");
+
+ /* as USB pins are shared with idddet, release them to allow
+ * iddet to request them
+ */
+ pinctrl_put(ab->pinctrl);
+ }
+}
+
+#define ab8500_usb_host_phy_en(ab) ab8500_usb_phy_enable(ab, true)
+#define ab8500_usb_host_phy_dis(ab) ab8500_usb_phy_disable(ab, true)
+#define ab8500_usb_peri_phy_en(ab) ab8500_usb_phy_enable(ab, false)
+#define ab8500_usb_peri_phy_dis(ab) ab8500_usb_phy_disable(ab, false)
+
+static int ab8505_usb_link_status_update(struct ab8500_usb *ab,
+ enum ab8505_usb_link_status lsts)
+{
+ enum ux500_musb_vbus_id_status event = 0;
+
+ dev_dbg(ab->dev, "ab8505_usb_link_status_update %d\n", lsts);
+
+ /*
+ * Spurious link_status interrupts are seen at the time of
+ * disconnection of a device in RIDA state
+ */
+ if (ab->previous_link_status_state == USB_LINK_ACA_RID_A_8505 &&
+ (lsts == USB_LINK_STD_HOST_NC_8505))
+ return 0;
+
+ ab->previous_link_status_state = lsts;
+
+ switch (lsts) {
+ case USB_LINK_ACA_RID_B_8505:
+ event = UX500_MUSB_RIDB;
+ case USB_LINK_NOT_CONFIGURED_8505:
+ case USB_LINK_RESERVED0_8505:
+ case USB_LINK_RESERVED1_8505:
+ case USB_LINK_RESERVED2_8505:
+ case USB_LINK_RESERVED3_8505:
+ ab->mode = USB_IDLE;
+ ab->phy.otg->default_a = false;
+ ab->vbus_draw = 0;
+ if (event != UX500_MUSB_RIDB)
+ event = UX500_MUSB_NONE;
+ /*
+ * Fallback to default B_IDLE as nothing
+ * is connected
+ */
+ ab->phy.state = OTG_STATE_B_IDLE;
+ break;
+
+ case USB_LINK_ACA_RID_C_NM_8505:
+ event = UX500_MUSB_RIDC;
+ case USB_LINK_STD_HOST_NC_8505:
+ case USB_LINK_STD_HOST_C_NS_8505:
+ case USB_LINK_STD_HOST_C_S_8505:
+ case USB_LINK_CDP_8505:
+ if (ab->mode == USB_IDLE) {
+ ab->mode = USB_PERIPHERAL;
+ ab8500_usb_peri_phy_en(ab);
+ atomic_notifier_call_chain(&ab->phy.notifier,
+ UX500_MUSB_PREPARE, &ab->vbus_draw);
+ }
+ if (event != UX500_MUSB_RIDC)
+ event = UX500_MUSB_VBUS;
+ break;
+
+ case USB_LINK_ACA_RID_A_8505:
+ case USB_LINK_ACA_DOCK_CHGR_8505:
+ event = UX500_MUSB_RIDA;
+ case USB_LINK_HM_IDGND_8505:
+ if (ab->mode == USB_IDLE) {
+ ab->mode = USB_HOST;
+ ab8500_usb_host_phy_en(ab);
+ atomic_notifier_call_chain(&ab->phy.notifier,
+ UX500_MUSB_PREPARE, &ab->vbus_draw);
+ }
+ ab->phy.otg->default_a = true;
+ if (event != UX500_MUSB_RIDA)
+ event = UX500_MUSB_ID;
+ atomic_notifier_call_chain(&ab->phy.notifier,
+ event, &ab->vbus_draw);
+ break;
+
+ case USB_LINK_DEDICATED_CHG_8505:
+ ab->mode = USB_DEDICATED_CHG;
+ event = UX500_MUSB_CHARGER;
+ atomic_notifier_call_chain(&ab->phy.notifier,
+ event, &ab->vbus_draw);
+ break;
+
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int ab8500_usb_link_status_update(struct ab8500_usb *ab,
+ enum ab8500_usb_link_status lsts)
+{
+ enum ux500_musb_vbus_id_status event = 0;
+
+ dev_dbg(ab->dev, "ab8500_usb_link_status_update %d\n", lsts);
+
+ /*
+ * Spurious link_status interrupts are seen in case of a
+ * disconnection of a device in IDGND and RIDA stage
+ */
+ if (ab->previous_link_status_state == USB_LINK_HM_IDGND_8500 &&
+ (lsts == USB_LINK_STD_HOST_C_NS_8500 ||
+ lsts == USB_LINK_STD_HOST_NC_8500))
+ return 0;
+
+ if (ab->previous_link_status_state == USB_LINK_ACA_RID_A_8500 &&
+ lsts == USB_LINK_STD_HOST_NC_8500)
+ return 0;
+
+ ab->previous_link_status_state = lsts;
+
+ switch (lsts) {
+ case USB_LINK_ACA_RID_B_8500:
+ event = UX500_MUSB_RIDB;
+ case USB_LINK_NOT_CONFIGURED_8500:
+ case USB_LINK_NOT_VALID_LINK_8500:
+ ab->mode = USB_IDLE;
+ ab->phy.otg->default_a = false;
+ ab->vbus_draw = 0;
+ if (event != UX500_MUSB_RIDB)
+ event = UX500_MUSB_NONE;
+ /* Fallback to default B_IDLE as nothing is connected */
+ ab->phy.state = OTG_STATE_B_IDLE;
+ break;
+
+ case USB_LINK_ACA_RID_C_NM_8500:
+ case USB_LINK_ACA_RID_C_HS_8500:
+ case USB_LINK_ACA_RID_C_HS_CHIRP_8500:
+ event = UX500_MUSB_RIDC;
+ case USB_LINK_STD_HOST_NC_8500:
+ case USB_LINK_STD_HOST_C_NS_8500:
+ case USB_LINK_STD_HOST_C_S_8500:
+ case USB_LINK_HOST_CHG_NM_8500:
+ case USB_LINK_HOST_CHG_HS_8500:
+ case USB_LINK_HOST_CHG_HS_CHIRP_8500:
+ if (ab->mode == USB_IDLE) {
+ ab->mode = USB_PERIPHERAL;
+ ab8500_usb_peri_phy_en(ab);
+ atomic_notifier_call_chain(&ab->phy.notifier,
+ UX500_MUSB_PREPARE, &ab->vbus_draw);
+ }
+ if (event != UX500_MUSB_RIDC)
+ event = UX500_MUSB_VBUS;
+ break;
+
+ case USB_LINK_ACA_RID_A_8500:
+ event = UX500_MUSB_RIDA;
+ case USB_LINK_HM_IDGND_8500:
+ if (ab->mode == USB_IDLE) {
+ ab->mode = USB_HOST;
+ ab8500_usb_host_phy_en(ab);
+ atomic_notifier_call_chain(&ab->phy.notifier,
+ UX500_MUSB_PREPARE, &ab->vbus_draw);
+ }
+ ab->phy.otg->default_a = true;
+ if (event != UX500_MUSB_RIDA)
+ event = UX500_MUSB_ID;
+ atomic_notifier_call_chain(&ab->phy.notifier,
+ event, &ab->vbus_draw);
+ break;
+
+ case USB_LINK_DEDICATED_CHG_8500:
+ ab->mode = USB_DEDICATED_CHG;
+ event = UX500_MUSB_CHARGER;
+ atomic_notifier_call_chain(&ab->phy.notifier,
+ event, &ab->vbus_draw);
+ break;
+
+ case USB_LINK_RESERVED_8500:
+ break;
+ }
+
+ return 0;
+}
+
+/*
+ * Connection Sequence:
+ * 1. Link Status Interrupt
+ * 2. Enable AB clock
+ * 3. Enable AB regulators
+ * 4. Enable USB phy
+ * 5. Reset the musb controller
+ * 6. Switch the ULPI GPIO pins to fucntion mode
+ * 7. Enable the musb Peripheral5 clock
+ * 8. Restore MUSB context
+ */
+static int abx500_usb_link_status_update(struct ab8500_usb *ab)
+{
+ u8 reg;
+ int ret = 0;
+
+ if (is_ab8500(ab->ab8500)) {
+ enum ab8500_usb_link_status lsts;
+
+ abx500_get_register_interruptible(ab->dev,
+ AB8500_USB, AB8500_USB_LINE_STAT_REG, &reg);
+ lsts = (reg >> 3) & 0x0F;
+ ret = ab8500_usb_link_status_update(ab, lsts);
+ } else if (is_ab8505(ab->ab8500)) {
+ enum ab8505_usb_link_status lsts;
+
+ abx500_get_register_interruptible(ab->dev,
+ AB8500_USB, AB8505_USB_LINE_STAT_REG, &reg);
+ lsts = (reg >> 3) & 0x1F;
+ ret = ab8505_usb_link_status_update(ab, lsts);
+ }
+
+ return ret;
+}
+
+/*
+ * Disconnection Sequence:
+ * 1. Disconect Interrupt
+ * 2. Disable regulators
+ * 3. Disable AB clock
+ * 4. Disable the Phy
+ * 5. Link Status Interrupt
+ * 6. Disable Musb Clock
+ */
+static irqreturn_t ab8500_usb_disconnect_irq(int irq, void *data)
+{
+ struct ab8500_usb *ab = (struct ab8500_usb *) data;
+ enum usb_phy_events event = UX500_MUSB_NONE;
+
+ /* Link status will not be updated till phy is disabled. */
+ if (ab->mode == USB_HOST) {
+ ab->phy.otg->default_a = false;
+ ab->vbus_draw = 0;
+ atomic_notifier_call_chain(&ab->phy.notifier,
+ event, &ab->vbus_draw);
+ ab8500_usb_host_phy_dis(ab);
+ ab->mode = USB_IDLE;
+ }
+
+ if (ab->mode == USB_PERIPHERAL) {
+ atomic_notifier_call_chain(&ab->phy.notifier,
+ event, &ab->vbus_draw);
+ ab8500_usb_peri_phy_dis(ab);
+ atomic_notifier_call_chain(&ab->phy.notifier,
+ UX500_MUSB_CLEAN, &ab->vbus_draw);
+ ab->mode = USB_IDLE;
+ ab->phy.otg->default_a = false;
+ ab->vbus_draw = 0;
+ }
+
+ if (is_ab8500_2p0(ab->ab8500)) {
+ if (ab->mode == USB_DEDICATED_CHG) {
+ ab8500_usb_wd_linkstatus(ab,
+ AB8500_BIT_PHY_CTRL_DEVICE_EN);
+ abx500_mask_and_set_register_interruptible(ab->dev,
+ AB8500_USB, AB8500_USB_PHY_CTRL_REG,
+ AB8500_BIT_PHY_CTRL_DEVICE_EN, 0);
+ }
+ }
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t ab8500_usb_link_status_irq(int irq, void *data)
+{
+ struct ab8500_usb *ab = (struct ab8500_usb *) data;
+
+ abx500_usb_link_status_update(ab);
+
+ return IRQ_HANDLED;
+}
+
+static void ab8500_usb_phy_disable_work(struct work_struct *work)
+{
+ struct ab8500_usb *ab = container_of(work, struct ab8500_usb,
+ phy_dis_work);
+
+ if (!ab->phy.otg->host)
+ ab8500_usb_host_phy_dis(ab);
+
+ if (!ab->phy.otg->gadget)
+ ab8500_usb_peri_phy_dis(ab);
+}
+
+static unsigned ab8500_eyediagram_workaroud(struct ab8500_usb *ab, unsigned mA)
+{
+ /*
+ * AB8500 V2 has eye diagram issues when drawing more than 100mA from
+ * VBUS. Set charging current to 100mA in case of standard host
+ */
+ if (is_ab8500_2p0_or_earlier(ab->ab8500))
+ if (mA > 100)
+ mA = 100;
+
+ return mA;
+}
+
+static int ab8500_usb_set_power(struct usb_phy *phy, unsigned mA)
+{
+ struct ab8500_usb *ab;
+
+ if (!phy)
+ return -ENODEV;
+
+ ab = phy_to_ab(phy);
+
+ mA = ab8500_eyediagram_workaroud(ab, mA);
+
+ ab->vbus_draw = mA;
+
+ atomic_notifier_call_chain(&ab->phy.notifier,
+ UX500_MUSB_VBUS, &ab->vbus_draw);
+
+ return 0;
+}
+
+static int ab8500_usb_set_suspend(struct usb_phy *x, int suspend)
+{
+ /* TODO */
+ return 0;
+}
+
+static int ab8500_usb_set_peripheral(struct usb_otg *otg,
+ struct usb_gadget *gadget)
+{
+ struct ab8500_usb *ab;
+
+ if (!otg)
+ return -ENODEV;
+
+ ab = phy_to_ab(otg->phy);
+
+ ab->phy.otg->gadget = gadget;
+
+ /* Some drivers call this function in atomic context.
+ * Do not update ab8500 registers directly till this
+ * is fixed.
+ */
+
+ if ((ab->mode != USB_IDLE) && (!gadget)) {
+ ab->mode = USB_IDLE;
+ schedule_work(&ab->phy_dis_work);
+ }
+
+ return 0;
+}
+
+static int ab8500_usb_set_host(struct usb_otg *otg, struct usb_bus *host)
+{
+ struct ab8500_usb *ab;
+
+ if (!otg)
+ return -ENODEV;
+
+ ab = phy_to_ab(otg->phy);
+
+ ab->phy.otg->host = host;
+
+ /* Some drivers call this function in atomic context.
+ * Do not update ab8500 registers directly till this
+ * is fixed.
+ */
+
+ if ((ab->mode != USB_IDLE) && (!host)) {
+ ab->mode = USB_IDLE;
+ schedule_work(&ab->phy_dis_work);
+ }
+
+ return 0;
+}
+
+static int ab8500_usb_regulator_get(struct ab8500_usb *ab)
+{
+ int err;
+
+ ab->v_ape = devm_regulator_get(ab->dev, "v-ape");
+ if (IS_ERR(ab->v_ape)) {
+ dev_err(ab->dev, "Could not get v-ape supply\n");
+ err = PTR_ERR(ab->v_ape);
+ return err;
+ }
+
+ ab->v_ulpi = devm_regulator_get(ab->dev, "vddulpivio18");
+ if (IS_ERR(ab->v_ulpi)) {
+ dev_err(ab->dev, "Could not get vddulpivio18 supply\n");
+ err = PTR_ERR(ab->v_ulpi);
+ return err;
+ }
+
+ ab->v_musb = devm_regulator_get(ab->dev, "musb_1v8");
+ if (IS_ERR(ab->v_musb)) {
+ dev_err(ab->dev, "Could not get musb_1v8 supply\n");
+ err = PTR_ERR(ab->v_musb);
+ return err;
+ }
+
+ return 0;
+}
+
+static int ab8500_usb_irq_setup(struct platform_device *pdev,
+ struct ab8500_usb *ab)
+{
+ int err;
+ int irq;
+
+ irq = platform_get_irq_byname(pdev, "USB_LINK_STATUS");
+ if (irq < 0) {
+ dev_err(&pdev->dev, "Link status irq not found\n");
+ return irq;
+ }
+ err = devm_request_threaded_irq(&pdev->dev, irq, NULL,
+ ab8500_usb_link_status_irq,
+ IRQF_NO_SUSPEND | IRQF_SHARED, "usb-link-status", ab);
+ if (err < 0) {
+ dev_err(ab->dev, "request_irq failed for link status irq\n");
+ return err;
+ }
+
+ irq = platform_get_irq_byname(pdev, "ID_WAKEUP_F");
+ if (irq < 0) {
+ dev_err(&pdev->dev, "ID fall irq not found\n");
+ return irq;
+ }
+ err = devm_request_threaded_irq(&pdev->dev, irq, NULL,
+ ab8500_usb_disconnect_irq,
+ IRQF_NO_SUSPEND | IRQF_SHARED, "usb-id-fall", ab);
+ if (err < 0) {
+ dev_err(ab->dev, "request_irq failed for ID fall irq\n");
+ return err;
+ }
+
+ irq = platform_get_irq_byname(pdev, "VBUS_DET_F");
+ if (irq < 0) {
+ dev_err(&pdev->dev, "VBUS fall irq not found\n");
+ return irq;
+ }
+ err = devm_request_threaded_irq(&pdev->dev, irq, NULL,
+ ab8500_usb_disconnect_irq,
+ IRQF_NO_SUSPEND | IRQF_SHARED, "usb-vbus-fall", ab);
+ if (err < 0) {
+ dev_err(ab->dev, "request_irq failed for Vbus fall irq\n");
+ return err;
+ }
+
+ return 0;
+}
+
+static int ab8500_usb_probe(struct platform_device *pdev)
+{
+ struct ab8500_usb *ab;
+ struct ab8500 *ab8500;
+ struct usb_otg *otg;
+ int err;
+ int rev;
+
+ ab8500 = dev_get_drvdata(pdev->dev.parent);
+ rev = abx500_get_chip_id(&pdev->dev);
+
+ if (is_ab8500_1p1_or_earlier(ab8500)) {
+ dev_err(&pdev->dev, "Unsupported AB8500 chip rev=%d\n", rev);
+ return -ENODEV;
+ }
+
+ ab = devm_kzalloc(&pdev->dev, sizeof(*ab), GFP_KERNEL);
+ if (!ab)
+ return -ENOMEM;
+
+ otg = devm_kzalloc(&pdev->dev, sizeof(*otg), GFP_KERNEL);
+ if (!otg)
+ return -ENOMEM;
+
+ ab->dev = &pdev->dev;
+ ab->ab8500 = ab8500;
+ ab->phy.dev = ab->dev;
+ ab->phy.otg = otg;
+ ab->phy.label = "ab8500";
+ ab->phy.set_suspend = ab8500_usb_set_suspend;
+ ab->phy.set_power = ab8500_usb_set_power;
+ ab->phy.state = OTG_STATE_UNDEFINED;
+
+ otg->phy = &ab->phy;
+ otg->set_host = ab8500_usb_set_host;
+ otg->set_peripheral = ab8500_usb_set_peripheral;
+
+ platform_set_drvdata(pdev, ab);
+
+ ATOMIC_INIT_NOTIFIER_HEAD(&ab->phy.notifier);
+
+ /* all: Disable phy when called from set_host and set_peripheral */
+ INIT_WORK(&ab->phy_dis_work, ab8500_usb_phy_disable_work);
+
+ err = ab8500_usb_regulator_get(ab);
+ if (err)
+ return err;
+
+ err = ab8500_usb_irq_setup(pdev, ab);
+ if (err < 0)
+ return err;
+
+ err = usb_add_phy(&ab->phy, USB_PHY_TYPE_USB2);
+ if (err) {
+ dev_err(&pdev->dev, "Can't register transceiver\n");
+ return err;
+ }
+
+ /* Phy tuning values for AB8500 */
+ if (!is_ab8500_2p0_or_earlier(ab->ab8500)) {
+ /* Enable the PBT/Bank 0x12 access */
+ err = abx500_set_register_interruptible(ab->dev,
+ AB8500_DEVELOPMENT, AB8500_BANK12_ACCESS, 0x01);
+ if (err < 0)
+ dev_err(ab->dev, "Failed to enable bank12 access err=%d\n",
+ err);
+
+ err = abx500_set_register_interruptible(ab->dev,
+ AB8500_DEBUG, AB8500_USB_PHY_TUNE1, 0xC8);
+ if (err < 0)
+ dev_err(ab->dev, "Failed to set PHY_TUNE1 register err=%d\n",
+ err);
+
+ err = abx500_set_register_interruptible(ab->dev,
+ AB8500_DEBUG, AB8500_USB_PHY_TUNE2, 0x00);
+ if (err < 0)
+ dev_err(ab->dev, "Failed to set PHY_TUNE2 register err=%d\n",
+ err);
+
+ err = abx500_set_register_interruptible(ab->dev,
+ AB8500_DEBUG, AB8500_USB_PHY_TUNE3, 0x78);
+ if (err < 0)
+ dev_err(ab->dev, "Failed to set PHY_TUNE3 regester err=%d\n",
+ err);
+
+ /* Switch to normal mode/disable Bank 0x12 access */
+ err = abx500_set_register_interruptible(ab->dev,
+ AB8500_DEVELOPMENT, AB8500_BANK12_ACCESS, 0x00);
+ if (err < 0)
+ dev_err(ab->dev, "Failed to switch bank12 access err=%d\n",
+ err);
+ }
+
+ /* Phy tuning values for AB8505 */
+ if (is_ab8505(ab->ab8500)) {
+ /* Enable the PBT/Bank 0x12 access */
+ err = abx500_mask_and_set_register_interruptible(ab->dev,
+ AB8500_DEVELOPMENT, AB8500_BANK12_ACCESS,
+ 0x01, 0x01);
+ if (err < 0)
+ dev_err(ab->dev, "Failed to enable bank12 access err=%d\n",
+ err);
+
+ err = abx500_mask_and_set_register_interruptible(ab->dev,
+ AB8500_DEBUG, AB8500_USB_PHY_TUNE1,
+ 0xC8, 0xC8);
+ if (err < 0)
+ dev_err(ab->dev, "Failed to set PHY_TUNE1 register err=%d\n",
+ err);
+
+ err = abx500_mask_and_set_register_interruptible(ab->dev,
+ AB8500_DEBUG, AB8500_USB_PHY_TUNE2,
+ 0x60, 0x60);
+ if (err < 0)
+ dev_err(ab->dev, "Failed to set PHY_TUNE2 register err=%d\n",
+ err);
+
+ err = abx500_mask_and_set_register_interruptible(ab->dev,
+ AB8500_DEBUG, AB8500_USB_PHY_TUNE3,
+ 0xFC, 0x80);
+
+ if (err < 0)
+ dev_err(ab->dev, "Failed to set PHY_TUNE3 regester err=%d\n",
+ err);
+
+ /* Switch to normal mode/disable Bank 0x12 access */
+ err = abx500_mask_and_set_register_interruptible(ab->dev,
+ AB8500_DEVELOPMENT, AB8500_BANK12_ACCESS,
+ 0x00, 0x00);
+ if (err < 0)
+ dev_err(ab->dev, "Failed to switch bank12 access err=%d\n",
+ err);
+ }
+
+ /* Needed to enable ID detection. */
+ ab8500_usb_wd_workaround(ab);
+
+ abx500_usb_link_status_update(ab);
+
+ dev_info(&pdev->dev, "revision 0x%2x driver initialized\n", rev);
+
+ return 0;
+}
+
+static int ab8500_usb_remove(struct platform_device *pdev)
+{
+ struct ab8500_usb *ab = platform_get_drvdata(pdev);
+
+ cancel_work_sync(&ab->phy_dis_work);
+
+ usb_remove_phy(&ab->phy);
+
+ if (ab->mode == USB_HOST)
+ ab8500_usb_host_phy_dis(ab);
+ else if (ab->mode == USB_PERIPHERAL)
+ ab8500_usb_peri_phy_dis(ab);
+
+ platform_set_drvdata(pdev, NULL);
+
+ return 0;
+}
+
+static struct platform_driver ab8500_usb_driver = {
+ .probe = ab8500_usb_probe,
+ .remove = ab8500_usb_remove,
+ .driver = {
+ .name = "ab8500-usb",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init ab8500_usb_init(void)
+{
+ return platform_driver_register(&ab8500_usb_driver);
+}
+subsys_initcall(ab8500_usb_init);
+
+static void __exit ab8500_usb_exit(void)
+{
+ platform_driver_unregister(&ab8500_usb_driver);
+}
+module_exit(ab8500_usb_exit);
+
+MODULE_ALIAS("platform:ab8500_usb");
+MODULE_AUTHOR("ST-Ericsson AB");
+MODULE_DESCRIPTION("AB8500 usb transceiver driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/otg/fsl_otg.c b/drivers/usb/phy/phy-fsl-usb.c
index d16adb41eb2..97b9308507c 100644
--- a/drivers/usb/otg/fsl_otg.c
+++ b/drivers/usb/phy/phy-fsl-usb.c
@@ -43,7 +43,7 @@
#include <asm/unaligned.h>
-#include "fsl_otg.h"
+#include "phy-fsl-usb.h"
#define DRIVER_VERSION "Rev. 1.55"
#define DRIVER_AUTHOR "Jerry Huang/Li Yang"
@@ -361,28 +361,18 @@ int fsl_otg_init_timers(struct otg_fsm *fsm)
void fsl_otg_uninit_timers(void)
{
/* FSM used timers */
- if (a_wait_vrise_tmr != NULL)
- kfree(a_wait_vrise_tmr);
- if (a_wait_bcon_tmr != NULL)
- kfree(a_wait_bcon_tmr);
- if (a_aidl_bdis_tmr != NULL)
- kfree(a_aidl_bdis_tmr);
- if (b_ase0_brst_tmr != NULL)
- kfree(b_ase0_brst_tmr);
- if (b_se0_srp_tmr != NULL)
- kfree(b_se0_srp_tmr);
- if (b_srp_fail_tmr != NULL)
- kfree(b_srp_fail_tmr);
- if (a_wait_enum_tmr != NULL)
- kfree(a_wait_enum_tmr);
+ kfree(a_wait_vrise_tmr);
+ kfree(a_wait_bcon_tmr);
+ kfree(a_aidl_bdis_tmr);
+ kfree(b_ase0_brst_tmr);
+ kfree(b_se0_srp_tmr);
+ kfree(b_srp_fail_tmr);
+ kfree(a_wait_enum_tmr);
/* device driver used timers */
- if (b_srp_wait_tmr != NULL)
- kfree(b_srp_wait_tmr);
- if (b_data_pulse_tmr != NULL)
- kfree(b_data_pulse_tmr);
- if (b_vbus_pulse_tmr != NULL)
- kfree(b_vbus_pulse_tmr);
+ kfree(b_srp_wait_tmr);
+ kfree(b_data_pulse_tmr);
+ kfree(b_vbus_pulse_tmr);
}
/* Add timer to timer list */
@@ -1002,7 +992,7 @@ static int show_fsl_usb2_otg_state(struct device *dev,
/* State */
t = scnprintf(next, size,
"OTG state: %s\n\n",
- otg_state_string(fsl_otg_dev->phy.state));
+ usb_otg_state_string(fsl_otg_dev->phy.state));
size -= t;
next += t;
diff --git a/drivers/usb/otg/fsl_otg.h b/drivers/usb/phy/phy-fsl-usb.h
index ca266280895..ca266280895 100644
--- a/drivers/usb/otg/fsl_otg.h
+++ b/drivers/usb/phy/phy-fsl-usb.h
diff --git a/drivers/usb/otg/otg_fsm.c b/drivers/usb/phy/phy-fsm-usb.c
index ade131a8ae5..c520b3548e7 100644
--- a/drivers/usb/otg/otg_fsm.c
+++ b/drivers/usb/phy/phy-fsm-usb.c
@@ -29,7 +29,7 @@
#include <linux/usb/gadget.h>
#include <linux/usb/otg.h>
-#include "otg_fsm.h"
+#include "phy-otg-fsm.h"
/* Change USB protocol when there is a protocol change */
static int otg_set_protocol(struct otg_fsm *fsm, int protocol)
@@ -119,7 +119,7 @@ int otg_set_state(struct otg_fsm *fsm, enum usb_otg_state new_state)
state_changed = 1;
if (fsm->otg->phy->state == new_state)
return 0;
- VDBG("Set state: %s\n", otg_state_string(new_state));
+ VDBG("Set state: %s\n", usb_otg_state_string(new_state));
otg_leave_state(fsm, fsm->otg->phy->state);
switch (new_state) {
case OTG_STATE_B_IDLE:
diff --git a/drivers/usb/otg/otg_fsm.h b/drivers/usb/phy/phy-fsm-usb.h
index c30a2e1d9e4..c30a2e1d9e4 100644
--- a/drivers/usb/otg/otg_fsm.h
+++ b/drivers/usb/phy/phy-fsm-usb.h
diff --git a/drivers/usb/otg/gpio_vbus.c b/drivers/usb/phy/phy-gpio-vbus-usb.c
index a7d4ac59198..4c76074e518 100644
--- a/drivers/usb/otg/gpio_vbus.c
+++ b/drivers/usb/phy/phy-gpio-vbus-usb.c
@@ -61,6 +61,7 @@ static void set_vbus_draw(struct gpio_vbus_data *gpio_vbus, unsigned mA)
{
struct regulator *vbus_draw = gpio_vbus->vbus_draw;
int enabled;
+ int ret;
if (!vbus_draw)
return;
@@ -69,12 +70,16 @@ static void set_vbus_draw(struct gpio_vbus_data *gpio_vbus, unsigned mA)
if (mA) {
regulator_set_current_limit(vbus_draw, 0, 1000 * mA);
if (!enabled) {
- regulator_enable(vbus_draw);
+ ret = regulator_enable(vbus_draw);
+ if (ret < 0)
+ return;
gpio_vbus->vbus_draw_enabled = 1;
}
} else {
if (enabled) {
- regulator_disable(vbus_draw);
+ ret = regulator_disable(vbus_draw);
+ if (ret < 0)
+ return;
gpio_vbus->vbus_draw_enabled = 0;
}
}
diff --git a/drivers/usb/otg/isp1301_omap.c b/drivers/usb/phy/phy-isp1301-omap.c
index af9cb11626b..ae481afcb3e 100644
--- a/drivers/usb/otg/isp1301_omap.c
+++ b/drivers/usb/phy/phy-isp1301-omap.c
@@ -236,7 +236,7 @@ isp1301_clear_bits(struct isp1301 *isp, u8 reg, u8 bits)
static inline const char *state_name(struct isp1301 *isp)
{
- return otg_state_string(isp->phy.state);
+ return usb_otg_state_string(isp->phy.state);
}
/*-------------------------------------------------------------------------*/
@@ -481,7 +481,7 @@ static void check_state(struct isp1301 *isp, const char *tag)
if (isp->phy.state == state && !extra)
return;
pr_debug("otg: %s FSM %s/%02x, %s, %06x\n", tag,
- otg_state_string(state), fsm, state_name(isp),
+ usb_otg_state_string(state), fsm, state_name(isp),
omap_readl(OTG_CTRL));
}
@@ -1077,7 +1077,7 @@ static void isp_update_otg(struct isp1301 *isp, u8 stat)
if (state != isp->phy.state)
pr_debug(" isp, %s -> %s\n",
- otg_state_string(state), state_name(isp));
+ usb_otg_state_string(state), state_name(isp));
#ifdef CONFIG_USB_OTG
/* update the OTG controller state to match the isp1301; may
@@ -1212,7 +1212,7 @@ static void isp1301_release(struct device *dev)
static struct isp1301 *the_transceiver;
-static int __exit isp1301_remove(struct i2c_client *i2c)
+static int isp1301_remove(struct i2c_client *i2c)
{
struct isp1301 *isp;
@@ -1634,7 +1634,7 @@ static struct i2c_driver isp1301_driver = {
.name = "isp1301_omap",
},
.probe = isp1301_probe,
- .remove = __exit_p(isp1301_remove),
+ .remove = isp1301_remove,
.id_table = isp1301_id,
};
diff --git a/drivers/usb/phy/phy-isp1301.c b/drivers/usb/phy/phy-isp1301.c
new file mode 100644
index 00000000000..225ae6c97ee
--- /dev/null
+++ b/drivers/usb/phy/phy-isp1301.c
@@ -0,0 +1,162 @@
+/*
+ * NXP ISP1301 USB transceiver driver
+ *
+ * Copyright (C) 2012 Roland Stigge
+ *
+ * Author: Roland Stigge <stigge@antcom.de>
+ *
+ * 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/module.h>
+#include <linux/mutex.h>
+#include <linux/i2c.h>
+#include <linux/usb/phy.h>
+#include <linux/usb/isp1301.h>
+
+#define DRV_NAME "isp1301"
+
+struct isp1301 {
+ struct usb_phy phy;
+ struct mutex mutex;
+
+ struct i2c_client *client;
+};
+
+#define phy_to_isp(p) (container_of((p), struct isp1301, phy))
+
+static const struct i2c_device_id isp1301_id[] = {
+ { "isp1301", 0 },
+ { }
+};
+
+static struct i2c_client *isp1301_i2c_client;
+
+static int __isp1301_write(struct isp1301 *isp, u8 reg, u8 value, u8 clear)
+{
+ return i2c_smbus_write_byte_data(isp->client, reg | clear, value);
+}
+
+static int isp1301_write(struct isp1301 *isp, u8 reg, u8 value)
+{
+ return __isp1301_write(isp, reg, value, 0);
+}
+
+static int isp1301_clear(struct isp1301 *isp, u8 reg, u8 value)
+{
+ return __isp1301_write(isp, reg, value, ISP1301_I2C_REG_CLEAR_ADDR);
+}
+
+static int isp1301_phy_init(struct usb_phy *phy)
+{
+ struct isp1301 *isp = phy_to_isp(phy);
+
+ /* Disable transparent UART mode first */
+ isp1301_clear(isp, ISP1301_I2C_MODE_CONTROL_1, MC1_UART_EN);
+ isp1301_clear(isp, ISP1301_I2C_MODE_CONTROL_1, ~MC1_SPEED_REG);
+ isp1301_write(isp, ISP1301_I2C_MODE_CONTROL_1, MC1_SPEED_REG);
+ isp1301_clear(isp, ISP1301_I2C_MODE_CONTROL_2, ~0);
+ isp1301_write(isp, ISP1301_I2C_MODE_CONTROL_2, (MC2_BI_DI | MC2_PSW_EN
+ | MC2_SPD_SUSP_CTRL));
+
+ isp1301_clear(isp, ISP1301_I2C_OTG_CONTROL_1, ~0);
+ isp1301_write(isp, ISP1301_I2C_MODE_CONTROL_1, MC1_DAT_SE0);
+ isp1301_write(isp, ISP1301_I2C_OTG_CONTROL_1, (OTG1_DM_PULLDOWN
+ | OTG1_DP_PULLDOWN));
+ isp1301_clear(isp, ISP1301_I2C_OTG_CONTROL_1, (OTG1_DM_PULLUP
+ | OTG1_DP_PULLUP));
+
+ /* mask all interrupts */
+ isp1301_clear(isp, ISP1301_I2C_INTERRUPT_LATCH, ~0);
+ isp1301_clear(isp, ISP1301_I2C_INTERRUPT_FALLING, ~0);
+ isp1301_clear(isp, ISP1301_I2C_INTERRUPT_RISING, ~0);
+
+ return 0;
+}
+
+static int isp1301_phy_set_vbus(struct usb_phy *phy, int on)
+{
+ struct isp1301 *isp = phy_to_isp(phy);
+
+ if (on)
+ isp1301_write(isp, ISP1301_I2C_OTG_CONTROL_1, OTG1_VBUS_DRV);
+ else
+ isp1301_clear(isp, ISP1301_I2C_OTG_CONTROL_1, OTG1_VBUS_DRV);
+
+ return 0;
+}
+
+static int isp1301_probe(struct i2c_client *client,
+ const struct i2c_device_id *i2c_id)
+{
+ struct isp1301 *isp;
+ struct usb_phy *phy;
+
+ isp = devm_kzalloc(&client->dev, sizeof(*isp), GFP_KERNEL);
+ if (!isp)
+ return -ENOMEM;
+
+ isp->client = client;
+ mutex_init(&isp->mutex);
+
+ phy = &isp->phy;
+ phy->label = DRV_NAME;
+ phy->init = isp1301_phy_init;
+ phy->set_vbus = isp1301_phy_set_vbus;
+ phy->type = USB_PHY_TYPE_USB2;
+
+ i2c_set_clientdata(client, isp);
+ usb_add_phy_dev(phy);
+
+ isp1301_i2c_client = client;
+
+ return 0;
+}
+
+static int isp1301_remove(struct i2c_client *client)
+{
+ struct isp1301 *isp = i2c_get_clientdata(client);
+
+ usb_remove_phy(&isp->phy);
+ isp1301_i2c_client = NULL;
+
+ return 0;
+}
+
+static struct i2c_driver isp1301_driver = {
+ .driver = {
+ .name = DRV_NAME,
+ },
+ .probe = isp1301_probe,
+ .remove = isp1301_remove,
+ .id_table = isp1301_id,
+};
+
+module_i2c_driver(isp1301_driver);
+
+static int match(struct device *dev, void *data)
+{
+ struct device_node *node = (struct device_node *)data;
+ return (dev->of_node == node) &&
+ (dev->driver == &isp1301_driver.driver);
+}
+
+struct i2c_client *isp1301_get_client(struct device_node *node)
+{
+ if (node) { /* reference of ISP1301 I2C node via DT */
+ struct device *dev = bus_find_device(&i2c_bus_type, NULL,
+ node, match);
+ if (!dev)
+ return NULL;
+ return to_i2c_client(dev);
+ } else { /* non-DT: only one ISP1301 chip supported */
+ return isp1301_i2c_client;
+ }
+}
+EXPORT_SYMBOL_GPL(isp1301_get_client);
+
+MODULE_AUTHOR("Roland Stigge <stigge@antcom.de>");
+MODULE_DESCRIPTION("NXP ISP1301 USB transceiver driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/phy/phy-msm-usb.c
index 749fbf41fb6..749fbf41fb6 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/phy/phy-msm-usb.c
diff --git a/drivers/usb/phy/mv_u3d_phy.c b/drivers/usb/phy/phy-mv-u3d-usb.c
index 9d8599122aa..f7838a43347 100644
--- a/drivers/usb/phy/mv_u3d_phy.c
+++ b/drivers/usb/phy/phy-mv-u3d-usb.c
@@ -15,7 +15,7 @@
#include <linux/usb/otg.h>
#include <linux/platform_data/mv_usb.h>
-#include "mv_u3d_phy.h"
+#include "phy-mv-u3d-usb.h"
/*
* struct mv_u3d_phy - transceiver driver state
@@ -313,7 +313,7 @@ err:
return ret;
}
-static int __exit mv_u3d_phy_remove(struct platform_device *pdev)
+static int mv_u3d_phy_remove(struct platform_device *pdev)
{
struct mv_u3d_phy *mv_u3d_phy = platform_get_drvdata(pdev);
diff --git a/drivers/usb/phy/mv_u3d_phy.h b/drivers/usb/phy/phy-mv-u3d-usb.h
index 2a658cb9a52..2a658cb9a52 100644
--- a/drivers/usb/phy/mv_u3d_phy.h
+++ b/drivers/usb/phy/phy-mv-u3d-usb.h
diff --git a/drivers/usb/otg/mv_otg.c b/drivers/usb/phy/phy-mv-usb.c
index b6a9be31133..c987bbe2785 100644
--- a/drivers/usb/otg/mv_otg.c
+++ b/drivers/usb/phy/phy-mv-usb.c
@@ -27,7 +27,7 @@
#include <linux/usb/hcd.h>
#include <linux/platform_data/mv_usb.h>
-#include "mv_otg.h"
+#include "phy-mv-usb.h"
#define DRIVER_DESC "Marvell USB OTG transceiver driver"
#define DRIVER_VERSION "Jan 20, 2010"
@@ -237,18 +237,12 @@ static void mv_otg_start_periphrals(struct mv_otg *mvotg, int on)
static void otg_clock_enable(struct mv_otg *mvotg)
{
- unsigned int i;
-
- for (i = 0; i < mvotg->clknum; i++)
- clk_prepare_enable(mvotg->clk[i]);
+ clk_prepare_enable(mvotg->clk);
}
static void otg_clock_disable(struct mv_otg *mvotg)
{
- unsigned int i;
-
- for (i = 0; i < mvotg->clknum; i++)
- clk_disable_unprepare(mvotg->clk[i]);
+ clk_disable_unprepare(mvotg->clk);
}
static int mv_otg_enable_internal(struct mv_otg *mvotg)
@@ -684,16 +678,14 @@ static int mv_otg_probe(struct platform_device *pdev)
struct mv_otg *mvotg;
struct usb_otg *otg;
struct resource *r;
- int retval = 0, clk_i, i;
- size_t size;
+ int retval = 0, i;
if (pdata == NULL) {
dev_err(&pdev->dev, "failed to get platform data\n");
return -ENODEV;
}
- size = sizeof(*mvotg) + sizeof(struct clk *) * pdata->clknum;
- mvotg = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
+ mvotg = devm_kzalloc(&pdev->dev, sizeof(*mvotg), GFP_KERNEL);
if (!mvotg) {
dev_err(&pdev->dev, "failed to allocate memory!\n");
return -ENOMEM;
@@ -708,15 +700,9 @@ static int mv_otg_probe(struct platform_device *pdev)
mvotg->pdev = pdev;
mvotg->pdata = pdata;
- mvotg->clknum = pdata->clknum;
- for (clk_i = 0; clk_i < mvotg->clknum; clk_i++) {
- mvotg->clk[clk_i] = devm_clk_get(&pdev->dev,
- pdata->clkname[clk_i]);
- if (IS_ERR(mvotg->clk[clk_i])) {
- retval = PTR_ERR(mvotg->clk[clk_i]);
- return retval;
- }
- }
+ mvotg->clk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(mvotg->clk))
+ return PTR_ERR(mvotg->clk);
mvotg->qwork = create_singlethread_workqueue("mv_otg_queue");
if (!mvotg->qwork) {
diff --git a/drivers/usb/otg/mv_otg.h b/drivers/usb/phy/phy-mv-usb.h
index 8a9e351b36b..551da6eb0ba 100644
--- a/drivers/usb/otg/mv_otg.h
+++ b/drivers/usb/phy/phy-mv-usb.h
@@ -158,8 +158,7 @@ struct mv_otg {
unsigned int active;
unsigned int clock_gating;
- unsigned int clknum;
- struct clk *clk[0];
+ struct clk *clk;
};
#endif
diff --git a/drivers/usb/otg/mxs-phy.c b/drivers/usb/phy/phy-mxs-usb.c
index b0d9f119c74..9d4381e64d5 100644
--- a/drivers/usb/otg/mxs-phy.c
+++ b/drivers/usb/phy/phy-mxs-usb.c
@@ -48,12 +48,12 @@ static void mxs_phy_hw_init(struct mxs_phy *mxs_phy)
stmp_reset_block(base + HW_USBPHY_CTRL);
/* Power up the PHY */
- writel_relaxed(0, base + HW_USBPHY_PWD);
+ writel(0, base + HW_USBPHY_PWD);
/* enable FS/LS device */
- writel_relaxed(BM_USBPHY_CTRL_ENUTMILEVEL2 |
- BM_USBPHY_CTRL_ENUTMILEVEL3,
- base + HW_USBPHY_CTRL_SET);
+ writel(BM_USBPHY_CTRL_ENUTMILEVEL2 |
+ BM_USBPHY_CTRL_ENUTMILEVEL3,
+ base + HW_USBPHY_CTRL_SET);
}
static int mxs_phy_init(struct usb_phy *phy)
@@ -70,8 +70,8 @@ static void mxs_phy_shutdown(struct usb_phy *phy)
{
struct mxs_phy *mxs_phy = to_mxs_phy(phy);
- writel_relaxed(BM_USBPHY_CTRL_CLKGATE,
- phy->io_priv + HW_USBPHY_CTRL_SET);
+ writel(BM_USBPHY_CTRL_CLKGATE,
+ phy->io_priv + HW_USBPHY_CTRL_SET);
clk_disable_unprepare(mxs_phy->clk);
}
@@ -81,15 +81,15 @@ static int mxs_phy_suspend(struct usb_phy *x, int suspend)
struct mxs_phy *mxs_phy = to_mxs_phy(x);
if (suspend) {
- writel_relaxed(0xffffffff, x->io_priv + HW_USBPHY_PWD);
- writel_relaxed(BM_USBPHY_CTRL_CLKGATE,
- x->io_priv + HW_USBPHY_CTRL_SET);
+ writel(0xffffffff, x->io_priv + HW_USBPHY_PWD);
+ writel(BM_USBPHY_CTRL_CLKGATE,
+ x->io_priv + HW_USBPHY_CTRL_SET);
clk_disable_unprepare(mxs_phy->clk);
} else {
clk_prepare_enable(mxs_phy->clk);
- writel_relaxed(BM_USBPHY_CTRL_CLKGATE,
- x->io_priv + HW_USBPHY_CTRL_CLR);
- writel_relaxed(0, x->io_priv + HW_USBPHY_PWD);
+ writel(BM_USBPHY_CTRL_CLKGATE,
+ x->io_priv + HW_USBPHY_CTRL_CLR);
+ writel(0, x->io_priv + HW_USBPHY_PWD);
}
return 0;
@@ -102,8 +102,8 @@ static int mxs_phy_on_connect(struct usb_phy *phy,
(speed == USB_SPEED_HIGH) ? "high" : "non-high");
if (speed == USB_SPEED_HIGH)
- writel_relaxed(BM_USBPHY_CTRL_ENHOSTDISCONDETECT,
- phy->io_priv + HW_USBPHY_CTRL_SET);
+ writel(BM_USBPHY_CTRL_ENHOSTDISCONDETECT,
+ phy->io_priv + HW_USBPHY_CTRL_SET);
return 0;
}
@@ -115,8 +115,8 @@ static int mxs_phy_on_disconnect(struct usb_phy *phy,
(speed == USB_SPEED_HIGH) ? "high" : "non-high");
if (speed == USB_SPEED_HIGH)
- writel_relaxed(BM_USBPHY_CTRL_ENHOSTDISCONDETECT,
- phy->io_priv + HW_USBPHY_CTRL_CLR);
+ writel(BM_USBPHY_CTRL_ENHOSTDISCONDETECT,
+ phy->io_priv + HW_USBPHY_CTRL_CLR);
return 0;
}
@@ -127,6 +127,7 @@ static int mxs_phy_probe(struct platform_device *pdev)
void __iomem *base;
struct clk *clk;
struct mxs_phy *mxs_phy;
+ int ret;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
@@ -166,11 +167,19 @@ static int mxs_phy_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, &mxs_phy->phy);
+ ret = usb_add_phy_dev(&mxs_phy->phy);
+ if (ret)
+ return ret;
+
return 0;
}
static int mxs_phy_remove(struct platform_device *pdev)
{
+ struct mxs_phy *mxs_phy = platform_get_drvdata(pdev);
+
+ usb_remove_phy(&mxs_phy->phy);
+
platform_set_drvdata(pdev, NULL);
return 0;
diff --git a/drivers/usb/otg/nop-usb-xceiv.c b/drivers/usb/phy/phy-nop.c
index a3ce24b94a7..2b10cc969bb 100644
--- a/drivers/usb/otg/nop-usb-xceiv.c
+++ b/drivers/usb/phy/phy-nop.c
@@ -32,10 +32,16 @@
#include <linux/usb/otg.h>
#include <linux/usb/nop-usb-xceiv.h>
#include <linux/slab.h>
+#include <linux/clk.h>
+#include <linux/regulator/consumer.h>
+#include <linux/of.h>
struct nop_usb_xceiv {
- struct usb_phy phy;
- struct device *dev;
+ struct usb_phy phy;
+ struct device *dev;
+ struct clk *clk;
+ struct regulator *vcc;
+ struct regulator *reset;
};
static struct platform_device *pd;
@@ -64,6 +70,46 @@ static int nop_set_suspend(struct usb_phy *x, int suspend)
return 0;
}
+static int nop_init(struct usb_phy *phy)
+{
+ struct nop_usb_xceiv *nop = dev_get_drvdata(phy->dev);
+
+ if (!IS_ERR(nop->vcc)) {
+ if (regulator_enable(nop->vcc))
+ dev_err(phy->dev, "Failed to enable power\n");
+ }
+
+ if (!IS_ERR(nop->clk))
+ clk_enable(nop->clk);
+
+ if (!IS_ERR(nop->reset)) {
+ /* De-assert RESET */
+ if (regulator_enable(nop->reset))
+ dev_err(phy->dev, "Failed to de-assert reset\n");
+ }
+
+ return 0;
+}
+
+static void nop_shutdown(struct usb_phy *phy)
+{
+ struct nop_usb_xceiv *nop = dev_get_drvdata(phy->dev);
+
+ if (!IS_ERR(nop->reset)) {
+ /* Assert RESET */
+ if (regulator_disable(nop->reset))
+ dev_err(phy->dev, "Failed to assert reset\n");
+ }
+
+ if (!IS_ERR(nop->clk))
+ clk_disable(nop->clk);
+
+ if (!IS_ERR(nop->vcc)) {
+ if (regulator_disable(nop->vcc))
+ dev_err(phy->dev, "Failed to disable power\n");
+ }
+}
+
static int nop_set_peripheral(struct usb_otg *otg, struct usb_gadget *gadget)
{
if (!otg)
@@ -95,39 +141,96 @@ static int nop_set_host(struct usb_otg *otg, struct usb_bus *host)
static int nop_usb_xceiv_probe(struct platform_device *pdev)
{
+ struct device *dev = &pdev->dev;
struct nop_usb_xceiv_platform_data *pdata = pdev->dev.platform_data;
struct nop_usb_xceiv *nop;
enum usb_phy_type type = USB_PHY_TYPE_USB2;
int err;
+ u32 clk_rate = 0;
+ bool needs_vcc = false;
+ bool needs_reset = false;
- nop = kzalloc(sizeof *nop, GFP_KERNEL);
+ nop = devm_kzalloc(&pdev->dev, sizeof(*nop), GFP_KERNEL);
if (!nop)
return -ENOMEM;
- nop->phy.otg = kzalloc(sizeof *nop->phy.otg, GFP_KERNEL);
- if (!nop->phy.otg) {
- kfree(nop);
+ nop->phy.otg = devm_kzalloc(&pdev->dev, sizeof(*nop->phy.otg),
+ GFP_KERNEL);
+ if (!nop->phy.otg)
return -ENOMEM;
- }
- if (pdata)
+ if (dev->of_node) {
+ struct device_node *node = dev->of_node;
+
+ if (of_property_read_u32(node, "clock-frequency", &clk_rate))
+ clk_rate = 0;
+
+ needs_vcc = of_property_read_bool(node, "vcc-supply");
+ needs_reset = of_property_read_bool(node, "reset-supply");
+
+ } else if (pdata) {
type = pdata->type;
+ clk_rate = pdata->clk_rate;
+ needs_vcc = pdata->needs_vcc;
+ needs_reset = pdata->needs_reset;
+ }
+
+ nop->clk = devm_clk_get(&pdev->dev, "main_clk");
+ if (IS_ERR(nop->clk)) {
+ dev_dbg(&pdev->dev, "Can't get phy clock: %ld\n",
+ PTR_ERR(nop->clk));
+ }
+
+ if (!IS_ERR(nop->clk) && clk_rate) {
+ err = clk_set_rate(nop->clk, clk_rate);
+ if (err) {
+ dev_err(&pdev->dev, "Error setting clock rate\n");
+ return err;
+ }
+ }
+
+ if (!IS_ERR(nop->clk)) {
+ err = clk_prepare(nop->clk);
+ if (err) {
+ dev_err(&pdev->dev, "Error preparing clock\n");
+ return err;
+ }
+ }
+
+ nop->vcc = devm_regulator_get(&pdev->dev, "vcc");
+ if (IS_ERR(nop->vcc)) {
+ dev_dbg(&pdev->dev, "Error getting vcc regulator: %ld\n",
+ PTR_ERR(nop->vcc));
+ if (needs_vcc)
+ return -EPROBE_DEFER;
+ }
+
+ nop->reset = devm_regulator_get(&pdev->dev, "reset");
+ if (IS_ERR(nop->reset)) {
+ dev_dbg(&pdev->dev, "Error getting reset regulator: %ld\n",
+ PTR_ERR(nop->reset));
+ if (needs_reset)
+ return -EPROBE_DEFER;
+ }
nop->dev = &pdev->dev;
nop->phy.dev = nop->dev;
nop->phy.label = "nop-xceiv";
nop->phy.set_suspend = nop_set_suspend;
+ nop->phy.init = nop_init;
+ nop->phy.shutdown = nop_shutdown;
nop->phy.state = OTG_STATE_UNDEFINED;
+ nop->phy.type = type;
nop->phy.otg->phy = &nop->phy;
nop->phy.otg->set_host = nop_set_host;
nop->phy.otg->set_peripheral = nop_set_peripheral;
- err = usb_add_phy(&nop->phy, type);
+ err = usb_add_phy_dev(&nop->phy);
if (err) {
dev_err(&pdev->dev, "can't register transceiver, err: %d\n",
err);
- goto exit;
+ goto err_add;
}
platform_set_drvdata(pdev, nop);
@@ -135,9 +238,10 @@ static int nop_usb_xceiv_probe(struct platform_device *pdev)
ATOMIC_INIT_NOTIFIER_HEAD(&nop->phy.notifier);
return 0;
-exit:
- kfree(nop->phy.otg);
- kfree(nop);
+
+err_add:
+ if (!IS_ERR(nop->clk))
+ clk_unprepare(nop->clk);
return err;
}
@@ -145,21 +249,30 @@ static int nop_usb_xceiv_remove(struct platform_device *pdev)
{
struct nop_usb_xceiv *nop = platform_get_drvdata(pdev);
+ if (!IS_ERR(nop->clk))
+ clk_unprepare(nop->clk);
+
usb_remove_phy(&nop->phy);
platform_set_drvdata(pdev, NULL);
- kfree(nop->phy.otg);
- kfree(nop);
return 0;
}
+static const struct of_device_id nop_xceiv_dt_ids[] = {
+ { .compatible = "usb-nop-xceiv" },
+ { }
+};
+
+MODULE_DEVICE_TABLE(of, nop_xceiv_dt_ids);
+
static struct platform_driver nop_usb_xceiv_driver = {
.probe = nop_usb_xceiv_probe,
.remove = nop_usb_xceiv_remove,
.driver = {
.name = "nop_usb_xceiv",
.owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(nop_xceiv_dt_ids),
},
};
diff --git a/drivers/usb/phy/omap-control-usb.c b/drivers/usb/phy/phy-omap-control.c
index 5323b71c352..1419ceda975 100644
--- a/drivers/usb/phy/omap-control-usb.c
+++ b/drivers/usb/phy/phy-omap-control.c
@@ -219,32 +219,26 @@ static int omap_control_usb_probe(struct platform_device *pdev)
res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
"control_dev_conf");
- control_usb->dev_conf = devm_request_and_ioremap(&pdev->dev, res);
- if (!control_usb->dev_conf) {
- dev_err(&pdev->dev, "Failed to obtain io memory\n");
- return -EADDRNOTAVAIL;
- }
+ control_usb->dev_conf = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(control_usb->dev_conf))
+ return PTR_ERR(control_usb->dev_conf);
if (control_usb->type == OMAP_CTRL_DEV_TYPE1) {
res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
"otghs_control");
- control_usb->otghs_control = devm_request_and_ioremap(
+ control_usb->otghs_control = devm_ioremap_resource(
&pdev->dev, res);
- if (!control_usb->otghs_control) {
- dev_err(&pdev->dev, "Failed to obtain io memory\n");
- return -EADDRNOTAVAIL;
- }
+ if (IS_ERR(control_usb->otghs_control))
+ return PTR_ERR(control_usb->otghs_control);
}
if (control_usb->type == OMAP_CTRL_DEV_TYPE2) {
res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
"phy_power_usb");
- control_usb->phy_power = devm_request_and_ioremap(
+ control_usb->phy_power = devm_ioremap_resource(
&pdev->dev, res);
- if (!control_usb->phy_power) {
- dev_dbg(&pdev->dev, "Failed to obtain io memory\n");
- return -EADDRNOTAVAIL;
- }
+ if (IS_ERR(control_usb->phy_power))
+ return PTR_ERR(control_usb->phy_power);
control_usb->sys_clk = devm_clk_get(control_usb->dev,
"sys_clkin");
diff --git a/drivers/usb/phy/omap-usb2.c b/drivers/usb/phy/phy-omap-usb2.c
index 844ab68f08d..844ab68f08d 100644
--- a/drivers/usb/phy/omap-usb2.c
+++ b/drivers/usb/phy/phy-omap-usb2.c
diff --git a/drivers/usb/phy/omap-usb3.c b/drivers/usb/phy/phy-omap-usb3.c
index fadc0c2b65b..a6e60b1e102 100644
--- a/drivers/usb/phy/omap-usb3.c
+++ b/drivers/usb/phy/phy-omap-usb3.c
@@ -212,11 +212,9 @@ static int omap_usb3_probe(struct platform_device *pdev)
}
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pll_ctrl");
- phy->pll_ctrl_base = devm_request_and_ioremap(&pdev->dev, res);
- if (!phy->pll_ctrl_base) {
- dev_err(&pdev->dev, "ioremap of pll_ctrl failed\n");
- return -ENOMEM;
- }
+ phy->pll_ctrl_base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(phy->pll_ctrl_base))
+ return PTR_ERR(phy->pll_ctrl_base);
phy->dev = &pdev->dev;
diff --git a/drivers/usb/phy/rcar-phy.c b/drivers/usb/phy/phy-rcar-usb.c
index a35681b0c50..a35681b0c50 100644
--- a/drivers/usb/phy/rcar-phy.c
+++ b/drivers/usb/phy/phy-rcar-usb.c
diff --git a/drivers/usb/phy/phy-samsung-usb.c b/drivers/usb/phy/phy-samsung-usb.c
new file mode 100644
index 00000000000..7b118ee5f5e
--- /dev/null
+++ b/drivers/usb/phy/phy-samsung-usb.c
@@ -0,0 +1,236 @@
+/* linux/drivers/usb/phy/phy-samsung-usb.c
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * Author: Praveen Paneri <p.paneri@samsung.com>
+ *
+ * Samsung USB-PHY helper driver with common function calls;
+ * interacts with Samsung USB 2.0 PHY controller driver and later
+ * with Samsung USB 3.0 PHY driver.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/usb/samsung_usb_phy.h>
+
+#include "phy-samsung-usb.h"
+
+int samsung_usbphy_parse_dt(struct samsung_usbphy *sphy)
+{
+ struct device_node *usbphy_sys;
+
+ /* Getting node for system controller interface for usb-phy */
+ usbphy_sys = of_get_child_by_name(sphy->dev->of_node, "usbphy-sys");
+ if (!usbphy_sys) {
+ dev_err(sphy->dev, "No sys-controller interface for usb-phy\n");
+ return -ENODEV;
+ }
+
+ sphy->pmuregs = of_iomap(usbphy_sys, 0);
+
+ if (sphy->pmuregs == NULL) {
+ dev_err(sphy->dev, "Can't get usb-phy pmu control register\n");
+ goto err0;
+ }
+
+ sphy->sysreg = of_iomap(usbphy_sys, 1);
+
+ /*
+ * Not returning error code here, since this situation is not fatal.
+ * Few SoCs may not have this switch available
+ */
+ if (sphy->sysreg == NULL)
+ dev_warn(sphy->dev, "Can't get usb-phy sysreg cfg register\n");
+
+ of_node_put(usbphy_sys);
+
+ return 0;
+
+err0:
+ of_node_put(usbphy_sys);
+ return -ENXIO;
+}
+EXPORT_SYMBOL_GPL(samsung_usbphy_parse_dt);
+
+/*
+ * Set isolation here for phy.
+ * Here 'on = true' would mean USB PHY block is isolated, hence
+ * de-activated and vice-versa.
+ */
+void samsung_usbphy_set_isolation(struct samsung_usbphy *sphy, bool on)
+{
+ void __iomem *reg = NULL;
+ u32 reg_val;
+ u32 en_mask = 0;
+
+ if (!sphy->pmuregs) {
+ dev_warn(sphy->dev, "Can't set pmu isolation\n");
+ return;
+ }
+
+ switch (sphy->drv_data->cpu_type) {
+ case TYPE_S3C64XX:
+ /*
+ * Do nothing: We will add here once S3C64xx goes for DT support
+ */
+ break;
+ case TYPE_EXYNOS4210:
+ /*
+ * Fall through since exynos4210 and exynos5250 have similar
+ * register architecture: two separate registers for host and
+ * device phy control with enable bit at position 0.
+ */
+ case TYPE_EXYNOS5250:
+ if (sphy->phy_type == USB_PHY_TYPE_DEVICE) {
+ reg = sphy->pmuregs +
+ sphy->drv_data->devphy_reg_offset;
+ en_mask = sphy->drv_data->devphy_en_mask;
+ } else if (sphy->phy_type == USB_PHY_TYPE_HOST) {
+ reg = sphy->pmuregs +
+ sphy->drv_data->hostphy_reg_offset;
+ en_mask = sphy->drv_data->hostphy_en_mask;
+ }
+ break;
+ default:
+ dev_err(sphy->dev, "Invalid SoC type\n");
+ return;
+ }
+
+ reg_val = readl(reg);
+
+ if (on)
+ reg_val &= ~en_mask;
+ else
+ reg_val |= en_mask;
+
+ writel(reg_val, reg);
+}
+EXPORT_SYMBOL_GPL(samsung_usbphy_set_isolation);
+
+/*
+ * Configure the mode of working of usb-phy here: HOST/DEVICE.
+ */
+void samsung_usbphy_cfg_sel(struct samsung_usbphy *sphy)
+{
+ u32 reg;
+
+ if (!sphy->sysreg) {
+ dev_warn(sphy->dev, "Can't configure specified phy mode\n");
+ return;
+ }
+
+ reg = readl(sphy->sysreg);
+
+ if (sphy->phy_type == USB_PHY_TYPE_DEVICE)
+ reg &= ~EXYNOS_USB20PHY_CFG_HOST_LINK;
+ else if (sphy->phy_type == USB_PHY_TYPE_HOST)
+ reg |= EXYNOS_USB20PHY_CFG_HOST_LINK;
+
+ writel(reg, sphy->sysreg);
+}
+EXPORT_SYMBOL_GPL(samsung_usbphy_cfg_sel);
+
+/*
+ * PHYs are different for USB Device and USB Host.
+ * This make sure that correct PHY type is selected before
+ * any operation on PHY.
+ */
+int samsung_usbphy_set_type(struct usb_phy *phy,
+ enum samsung_usb_phy_type phy_type)
+{
+ struct samsung_usbphy *sphy = phy_to_sphy(phy);
+
+ sphy->phy_type = phy_type;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(samsung_usbphy_set_type);
+
+/*
+ * Returns reference clock frequency selection value
+ */
+int samsung_usbphy_get_refclk_freq(struct samsung_usbphy *sphy)
+{
+ struct clk *ref_clk;
+ int refclk_freq = 0;
+
+ /*
+ * In exynos5250 USB host and device PHY use
+ * external crystal clock XXTI
+ */
+ if (sphy->drv_data->cpu_type == TYPE_EXYNOS5250)
+ ref_clk = devm_clk_get(sphy->dev, "ext_xtal");
+ else
+ ref_clk = devm_clk_get(sphy->dev, "xusbxti");
+ if (IS_ERR(ref_clk)) {
+ dev_err(sphy->dev, "Failed to get reference clock\n");
+ return PTR_ERR(ref_clk);
+ }
+
+ if (sphy->drv_data->cpu_type == TYPE_EXYNOS5250) {
+ /* set clock frequency for PLL */
+ switch (clk_get_rate(ref_clk)) {
+ case 9600 * KHZ:
+ refclk_freq = FSEL_CLKSEL_9600K;
+ break;
+ case 10 * MHZ:
+ refclk_freq = FSEL_CLKSEL_10M;
+ break;
+ case 12 * MHZ:
+ refclk_freq = FSEL_CLKSEL_12M;
+ break;
+ case 19200 * KHZ:
+ refclk_freq = FSEL_CLKSEL_19200K;
+ break;
+ case 20 * MHZ:
+ refclk_freq = FSEL_CLKSEL_20M;
+ break;
+ case 50 * MHZ:
+ refclk_freq = FSEL_CLKSEL_50M;
+ break;
+ case 24 * MHZ:
+ default:
+ /* default reference clock */
+ refclk_freq = FSEL_CLKSEL_24M;
+ break;
+ }
+ } else {
+ switch (clk_get_rate(ref_clk)) {
+ case 12 * MHZ:
+ refclk_freq = PHYCLK_CLKSEL_12M;
+ break;
+ case 24 * MHZ:
+ refclk_freq = PHYCLK_CLKSEL_24M;
+ break;
+ case 48 * MHZ:
+ refclk_freq = PHYCLK_CLKSEL_48M;
+ break;
+ default:
+ if (sphy->drv_data->cpu_type == TYPE_S3C64XX)
+ refclk_freq = PHYCLK_CLKSEL_48M;
+ else
+ refclk_freq = PHYCLK_CLKSEL_24M;
+ break;
+ }
+ }
+ clk_put(ref_clk);
+
+ return refclk_freq;
+}
+EXPORT_SYMBOL_GPL(samsung_usbphy_get_refclk_freq);
diff --git a/drivers/usb/phy/phy-samsung-usb.h b/drivers/usb/phy/phy-samsung-usb.h
new file mode 100644
index 00000000000..70a9cae5e37
--- /dev/null
+++ b/drivers/usb/phy/phy-samsung-usb.h
@@ -0,0 +1,327 @@
+/* linux/drivers/usb/phy/phy-samsung-usb.h
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * Samsung USB-PHY transceiver; talks to S3C HS OTG controller, EHCI-S5P and
+ * OHCI-EXYNOS controllers.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/usb/phy.h>
+
+/* Register definitions */
+
+#define SAMSUNG_PHYPWR (0x00)
+
+#define PHYPWR_NORMAL_MASK (0x19 << 0)
+#define PHYPWR_OTG_DISABLE (0x1 << 4)
+#define PHYPWR_ANALOG_POWERDOWN (0x1 << 3)
+#define PHYPWR_FORCE_SUSPEND (0x1 << 1)
+/* For Exynos4 */
+#define PHYPWR_NORMAL_MASK_PHY0 (0x39 << 0)
+#define PHYPWR_SLEEP_PHY0 (0x1 << 5)
+
+#define SAMSUNG_PHYCLK (0x04)
+
+#define PHYCLK_MODE_USB11 (0x1 << 6)
+#define PHYCLK_EXT_OSC (0x1 << 5)
+#define PHYCLK_COMMON_ON_N (0x1 << 4)
+#define PHYCLK_ID_PULL (0x1 << 2)
+#define PHYCLK_CLKSEL_MASK (0x3 << 0)
+#define PHYCLK_CLKSEL_48M (0x0 << 0)
+#define PHYCLK_CLKSEL_12M (0x2 << 0)
+#define PHYCLK_CLKSEL_24M (0x3 << 0)
+
+#define SAMSUNG_RSTCON (0x08)
+
+#define RSTCON_PHYLINK_SWRST (0x1 << 2)
+#define RSTCON_HLINK_SWRST (0x1 << 1)
+#define RSTCON_SWRST (0x1 << 0)
+
+/* EXYNOS5 */
+#define EXYNOS5_PHY_HOST_CTRL0 (0x00)
+
+#define HOST_CTRL0_PHYSWRSTALL (0x1 << 31)
+
+#define HOST_CTRL0_REFCLKSEL_MASK (0x3 << 19)
+#define HOST_CTRL0_REFCLKSEL_XTAL (0x0 << 19)
+#define HOST_CTRL0_REFCLKSEL_EXTL (0x1 << 19)
+#define HOST_CTRL0_REFCLKSEL_CLKCORE (0x2 << 19)
+
+#define HOST_CTRL0_FSEL_MASK (0x7 << 16)
+#define HOST_CTRL0_FSEL(_x) ((_x) << 16)
+
+#define FSEL_CLKSEL_50M (0x7)
+#define FSEL_CLKSEL_24M (0x5)
+#define FSEL_CLKSEL_20M (0x4)
+#define FSEL_CLKSEL_19200K (0x3)
+#define FSEL_CLKSEL_12M (0x2)
+#define FSEL_CLKSEL_10M (0x1)
+#define FSEL_CLKSEL_9600K (0x0)
+
+#define HOST_CTRL0_TESTBURNIN (0x1 << 11)
+#define HOST_CTRL0_RETENABLE (0x1 << 10)
+#define HOST_CTRL0_COMMONON_N (0x1 << 9)
+#define HOST_CTRL0_SIDDQ (0x1 << 6)
+#define HOST_CTRL0_FORCESLEEP (0x1 << 5)
+#define HOST_CTRL0_FORCESUSPEND (0x1 << 4)
+#define HOST_CTRL0_WORDINTERFACE (0x1 << 3)
+#define HOST_CTRL0_UTMISWRST (0x1 << 2)
+#define HOST_CTRL0_LINKSWRST (0x1 << 1)
+#define HOST_CTRL0_PHYSWRST (0x1 << 0)
+
+#define EXYNOS5_PHY_HOST_TUNE0 (0x04)
+
+#define EXYNOS5_PHY_HSIC_CTRL1 (0x10)
+
+#define EXYNOS5_PHY_HSIC_TUNE1 (0x14)
+
+#define EXYNOS5_PHY_HSIC_CTRL2 (0x20)
+
+#define EXYNOS5_PHY_HSIC_TUNE2 (0x24)
+
+#define HSIC_CTRL_REFCLKSEL_MASK (0x3 << 23)
+#define HSIC_CTRL_REFCLKSEL (0x2 << 23)
+
+#define HSIC_CTRL_REFCLKDIV_MASK (0x7f << 16)
+#define HSIC_CTRL_REFCLKDIV(_x) ((_x) << 16)
+#define HSIC_CTRL_REFCLKDIV_12 (0x24 << 16)
+#define HSIC_CTRL_REFCLKDIV_15 (0x1c << 16)
+#define HSIC_CTRL_REFCLKDIV_16 (0x1a << 16)
+#define HSIC_CTRL_REFCLKDIV_19_2 (0x15 << 16)
+#define HSIC_CTRL_REFCLKDIV_20 (0x14 << 16)
+
+#define HSIC_CTRL_SIDDQ (0x1 << 6)
+#define HSIC_CTRL_FORCESLEEP (0x1 << 5)
+#define HSIC_CTRL_FORCESUSPEND (0x1 << 4)
+#define HSIC_CTRL_WORDINTERFACE (0x1 << 3)
+#define HSIC_CTRL_UTMISWRST (0x1 << 2)
+#define HSIC_CTRL_PHYSWRST (0x1 << 0)
+
+#define EXYNOS5_PHY_HOST_EHCICTRL (0x30)
+
+#define HOST_EHCICTRL_ENAINCRXALIGN (0x1 << 29)
+#define HOST_EHCICTRL_ENAINCR4 (0x1 << 28)
+#define HOST_EHCICTRL_ENAINCR8 (0x1 << 27)
+#define HOST_EHCICTRL_ENAINCR16 (0x1 << 26)
+
+#define EXYNOS5_PHY_HOST_OHCICTRL (0x34)
+
+#define HOST_OHCICTRL_SUSPLGCY (0x1 << 3)
+#define HOST_OHCICTRL_APPSTARTCLK (0x1 << 2)
+#define HOST_OHCICTRL_CNTSEL (0x1 << 1)
+#define HOST_OHCICTRL_CLKCKTRST (0x1 << 0)
+
+#define EXYNOS5_PHY_OTG_SYS (0x38)
+
+#define OTG_SYS_PHYLINK_SWRESET (0x1 << 14)
+#define OTG_SYS_LINKSWRST_UOTG (0x1 << 13)
+#define OTG_SYS_PHY0_SWRST (0x1 << 12)
+
+#define OTG_SYS_REFCLKSEL_MASK (0x3 << 9)
+#define OTG_SYS_REFCLKSEL_XTAL (0x0 << 9)
+#define OTG_SYS_REFCLKSEL_EXTL (0x1 << 9)
+#define OTG_SYS_REFCLKSEL_CLKCORE (0x2 << 9)
+
+#define OTG_SYS_IDPULLUP_UOTG (0x1 << 8)
+#define OTG_SYS_COMMON_ON (0x1 << 7)
+
+#define OTG_SYS_FSEL_MASK (0x7 << 4)
+#define OTG_SYS_FSEL(_x) ((_x) << 4)
+
+#define OTG_SYS_FORCESLEEP (0x1 << 3)
+#define OTG_SYS_OTGDISABLE (0x1 << 2)
+#define OTG_SYS_SIDDQ_UOTG (0x1 << 1)
+#define OTG_SYS_FORCESUSPEND (0x1 << 0)
+
+#define EXYNOS5_PHY_OTG_TUNE (0x40)
+
+/* EXYNOS5: USB 3.0 DRD */
+#define EXYNOS5_DRD_LINKSYSTEM (0x04)
+
+#define LINKSYSTEM_FLADJ_MASK (0x3f << 1)
+#define LINKSYSTEM_FLADJ(_x) ((_x) << 1)
+#define LINKSYSTEM_XHCI_VERSION_CONTROL (0x1 << 27)
+
+#define EXYNOS5_DRD_PHYUTMI (0x08)
+
+#define PHYUTMI_OTGDISABLE (0x1 << 6)
+#define PHYUTMI_FORCESUSPEND (0x1 << 1)
+#define PHYUTMI_FORCESLEEP (0x1 << 0)
+
+#define EXYNOS5_DRD_PHYPIPE (0x0c)
+
+#define EXYNOS5_DRD_PHYCLKRST (0x10)
+
+#define PHYCLKRST_SSC_REFCLKSEL_MASK (0xff << 23)
+#define PHYCLKRST_SSC_REFCLKSEL(_x) ((_x) << 23)
+
+#define PHYCLKRST_SSC_RANGE_MASK (0x03 << 21)
+#define PHYCLKRST_SSC_RANGE(_x) ((_x) << 21)
+
+#define PHYCLKRST_SSC_EN (0x1 << 20)
+#define PHYCLKRST_REF_SSP_EN (0x1 << 19)
+#define PHYCLKRST_REF_CLKDIV2 (0x1 << 18)
+
+#define PHYCLKRST_MPLL_MULTIPLIER_MASK (0x7f << 11)
+#define PHYCLKRST_MPLL_MULTIPLIER_100MHZ_REF (0x19 << 11)
+#define PHYCLKRST_MPLL_MULTIPLIER_50M_REF (0x02 << 11)
+#define PHYCLKRST_MPLL_MULTIPLIER_24MHZ_REF (0x68 << 11)
+#define PHYCLKRST_MPLL_MULTIPLIER_20MHZ_REF (0x7d << 11)
+#define PHYCLKRST_MPLL_MULTIPLIER_19200KHZ_REF (0x02 << 11)
+
+#define PHYCLKRST_FSEL_MASK (0x3f << 5)
+#define PHYCLKRST_FSEL(_x) ((_x) << 5)
+#define PHYCLKRST_FSEL_PAD_100MHZ (0x27 << 5)
+#define PHYCLKRST_FSEL_PAD_24MHZ (0x2a << 5)
+#define PHYCLKRST_FSEL_PAD_20MHZ (0x31 << 5)
+#define PHYCLKRST_FSEL_PAD_19_2MHZ (0x38 << 5)
+
+#define PHYCLKRST_RETENABLEN (0x1 << 4)
+
+#define PHYCLKRST_REFCLKSEL_MASK (0x03 << 2)
+#define PHYCLKRST_REFCLKSEL_PAD_REFCLK (0x2 << 2)
+#define PHYCLKRST_REFCLKSEL_EXT_REFCLK (0x3 << 2)
+
+#define PHYCLKRST_PORTRESET (0x1 << 1)
+#define PHYCLKRST_COMMONONN (0x1 << 0)
+
+#define EXYNOS5_DRD_PHYREG0 (0x14)
+#define EXYNOS5_DRD_PHYREG1 (0x18)
+
+#define EXYNOS5_DRD_PHYPARAM0 (0x1c)
+
+#define PHYPARAM0_REF_USE_PAD (0x1 << 31)
+#define PHYPARAM0_REF_LOSLEVEL_MASK (0x1f << 26)
+#define PHYPARAM0_REF_LOSLEVEL (0x9 << 26)
+
+#define EXYNOS5_DRD_PHYPARAM1 (0x20)
+
+#define PHYPARAM1_PCS_TXDEEMPH_MASK (0x1f << 0)
+#define PHYPARAM1_PCS_TXDEEMPH (0x1c)
+
+#define EXYNOS5_DRD_PHYTERM (0x24)
+
+#define EXYNOS5_DRD_PHYTEST (0x28)
+
+#define PHYTEST_POWERDOWN_SSP (0x1 << 3)
+#define PHYTEST_POWERDOWN_HSP (0x1 << 2)
+
+#define EXYNOS5_DRD_PHYADP (0x2c)
+
+#define EXYNOS5_DRD_PHYBATCHG (0x30)
+
+#define PHYBATCHG_UTMI_CLKSEL (0x1 << 2)
+
+#define EXYNOS5_DRD_PHYRESUME (0x34)
+#define EXYNOS5_DRD_LINKPORT (0x44)
+
+#ifndef MHZ
+#define MHZ (1000*1000)
+#endif
+
+#ifndef KHZ
+#define KHZ (1000)
+#endif
+
+#define EXYNOS_USBHOST_PHY_CTRL_OFFSET (0x4)
+#define S3C64XX_USBPHY_ENABLE (0x1 << 16)
+#define EXYNOS_USBPHY_ENABLE (0x1 << 0)
+#define EXYNOS_USB20PHY_CFG_HOST_LINK (0x1 << 0)
+
+enum samsung_cpu_type {
+ TYPE_S3C64XX,
+ TYPE_EXYNOS4210,
+ TYPE_EXYNOS5250,
+};
+
+/*
+ * struct samsung_usbphy_drvdata - driver data for various SoC variants
+ * @cpu_type: machine identifier
+ * @devphy_en_mask: device phy enable mask for PHY CONTROL register
+ * @hostphy_en_mask: host phy enable mask for PHY CONTROL register
+ * @devphy_reg_offset: offset to DEVICE PHY CONTROL register from
+ * mapped address of system controller.
+ * @hostphy_reg_offset: offset to HOST PHY CONTROL register from
+ * mapped address of system controller.
+ *
+ * Here we have a separate mask for device type phy.
+ * Having different masks for host and device type phy helps
+ * in setting independent masks in case of SoCs like S5PV210,
+ * in which PHY0 and PHY1 enable bits belong to same register
+ * placed at position 0 and 1 respectively.
+ * Although for newer SoCs like exynos these bits belong to
+ * different registers altogether placed at position 0.
+ */
+struct samsung_usbphy_drvdata {
+ int cpu_type;
+ int devphy_en_mask;
+ int hostphy_en_mask;
+ u32 devphy_reg_offset;
+ u32 hostphy_reg_offset;
+};
+
+/*
+ * struct samsung_usbphy - transceiver driver state
+ * @phy: transceiver structure
+ * @plat: platform data
+ * @dev: The parent device supplied to the probe function
+ * @clk: usb phy clock
+ * @regs: usb phy controller registers memory base
+ * @pmuregs: USB device PHY_CONTROL register memory base
+ * @sysreg: USB2.0 PHY_CFG register memory base
+ * @ref_clk_freq: reference clock frequency selection
+ * @drv_data: driver data available for different SoCs
+ * @phy_type: Samsung SoCs specific phy types: #HOST
+ * #DEVICE
+ * @phy_usage: usage count for phy
+ * @lock: lock for phy operations
+ */
+struct samsung_usbphy {
+ struct usb_phy phy;
+ struct samsung_usbphy_data *plat;
+ struct device *dev;
+ struct clk *clk;
+ void __iomem *regs;
+ void __iomem *pmuregs;
+ void __iomem *sysreg;
+ int ref_clk_freq;
+ const struct samsung_usbphy_drvdata *drv_data;
+ enum samsung_usb_phy_type phy_type;
+ atomic_t phy_usage;
+ spinlock_t lock;
+};
+
+#define phy_to_sphy(x) container_of((x), struct samsung_usbphy, phy)
+
+static const struct of_device_id samsung_usbphy_dt_match[];
+
+static inline const struct samsung_usbphy_drvdata
+*samsung_usbphy_get_driver_data(struct platform_device *pdev)
+{
+ if (pdev->dev.of_node) {
+ const struct of_device_id *match;
+ match = of_match_node(samsung_usbphy_dt_match,
+ pdev->dev.of_node);
+ return match->data;
+ }
+
+ return (struct samsung_usbphy_drvdata *)
+ platform_get_device_id(pdev)->driver_data;
+}
+
+extern int samsung_usbphy_parse_dt(struct samsung_usbphy *sphy);
+extern void samsung_usbphy_set_isolation(struct samsung_usbphy *sphy, bool on);
+extern void samsung_usbphy_cfg_sel(struct samsung_usbphy *sphy);
+extern int samsung_usbphy_set_type(struct usb_phy *phy,
+ enum samsung_usb_phy_type phy_type);
+extern int samsung_usbphy_get_refclk_freq(struct samsung_usbphy *sphy);
diff --git a/drivers/usb/phy/phy-samsung-usb2.c b/drivers/usb/phy/phy-samsung-usb2.c
new file mode 100644
index 00000000000..45ffe036dac
--- /dev/null
+++ b/drivers/usb/phy/phy-samsung-usb2.c
@@ -0,0 +1,509 @@
+/* linux/drivers/usb/phy/phy-samsung-usb2.c
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * Author: Praveen Paneri <p.paneri@samsung.com>
+ *
+ * Samsung USB2.0 PHY transceiver; talks to S3C HS OTG controller, EHCI-S5P and
+ * OHCI-EXYNOS controllers.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/usb/otg.h>
+#include <linux/usb/samsung_usb_phy.h>
+#include <linux/platform_data/samsung-usbphy.h>
+
+#include "phy-samsung-usb.h"
+
+static int samsung_usbphy_set_host(struct usb_otg *otg, struct usb_bus *host)
+{
+ if (!otg)
+ return -ENODEV;
+
+ if (!otg->host)
+ otg->host = host;
+
+ return 0;
+}
+
+static bool exynos5_phyhost_is_on(void __iomem *regs)
+{
+ u32 reg;
+
+ reg = readl(regs + EXYNOS5_PHY_HOST_CTRL0);
+
+ return !(reg & HOST_CTRL0_SIDDQ);
+}
+
+static void samsung_exynos5_usb2phy_enable(struct samsung_usbphy *sphy)
+{
+ void __iomem *regs = sphy->regs;
+ u32 phyclk = sphy->ref_clk_freq;
+ u32 phyhost;
+ u32 phyotg;
+ u32 phyhsic;
+ u32 ehcictrl;
+ u32 ohcictrl;
+
+ /*
+ * phy_usage helps in keeping usage count for phy
+ * so that the first consumer enabling the phy is also
+ * the last consumer to disable it.
+ */
+
+ atomic_inc(&sphy->phy_usage);
+
+ if (exynos5_phyhost_is_on(regs)) {
+ dev_info(sphy->dev, "Already power on PHY\n");
+ return;
+ }
+
+ /* Host configuration */
+ phyhost = readl(regs + EXYNOS5_PHY_HOST_CTRL0);
+
+ /* phy reference clock configuration */
+ phyhost &= ~HOST_CTRL0_FSEL_MASK;
+ phyhost |= HOST_CTRL0_FSEL(phyclk);
+
+ /* host phy reset */
+ phyhost &= ~(HOST_CTRL0_PHYSWRST |
+ HOST_CTRL0_PHYSWRSTALL |
+ HOST_CTRL0_SIDDQ |
+ /* Enable normal mode of operation */
+ HOST_CTRL0_FORCESUSPEND |
+ HOST_CTRL0_FORCESLEEP);
+
+ /* Link reset */
+ phyhost |= (HOST_CTRL0_LINKSWRST |
+ HOST_CTRL0_UTMISWRST |
+ /* COMMON Block configuration during suspend */
+ HOST_CTRL0_COMMONON_N);
+ writel(phyhost, regs + EXYNOS5_PHY_HOST_CTRL0);
+ udelay(10);
+ phyhost &= ~(HOST_CTRL0_LINKSWRST |
+ HOST_CTRL0_UTMISWRST);
+ writel(phyhost, regs + EXYNOS5_PHY_HOST_CTRL0);
+
+ /* OTG configuration */
+ phyotg = readl(regs + EXYNOS5_PHY_OTG_SYS);
+
+ /* phy reference clock configuration */
+ phyotg &= ~OTG_SYS_FSEL_MASK;
+ phyotg |= OTG_SYS_FSEL(phyclk);
+
+ /* Enable normal mode of operation */
+ phyotg &= ~(OTG_SYS_FORCESUSPEND |
+ OTG_SYS_SIDDQ_UOTG |
+ OTG_SYS_FORCESLEEP |
+ OTG_SYS_REFCLKSEL_MASK |
+ /* COMMON Block configuration during suspend */
+ OTG_SYS_COMMON_ON);
+
+ /* OTG phy & link reset */
+ phyotg |= (OTG_SYS_PHY0_SWRST |
+ OTG_SYS_LINKSWRST_UOTG |
+ OTG_SYS_PHYLINK_SWRESET |
+ OTG_SYS_OTGDISABLE |
+ /* Set phy refclk */
+ OTG_SYS_REFCLKSEL_CLKCORE);
+
+ writel(phyotg, regs + EXYNOS5_PHY_OTG_SYS);
+ udelay(10);
+ phyotg &= ~(OTG_SYS_PHY0_SWRST |
+ OTG_SYS_LINKSWRST_UOTG |
+ OTG_SYS_PHYLINK_SWRESET);
+ writel(phyotg, regs + EXYNOS5_PHY_OTG_SYS);
+
+ /* HSIC phy configuration */
+ phyhsic = (HSIC_CTRL_REFCLKDIV_12 |
+ HSIC_CTRL_REFCLKSEL |
+ HSIC_CTRL_PHYSWRST);
+ writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL1);
+ writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL2);
+ udelay(10);
+ phyhsic &= ~HSIC_CTRL_PHYSWRST;
+ writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL1);
+ writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL2);
+
+ udelay(80);
+
+ /* enable EHCI DMA burst */
+ ehcictrl = readl(regs + EXYNOS5_PHY_HOST_EHCICTRL);
+ ehcictrl |= (HOST_EHCICTRL_ENAINCRXALIGN |
+ HOST_EHCICTRL_ENAINCR4 |
+ HOST_EHCICTRL_ENAINCR8 |
+ HOST_EHCICTRL_ENAINCR16);
+ writel(ehcictrl, regs + EXYNOS5_PHY_HOST_EHCICTRL);
+
+ /* set ohci_suspend_on_n */
+ ohcictrl = readl(regs + EXYNOS5_PHY_HOST_OHCICTRL);
+ ohcictrl |= HOST_OHCICTRL_SUSPLGCY;
+ writel(ohcictrl, regs + EXYNOS5_PHY_HOST_OHCICTRL);
+}
+
+static void samsung_usb2phy_enable(struct samsung_usbphy *sphy)
+{
+ void __iomem *regs = sphy->regs;
+ u32 phypwr;
+ u32 phyclk;
+ u32 rstcon;
+
+ /* set clock frequency for PLL */
+ phyclk = sphy->ref_clk_freq;
+ phypwr = readl(regs + SAMSUNG_PHYPWR);
+ rstcon = readl(regs + SAMSUNG_RSTCON);
+
+ switch (sphy->drv_data->cpu_type) {
+ case TYPE_S3C64XX:
+ phyclk &= ~PHYCLK_COMMON_ON_N;
+ phypwr &= ~PHYPWR_NORMAL_MASK;
+ rstcon |= RSTCON_SWRST;
+ break;
+ case TYPE_EXYNOS4210:
+ phypwr &= ~PHYPWR_NORMAL_MASK_PHY0;
+ rstcon |= RSTCON_SWRST;
+ default:
+ break;
+ }
+
+ writel(phyclk, regs + SAMSUNG_PHYCLK);
+ /* Configure PHY0 for normal operation*/
+ writel(phypwr, regs + SAMSUNG_PHYPWR);
+ /* reset all ports of PHY and Link */
+ writel(rstcon, regs + SAMSUNG_RSTCON);
+ udelay(10);
+ rstcon &= ~RSTCON_SWRST;
+ writel(rstcon, regs + SAMSUNG_RSTCON);
+}
+
+static void samsung_exynos5_usb2phy_disable(struct samsung_usbphy *sphy)
+{
+ void __iomem *regs = sphy->regs;
+ u32 phyhost;
+ u32 phyotg;
+ u32 phyhsic;
+
+ if (atomic_dec_return(&sphy->phy_usage) > 0) {
+ dev_info(sphy->dev, "still being used\n");
+ return;
+ }
+
+ phyhsic = (HSIC_CTRL_REFCLKDIV_12 |
+ HSIC_CTRL_REFCLKSEL |
+ HSIC_CTRL_SIDDQ |
+ HSIC_CTRL_FORCESLEEP |
+ HSIC_CTRL_FORCESUSPEND);
+ writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL1);
+ writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL2);
+
+ phyhost = readl(regs + EXYNOS5_PHY_HOST_CTRL0);
+ phyhost |= (HOST_CTRL0_SIDDQ |
+ HOST_CTRL0_FORCESUSPEND |
+ HOST_CTRL0_FORCESLEEP |
+ HOST_CTRL0_PHYSWRST |
+ HOST_CTRL0_PHYSWRSTALL);
+ writel(phyhost, regs + EXYNOS5_PHY_HOST_CTRL0);
+
+ phyotg = readl(regs + EXYNOS5_PHY_OTG_SYS);
+ phyotg |= (OTG_SYS_FORCESUSPEND |
+ OTG_SYS_SIDDQ_UOTG |
+ OTG_SYS_FORCESLEEP);
+ writel(phyotg, regs + EXYNOS5_PHY_OTG_SYS);
+}
+
+static void samsung_usb2phy_disable(struct samsung_usbphy *sphy)
+{
+ void __iomem *regs = sphy->regs;
+ u32 phypwr;
+
+ phypwr = readl(regs + SAMSUNG_PHYPWR);
+
+ switch (sphy->drv_data->cpu_type) {
+ case TYPE_S3C64XX:
+ phypwr |= PHYPWR_NORMAL_MASK;
+ break;
+ case TYPE_EXYNOS4210:
+ phypwr |= PHYPWR_NORMAL_MASK_PHY0;
+ default:
+ break;
+ }
+
+ /* Disable analog and otg block power */
+ writel(phypwr, regs + SAMSUNG_PHYPWR);
+}
+
+/*
+ * The function passed to the usb driver for phy initialization
+ */
+static int samsung_usb2phy_init(struct usb_phy *phy)
+{
+ struct samsung_usbphy *sphy;
+ struct usb_bus *host = NULL;
+ unsigned long flags;
+ int ret = 0;
+
+ sphy = phy_to_sphy(phy);
+
+ host = phy->otg->host;
+
+ /* Enable the phy clock */
+ ret = clk_prepare_enable(sphy->clk);
+ if (ret) {
+ dev_err(sphy->dev, "%s: clk_prepare_enable failed\n", __func__);
+ return ret;
+ }
+
+ spin_lock_irqsave(&sphy->lock, flags);
+
+ if (host) {
+ /* setting default phy-type for USB 2.0 */
+ if (!strstr(dev_name(host->controller), "ehci") ||
+ !strstr(dev_name(host->controller), "ohci"))
+ samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_HOST);
+ } else {
+ samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_DEVICE);
+ }
+
+ /* Disable phy isolation */
+ if (sphy->plat && sphy->plat->pmu_isolation)
+ sphy->plat->pmu_isolation(false);
+ else
+ samsung_usbphy_set_isolation(sphy, false);
+
+ /* Selecting Host/OTG mode; After reset USB2.0PHY_CFG: HOST */
+ samsung_usbphy_cfg_sel(sphy);
+
+ /* Initialize usb phy registers */
+ if (sphy->drv_data->cpu_type == TYPE_EXYNOS5250)
+ samsung_exynos5_usb2phy_enable(sphy);
+ else
+ samsung_usb2phy_enable(sphy);
+
+ spin_unlock_irqrestore(&sphy->lock, flags);
+
+ /* Disable the phy clock */
+ clk_disable_unprepare(sphy->clk);
+
+ return ret;
+}
+
+/*
+ * The function passed to the usb driver for phy shutdown
+ */
+static void samsung_usb2phy_shutdown(struct usb_phy *phy)
+{
+ struct samsung_usbphy *sphy;
+ struct usb_bus *host = NULL;
+ unsigned long flags;
+
+ sphy = phy_to_sphy(phy);
+
+ host = phy->otg->host;
+
+ if (clk_prepare_enable(sphy->clk)) {
+ dev_err(sphy->dev, "%s: clk_prepare_enable failed\n", __func__);
+ return;
+ }
+
+ spin_lock_irqsave(&sphy->lock, flags);
+
+ if (host) {
+ /* setting default phy-type for USB 2.0 */
+ if (!strstr(dev_name(host->controller), "ehci") ||
+ !strstr(dev_name(host->controller), "ohci"))
+ samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_HOST);
+ } else {
+ samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_DEVICE);
+ }
+
+ /* De-initialize usb phy registers */
+ if (sphy->drv_data->cpu_type == TYPE_EXYNOS5250)
+ samsung_exynos5_usb2phy_disable(sphy);
+ else
+ samsung_usb2phy_disable(sphy);
+
+ /* Enable phy isolation */
+ if (sphy->plat && sphy->plat->pmu_isolation)
+ sphy->plat->pmu_isolation(true);
+ else
+ samsung_usbphy_set_isolation(sphy, true);
+
+ spin_unlock_irqrestore(&sphy->lock, flags);
+
+ clk_disable_unprepare(sphy->clk);
+}
+
+static int samsung_usb2phy_probe(struct platform_device *pdev)
+{
+ struct samsung_usbphy *sphy;
+ struct usb_otg *otg;
+ struct samsung_usbphy_data *pdata = pdev->dev.platform_data;
+ const struct samsung_usbphy_drvdata *drv_data;
+ struct device *dev = &pdev->dev;
+ struct resource *phy_mem;
+ void __iomem *phy_base;
+ struct clk *clk;
+ int ret;
+
+ phy_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!phy_mem) {
+ dev_err(dev, "%s: missing mem resource\n", __func__);
+ return -ENODEV;
+ }
+
+ phy_base = devm_ioremap_resource(dev, phy_mem);
+ if (IS_ERR(phy_base))
+ return PTR_ERR(phy_base);
+
+ sphy = devm_kzalloc(dev, sizeof(*sphy), GFP_KERNEL);
+ if (!sphy)
+ return -ENOMEM;
+
+ otg = devm_kzalloc(dev, sizeof(*otg), GFP_KERNEL);
+ if (!otg)
+ return -ENOMEM;
+
+ drv_data = samsung_usbphy_get_driver_data(pdev);
+
+ if (drv_data->cpu_type == TYPE_EXYNOS5250)
+ clk = devm_clk_get(dev, "usbhost");
+ else
+ clk = devm_clk_get(dev, "otg");
+
+ if (IS_ERR(clk)) {
+ dev_err(dev, "Failed to get otg clock\n");
+ return PTR_ERR(clk);
+ }
+
+ sphy->dev = dev;
+
+ if (dev->of_node) {
+ ret = samsung_usbphy_parse_dt(sphy);
+ if (ret < 0)
+ return ret;
+ } else {
+ if (!pdata) {
+ dev_err(dev, "no platform data specified\n");
+ return -EINVAL;
+ }
+ }
+
+ sphy->plat = pdata;
+ sphy->regs = phy_base;
+ sphy->clk = clk;
+ sphy->drv_data = drv_data;
+ sphy->phy.dev = sphy->dev;
+ sphy->phy.label = "samsung-usb2phy";
+ sphy->phy.init = samsung_usb2phy_init;
+ sphy->phy.shutdown = samsung_usb2phy_shutdown;
+ sphy->ref_clk_freq = samsung_usbphy_get_refclk_freq(sphy);
+
+ sphy->phy.otg = otg;
+ sphy->phy.otg->phy = &sphy->phy;
+ sphy->phy.otg->set_host = samsung_usbphy_set_host;
+
+ spin_lock_init(&sphy->lock);
+
+ platform_set_drvdata(pdev, sphy);
+
+ return usb_add_phy(&sphy->phy, USB_PHY_TYPE_USB2);
+}
+
+static int samsung_usb2phy_remove(struct platform_device *pdev)
+{
+ struct samsung_usbphy *sphy = platform_get_drvdata(pdev);
+
+ usb_remove_phy(&sphy->phy);
+
+ if (sphy->pmuregs)
+ iounmap(sphy->pmuregs);
+ if (sphy->sysreg)
+ iounmap(sphy->sysreg);
+
+ return 0;
+}
+
+static const struct samsung_usbphy_drvdata usb2phy_s3c64xx = {
+ .cpu_type = TYPE_S3C64XX,
+ .devphy_en_mask = S3C64XX_USBPHY_ENABLE,
+};
+
+static const struct samsung_usbphy_drvdata usb2phy_exynos4 = {
+ .cpu_type = TYPE_EXYNOS4210,
+ .devphy_en_mask = EXYNOS_USBPHY_ENABLE,
+ .hostphy_en_mask = EXYNOS_USBPHY_ENABLE,
+};
+
+static struct samsung_usbphy_drvdata usb2phy_exynos5 = {
+ .cpu_type = TYPE_EXYNOS5250,
+ .hostphy_en_mask = EXYNOS_USBPHY_ENABLE,
+ .hostphy_reg_offset = EXYNOS_USBHOST_PHY_CTRL_OFFSET,
+};
+
+#ifdef CONFIG_OF
+static const struct of_device_id samsung_usbphy_dt_match[] = {
+ {
+ .compatible = "samsung,s3c64xx-usb2phy",
+ .data = &usb2phy_s3c64xx,
+ }, {
+ .compatible = "samsung,exynos4210-usb2phy",
+ .data = &usb2phy_exynos4,
+ }, {
+ .compatible = "samsung,exynos5250-usb2phy",
+ .data = &usb2phy_exynos5
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(of, samsung_usbphy_dt_match);
+#endif
+
+static struct platform_device_id samsung_usbphy_driver_ids[] = {
+ {
+ .name = "s3c64xx-usb2phy",
+ .driver_data = (unsigned long)&usb2phy_s3c64xx,
+ }, {
+ .name = "exynos4210-usb2phy",
+ .driver_data = (unsigned long)&usb2phy_exynos4,
+ }, {
+ .name = "exynos5250-usb2phy",
+ .driver_data = (unsigned long)&usb2phy_exynos5,
+ },
+ {},
+};
+
+MODULE_DEVICE_TABLE(platform, samsung_usbphy_driver_ids);
+
+static struct platform_driver samsung_usb2phy_driver = {
+ .probe = samsung_usb2phy_probe,
+ .remove = samsung_usb2phy_remove,
+ .id_table = samsung_usbphy_driver_ids,
+ .driver = {
+ .name = "samsung-usb2phy",
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(samsung_usbphy_dt_match),
+ },
+};
+
+module_platform_driver(samsung_usb2phy_driver);
+
+MODULE_DESCRIPTION("Samsung USB 2.0 phy controller");
+MODULE_AUTHOR("Praveen Paneri <p.paneri@samsung.com>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:samsung-usb2phy");
diff --git a/drivers/usb/phy/phy-samsung-usb3.c b/drivers/usb/phy/phy-samsung-usb3.c
new file mode 100644
index 00000000000..133f3d0c554
--- /dev/null
+++ b/drivers/usb/phy/phy-samsung-usb3.c
@@ -0,0 +1,347 @@
+/* linux/drivers/usb/phy/phy-samsung-usb3.c
+ *
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * Author: Vivek Gautam <gautam.vivek@samsung.com>
+ *
+ * Samsung USB 3.0 PHY transceiver; talks to DWC3 controller.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/usb/samsung_usb_phy.h>
+#include <linux/platform_data/samsung-usbphy.h>
+
+#include "phy-samsung-usb.h"
+
+/*
+ * Sets the phy clk as EXTREFCLK (XXTI) which is internal clock from clock core.
+ */
+static u32 samsung_usb3phy_set_refclk(struct samsung_usbphy *sphy)
+{
+ u32 reg;
+ u32 refclk;
+
+ refclk = sphy->ref_clk_freq;
+
+ reg = PHYCLKRST_REFCLKSEL_EXT_REFCLK |
+ PHYCLKRST_FSEL(refclk);
+
+ switch (refclk) {
+ case FSEL_CLKSEL_50M:
+ reg |= (PHYCLKRST_MPLL_MULTIPLIER_50M_REF |
+ PHYCLKRST_SSC_REFCLKSEL(0x00));
+ break;
+ case FSEL_CLKSEL_20M:
+ reg |= (PHYCLKRST_MPLL_MULTIPLIER_20MHZ_REF |
+ PHYCLKRST_SSC_REFCLKSEL(0x00));
+ break;
+ case FSEL_CLKSEL_19200K:
+ reg |= (PHYCLKRST_MPLL_MULTIPLIER_19200KHZ_REF |
+ PHYCLKRST_SSC_REFCLKSEL(0x88));
+ break;
+ case FSEL_CLKSEL_24M:
+ default:
+ reg |= (PHYCLKRST_MPLL_MULTIPLIER_24MHZ_REF |
+ PHYCLKRST_SSC_REFCLKSEL(0x88));
+ break;
+ }
+
+ return reg;
+}
+
+static int samsung_exynos5_usb3phy_enable(struct samsung_usbphy *sphy)
+{
+ void __iomem *regs = sphy->regs;
+ u32 phyparam0;
+ u32 phyparam1;
+ u32 linksystem;
+ u32 phybatchg;
+ u32 phytest;
+ u32 phyclkrst;
+
+ /* Reset USB 3.0 PHY */
+ writel(0x0, regs + EXYNOS5_DRD_PHYREG0);
+
+ phyparam0 = readl(regs + EXYNOS5_DRD_PHYPARAM0);
+ /* Select PHY CLK source */
+ phyparam0 &= ~PHYPARAM0_REF_USE_PAD;
+ /* Set Loss-of-Signal Detector sensitivity */
+ phyparam0 &= ~PHYPARAM0_REF_LOSLEVEL_MASK;
+ phyparam0 |= PHYPARAM0_REF_LOSLEVEL;
+ writel(phyparam0, regs + EXYNOS5_DRD_PHYPARAM0);
+
+ writel(0x0, regs + EXYNOS5_DRD_PHYRESUME);
+
+ /*
+ * Setting the Frame length Adj value[6:1] to default 0x20
+ * See xHCI 1.0 spec, 5.2.4
+ */
+ linksystem = LINKSYSTEM_XHCI_VERSION_CONTROL |
+ LINKSYSTEM_FLADJ(0x20);
+ writel(linksystem, regs + EXYNOS5_DRD_LINKSYSTEM);
+
+ phyparam1 = readl(regs + EXYNOS5_DRD_PHYPARAM1);
+ /* Set Tx De-Emphasis level */
+ phyparam1 &= ~PHYPARAM1_PCS_TXDEEMPH_MASK;
+ phyparam1 |= PHYPARAM1_PCS_TXDEEMPH;
+ writel(phyparam1, regs + EXYNOS5_DRD_PHYPARAM1);
+
+ phybatchg = readl(regs + EXYNOS5_DRD_PHYBATCHG);
+ phybatchg |= PHYBATCHG_UTMI_CLKSEL;
+ writel(phybatchg, regs + EXYNOS5_DRD_PHYBATCHG);
+
+ /* PHYTEST POWERDOWN Control */
+ phytest = readl(regs + EXYNOS5_DRD_PHYTEST);
+ phytest &= ~(PHYTEST_POWERDOWN_SSP |
+ PHYTEST_POWERDOWN_HSP);
+ writel(phytest, regs + EXYNOS5_DRD_PHYTEST);
+
+ /* UTMI Power Control */
+ writel(PHYUTMI_OTGDISABLE, regs + EXYNOS5_DRD_PHYUTMI);
+
+ phyclkrst = samsung_usb3phy_set_refclk(sphy);
+
+ phyclkrst |= PHYCLKRST_PORTRESET |
+ /* Digital power supply in normal operating mode */
+ PHYCLKRST_RETENABLEN |
+ /* Enable ref clock for SS function */
+ PHYCLKRST_REF_SSP_EN |
+ /* Enable spread spectrum */
+ PHYCLKRST_SSC_EN |
+ /* Power down HS Bias and PLL blocks in suspend mode */
+ PHYCLKRST_COMMONONN;
+
+ writel(phyclkrst, regs + EXYNOS5_DRD_PHYCLKRST);
+
+ udelay(10);
+
+ phyclkrst &= ~(PHYCLKRST_PORTRESET);
+ writel(phyclkrst, regs + EXYNOS5_DRD_PHYCLKRST);
+
+ return 0;
+}
+
+static void samsung_exynos5_usb3phy_disable(struct samsung_usbphy *sphy)
+{
+ u32 phyutmi;
+ u32 phyclkrst;
+ u32 phytest;
+ void __iomem *regs = sphy->regs;
+
+ phyutmi = PHYUTMI_OTGDISABLE |
+ PHYUTMI_FORCESUSPEND |
+ PHYUTMI_FORCESLEEP;
+ writel(phyutmi, regs + EXYNOS5_DRD_PHYUTMI);
+
+ /* Resetting the PHYCLKRST enable bits to reduce leakage current */
+ phyclkrst = readl(regs + EXYNOS5_DRD_PHYCLKRST);
+ phyclkrst &= ~(PHYCLKRST_REF_SSP_EN |
+ PHYCLKRST_SSC_EN |
+ PHYCLKRST_COMMONONN);
+ writel(phyclkrst, regs + EXYNOS5_DRD_PHYCLKRST);
+
+ /* Control PHYTEST to remove leakage current */
+ phytest = readl(regs + EXYNOS5_DRD_PHYTEST);
+ phytest |= (PHYTEST_POWERDOWN_SSP |
+ PHYTEST_POWERDOWN_HSP);
+ writel(phytest, regs + EXYNOS5_DRD_PHYTEST);
+}
+
+static int samsung_usb3phy_init(struct usb_phy *phy)
+{
+ struct samsung_usbphy *sphy;
+ unsigned long flags;
+ int ret = 0;
+
+ sphy = phy_to_sphy(phy);
+
+ /* Enable the phy clock */
+ ret = clk_prepare_enable(sphy->clk);
+ if (ret) {
+ dev_err(sphy->dev, "%s: clk_prepare_enable failed\n", __func__);
+ return ret;
+ }
+
+ spin_lock_irqsave(&sphy->lock, flags);
+
+ /* setting default phy-type for USB 3.0 */
+ samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_DEVICE);
+
+ /* Disable phy isolation */
+ samsung_usbphy_set_isolation(sphy, false);
+
+ /* Initialize usb phy registers */
+ samsung_exynos5_usb3phy_enable(sphy);
+
+ spin_unlock_irqrestore(&sphy->lock, flags);
+
+ /* Disable the phy clock */
+ clk_disable_unprepare(sphy->clk);
+
+ return ret;
+}
+
+/*
+ * The function passed to the usb driver for phy shutdown
+ */
+static void samsung_usb3phy_shutdown(struct usb_phy *phy)
+{
+ struct samsung_usbphy *sphy;
+ unsigned long flags;
+
+ sphy = phy_to_sphy(phy);
+
+ if (clk_prepare_enable(sphy->clk)) {
+ dev_err(sphy->dev, "%s: clk_prepare_enable failed\n", __func__);
+ return;
+ }
+
+ spin_lock_irqsave(&sphy->lock, flags);
+
+ /* setting default phy-type for USB 3.0 */
+ samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_DEVICE);
+
+ /* De-initialize usb phy registers */
+ samsung_exynos5_usb3phy_disable(sphy);
+
+ /* Enable phy isolation */
+ samsung_usbphy_set_isolation(sphy, true);
+
+ spin_unlock_irqrestore(&sphy->lock, flags);
+
+ clk_disable_unprepare(sphy->clk);
+}
+
+static int samsung_usb3phy_probe(struct platform_device *pdev)
+{
+ struct samsung_usbphy *sphy;
+ struct samsung_usbphy_data *pdata = pdev->dev.platform_data;
+ struct device *dev = &pdev->dev;
+ struct resource *phy_mem;
+ void __iomem *phy_base;
+ struct clk *clk;
+ int ret;
+
+ phy_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!phy_mem) {
+ dev_err(dev, "%s: missing mem resource\n", __func__);
+ return -ENODEV;
+ }
+
+ phy_base = devm_ioremap_resource(dev, phy_mem);
+ if (IS_ERR(phy_base))
+ return PTR_ERR(phy_base);
+
+ sphy = devm_kzalloc(dev, sizeof(*sphy), GFP_KERNEL);
+ if (!sphy)
+ return -ENOMEM;
+
+ clk = devm_clk_get(dev, "usbdrd30");
+ if (IS_ERR(clk)) {
+ dev_err(dev, "Failed to get device clock\n");
+ return PTR_ERR(clk);
+ }
+
+ sphy->dev = dev;
+
+ if (dev->of_node) {
+ ret = samsung_usbphy_parse_dt(sphy);
+ if (ret < 0)
+ return ret;
+ } else {
+ if (!pdata) {
+ dev_err(dev, "no platform data specified\n");
+ return -EINVAL;
+ }
+ }
+
+ sphy->plat = pdata;
+ sphy->regs = phy_base;
+ sphy->clk = clk;
+ sphy->phy.dev = sphy->dev;
+ sphy->phy.label = "samsung-usb3phy";
+ sphy->phy.init = samsung_usb3phy_init;
+ sphy->phy.shutdown = samsung_usb3phy_shutdown;
+ sphy->drv_data = samsung_usbphy_get_driver_data(pdev);
+ sphy->ref_clk_freq = samsung_usbphy_get_refclk_freq(sphy);
+
+ spin_lock_init(&sphy->lock);
+
+ platform_set_drvdata(pdev, sphy);
+
+ return usb_add_phy(&sphy->phy, USB_PHY_TYPE_USB3);
+}
+
+static int samsung_usb3phy_remove(struct platform_device *pdev)
+{
+ struct samsung_usbphy *sphy = platform_get_drvdata(pdev);
+
+ usb_remove_phy(&sphy->phy);
+
+ if (sphy->pmuregs)
+ iounmap(sphy->pmuregs);
+ if (sphy->sysreg)
+ iounmap(sphy->sysreg);
+
+ return 0;
+}
+
+static struct samsung_usbphy_drvdata usb3phy_exynos5 = {
+ .cpu_type = TYPE_EXYNOS5250,
+ .devphy_en_mask = EXYNOS_USBPHY_ENABLE,
+};
+
+#ifdef CONFIG_OF
+static const struct of_device_id samsung_usbphy_dt_match[] = {
+ {
+ .compatible = "samsung,exynos5250-usb3phy",
+ .data = &usb3phy_exynos5
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(of, samsung_usbphy_dt_match);
+#endif
+
+static struct platform_device_id samsung_usbphy_driver_ids[] = {
+ {
+ .name = "exynos5250-usb3phy",
+ .driver_data = (unsigned long)&usb3phy_exynos5,
+ },
+ {},
+};
+
+MODULE_DEVICE_TABLE(platform, samsung_usbphy_driver_ids);
+
+static struct platform_driver samsung_usb3phy_driver = {
+ .probe = samsung_usb3phy_probe,
+ .remove = samsung_usb3phy_remove,
+ .id_table = samsung_usbphy_driver_ids,
+ .driver = {
+ .name = "samsung-usb3phy",
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(samsung_usbphy_dt_match),
+ },
+};
+
+module_platform_driver(samsung_usb3phy_driver);
+
+MODULE_DESCRIPTION("Samsung USB 3.0 phy controller");
+MODULE_AUTHOR("Vivek Gautam <gautam.vivek@samsung.com>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:samsung-usb3phy");
diff --git a/drivers/usb/phy/tegra_usb_phy.c b/drivers/usb/phy/phy-tegra-usb.c
index 5487d38481a..17d811292f3 100644
--- a/drivers/usb/phy/tegra_usb_phy.c
+++ b/drivers/usb/phy/phy-tegra-usb.c
@@ -299,7 +299,7 @@ static void utmi_phy_clk_disable(struct tegra_usb_phy *phy)
val &= ~USB_SUSP_SET;
writel(val, base + USB_SUSP_CTRL);
} else
- tegra_ehci_set_phcd(&phy->u_phy, true);
+ phy->set_phcd(&phy->u_phy, true);
if (utmi_wait_register(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID, 0) < 0)
pr_err("%s: timeout waiting for phy to stabilize\n", __func__);
@@ -321,7 +321,7 @@ static void utmi_phy_clk_enable(struct tegra_usb_phy *phy)
val &= ~USB_SUSP_CLR;
writel(val, base + USB_SUSP_CTRL);
} else
- tegra_ehci_set_phcd(&phy->u_phy, false);
+ phy->set_phcd(&phy->u_phy, false);
if (utmi_wait_register(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID,
USB_PHY_CLK_VALID))
@@ -444,7 +444,7 @@ static int utmi_phy_power_on(struct tegra_usb_phy *phy)
utmi_phy_clk_enable(phy);
if (!phy->is_legacy_phy)
- tegra_ehci_set_pts(&phy->u_phy, 0);
+ phy->set_pts(&phy->u_phy, 0);
return 0;
}
@@ -688,7 +688,10 @@ static int tegra_usb_phy_suspend(struct usb_phy *x, int suspend)
}
struct tegra_usb_phy *tegra_usb_phy_open(struct device *dev, int instance,
- void __iomem *regs, void *config, enum tegra_usb_phy_mode phy_mode)
+ void __iomem *regs, void *config, enum tegra_usb_phy_mode phy_mode,
+ void (*set_pts)(struct usb_phy *x, u8 pts_val),
+ void (*set_phcd)(struct usb_phy *x, bool enable))
+
{
struct tegra_usb_phy *phy;
unsigned long parent_rate;
@@ -707,6 +710,8 @@ struct tegra_usb_phy *tegra_usb_phy_open(struct device *dev, int instance,
phy->dev = dev;
phy->is_legacy_phy =
of_property_read_bool(np, "nvidia,has-legacy-mode");
+ phy->set_pts = set_pts;
+ phy->set_phcd = set_phcd;
err = of_property_match_string(np, "phy_type", "ulpi");
if (err < 0)
phy->is_ulpi_phy = false;
diff --git a/drivers/usb/otg/twl4030-usb.c b/drivers/usb/phy/phy-twl4030-usb.c
index a994715a310..8f78d2d4072 100644
--- a/drivers/usb/otg/twl4030-usb.c
+++ b/drivers/usb/phy/phy-twl4030-usb.c
@@ -163,6 +163,8 @@ struct twl4030_usb {
bool vbus_supplied;
u8 asleep;
bool irq_enabled;
+
+ struct delayed_work id_workaround_work;
};
/* internal define on top of container_of */
@@ -246,6 +248,25 @@ twl4030_usb_clear_bits(struct twl4030_usb *twl, u8 reg, u8 bits)
/*-------------------------------------------------------------------------*/
+static bool twl4030_is_driving_vbus(struct twl4030_usb *twl)
+{
+ int ret;
+
+ ret = twl4030_usb_read(twl, PHY_CLK_CTRL_STS);
+ if (ret < 0 || !(ret & PHY_DPLL_CLK))
+ /*
+ * if clocks are off, registers are not updated,
+ * but we can assume we don't drive VBUS in this case
+ */
+ return false;
+
+ ret = twl4030_usb_read(twl, ULPI_OTG_CTRL);
+ if (ret < 0)
+ return false;
+
+ return (ret & (ULPI_OTG_DRVVBUS | ULPI_OTG_CHRGVBUS)) ? true : false;
+}
+
static enum omap_musb_vbus_id_status
twl4030_usb_linkstat(struct twl4030_usb *twl)
{
@@ -268,13 +289,19 @@ static enum omap_musb_vbus_id_status
if (status < 0)
dev_err(twl->dev, "USB link status err %d\n", status);
else if (status & (BIT(7) | BIT(2))) {
- if (status & (BIT(7)))
- twl->vbus_supplied = true;
+ if (status & BIT(7)) {
+ if (twl4030_is_driving_vbus(twl))
+ status &= ~BIT(7);
+ else
+ twl->vbus_supplied = true;
+ }
if (status & BIT(2))
linkstat = OMAP_MUSB_ID_GROUND;
- else
+ else if (status & BIT(7))
linkstat = OMAP_MUSB_VBUS_VALID;
+ else
+ linkstat = OMAP_MUSB_VBUS_OFF;
} else {
if (twl->linkstat != OMAP_MUSB_UNKNOWN)
linkstat = OMAP_MUSB_VBUS_OFF;
@@ -287,10 +314,6 @@ static enum omap_musb_vbus_id_status
* are registered, and that both are active...
*/
- spin_lock_irq(&twl->lock);
- twl->linkstat = linkstat;
- spin_unlock_irq(&twl->lock);
-
return linkstat;
}
@@ -361,9 +384,17 @@ static void __twl4030_phy_power(struct twl4030_usb *twl, int on)
static void twl4030_phy_power(struct twl4030_usb *twl, int on)
{
+ int ret;
+
if (on) {
- regulator_enable(twl->usb3v1);
- regulator_enable(twl->usb1v8);
+ ret = regulator_enable(twl->usb3v1);
+ if (ret)
+ dev_err(twl->dev, "Failed to enable usb3v1\n");
+
+ ret = regulator_enable(twl->usb1v8);
+ if (ret)
+ dev_err(twl->dev, "Failed to enable usb1v8\n");
+
/*
* Disabling usb3v1 regulator (= writing 0 to VUSB3V1_DEV_GRP
* in twl4030) resets the VUSB_DEDICATED2 register. This reset
@@ -372,7 +403,11 @@ static void twl4030_phy_power(struct twl4030_usb *twl, int on)
* is re-activated. This ensures that VUSB3V1 is really active.
*/
twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB_DEDICATED2);
- regulator_enable(twl->usb1v5);
+
+ ret = regulator_enable(twl->usb1v5);
+ if (ret)
+ dev_err(twl->dev, "Failed to enable usb1v5\n");
+
__twl4030_phy_power(twl, 1);
twl4030_usb_write(twl, PHY_CLK_CTRL,
twl4030_usb_read(twl, PHY_CLK_CTRL) |
@@ -412,6 +447,16 @@ static void twl4030_phy_resume(struct twl4030_usb *twl)
__twl4030_phy_resume(twl);
twl->asleep = 0;
dev_dbg(twl->dev, "%s\n", __func__);
+
+ /*
+ * XXX When VBUS gets driven after musb goes to A mode,
+ * ID_PRES related interrupts no longer arrive, why?
+ * Register itself is updated fine though, so we must poll.
+ */
+ if (twl->linkstat == OMAP_MUSB_ID_GROUND) {
+ cancel_delayed_work(&twl->id_workaround_work);
+ schedule_delayed_work(&twl->id_workaround_work, HZ);
+ }
}
static int twl4030_usb_ldo_init(struct twl4030_usb *twl)
@@ -432,7 +477,7 @@ static int twl4030_usb_ldo_init(struct twl4030_usb *twl)
/* Initialize 3.1V regulator */
twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB3V1_DEV_GRP);
- twl->usb3v1 = regulator_get(twl->dev, "usb3v1");
+ twl->usb3v1 = devm_regulator_get(twl->dev, "usb3v1");
if (IS_ERR(twl->usb3v1))
return -ENODEV;
@@ -441,18 +486,18 @@ static int twl4030_usb_ldo_init(struct twl4030_usb *twl)
/* Initialize 1.5V regulator */
twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB1V5_DEV_GRP);
- twl->usb1v5 = regulator_get(twl->dev, "usb1v5");
+ twl->usb1v5 = devm_regulator_get(twl->dev, "usb1v5");
if (IS_ERR(twl->usb1v5))
- goto fail1;
+ return -ENODEV;
twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB1V5_TYPE);
/* Initialize 1.8V regulator */
twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB1V8_DEV_GRP);
- twl->usb1v8 = regulator_get(twl->dev, "usb1v8");
+ twl->usb1v8 = devm_regulator_get(twl->dev, "usb1v8");
if (IS_ERR(twl->usb1v8))
- goto fail2;
+ return -ENODEV;
twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB1V8_TYPE);
@@ -461,14 +506,6 @@ static int twl4030_usb_ldo_init(struct twl4030_usb *twl)
TWL4030_PM_MASTER_PROTECT_KEY);
return 0;
-
-fail2:
- regulator_put(twl->usb1v5);
- twl->usb1v5 = NULL;
-fail1:
- regulator_put(twl->usb3v1);
- twl->usb3v1 = NULL;
- return -ENODEV;
}
static ssize_t twl4030_usb_vbus_show(struct device *dev,
@@ -491,9 +528,18 @@ static irqreturn_t twl4030_usb_irq(int irq, void *_twl)
{
struct twl4030_usb *twl = _twl;
enum omap_musb_vbus_id_status status;
+ bool status_changed = false;
status = twl4030_usb_linkstat(twl);
- if (status > 0) {
+
+ spin_lock_irq(&twl->lock);
+ if (status >= 0 && status != twl->linkstat) {
+ twl->linkstat = status;
+ status_changed = true;
+ }
+ spin_unlock_irq(&twl->lock);
+
+ if (status_changed) {
/* FIXME add a set_power() method so that B-devices can
* configure the charger appropriately. It's not always
* correct to consume VBUS power, and how much current to
@@ -505,37 +551,62 @@ static irqreturn_t twl4030_usb_irq(int irq, void *_twl)
* USB_LINK_VBUS state. musb_hdrc won't care until it
* starts to handle softconnect right.
*/
- if (status == OMAP_MUSB_VBUS_OFF ||
- status == OMAP_MUSB_ID_FLOAT)
- twl4030_phy_suspend(twl, 0);
- else
- twl4030_phy_resume(twl);
-
- omap_musb_mailbox(twl->linkstat);
+ omap_musb_mailbox(status);
}
sysfs_notify(&twl->dev->kobj, NULL, "vbus");
return IRQ_HANDLED;
}
-static void twl4030_usb_phy_init(struct twl4030_usb *twl)
+static void twl4030_id_workaround_work(struct work_struct *work)
{
+ struct twl4030_usb *twl = container_of(work, struct twl4030_usb,
+ id_workaround_work.work);
enum omap_musb_vbus_id_status status;
+ bool status_changed = false;
status = twl4030_usb_linkstat(twl);
- if (status > 0) {
- if (status == OMAP_MUSB_VBUS_OFF ||
- status == OMAP_MUSB_ID_FLOAT) {
- __twl4030_phy_power(twl, 0);
- twl->asleep = 1;
- } else {
- __twl4030_phy_resume(twl);
- twl->asleep = 0;
- }
- omap_musb_mailbox(twl->linkstat);
+ spin_lock_irq(&twl->lock);
+ if (status >= 0 && status != twl->linkstat) {
+ twl->linkstat = status;
+ status_changed = true;
+ }
+ spin_unlock_irq(&twl->lock);
+
+ if (status_changed) {
+ dev_dbg(twl->dev, "handle missing status change to %d\n",
+ status);
+ omap_musb_mailbox(status);
}
+
+ /* don't schedule during sleep - irq works right then */
+ if (status == OMAP_MUSB_ID_GROUND && !twl->asleep) {
+ cancel_delayed_work(&twl->id_workaround_work);
+ schedule_delayed_work(&twl->id_workaround_work, HZ);
+ }
+}
+
+static int twl4030_usb_phy_init(struct usb_phy *phy)
+{
+ struct twl4030_usb *twl = phy_to_twl(phy);
+ enum omap_musb_vbus_id_status status;
+
+ /*
+ * Start in sleep state, we'll get called through set_suspend()
+ * callback when musb is runtime resumed and it's time to start.
+ */
+ __twl4030_phy_power(twl, 0);
+ twl->asleep = 1;
+
+ status = twl4030_usb_linkstat(twl);
+ twl->linkstat = status;
+
+ if (status == OMAP_MUSB_ID_GROUND || status == OMAP_MUSB_VBUS_VALID)
+ omap_musb_mailbox(twl->linkstat);
+
sysfs_notify(&twl->dev->kobj, NULL, "vbus");
+ return 0;
}
static int twl4030_set_suspend(struct usb_phy *x, int suspend)
@@ -612,6 +683,7 @@ static int twl4030_usb_probe(struct platform_device *pdev)
twl->phy.otg = otg;
twl->phy.type = USB_PHY_TYPE_USB2;
twl->phy.set_suspend = twl4030_set_suspend;
+ twl->phy.init = twl4030_usb_phy_init;
otg->phy = &twl->phy;
otg->set_host = twl4030_set_host;
@@ -620,6 +692,8 @@ static int twl4030_usb_probe(struct platform_device *pdev)
/* init spinlock for workqueue */
spin_lock_init(&twl->lock);
+ INIT_DELAYED_WORK(&twl->id_workaround_work, twl4030_id_workaround_work);
+
err = twl4030_usb_ldo_init(twl);
if (err) {
dev_err(&pdev->dev, "ldo init failed\n");
@@ -640,30 +714,25 @@ static int twl4030_usb_probe(struct platform_device *pdev)
* need both handles, otherwise just one suffices.
*/
twl->irq_enabled = true;
- status = request_threaded_irq(twl->irq, NULL, twl4030_usb_irq,
- IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING |
- IRQF_ONESHOT, "twl4030_usb", twl);
+ status = devm_request_threaded_irq(twl->dev, twl->irq, NULL,
+ twl4030_usb_irq, IRQF_TRIGGER_FALLING |
+ IRQF_TRIGGER_RISING | IRQF_ONESHOT, "twl4030_usb", twl);
if (status < 0) {
dev_dbg(&pdev->dev, "can't get IRQ %d, err %d\n",
twl->irq, status);
return status;
}
- /* Power down phy or make it work according to
- * current link state.
- */
- twl4030_usb_phy_init(twl);
-
dev_info(&pdev->dev, "Initialized TWL4030 USB module\n");
return 0;
}
-static int __exit twl4030_usb_remove(struct platform_device *pdev)
+static int twl4030_usb_remove(struct platform_device *pdev)
{
struct twl4030_usb *twl = platform_get_drvdata(pdev);
int val;
- free_irq(twl->irq, twl);
+ cancel_delayed_work(&twl->id_workaround_work);
device_remove_file(twl->dev, &dev_attr_vbus);
/* set transceiver mode to power on defaults */
@@ -685,9 +754,6 @@ static int __exit twl4030_usb_remove(struct platform_device *pdev)
if (!twl->asleep)
twl4030_phy_power(twl, 0);
- regulator_put(twl->usb1v5);
- regulator_put(twl->usb1v8);
- regulator_put(twl->usb3v1);
return 0;
}
@@ -702,7 +768,7 @@ MODULE_DEVICE_TABLE(of, twl4030_usb_id_table);
static struct platform_driver twl4030_usb_driver = {
.probe = twl4030_usb_probe,
- .remove = __exit_p(twl4030_usb_remove),
+ .remove = twl4030_usb_remove,
.driver = {
.name = "twl4030_usb",
.owner = THIS_MODULE,
diff --git a/drivers/usb/otg/twl6030-usb.c b/drivers/usb/phy/phy-twl6030-usb.c
index 8cd6cf49bdb..9de7ada90a8 100644
--- a/drivers/usb/otg/twl6030-usb.c
+++ b/drivers/usb/phy/phy-twl6030-usb.c
@@ -211,6 +211,7 @@ static irqreturn_t twl6030_usb_irq(int irq, void *_twl)
struct twl6030_usb *twl = _twl;
enum omap_musb_vbus_id_status status = OMAP_MUSB_UNKNOWN;
u8 vbus_state, hw_state;
+ int ret;
hw_state = twl6030_readb(twl, TWL6030_MODULE_ID0, STS_HW_CONDITIONS);
@@ -218,7 +219,10 @@ static irqreturn_t twl6030_usb_irq(int irq, void *_twl)
CONTROLLER_STAT1);
if (!(hw_state & STS_USB_ID)) {
if (vbus_state & VBUS_DET) {
- regulator_enable(twl->usb3v3);
+ ret = regulator_enable(twl->usb3v3);
+ if (ret)
+ dev_err(twl->dev, "Failed to enable usb3v3\n");
+
twl->asleep = 1;
status = OMAP_MUSB_VBUS_VALID;
twl->linkstat = status;
@@ -245,12 +249,15 @@ static irqreturn_t twl6030_usbotg_irq(int irq, void *_twl)
struct twl6030_usb *twl = _twl;
enum omap_musb_vbus_id_status status = OMAP_MUSB_UNKNOWN;
u8 hw_state;
+ int ret;
hw_state = twl6030_readb(twl, TWL6030_MODULE_ID0, STS_HW_CONDITIONS);
if (hw_state & STS_USB_ID) {
+ ret = regulator_enable(twl->usb3v3);
+ if (ret)
+ dev_err(twl->dev, "Failed to enable usb3v3\n");
- regulator_enable(twl->usb3v3);
twl->asleep = 1;
twl6030_writeb(twl, TWL_MODULE_USB, 0x1, USB_ID_INT_EN_HI_CLR);
twl6030_writeb(twl, TWL_MODULE_USB, 0x10, USB_ID_INT_EN_HI_SET);
@@ -393,7 +400,7 @@ static int twl6030_usb_probe(struct platform_device *pdev)
return 0;
}
-static int __exit twl6030_usb_remove(struct platform_device *pdev)
+static int twl6030_usb_remove(struct platform_device *pdev)
{
struct twl6030_usb *twl = platform_get_drvdata(pdev);
@@ -420,7 +427,7 @@ MODULE_DEVICE_TABLE(of, twl6030_usb_id_table);
static struct platform_driver twl6030_usb_driver = {
.probe = twl6030_usb_probe,
- .remove = __exit_p(twl6030_usb_remove),
+ .remove = twl6030_usb_remove,
.driver = {
.name = "twl6030_usb",
.owner = THIS_MODULE,
diff --git a/drivers/usb/otg/ulpi_viewport.c b/drivers/usb/phy/phy-ulpi-viewport.c
index c5ba7e5423f..c5ba7e5423f 100644
--- a/drivers/usb/otg/ulpi_viewport.c
+++ b/drivers/usb/phy/phy-ulpi-viewport.c
diff --git a/drivers/usb/otg/ulpi.c b/drivers/usb/phy/phy-ulpi.c
index 217339dd7a9..217339dd7a9 100644
--- a/drivers/usb/otg/ulpi.c
+++ b/drivers/usb/phy/phy-ulpi.c
diff --git a/drivers/usb/otg/otg.c b/drivers/usb/phy/phy.c
index e1814397ca3..a9984c700d2 100644
--- a/drivers/usb/otg/otg.c
+++ b/drivers/usb/phy/phy.c
@@ -1,14 +1,13 @@
/*
- * otg.c -- USB OTG utility code
+ * phy.c -- USB phy handling
*
- * Copyright (C) 2004 Texas Instruments
+ * Copyright (C) 2004-2013 Texas Instruments
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
-
#include <linux/kernel.h>
#include <linux/export.h>
#include <linux/err.h>
@@ -17,7 +16,7 @@
#include <linux/slab.h>
#include <linux/of.h>
-#include <linux/usb/otg.h>
+#include <linux/usb/phy.h>
static LIST_HEAD(phy_list);
static LIST_HEAD(phy_bind_list);
@@ -110,7 +109,7 @@ struct usb_phy *devm_usb_get_phy(struct device *dev, enum usb_phy_type type)
return phy;
}
-EXPORT_SYMBOL(devm_usb_get_phy);
+EXPORT_SYMBOL_GPL(devm_usb_get_phy);
/**
* usb_get_phy - find the USB PHY
@@ -130,7 +129,7 @@ struct usb_phy *usb_get_phy(enum usb_phy_type type)
spin_lock_irqsave(&phy_lock, flags);
phy = __usb_find_phy(&phy_list, type);
- if (IS_ERR(phy)) {
+ if (IS_ERR(phy) || !try_module_get(phy->dev->driver->owner)) {
pr_err("unable to find transceiver of type %s\n",
usb_phy_type_string(type));
goto err0;
@@ -143,7 +142,7 @@ err0:
return phy;
}
-EXPORT_SYMBOL(usb_get_phy);
+EXPORT_SYMBOL_GPL(usb_get_phy);
/**
* devm_usb_get_phy_by_phandle - find the USB PHY by phandle
@@ -207,7 +206,7 @@ err0:
return phy;
}
-EXPORT_SYMBOL(devm_usb_get_phy_by_phandle);
+EXPORT_SYMBOL_GPL(devm_usb_get_phy_by_phandle);
/**
* usb_get_phy_dev - find the USB PHY
@@ -228,7 +227,7 @@ struct usb_phy *usb_get_phy_dev(struct device *dev, u8 index)
spin_lock_irqsave(&phy_lock, flags);
phy = __usb_find_phy_dev(dev, &phy_bind_list, index);
- if (IS_ERR(phy)) {
+ if (IS_ERR(phy) || !try_module_get(phy->dev->driver->owner)) {
pr_err("unable to find transceiver\n");
goto err0;
}
@@ -240,7 +239,7 @@ err0:
return phy;
}
-EXPORT_SYMBOL(usb_get_phy_dev);
+EXPORT_SYMBOL_GPL(usb_get_phy_dev);
/**
* devm_usb_get_phy_dev - find the USB PHY using device ptr and index
@@ -270,7 +269,7 @@ struct usb_phy *devm_usb_get_phy_dev(struct device *dev, u8 index)
return phy;
}
-EXPORT_SYMBOL(devm_usb_get_phy_dev);
+EXPORT_SYMBOL_GPL(devm_usb_get_phy_dev);
/**
* devm_usb_put_phy - release the USB PHY
@@ -289,7 +288,7 @@ void devm_usb_put_phy(struct device *dev, struct usb_phy *phy)
r = devres_destroy(dev, devm_usb_phy_release, devm_usb_phy_match, phy);
dev_WARN_ONCE(dev, r, "couldn't find PHY resource\n");
}
-EXPORT_SYMBOL(devm_usb_put_phy);
+EXPORT_SYMBOL_GPL(devm_usb_put_phy);
/**
* usb_put_phy - release the USB PHY
@@ -301,10 +300,14 @@ EXPORT_SYMBOL(devm_usb_put_phy);
*/
void usb_put_phy(struct usb_phy *x)
{
- if (x)
+ if (x) {
+ struct module *owner = x->dev->driver->owner;
+
put_device(x->dev);
+ module_put(owner);
+ }
}
-EXPORT_SYMBOL(usb_put_phy);
+EXPORT_SYMBOL_GPL(usb_put_phy);
/**
* usb_add_phy - declare the USB PHY
@@ -344,7 +347,7 @@ out:
spin_unlock_irqrestore(&phy_lock, flags);
return ret;
}
-EXPORT_SYMBOL(usb_add_phy);
+EXPORT_SYMBOL_GPL(usb_add_phy);
/**
* usb_add_phy_dev - declare the USB PHY
@@ -374,7 +377,7 @@ int usb_add_phy_dev(struct usb_phy *x)
spin_unlock_irqrestore(&phy_lock, flags);
return 0;
}
-EXPORT_SYMBOL(usb_add_phy_dev);
+EXPORT_SYMBOL_GPL(usb_add_phy_dev);
/**
* usb_remove_phy - remove the OTG PHY
@@ -396,7 +399,7 @@ void usb_remove_phy(struct usb_phy *x)
}
spin_unlock_irqrestore(&phy_lock, flags);
}
-EXPORT_SYMBOL(usb_remove_phy);
+EXPORT_SYMBOL_GPL(usb_remove_phy);
/**
* usb_bind_phy - bind the phy and the controller that uses the phy
@@ -410,7 +413,7 @@ EXPORT_SYMBOL(usb_remove_phy);
*
* To be used by platform specific initialization code.
*/
-int __init usb_bind_phy(const char *dev_name, u8 index,
+int usb_bind_phy(const char *dev_name, u8 index,
const char *phy_dev_name)
{
struct usb_phy_bind *phy_bind;
@@ -433,38 +436,3 @@ int __init usb_bind_phy(const char *dev_name, u8 index,
return 0;
}
EXPORT_SYMBOL_GPL(usb_bind_phy);
-
-const char *otg_state_string(enum usb_otg_state state)
-{
- switch (state) {
- case OTG_STATE_A_IDLE:
- return "a_idle";
- case OTG_STATE_A_WAIT_VRISE:
- return "a_wait_vrise";
- case OTG_STATE_A_WAIT_BCON:
- return "a_wait_bcon";
- case OTG_STATE_A_HOST:
- return "a_host";
- case OTG_STATE_A_SUSPEND:
- return "a_suspend";
- case OTG_STATE_A_PERIPHERAL:
- return "a_peripheral";
- case OTG_STATE_A_WAIT_VFALL:
- return "a_wait_vfall";
- case OTG_STATE_A_VBUS_ERR:
- return "a_vbus_err";
- case OTG_STATE_B_IDLE:
- return "b_idle";
- case OTG_STATE_B_SRP_INIT:
- return "b_srp_init";
- case OTG_STATE_B_PERIPHERAL:
- return "b_peripheral";
- case OTG_STATE_B_WAIT_ACON:
- return "b_wait_acon";
- case OTG_STATE_B_HOST:
- return "b_host";
- default:
- return "UNDEFINED";
- }
-}
-EXPORT_SYMBOL(otg_state_string);
diff --git a/drivers/usb/phy/samsung-usbphy.c b/drivers/usb/phy/samsung-usbphy.c
deleted file mode 100644
index 6ea55373383..00000000000
--- a/drivers/usb/phy/samsung-usbphy.c
+++ /dev/null
@@ -1,930 +0,0 @@
-/* linux/drivers/usb/phy/samsung-usbphy.c
- *
- * Copyright (c) 2012 Samsung Electronics Co., Ltd.
- * http://www.samsung.com
- *
- * Author: Praveen Paneri <p.paneri@samsung.com>
- *
- * Samsung USB2.0 PHY transceiver; talks to S3C HS OTG controller, EHCI-S5P and
- * OHCI-EXYNOS controllers.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/clk.h>
-#include <linux/delay.h>
-#include <linux/device.h>
-#include <linux/err.h>
-#include <linux/io.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/usb/otg.h>
-#include <linux/usb/samsung_usb_phy.h>
-#include <linux/platform_data/samsung-usbphy.h>
-
-/* Register definitions */
-
-#define SAMSUNG_PHYPWR (0x00)
-
-#define PHYPWR_NORMAL_MASK (0x19 << 0)
-#define PHYPWR_OTG_DISABLE (0x1 << 4)
-#define PHYPWR_ANALOG_POWERDOWN (0x1 << 3)
-#define PHYPWR_FORCE_SUSPEND (0x1 << 1)
-/* For Exynos4 */
-#define PHYPWR_NORMAL_MASK_PHY0 (0x39 << 0)
-#define PHYPWR_SLEEP_PHY0 (0x1 << 5)
-
-#define SAMSUNG_PHYCLK (0x04)
-
-#define PHYCLK_MODE_USB11 (0x1 << 6)
-#define PHYCLK_EXT_OSC (0x1 << 5)
-#define PHYCLK_COMMON_ON_N (0x1 << 4)
-#define PHYCLK_ID_PULL (0x1 << 2)
-#define PHYCLK_CLKSEL_MASK (0x3 << 0)
-#define PHYCLK_CLKSEL_48M (0x0 << 0)
-#define PHYCLK_CLKSEL_12M (0x2 << 0)
-#define PHYCLK_CLKSEL_24M (0x3 << 0)
-
-#define SAMSUNG_RSTCON (0x08)
-
-#define RSTCON_PHYLINK_SWRST (0x1 << 2)
-#define RSTCON_HLINK_SWRST (0x1 << 1)
-#define RSTCON_SWRST (0x1 << 0)
-
-/* EXYNOS5 */
-#define EXYNOS5_PHY_HOST_CTRL0 (0x00)
-
-#define HOST_CTRL0_PHYSWRSTALL (0x1 << 31)
-
-#define HOST_CTRL0_REFCLKSEL_MASK (0x3 << 19)
-#define HOST_CTRL0_REFCLKSEL_XTAL (0x0 << 19)
-#define HOST_CTRL0_REFCLKSEL_EXTL (0x1 << 19)
-#define HOST_CTRL0_REFCLKSEL_CLKCORE (0x2 << 19)
-
-#define HOST_CTRL0_FSEL_MASK (0x7 << 16)
-#define HOST_CTRL0_FSEL(_x) ((_x) << 16)
-
-#define FSEL_CLKSEL_50M (0x7)
-#define FSEL_CLKSEL_24M (0x5)
-#define FSEL_CLKSEL_20M (0x4)
-#define FSEL_CLKSEL_19200K (0x3)
-#define FSEL_CLKSEL_12M (0x2)
-#define FSEL_CLKSEL_10M (0x1)
-#define FSEL_CLKSEL_9600K (0x0)
-
-#define HOST_CTRL0_TESTBURNIN (0x1 << 11)
-#define HOST_CTRL0_RETENABLE (0x1 << 10)
-#define HOST_CTRL0_COMMONON_N (0x1 << 9)
-#define HOST_CTRL0_SIDDQ (0x1 << 6)
-#define HOST_CTRL0_FORCESLEEP (0x1 << 5)
-#define HOST_CTRL0_FORCESUSPEND (0x1 << 4)
-#define HOST_CTRL0_WORDINTERFACE (0x1 << 3)
-#define HOST_CTRL0_UTMISWRST (0x1 << 2)
-#define HOST_CTRL0_LINKSWRST (0x1 << 1)
-#define HOST_CTRL0_PHYSWRST (0x1 << 0)
-
-#define EXYNOS5_PHY_HOST_TUNE0 (0x04)
-
-#define EXYNOS5_PHY_HSIC_CTRL1 (0x10)
-
-#define EXYNOS5_PHY_HSIC_TUNE1 (0x14)
-
-#define EXYNOS5_PHY_HSIC_CTRL2 (0x20)
-
-#define EXYNOS5_PHY_HSIC_TUNE2 (0x24)
-
-#define HSIC_CTRL_REFCLKSEL_MASK (0x3 << 23)
-#define HSIC_CTRL_REFCLKSEL (0x2 << 23)
-
-#define HSIC_CTRL_REFCLKDIV_MASK (0x7f << 16)
-#define HSIC_CTRL_REFCLKDIV(_x) ((_x) << 16)
-#define HSIC_CTRL_REFCLKDIV_12 (0x24 << 16)
-#define HSIC_CTRL_REFCLKDIV_15 (0x1c << 16)
-#define HSIC_CTRL_REFCLKDIV_16 (0x1a << 16)
-#define HSIC_CTRL_REFCLKDIV_19_2 (0x15 << 16)
-#define HSIC_CTRL_REFCLKDIV_20 (0x14 << 16)
-
-#define HSIC_CTRL_SIDDQ (0x1 << 6)
-#define HSIC_CTRL_FORCESLEEP (0x1 << 5)
-#define HSIC_CTRL_FORCESUSPEND (0x1 << 4)
-#define HSIC_CTRL_WORDINTERFACE (0x1 << 3)
-#define HSIC_CTRL_UTMISWRST (0x1 << 2)
-#define HSIC_CTRL_PHYSWRST (0x1 << 0)
-
-#define EXYNOS5_PHY_HOST_EHCICTRL (0x30)
-
-#define HOST_EHCICTRL_ENAINCRXALIGN (0x1 << 29)
-#define HOST_EHCICTRL_ENAINCR4 (0x1 << 28)
-#define HOST_EHCICTRL_ENAINCR8 (0x1 << 27)
-#define HOST_EHCICTRL_ENAINCR16 (0x1 << 26)
-
-#define EXYNOS5_PHY_HOST_OHCICTRL (0x34)
-
-#define HOST_OHCICTRL_SUSPLGCY (0x1 << 3)
-#define HOST_OHCICTRL_APPSTARTCLK (0x1 << 2)
-#define HOST_OHCICTRL_CNTSEL (0x1 << 1)
-#define HOST_OHCICTRL_CLKCKTRST (0x1 << 0)
-
-#define EXYNOS5_PHY_OTG_SYS (0x38)
-
-#define OTG_SYS_PHYLINK_SWRESET (0x1 << 14)
-#define OTG_SYS_LINKSWRST_UOTG (0x1 << 13)
-#define OTG_SYS_PHY0_SWRST (0x1 << 12)
-
-#define OTG_SYS_REFCLKSEL_MASK (0x3 << 9)
-#define OTG_SYS_REFCLKSEL_XTAL (0x0 << 9)
-#define OTG_SYS_REFCLKSEL_EXTL (0x1 << 9)
-#define OTG_SYS_REFCLKSEL_CLKCORE (0x2 << 9)
-
-#define OTG_SYS_IDPULLUP_UOTG (0x1 << 8)
-#define OTG_SYS_COMMON_ON (0x1 << 7)
-
-#define OTG_SYS_FSEL_MASK (0x7 << 4)
-#define OTG_SYS_FSEL(_x) ((_x) << 4)
-
-#define OTG_SYS_FORCESLEEP (0x1 << 3)
-#define OTG_SYS_OTGDISABLE (0x1 << 2)
-#define OTG_SYS_SIDDQ_UOTG (0x1 << 1)
-#define OTG_SYS_FORCESUSPEND (0x1 << 0)
-
-#define EXYNOS5_PHY_OTG_TUNE (0x40)
-
-#ifndef MHZ
-#define MHZ (1000*1000)
-#endif
-
-#ifndef KHZ
-#define KHZ (1000)
-#endif
-
-#define EXYNOS_USBHOST_PHY_CTRL_OFFSET (0x4)
-#define S3C64XX_USBPHY_ENABLE (0x1 << 16)
-#define EXYNOS_USBPHY_ENABLE (0x1 << 0)
-#define EXYNOS_USB20PHY_CFG_HOST_LINK (0x1 << 0)
-
-enum samsung_cpu_type {
- TYPE_S3C64XX,
- TYPE_EXYNOS4210,
- TYPE_EXYNOS5250,
-};
-
-/*
- * struct samsung_usbphy_drvdata - driver data for various SoC variants
- * @cpu_type: machine identifier
- * @devphy_en_mask: device phy enable mask for PHY CONTROL register
- * @hostphy_en_mask: host phy enable mask for PHY CONTROL register
- * @devphy_reg_offset: offset to DEVICE PHY CONTROL register from
- * mapped address of system controller.
- * @hostphy_reg_offset: offset to HOST PHY CONTROL register from
- * mapped address of system controller.
- *
- * Here we have a separate mask for device type phy.
- * Having different masks for host and device type phy helps
- * in setting independent masks in case of SoCs like S5PV210,
- * in which PHY0 and PHY1 enable bits belong to same register
- * placed at position 0 and 1 respectively.
- * Although for newer SoCs like exynos these bits belong to
- * different registers altogether placed at position 0.
- */
-struct samsung_usbphy_drvdata {
- int cpu_type;
- int devphy_en_mask;
- int hostphy_en_mask;
- u32 devphy_reg_offset;
- u32 hostphy_reg_offset;
-};
-
-/*
- * struct samsung_usbphy - transceiver driver state
- * @phy: transceiver structure
- * @plat: platform data
- * @dev: The parent device supplied to the probe function
- * @clk: usb phy clock
- * @regs: usb phy controller registers memory base
- * @pmuregs: USB device PHY_CONTROL register memory base
- * @sysreg: USB2.0 PHY_CFG register memory base
- * @ref_clk_freq: reference clock frequency selection
- * @drv_data: driver data available for different SoCs
- * @phy_type: Samsung SoCs specific phy types: #HOST
- * #DEVICE
- * @phy_usage: usage count for phy
- * @lock: lock for phy operations
- */
-struct samsung_usbphy {
- struct usb_phy phy;
- struct samsung_usbphy_data *plat;
- struct device *dev;
- struct clk *clk;
- void __iomem *regs;
- void __iomem *pmuregs;
- void __iomem *sysreg;
- int ref_clk_freq;
- const struct samsung_usbphy_drvdata *drv_data;
- enum samsung_usb_phy_type phy_type;
- atomic_t phy_usage;
- spinlock_t lock;
-};
-
-#define phy_to_sphy(x) container_of((x), struct samsung_usbphy, phy)
-
-int samsung_usbphy_set_host(struct usb_otg *otg, struct usb_bus *host)
-{
- if (!otg)
- return -ENODEV;
-
- if (!otg->host)
- otg->host = host;
-
- return 0;
-}
-
-static int samsung_usbphy_parse_dt(struct samsung_usbphy *sphy)
-{
- struct device_node *usbphy_sys;
-
- /* Getting node for system controller interface for usb-phy */
- usbphy_sys = of_get_child_by_name(sphy->dev->of_node, "usbphy-sys");
- if (!usbphy_sys) {
- dev_err(sphy->dev, "No sys-controller interface for usb-phy\n");
- return -ENODEV;
- }
-
- sphy->pmuregs = of_iomap(usbphy_sys, 0);
-
- if (sphy->pmuregs == NULL) {
- dev_err(sphy->dev, "Can't get usb-phy pmu control register\n");
- goto err0;
- }
-
- sphy->sysreg = of_iomap(usbphy_sys, 1);
-
- /*
- * Not returning error code here, since this situation is not fatal.
- * Few SoCs may not have this switch available
- */
- if (sphy->sysreg == NULL)
- dev_warn(sphy->dev, "Can't get usb-phy sysreg cfg register\n");
-
- of_node_put(usbphy_sys);
-
- return 0;
-
-err0:
- of_node_put(usbphy_sys);
- return -ENXIO;
-}
-
-/*
- * Set isolation here for phy.
- * Here 'on = true' would mean USB PHY block is isolated, hence
- * de-activated and vice-versa.
- */
-static void samsung_usbphy_set_isolation(struct samsung_usbphy *sphy, bool on)
-{
- void __iomem *reg = NULL;
- u32 reg_val;
- u32 en_mask = 0;
-
- if (!sphy->pmuregs) {
- dev_warn(sphy->dev, "Can't set pmu isolation\n");
- return;
- }
-
- switch (sphy->drv_data->cpu_type) {
- case TYPE_S3C64XX:
- /*
- * Do nothing: We will add here once S3C64xx goes for DT support
- */
- break;
- case TYPE_EXYNOS4210:
- /*
- * Fall through since exynos4210 and exynos5250 have similar
- * register architecture: two separate registers for host and
- * device phy control with enable bit at position 0.
- */
- case TYPE_EXYNOS5250:
- if (sphy->phy_type == USB_PHY_TYPE_DEVICE) {
- reg = sphy->pmuregs +
- sphy->drv_data->devphy_reg_offset;
- en_mask = sphy->drv_data->devphy_en_mask;
- } else if (sphy->phy_type == USB_PHY_TYPE_HOST) {
- reg = sphy->pmuregs +
- sphy->drv_data->hostphy_reg_offset;
- en_mask = sphy->drv_data->hostphy_en_mask;
- }
- break;
- default:
- dev_err(sphy->dev, "Invalid SoC type\n");
- return;
- }
-
- reg_val = readl(reg);
-
- if (on)
- reg_val &= ~en_mask;
- else
- reg_val |= en_mask;
-
- writel(reg_val, reg);
-}
-
-/*
- * Configure the mode of working of usb-phy here: HOST/DEVICE.
- */
-static void samsung_usbphy_cfg_sel(struct samsung_usbphy *sphy)
-{
- u32 reg;
-
- if (!sphy->sysreg) {
- dev_warn(sphy->dev, "Can't configure specified phy mode\n");
- return;
- }
-
- reg = readl(sphy->sysreg);
-
- if (sphy->phy_type == USB_PHY_TYPE_DEVICE)
- reg &= ~EXYNOS_USB20PHY_CFG_HOST_LINK;
- else if (sphy->phy_type == USB_PHY_TYPE_HOST)
- reg |= EXYNOS_USB20PHY_CFG_HOST_LINK;
-
- writel(reg, sphy->sysreg);
-}
-
-/*
- * PHYs are different for USB Device and USB Host.
- * This make sure that correct PHY type is selected before
- * any operation on PHY.
- */
-static int samsung_usbphy_set_type(struct usb_phy *phy,
- enum samsung_usb_phy_type phy_type)
-{
- struct samsung_usbphy *sphy = phy_to_sphy(phy);
-
- sphy->phy_type = phy_type;
-
- return 0;
-}
-
-/*
- * Returns reference clock frequency selection value
- */
-static int samsung_usbphy_get_refclk_freq(struct samsung_usbphy *sphy)
-{
- struct clk *ref_clk;
- int refclk_freq = 0;
-
- /*
- * In exynos5250 USB host and device PHY use
- * external crystal clock XXTI
- */
- if (sphy->drv_data->cpu_type == TYPE_EXYNOS5250)
- ref_clk = clk_get(sphy->dev, "ext_xtal");
- else
- ref_clk = clk_get(sphy->dev, "xusbxti");
- if (IS_ERR(ref_clk)) {
- dev_err(sphy->dev, "Failed to get reference clock\n");
- return PTR_ERR(ref_clk);
- }
-
- if (sphy->drv_data->cpu_type == TYPE_EXYNOS5250) {
- /* set clock frequency for PLL */
- switch (clk_get_rate(ref_clk)) {
- case 9600 * KHZ:
- refclk_freq = FSEL_CLKSEL_9600K;
- break;
- case 10 * MHZ:
- refclk_freq = FSEL_CLKSEL_10M;
- break;
- case 12 * MHZ:
- refclk_freq = FSEL_CLKSEL_12M;
- break;
- case 19200 * KHZ:
- refclk_freq = FSEL_CLKSEL_19200K;
- break;
- case 20 * MHZ:
- refclk_freq = FSEL_CLKSEL_20M;
- break;
- case 50 * MHZ:
- refclk_freq = FSEL_CLKSEL_50M;
- break;
- case 24 * MHZ:
- default:
- /* default reference clock */
- refclk_freq = FSEL_CLKSEL_24M;
- break;
- }
- } else {
- switch (clk_get_rate(ref_clk)) {
- case 12 * MHZ:
- refclk_freq = PHYCLK_CLKSEL_12M;
- break;
- case 24 * MHZ:
- refclk_freq = PHYCLK_CLKSEL_24M;
- break;
- case 48 * MHZ:
- refclk_freq = PHYCLK_CLKSEL_48M;
- break;
- default:
- if (sphy->drv_data->cpu_type == TYPE_S3C64XX)
- refclk_freq = PHYCLK_CLKSEL_48M;
- else
- refclk_freq = PHYCLK_CLKSEL_24M;
- break;
- }
- }
- clk_put(ref_clk);
-
- return refclk_freq;
-}
-
-static bool exynos5_phyhost_is_on(void *regs)
-{
- u32 reg;
-
- reg = readl(regs + EXYNOS5_PHY_HOST_CTRL0);
-
- return !(reg & HOST_CTRL0_SIDDQ);
-}
-
-static void samsung_exynos5_usbphy_enable(struct samsung_usbphy *sphy)
-{
- void __iomem *regs = sphy->regs;
- u32 phyclk = sphy->ref_clk_freq;
- u32 phyhost;
- u32 phyotg;
- u32 phyhsic;
- u32 ehcictrl;
- u32 ohcictrl;
-
- /*
- * phy_usage helps in keeping usage count for phy
- * so that the first consumer enabling the phy is also
- * the last consumer to disable it.
- */
-
- atomic_inc(&sphy->phy_usage);
-
- if (exynos5_phyhost_is_on(regs)) {
- dev_info(sphy->dev, "Already power on PHY\n");
- return;
- }
-
- /* Host configuration */
- phyhost = readl(regs + EXYNOS5_PHY_HOST_CTRL0);
-
- /* phy reference clock configuration */
- phyhost &= ~HOST_CTRL0_FSEL_MASK;
- phyhost |= HOST_CTRL0_FSEL(phyclk);
-
- /* host phy reset */
- phyhost &= ~(HOST_CTRL0_PHYSWRST |
- HOST_CTRL0_PHYSWRSTALL |
- HOST_CTRL0_SIDDQ |
- /* Enable normal mode of operation */
- HOST_CTRL0_FORCESUSPEND |
- HOST_CTRL0_FORCESLEEP);
-
- /* Link reset */
- phyhost |= (HOST_CTRL0_LINKSWRST |
- HOST_CTRL0_UTMISWRST |
- /* COMMON Block configuration during suspend */
- HOST_CTRL0_COMMONON_N);
- writel(phyhost, regs + EXYNOS5_PHY_HOST_CTRL0);
- udelay(10);
- phyhost &= ~(HOST_CTRL0_LINKSWRST |
- HOST_CTRL0_UTMISWRST);
- writel(phyhost, regs + EXYNOS5_PHY_HOST_CTRL0);
-
- /* OTG configuration */
- phyotg = readl(regs + EXYNOS5_PHY_OTG_SYS);
-
- /* phy reference clock configuration */
- phyotg &= ~OTG_SYS_FSEL_MASK;
- phyotg |= OTG_SYS_FSEL(phyclk);
-
- /* Enable normal mode of operation */
- phyotg &= ~(OTG_SYS_FORCESUSPEND |
- OTG_SYS_SIDDQ_UOTG |
- OTG_SYS_FORCESLEEP |
- OTG_SYS_REFCLKSEL_MASK |
- /* COMMON Block configuration during suspend */
- OTG_SYS_COMMON_ON);
-
- /* OTG phy & link reset */
- phyotg |= (OTG_SYS_PHY0_SWRST |
- OTG_SYS_LINKSWRST_UOTG |
- OTG_SYS_PHYLINK_SWRESET |
- OTG_SYS_OTGDISABLE |
- /* Set phy refclk */
- OTG_SYS_REFCLKSEL_CLKCORE);
-
- writel(phyotg, regs + EXYNOS5_PHY_OTG_SYS);
- udelay(10);
- phyotg &= ~(OTG_SYS_PHY0_SWRST |
- OTG_SYS_LINKSWRST_UOTG |
- OTG_SYS_PHYLINK_SWRESET);
- writel(phyotg, regs + EXYNOS5_PHY_OTG_SYS);
-
- /* HSIC phy configuration */
- phyhsic = (HSIC_CTRL_REFCLKDIV_12 |
- HSIC_CTRL_REFCLKSEL |
- HSIC_CTRL_PHYSWRST);
- writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL1);
- writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL2);
- udelay(10);
- phyhsic &= ~HSIC_CTRL_PHYSWRST;
- writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL1);
- writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL2);
-
- udelay(80);
-
- /* enable EHCI DMA burst */
- ehcictrl = readl(regs + EXYNOS5_PHY_HOST_EHCICTRL);
- ehcictrl |= (HOST_EHCICTRL_ENAINCRXALIGN |
- HOST_EHCICTRL_ENAINCR4 |
- HOST_EHCICTRL_ENAINCR8 |
- HOST_EHCICTRL_ENAINCR16);
- writel(ehcictrl, regs + EXYNOS5_PHY_HOST_EHCICTRL);
-
- /* set ohci_suspend_on_n */
- ohcictrl = readl(regs + EXYNOS5_PHY_HOST_OHCICTRL);
- ohcictrl |= HOST_OHCICTRL_SUSPLGCY;
- writel(ohcictrl, regs + EXYNOS5_PHY_HOST_OHCICTRL);
-}
-
-static void samsung_usbphy_enable(struct samsung_usbphy *sphy)
-{
- void __iomem *regs = sphy->regs;
- u32 phypwr;
- u32 phyclk;
- u32 rstcon;
-
- /* set clock frequency for PLL */
- phyclk = sphy->ref_clk_freq;
- phypwr = readl(regs + SAMSUNG_PHYPWR);
- rstcon = readl(regs + SAMSUNG_RSTCON);
-
- switch (sphy->drv_data->cpu_type) {
- case TYPE_S3C64XX:
- phyclk &= ~PHYCLK_COMMON_ON_N;
- phypwr &= ~PHYPWR_NORMAL_MASK;
- rstcon |= RSTCON_SWRST;
- break;
- case TYPE_EXYNOS4210:
- phypwr &= ~PHYPWR_NORMAL_MASK_PHY0;
- rstcon |= RSTCON_SWRST;
- default:
- break;
- }
-
- writel(phyclk, regs + SAMSUNG_PHYCLK);
- /* Configure PHY0 for normal operation*/
- writel(phypwr, regs + SAMSUNG_PHYPWR);
- /* reset all ports of PHY and Link */
- writel(rstcon, regs + SAMSUNG_RSTCON);
- udelay(10);
- rstcon &= ~RSTCON_SWRST;
- writel(rstcon, regs + SAMSUNG_RSTCON);
-}
-
-static void samsung_exynos5_usbphy_disable(struct samsung_usbphy *sphy)
-{
- void __iomem *regs = sphy->regs;
- u32 phyhost;
- u32 phyotg;
- u32 phyhsic;
-
- if (atomic_dec_return(&sphy->phy_usage) > 0) {
- dev_info(sphy->dev, "still being used\n");
- return;
- }
-
- phyhsic = (HSIC_CTRL_REFCLKDIV_12 |
- HSIC_CTRL_REFCLKSEL |
- HSIC_CTRL_SIDDQ |
- HSIC_CTRL_FORCESLEEP |
- HSIC_CTRL_FORCESUSPEND);
- writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL1);
- writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL2);
-
- phyhost = readl(regs + EXYNOS5_PHY_HOST_CTRL0);
- phyhost |= (HOST_CTRL0_SIDDQ |
- HOST_CTRL0_FORCESUSPEND |
- HOST_CTRL0_FORCESLEEP |
- HOST_CTRL0_PHYSWRST |
- HOST_CTRL0_PHYSWRSTALL);
- writel(phyhost, regs + EXYNOS5_PHY_HOST_CTRL0);
-
- phyotg = readl(regs + EXYNOS5_PHY_OTG_SYS);
- phyotg |= (OTG_SYS_FORCESUSPEND |
- OTG_SYS_SIDDQ_UOTG |
- OTG_SYS_FORCESLEEP);
- writel(phyotg, regs + EXYNOS5_PHY_OTG_SYS);
-}
-
-static void samsung_usbphy_disable(struct samsung_usbphy *sphy)
-{
- void __iomem *regs = sphy->regs;
- u32 phypwr;
-
- phypwr = readl(regs + SAMSUNG_PHYPWR);
-
- switch (sphy->drv_data->cpu_type) {
- case TYPE_S3C64XX:
- phypwr |= PHYPWR_NORMAL_MASK;
- break;
- case TYPE_EXYNOS4210:
- phypwr |= PHYPWR_NORMAL_MASK_PHY0;
- default:
- break;
- }
-
- /* Disable analog and otg block power */
- writel(phypwr, regs + SAMSUNG_PHYPWR);
-}
-
-/*
- * The function passed to the usb driver for phy initialization
- */
-static int samsung_usbphy_init(struct usb_phy *phy)
-{
- struct samsung_usbphy *sphy;
- struct usb_bus *host = NULL;
- unsigned long flags;
- int ret = 0;
-
- sphy = phy_to_sphy(phy);
-
- host = phy->otg->host;
-
- /* Enable the phy clock */
- ret = clk_prepare_enable(sphy->clk);
- if (ret) {
- dev_err(sphy->dev, "%s: clk_prepare_enable failed\n", __func__);
- return ret;
- }
-
- spin_lock_irqsave(&sphy->lock, flags);
-
- if (host) {
- /* setting default phy-type for USB 2.0 */
- if (!strstr(dev_name(host->controller), "ehci") ||
- !strstr(dev_name(host->controller), "ohci"))
- samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_HOST);
- } else {
- samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_DEVICE);
- }
-
- /* Disable phy isolation */
- if (sphy->plat && sphy->plat->pmu_isolation)
- sphy->plat->pmu_isolation(false);
- else
- samsung_usbphy_set_isolation(sphy, false);
-
- /* Selecting Host/OTG mode; After reset USB2.0PHY_CFG: HOST */
- samsung_usbphy_cfg_sel(sphy);
-
- /* Initialize usb phy registers */
- if (sphy->drv_data->cpu_type == TYPE_EXYNOS5250)
- samsung_exynos5_usbphy_enable(sphy);
- else
- samsung_usbphy_enable(sphy);
-
- spin_unlock_irqrestore(&sphy->lock, flags);
-
- /* Disable the phy clock */
- clk_disable_unprepare(sphy->clk);
-
- return ret;
-}
-
-/*
- * The function passed to the usb driver for phy shutdown
- */
-static void samsung_usbphy_shutdown(struct usb_phy *phy)
-{
- struct samsung_usbphy *sphy;
- struct usb_bus *host = NULL;
- unsigned long flags;
-
- sphy = phy_to_sphy(phy);
-
- host = phy->otg->host;
-
- if (clk_prepare_enable(sphy->clk)) {
- dev_err(sphy->dev, "%s: clk_prepare_enable failed\n", __func__);
- return;
- }
-
- spin_lock_irqsave(&sphy->lock, flags);
-
- if (host) {
- /* setting default phy-type for USB 2.0 */
- if (!strstr(dev_name(host->controller), "ehci") ||
- !strstr(dev_name(host->controller), "ohci"))
- samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_HOST);
- } else {
- samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_DEVICE);
- }
-
- /* De-initialize usb phy registers */
- if (sphy->drv_data->cpu_type == TYPE_EXYNOS5250)
- samsung_exynos5_usbphy_disable(sphy);
- else
- samsung_usbphy_disable(sphy);
-
- /* Enable phy isolation */
- if (sphy->plat && sphy->plat->pmu_isolation)
- sphy->plat->pmu_isolation(true);
- else
- samsung_usbphy_set_isolation(sphy, true);
-
- spin_unlock_irqrestore(&sphy->lock, flags);
-
- clk_disable_unprepare(sphy->clk);
-}
-
-static const struct of_device_id samsung_usbphy_dt_match[];
-
-static inline const struct samsung_usbphy_drvdata
-*samsung_usbphy_get_driver_data(struct platform_device *pdev)
-{
- if (pdev->dev.of_node) {
- const struct of_device_id *match;
- match = of_match_node(samsung_usbphy_dt_match,
- pdev->dev.of_node);
- return match->data;
- }
-
- return (struct samsung_usbphy_drvdata *)
- platform_get_device_id(pdev)->driver_data;
-}
-
-static int samsung_usbphy_probe(struct platform_device *pdev)
-{
- struct samsung_usbphy *sphy;
- struct usb_otg *otg;
- struct samsung_usbphy_data *pdata = pdev->dev.platform_data;
- const struct samsung_usbphy_drvdata *drv_data;
- struct device *dev = &pdev->dev;
- struct resource *phy_mem;
- void __iomem *phy_base;
- struct clk *clk;
- int ret;
-
- phy_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!phy_mem) {
- dev_err(dev, "%s: missing mem resource\n", __func__);
- return -ENODEV;
- }
-
- phy_base = devm_request_and_ioremap(dev, phy_mem);
- if (!phy_base) {
- dev_err(dev, "%s: register mapping failed\n", __func__);
- return -ENXIO;
- }
-
- sphy = devm_kzalloc(dev, sizeof(*sphy), GFP_KERNEL);
- if (!sphy)
- return -ENOMEM;
-
- otg = devm_kzalloc(dev, sizeof(*otg), GFP_KERNEL);
- if (!otg)
- return -ENOMEM;
-
- drv_data = samsung_usbphy_get_driver_data(pdev);
-
- if (drv_data->cpu_type == TYPE_EXYNOS5250)
- clk = devm_clk_get(dev, "usbhost");
- else
- clk = devm_clk_get(dev, "otg");
-
- if (IS_ERR(clk)) {
- dev_err(dev, "Failed to get otg clock\n");
- return PTR_ERR(clk);
- }
-
- sphy->dev = dev;
-
- if (dev->of_node) {
- ret = samsung_usbphy_parse_dt(sphy);
- if (ret < 0)
- return ret;
- } else {
- if (!pdata) {
- dev_err(dev, "no platform data specified\n");
- return -EINVAL;
- }
- }
-
- sphy->plat = pdata;
- sphy->regs = phy_base;
- sphy->clk = clk;
- sphy->drv_data = drv_data;
- sphy->phy.dev = sphy->dev;
- sphy->phy.label = "samsung-usbphy";
- sphy->phy.init = samsung_usbphy_init;
- sphy->phy.shutdown = samsung_usbphy_shutdown;
- sphy->ref_clk_freq = samsung_usbphy_get_refclk_freq(sphy);
-
- sphy->phy.otg = otg;
- sphy->phy.otg->phy = &sphy->phy;
- sphy->phy.otg->set_host = samsung_usbphy_set_host;
-
- spin_lock_init(&sphy->lock);
-
- platform_set_drvdata(pdev, sphy);
-
- return usb_add_phy(&sphy->phy, USB_PHY_TYPE_USB2);
-}
-
-static int samsung_usbphy_remove(struct platform_device *pdev)
-{
- struct samsung_usbphy *sphy = platform_get_drvdata(pdev);
-
- usb_remove_phy(&sphy->phy);
-
- if (sphy->pmuregs)
- iounmap(sphy->pmuregs);
- if (sphy->sysreg)
- iounmap(sphy->sysreg);
-
- return 0;
-}
-
-static const struct samsung_usbphy_drvdata usbphy_s3c64xx = {
- .cpu_type = TYPE_S3C64XX,
- .devphy_en_mask = S3C64XX_USBPHY_ENABLE,
-};
-
-static const struct samsung_usbphy_drvdata usbphy_exynos4 = {
- .cpu_type = TYPE_EXYNOS4210,
- .devphy_en_mask = EXYNOS_USBPHY_ENABLE,
- .hostphy_en_mask = EXYNOS_USBPHY_ENABLE,
-};
-
-static struct samsung_usbphy_drvdata usbphy_exynos5 = {
- .cpu_type = TYPE_EXYNOS5250,
- .hostphy_en_mask = EXYNOS_USBPHY_ENABLE,
- .hostphy_reg_offset = EXYNOS_USBHOST_PHY_CTRL_OFFSET,
-};
-
-#ifdef CONFIG_OF
-static const struct of_device_id samsung_usbphy_dt_match[] = {
- {
- .compatible = "samsung,s3c64xx-usbphy",
- .data = &usbphy_s3c64xx,
- }, {
- .compatible = "samsung,exynos4210-usbphy",
- .data = &usbphy_exynos4,
- }, {
- .compatible = "samsung,exynos5250-usbphy",
- .data = &usbphy_exynos5
- },
- {},
-};
-MODULE_DEVICE_TABLE(of, samsung_usbphy_dt_match);
-#endif
-
-static struct platform_device_id samsung_usbphy_driver_ids[] = {
- {
- .name = "s3c64xx-usbphy",
- .driver_data = (unsigned long)&usbphy_s3c64xx,
- }, {
- .name = "exynos4210-usbphy",
- .driver_data = (unsigned long)&usbphy_exynos4,
- }, {
- .name = "exynos5250-usbphy",
- .driver_data = (unsigned long)&usbphy_exynos5,
- },
- {},
-};
-
-MODULE_DEVICE_TABLE(platform, samsung_usbphy_driver_ids);
-
-static struct platform_driver samsung_usbphy_driver = {
- .probe = samsung_usbphy_probe,
- .remove = samsung_usbphy_remove,
- .id_table = samsung_usbphy_driver_ids,
- .driver = {
- .name = "samsung-usbphy",
- .owner = THIS_MODULE,
- .of_match_table = of_match_ptr(samsung_usbphy_dt_match),
- },
-};
-
-module_platform_driver(samsung_usbphy_driver);
-
-MODULE_DESCRIPTION("Samsung USB phy controller");
-MODULE_AUTHOR("Praveen Paneri <p.paneri@samsung.com>");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:samsung-usbphy");
diff --git a/drivers/usb/renesas_usbhs/Kconfig b/drivers/usb/renesas_usbhs/Kconfig
index 29feb00d7f3..019bf7e49ee 100644
--- a/drivers/usb/renesas_usbhs/Kconfig
+++ b/drivers/usb/renesas_usbhs/Kconfig
@@ -4,7 +4,7 @@
config USB_RENESAS_USBHS
tristate 'Renesas USBHS controller'
- depends on USB && USB_GADGET && GENERIC_HARDIRQS
+ depends on USB_GADGET && GENERIC_HARDIRQS
default n
help
Renesas USBHS is a discrete USB host and peripheral controller chip
diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c
index 9538f0feafe..45b94019aec 100644
--- a/drivers/usb/renesas_usbhs/fifo.c
+++ b/drivers/usb/renesas_usbhs/fifo.c
@@ -32,7 +32,6 @@
*/
void usbhs_pkt_init(struct usbhs_pkt *pkt)
{
- pkt->dma = DMA_ADDR_INVALID;
INIT_LIST_HEAD(&pkt->node);
}
diff --git a/drivers/usb/renesas_usbhs/fifo.h b/drivers/usb/renesas_usbhs/fifo.h
index c31731a843d..a168a1760fc 100644
--- a/drivers/usb/renesas_usbhs/fifo.h
+++ b/drivers/usb/renesas_usbhs/fifo.h
@@ -23,8 +23,6 @@
#include <asm/dma.h>
#include "pipe.h"
-#define DMA_ADDR_INVALID (~(dma_addr_t)0)
-
struct usbhs_fifo {
char *name;
u32 port; /* xFIFO */
diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c b/drivers/usb/renesas_usbhs/mod_gadget.c
index 78fca978b2d..ed4949faa70 100644
--- a/drivers/usb/renesas_usbhs/mod_gadget.c
+++ b/drivers/usb/renesas_usbhs/mod_gadget.c
@@ -230,7 +230,7 @@ static int usbhsg_recip_handler_std_clear_endpoint(struct usbhs_priv *priv,
return 0;
}
-struct usbhsg_recip_handle req_clear_feature = {
+static struct usbhsg_recip_handle req_clear_feature = {
.name = "clear feature",
.device = usbhsg_recip_handler_std_control_done,
.interface = usbhsg_recip_handler_std_control_done,
@@ -271,7 +271,7 @@ static int usbhsg_recip_handler_std_set_endpoint(struct usbhs_priv *priv,
return 0;
}
-struct usbhsg_recip_handle req_set_feature = {
+static struct usbhsg_recip_handle req_set_feature = {
.name = "set feature",
.device = usbhsg_recip_handler_std_set_device,
.interface = usbhsg_recip_handler_std_control_done,
@@ -372,7 +372,7 @@ static int usbhsg_recip_handler_std_get_endpoint(struct usbhs_priv *priv,
return 0;
}
-struct usbhsg_recip_handle req_get_status = {
+static struct usbhsg_recip_handle req_get_status = {
.name = "get status",
.device = usbhsg_recip_handler_std_get_device,
.interface = usbhsg_recip_handler_std_get_interface,
@@ -845,7 +845,6 @@ static int usbhsg_gadget_start(struct usb_gadget *gadget,
/* first hook up the driver ... */
gpriv->driver = driver;
- gpriv->gadget.dev.driver = &driver->driver;
return usbhsg_try_start(priv, USBHSG_STATUS_REGISTERD);
}
@@ -861,7 +860,6 @@ static int usbhsg_gadget_stop(struct usb_gadget *gadget,
return -EINVAL;
usbhsg_try_stop(priv, USBHSG_STATUS_REGISTERD);
- gpriv->gadget.dev.driver = NULL;
gpriv->driver = NULL;
return 0;
@@ -925,11 +923,6 @@ static int usbhsg_stop(struct usbhs_priv *priv)
return usbhsg_try_stop(priv, USBHSG_STATUS_STARTED);
}
-static void usbhs_mod_gadget_release(struct device *pdev)
-{
- /* do nothing */
-}
-
int usbhs_mod_gadget_probe(struct usbhs_priv *priv)
{
struct usbhsg_gpriv *gpriv;
@@ -976,15 +969,10 @@ int usbhs_mod_gadget_probe(struct usbhs_priv *priv)
/*
* init gadget
*/
- dev_set_name(&gpriv->gadget.dev, "gadget");
gpriv->gadget.dev.parent = dev;
- gpriv->gadget.dev.release = usbhs_mod_gadget_release;
gpriv->gadget.name = "renesas_usbhs_udc";
gpriv->gadget.ops = &usbhsg_gadget_ops;
gpriv->gadget.max_speed = USB_SPEED_HIGH;
- ret = device_register(&gpriv->gadget.dev);
- if (ret < 0)
- goto err_add_udc;
INIT_LIST_HEAD(&gpriv->gadget.ep_list);
@@ -1014,15 +1002,13 @@ int usbhs_mod_gadget_probe(struct usbhs_priv *priv)
ret = usb_add_gadget_udc(dev, &gpriv->gadget);
if (ret)
- goto err_register;
+ goto err_add_udc;
dev_info(dev, "gadget probed\n");
return 0;
-err_register:
- device_unregister(&gpriv->gadget.dev);
err_add_udc:
kfree(gpriv->uep);
@@ -1038,8 +1024,6 @@ void usbhs_mod_gadget_remove(struct usbhs_priv *priv)
usb_del_gadget_udc(&gpriv->gadget);
- device_unregister(&gpriv->gadget.dev);
-
kfree(gpriv->uep);
kfree(gpriv);
}
diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig
index 17b7f9ae36a..1d55762afbb 100644
--- a/drivers/usb/serial/Kconfig
+++ b/drivers/usb/serial/Kconfig
@@ -4,7 +4,7 @@
menuconfig USB_SERIAL
tristate "USB Serial Converter support"
- depends on USB && TTY
+ depends on TTY
---help---
Say Y here if you have a USB device that provides normal serial
ports, or acts like a serial device, and you want to connect it to
@@ -667,6 +667,23 @@ config USB_SERIAL_ZIO
To compile this driver as a module, choose M here: the
module will be called zio.
+config USB_SERIAL_WISHBONE
+ tristate "USB-Wishbone adapter interface driver"
+ help
+ Say Y here if you want to use a USB attached Wishbone bus.
+
+ Wishbone is an open hardware SoC bus commonly used in FPGA
+ designs. Bus access can be serialized using the Etherbone
+ protocol <http://www.ohwr.org/projects/etherbone-core>.
+
+ This driver is intended to be used with devices which attach
+ their internal Wishbone bus to a USB serial interface using
+ the Etherbone protocol. A userspace library is required to
+ speak the protocol made available by this driver as ttyUSBx.
+
+ To compile this driver as a module, choose M here: the
+ module will be called wishbone-serial.
+
config USB_SERIAL_ZTE
tristate "ZTE USB serial driver"
help
diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile
index eaf5ca14dfe..cec63fa1910 100644
--- a/drivers/usb/serial/Makefile
+++ b/drivers/usb/serial/Makefile
@@ -58,6 +58,7 @@ obj-$(CONFIG_USB_SERIAL_SYMBOL) += symbolserial.o
obj-$(CONFIG_USB_SERIAL_WWAN) += usb_wwan.o
obj-$(CONFIG_USB_SERIAL_TI) += ti_usb_3410_5052.o
obj-$(CONFIG_USB_SERIAL_VISOR) += visor.o
+obj-$(CONFIG_USB_SERIAL_WISHBONE) += wishbone-serial.o
obj-$(CONFIG_USB_SERIAL_WHITEHEAT) += whiteheat.o
obj-$(CONFIG_USB_SERIAL_XIRCOM) += keyspan_pda.o
obj-$(CONFIG_USB_SERIAL_VIVOPAY_SERIAL) += vivopay-serial.o
diff --git a/drivers/usb/serial/ark3116.c b/drivers/usb/serial/ark3116.c
index cbd904b8fba..3b16118cbf6 100644
--- a/drivers/usb/serial/ark3116.c
+++ b/drivers/usb/serial/ark3116.c
@@ -62,8 +62,6 @@ static int is_irda(struct usb_serial *serial)
}
struct ark3116_private {
- wait_queue_head_t delta_msr_wait;
- struct async_icount icount;
int irda; /* 1 for irda device */
/* protects hw register updates */
@@ -146,7 +144,6 @@ static int ark3116_port_probe(struct usb_serial_port *port)
if (!priv)
return -ENOMEM;
- init_waitqueue_head(&priv->delta_msr_wait);
mutex_init(&priv->hw_lock);
spin_lock_init(&priv->status_lock);
@@ -343,18 +340,15 @@ static void ark3116_close(struct usb_serial_port *port)
{
struct usb_serial *serial = port->serial;
- if (serial->dev) {
- /* disable DMA */
- ark3116_write_reg(serial, UART_FCR, 0);
-
- /* deactivate interrupts */
- ark3116_write_reg(serial, UART_IER, 0);
+ /* disable DMA */
+ ark3116_write_reg(serial, UART_FCR, 0);
- usb_serial_generic_close(port);
- if (serial->num_interrupt_in)
- usb_kill_urb(port->interrupt_in_urb);
- }
+ /* deactivate interrupts */
+ ark3116_write_reg(serial, UART_IER, 0);
+ usb_serial_generic_close(port);
+ if (serial->num_interrupt_in)
+ usb_kill_urb(port->interrupt_in_urb);
}
static int ark3116_open(struct tty_struct *tty, struct usb_serial_port *port)
@@ -407,31 +401,10 @@ err_out:
return result;
}
-static int ark3116_get_icount(struct tty_struct *tty,
- struct serial_icounter_struct *icount)
-{
- struct usb_serial_port *port = tty->driver_data;
- struct ark3116_private *priv = usb_get_serial_port_data(port);
- struct async_icount cnow = priv->icount;
- icount->cts = cnow.cts;
- icount->dsr = cnow.dsr;
- icount->rng = cnow.rng;
- icount->dcd = cnow.dcd;
- icount->rx = cnow.rx;
- icount->tx = cnow.tx;
- icount->frame = cnow.frame;
- icount->overrun = cnow.overrun;
- icount->parity = cnow.parity;
- icount->brk = cnow.brk;
- icount->buf_overrun = cnow.buf_overrun;
- return 0;
-}
-
static int ark3116_ioctl(struct tty_struct *tty,
unsigned int cmd, unsigned long arg)
{
struct usb_serial_port *port = tty->driver_data;
- struct ark3116_private *priv = usb_get_serial_port_data(port);
struct serial_struct serstruct;
void __user *user_arg = (void __user *)arg;
@@ -453,29 +426,6 @@ static int ark3116_ioctl(struct tty_struct *tty,
if (copy_from_user(&serstruct, user_arg, sizeof(serstruct)))
return -EFAULT;
return 0;
- case TIOCMIWAIT:
- for (;;) {
- struct async_icount prev = priv->icount;
- interruptible_sleep_on(&priv->delta_msr_wait);
- /* see if a signal did it */
- if (signal_pending(current))
- return -ERESTARTSYS;
- if ((prev.rng == priv->icount.rng) &&
- (prev.dsr == priv->icount.dsr) &&
- (prev.dcd == priv->icount.dcd) &&
- (prev.cts == priv->icount.cts))
- return -EIO;
- if ((arg & TIOCM_RNG &&
- (prev.rng != priv->icount.rng)) ||
- (arg & TIOCM_DSR &&
- (prev.dsr != priv->icount.dsr)) ||
- (arg & TIOCM_CD &&
- (prev.dcd != priv->icount.dcd)) ||
- (arg & TIOCM_CTS &&
- (prev.cts != priv->icount.cts)))
- return 0;
- }
- break;
}
return -ENOIOCTLCMD;
@@ -573,14 +523,14 @@ static void ark3116_update_msr(struct usb_serial_port *port, __u8 msr)
if (msr & UART_MSR_ANY_DELTA) {
/* update input line counters */
if (msr & UART_MSR_DCTS)
- priv->icount.cts++;
+ port->icount.cts++;
if (msr & UART_MSR_DDSR)
- priv->icount.dsr++;
+ port->icount.dsr++;
if (msr & UART_MSR_DDCD)
- priv->icount.dcd++;
+ port->icount.dcd++;
if (msr & UART_MSR_TERI)
- priv->icount.rng++;
- wake_up_interruptible(&priv->delta_msr_wait);
+ port->icount.rng++;
+ wake_up_interruptible(&port->port.delta_msr_wait);
}
}
@@ -596,13 +546,13 @@ static void ark3116_update_lsr(struct usb_serial_port *port, __u8 lsr)
if (lsr&UART_LSR_BRK_ERROR_BITS) {
if (lsr & UART_LSR_BI)
- priv->icount.brk++;
+ port->icount.brk++;
if (lsr & UART_LSR_FE)
- priv->icount.frame++;
+ port->icount.frame++;
if (lsr & UART_LSR_PE)
- priv->icount.parity++;
+ port->icount.parity++;
if (lsr & UART_LSR_OE)
- priv->icount.overrun++;
+ port->icount.overrun++;
}
}
@@ -720,7 +670,8 @@ static struct usb_serial_driver ark3116_device = {
.ioctl = ark3116_ioctl,
.tiocmget = ark3116_tiocmget,
.tiocmset = ark3116_tiocmset,
- .get_icount = ark3116_get_icount,
+ .tiocmiwait = usb_serial_generic_tiocmiwait,
+ .get_icount = usb_serial_generic_get_icount,
.open = ark3116_open,
.close = ark3116_close,
.break_ctl = ark3116_break_ctl,
diff --git a/drivers/usb/serial/bus.c b/drivers/usb/serial/bus.c
index 37decb13d7e..3c4db6d196c 100644
--- a/drivers/usb/serial/bus.c
+++ b/drivers/usb/serial/bus.c
@@ -106,14 +106,15 @@ static int usb_serial_device_remove(struct device *dev)
/* make sure suspend/resume doesn't race against port_remove */
usb_autopm_get_interface(port->serial->interface);
+ minor = port->number;
+ tty_unregister_device(usb_serial_tty_driver, minor);
+
device_remove_file(&port->dev, &dev_attr_port_number);
driver = port->serial->type;
if (driver->port_remove)
retval = driver->port_remove(port);
- minor = port->number;
- tty_unregister_device(usb_serial_tty_driver, minor);
dev_info(dev, "%s converter now disconnected from ttyUSB%d\n",
driver->description, minor);
diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c
index d255f66e708..c2a4171ab9c 100644
--- a/drivers/usb/serial/ch341.c
+++ b/drivers/usb/serial/ch341.c
@@ -80,7 +80,6 @@ MODULE_DEVICE_TABLE(usb, id_table);
struct ch341_private {
spinlock_t lock; /* access lock */
- wait_queue_head_t delta_msr_wait; /* wait queue for modem status */
unsigned baud_rate; /* set baud rate */
u8 line_control; /* set line control value RTS/DTR */
u8 line_status; /* active status of modem control inputs */
@@ -252,7 +251,6 @@ static int ch341_port_probe(struct usb_serial_port *port)
return -ENOMEM;
spin_lock_init(&priv->lock);
- init_waitqueue_head(&priv->delta_msr_wait);
priv->baud_rate = DEFAULT_BAUD_RATE;
priv->line_control = CH341_BIT_RTS | CH341_BIT_DTR;
@@ -298,7 +296,6 @@ static void ch341_dtr_rts(struct usb_serial_port *port, int on)
priv->line_control &= ~(CH341_BIT_RTS | CH341_BIT_DTR);
spin_unlock_irqrestore(&priv->lock, flags);
ch341_set_handshake(port->serial->dev, priv->line_control);
- wake_up_interruptible(&priv->delta_msr_wait);
}
static void ch341_close(struct usb_serial_port *port)
@@ -491,7 +488,7 @@ static void ch341_read_int_callback(struct urb *urb)
tty_kref_put(tty);
}
- wake_up_interruptible(&priv->delta_msr_wait);
+ wake_up_interruptible(&port->port.delta_msr_wait);
}
exit:
@@ -502,8 +499,9 @@ exit:
__func__, status);
}
-static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
+static int ch341_tiocmiwait(struct tty_struct *tty, unsigned long arg)
{
+ struct usb_serial_port *port = tty->driver_data;
struct ch341_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
u8 prevstatus;
@@ -517,11 +515,14 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
spin_unlock_irqrestore(&priv->lock, flags);
while (!multi_change) {
- interruptible_sleep_on(&priv->delta_msr_wait);
+ interruptible_sleep_on(&port->port.delta_msr_wait);
/* see if a signal did it */
if (signal_pending(current))
return -ERESTARTSYS;
+ if (port->serial->disconnected)
+ return -EIO;
+
spin_lock_irqsave(&priv->lock, flags);
status = priv->line_status;
multi_change = priv->multi_status_change;
@@ -541,26 +542,6 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
return 0;
}
-static int ch341_ioctl(struct tty_struct *tty,
- unsigned int cmd, unsigned long arg)
-{
- struct usb_serial_port *port = tty->driver_data;
-
- dev_dbg(&port->dev, "%s (%d) cmd = 0x%04x\n", __func__, port->number, cmd);
-
- switch (cmd) {
- case TIOCMIWAIT:
- dev_dbg(&port->dev, "%s (%d) TIOCMIWAIT\n", __func__, port->number);
- return wait_modem_info(port, arg);
-
- default:
- dev_dbg(&port->dev, "%s not supported = 0x%04x\n", __func__, cmd);
- break;
- }
-
- return -ENOIOCTLCMD;
-}
-
static int ch341_tiocmget(struct tty_struct *tty)
{
struct usb_serial_port *port = tty->driver_data;
@@ -610,11 +591,11 @@ static struct usb_serial_driver ch341_device = {
.dtr_rts = ch341_dtr_rts,
.carrier_raised = ch341_carrier_raised,
.close = ch341_close,
- .ioctl = ch341_ioctl,
.set_termios = ch341_set_termios,
.break_ctl = ch341_break_ctl,
.tiocmget = ch341_tiocmget,
.tiocmset = ch341_tiocmset,
+ .tiocmiwait = ch341_tiocmiwait,
.read_int_callback = ch341_read_int_callback,
.port_probe = ch341_port_probe,
.port_remove = ch341_port_remove,
diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c
index edc0f0dcad8..2c659553c07 100644
--- a/drivers/usb/serial/cp210x.c
+++ b/drivers/usb/serial/cp210x.c
@@ -85,6 +85,7 @@ static const struct usb_device_id id_table[] = {
{ USB_DEVICE(0x10C4, 0x813F) }, /* Tams Master Easy Control */
{ USB_DEVICE(0x10C4, 0x814A) }, /* West Mountain Radio RIGblaster P&P */
{ USB_DEVICE(0x10C4, 0x814B) }, /* West Mountain Radio RIGtalk */
+ { USB_DEVICE(0x2405, 0x0003) }, /* West Mountain Radio RIGblaster Advantage */
{ USB_DEVICE(0x10C4, 0x8156) }, /* B&G H3000 link cable */
{ USB_DEVICE(0x10C4, 0x815E) }, /* Helicomm IP-Link 1220-DVM */
{ USB_DEVICE(0x10C4, 0x815F) }, /* Timewave HamLinkUSB */
@@ -150,6 +151,25 @@ static const struct usb_device_id id_table[] = {
{ USB_DEVICE(0x1BE3, 0x07A6) }, /* WAGO 750-923 USB Service Cable */
{ USB_DEVICE(0x1E29, 0x0102) }, /* Festo CPX-USB */
{ USB_DEVICE(0x1E29, 0x0501) }, /* Festo CMSP */
+ { USB_DEVICE(0x1FB9, 0x0100) }, /* Lake Shore Model 121 Current Source */
+ { USB_DEVICE(0x1FB9, 0x0200) }, /* Lake Shore Model 218A Temperature Monitor */
+ { USB_DEVICE(0x1FB9, 0x0201) }, /* Lake Shore Model 219 Temperature Monitor */
+ { USB_DEVICE(0x1FB9, 0x0202) }, /* Lake Shore Model 233 Temperature Transmitter */
+ { USB_DEVICE(0x1FB9, 0x0203) }, /* Lake Shore Model 235 Temperature Transmitter */
+ { USB_DEVICE(0x1FB9, 0x0300) }, /* Lake Shore Model 335 Temperature Controller */
+ { USB_DEVICE(0x1FB9, 0x0301) }, /* Lake Shore Model 336 Temperature Controller */
+ { USB_DEVICE(0x1FB9, 0x0302) }, /* Lake Shore Model 350 Temperature Controller */
+ { USB_DEVICE(0x1FB9, 0x0303) }, /* Lake Shore Model 371 AC Bridge */
+ { USB_DEVICE(0x1FB9, 0x0400) }, /* Lake Shore Model 411 Handheld Gaussmeter */
+ { USB_DEVICE(0x1FB9, 0x0401) }, /* Lake Shore Model 425 Gaussmeter */
+ { USB_DEVICE(0x1FB9, 0x0402) }, /* Lake Shore Model 455A Gaussmeter */
+ { USB_DEVICE(0x1FB9, 0x0403) }, /* Lake Shore Model 475A Gaussmeter */
+ { USB_DEVICE(0x1FB9, 0x0404) }, /* Lake Shore Model 465 Three Axis Gaussmeter */
+ { USB_DEVICE(0x1FB9, 0x0600) }, /* Lake Shore Model 625A Superconducting MPS */
+ { USB_DEVICE(0x1FB9, 0x0601) }, /* Lake Shore Model 642A Magnet Power Supply */
+ { USB_DEVICE(0x1FB9, 0x0602) }, /* Lake Shore Model 648 Magnet Power Supply */
+ { USB_DEVICE(0x1FB9, 0x0700) }, /* Lake Shore Model 737 VSM Controller */
+ { USB_DEVICE(0x1FB9, 0x0701) }, /* Lake Shore Model 776 Hall Matrix */
{ USB_DEVICE(0x3195, 0xF190) }, /* Link Instruments MSO-19 */
{ USB_DEVICE(0x3195, 0xF280) }, /* Link Instruments MSO-28 */
{ USB_DEVICE(0x3195, 0xF281) }, /* Link Instruments MSO-28 */
@@ -442,11 +462,7 @@ static int cp210x_open(struct tty_struct *tty, struct usb_serial_port *port)
static void cp210x_close(struct usb_serial_port *port)
{
usb_serial_generic_close(port);
-
- mutex_lock(&port->serial->disc_mutex);
- if (!port->serial->disconnected)
- cp210x_set_config_single(port, CP210X_IFC_ENABLE, UART_DISABLE);
- mutex_unlock(&port->serial->disc_mutex);
+ cp210x_set_config_single(port, CP210X_IFC_ENABLE, UART_DISABLE);
}
/*
diff --git a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c
index 629bd289450..781426230d6 100644
--- a/drivers/usb/serial/cyberjack.c
+++ b/drivers/usb/serial/cyberjack.c
@@ -51,7 +51,6 @@
#define CYBERJACK_PRODUCT_ID 0x0100
/* Function prototypes */
-static void cyberjack_disconnect(struct usb_serial *serial);
static int cyberjack_port_probe(struct usb_serial_port *port);
static int cyberjack_port_remove(struct usb_serial_port *port);
static int cyberjack_open(struct tty_struct *tty,
@@ -79,7 +78,6 @@ static struct usb_serial_driver cyberjack_device = {
.description = "Reiner SCT Cyberjack USB card reader",
.id_table = id_table,
.num_ports = 1,
- .disconnect = cyberjack_disconnect,
.port_probe = cyberjack_port_probe,
.port_remove = cyberjack_port_remove,
.open = cyberjack_open,
@@ -130,20 +128,14 @@ static int cyberjack_port_remove(struct usb_serial_port *port)
{
struct cyberjack_private *priv;
+ usb_kill_urb(port->interrupt_in_urb);
+
priv = usb_get_serial_port_data(port);
kfree(priv);
return 0;
}
-static void cyberjack_disconnect(struct usb_serial *serial)
-{
- int i;
-
- for (i = 0; i < serial->num_ports; ++i)
- usb_kill_urb(serial->port[i]->interrupt_in_urb);
-}
-
static int cyberjack_open(struct tty_struct *tty,
struct usb_serial_port *port)
{
@@ -166,11 +158,8 @@ static int cyberjack_open(struct tty_struct *tty,
static void cyberjack_close(struct usb_serial_port *port)
{
- if (port->serial->dev) {
- /* shutdown any bulk reads that might be going on */
- usb_kill_urb(port->write_urb);
- usb_kill_urb(port->read_urb);
- }
+ usb_kill_urb(port->write_urb);
+ usb_kill_urb(port->read_urb);
}
static int cyberjack_write(struct tty_struct *tty,
diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c
index 8efa19d0e9f..d341555d37d 100644
--- a/drivers/usb/serial/cypress_m8.c
+++ b/drivers/usb/serial/cypress_m8.c
@@ -111,7 +111,6 @@ struct cypress_private {
int baud_rate; /* stores current baud rate in
integer form */
int isthrottled; /* if throttled, discard reads */
- wait_queue_head_t delta_msr_wait; /* used for TIOCMIWAIT */
char prev_status, diff_status; /* used for TIOCMIWAIT */
/* we pass a pointer to this as the argument sent to
cypress_set_termios old_termios */
@@ -130,13 +129,12 @@ static int cypress_write(struct tty_struct *tty, struct usb_serial_port *port,
const unsigned char *buf, int count);
static void cypress_send(struct usb_serial_port *port);
static int cypress_write_room(struct tty_struct *tty);
-static int cypress_ioctl(struct tty_struct *tty,
- unsigned int cmd, unsigned long arg);
static void cypress_set_termios(struct tty_struct *tty,
struct usb_serial_port *port, struct ktermios *old);
static int cypress_tiocmget(struct tty_struct *tty);
static int cypress_tiocmset(struct tty_struct *tty,
unsigned int set, unsigned int clear);
+static int cypress_tiocmiwait(struct tty_struct *tty, unsigned long arg);
static int cypress_chars_in_buffer(struct tty_struct *tty);
static void cypress_throttle(struct tty_struct *tty);
static void cypress_unthrottle(struct tty_struct *tty);
@@ -159,10 +157,10 @@ static struct usb_serial_driver cypress_earthmate_device = {
.dtr_rts = cypress_dtr_rts,
.write = cypress_write,
.write_room = cypress_write_room,
- .ioctl = cypress_ioctl,
.set_termios = cypress_set_termios,
.tiocmget = cypress_tiocmget,
.tiocmset = cypress_tiocmset,
+ .tiocmiwait = cypress_tiocmiwait,
.chars_in_buffer = cypress_chars_in_buffer,
.throttle = cypress_throttle,
.unthrottle = cypress_unthrottle,
@@ -185,10 +183,10 @@ static struct usb_serial_driver cypress_hidcom_device = {
.dtr_rts = cypress_dtr_rts,
.write = cypress_write,
.write_room = cypress_write_room,
- .ioctl = cypress_ioctl,
.set_termios = cypress_set_termios,
.tiocmget = cypress_tiocmget,
.tiocmset = cypress_tiocmset,
+ .tiocmiwait = cypress_tiocmiwait,
.chars_in_buffer = cypress_chars_in_buffer,
.throttle = cypress_throttle,
.unthrottle = cypress_unthrottle,
@@ -211,10 +209,10 @@ static struct usb_serial_driver cypress_ca42v2_device = {
.dtr_rts = cypress_dtr_rts,
.write = cypress_write,
.write_room = cypress_write_room,
- .ioctl = cypress_ioctl,
.set_termios = cypress_set_termios,
.tiocmget = cypress_tiocmget,
.tiocmset = cypress_tiocmset,
+ .tiocmiwait = cypress_tiocmiwait,
.chars_in_buffer = cypress_chars_in_buffer,
.throttle = cypress_throttle,
.unthrottle = cypress_unthrottle,
@@ -449,7 +447,6 @@ static int cypress_generic_port_probe(struct usb_serial_port *port)
kfree(priv);
return -ENOMEM;
}
- init_waitqueue_head(&priv->delta_msr_wait);
usb_reset_configuration(serial->dev);
@@ -635,12 +632,6 @@ static void cypress_close(struct usb_serial_port *port)
struct cypress_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
- /* writing is potentially harmful, lock must be taken */
- mutex_lock(&port->serial->disc_mutex);
- if (port->serial->disconnected) {
- mutex_unlock(&port->serial->disc_mutex);
- return;
- }
spin_lock_irqsave(&priv->lock, flags);
kfifo_reset_out(&priv->write_fifo);
spin_unlock_irqrestore(&priv->lock, flags);
@@ -652,7 +643,6 @@ static void cypress_close(struct usb_serial_port *port)
if (stats)
dev_info(&port->dev, "Statistics: %d Bytes In | %d Bytes Out | %d Commands Issued\n",
priv->bytes_in, priv->bytes_out, priv->cmd_count);
- mutex_unlock(&port->serial->disc_mutex);
} /* cypress_close */
@@ -857,51 +847,43 @@ static int cypress_tiocmset(struct tty_struct *tty,
}
-static int cypress_ioctl(struct tty_struct *tty,
- unsigned int cmd, unsigned long arg)
+static int cypress_tiocmiwait(struct tty_struct *tty, unsigned long arg)
{
struct usb_serial_port *port = tty->driver_data;
struct cypress_private *priv = usb_get_serial_port_data(port);
-
- dev_dbg(&port->dev, "%s - port %d, cmd 0x%.4x\n", __func__, port->number, cmd);
-
- switch (cmd) {
- /* This code comes from drivers/char/serial.c and ftdi_sio.c */
- case TIOCMIWAIT:
- while (priv != NULL) {
- interruptible_sleep_on(&priv->delta_msr_wait);
- /* see if a signal did it */
- if (signal_pending(current))
- return -ERESTARTSYS;
- else {
- char diff = priv->diff_status;
- if (diff == 0)
- return -EIO; /* no change => error */
-
- /* consume all events */
- priv->diff_status = 0;
-
- /* return 0 if caller wanted to know about
- these bits */
- if (((arg & TIOCM_RNG) && (diff & UART_RI)) ||
- ((arg & TIOCM_DSR) && (diff & UART_DSR)) ||
- ((arg & TIOCM_CD) && (diff & UART_CD)) ||
- ((arg & TIOCM_CTS) && (diff & UART_CTS)))
- return 0;
- /* otherwise caller can't care less about what
- * happened, and so we continue to wait for
- * more events.
- */
- }
- }
- return 0;
- default:
- break;
+ char diff;
+
+ for (;;) {
+ interruptible_sleep_on(&port->port.delta_msr_wait);
+ /* see if a signal did it */
+ if (signal_pending(current))
+ return -ERESTARTSYS;
+
+ if (port->serial->disconnected)
+ return -EIO;
+
+ diff = priv->diff_status;
+ if (diff == 0)
+ return -EIO; /* no change => error */
+
+ /* consume all events */
+ priv->diff_status = 0;
+
+ /* return 0 if caller wanted to know about
+ these bits */
+ if (((arg & TIOCM_RNG) && (diff & UART_RI)) ||
+ ((arg & TIOCM_DSR) && (diff & UART_DSR)) ||
+ ((arg & TIOCM_CD) && (diff & UART_CD)) ||
+ ((arg & TIOCM_CTS) && (diff & UART_CTS)))
+ return 0;
+ /* otherwise caller can't care less about what
+ * happened, and so we continue to wait for
+ * more events.
+ */
}
- dev_dbg(&port->dev, "%s - arg not supported - it was 0x%04x - check include/asm/ioctls.h\n", __func__, cmd);
- return -ENOIOCTLCMD;
-} /* cypress_ioctl */
+ return 0;
+}
static void cypress_set_termios(struct tty_struct *tty,
struct usb_serial_port *port, struct ktermios *old_termios)
@@ -1187,7 +1169,7 @@ static void cypress_read_int_callback(struct urb *urb)
if (priv->current_status != priv->prev_status) {
priv->diff_status |= priv->current_status ^
priv->prev_status;
- wake_up_interruptible(&priv->delta_msr_wait);
+ wake_up_interruptible(&port->port.delta_msr_wait);
priv->prev_status = priv->current_status;
}
spin_unlock_irqrestore(&priv->lock, flags);
diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c
index ebe45fa0ed5..7b807d38952 100644
--- a/drivers/usb/serial/digi_acceleport.c
+++ b/drivers/usb/serial/digi_acceleport.c
@@ -196,7 +196,6 @@ struct digi_port {
unsigned char dp_out_buf[DIGI_OUT_BUF_SIZE];
int dp_write_urb_in_use;
unsigned int dp_modem_signals;
- wait_queue_head_t dp_modem_change_wait;
int dp_transmit_idle;
wait_queue_head_t dp_transmit_idle_wait;
int dp_throttled;
@@ -210,7 +209,6 @@ struct digi_port {
/* Local Function Declarations */
-static void digi_wakeup_write(struct usb_serial_port *port);
static void digi_wakeup_write_lock(struct work_struct *work);
static int digi_write_oob_command(struct usb_serial_port *port,
unsigned char *buf, int count, int interruptible);
@@ -374,20 +372,10 @@ static void digi_wakeup_write_lock(struct work_struct *work)
unsigned long flags;
spin_lock_irqsave(&priv->dp_port_lock, flags);
- digi_wakeup_write(port);
+ tty_port_tty_wakeup(&port->port);
spin_unlock_irqrestore(&priv->dp_port_lock, flags);
}
-static void digi_wakeup_write(struct usb_serial_port *port)
-{
- struct tty_struct *tty = tty_port_tty_get(&port->port);
- if (tty) {
- tty_wakeup(tty);
- tty_kref_put(tty);
- }
-}
-
-
/*
* Digi Write OOB Command
*
@@ -1044,7 +1032,7 @@ static void digi_write_bulk_callback(struct urb *urb)
}
}
/* wake up processes sleeping on writes immediately */
- digi_wakeup_write(port);
+ tty_port_tty_wakeup(&port->port);
/* also queue up a wakeup at scheduler time, in case we */
/* lost the race in write_chan(). */
schedule_work(&priv->dp_wakeup_work);
@@ -1149,53 +1137,51 @@ static void digi_close(struct usb_serial_port *port)
if (port->serial->disconnected)
goto exit;
- if (port->serial->dev) {
- /* FIXME: Transmit idle belongs in the wait_unti_sent path */
- digi_transmit_idle(port, DIGI_CLOSE_TIMEOUT);
-
- /* disable input flow control */
- buf[0] = DIGI_CMD_SET_INPUT_FLOW_CONTROL;
- buf[1] = priv->dp_port_num;
- buf[2] = DIGI_DISABLE;
- buf[3] = 0;
-
- /* disable output flow control */
- buf[4] = DIGI_CMD_SET_OUTPUT_FLOW_CONTROL;
- buf[5] = priv->dp_port_num;
- buf[6] = DIGI_DISABLE;
- buf[7] = 0;
-
- /* disable reading modem signals automatically */
- buf[8] = DIGI_CMD_READ_INPUT_SIGNALS;
- buf[9] = priv->dp_port_num;
- buf[10] = DIGI_DISABLE;
- buf[11] = 0;
-
- /* disable receive */
- buf[12] = DIGI_CMD_RECEIVE_ENABLE;
- buf[13] = priv->dp_port_num;
- buf[14] = DIGI_DISABLE;
- buf[15] = 0;
-
- /* flush fifos */
- buf[16] = DIGI_CMD_IFLUSH_FIFO;
- buf[17] = priv->dp_port_num;
- buf[18] = DIGI_FLUSH_TX | DIGI_FLUSH_RX;
- buf[19] = 0;
-
- ret = digi_write_oob_command(port, buf, 20, 0);
- if (ret != 0)
- dev_dbg(&port->dev, "digi_close: write oob failed, ret=%d\n", ret);
-
- /* wait for final commands on oob port to complete */
- prepare_to_wait(&priv->dp_flush_wait, &wait,
- TASK_INTERRUPTIBLE);
- schedule_timeout(DIGI_CLOSE_TIMEOUT);
- finish_wait(&priv->dp_flush_wait, &wait);
-
- /* shutdown any outstanding bulk writes */
- usb_kill_urb(port->write_urb);
- }
+ /* FIXME: Transmit idle belongs in the wait_unti_sent path */
+ digi_transmit_idle(port, DIGI_CLOSE_TIMEOUT);
+
+ /* disable input flow control */
+ buf[0] = DIGI_CMD_SET_INPUT_FLOW_CONTROL;
+ buf[1] = priv->dp_port_num;
+ buf[2] = DIGI_DISABLE;
+ buf[3] = 0;
+
+ /* disable output flow control */
+ buf[4] = DIGI_CMD_SET_OUTPUT_FLOW_CONTROL;
+ buf[5] = priv->dp_port_num;
+ buf[6] = DIGI_DISABLE;
+ buf[7] = 0;
+
+ /* disable reading modem signals automatically */
+ buf[8] = DIGI_CMD_READ_INPUT_SIGNALS;
+ buf[9] = priv->dp_port_num;
+ buf[10] = DIGI_DISABLE;
+ buf[11] = 0;
+
+ /* disable receive */
+ buf[12] = DIGI_CMD_RECEIVE_ENABLE;
+ buf[13] = priv->dp_port_num;
+ buf[14] = DIGI_DISABLE;
+ buf[15] = 0;
+
+ /* flush fifos */
+ buf[16] = DIGI_CMD_IFLUSH_FIFO;
+ buf[17] = priv->dp_port_num;
+ buf[18] = DIGI_FLUSH_TX | DIGI_FLUSH_RX;
+ buf[19] = 0;
+
+ ret = digi_write_oob_command(port, buf, 20, 0);
+ if (ret != 0)
+ dev_dbg(&port->dev, "digi_close: write oob failed, ret=%d\n",
+ ret);
+ /* wait for final commands on oob port to complete */
+ prepare_to_wait(&priv->dp_flush_wait, &wait,
+ TASK_INTERRUPTIBLE);
+ schedule_timeout(DIGI_CLOSE_TIMEOUT);
+ finish_wait(&priv->dp_flush_wait, &wait);
+
+ /* shutdown any outstanding bulk writes */
+ usb_kill_urb(port->write_urb);
exit:
spin_lock_irq(&priv->dp_port_lock);
priv->dp_write_urb_in_use = 0;
@@ -1252,7 +1238,6 @@ static int digi_port_init(struct usb_serial_port *port, unsigned port_num)
spin_lock_init(&priv->dp_port_lock);
priv->dp_port_num = port_num;
- init_waitqueue_head(&priv->dp_modem_change_wait);
init_waitqueue_head(&priv->dp_transmit_idle_wait);
init_waitqueue_head(&priv->dp_flush_wait);
init_waitqueue_head(&priv->dp_close_wait);
@@ -1522,7 +1507,7 @@ static int digi_read_oob_callback(struct urb *urb)
/* port must be open to use tty struct */
if (rts) {
tty->hw_stopped = 0;
- digi_wakeup_write(port);
+ tty_port_tty_wakeup(&port->port);
}
} else {
priv->dp_modem_signals &= ~TIOCM_CTS;
@@ -1543,7 +1528,6 @@ static int digi_read_oob_callback(struct urb *urb)
else
priv->dp_modem_signals &= ~TIOCM_CD;
- wake_up_interruptible(&priv->dp_modem_change_wait);
spin_unlock(&priv->dp_port_lock);
} else if (opcode == DIGI_CMD_TRANSMIT_IDLE) {
spin_lock(&priv->dp_port_lock);
diff --git a/drivers/usb/serial/f81232.c b/drivers/usb/serial/f81232.c
index b1b2dc64b50..090b411d893 100644
--- a/drivers/usb/serial/f81232.c
+++ b/drivers/usb/serial/f81232.c
@@ -47,7 +47,6 @@ MODULE_DEVICE_TABLE(usb, id_table);
struct f81232_private {
spinlock_t lock;
- wait_queue_head_t delta_msr_wait;
u8 line_control;
u8 line_status;
};
@@ -111,7 +110,7 @@ static void f81232_process_read_urb(struct urb *urb)
line_status = priv->line_status;
priv->line_status &= ~UART_STATE_TRANSIENT_MASK;
spin_unlock_irqrestore(&priv->lock, flags);
- wake_up_interruptible(&priv->delta_msr_wait);
+ wake_up_interruptible(&port->port.delta_msr_wait);
if (!urb->actual_length)
return;
@@ -243,8 +242,9 @@ static int f81232_carrier_raised(struct usb_serial_port *port)
return 0;
}
-static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
+static int f81232_tiocmiwait(struct tty_struct *tty, unsigned long arg)
{
+ struct usb_serial_port *port = tty->driver_data;
struct f81232_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
unsigned int prevstatus;
@@ -256,11 +256,14 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
spin_unlock_irqrestore(&priv->lock, flags);
while (1) {
- interruptible_sleep_on(&priv->delta_msr_wait);
+ interruptible_sleep_on(&port->port.delta_msr_wait);
/* see if a signal did it */
if (signal_pending(current))
return -ERESTARTSYS;
+ if (port->serial->disconnected)
+ return -EIO;
+
spin_lock_irqsave(&priv->lock, flags);
status = priv->line_status;
spin_unlock_irqrestore(&priv->lock, flags);
@@ -300,11 +303,6 @@ static int f81232_ioctl(struct tty_struct *tty,
return -EFAULT;
return 0;
-
- case TIOCMIWAIT:
- dev_dbg(&port->dev, "%s (%d) TIOCMIWAIT\n", __func__,
- port->number);
- return wait_modem_info(port, arg);
default:
dev_dbg(&port->dev, "%s not supported = 0x%04x\n",
__func__, cmd);
@@ -322,7 +320,6 @@ static int f81232_port_probe(struct usb_serial_port *port)
return -ENOMEM;
spin_lock_init(&priv->lock);
- init_waitqueue_head(&priv->delta_msr_wait);
usb_set_serial_port_data(port, priv);
@@ -357,6 +354,7 @@ static struct usb_serial_driver f81232_device = {
.set_termios = f81232_set_termios,
.tiocmget = f81232_tiocmget,
.tiocmset = f81232_tiocmset,
+ .tiocmiwait = f81232_tiocmiwait,
.process_read_urb = f81232_process_read_urb,
.read_int_callback = f81232_read_int_callback,
.port_probe = f81232_port_probe,
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index edd162df49c..242b5776648 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -1,7 +1,7 @@
/*
* USB FTDI SIO driver
*
- * Copyright (C) 2009 - 2010
+ * Copyright (C) 2009 - 2013
* Johan Hovold (jhovold@gmail.com)
* Copyright (C) 1999 - 2001
* Greg Kroah-Hartman (greg@kroah.com)
@@ -55,7 +55,6 @@ static __u16 vendor = FTDI_VID;
static __u16 product;
struct ftdi_private {
- struct kref kref;
enum ftdi_chip_type chip_type;
/* type of device, either SIO or FT8U232AM */
int baud_base; /* baud base clock for divisor setting */
@@ -68,10 +67,7 @@ struct ftdi_private {
*/
int flags; /* some ASYNC_xxxx flags are supported */
unsigned long last_dtr_rts; /* saved modem control outputs */
- struct async_icount icount;
- wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */
char prev_status; /* Used for TIOCMIWAIT */
- bool dev_gone; /* Used to abort TIOCMIWAIT */
char transmit_empty; /* If transmitter is empty or not */
__u16 interface; /* FT2232C, FT2232H or FT4232H port interface
(0 for FT232/245) */
@@ -191,6 +187,7 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(FTDI_VID, FTDI_OPENDCC_THROTTLE_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_OPENDCC_GATEWAY_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_OPENDCC_GBM_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_OPENDCC_GBM_BOOST_PID) },
{ USB_DEVICE(NEWPORT_VID, NEWPORT_AGILIS_PID) },
{ USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_IOBOARD_PID) },
{ USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_MINI_IOBOARD_PID) },
@@ -642,6 +639,7 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(FTDI_VID, FTDI_RM_CANVIEW_PID) },
{ USB_DEVICE(ACTON_VID, ACTON_SPECTRAPRO_PID) },
{ USB_DEVICE(CONTEC_VID, CONTEC_COM1USBH_PID) },
+ { USB_DEVICE(MITSUBISHI_VID, MITSUBISHI_FXUSB_PID) },
{ USB_DEVICE(BANDB_VID, BANDB_USOTL4_PID) },
{ USB_DEVICE(BANDB_VID, BANDB_USTL4_PID) },
{ USB_DEVICE(BANDB_VID, BANDB_USO9ML2_PID) },
@@ -871,7 +869,9 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(FTDI_VID, FTDI_DOTEC_PID) },
{ USB_DEVICE(QIHARDWARE_VID, MILKYMISTONE_JTAGSERIAL_PID),
.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
- { USB_DEVICE(ST_VID, ST_STMCLT1030_PID),
+ { USB_DEVICE(ST_VID, ST_STMCLT_2232_PID),
+ .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
+ { USB_DEVICE(ST_VID, ST_STMCLT_4232_PID),
.driver_info = (kernel_ulong_t)&ftdi_stmclite_quirk },
{ USB_DEVICE(FTDI_VID, FTDI_RF_R106) },
{ USB_DEVICE(FTDI_VID, FTDI_DISTORTEC_JTAG_LOCK_PICK_PID),
@@ -912,7 +912,6 @@ static int ftdi_sio_probe(struct usb_serial *serial,
static int ftdi_sio_port_probe(struct usb_serial_port *port);
static int ftdi_sio_port_remove(struct usb_serial_port *port);
static int ftdi_open(struct tty_struct *tty, struct usb_serial_port *port);
-static void ftdi_close(struct usb_serial_port *port);
static void ftdi_dtr_rts(struct usb_serial_port *port, int on);
static void ftdi_process_read_urb(struct urb *urb);
static int ftdi_prepare_write_buffer(struct usb_serial_port *port,
@@ -922,8 +921,6 @@ static void ftdi_set_termios(struct tty_struct *tty,
static int ftdi_tiocmget(struct tty_struct *tty);
static int ftdi_tiocmset(struct tty_struct *tty,
unsigned int set, unsigned int clear);
-static int ftdi_get_icount(struct tty_struct *tty,
- struct serial_icounter_struct *icount);
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);
@@ -952,7 +949,6 @@ static struct usb_serial_driver ftdi_sio_device = {
.port_probe = ftdi_sio_port_probe,
.port_remove = ftdi_sio_port_remove,
.open = ftdi_open,
- .close = ftdi_close,
.dtr_rts = ftdi_dtr_rts,
.throttle = usb_serial_generic_throttle,
.unthrottle = usb_serial_generic_unthrottle,
@@ -960,7 +956,8 @@ static struct usb_serial_driver ftdi_sio_device = {
.prepare_write_buffer = ftdi_prepare_write_buffer,
.tiocmget = ftdi_tiocmget,
.tiocmset = ftdi_tiocmset,
- .get_icount = ftdi_get_icount,
+ .tiocmiwait = usb_serial_generic_tiocmiwait,
+ .get_icount = usb_serial_generic_get_icount,
.ioctl = ftdi_ioctl,
.set_termios = ftdi_set_termios,
.break_ctl = ftdi_break_ctl,
@@ -1689,12 +1686,9 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port)
return -ENOMEM;
}
- kref_init(&priv->kref);
mutex_init(&priv->cfg_lock);
- init_waitqueue_head(&priv->delta_msr_wait);
priv->flags = ASYNC_LOW_LATENCY;
- priv->dev_gone = false;
if (quirk && quirk->port_probe)
quirk->port_probe(priv);
@@ -1795,20 +1789,24 @@ static int ftdi_8u2232c_probe(struct usb_serial *serial)
}
/*
- * First and second port on STMCLiteadaptors is reserved for JTAG interface
- * and the forth port for pio
+ * First two ports on JTAG adaptors using an FT4232 such as STMicroelectronics's
+ * ST Micro Connect Lite are reserved for JTAG or other non-UART interfaces and
+ * can be accessed from userspace.
+ * The next two ports are enabled as UARTs by default, where port 2 is
+ * a conventional RS-232 UART.
*/
static int ftdi_stmclite_probe(struct usb_serial *serial)
{
struct usb_device *udev = serial->dev;
struct usb_interface *interface = serial->interface;
- if (interface == udev->actconfig->interface[2])
- return 0;
-
- dev_info(&udev->dev, "Ignoring serial port reserved for JTAG\n");
+ if (interface == udev->actconfig->interface[0] ||
+ interface == udev->actconfig->interface[1]) {
+ dev_info(&udev->dev, "Ignoring serial port reserved for JTAG\n");
+ return -ENODEV;
+ }
- return -ENODEV;
+ return 0;
}
/*
@@ -1829,23 +1827,13 @@ static int ftdi_mtxorb_hack_setup(struct usb_serial *serial)
return 0;
}
-static void ftdi_sio_priv_release(struct kref *k)
-{
- struct ftdi_private *priv = container_of(k, struct ftdi_private, kref);
-
- kfree(priv);
-}
-
static int ftdi_sio_port_remove(struct usb_serial_port *port)
{
struct ftdi_private *priv = usb_get_serial_port_data(port);
- priv->dev_gone = true;
- wake_up_interruptible_all(&priv->delta_msr_wait);
-
remove_sysfs_attrs(port);
- kref_put(&priv->kref, ftdi_sio_priv_release);
+ kfree(priv);
return 0;
}
@@ -1855,7 +1843,6 @@ static int ftdi_open(struct tty_struct *tty, struct usb_serial_port *port)
struct ktermios dummy;
struct usb_device *dev = port->serial->dev;
struct ftdi_private *priv = usb_get_serial_port_data(port);
- int result;
/* No error checking for this (will get errors later anyway) */
/* See ftdi_sio.h for description of what is reset */
@@ -1874,12 +1861,7 @@ static int ftdi_open(struct tty_struct *tty, struct usb_serial_port *port)
ftdi_set_termios(tty, port, &dummy);
}
- /* Start reading from the device */
- result = usb_serial_generic_open(tty, port);
- if (!result)
- kref_get(&priv->kref);
-
- return result;
+ return usb_serial_generic_open(tty, port);
}
static void ftdi_dtr_rts(struct usb_serial_port *port, int on)
@@ -1904,19 +1886,6 @@ static void ftdi_dtr_rts(struct usb_serial_port *port, int on)
clear_mctrl(port, TIOCM_DTR | TIOCM_RTS);
}
-/*
- * usbserial:__serial_close only calls ftdi_close if the point is open
- *
- * This only gets called when it is the last close
- */
-static void ftdi_close(struct usb_serial_port *port)
-{
- struct ftdi_private *priv = usb_get_serial_port_data(port);
-
- usb_serial_generic_close(port);
- kref_put(&priv->kref, ftdi_sio_priv_release);
-}
-
/* The SIO requires the first byte to have:
* B0 1
* B1 0
@@ -1944,7 +1913,7 @@ static int ftdi_prepare_write_buffer(struct usb_serial_port *port,
c = kfifo_out(&port->write_fifo, &buffer[i + 1], len);
if (!c)
break;
- priv->icount.tx += c;
+ port->icount.tx += c;
buffer[i] = (c << 2) + 1;
count += c + 1;
}
@@ -1952,7 +1921,7 @@ static int ftdi_prepare_write_buffer(struct usb_serial_port *port,
} else {
count = kfifo_out_locked(&port->write_fifo, dest, size,
&port->lock);
- priv->icount.tx += count;
+ port->icount.tx += count;
}
return count;
@@ -1981,15 +1950,15 @@ static int ftdi_process_packet(struct usb_serial_port *port,
char diff_status = status ^ priv->prev_status;
if (diff_status & FTDI_RS0_CTS)
- priv->icount.cts++;
+ port->icount.cts++;
if (diff_status & FTDI_RS0_DSR)
- priv->icount.dsr++;
+ port->icount.dsr++;
if (diff_status & FTDI_RS0_RI)
- priv->icount.rng++;
+ port->icount.rng++;
if (diff_status & FTDI_RS0_RLSD)
- priv->icount.dcd++;
+ port->icount.dcd++;
- wake_up_interruptible_all(&priv->delta_msr_wait);
+ wake_up_interruptible(&port->port.delta_msr_wait);
priv->prev_status = status;
}
@@ -1999,18 +1968,18 @@ static int ftdi_process_packet(struct usb_serial_port *port,
* over framing errors */
if (packet[1] & FTDI_RS_BI) {
flag = TTY_BREAK;
- priv->icount.brk++;
+ port->icount.brk++;
usb_serial_handle_break(port);
} else if (packet[1] & FTDI_RS_PE) {
flag = TTY_PARITY;
- priv->icount.parity++;
+ port->icount.parity++;
} else if (packet[1] & FTDI_RS_FE) {
flag = TTY_FRAME;
- priv->icount.frame++;
+ port->icount.frame++;
}
/* Overrun is special, not associated with a char */
if (packet[1] & FTDI_RS_OE) {
- priv->icount.overrun++;
+ port->icount.overrun++;
tty_insert_flip_char(&port->port, 0, TTY_OVERRUN);
}
}
@@ -2024,7 +1993,7 @@ static int ftdi_process_packet(struct usb_serial_port *port,
len -= 2;
if (!len)
return 0; /* status only */
- priv->icount.rx += len;
+ port->icount.rx += len;
ch = packet + 2;
if (port->port.console && port->sysrq) {
@@ -2388,34 +2357,10 @@ static int ftdi_tiocmset(struct tty_struct *tty,
return update_mctrl(port, set, clear);
}
-static int ftdi_get_icount(struct tty_struct *tty,
- struct serial_icounter_struct *icount)
-{
- struct usb_serial_port *port = tty->driver_data;
- struct ftdi_private *priv = usb_get_serial_port_data(port);
- struct async_icount *ic = &priv->icount;
-
- icount->cts = ic->cts;
- icount->dsr = ic->dsr;
- icount->rng = ic->rng;
- icount->dcd = ic->dcd;
- icount->tx = ic->tx;
- icount->rx = ic->rx;
- icount->frame = ic->frame;
- icount->parity = ic->parity;
- icount->overrun = ic->overrun;
- icount->brk = ic->brk;
- icount->buf_overrun = ic->buf_overrun;
- return 0;
-}
-
static int ftdi_ioctl(struct tty_struct *tty,
unsigned int cmd, unsigned long arg)
{
struct usb_serial_port *port = tty->driver_data;
- struct ftdi_private *priv = usb_get_serial_port_data(port);
- struct async_icount cnow;
- struct async_icount cprev;
dev_dbg(&port->dev, "%s cmd 0x%04x\n", __func__, cmd);
@@ -2429,33 +2374,6 @@ static int ftdi_ioctl(struct tty_struct *tty,
case TIOCSSERIAL: /* sets serial port data */
return set_serial_info(tty, port,
(struct serial_struct __user *) arg);
-
- /*
- * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change
- * - mask passed in arg for lines of interest
- * (use |'ed TIOCM_RNG/DSR/CD/CTS for masking)
- * Caller should use TIOCGICOUNT to see which one it was.
- *
- * This code is borrowed from linux/drivers/char/serial.c
- */
- case TIOCMIWAIT:
- cprev = priv->icount;
- while (!priv->dev_gone) {
- interruptible_sleep_on(&priv->delta_msr_wait);
- /* see if a signal did it */
- if (signal_pending(current))
- return -ERESTARTSYS;
- cnow = priv->icount;
- if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
- ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
- ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) ||
- ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) {
- return 0;
- }
- cprev = cnow;
- }
- return -EIO;
- break;
case TIOCSERGETLSR:
return get_lsr_info(port, (struct serial_struct __user *)arg);
break;
diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h
index 9d359e189a6..98528270c43 100644
--- a/drivers/usb/serial/ftdi_sio_ids.h
+++ b/drivers/usb/serial/ftdi_sio_ids.h
@@ -74,6 +74,7 @@
#define FTDI_OPENDCC_THROTTLE_PID 0xBFDA
#define FTDI_OPENDCC_GATEWAY_PID 0xBFDB
#define FTDI_OPENDCC_GBM_PID 0xBFDC
+#define FTDI_OPENDCC_GBM_BOOST_PID 0xBFDD
/* NZR SEM 16+ USB (http://www.nzr.de) */
#define FTDI_NZR_SEM_USB_PID 0xC1E0 /* NZR SEM-LOG16+ */
@@ -584,6 +585,13 @@
#define CONTEC_COM1USBH_PID 0x8311 /* COM-1(USB)H */
/*
+ * Mitsubishi Electric Corp. (http://www.meau.com)
+ * Submitted by Konstantin Holoborodko
+ */
+#define MITSUBISHI_VID 0x06D3
+#define MITSUBISHI_FXUSB_PID 0x0284 /* USB/RS422 converters: FX-USB-AW/-BD */
+
+/*
* Definitions for B&B Electronics products.
*/
#define BANDB_VID 0x0856 /* B&B Electronics Vendor ID */
@@ -1143,7 +1151,8 @@
* STMicroelectonics
*/
#define ST_VID 0x0483
-#define ST_STMCLT1030_PID 0x3747 /* ST Micro Connect Lite STMCLT1030 */
+#define ST_STMCLT_2232_PID 0x3746
+#define ST_STMCLT_4232_PID 0x3747
/*
* Papouch products (http://www.papouch.com/)
diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c
index 1a07b12ef34..b110c573ea8 100644
--- a/drivers/usb/serial/garmin_gps.c
+++ b/drivers/usb/serial/garmin_gps.c
@@ -946,20 +946,13 @@ static int garmin_open(struct tty_struct *tty, struct usb_serial_port *port)
static void garmin_close(struct usb_serial_port *port)
{
- struct usb_serial *serial = port->serial;
struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);
dev_dbg(&port->dev, "%s - port %d - mode=%d state=%d flags=0x%X\n",
__func__, port->number, garmin_data_p->mode,
garmin_data_p->state, garmin_data_p->flags);
- if (!serial)
- return;
-
- mutex_lock(&port->serial->disc_mutex);
-
- if (!port->serial->disconnected)
- garmin_clear(garmin_data_p);
+ garmin_clear(garmin_data_p);
/* shutdown our urbs */
usb_kill_urb(port->read_urb);
@@ -968,8 +961,6 @@ static void garmin_close(struct usb_serial_port *port)
/* keep reset state so we know that we must start a new session */
if (garmin_data_p->state != STATE_RESET)
garmin_data_p->state = STATE_DISCONNECTED;
-
- mutex_unlock(&port->serial->disc_mutex);
}
@@ -1190,17 +1181,11 @@ static void garmin_read_bulk_callback(struct urb *urb)
{
unsigned long flags;
struct usb_serial_port *port = urb->context;
- struct usb_serial *serial = port->serial;
struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);
unsigned char *data = urb->transfer_buffer;
int status = urb->status;
int retval;
- if (!serial) {
- dev_dbg(&urb->dev->dev, "%s - bad serial pointer, exiting\n", __func__);
- return;
- }
-
if (status) {
dev_dbg(&urb->dev->dev, "%s - nonzero read bulk status received: %d\n",
__func__, status);
diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c
index 4c5c23f1cae..297665fdd16 100644
--- a/drivers/usb/serial/generic.c
+++ b/drivers/usb/serial/generic.c
@@ -1,7 +1,7 @@
/*
* USB Serial Converter Generic functions
*
- * Copyright (C) 2010 - 2011 Johan Hovold (jhovold@gmail.com)
+ * Copyright (C) 2010 - 2013 Johan Hovold (jhovold@gmail.com)
* Copyright (C) 1999 - 2002 Greg Kroah-Hartman (greg@kroah.com)
*
* This program is free software; you can redistribute it and/or
@@ -45,8 +45,6 @@ struct usb_serial_driver usb_serial_generic_device = {
},
.id_table = generic_device_ids,
.num_ports = 1,
- .disconnect = usb_serial_generic_disconnect,
- .release = usb_serial_generic_release,
.throttle = usb_serial_generic_throttle,
.unthrottle = usb_serial_generic_unthrottle,
.resume = usb_serial_generic_resume,
@@ -102,32 +100,23 @@ int usb_serial_generic_open(struct tty_struct *tty, struct usb_serial_port *port
}
EXPORT_SYMBOL_GPL(usb_serial_generic_open);
-static void generic_cleanup(struct usb_serial_port *port)
+void usb_serial_generic_close(struct usb_serial_port *port)
{
- struct usb_serial *serial = port->serial;
unsigned long flags;
int i;
- if (serial->dev) {
- /* shutdown any bulk transfers that might be going on */
- if (port->bulk_out_size) {
- for (i = 0; i < ARRAY_SIZE(port->write_urbs); ++i)
- usb_kill_urb(port->write_urbs[i]);
+ if (port->bulk_out_size) {
+ for (i = 0; i < ARRAY_SIZE(port->write_urbs); ++i)
+ usb_kill_urb(port->write_urbs[i]);
- spin_lock_irqsave(&port->lock, flags);
- kfifo_reset_out(&port->write_fifo);
- spin_unlock_irqrestore(&port->lock, flags);
- }
- if (port->bulk_in_size) {
- for (i = 0; i < ARRAY_SIZE(port->read_urbs); ++i)
- usb_kill_urb(port->read_urbs[i]);
- }
+ spin_lock_irqsave(&port->lock, flags);
+ kfifo_reset_out(&port->write_fifo);
+ spin_unlock_irqrestore(&port->lock, flags);
+ }
+ if (port->bulk_in_size) {
+ for (i = 0; i < ARRAY_SIZE(port->read_urbs); ++i)
+ usb_kill_urb(port->read_urbs[i]);
}
-}
-
-void usb_serial_generic_close(struct usb_serial_port *port)
-{
- generic_cleanup(port);
}
EXPORT_SYMBOL_GPL(usb_serial_generic_close);
@@ -272,8 +261,7 @@ static int usb_serial_generic_submit_read_urb(struct usb_serial_port *port,
if (!test_and_clear_bit(index, &port->read_urbs_free))
return 0;
- dev_dbg(&port->dev, "%s - port %d, urb %d\n", __func__,
- port->number, index);
+ dev_dbg(&port->dev, "%s - urb %d\n", __func__, index);
res = usb_submit_urb(port->read_urbs[index], mem_flags);
if (res) {
@@ -347,8 +335,8 @@ void usb_serial_generic_read_bulk_callback(struct urb *urb)
}
set_bit(i, &port->read_urbs_free);
- dev_dbg(&port->dev, "%s - port %d, urb %d, len %d\n",
- __func__, port->number, i, urb->actual_length);
+ dev_dbg(&port->dev, "%s - urb %d, len %d\n", __func__, i,
+ urb->actual_length);
if (urb->status) {
dev_dbg(&port->dev, "%s - non-zero urb status: %d\n",
@@ -430,6 +418,91 @@ void usb_serial_generic_unthrottle(struct tty_struct *tty)
}
EXPORT_SYMBOL_GPL(usb_serial_generic_unthrottle);
+static bool usb_serial_generic_msr_changed(struct tty_struct *tty,
+ unsigned long arg, struct async_icount *cprev)
+{
+ struct usb_serial_port *port = tty->driver_data;
+ struct async_icount cnow;
+ unsigned long flags;
+ bool ret;
+
+ /*
+ * Use tty-port initialised flag to detect all hangups including the
+ * one generated at USB-device disconnect.
+ *
+ * FIXME: Remove hupping check once tty_port_hangup calls shutdown
+ * (which clears the initialised flag) before wake up.
+ */
+ if (test_bit(TTY_HUPPING, &tty->flags))
+ return true;
+ if (!test_bit(ASYNCB_INITIALIZED, &port->port.flags))
+ return true;
+
+ spin_lock_irqsave(&port->lock, flags);
+ cnow = port->icount; /* atomic copy*/
+ spin_unlock_irqrestore(&port->lock, flags);
+
+ ret = ((arg & TIOCM_RNG) && (cnow.rng != cprev->rng)) ||
+ ((arg & TIOCM_DSR) && (cnow.dsr != cprev->dsr)) ||
+ ((arg & TIOCM_CD) && (cnow.dcd != cprev->dcd)) ||
+ ((arg & TIOCM_CTS) && (cnow.cts != cprev->cts));
+
+ *cprev = cnow;
+
+ return ret;
+}
+
+int usb_serial_generic_tiocmiwait(struct tty_struct *tty, unsigned long arg)
+{
+ struct usb_serial_port *port = tty->driver_data;
+ struct async_icount cnow;
+ unsigned long flags;
+ int ret;
+
+ spin_lock_irqsave(&port->lock, flags);
+ cnow = port->icount; /* atomic copy */
+ spin_unlock_irqrestore(&port->lock, flags);
+
+ ret = wait_event_interruptible(port->port.delta_msr_wait,
+ usb_serial_generic_msr_changed(tty, arg, &cnow));
+ if (!ret) {
+ if (test_bit(TTY_HUPPING, &tty->flags))
+ ret = -EIO;
+ if (!test_bit(ASYNCB_INITIALIZED, &port->port.flags))
+ ret = -EIO;
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(usb_serial_generic_tiocmiwait);
+
+int usb_serial_generic_get_icount(struct tty_struct *tty,
+ struct serial_icounter_struct *icount)
+{
+ struct usb_serial_port *port = tty->driver_data;
+ struct async_icount cnow;
+ unsigned long flags;
+
+ spin_lock_irqsave(&port->lock, flags);
+ cnow = port->icount; /* atomic copy */
+ spin_unlock_irqrestore(&port->lock, flags);
+
+ icount->cts = cnow.cts;
+ icount->dsr = cnow.dsr;
+ icount->rng = cnow.rng;
+ icount->dcd = cnow.dcd;
+ icount->tx = cnow.tx;
+ icount->rx = cnow.rx;
+ icount->frame = cnow.frame;
+ icount->parity = cnow.parity;
+ icount->overrun = cnow.overrun;
+ icount->brk = cnow.brk;
+ icount->buf_overrun = cnow.buf_overrun;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(usb_serial_generic_get_icount);
+
#ifdef CONFIG_MAGIC_SYSRQ
int usb_serial_handle_sysrq_char(struct usb_serial_port *port, unsigned int ch)
{
@@ -473,8 +546,7 @@ void usb_serial_handle_dcd_change(struct usb_serial_port *usb_port,
{
struct tty_port *port = &usb_port->port;
- dev_dbg(&usb_port->dev, "%s - port %d, status %d\n", __func__,
- usb_port->number, status);
+ dev_dbg(&usb_port->dev, "%s - status %d\n", __func__, status);
if (status)
wake_up_interruptible(&port->open_wait);
@@ -510,17 +582,3 @@ int usb_serial_generic_resume(struct usb_serial *serial)
return c ? -EIO : 0;
}
EXPORT_SYMBOL_GPL(usb_serial_generic_resume);
-
-void usb_serial_generic_disconnect(struct usb_serial *serial)
-{
- int i;
-
- /* stop reads and writes on all ports */
- for (i = 0; i < serial->num_ports; ++i)
- generic_cleanup(serial->port[i]);
-}
-EXPORT_SYMBOL_GPL(usb_serial_generic_disconnect);
-
-void usb_serial_generic_release(struct usb_serial *serial)
-{
-}
diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c
index b00e5cbf741..1477e859347 100644
--- a/drivers/usb/serial/io_edgeport.c
+++ b/drivers/usb/serial/io_edgeport.c
@@ -110,9 +110,7 @@ struct edgeport_port {
wait_queue_head_t wait_chase; /* for handling sleeping while waiting for chase to finish */
wait_queue_head_t wait_open; /* for handling sleeping while waiting for open to finish */
wait_queue_head_t wait_command; /* for handling sleeping while waiting for command to finish */
- wait_queue_head_t delta_msr_wait; /* for handling sleeping while waiting for msr change to happen */
- struct async_icount icount;
struct usb_serial_port *port; /* loop back to the owner of this object */
};
@@ -216,8 +214,6 @@ static void edge_break(struct tty_struct *tty, int break_state);
static int edge_tiocmget(struct tty_struct *tty);
static int edge_tiocmset(struct tty_struct *tty,
unsigned int set, unsigned int clear);
-static int edge_get_icount(struct tty_struct *tty,
- struct serial_icounter_struct *icount);
static int edge_startup(struct usb_serial *serial);
static void edge_disconnect(struct usb_serial *serial);
static void edge_release(struct usb_serial *serial);
@@ -565,7 +561,6 @@ static void edge_interrupt_callback(struct urb *urb)
struct device *dev;
struct edgeport_port *edge_port;
struct usb_serial_port *port;
- struct tty_struct *tty;
unsigned char *data = urb->transfer_buffer;
int length = urb->actual_length;
int bytes_avail;
@@ -644,12 +639,7 @@ static void edge_interrupt_callback(struct urb *urb)
/* tell the tty driver that something
has changed */
- tty = tty_port_tty_get(
- &edge_port->port->port);
- if (tty) {
- tty_wakeup(tty);
- tty_kref_put(tty);
- }
+ tty_port_tty_wakeup(&edge_port->port->port);
/* Since we have more credit, check
if more data can be sent */
send_more_port_data(edge_serial,
@@ -738,7 +728,6 @@ static void edge_bulk_in_callback(struct urb *urb)
static void edge_bulk_out_data_callback(struct urb *urb)
{
struct edgeport_port *edge_port = urb->context;
- struct tty_struct *tty;
int status = urb->status;
if (status) {
@@ -747,14 +736,8 @@ static void edge_bulk_out_data_callback(struct urb *urb)
__func__, status);
}
- tty = tty_port_tty_get(&edge_port->port->port);
-
- if (tty && edge_port->open) {
- /* let the tty driver wakeup if it has a special
- write_wakeup function */
- tty_wakeup(tty);
- }
- tty_kref_put(tty);
+ if (edge_port->open)
+ tty_port_tty_wakeup(&edge_port->port->port);
/* Release the Write URB */
edge_port->write_in_progress = false;
@@ -773,7 +756,6 @@ static void edge_bulk_out_data_callback(struct urb *urb)
static void edge_bulk_out_cmd_callback(struct urb *urb)
{
struct edgeport_port *edge_port = urb->context;
- struct tty_struct *tty;
int status = urb->status;
atomic_dec(&CmdUrbs);
@@ -794,13 +776,9 @@ static void edge_bulk_out_cmd_callback(struct urb *urb)
return;
}
- /* Get pointer to tty */
- tty = tty_port_tty_get(&edge_port->port->port);
-
/* tell the tty driver that something has changed */
- if (tty && edge_port->open)
- tty_wakeup(tty);
- tty_kref_put(tty);
+ if (edge_port->open)
+ tty_port_tty_wakeup(&edge_port->port->port);
/* we have completed the command */
edge_port->commandPending = false;
@@ -884,12 +862,8 @@ static int edge_open(struct tty_struct *tty, struct usb_serial_port *port)
/* initialize our wait queues */
init_waitqueue_head(&edge_port->wait_open);
init_waitqueue_head(&edge_port->wait_chase);
- init_waitqueue_head(&edge_port->delta_msr_wait);
init_waitqueue_head(&edge_port->wait_command);
- /* initialize our icount structure */
- memset(&(edge_port->icount), 0x00, sizeof(edge_port->icount));
-
/* initialize our port settings */
edge_port->txCredits = 0; /* Can't send any data yet */
/* Must always set this bit to enable ints! */
@@ -1316,7 +1290,7 @@ static void send_more_port_data(struct edgeport_serial *edge_serial,
/* decrement the number of credits we have by the number we just sent */
edge_port->txCredits -= count;
- edge_port->icount.tx += count;
+ edge_port->port->icount.tx += count;
status = usb_submit_urb(urb, GFP_ATOMIC);
if (status) {
@@ -1328,7 +1302,7 @@ static void send_more_port_data(struct edgeport_serial *edge_serial,
/* revert the credits as something bad happened. */
edge_port->txCredits += count;
- edge_port->icount.tx -= count;
+ edge_port->port->icount.tx -= count;
}
dev_dbg(dev, "%s wrote %d byte(s) TxCredit %d, Fifo %d\n",
__func__, count, edge_port->txCredits, fifo->count);
@@ -1590,31 +1564,6 @@ static int edge_tiocmget(struct tty_struct *tty)
return result;
}
-static int edge_get_icount(struct tty_struct *tty,
- struct serial_icounter_struct *icount)
-{
- struct usb_serial_port *port = tty->driver_data;
- struct edgeport_port *edge_port = usb_get_serial_port_data(port);
- struct async_icount cnow;
- cnow = edge_port->icount;
-
- icount->cts = cnow.cts;
- icount->dsr = cnow.dsr;
- icount->rng = cnow.rng;
- icount->dcd = cnow.dcd;
- icount->rx = cnow.rx;
- icount->tx = cnow.tx;
- icount->frame = cnow.frame;
- icount->overrun = cnow.overrun;
- icount->parity = cnow.parity;
- icount->brk = cnow.brk;
- icount->buf_overrun = cnow.buf_overrun;
-
- dev_dbg(&port->dev, "%s (%d) TIOCGICOUNT RX=%d, TX=%d\n", __func__,
- port->number, icount->rx, icount->tx);
- return 0;
-}
-
static int get_serial_info(struct edgeport_port *edge_port,
struct serial_struct __user *retinfo)
{
@@ -1651,8 +1600,6 @@ static int edge_ioctl(struct tty_struct *tty,
struct usb_serial_port *port = tty->driver_data;
DEFINE_WAIT(wait);
struct edgeport_port *edge_port = usb_get_serial_port_data(port);
- struct async_icount cnow;
- struct async_icount cprev;
dev_dbg(&port->dev, "%s - port %d, cmd = 0x%x\n", __func__, port->number, cmd);
@@ -1664,33 +1611,6 @@ static int edge_ioctl(struct tty_struct *tty,
case TIOCGSERIAL:
dev_dbg(&port->dev, "%s (%d) TIOCGSERIAL\n", __func__, port->number);
return get_serial_info(edge_port, (struct serial_struct __user *) arg);
-
- case TIOCMIWAIT:
- dev_dbg(&port->dev, "%s (%d) TIOCMIWAIT\n", __func__, port->number);
- cprev = edge_port->icount;
- while (1) {
- prepare_to_wait(&edge_port->delta_msr_wait,
- &wait, TASK_INTERRUPTIBLE);
- schedule();
- finish_wait(&edge_port->delta_msr_wait, &wait);
- /* see if a signal did it */
- if (signal_pending(current))
- return -ERESTARTSYS;
- cnow = edge_port->icount;
- if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
- cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
- return -EIO; /* no change => error */
- if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
- ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
- ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) ||
- ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) {
- return 0;
- }
- cprev = cnow;
- }
- /* NOTREACHED */
- break;
-
}
return -ENOIOCTLCMD;
}
@@ -1864,7 +1784,7 @@ static void process_rcvd_data(struct edgeport_serial *edge_serial,
edge_serial->rxPort);
edge_tty_recv(edge_port->port, buffer,
rxLen);
- edge_port->icount.rx += rxLen;
+ edge_port->port->icount.rx += rxLen;
}
buffer += rxLen;
}
@@ -2040,7 +1960,7 @@ static void handle_new_msr(struct edgeport_port *edge_port, __u8 newMsr)
if (newMsr & (EDGEPORT_MSR_DELTA_CTS | EDGEPORT_MSR_DELTA_DSR |
EDGEPORT_MSR_DELTA_RI | EDGEPORT_MSR_DELTA_CD)) {
- icount = &edge_port->icount;
+ icount = &edge_port->port->icount;
/* update input line counters */
if (newMsr & EDGEPORT_MSR_DELTA_CTS)
@@ -2051,7 +1971,7 @@ static void handle_new_msr(struct edgeport_port *edge_port, __u8 newMsr)
icount->dcd++;
if (newMsr & EDGEPORT_MSR_DELTA_RI)
icount->rng++;
- wake_up_interruptible(&edge_port->delta_msr_wait);
+ wake_up_interruptible(&edge_port->port->port.delta_msr_wait);
}
/* Save the new modem status */
@@ -2086,7 +2006,7 @@ static void handle_new_lsr(struct edgeport_port *edge_port, __u8 lsrData,
edge_tty_recv(edge_port->port, &data, 1);
/* update input line counters */
- icount = &edge_port->icount;
+ icount = &edge_port->port->icount;
if (newLsr & LSR_BREAK)
icount->brk++;
if (newLsr & LSR_OVER_ERR)
diff --git a/drivers/usb/serial/io_tables.h b/drivers/usb/serial/io_tables.h
index 1511dd0ad32..ae5fac5656c 100644
--- a/drivers/usb/serial/io_tables.h
+++ b/drivers/usb/serial/io_tables.h
@@ -116,7 +116,8 @@ static struct usb_serial_driver edgeport_2port_device = {
.set_termios = edge_set_termios,
.tiocmget = edge_tiocmget,
.tiocmset = edge_tiocmset,
- .get_icount = edge_get_icount,
+ .tiocmiwait = usb_serial_generic_tiocmiwait,
+ .get_icount = usb_serial_generic_get_icount,
.write = edge_write,
.write_room = edge_write_room,
.chars_in_buffer = edge_chars_in_buffer,
@@ -147,7 +148,8 @@ static struct usb_serial_driver edgeport_4port_device = {
.set_termios = edge_set_termios,
.tiocmget = edge_tiocmget,
.tiocmset = edge_tiocmset,
- .get_icount = edge_get_icount,
+ .tiocmiwait = usb_serial_generic_tiocmiwait,
+ .get_icount = usb_serial_generic_get_icount,
.write = edge_write,
.write_room = edge_write_room,
.chars_in_buffer = edge_chars_in_buffer,
@@ -178,7 +180,8 @@ static struct usb_serial_driver edgeport_8port_device = {
.set_termios = edge_set_termios,
.tiocmget = edge_tiocmget,
.tiocmset = edge_tiocmset,
- .get_icount = edge_get_icount,
+ .tiocmiwait = usb_serial_generic_tiocmiwait,
+ .get_icount = usb_serial_generic_get_icount,
.write = edge_write,
.write_room = edge_write_room,
.chars_in_buffer = edge_chars_in_buffer,
@@ -209,7 +212,8 @@ static struct usb_serial_driver epic_device = {
.set_termios = edge_set_termios,
.tiocmget = edge_tiocmget,
.tiocmset = edge_tiocmset,
- .get_icount = edge_get_icount,
+ .tiocmiwait = usb_serial_generic_tiocmiwait,
+ .get_icount = usb_serial_generic_get_icount,
.write = edge_write,
.write_room = edge_write_room,
.chars_in_buffer = edge_chars_in_buffer,
diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c
index c23776679f7..158bf4bc29c 100644
--- a/drivers/usb/serial/io_ti.c
+++ b/drivers/usb/serial/io_ti.c
@@ -86,10 +86,7 @@ struct edgeport_port {
int baud_rate;
int close_pending;
int lsr_event;
- struct async_icount icount;
- wait_queue_head_t delta_msr_wait; /* for handling sleeping while
- waiting for msr change to
- happen */
+
struct edgeport_serial *edge_serial;
struct usb_serial_port *port;
__u8 bUartMode; /* Port type, 0: RS232, etc. */
@@ -209,7 +206,7 @@ static int restart_read(struct edgeport_port *edge_port);
static void edge_set_termios(struct tty_struct *tty,
struct usb_serial_port *port, struct ktermios *old_termios);
-static void edge_send(struct tty_struct *tty);
+static void edge_send(struct usb_serial_port *port, struct tty_struct *tty);
/* sysfs attributes */
static int edge_create_sysfs_attrs(struct usb_serial_port *port);
@@ -1448,7 +1445,7 @@ static void handle_new_msr(struct edgeport_port *edge_port, __u8 msr)
if (msr & (EDGEPORT_MSR_DELTA_CTS | EDGEPORT_MSR_DELTA_DSR |
EDGEPORT_MSR_DELTA_RI | EDGEPORT_MSR_DELTA_CD)) {
- icount = &edge_port->icount;
+ icount = &edge_port->port->icount;
/* update input line counters */
if (msr & EDGEPORT_MSR_DELTA_CTS)
@@ -1459,7 +1456,7 @@ static void handle_new_msr(struct edgeport_port *edge_port, __u8 msr)
icount->dcd++;
if (msr & EDGEPORT_MSR_DELTA_RI)
icount->rng++;
- wake_up_interruptible(&edge_port->delta_msr_wait);
+ wake_up_interruptible(&edge_port->port->port.delta_msr_wait);
}
/* Save the new modem status */
@@ -1501,7 +1498,7 @@ static void handle_new_lsr(struct edgeport_port *edge_port, int lsr_data,
edge_tty_recv(edge_port->port, &data, 1);
/* update input line counters */
- icount = &edge_port->icount;
+ icount = &edge_port->port->icount;
if (new_lsr & LSR_BREAK)
icount->brk++;
if (new_lsr & LSR_OVER_ERR)
@@ -1660,7 +1657,7 @@ static void edge_bulk_in_callback(struct urb *urb)
else
edge_tty_recv(edge_port->port, data,
urb->actual_length);
- edge_port->icount.rx += urb->actual_length;
+ edge_port->port->icount.rx += urb->actual_length;
}
exit:
@@ -1715,7 +1712,7 @@ static void edge_bulk_out_callback(struct urb *urb)
/* send any buffered data */
tty = tty_port_tty_get(&port->port);
- edge_send(tty);
+ edge_send(port, tty);
tty_kref_put(tty);
}
@@ -1753,9 +1750,6 @@ static int edge_open(struct tty_struct *tty, struct usb_serial_port *port)
dev = port->serial->dev;
- memset(&(edge_port->icount), 0x00, sizeof(edge_port->icount));
- init_waitqueue_head(&edge_port->delta_msr_wait);
-
/* turn off loopback */
status = ti_do_config(edge_port, UMPC_SET_CLR_LOOPBACK, 0);
if (status) {
@@ -1913,21 +1907,10 @@ static void edge_close(struct usb_serial_port *port)
kfifo_reset_out(&edge_port->write_fifo);
spin_unlock_irqrestore(&edge_port->ep_lock, flags);
- /* assuming we can still talk to the device,
- * send a close port command to it */
dev_dbg(&port->dev, "%s - send umpc_close_port\n", __func__);
port_number = port->number - port->serial->minor;
-
- mutex_lock(&serial->disc_mutex);
- if (!serial->disconnected) {
- send_cmd(serial->dev,
- UMPC_CLOSE_PORT,
- (__u8)(UMPM_UART1_PORT + port_number),
- 0,
- NULL,
- 0);
- }
- mutex_unlock(&serial->disc_mutex);
+ send_cmd(serial->dev, UMPC_CLOSE_PORT,
+ (__u8)(UMPM_UART1_PORT + port_number), 0, NULL, 0);
mutex_lock(&edge_serial->es_lock);
--edge_port->edge_serial->num_ports_open;
@@ -1957,14 +1940,13 @@ static int edge_write(struct tty_struct *tty, struct usb_serial_port *port,
count = kfifo_in_locked(&edge_port->write_fifo, data, count,
&edge_port->ep_lock);
- edge_send(tty);
+ edge_send(port, tty);
return count;
}
-static void edge_send(struct tty_struct *tty)
+static void edge_send(struct usb_serial_port *port, struct tty_struct *tty)
{
- struct usb_serial_port *port = tty->driver_data;
int count, result;
struct edgeport_port *edge_port = usb_get_serial_port_data(port);
unsigned long flags;
@@ -2003,7 +1985,7 @@ static void edge_send(struct tty_struct *tty)
edge_port->ep_write_urb_in_use = 0;
/* TODO: reschedule edge_send */
} else
- edge_port->icount.tx += count;
+ edge_port->port->icount.tx += count;
/* wakeup any process waiting for writes to complete */
/* there is now more room in the buffer for new writes */
@@ -2364,27 +2346,6 @@ static int edge_tiocmget(struct tty_struct *tty)
return result;
}
-static int edge_get_icount(struct tty_struct *tty,
- struct serial_icounter_struct *icount)
-{
- struct usb_serial_port *port = tty->driver_data;
- struct edgeport_port *edge_port = usb_get_serial_port_data(port);
- struct async_icount *ic = &edge_port->icount;
-
- icount->cts = ic->cts;
- icount->dsr = ic->dsr;
- icount->rng = ic->rng;
- icount->dcd = ic->dcd;
- icount->tx = ic->tx;
- icount->rx = ic->rx;
- icount->frame = ic->frame;
- icount->parity = ic->parity;
- icount->overrun = ic->overrun;
- icount->brk = ic->brk;
- icount->buf_overrun = ic->buf_overrun;
- return 0;
-}
-
static int get_serial_info(struct edgeport_port *edge_port,
struct serial_struct __user *retinfo)
{
@@ -2396,7 +2357,7 @@ static int get_serial_info(struct edgeport_port *edge_port,
cwait = edge_port->port->port.closing_wait;
if (cwait != ASYNC_CLOSING_WAIT_NONE)
- cwait = jiffies_to_msecs(closing_wait) / 10;
+ cwait = jiffies_to_msecs(cwait) / 10;
memset(&tmp, 0, sizeof(tmp));
@@ -2420,8 +2381,6 @@ static int edge_ioctl(struct tty_struct *tty,
{
struct usb_serial_port *port = tty->driver_data;
struct edgeport_port *edge_port = usb_get_serial_port_data(port);
- struct async_icount cnow;
- struct async_icount cprev;
dev_dbg(&port->dev, "%s - port %d, cmd = 0x%x\n", __func__, port->number, cmd);
@@ -2430,28 +2389,6 @@ static int edge_ioctl(struct tty_struct *tty,
dev_dbg(&port->dev, "%s - TIOCGSERIAL\n", __func__);
return get_serial_info(edge_port,
(struct serial_struct __user *) arg);
- case TIOCMIWAIT:
- dev_dbg(&port->dev, "%s - TIOCMIWAIT\n", __func__);
- cprev = edge_port->icount;
- while (1) {
- interruptible_sleep_on(&edge_port->delta_msr_wait);
- /* see if a signal did it */
- if (signal_pending(current))
- return -ERESTARTSYS;
- cnow = edge_port->icount;
- if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
- cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
- return -EIO; /* no change => error */
- if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
- ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
- ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) ||
- ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) {
- return 0;
- }
- cprev = cnow;
- }
- /* not reached */
- break;
}
return -ENOIOCTLCMD;
}
@@ -2463,8 +2400,6 @@ static void edge_break(struct tty_struct *tty, int break_state)
int status;
int bv = 0; /* Off */
- tty_wait_until_sent(tty, 0);
-
if (break_state == -1)
bv = 1; /* On */
status = ti_do_config(edge_port, UMPC_SET_CLR_BREAK, bv);
@@ -2546,7 +2481,6 @@ static int edge_port_remove(struct usb_serial_port *port)
struct edgeport_port *edge_port;
edge_port = usb_get_serial_port_data(port);
-
edge_remove_sysfs_attrs(port);
kfifo_free(&edge_port->write_fifo);
kfree(edge_port);
@@ -2618,7 +2552,8 @@ static struct usb_serial_driver edgeport_1port_device = {
.set_termios = edge_set_termios,
.tiocmget = edge_tiocmget,
.tiocmset = edge_tiocmset,
- .get_icount = edge_get_icount,
+ .tiocmiwait = usb_serial_generic_tiocmiwait,
+ .get_icount = usb_serial_generic_get_icount,
.write = edge_write,
.write_room = edge_write_room,
.chars_in_buffer = edge_chars_in_buffer,
@@ -2649,6 +2584,8 @@ static struct usb_serial_driver edgeport_2port_device = {
.set_termios = edge_set_termios,
.tiocmget = edge_tiocmget,
.tiocmset = edge_tiocmset,
+ .tiocmiwait = usb_serial_generic_tiocmiwait,
+ .get_icount = usb_serial_generic_get_icount,
.write = edge_write,
.write_room = edge_write_room,
.chars_in_buffer = edge_chars_in_buffer,
diff --git a/drivers/usb/serial/iuu_phoenix.c b/drivers/usb/serial/iuu_phoenix.c
index ff77027160a..9d74c278b7b 100644
--- a/drivers/usb/serial/iuu_phoenix.c
+++ b/drivers/usb/serial/iuu_phoenix.c
@@ -55,7 +55,6 @@ static void read_rxcmd_callback(struct urb *urb);
struct iuu_private {
spinlock_t lock; /* store irq state */
- wait_queue_head_t delta_msr_wait;
u8 line_status;
int tiostatus; /* store IUART SIGNAL for tiocmget call */
u8 reset; /* if 1 reset is needed */
@@ -94,7 +93,6 @@ static int iuu_port_probe(struct usb_serial_port *port)
priv->vcc = vcc_default;
spin_lock_init(&priv->lock);
- init_waitqueue_head(&priv->delta_msr_wait);
usb_set_serial_port_data(port, priv);
@@ -944,22 +942,13 @@ static void iuu_set_termios(struct tty_struct *tty,
static void iuu_close(struct usb_serial_port *port)
{
/* iuu_led (port,255,0,0,0); */
- struct usb_serial *serial;
-
- serial = port->serial;
- if (!serial)
- return;
iuu_uart_off(port);
- if (serial->dev) {
- /* free writebuf */
- /* shutdown our urbs */
- dev_dbg(&port->dev, "%s - shutting down urbs\n", __func__);
- usb_kill_urb(port->write_urb);
- usb_kill_urb(port->read_urb);
- usb_kill_urb(port->interrupt_in_urb);
- iuu_led(port, 0, 0, 0xF000, 0xFF);
- }
+
+ usb_kill_urb(port->write_urb);
+ usb_kill_urb(port->read_urb);
+
+ iuu_led(port, 0, 0, 0xF000, 0xFF);
}
static void iuu_init_termios(struct tty_struct *tty)
diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c
index 1fd1935c831..eb30d7b01f3 100644
--- a/drivers/usb/serial/keyspan.c
+++ b/drivers/usb/serial/keyspan.c
@@ -378,7 +378,6 @@ static void usa26_instat_callback(struct urb *urb)
struct usb_serial *serial;
struct usb_serial_port *port;
struct keyspan_port_private *p_priv;
- struct tty_struct *tty;
int old_dcd_state, err;
int status = urb->status;
@@ -421,12 +420,8 @@ static void usa26_instat_callback(struct urb *urb)
p_priv->dcd_state = ((msg->gpia_dcd) ? 1 : 0);
p_priv->ri_state = ((msg->ri) ? 1 : 0);
- if (old_dcd_state != p_priv->dcd_state) {
- tty = tty_port_tty_get(&port->port);
- if (tty && !C_CLOCAL(tty))
- tty_hangup(tty);
- tty_kref_put(tty);
- }
+ if (old_dcd_state != p_priv->dcd_state)
+ tty_port_tty_hangup(&port->port, true);
/* Resubmit urb so we continue receiving */
err = usb_submit_urb(urb, GFP_ATOMIC);
@@ -510,7 +505,6 @@ static void usa28_instat_callback(struct urb *urb)
struct usb_serial *serial;
struct usb_serial_port *port;
struct keyspan_port_private *p_priv;
- struct tty_struct *tty;
int old_dcd_state;
int status = urb->status;
@@ -551,12 +545,8 @@ static void usa28_instat_callback(struct urb *urb)
p_priv->dcd_state = ((msg->dcd) ? 1 : 0);
p_priv->ri_state = ((msg->ri) ? 1 : 0);
- if (old_dcd_state != p_priv->dcd_state && old_dcd_state) {
- tty = tty_port_tty_get(&port->port);
- if (tty && !C_CLOCAL(tty))
- tty_hangup(tty);
- tty_kref_put(tty);
- }
+ if (old_dcd_state != p_priv->dcd_state && old_dcd_state)
+ tty_port_tty_hangup(&port->port, true);
/* Resubmit urb so we continue receiving */
err = usb_submit_urb(urb, GFP_ATOMIC);
@@ -642,12 +632,8 @@ static void usa49_instat_callback(struct urb *urb)
p_priv->dcd_state = ((msg->dcd) ? 1 : 0);
p_priv->ri_state = ((msg->ri) ? 1 : 0);
- if (old_dcd_state != p_priv->dcd_state && old_dcd_state) {
- struct tty_struct *tty = tty_port_tty_get(&port->port);
- if (tty && !C_CLOCAL(tty))
- tty_hangup(tty);
- tty_kref_put(tty);
- }
+ if (old_dcd_state != p_priv->dcd_state && old_dcd_state)
+ tty_port_tty_hangup(&port->port, true);
/* Resubmit urb so we continue receiving */
err = usb_submit_urb(urb, GFP_ATOMIC);
@@ -726,45 +712,45 @@ static void usa49wg_indat_callback(struct urb *urb)
i = 0;
len = 0;
- if (urb->actual_length) {
- while (i < urb->actual_length) {
+ while (i < urb->actual_length) {
- /* Check port number from message*/
- if (data[i] >= serial->num_ports) {
- dev_dbg(&urb->dev->dev, "%s - Unexpected port number %d\n",
- __func__, data[i]);
- return;
- }
- port = serial->port[data[i++]];
- len = data[i++];
+ /* Check port number from message */
+ if (data[i] >= serial->num_ports) {
+ dev_dbg(&urb->dev->dev, "%s - Unexpected port number %d\n",
+ __func__, data[i]);
+ return;
+ }
+ port = serial->port[data[i++]];
+ len = data[i++];
- /* 0x80 bit is error flag */
- if ((data[i] & 0x80) == 0) {
- /* no error on any byte */
- i++;
- for (x = 1; x < len ; ++x)
- tty_insert_flip_char(&port->port,
- data[i++], 0);
- } else {
- /*
- * some bytes had errors, every byte has status
- */
- for (x = 0; x + 1 < len; x += 2) {
- int stat = data[i], flag = 0;
- if (stat & RXERROR_OVERRUN)
- flag |= TTY_OVERRUN;
- if (stat & RXERROR_FRAMING)
- flag |= TTY_FRAME;
- if (stat & RXERROR_PARITY)
- flag |= TTY_PARITY;
- /* XXX should handle break (0x10) */
- tty_insert_flip_char(&port->port,
- data[i+1], flag);
- i += 2;
- }
+ /* 0x80 bit is error flag */
+ if ((data[i] & 0x80) == 0) {
+ /* no error on any byte */
+ i++;
+ for (x = 1; x < len && i < urb->actual_length; ++x)
+ tty_insert_flip_char(&port->port,
+ data[i++], 0);
+ } else {
+ /*
+ * some bytes had errors, every byte has status
+ */
+ for (x = 0; x + 1 < len &&
+ i + 1 < urb->actual_length; x += 2) {
+ int stat = data[i], flag = 0;
+
+ if (stat & RXERROR_OVERRUN)
+ flag |= TTY_OVERRUN;
+ if (stat & RXERROR_FRAMING)
+ flag |= TTY_FRAME;
+ if (stat & RXERROR_PARITY)
+ flag |= TTY_PARITY;
+ /* XXX should handle break (0x10) */
+ tty_insert_flip_char(&port->port, data[i+1],
+ flag);
+ i += 2;
}
- tty_flip_buffer_push(&port->port);
}
+ tty_flip_buffer_push(&port->port);
}
/* Resubmit urb so we continue receiving */
@@ -851,7 +837,6 @@ static void usa90_instat_callback(struct urb *urb)
struct usb_serial *serial;
struct usb_serial_port *port;
struct keyspan_port_private *p_priv;
- struct tty_struct *tty;
int old_dcd_state, err;
int status = urb->status;
@@ -880,12 +865,8 @@ static void usa90_instat_callback(struct urb *urb)
p_priv->dcd_state = ((msg->dcd) ? 1 : 0);
p_priv->ri_state = ((msg->ri) ? 1 : 0);
- if (old_dcd_state != p_priv->dcd_state && old_dcd_state) {
- tty = tty_port_tty_get(&port->port);
- if (tty && !C_CLOCAL(tty))
- tty_hangup(tty);
- tty_kref_put(tty);
- }
+ if (old_dcd_state != p_priv->dcd_state && old_dcd_state)
+ tty_port_tty_hangup(&port->port, true);
/* Resubmit urb so we continue receiving */
err = usb_submit_urb(urb, GFP_ATOMIC);
@@ -953,12 +934,8 @@ static void usa67_instat_callback(struct urb *urb)
p_priv->cts_state = ((msg->hskia_cts) ? 1 : 0);
p_priv->dcd_state = ((msg->gpia_dcd) ? 1 : 0);
- if (old_dcd_state != p_priv->dcd_state && old_dcd_state) {
- struct tty_struct *tty = tty_port_tty_get(&port->port);
- if (tty && !C_CLOCAL(tty))
- tty_hangup(tty);
- tty_kref_put(tty);
- }
+ if (old_dcd_state != p_priv->dcd_state && old_dcd_state)
+ tty_port_tty_hangup(&port->port, true);
/* Resubmit urb so we continue receiving */
err = usb_submit_urb(urb, GFP_ATOMIC);
@@ -1115,7 +1092,6 @@ static void keyspan_dtr_rts(struct usb_serial_port *port, int on)
static void keyspan_close(struct usb_serial_port *port)
{
int i;
- struct usb_serial *serial = port->serial;
struct keyspan_port_private *p_priv;
p_priv = usb_get_serial_port_data(port);
@@ -1123,28 +1099,17 @@ static void keyspan_close(struct usb_serial_port *port)
p_priv->rts_state = 0;
p_priv->dtr_state = 0;
- if (serial->dev) {
- keyspan_send_setup(port, 2);
- /* pilot-xfer seems to work best with this delay */
- mdelay(100);
- /* keyspan_set_termios(port, NULL); */
- }
-
- /*while (p_priv->outcont_urb->status == -EINPROGRESS) {
- dev_dbg(&port->dev, "%s - urb in progress\n", __func__);
- }*/
+ keyspan_send_setup(port, 2);
+ /* pilot-xfer seems to work best with this delay */
+ mdelay(100);
p_priv->out_flip = 0;
p_priv->in_flip = 0;
- if (serial->dev) {
- /* Stop reading/writing urbs */
- stop_urb(p_priv->inack_urb);
- /* stop_urb(p_priv->outcont_urb); */
- for (i = 0; i < 2; i++) {
- stop_urb(p_priv->in_urbs[i]);
- stop_urb(p_priv->out_urbs[i]);
- }
+ stop_urb(p_priv->inack_urb);
+ for (i = 0; i < 2; i++) {
+ stop_urb(p_priv->in_urbs[i]);
+ stop_urb(p_priv->out_urbs[i]);
}
}
diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c
index 3b17d5d13dc..5f1d382e55c 100644
--- a/drivers/usb/serial/keyspan_pda.c
+++ b/drivers/usb/serial/keyspan_pda.c
@@ -104,10 +104,8 @@ static void keyspan_pda_wakeup_write(struct work_struct *work)
struct keyspan_pda_private *priv =
container_of(work, struct keyspan_pda_private, wakeup_work);
struct usb_serial_port *port = priv->port;
- struct tty_struct *tty = tty_port_tty_get(&port->port);
- if (tty)
- tty_wakeup(tty);
- tty_kref_put(tty);
+
+ tty_port_tty_wakeup(&port->port);
}
static void keyspan_pda_request_unthrottle(struct work_struct *work)
@@ -595,12 +593,10 @@ static void keyspan_pda_dtr_rts(struct usb_serial_port *port, int on)
{
struct usb_serial *serial = port->serial;
- if (serial->dev) {
- if (on)
- keyspan_pda_set_modem_info(serial, (1<<7) | (1<< 2));
- else
- keyspan_pda_set_modem_info(serial, 0);
- }
+ if (on)
+ keyspan_pda_set_modem_info(serial, (1 << 7) | (1 << 2));
+ else
+ keyspan_pda_set_modem_info(serial, 0);
}
@@ -651,13 +647,8 @@ error:
}
static void keyspan_pda_close(struct usb_serial_port *port)
{
- struct usb_serial *serial = port->serial;
-
- if (serial->dev) {
- /* shutdown our bulk reads and writes */
- usb_kill_urb(port->write_urb);
- usb_kill_urb(port->interrupt_in_urb);
- }
+ usb_kill_urb(port->write_urb);
+ usb_kill_urb(port->interrupt_in_urb);
}
diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c
index 769d910ae0a..1b4054fe52a 100644
--- a/drivers/usb/serial/kl5kusb105.c
+++ b/drivers/usb/serial/kl5kusb105.c
@@ -341,28 +341,20 @@ static void klsi_105_close(struct usb_serial_port *port)
{
int rc;
- mutex_lock(&port->serial->disc_mutex);
- if (!port->serial->disconnected) {
- /* send READ_OFF */
- rc = usb_control_msg(port->serial->dev,
- usb_sndctrlpipe(port->serial->dev, 0),
- KL5KUSB105A_SIO_CONFIGURE,
- USB_TYPE_VENDOR | USB_DIR_OUT,
- KL5KUSB105A_SIO_CONFIGURE_READ_OFF,
- 0, /* index */
- NULL, 0,
- KLSI_TIMEOUT);
- if (rc < 0)
- dev_err(&port->dev,
- "Disabling read failed (error = %d)\n", rc);
- }
- mutex_unlock(&port->serial->disc_mutex);
+ /* send READ_OFF */
+ rc = usb_control_msg(port->serial->dev,
+ usb_sndctrlpipe(port->serial->dev, 0),
+ KL5KUSB105A_SIO_CONFIGURE,
+ USB_TYPE_VENDOR | USB_DIR_OUT,
+ KL5KUSB105A_SIO_CONFIGURE_READ_OFF,
+ 0, /* index */
+ NULL, 0,
+ KLSI_TIMEOUT);
+ if (rc < 0)
+ dev_err(&port->dev, "failed to disable read: %d\n", rc);
/* shutdown our bulk reads and writes */
usb_serial_generic_close(port);
-
- /* wgg - do I need this? I think so. */
- usb_kill_urb(port->interrupt_in_urb);
}
/* We need to write a complete 64-byte data block and encode the
diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c
index 903d938e174..78b48c31abf 100644
--- a/drivers/usb/serial/kobil_sct.c
+++ b/drivers/usb/serial/kobil_sct.c
@@ -65,7 +65,7 @@ static int kobil_tiocmget(struct tty_struct *tty);
static int kobil_tiocmset(struct tty_struct *tty,
unsigned int set, unsigned int clear);
static void kobil_read_int_callback(struct urb *urb);
-static void kobil_write_callback(struct urb *purb);
+static void kobil_write_int_callback(struct urb *urb);
static void kobil_set_termios(struct tty_struct *tty,
struct usb_serial_port *port, struct ktermios *old);
static void kobil_init_termios(struct tty_struct *tty);
@@ -99,6 +99,7 @@ static struct usb_serial_driver kobil_device = {
.write = kobil_write,
.write_room = kobil_write_room,
.read_int_callback = kobil_read_int_callback,
+ .write_int_callback = kobil_write_int_callback,
};
static struct usb_serial_driver * const serial_drivers[] = {
@@ -106,8 +107,6 @@ static struct usb_serial_driver * const serial_drivers[] = {
};
struct kobil_private {
- int write_int_endpoint_address;
- int read_int_endpoint_address;
unsigned char buf[KOBIL_BUF_LENGTH]; /* buffer for the APDU to send */
int filled; /* index of the last char in buf */
int cur_pos; /* index of the next char to send in buf */
@@ -117,14 +116,8 @@ struct kobil_private {
static int kobil_port_probe(struct usb_serial_port *port)
{
- int i;
struct usb_serial *serial = port->serial;
struct kobil_private *priv;
- struct usb_device *pdev;
- struct usb_host_config *actconfig;
- struct usb_interface *interface;
- struct usb_host_interface *altsetting;
- struct usb_host_endpoint *endpoint;
priv = kmalloc(sizeof(struct kobil_private), GFP_KERNEL);
if (!priv)
@@ -150,30 +143,6 @@ static int kobil_port_probe(struct usb_serial_port *port)
}
usb_set_serial_port_data(port, priv);
- /* search for the necessary endpoints */
- pdev = serial->dev;
- actconfig = pdev->actconfig;
- interface = actconfig->interface[0];
- altsetting = interface->cur_altsetting;
- endpoint = altsetting->endpoint;
-
- for (i = 0; i < altsetting->desc.bNumEndpoints; i++) {
- endpoint = &altsetting->endpoint[i];
- if (usb_endpoint_is_int_out(&endpoint->desc)) {
- dev_dbg(&serial->dev->dev,
- "%s Found interrupt out endpoint. Address: %d\n",
- __func__, endpoint->desc.bEndpointAddress);
- priv->write_int_endpoint_address =
- endpoint->desc.bEndpointAddress;
- }
- if (usb_endpoint_is_int_in(&endpoint->desc)) {
- dev_dbg(&serial->dev->dev,
- "%s Found interrupt in endpoint. Address: %d\n",
- __func__, endpoint->desc.bEndpointAddress);
- priv->read_int_endpoint_address =
- endpoint->desc.bEndpointAddress;
- }
- }
return 0;
}
@@ -205,7 +174,6 @@ static int kobil_open(struct tty_struct *tty, struct usb_serial_port *port)
struct kobil_private *priv;
unsigned char *transfer_buffer;
int transfer_buffer_length = 8;
- int write_urb_transfer_buffer_length = 8;
priv = usb_get_serial_port_data(port);
@@ -214,27 +182,6 @@ static int kobil_open(struct tty_struct *tty, struct usb_serial_port *port)
if (!transfer_buffer)
return -ENOMEM;
- /* allocate write_urb */
- if (!port->write_urb) {
- dev_dbg(dev, "%s - Allocating port->write_urb\n", __func__);
- port->write_urb = usb_alloc_urb(0, GFP_KERNEL);
- if (!port->write_urb) {
- dev_dbg(dev, "%s - usb_alloc_urb failed\n", __func__);
- kfree(transfer_buffer);
- return -ENOMEM;
- }
- }
-
- /* allocate memory for write_urb transfer buffer */
- port->write_urb->transfer_buffer =
- kmalloc(write_urb_transfer_buffer_length, GFP_KERNEL);
- if (!port->write_urb->transfer_buffer) {
- kfree(transfer_buffer);
- usb_free_urb(port->write_urb);
- port->write_urb = NULL;
- return -ENOMEM;
- }
-
/* get hardware version */
result = usb_control_msg(port->serial->dev,
usb_rcvctrlpipe(port->serial->dev, 0),
@@ -310,12 +257,7 @@ static int kobil_open(struct tty_struct *tty, struct usb_serial_port *port)
static void kobil_close(struct usb_serial_port *port)
{
/* FIXME: Add rts/dtr methods */
- if (port->write_urb) {
- usb_poison_urb(port->write_urb);
- kfree(port->write_urb->transfer_buffer);
- usb_free_urb(port->write_urb);
- port->write_urb = NULL;
- }
+ usb_kill_urb(port->interrupt_out_urb);
usb_kill_urb(port->interrupt_in_urb);
}
@@ -333,24 +275,8 @@ static void kobil_read_int_callback(struct urb *urb)
}
if (urb->actual_length) {
-
- /* BEGIN DEBUG */
- /*
- char *dbg_data;
-
- dbg_data = kzalloc((3 * purb->actual_length + 10)
- * sizeof(char), GFP_KERNEL);
- if (! dbg_data) {
- return;
- }
- for (i = 0; i < purb->actual_length; i++) {
- sprintf(dbg_data +3*i, "%02X ", data[i]);
- }
- dev_dbg(&port->dev, " <-- %s\n", dbg_data);
- kfree(dbg_data);
- */
- /* END DEBUG */
-
+ usb_serial_debug_data(&port->dev, __func__, urb->actual_length,
+ data);
tty_insert_flip_string(&port->port, data, urb->actual_length);
tty_flip_buffer_push(&port->port);
}
@@ -360,7 +286,7 @@ static void kobil_read_int_callback(struct urb *urb)
}
-static void kobil_write_callback(struct urb *purb)
+static void kobil_write_int_callback(struct urb *urb)
{
}
@@ -403,23 +329,14 @@ static int kobil_write(struct tty_struct *tty, struct usb_serial_port *port,
while (todo > 0) {
/* max 8 byte in one urb (endpoint size) */
- length = (todo < 8) ? todo : 8;
+ length = min(todo, port->interrupt_out_size);
/* copy data to transfer buffer */
- memcpy(port->write_urb->transfer_buffer,
+ memcpy(port->interrupt_out_buffer,
priv->buf + priv->cur_pos, length);
- usb_fill_int_urb(port->write_urb,
- port->serial->dev,
- usb_sndintpipe(port->serial->dev,
- priv->write_int_endpoint_address),
- port->write_urb->transfer_buffer,
- length,
- kobil_write_callback,
- port,
- 8
- );
+ port->interrupt_out_urb->transfer_buffer_length = length;
priv->cur_pos = priv->cur_pos + length;
- result = usb_submit_urb(port->write_urb, GFP_NOIO);
+ result = usb_submit_urb(port->interrupt_out_urb, GFP_NOIO);
dev_dbg(&port->dev, "%s - Send write URB returns: %i\n", __func__, result);
todo = priv->filled - priv->cur_pos;
diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c
index a64d420f687..6a15adf5336 100644
--- a/drivers/usb/serial/mct_u232.c
+++ b/drivers/usb/serial/mct_u232.c
@@ -35,7 +35,6 @@
#include <linux/usb.h>
#include <linux/usb/serial.h>
#include <linux/serial.h>
-#include <linux/ioctl.h>
#include "mct_u232.h"
#define DRIVER_AUTHOR "Wolfgang Grandegger <wolfgang@ces.ch>"
@@ -44,7 +43,6 @@
/*
* Function prototypes
*/
-static int mct_u232_startup(struct usb_serial *serial);
static int mct_u232_port_probe(struct usb_serial_port *port);
static int mct_u232_port_remove(struct usb_serial_port *remove);
static int mct_u232_open(struct tty_struct *tty, struct usb_serial_port *port);
@@ -57,10 +55,6 @@ static void mct_u232_break_ctl(struct tty_struct *tty, int break_state);
static int mct_u232_tiocmget(struct tty_struct *tty);
static int mct_u232_tiocmset(struct tty_struct *tty,
unsigned int set, unsigned int clear);
-static int mct_u232_ioctl(struct tty_struct *tty,
- unsigned int cmd, unsigned long arg);
-static int mct_u232_get_icount(struct tty_struct *tty,
- struct serial_icounter_struct *icount);
static void mct_u232_throttle(struct tty_struct *tty);
static void mct_u232_unthrottle(struct tty_struct *tty);
@@ -95,11 +89,10 @@ static struct usb_serial_driver mct_u232_device = {
.break_ctl = mct_u232_break_ctl,
.tiocmget = mct_u232_tiocmget,
.tiocmset = mct_u232_tiocmset,
- .attach = mct_u232_startup,
+ .tiocmiwait = usb_serial_generic_tiocmiwait,
.port_probe = mct_u232_port_probe,
.port_remove = mct_u232_port_remove,
- .ioctl = mct_u232_ioctl,
- .get_icount = mct_u232_get_icount,
+ .get_icount = usb_serial_generic_get_icount,
};
static struct usb_serial_driver * const serial_drivers[] = {
@@ -107,15 +100,13 @@ static struct usb_serial_driver * const serial_drivers[] = {
};
struct mct_u232_private {
+ struct urb *read_urb;
spinlock_t lock;
unsigned int control_state; /* Modem Line Setting (TIOCM) */
unsigned char last_lcr; /* Line Control Register */
unsigned char last_lsr; /* Line Status Register */
unsigned char last_msr; /* Modem Status Register */
unsigned int rx_flags; /* Throttling flags */
- struct async_icount icount;
- wait_queue_head_t msr_wait; /* for handling sleeping while waiting
- for msr change to happen */
};
#define THROTTLED 0x01
@@ -384,22 +375,6 @@ static void mct_u232_msr_to_state(struct usb_serial_port *port,
* Driver's tty interface functions
*/
-static int mct_u232_startup(struct usb_serial *serial)
-{
- struct usb_serial_port *port, *rport;
-
- /* Puh, that's dirty */
- port = serial->port[0];
- rport = serial->port[1];
- /* No unlinking, it wasn't submitted yet. */
- usb_free_urb(port->read_urb);
- port->read_urb = rport->interrupt_in_urb;
- rport->interrupt_in_urb = NULL;
- port->read_urb->context = port;
-
- return 0;
-} /* mct_u232_startup */
-
static int mct_u232_port_probe(struct usb_serial_port *port)
{
struct mct_u232_private *priv;
@@ -408,8 +383,11 @@ static int mct_u232_port_probe(struct usb_serial_port *port)
if (!priv)
return -ENOMEM;
+ /* Use second interrupt-in endpoint for reading. */
+ priv->read_urb = port->serial->port[1]->interrupt_in_urb;
+ priv->read_urb->context = port;
+
spin_lock_init(&priv->lock);
- init_waitqueue_head(&priv->msr_wait);
usb_set_serial_port_data(port, priv);
@@ -472,17 +450,17 @@ static int mct_u232_open(struct tty_struct *tty, struct usb_serial_port *port)
mct_u232_msr_to_state(port, &priv->control_state, priv->last_msr);
spin_unlock_irqrestore(&priv->lock, flags);
- retval = usb_submit_urb(port->read_urb, GFP_KERNEL);
+ retval = usb_submit_urb(priv->read_urb, GFP_KERNEL);
if (retval) {
dev_err(&port->dev,
- "usb_submit_urb(read bulk) failed pipe 0x%x err %d\n",
+ "usb_submit_urb(read) failed pipe 0x%x err %d\n",
port->read_urb->pipe, retval);
goto error;
}
retval = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
if (retval) {
- usb_kill_urb(port->read_urb);
+ usb_kill_urb(priv->read_urb);
dev_err(&port->dev,
"usb_submit_urb(read int) failed pipe 0x%x err %d",
port->interrupt_in_urb->pipe, retval);
@@ -512,11 +490,9 @@ static void mct_u232_dtr_rts(struct usb_serial_port *port, int on)
static void mct_u232_close(struct usb_serial_port *port)
{
- /*
- * Must kill the read urb as it is actually an interrupt urb, which
- * generic close thus fails to kill.
- */
- usb_kill_urb(port->read_urb);
+ struct mct_u232_private *priv = usb_get_serial_port_data(port);
+
+ usb_kill_urb(priv->read_urb);
usb_kill_urb(port->interrupt_in_urb);
usb_serial_generic_close(port);
@@ -573,7 +549,7 @@ static void mct_u232_read_int_callback(struct urb *urb)
/* Record Control Line states */
mct_u232_msr_to_state(port, &priv->control_state, priv->last_msr);
- mct_u232_msr_to_icount(&priv->icount, priv->last_msr);
+ mct_u232_msr_to_icount(&port->icount, priv->last_msr);
#if 0
/* Not yet handled. See belkin_sa.c for further information */
@@ -601,7 +577,7 @@ static void mct_u232_read_int_callback(struct urb *urb)
tty_kref_put(tty);
}
#endif
- wake_up_interruptible(&priv->msr_wait);
+ wake_up_interruptible(&port->port.delta_msr_wait);
spin_unlock_irqrestore(&priv->lock, flags);
exit:
retval = usb_submit_urb(urb, GFP_ATOMIC);
@@ -789,82 +765,6 @@ static void mct_u232_unthrottle(struct tty_struct *tty)
}
}
-static int mct_u232_ioctl(struct tty_struct *tty,
- unsigned int cmd, unsigned long arg)
-{
- DEFINE_WAIT(wait);
- struct usb_serial_port *port = tty->driver_data;
- struct mct_u232_private *mct_u232_port = usb_get_serial_port_data(port);
- struct async_icount cnow, cprev;
- unsigned long flags;
-
- dev_dbg(&port->dev, "%s - cmd = 0x%x\n", __func__, cmd);
-
- switch (cmd) {
-
- case TIOCMIWAIT:
-
- dev_dbg(&port->dev, "%s TIOCMIWAIT", __func__);
-
- spin_lock_irqsave(&mct_u232_port->lock, flags);
- cprev = mct_u232_port->icount;
- spin_unlock_irqrestore(&mct_u232_port->lock, flags);
- for ( ; ; ) {
- prepare_to_wait(&mct_u232_port->msr_wait,
- &wait, TASK_INTERRUPTIBLE);
- schedule();
- finish_wait(&mct_u232_port->msr_wait, &wait);
- /* see if a signal did it */
- if (signal_pending(current))
- return -ERESTARTSYS;
- spin_lock_irqsave(&mct_u232_port->lock, flags);
- cnow = mct_u232_port->icount;
- spin_unlock_irqrestore(&mct_u232_port->lock, flags);
- if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
- cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
- return -EIO; /* no change => error */
- if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
- ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
- ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) ||
- ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) {
- return 0;
- }
- cprev = cnow;
- }
-
- }
- return -ENOIOCTLCMD;
-}
-
-static int mct_u232_get_icount(struct tty_struct *tty,
- struct serial_icounter_struct *icount)
-{
- struct usb_serial_port *port = tty->driver_data;
- struct mct_u232_private *mct_u232_port = usb_get_serial_port_data(port);
- struct async_icount *ic = &mct_u232_port->icount;
- unsigned long flags;
-
- spin_lock_irqsave(&mct_u232_port->lock, flags);
-
- icount->cts = ic->cts;
- icount->dsr = ic->dsr;
- icount->rng = ic->rng;
- icount->dcd = ic->dcd;
- icount->rx = ic->rx;
- icount->tx = ic->tx;
- icount->frame = ic->frame;
- icount->overrun = ic->overrun;
- icount->parity = ic->parity;
- icount->brk = ic->brk;
- icount->buf_overrun = ic->buf_overrun;
-
- spin_unlock_irqrestore(&mct_u232_port->lock, flags);
-
- dev_dbg(&port->dev, "%s TIOCGICOUNT RX=%d, TX=%d\n",
- __func__, icount->rx, icount->tx);
- return 0;
-}
-
module_usb_serial_driver(serial_drivers, id_table);
MODULE_AUTHOR(DRIVER_AUTHOR);
diff --git a/drivers/usb/serial/metro-usb.c b/drivers/usb/serial/metro-usb.c
index bf3c7a23553..47e247759eb 100644
--- a/drivers/usb/serial/metro-usb.c
+++ b/drivers/usb/serial/metro-usb.c
@@ -177,10 +177,7 @@ static void metrousb_cleanup(struct usb_serial_port *port)
usb_unlink_urb(port->interrupt_in_urb);
usb_kill_urb(port->interrupt_in_urb);
- mutex_lock(&port->serial->disc_mutex);
- if (!port->serial->disconnected)
- metrousb_send_unidirectional_cmd(UNI_CMD_CLOSE, port);
- mutex_unlock(&port->serial->disc_mutex);
+ metrousb_send_unidirectional_cmd(UNI_CMD_CLOSE, port);
}
static int metrousb_open(struct tty_struct *tty, struct usb_serial_port *port)
diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c
index e0ebec3b5d6..cc0e54345df 100644
--- a/drivers/usb/serial/mos7720.c
+++ b/drivers/usb/serial/mos7720.c
@@ -62,7 +62,6 @@ struct moschip_port {
__u8 shadowMCR; /* last MCR value received */
__u8 shadowMSR; /* last MSR value received */
char open;
- struct async_icount icount;
struct usb_serial_port *port; /* loop back to the owner */
struct urb *write_urb_pool[NUM_URBS];
};
@@ -932,7 +931,6 @@ static void mos7720_bulk_in_callback(struct urb *urb)
static void mos7720_bulk_out_data_callback(struct urb *urb)
{
struct moschip_port *mos7720_port;
- struct tty_struct *tty;
int status = urb->status;
if (status) {
@@ -946,11 +944,8 @@ static void mos7720_bulk_out_data_callback(struct urb *urb)
return ;
}
- tty = tty_port_tty_get(&mos7720_port->port->port);
-
- if (tty && mos7720_port->open)
- tty_wakeup(tty);
- tty_kref_put(tty);
+ if (mos7720_port->open)
+ tty_port_tty_wakeup(&mos7720_port->port->port);
}
/*
@@ -1075,9 +1070,6 @@ static int mos7720_open(struct tty_struct *tty, struct usb_serial_port *port)
dev_err(&port->dev, "%s - Error %d submitting read urb\n",
__func__, response);
- /* initialize our icount structure */
- memset(&(mos7720_port->icount), 0x00, sizeof(mos7720_port->icount));
-
/* initialize our port settings */
mos7720_port->shadowMCR = UART_MCR_OUT2; /* Must set to enable ints! */
@@ -1144,16 +1136,9 @@ static void mos7720_close(struct usb_serial_port *port)
usb_kill_urb(port->write_urb);
usb_kill_urb(port->read_urb);
- mutex_lock(&serial->disc_mutex);
- /* these commands must not be issued if the device has
- * been disconnected */
- if (!serial->disconnected) {
- write_mos_reg(serial, port->number - port->serial->minor,
- MCR, 0x00);
- write_mos_reg(serial, port->number - port->serial->minor,
- IER, 0x00);
- }
- mutex_unlock(&serial->disc_mutex);
+ write_mos_reg(serial, port->number - port->serial->minor, MCR, 0x00);
+ write_mos_reg(serial, port->number - port->serial->minor, IER, 0x00);
+
mos7720_port->open = 0;
}
@@ -1803,33 +1788,6 @@ static int mos7720_tiocmset(struct tty_struct *tty,
return 0;
}
-static int mos7720_get_icount(struct tty_struct *tty,
- struct serial_icounter_struct *icount)
-{
- struct usb_serial_port *port = tty->driver_data;
- struct moschip_port *mos7720_port;
- struct async_icount cnow;
-
- mos7720_port = usb_get_serial_port_data(port);
- cnow = mos7720_port->icount;
-
- icount->cts = cnow.cts;
- icount->dsr = cnow.dsr;
- icount->rng = cnow.rng;
- icount->dcd = cnow.dcd;
- icount->rx = cnow.rx;
- icount->tx = cnow.tx;
- icount->frame = cnow.frame;
- icount->overrun = cnow.overrun;
- icount->parity = cnow.parity;
- icount->brk = cnow.brk;
- icount->buf_overrun = cnow.buf_overrun;
-
- dev_dbg(&port->dev, "%s TIOCGICOUNT RX=%d, TX=%d\n", __func__,
- icount->rx, icount->tx);
- return 0;
-}
-
static int set_modem_info(struct moschip_port *mos7720_port, unsigned int cmd,
unsigned int __user *value)
{
@@ -1905,8 +1863,6 @@ static int mos7720_ioctl(struct tty_struct *tty,
{
struct usb_serial_port *port = tty->driver_data;
struct moschip_port *mos7720_port;
- struct async_icount cnow;
- struct async_icount cprev;
mos7720_port = usb_get_serial_port_data(port);
if (mos7720_port == NULL)
@@ -1931,27 +1887,6 @@ static int mos7720_ioctl(struct tty_struct *tty,
dev_dbg(&port->dev, "%s TIOCGSERIAL\n", __func__);
return get_serial_info(mos7720_port,
(struct serial_struct __user *)arg);
-
- case TIOCMIWAIT:
- dev_dbg(&port->dev, "%s TIOCMIWAIT\n", __func__);
- cprev = mos7720_port->icount;
- while (1) {
- if (signal_pending(current))
- return -ERESTARTSYS;
- cnow = mos7720_port->icount;
- if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
- cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
- return -EIO; /* no change => error */
- if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
- ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
- ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) ||
- ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) {
- return 0;
- }
- cprev = cnow;
- }
- /* NOTREACHED */
- break;
}
return -ENOIOCTLCMD;
@@ -2107,7 +2042,6 @@ static struct usb_serial_driver moschip7720_2port_driver = {
.ioctl = mos7720_ioctl,
.tiocmget = mos7720_tiocmget,
.tiocmset = mos7720_tiocmset,
- .get_icount = mos7720_get_icount,
.set_termios = mos7720_set_termios,
.write = mos7720_write,
.write_room = mos7720_write_room,
diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c
index 809fb329eca..a0d5ea54598 100644
--- a/drivers/usb/serial/mos7840.c
+++ b/drivers/usb/serial/mos7840.c
@@ -219,9 +219,6 @@ struct moschip_port {
char open;
char open_ports;
wait_queue_head_t wait_chase; /* for handling sleeping while waiting for chase to finish */
- wait_queue_head_t delta_msr_wait; /* for handling sleeping while waiting for msr change to happen */
- int delta_msr_cond;
- struct async_icount icount;
struct usb_serial_port *port; /* loop back to the owner of this object */
/* Offsets */
@@ -400,29 +397,22 @@ static void mos7840_handle_new_msr(struct moschip_port *port, __u8 new_msr)
struct moschip_port *mos7840_port;
struct async_icount *icount;
mos7840_port = port;
- icount = &mos7840_port->icount;
if (new_msr &
(MOS_MSR_DELTA_CTS | MOS_MSR_DELTA_DSR | MOS_MSR_DELTA_RI |
MOS_MSR_DELTA_CD)) {
- icount = &mos7840_port->icount;
+ icount = &mos7840_port->port->icount;
/* update input line counters */
- if (new_msr & MOS_MSR_DELTA_CTS) {
+ if (new_msr & MOS_MSR_DELTA_CTS)
icount->cts++;
- smp_wmb();
- }
- if (new_msr & MOS_MSR_DELTA_DSR) {
+ if (new_msr & MOS_MSR_DELTA_DSR)
icount->dsr++;
- smp_wmb();
- }
- if (new_msr & MOS_MSR_DELTA_CD) {
+ if (new_msr & MOS_MSR_DELTA_CD)
icount->dcd++;
- smp_wmb();
- }
- if (new_msr & MOS_MSR_DELTA_RI) {
+ if (new_msr & MOS_MSR_DELTA_RI)
icount->rng++;
- smp_wmb();
- }
+
+ wake_up_interruptible(&port->port->port.delta_msr_wait);
}
}
@@ -440,23 +430,15 @@ static void mos7840_handle_new_lsr(struct moschip_port *port, __u8 new_lsr)
}
/* update input line counters */
- icount = &port->icount;
- if (new_lsr & SERIAL_LSR_BI) {
+ icount = &port->port->icount;
+ if (new_lsr & SERIAL_LSR_BI)
icount->brk++;
- smp_wmb();
- }
- if (new_lsr & SERIAL_LSR_OE) {
+ if (new_lsr & SERIAL_LSR_OE)
icount->overrun++;
- smp_wmb();
- }
- if (new_lsr & SERIAL_LSR_PE) {
+ if (new_lsr & SERIAL_LSR_PE)
icount->parity++;
- smp_wmb();
- }
- if (new_lsr & SERIAL_LSR_FE) {
+ if (new_lsr & SERIAL_LSR_FE)
icount->frame++;
- smp_wmb();
- }
}
/************************************************************************/
@@ -775,9 +757,8 @@ static void mos7840_bulk_in_callback(struct urb *urb)
struct tty_port *tport = &mos7840_port->port->port;
tty_insert_flip_string(tport, data, urb->actual_length);
tty_flip_buffer_push(tport);
- mos7840_port->icount.rx += urb->actual_length;
- smp_wmb();
- dev_dbg(&port->dev, "mos7840_port->icount.rx is %d:\n", mos7840_port->icount.rx);
+ port->icount.rx += urb->actual_length;
+ dev_dbg(&port->dev, "icount.rx is %d:\n", port->icount.rx);
}
if (!mos7840_port->read_urb) {
@@ -814,7 +795,6 @@ static void mos7840_bulk_out_data_callback(struct urb *urb)
{
struct moschip_port *mos7840_port;
struct usb_serial_port *port;
- struct tty_struct *tty;
int status = urb->status;
int i;
@@ -837,10 +817,8 @@ static void mos7840_bulk_out_data_callback(struct urb *urb)
if (mos7840_port_paranoia_check(port, __func__))
return;
- tty = tty_port_tty_get(&port->port);
- if (tty && mos7840_port->open)
- tty_wakeup(tty);
- tty_kref_put(tty);
+ if (mos7840_port->open)
+ tty_port_tty_wakeup(&port->port);
}
@@ -1127,10 +1105,6 @@ static int mos7840_open(struct tty_struct *tty, struct usb_serial_port *port)
/* initialize our wait queues */
init_waitqueue_head(&mos7840_port->wait_chase);
- init_waitqueue_head(&mos7840_port->delta_msr_wait);
-
- /* initialize our icount structure */
- memset(&(mos7840_port->icount), 0x00, sizeof(mos7840_port->icount));
/* initialize our port settings */
/* Must set to enable ints! */
@@ -1138,8 +1112,6 @@ static int mos7840_open(struct tty_struct *tty, struct usb_serial_port *port)
/* send a open port command */
mos7840_port->open = 1;
/* mos7840_change_port_settings(mos7840_port,old_termios); */
- mos7840_port->icount.tx = 0;
- mos7840_port->icount.rx = 0;
return 0;
}
@@ -1222,25 +1194,10 @@ static void mos7840_close(struct usb_serial_port *port)
}
}
- /* While closing port, shutdown all bulk read, write *
- * and interrupt read if they exists */
- if (serial->dev) {
- if (mos7840_port->write_urb) {
- dev_dbg(&port->dev, "%s", "Shutdown bulk write\n");
- usb_kill_urb(mos7840_port->write_urb);
- }
- if (mos7840_port->read_urb) {
- dev_dbg(&port->dev, "%s", "Shutdown bulk read\n");
- usb_kill_urb(mos7840_port->read_urb);
- mos7840_port->read_urb_busy = false;
- }
- if ((&mos7840_port->control_urb)) {
- dev_dbg(&port->dev, "%s", "Shutdown control read\n");
- /*/ usb_kill_urb (mos7840_port->control_urb); */
- }
- }
-/* if(mos7840_port->ctrl_buf != NULL) */
-/* kfree(mos7840_port->ctrl_buf); */
+ usb_kill_urb(mos7840_port->write_urb);
+ usb_kill_urb(mos7840_port->read_urb);
+ mos7840_port->read_urb_busy = false;
+
port0->open_ports--;
dev_dbg(&port->dev, "%s in close%d:in port%d\n", __func__, port0->open_ports, port->number);
if (port0->open_ports == 0) {
@@ -1252,8 +1209,7 @@ static void mos7840_close(struct usb_serial_port *port)
if (mos7840_port->write_urb) {
/* if this urb had a transfer buffer already (old tx) free it */
- if (mos7840_port->write_urb->transfer_buffer != NULL)
- kfree(mos7840_port->write_urb->transfer_buffer);
+ kfree(mos7840_port->write_urb->transfer_buffer);
usb_free_urb(mos7840_port->write_urb);
}
@@ -1330,9 +1286,8 @@ static void mos7840_break(struct tty_struct *tty, int break_state)
if (mos7840_port == NULL)
return;
- if (serial->dev)
- /* flush and block until tx is empty */
- mos7840_block_until_chase_response(tty, mos7840_port);
+ /* flush and block until tx is empty */
+ mos7840_block_until_chase_response(tty, mos7840_port);
if (break_state == -1)
data = mos7840_port->shadowLCR | LCR_SET_BREAK;
@@ -1522,9 +1477,8 @@ static int mos7840_write(struct tty_struct *tty, struct usb_serial_port *port,
goto exit;
}
bytes_sent = transfer_size;
- mos7840_port->icount.tx += transfer_size;
- smp_wmb();
- dev_dbg(&port->dev, "mos7840_port->icount.tx is %d:\n", mos7840_port->icount.tx);
+ port->icount.tx += transfer_size;
+ dev_dbg(&port->dev, "icount.tx is %d:\n", port->icount.tx);
exit:
return bytes_sent;
@@ -2017,8 +1971,6 @@ static void mos7840_change_port_settings(struct tty_struct *tty,
mos7840_port->read_urb_busy = false;
}
}
- wake_up(&mos7840_port->delta_msr_wait);
- mos7840_port->delta_msr_cond = 1;
dev_dbg(&port->dev, "%s - mos7840_port->shadowLCR is End %x\n", __func__,
mos7840_port->shadowLCR);
}
@@ -2145,34 +2097,6 @@ static int mos7840_get_serial_info(struct moschip_port *mos7840_port,
return 0;
}
-static int mos7840_get_icount(struct tty_struct *tty,
- struct serial_icounter_struct *icount)
-{
- struct usb_serial_port *port = tty->driver_data;
- struct moschip_port *mos7840_port;
- struct async_icount cnow;
-
- mos7840_port = mos7840_get_port_private(port);
- cnow = mos7840_port->icount;
-
- smp_rmb();
- icount->cts = cnow.cts;
- icount->dsr = cnow.dsr;
- icount->rng = cnow.rng;
- icount->dcd = cnow.dcd;
- icount->rx = cnow.rx;
- icount->tx = cnow.tx;
- icount->frame = cnow.frame;
- icount->overrun = cnow.overrun;
- icount->parity = cnow.parity;
- icount->brk = cnow.brk;
- icount->buf_overrun = cnow.buf_overrun;
-
- dev_dbg(&port->dev, "%s TIOCGICOUNT RX=%d, TX=%d\n", __func__,
- icount->rx, icount->tx);
- return 0;
-}
-
/*****************************************************************************
* SerialIoctl
* this function handles any ioctl calls to the driver
@@ -2185,9 +2109,6 @@ static int mos7840_ioctl(struct tty_struct *tty,
void __user *argp = (void __user *)arg;
struct moschip_port *mos7840_port;
- struct async_icount cnow;
- struct async_icount cprev;
-
if (mos7840_port_paranoia_check(port, __func__))
return -1;
@@ -2212,36 +2133,6 @@ static int mos7840_ioctl(struct tty_struct *tty,
case TIOCSSERIAL:
dev_dbg(&port->dev, "%s TIOCSSERIAL\n", __func__);
break;
-
- case TIOCMIWAIT:
- dev_dbg(&port->dev, "%s TIOCMIWAIT\n", __func__);
- cprev = mos7840_port->icount;
- while (1) {
- /* interruptible_sleep_on(&mos7840_port->delta_msr_wait); */
- mos7840_port->delta_msr_cond = 0;
- wait_event_interruptible(mos7840_port->delta_msr_wait,
- (mos7840_port->
- delta_msr_cond == 1));
-
- /* see if a signal did it */
- if (signal_pending(current))
- return -ERESTARTSYS;
- cnow = mos7840_port->icount;
- smp_rmb();
- if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
- cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
- return -EIO; /* no change => error */
- if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
- ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
- ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) ||
- ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) {
- return 0;
- }
- cprev = cnow;
- }
- /* NOTREACHED */
- break;
-
default:
break;
}
@@ -2588,7 +2479,8 @@ static struct usb_serial_driver moschip7840_4port_device = {
.break_ctl = mos7840_break,
.tiocmget = mos7840_tiocmget,
.tiocmset = mos7840_tiocmset,
- .get_icount = mos7840_get_icount,
+ .tiocmiwait = usb_serial_generic_tiocmiwait,
+ .get_icount = usb_serial_generic_get_icount,
.port_probe = mos7840_port_probe,
.port_remove = mos7840_port_remove,
.read_bulk_callback = mos7840_bulk_in_callback,
diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c
index 1e1cafe287e..5739bf6f720 100644
--- a/drivers/usb/serial/omninet.c
+++ b/drivers/usb/serial/omninet.c
@@ -33,8 +33,7 @@
/* function prototypes */
static int omninet_open(struct tty_struct *tty, struct usb_serial_port *port);
-static void omninet_close(struct usb_serial_port *port);
-static void omninet_read_bulk_callback(struct urb *urb);
+static void omninet_process_read_urb(struct urb *urb);
static void omninet_write_bulk_callback(struct urb *urb);
static int omninet_write(struct tty_struct *tty, struct usb_serial_port *port,
const unsigned char *buf, int count);
@@ -61,11 +60,10 @@ static struct usb_serial_driver zyxel_omninet_device = {
.port_probe = omninet_port_probe,
.port_remove = omninet_port_remove,
.open = omninet_open,
- .close = omninet_close,
.write = omninet_write,
.write_room = omninet_write_room,
- .read_bulk_callback = omninet_read_bulk_callback,
.write_bulk_callback = omninet_write_bulk_callback,
+ .process_read_urb = omninet_process_read_urb,
.disconnect = omninet_disconnect,
};
@@ -74,29 +72,28 @@ static struct usb_serial_driver * const serial_drivers[] = {
};
-/* The protocol.
+/*
+ * The protocol.
*
* The omni.net always exchange 64 bytes of data with the host. The first
- * four bytes are the control header, you can see it in the above structure.
+ * four bytes are the control header.
*
* oh_seq is a sequence number. Don't know if/how it's used.
* oh_len is the length of the data bytes in the packet.
* oh_xxx Bit-mapped, related to handshaking and status info.
- * I normally set it to 0x03 in trasmitted frames.
+ * I normally set it to 0x03 in transmitted frames.
* 7: Active when the TA is in a CONNECTed state.
* 6: unknown
* 5: handshaking, unknown
* 4: handshaking, unknown
* 3: unknown, usually 0
* 2: unknown, usually 0
- * 1: handshaking, unknown, usually set to 1 in trasmitted frames
- * 0: handshaking, unknown, usually set to 1 in trasmitted frames
+ * 1: handshaking, unknown, usually set to 1 in transmitted frames
+ * 0: handshaking, unknown, usually set to 1 in transmitted frames
* oh_pad Probably a pad byte.
*
* After the header you will find data bytes if oh_len was greater than zero.
- *
*/
-
struct omninet_header {
__u8 oh_seq;
__u8 oh_len;
@@ -112,7 +109,7 @@ static int omninet_port_probe(struct usb_serial_port *port)
{
struct omninet_data *od;
- od = kmalloc(sizeof(struct omninet_data), GFP_KERNEL);
+ od = kzalloc(sizeof(*od), GFP_KERNEL);
if (!od)
return -ENOMEM;
@@ -135,56 +132,32 @@ static int omninet_open(struct tty_struct *tty, struct usb_serial_port *port)
{
struct usb_serial *serial = port->serial;
struct usb_serial_port *wport;
- int result = 0;
wport = serial->port[1];
tty_port_tty_set(&wport->port, tty);
- /* Start reading from the device */
- result = usb_submit_urb(port->read_urb, GFP_KERNEL);
- if (result)
- dev_err(&port->dev,
- "%s - failed submitting read urb, error %d\n",
- __func__, result);
- return result;
-}
-
-static void omninet_close(struct usb_serial_port *port)
-{
- usb_kill_urb(port->read_urb);
+ return usb_serial_generic_open(tty, port);
}
+#define OMNINET_HEADERLEN 4
+#define OMNINET_BULKOUTSIZE 64
+#define OMNINET_PAYLOADSIZE (OMNINET_BULKOUTSIZE - OMNINET_HEADERLEN)
-#define OMNINET_DATAOFFSET 0x04
-#define OMNINET_HEADERLEN sizeof(struct omninet_header)
-#define OMNINET_BULKOUTSIZE (64 - OMNINET_HEADERLEN)
-
-static void omninet_read_bulk_callback(struct urb *urb)
+static void omninet_process_read_urb(struct urb *urb)
{
- struct usb_serial_port *port = urb->context;
- unsigned char *data = urb->transfer_buffer;
- struct omninet_header *header = (struct omninet_header *) &data[0];
- int status = urb->status;
- int result;
+ struct usb_serial_port *port = urb->context;
+ const struct omninet_header *hdr = urb->transfer_buffer;
+ const unsigned char *data;
+ size_t data_len;
- if (status) {
- dev_dbg(&port->dev, "%s - nonzero read bulk status received: %d\n",
- __func__, status);
+ if (urb->actual_length <= OMNINET_HEADERLEN || !hdr->oh_len)
return;
- }
-
- if (urb->actual_length && header->oh_len) {
- tty_insert_flip_string(&port->port, data + OMNINET_DATAOFFSET,
- header->oh_len);
- tty_flip_buffer_push(&port->port);
- }
- /* Continue trying to always read */
- result = usb_submit_urb(urb, GFP_ATOMIC);
- if (result)
- dev_err(&port->dev,
- "%s - failed resubmitting read urb, error %d\n",
- __func__, result);
+ data = (char *)urb->transfer_buffer + OMNINET_HEADERLEN;
+ data_len = min_t(size_t, urb->actual_length - OMNINET_HEADERLEN,
+ hdr->oh_len);
+ tty_insert_flip_string(&port->port, data, data_len);
+ tty_flip_buffer_push(&port->port);
}
static int omninet_write(struct tty_struct *tty, struct usb_serial_port *port,
@@ -209,9 +182,9 @@ static int omninet_write(struct tty_struct *tty, struct usb_serial_port *port,
return 0;
}
- count = (count > OMNINET_BULKOUTSIZE) ? OMNINET_BULKOUTSIZE : count;
+ count = (count > OMNINET_PAYLOADSIZE) ? OMNINET_PAYLOADSIZE : count;
- memcpy(wport->write_urb->transfer_buffer + OMNINET_DATAOFFSET,
+ memcpy(wport->write_urb->transfer_buffer + OMNINET_HEADERLEN,
buf, count);
usb_serial_debug_data(&port->dev, __func__, count,
@@ -223,7 +196,7 @@ static int omninet_write(struct tty_struct *tty, struct usb_serial_port *port,
header->oh_pad = 0x00;
/* send the data out the bulk port, always 64 bytes */
- wport->write_urb->transfer_buffer_length = 64;
+ wport->write_urb->transfer_buffer_length = OMNINET_BULKOUTSIZE;
result = usb_submit_urb(wport->write_urb, GFP_ATOMIC);
if (result) {
diff --git a/drivers/usb/serial/opticon.c b/drivers/usb/serial/opticon.c
index e13e1a4d3e1..5f4b0cd0f6e 100644
--- a/drivers/usb/serial/opticon.c
+++ b/drivers/usb/serial/opticon.c
@@ -120,7 +120,10 @@ static int send_control_msg(struct usb_serial_port *port, u8 requesttype,
0, 0, buffer, 1, 0);
kfree(buffer);
- return retval;
+ if (retval < 0)
+ return retval;
+
+ return 0;
}
static int opticon_open(struct tty_struct *tty, struct usb_serial_port *port)
@@ -306,7 +309,6 @@ static int opticon_tiocmset(struct tty_struct *tty,
unsigned int set, unsigned int clear)
{
struct usb_serial_port *port = tty->driver_data;
- struct usb_serial *serial = port->serial;
struct opticon_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
bool rts;
@@ -327,15 +329,11 @@ static int opticon_tiocmset(struct tty_struct *tty,
if (!changed)
return 0;
- /* Send the new RTS state to the connected device */
- mutex_lock(&serial->disc_mutex);
- if (!serial->disconnected)
- ret = send_control_msg(port, CONTROL_RTS, !rts);
- else
- ret = -ENODEV;
- mutex_unlock(&serial->disc_mutex);
+ ret = send_control_msg(port, CONTROL_RTS, !rts);
+ if (ret)
+ return usb_translate_errors(ret);
- return ret;
+ return 0;
}
static int get_serial_info(struct usb_serial_port *port,
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index f7d339d8187..734372846ab 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -341,10 +341,13 @@ static void option_instat_callback(struct urb *urb);
#define CINTERION_PRODUCT_EU3_E 0x0051
#define CINTERION_PRODUCT_EU3_P 0x0052
#define CINTERION_PRODUCT_PH8 0x0053
+#define CINTERION_PRODUCT_AH6 0x0055
+#define CINTERION_PRODUCT_PLS8 0x0060
/* Olivetti products */
#define OLIVETTI_VENDOR_ID 0x0b3c
#define OLIVETTI_PRODUCT_OLICARD100 0xc000
+#define OLIVETTI_PRODUCT_OLICARD145 0xc003
/* Celot products */
#define CELOT_VENDOR_ID 0x211f
@@ -579,6 +582,7 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE(QUANTA_VENDOR_ID, 0xea42),
.driver_info = (kernel_ulong_t)&net_intf4_blacklist },
{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0x1c05, USB_CLASS_COMM, 0x02, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0x1c1f, USB_CLASS_COMM, 0x02, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0x1c23, USB_CLASS_COMM, 0x02, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E173, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t) &net_intf1_blacklist },
@@ -1260,6 +1264,8 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_EU3_E) },
{ USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_EU3_P) },
{ USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_PH8) },
+ { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_AH6) },
+ { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_PLS8) },
{ USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_HC28_MDM) },
{ USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_HC28_MDMNET) },
{ USB_DEVICE(SIEMENS_VENDOR_ID, CINTERION_PRODUCT_HC25_MDM) },
@@ -1268,6 +1274,7 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE(SIEMENS_VENDOR_ID, CINTERION_PRODUCT_HC28_MDMNET) },
{ USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD100) },
+ { USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD145) },
{ USB_DEVICE(CELOT_VENDOR_ID, CELOT_PRODUCT_CT680M) }, /* CT-650 CDMA 450 1xEVDO modem */
{ USB_DEVICE(ONDA_VENDOR_ID, ONDA_MT825UP) }, /* ONDA MT825UP modem */
{ USB_DEVICE_AND_INTERFACE_INFO(SAMSUNG_VENDOR_ID, SAMSUNG_PRODUCT_GT_B3730, USB_CLASS_CDC_DATA, 0x00, 0x00) }, /* Samsung GT-B3730 LTE USB modem.*/
@@ -1345,6 +1352,12 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE(TPLINK_VENDOR_ID, TPLINK_PRODUCT_MA180),
.driver_info = (kernel_ulong_t)&net_intf4_blacklist },
{ USB_DEVICE(CHANGHONG_VENDOR_ID, CHANGHONG_PRODUCT_CH690) },
+ { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d01, 0xff, 0x02, 0x01) }, /* D-Link DWM-156 (variant) */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d01, 0xff, 0x00, 0x00) }, /* D-Link DWM-156 (variant) */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d02, 0xff, 0x02, 0x01) },
+ { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d02, 0xff, 0x00, 0x00) },
+ { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d03, 0xff, 0x02, 0x01) },
+ { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d03, 0xff, 0x00, 0x00) },
{ } /* Terminating entry */
};
MODULE_DEVICE_TABLE(usb, option_ids);
@@ -1532,13 +1545,8 @@ static void option_instat_callback(struct urb *urb)
portdata->dsr_state = ((signals & 0x02) ? 1 : 0);
portdata->ri_state = ((signals & 0x08) ? 1 : 0);
- if (old_dcd_state && !portdata->dcd_state) {
- struct tty_struct *tty =
- tty_port_tty_get(&port->port);
- if (tty && !C_CLOCAL(tty))
- tty_hangup(tty);
- tty_kref_put(tty);
- }
+ if (old_dcd_state && !portdata->dcd_state)
+ tty_port_tty_hangup(&port->port, true);
} else {
dev_dbg(dev, "%s: type %x req %x\n", __func__,
req_pkt->bRequestType, req_pkt->bRequest);
diff --git a/drivers/usb/serial/oti6858.c b/drivers/usb/serial/oti6858.c
index a958fd41b5b..7e3e0782e51 100644
--- a/drivers/usb/serial/oti6858.c
+++ b/drivers/usb/serial/oti6858.c
@@ -124,8 +124,6 @@ static void oti6858_close(struct usb_serial_port *port);
static void oti6858_set_termios(struct tty_struct *tty,
struct usb_serial_port *port, struct ktermios *old);
static void oti6858_init_termios(struct tty_struct *tty);
-static int oti6858_ioctl(struct tty_struct *tty,
- unsigned int cmd, unsigned long arg);
static void oti6858_read_int_callback(struct urb *urb);
static void oti6858_read_bulk_callback(struct urb *urb);
static void oti6858_write_bulk_callback(struct urb *urb);
@@ -136,6 +134,7 @@ static int oti6858_chars_in_buffer(struct tty_struct *tty);
static int oti6858_tiocmget(struct tty_struct *tty);
static int oti6858_tiocmset(struct tty_struct *tty,
unsigned int set, unsigned int clear);
+static int oti6858_tiocmiwait(struct tty_struct *tty, unsigned long arg);
static int oti6858_port_probe(struct usb_serial_port *port);
static int oti6858_port_remove(struct usb_serial_port *port);
@@ -150,11 +149,11 @@ static struct usb_serial_driver oti6858_device = {
.open = oti6858_open,
.close = oti6858_close,
.write = oti6858_write,
- .ioctl = oti6858_ioctl,
.set_termios = oti6858_set_termios,
.init_termios = oti6858_init_termios,
.tiocmget = oti6858_tiocmget,
.tiocmset = oti6858_tiocmset,
+ .tiocmiwait = oti6858_tiocmiwait,
.read_bulk_callback = oti6858_read_bulk_callback,
.read_int_callback = oti6858_read_int_callback,
.write_bulk_callback = oti6858_write_bulk_callback,
@@ -188,7 +187,6 @@ struct oti6858_private {
u8 setup_done;
struct delayed_work delayed_setup_work;
- wait_queue_head_t intr_wait;
struct usb_serial_port *port; /* USB port with which associated */
};
@@ -339,7 +337,6 @@ static int oti6858_port_probe(struct usb_serial_port *port)
return -ENOMEM;
spin_lock_init(&priv->lock);
- init_waitqueue_head(&priv->intr_wait);
priv->port = port;
INIT_DELAYED_WORK(&priv->delayed_setup_work, setup_line);
INIT_DELAYED_WORK(&priv->delayed_write_work, send_data);
@@ -652,8 +649,9 @@ static int oti6858_tiocmget(struct tty_struct *tty)
return result;
}
-static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
+static int oti6858_tiocmiwait(struct tty_struct *tty, unsigned long arg)
{
+ struct usb_serial_port *port = tty->driver_data;
struct oti6858_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
unsigned int prev, status;
@@ -664,11 +662,15 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
spin_unlock_irqrestore(&priv->lock, flags);
while (1) {
- wait_event_interruptible(priv->intr_wait,
+ wait_event_interruptible(port->port.delta_msr_wait,
+ port->serial->disconnected ||
priv->status.pin_state != prev);
if (signal_pending(current))
return -ERESTARTSYS;
+ if (port->serial->disconnected)
+ return -EIO;
+
spin_lock_irqsave(&priv->lock, flags);
status = priv->status.pin_state & PIN_MASK;
spin_unlock_irqrestore(&priv->lock, flags);
@@ -687,24 +689,6 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
return 0;
}
-static int oti6858_ioctl(struct tty_struct *tty,
- unsigned int cmd, unsigned long arg)
-{
- struct usb_serial_port *port = tty->driver_data;
-
- dev_dbg(&port->dev, "%s(cmd = 0x%04x, arg = 0x%08lx)\n", __func__, cmd, arg);
-
- switch (cmd) {
- case TIOCMIWAIT:
- dev_dbg(&port->dev, "%s(): TIOCMIWAIT\n", __func__);
- return wait_modem_info(port, arg);
- default:
- dev_dbg(&port->dev, "%s(): 0x%04x not supported\n", __func__, cmd);
- break;
- }
- return -ENOIOCTLCMD;
-}
-
static void oti6858_read_int_callback(struct urb *urb)
{
struct usb_serial_port *port = urb->context;
@@ -763,7 +747,7 @@ static void oti6858_read_int_callback(struct urb *urb)
if (!priv->transient) {
if (xs->pin_state != priv->status.pin_state)
- wake_up_interruptible(&priv->intr_wait);
+ wake_up_interruptible(&port->port.delta_msr_wait);
memcpy(&priv->status, xs, OTI6858_CTRL_PKT_SIZE);
}
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index 54adc9125e5..7151659367a 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -139,7 +139,6 @@ struct pl2303_serial_private {
struct pl2303_private {
spinlock_t lock;
- wait_queue_head_t delta_msr_wait;
u8 line_control;
u8 line_status;
};
@@ -150,7 +149,7 @@ static int pl2303_vendor_read(__u16 value, __u16 index,
int res = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
VENDOR_READ_REQUEST, VENDOR_READ_REQUEST_TYPE,
value, index, buf, 1, 100);
- dev_dbg(&serial->dev->dev, "0x%x:0x%x:0x%x:0x%x %d - %x\n",
+ dev_dbg(&serial->interface->dev, "0x%x:0x%x:0x%x:0x%x %d - %x\n",
VENDOR_READ_REQUEST_TYPE, VENDOR_READ_REQUEST, value, index,
res, buf[0]);
return res;
@@ -162,7 +161,7 @@ static int pl2303_vendor_write(__u16 value, __u16 index,
int res = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
VENDOR_WRITE_REQUEST, VENDOR_WRITE_REQUEST_TYPE,
value, index, NULL, 0, 100);
- dev_dbg(&serial->dev->dev, "0x%x:0x%x:0x%x:0x%x %d\n",
+ dev_dbg(&serial->interface->dev, "0x%x:0x%x:0x%x:0x%x %d\n",
VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, value, index,
res);
return res;
@@ -233,7 +232,6 @@ static int pl2303_port_probe(struct usb_serial_port *port)
return -ENOMEM;
spin_lock_init(&priv->lock);
- init_waitqueue_head(&priv->delta_msr_wait);
usb_set_serial_port_data(port, priv);
@@ -250,14 +248,15 @@ static int pl2303_port_remove(struct usb_serial_port *port)
return 0;
}
-static int set_control_lines(struct usb_device *dev, u8 value)
+static int pl2303_set_control_lines(struct usb_serial_port *port, u8 value)
{
+ struct usb_device *dev = port->serial->dev;
int retval;
retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
SET_CONTROL_REQUEST, SET_CONTROL_REQUEST_TYPE,
value, 0, NULL, 0, 100);
- dev_dbg(&dev->dev, "%s - value = %d, retval = %d\n", __func__,
+ dev_dbg(&port->dev, "%s - value = %d, retval = %d\n", __func__,
value, retval);
return retval;
}
@@ -439,7 +438,7 @@ static void pl2303_set_termios(struct tty_struct *tty,
if (control != priv->line_control) {
control = priv->line_control;
spin_unlock_irqrestore(&priv->lock, flags);
- set_control_lines(serial->dev, control);
+ pl2303_set_control_lines(port, control);
} else {
spin_unlock_irqrestore(&priv->lock, flags);
}
@@ -482,7 +481,7 @@ static void pl2303_dtr_rts(struct usb_serial_port *port, int on)
priv->line_control &= ~(CONTROL_DTR | CONTROL_RTS);
control = priv->line_control;
spin_unlock_irqrestore(&priv->lock, flags);
- set_control_lines(port->serial->dev, control);
+ pl2303_set_control_lines(port, control);
}
static void pl2303_close(struct usb_serial_port *port)
@@ -532,7 +531,6 @@ static int pl2303_tiocmset(struct tty_struct *tty,
unsigned int set, unsigned int clear)
{
struct usb_serial_port *port = tty->driver_data;
- struct usb_serial *serial = port->serial;
struct pl2303_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
u8 control;
@@ -550,14 +548,11 @@ static int pl2303_tiocmset(struct tty_struct *tty,
control = priv->line_control;
spin_unlock_irqrestore(&priv->lock, flags);
- mutex_lock(&serial->disc_mutex);
- if (!serial->disconnected)
- ret = set_control_lines(serial->dev, control);
- else
- ret = -ENODEV;
- mutex_unlock(&serial->disc_mutex);
+ ret = pl2303_set_control_lines(port, control);
+ if (ret)
+ return usb_translate_errors(ret);
- return ret;
+ return 0;
}
static int pl2303_tiocmget(struct tty_struct *tty)
@@ -594,8 +589,9 @@ static int pl2303_carrier_raised(struct usb_serial_port *port)
return 0;
}
-static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
+static int pl2303_tiocmiwait(struct tty_struct *tty, unsigned long arg)
{
+ struct usb_serial_port *port = tty->driver_data;
struct pl2303_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
unsigned int prevstatus;
@@ -607,11 +603,14 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
spin_unlock_irqrestore(&priv->lock, flags);
while (1) {
- interruptible_sleep_on(&priv->delta_msr_wait);
+ interruptible_sleep_on(&port->port.delta_msr_wait);
/* see if a signal did it */
if (signal_pending(current))
return -ERESTARTSYS;
+ if (port->serial->disconnected)
+ return -EIO;
+
spin_lock_irqsave(&priv->lock, flags);
status = priv->line_status;
spin_unlock_irqrestore(&priv->lock, flags);
@@ -650,10 +649,6 @@ static int pl2303_ioctl(struct tty_struct *tty,
return -EFAULT;
return 0;
-
- case TIOCMIWAIT:
- dev_dbg(&port->dev, "%s TIOCMIWAIT\n", __func__);
- return wait_modem_info(port, arg);
default:
dev_dbg(&port->dev, "%s not supported = 0x%04x\n", __func__, cmd);
break;
@@ -719,7 +714,7 @@ static void pl2303_update_line_status(struct usb_serial_port *port,
spin_unlock_irqrestore(&priv->lock, flags);
if (priv->line_status & UART_BREAK_ERROR)
usb_serial_handle_break(port);
- wake_up_interruptible(&priv->delta_msr_wait);
+ wake_up_interruptible(&port->port.delta_msr_wait);
tty = tty_port_tty_get(&port->port);
if (!tty)
@@ -783,7 +778,7 @@ static void pl2303_process_read_urb(struct urb *urb)
line_status = priv->line_status;
priv->line_status &= ~UART_STATE_TRANSIENT_MASK;
spin_unlock_irqrestore(&priv->lock, flags);
- wake_up_interruptible(&priv->delta_msr_wait);
+ wake_up_interruptible(&port->port.delta_msr_wait);
if (!urb->actual_length)
return;
@@ -834,6 +829,7 @@ static struct usb_serial_driver pl2303_device = {
.set_termios = pl2303_set_termios,
.tiocmget = pl2303_tiocmget,
.tiocmset = pl2303_tiocmset,
+ .tiocmiwait = pl2303_tiocmiwait,
.process_read_urb = pl2303_process_read_urb,
.read_int_callback = pl2303_read_int_callback,
.attach = pl2303_startup,
diff --git a/drivers/usb/serial/qcaux.c b/drivers/usb/serial/qcaux.c
index 9b1b96f2d09..31f81c3c15e 100644
--- a/drivers/usb/serial/qcaux.c
+++ b/drivers/usb/serial/qcaux.c
@@ -69,6 +69,7 @@ static struct usb_device_id id_table[] = {
{ USB_VENDOR_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, 0xff, 0xfd, 0xff) }, /* NMEA */
{ USB_VENDOR_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, 0xff, 0xfe, 0xff) }, /* WMC */
{ USB_VENDOR_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, 0xff, 0xff, 0xff) }, /* DIAG */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x1fac, 0x0151, 0xff, 0xff, 0xff) },
{ },
};
MODULE_DEVICE_TABLE(usb, id_table);
diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c
index 24662547dc5..59b32b78212 100644
--- a/drivers/usb/serial/qcserial.c
+++ b/drivers/usb/serial/qcserial.c
@@ -197,12 +197,15 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
if (is_gobi1k) {
/* Gobi 1K USB layout:
- * 0: serial port (doesn't respond)
+ * 0: DM/DIAG (use libqcdm from ModemManager for communication)
* 1: serial port (doesn't respond)
* 2: AT-capable modem port
* 3: QMI/net
*/
- if (ifnum == 2)
+ if (ifnum == 0) {
+ dev_dbg(dev, "Gobi 1K DM/DIAG interface found\n");
+ altsetting = 1;
+ } else if (ifnum == 2)
dev_dbg(dev, "Modem port found\n");
else
altsetting = -1;
diff --git a/drivers/usb/serial/quatech2.c b/drivers/usb/serial/quatech2.c
index 00e6c9bac8a..02b0803425c 100644
--- a/drivers/usb/serial/quatech2.c
+++ b/drivers/usb/serial/quatech2.c
@@ -116,7 +116,6 @@ struct qt2_serial_private {
};
struct qt2_port_private {
- bool is_open;
u8 device_port;
spinlock_t urb_lock;
@@ -128,9 +127,6 @@ struct qt2_port_private {
u8 shadowLSR;
u8 shadowMSR;
- wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */
- struct async_icount icount;
-
struct usb_serial_port *port;
};
@@ -398,7 +394,6 @@ static int qt2_open(struct tty_struct *tty, struct usb_serial_port *port)
return status;
}
- port_priv->is_open = true;
port_priv->device_port = (u8) device_port;
if (tty)
@@ -418,19 +413,11 @@ static void qt2_close(struct usb_serial_port *port)
serial = port->serial;
port_priv = usb_get_serial_port_data(port);
- port_priv->is_open = false;
-
spin_lock_irqsave(&port_priv->urb_lock, flags);
usb_kill_urb(port_priv->write_urb);
port_priv->urb_in_use = false;
spin_unlock_irqrestore(&port_priv->urb_lock, flags);
- mutex_lock(&port->serial->disc_mutex);
- if (port->serial->disconnected) {
- mutex_unlock(&port->serial->disc_mutex);
- return;
- }
-
/* flush the port transmit buffer */
i = usb_control_msg(serial->dev,
usb_rcvctrlpipe(serial->dev, 0),
@@ -461,8 +448,6 @@ static void qt2_close(struct usb_serial_port *port)
if (i < 0)
dev_err(&port->dev, "%s - close port failed %i\n",
__func__, i);
-
- mutex_unlock(&port->serial->disc_mutex);
}
static void qt2_disconnect(struct usb_serial *serial)
@@ -495,67 +480,6 @@ static int get_serial_info(struct usb_serial_port *port,
return 0;
}
-static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
-{
- struct qt2_port_private *priv = usb_get_serial_port_data(port);
- struct async_icount prev, cur;
- unsigned long flags;
-
- spin_lock_irqsave(&priv->lock, flags);
- prev = priv->icount;
- spin_unlock_irqrestore(&priv->lock, flags);
-
- while (1) {
- wait_event_interruptible(priv->delta_msr_wait,
- ((priv->icount.rng != prev.rng) ||
- (priv->icount.dsr != prev.dsr) ||
- (priv->icount.dcd != prev.dcd) ||
- (priv->icount.cts != prev.cts)));
-
- if (signal_pending(current))
- return -ERESTARTSYS;
-
- spin_lock_irqsave(&priv->lock, flags);
- cur = priv->icount;
- spin_unlock_irqrestore(&priv->lock, flags);
-
- if ((prev.rng == cur.rng) &&
- (prev.dsr == cur.dsr) &&
- (prev.dcd == cur.dcd) &&
- (prev.cts == cur.cts))
- return -EIO;
-
- if ((arg & TIOCM_RNG && (prev.rng != cur.rng)) ||
- (arg & TIOCM_DSR && (prev.dsr != cur.dsr)) ||
- (arg & TIOCM_CD && (prev.dcd != cur.dcd)) ||
- (arg & TIOCM_CTS && (prev.cts != cur.cts)))
- return 0;
- }
- return 0;
-}
-
-static int qt2_get_icount(struct tty_struct *tty,
- struct serial_icounter_struct *icount)
-{
- struct usb_serial_port *port = tty->driver_data;
- struct qt2_port_private *priv = usb_get_serial_port_data(port);
- struct async_icount cnow = priv->icount;
-
- icount->cts = cnow.cts;
- icount->dsr = cnow.dsr;
- icount->rng = cnow.rng;
- icount->dcd = cnow.dcd;
- icount->rx = cnow.rx;
- icount->tx = cnow.tx;
- icount->frame = cnow.frame;
- icount->overrun = cnow.overrun;
- icount->parity = cnow.parity;
- icount->brk = cnow.brk;
- icount->buf_overrun = cnow.buf_overrun;
-
- return 0;
-}
-
static int qt2_ioctl(struct tty_struct *tty,
unsigned int cmd, unsigned long arg)
{
@@ -565,10 +489,6 @@ static int qt2_ioctl(struct tty_struct *tty,
case TIOCGSERIAL:
return get_serial_info(port,
(struct serial_struct __user *)arg);
-
- case TIOCMIWAIT:
- return wait_modem_info(port, arg);
-
default:
break;
}
@@ -824,7 +744,6 @@ static int qt2_port_probe(struct usb_serial_port *port)
spin_lock_init(&port_priv->lock);
spin_lock_init(&port_priv->urb_lock);
- init_waitqueue_head(&port_priv->delta_msr_wait);
port_priv->port = port;
port_priv->write_urb = usb_alloc_urb(0, GFP_KERNEL);
@@ -905,12 +824,6 @@ static void qt2_break_ctl(struct tty_struct *tty, int break_state)
port_priv = usb_get_serial_port_data(port);
- if (!port_priv->is_open) {
- dev_err(&port->dev,
- "%s - port is not open\n", __func__);
- return;
- }
-
val = (break_state == -1) ? 1 : 0;
status = qt2_control_msg(port->serial->dev, QT2_BREAK_CONTROL,
@@ -956,18 +869,15 @@ static void qt2_update_msr(struct usb_serial_port *port, unsigned char *ch)
if (newMSR & UART_MSR_ANY_DELTA) {
/* update input line counters */
if (newMSR & UART_MSR_DCTS)
- port_priv->icount.cts++;
-
+ port->icount.cts++;
if (newMSR & UART_MSR_DDSR)
- port_priv->icount.dsr++;
-
+ port->icount.dsr++;
if (newMSR & UART_MSR_DDCD)
- port_priv->icount.dcd++;
-
+ port->icount.dcd++;
if (newMSR & UART_MSR_TERI)
- port_priv->icount.rng++;
+ port->icount.rng++;
- wake_up_interruptible(&port_priv->delta_msr_wait);
+ wake_up_interruptible(&port->port.delta_msr_wait);
}
}
@@ -987,7 +897,7 @@ static void qt2_update_lsr(struct usb_serial_port *port, unsigned char *ch)
port_priv->shadowLSR = newLSR;
spin_unlock_irqrestore(&port_priv->lock, flags);
- icount = &port_priv->icount;
+ icount = &port->icount;
if (newLSR & UART_LSR_BRK_ERROR_BITS) {
@@ -1097,7 +1007,8 @@ static struct usb_serial_driver qt2_device = {
.break_ctl = qt2_break_ctl,
.tiocmget = qt2_tiocmget,
.tiocmset = qt2_tiocmset,
- .get_icount = qt2_get_icount,
+ .tiocmiwait = usb_serial_generic_tiocmiwait,
+ .get_icount = usb_serial_generic_get_icount,
.ioctl = qt2_ioctl,
.set_termios = qt2_set_termios,
};
diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c
index c13f6e74774..8894665cd61 100644
--- a/drivers/usb/serial/sierra.c
+++ b/drivers/usb/serial/sierra.c
@@ -628,7 +628,6 @@ static void sierra_instat_callback(struct urb *urb)
unsigned char signals = *((unsigned char *)
urb->transfer_buffer +
sizeof(struct usb_ctrlrequest));
- struct tty_struct *tty;
dev_dbg(&port->dev, "%s: signal x%x\n", __func__,
signals);
@@ -639,11 +638,8 @@ static void sierra_instat_callback(struct urb *urb)
portdata->dsr_state = ((signals & 0x02) ? 1 : 0);
portdata->ri_state = ((signals & 0x08) ? 1 : 0);
- tty = tty_port_tty_get(&port->port);
- if (tty && !C_CLOCAL(tty) &&
- old_dcd_state && !portdata->dcd_state)
- tty_hangup(tty);
- tty_kref_put(tty);
+ if (old_dcd_state && !portdata->dcd_state)
+ tty_port_tty_hangup(&port->port, true);
} else {
dev_dbg(&port->dev, "%s: type %x req %x\n",
__func__, req_pkt->bRequestType,
@@ -778,30 +774,25 @@ static void sierra_close(struct usb_serial_port *port)
portdata->rts_state = 0;
portdata->dtr_state = 0;
- if (serial->dev) {
- mutex_lock(&serial->disc_mutex);
- if (!serial->disconnected) {
- serial->interface->needs_remote_wakeup = 0;
- /* odd error handling due to pm counters */
- if (!usb_autopm_get_interface(serial->interface))
- sierra_send_setup(port);
- else
- usb_autopm_get_interface_no_resume(serial->interface);
-
- }
- mutex_unlock(&serial->disc_mutex);
- spin_lock_irq(&intfdata->susp_lock);
- portdata->opened = 0;
- spin_unlock_irq(&intfdata->susp_lock);
+ mutex_lock(&serial->disc_mutex);
+ if (!serial->disconnected) {
+ serial->interface->needs_remote_wakeup = 0;
+ /* odd error handling due to pm counters */
+ if (!usb_autopm_get_interface(serial->interface))
+ sierra_send_setup(port);
+ else
+ usb_autopm_get_interface_no_resume(serial->interface);
+ }
+ mutex_unlock(&serial->disc_mutex);
+ spin_lock_irq(&intfdata->susp_lock);
+ portdata->opened = 0;
+ spin_unlock_irq(&intfdata->susp_lock);
- /* Stop reading urbs */
- sierra_stop_rx_urbs(port);
- /* .. and release them */
- for (i = 0; i < portdata->num_in_urbs; i++) {
- sierra_release_urb(portdata->in_urbs[i]);
- portdata->in_urbs[i] = NULL;
- }
+ sierra_stop_rx_urbs(port);
+ for (i = 0; i < portdata->num_in_urbs; i++) {
+ sierra_release_urb(portdata->in_urbs[i]);
+ portdata->in_urbs[i] = NULL;
}
}
diff --git a/drivers/usb/serial/spcp8x5.c b/drivers/usb/serial/spcp8x5.c
index 91ff8e3bddb..cf3df793c2b 100644
--- a/drivers/usb/serial/spcp8x5.c
+++ b/drivers/usb/serial/spcp8x5.c
@@ -1,7 +1,7 @@
/*
* spcp8x5 USB to serial adaptor driver
*
- * Copyright (C) 2010 Johan Hovold (jhovold@gmail.com)
+ * Copyright (C) 2010-2013 Johan Hovold (jhovold@gmail.com)
* Copyright (C) 2006 Linxb (xubin.lin@worldplus.com.cn)
* Copyright (C) 2006 S1 Corp.
*
@@ -13,8 +13,6 @@
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
- *
- *
*/
#include <linux/kernel.h>
#include <linux/errno.h>
@@ -28,7 +26,10 @@
#include <linux/usb.h>
#include <linux/usb/serial.h>
-#define DRIVER_DESC "SPCP8x5 USB to serial adaptor driver"
+#define DRIVER_DESC "SPCP8x5 USB to serial adaptor driver"
+
+#define SPCP825_QUIRK_NO_UART_STATUS 0x01
+#define SPCP825_QUIRK_NO_WORK_MODE 0x02
#define SPCP8x5_007_VID 0x04FC
#define SPCP8x5_007_PID 0x0201
@@ -46,13 +47,15 @@ static const struct usb_device_id id_table[] = {
{ USB_DEVICE(SPCP8x5_INTERMATIC_VID, SPCP8x5_INTERMATIC_PID)},
{ USB_DEVICE(SPCP8x5_835_VID, SPCP8x5_835_PID)},
{ USB_DEVICE(SPCP8x5_008_VID, SPCP8x5_008_PID)},
- { USB_DEVICE(SPCP8x5_007_VID, SPCP8x5_007_PID)},
+ { USB_DEVICE(SPCP8x5_007_VID, SPCP8x5_007_PID),
+ .driver_info = SPCP825_QUIRK_NO_UART_STATUS |
+ SPCP825_QUIRK_NO_WORK_MODE },
{ } /* Terminating entry */
};
MODULE_DEVICE_TABLE(usb, id_table);
struct spcp8x5_usb_ctrl_arg {
- u8 type;
+ u8 type;
u8 cmd;
u8 cmd_type;
u16 value;
@@ -138,51 +141,33 @@ struct spcp8x5_usb_ctrl_arg {
#define UART_OVERRUN_ERROR 0x40
#define UART_CTS 0x80
-enum spcp8x5_type {
- SPCP825_007_TYPE,
- SPCP825_008_TYPE,
- SPCP825_PHILIP_TYPE,
- SPCP825_INTERMATIC_TYPE,
- SPCP835_TYPE,
-};
-
struct spcp8x5_private {
- spinlock_t lock;
- enum spcp8x5_type type;
- wait_queue_head_t delta_msr_wait;
- u8 line_control;
- u8 line_status;
+ unsigned quirks;
+ spinlock_t lock;
+ u8 line_control;
};
+static int spcp8x5_probe(struct usb_serial *serial,
+ const struct usb_device_id *id)
+{
+ usb_set_serial_data(serial, (void *)id);
+
+ return 0;
+}
+
static int spcp8x5_port_probe(struct usb_serial_port *port)
{
- struct usb_serial *serial = port->serial;
+ const struct usb_device_id *id = usb_get_serial_data(port->serial);
struct spcp8x5_private *priv;
- enum spcp8x5_type type = SPCP825_007_TYPE;
- u16 product = le16_to_cpu(serial->dev->descriptor.idProduct);
-
- if (product == 0x0201)
- type = SPCP825_007_TYPE;
- else if (product == 0x0231)
- type = SPCP835_TYPE;
- else if (product == 0x0235)
- type = SPCP825_008_TYPE;
- else if (product == 0x0204)
- type = SPCP825_INTERMATIC_TYPE;
- else if (product == 0x0471 &&
- serial->dev->descriptor.idVendor == cpu_to_le16(0x081e))
- type = SPCP825_PHILIP_TYPE;
- dev_dbg(&serial->dev->dev, "device type = %d\n", (int)type);
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
spin_lock_init(&priv->lock);
- init_waitqueue_head(&priv->delta_msr_wait);
- priv->type = type;
+ priv->quirks = id->driver_info;
- usb_set_serial_port_data(port , priv);
+ usb_set_serial_port_data(port, priv);
return 0;
}
@@ -197,86 +182,79 @@ static int spcp8x5_port_remove(struct usb_serial_port *port)
return 0;
}
-/* set the modem control line of the device.
- * NOTE spcp825-007 not supported this */
-static int spcp8x5_set_ctrlLine(struct usb_device *dev, u8 value,
- enum spcp8x5_type type)
+static int spcp8x5_set_ctrl_line(struct usb_serial_port *port, u8 mcr)
{
+ struct spcp8x5_private *priv = usb_get_serial_port_data(port);
+ struct usb_device *dev = port->serial->dev;
int retval;
- u8 mcr = 0 ;
- if (type == SPCP825_007_TYPE)
+ if (priv->quirks & SPCP825_QUIRK_NO_UART_STATUS)
return -EPERM;
- mcr = (unsigned short)value;
retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
SET_UART_STATUS_TYPE, SET_UART_STATUS,
mcr, 0x04, NULL, 0, 100);
- if (retval != 0)
- dev_dbg(&dev->dev, "usb_control_msg return %#x\n", retval);
+ if (retval != 0) {
+ dev_err(&port->dev, "failed to set control lines: %d\n",
+ retval);
+ }
return retval;
}
-/* get the modem status register of the device
- * NOTE spcp825-007 not supported this */
-static int spcp8x5_get_msr(struct usb_device *dev, u8 *status,
- enum spcp8x5_type type)
+static int spcp8x5_get_msr(struct usb_serial_port *port, u8 *status)
{
- u8 *status_buffer;
+ struct spcp8x5_private *priv = usb_get_serial_port_data(port);
+ struct usb_device *dev = port->serial->dev;
+ u8 *buf;
int ret;
- /* I return Permited not support here but seem inval device
- * is more fix */
- if (type == SPCP825_007_TYPE)
+ if (priv->quirks & SPCP825_QUIRK_NO_UART_STATUS)
return -EPERM;
- if (status == NULL)
- return -EINVAL;
- status_buffer = kmalloc(1, GFP_KERNEL);
- if (!status_buffer)
+ buf = kzalloc(1, GFP_KERNEL);
+ if (!buf)
return -ENOMEM;
- status_buffer[0] = status[0];
ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
GET_UART_STATUS, GET_UART_STATUS_TYPE,
- 0, GET_UART_STATUS_MSR, status_buffer, 1, 100);
+ 0, GET_UART_STATUS_MSR, buf, 1, 100);
if (ret < 0)
- dev_dbg(&dev->dev, "Get MSR = 0x%p failed (error = %d)",
- status_buffer, ret);
+ dev_err(&port->dev, "failed to get modem status: %d", ret);
- dev_dbg(&dev->dev, "0xc0:0x22:0:6 %d - 0x%p ", ret, status_buffer);
- status[0] = status_buffer[0];
- kfree(status_buffer);
+ dev_dbg(&port->dev, "0xc0:0x22:0:6 %d - 0x02%x", ret, *buf);
+ *status = *buf;
+ kfree(buf);
return ret;
}
-/* select the work mode.
- * NOTE this function not supported by spcp825-007 */
-static void spcp8x5_set_workMode(struct usb_device *dev, u16 value,
- u16 index, enum spcp8x5_type type)
+static void spcp8x5_set_work_mode(struct usb_serial_port *port, u16 value,
+ u16 index)
{
+ struct spcp8x5_private *priv = usb_get_serial_port_data(port);
+ struct usb_device *dev = port->serial->dev;
int ret;
- /* I return Permited not support here but seem inval device
- * is more fix */
- if (type == SPCP825_007_TYPE)
+ if (priv->quirks & SPCP825_QUIRK_NO_WORK_MODE)
return;
ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
SET_WORKING_MODE_TYPE, SET_WORKING_MODE,
value, index, NULL, 0, 100);
- dev_dbg(&dev->dev, "value = %#x , index = %#x\n", value, index);
+ dev_dbg(&port->dev, "value = %#x , index = %#x\n", value, index);
if (ret < 0)
- dev_dbg(&dev->dev,
- "RTSCTS usb_control_msg(enable flowctrl) = %d\n", ret);
+ dev_err(&port->dev, "failed to set work mode: %d\n", ret);
}
static int spcp8x5_carrier_raised(struct usb_serial_port *port)
{
- struct spcp8x5_private *priv = usb_get_serial_port_data(port);
- if (priv->line_status & MSR_STATUS_LINE_DCD)
+ u8 msr;
+ int ret;
+
+ ret = spcp8x5_get_msr(port, &msr);
+ if (ret || msr & MSR_STATUS_LINE_DCD)
return 1;
+
return 0;
}
@@ -295,20 +273,17 @@ static void spcp8x5_dtr_rts(struct usb_serial_port *port, int on)
| MCR_CONTROL_LINE_RTS);
control = priv->line_control;
spin_unlock_irqrestore(&priv->lock, flags);
- spcp8x5_set_ctrlLine(port->serial->dev, control , priv->type);
+ spcp8x5_set_ctrl_line(port, control);
}
static void spcp8x5_init_termios(struct tty_struct *tty)
{
- /* for the 1st time call this function */
tty->termios = tty_std_termios;
tty->termios.c_cflag = B115200 | CS8 | CREAD | HUPCL | CLOCAL;
tty->termios.c_ispeed = 115200;
tty->termios.c_ospeed = 115200;
}
-/* set the serial param for transfer. we should check if we really need to
- * transfer. if we set flow control we should do this too. */
static void spcp8x5_set_termios(struct tty_struct *tty,
struct usb_serial_port *port, struct ktermios *old_termios)
{
@@ -323,7 +298,6 @@ static void spcp8x5_set_termios(struct tty_struct *tty,
int i;
u8 control;
-
/* check that they really want us to change something */
if (!tty_termios_hw_change(&tty->termios, old_termios))
return;
@@ -339,7 +313,7 @@ static void spcp8x5_set_termios(struct tty_struct *tty,
if (control != priv->line_control) {
control = priv->line_control;
spin_unlock_irqrestore(&priv->lock, flags);
- spcp8x5_set_ctrlLine(serial->dev, control , priv->type);
+ spcp8x5_set_ctrl_line(port, control);
} else {
spin_unlock_irqrestore(&priv->lock, flags);
}
@@ -399,9 +373,9 @@ static void spcp8x5_set_termios(struct tty_struct *tty,
if (cflag & PARENB) {
buf[1] |= (cflag & PARODD) ?
SET_UART_FORMAT_PAR_ODD : SET_UART_FORMAT_PAR_EVEN ;
- } else
+ } else {
buf[1] |= SET_UART_FORMAT_PAR_NONE;
-
+ }
uartdata = buf[0] | buf[1]<<8;
i = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
@@ -414,22 +388,16 @@ static void spcp8x5_set_termios(struct tty_struct *tty,
if (cflag & CRTSCTS) {
/* enable hardware flow control */
- spcp8x5_set_workMode(serial->dev, 0x000a,
- SET_WORKING_MODE_U2C, priv->type);
+ spcp8x5_set_work_mode(port, 0x000a, SET_WORKING_MODE_U2C);
}
}
-/* open the serial port. do some usb system call. set termios and get the line
- * status of the device. */
static int spcp8x5_open(struct tty_struct *tty, struct usb_serial_port *port)
{
struct ktermios tmp_termios;
struct usb_serial *serial = port->serial;
struct spcp8x5_private *priv = usb_get_serial_port_data(port);
int ret;
- unsigned long flags;
- u8 status = 0x30;
- /* status 0x30 means DSR and CTS = 1 other CDC RI and delta = 0 */
usb_clear_halt(serial->dev, port->write_urb->pipe);
usb_clear_halt(serial->dev, port->read_urb->pipe);
@@ -440,139 +408,16 @@ static int spcp8x5_open(struct tty_struct *tty, struct usb_serial_port *port)
if (ret)
return ret;
- spcp8x5_set_ctrlLine(serial->dev, priv->line_control , priv->type);
+ spcp8x5_set_ctrl_line(port, priv->line_control);
- /* Setup termios */
if (tty)
spcp8x5_set_termios(tty, port, &tmp_termios);
- spcp8x5_get_msr(serial->dev, &status, priv->type);
-
- /* may be we should update uart status here but now we did not do */
- spin_lock_irqsave(&priv->lock, flags);
- priv->line_status = status & 0xf0 ;
- spin_unlock_irqrestore(&priv->lock, flags);
-
port->port.drain_delay = 256;
return usb_serial_generic_open(tty, port);
}
-static void spcp8x5_process_read_urb(struct urb *urb)
-{
- struct usb_serial_port *port = urb->context;
- struct spcp8x5_private *priv = usb_get_serial_port_data(port);
- unsigned char *data = urb->transfer_buffer;
- unsigned long flags;
- u8 status;
- char tty_flag;
-
- /* get tty_flag from status */
- tty_flag = TTY_NORMAL;
-
- spin_lock_irqsave(&priv->lock, flags);
- status = priv->line_status;
- priv->line_status &= ~UART_STATE_TRANSIENT_MASK;
- spin_unlock_irqrestore(&priv->lock, flags);
- /* wake up the wait for termios */
- wake_up_interruptible(&priv->delta_msr_wait);
-
- if (!urb->actual_length)
- return;
-
-
- if (status & UART_STATE_TRANSIENT_MASK) {
- /* break takes precedence over parity, which takes precedence
- * over framing errors */
- if (status & UART_BREAK_ERROR)
- tty_flag = TTY_BREAK;
- else if (status & UART_PARITY_ERROR)
- tty_flag = TTY_PARITY;
- else if (status & UART_FRAME_ERROR)
- tty_flag = TTY_FRAME;
- dev_dbg(&port->dev, "tty_flag = %d\n", tty_flag);
-
- /* overrun is special, not associated with a char */
- if (status & UART_OVERRUN_ERROR)
- tty_insert_flip_char(&port->port, 0, TTY_OVERRUN);
-
- if (status & UART_DCD) {
- struct tty_struct *tty = tty_port_tty_get(&port->port);
- if (tty) {
- usb_serial_handle_dcd_change(port, tty,
- priv->line_status & MSR_STATUS_LINE_DCD);
- tty_kref_put(tty);
- }
- }
- }
-
- tty_insert_flip_string_fixed_flag(&port->port, data, tty_flag,
- urb->actual_length);
- tty_flip_buffer_push(&port->port);
-}
-
-static int spcp8x5_wait_modem_info(struct usb_serial_port *port,
- unsigned int arg)
-{
- struct spcp8x5_private *priv = usb_get_serial_port_data(port);
- unsigned long flags;
- unsigned int prevstatus;
- unsigned int status;
- unsigned int changed;
-
- spin_lock_irqsave(&priv->lock, flags);
- prevstatus = priv->line_status;
- spin_unlock_irqrestore(&priv->lock, flags);
-
- while (1) {
- /* wake up in bulk read */
- interruptible_sleep_on(&priv->delta_msr_wait);
-
- /* see if a signal did it */
- if (signal_pending(current))
- return -ERESTARTSYS;
-
- spin_lock_irqsave(&priv->lock, flags);
- status = priv->line_status;
- spin_unlock_irqrestore(&priv->lock, flags);
-
- changed = prevstatus^status;
-
- if (((arg & TIOCM_RNG) && (changed & MSR_STATUS_LINE_RI)) ||
- ((arg & TIOCM_DSR) && (changed & MSR_STATUS_LINE_DSR)) ||
- ((arg & TIOCM_CD) && (changed & MSR_STATUS_LINE_DCD)) ||
- ((arg & TIOCM_CTS) && (changed & MSR_STATUS_LINE_CTS)))
- return 0;
-
- prevstatus = status;
- }
- /* NOTREACHED */
- return 0;
-}
-
-static int spcp8x5_ioctl(struct tty_struct *tty,
- unsigned int cmd, unsigned long arg)
-{
- struct usb_serial_port *port = tty->driver_data;
-
- dev_dbg(&port->dev, "%s (%d) cmd = 0x%04x\n", __func__,
- port->number, cmd);
-
- switch (cmd) {
- case TIOCMIWAIT:
- dev_dbg(&port->dev, "%s (%d) TIOCMIWAIT\n", __func__,
- port->number);
- return spcp8x5_wait_modem_info(port, arg);
-
- default:
- dev_dbg(&port->dev, "%s not supported = 0x%04x", __func__,
- cmd);
- break;
- }
-
- return -ENOIOCTLCMD;
-}
-
static int spcp8x5_tiocmset(struct tty_struct *tty,
unsigned int set, unsigned int clear)
{
@@ -593,7 +438,7 @@ static int spcp8x5_tiocmset(struct tty_struct *tty,
control = priv->line_control;
spin_unlock_irqrestore(&priv->lock, flags);
- return spcp8x5_set_ctrlLine(port->serial->dev, control , priv->type);
+ return spcp8x5_set_ctrl_line(port, control);
}
static int spcp8x5_tiocmget(struct tty_struct *tty)
@@ -602,12 +447,15 @@ static int spcp8x5_tiocmget(struct tty_struct *tty)
struct spcp8x5_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
unsigned int mcr;
- unsigned int status;
+ u8 status;
unsigned int result;
+ result = spcp8x5_get_msr(port, &status);
+ if (result)
+ return result;
+
spin_lock_irqsave(&priv->lock, flags);
mcr = priv->line_control;
- status = priv->line_status;
spin_unlock_irqrestore(&priv->lock, flags);
result = ((mcr & MCR_DTR) ? TIOCM_DTR : 0)
@@ -620,7 +468,6 @@ static int spcp8x5_tiocmget(struct tty_struct *tty)
return result;
}
-/* All of the device info needed for the spcp8x5 SIO serial converter */
static struct usb_serial_driver spcp8x5_device = {
.driver = {
.owner = THIS_MODULE,
@@ -628,17 +475,16 @@ static struct usb_serial_driver spcp8x5_device = {
},
.id_table = id_table,
.num_ports = 1,
- .open = spcp8x5_open,
+ .open = spcp8x5_open,
.dtr_rts = spcp8x5_dtr_rts,
.carrier_raised = spcp8x5_carrier_raised,
- .set_termios = spcp8x5_set_termios,
+ .set_termios = spcp8x5_set_termios,
.init_termios = spcp8x5_init_termios,
- .ioctl = spcp8x5_ioctl,
- .tiocmget = spcp8x5_tiocmget,
- .tiocmset = spcp8x5_tiocmset,
+ .tiocmget = spcp8x5_tiocmget,
+ .tiocmset = spcp8x5_tiocmset,
+ .probe = spcp8x5_probe,
.port_probe = spcp8x5_port_probe,
.port_remove = spcp8x5_port_remove,
- .process_read_urb = spcp8x5_process_read_urb,
};
static struct usb_serial_driver * const serial_drivers[] = {
diff --git a/drivers/usb/serial/ssu100.c b/drivers/usb/serial/ssu100.c
index b57cf841c5b..5b62dbbdf99 100644
--- a/drivers/usb/serial/ssu100.c
+++ b/drivers/usb/serial/ssu100.c
@@ -61,8 +61,6 @@ struct ssu100_port_private {
spinlock_t status_lock;
u8 shadowLSR;
u8 shadowMSR;
- wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */
- struct async_icount icount;
};
static inline int ssu100_control_msg(struct usb_device *dev,
@@ -316,11 +314,6 @@ static int ssu100_open(struct tty_struct *tty, struct usb_serial_port *port)
return usb_serial_generic_open(tty, port);
}
-static void ssu100_close(struct usb_serial_port *port)
-{
- usb_serial_generic_close(port);
-}
-
static int get_serial_info(struct usb_serial_port *port,
struct serial_struct __user *retinfo)
{
@@ -344,69 +337,6 @@ static int get_serial_info(struct usb_serial_port *port,
return 0;
}
-static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
-{
- struct ssu100_port_private *priv = usb_get_serial_port_data(port);
- struct async_icount prev, cur;
- unsigned long flags;
-
- spin_lock_irqsave(&priv->status_lock, flags);
- prev = priv->icount;
- spin_unlock_irqrestore(&priv->status_lock, flags);
-
- while (1) {
- wait_event_interruptible(priv->delta_msr_wait,
- ((priv->icount.rng != prev.rng) ||
- (priv->icount.dsr != prev.dsr) ||
- (priv->icount.dcd != prev.dcd) ||
- (priv->icount.cts != prev.cts)));
-
- if (signal_pending(current))
- return -ERESTARTSYS;
-
- spin_lock_irqsave(&priv->status_lock, flags);
- cur = priv->icount;
- spin_unlock_irqrestore(&priv->status_lock, flags);
-
- if ((prev.rng == cur.rng) &&
- (prev.dsr == cur.dsr) &&
- (prev.dcd == cur.dcd) &&
- (prev.cts == cur.cts))
- return -EIO;
-
- if ((arg & TIOCM_RNG && (prev.rng != cur.rng)) ||
- (arg & TIOCM_DSR && (prev.dsr != cur.dsr)) ||
- (arg & TIOCM_CD && (prev.dcd != cur.dcd)) ||
- (arg & TIOCM_CTS && (prev.cts != cur.cts)))
- return 0;
- }
- return 0;
-}
-
-static int ssu100_get_icount(struct tty_struct *tty,
- struct serial_icounter_struct *icount)
-{
- struct usb_serial_port *port = tty->driver_data;
- struct ssu100_port_private *priv = usb_get_serial_port_data(port);
- struct async_icount cnow = priv->icount;
-
- icount->cts = cnow.cts;
- icount->dsr = cnow.dsr;
- icount->rng = cnow.rng;
- icount->dcd = cnow.dcd;
- icount->rx = cnow.rx;
- icount->tx = cnow.tx;
- icount->frame = cnow.frame;
- icount->overrun = cnow.overrun;
- icount->parity = cnow.parity;
- icount->brk = cnow.brk;
- icount->buf_overrun = cnow.buf_overrun;
-
- return 0;
-}
-
-
-
static int ssu100_ioctl(struct tty_struct *tty,
unsigned int cmd, unsigned long arg)
{
@@ -418,10 +348,6 @@ static int ssu100_ioctl(struct tty_struct *tty,
case TIOCGSERIAL:
return get_serial_info(port,
(struct serial_struct __user *) arg);
-
- case TIOCMIWAIT:
- return wait_modem_info(port, arg);
-
default:
break;
}
@@ -445,7 +371,6 @@ static int ssu100_port_probe(struct usb_serial_port *port)
return -ENOMEM;
spin_lock_init(&priv->status_lock);
- init_waitqueue_head(&priv->delta_msr_wait);
usb_set_serial_port_data(port, priv);
@@ -530,14 +455,14 @@ static void ssu100_update_msr(struct usb_serial_port *port, u8 msr)
if (msr & UART_MSR_ANY_DELTA) {
/* update input line counters */
if (msr & UART_MSR_DCTS)
- priv->icount.cts++;
+ port->icount.cts++;
if (msr & UART_MSR_DDSR)
- priv->icount.dsr++;
+ port->icount.dsr++;
if (msr & UART_MSR_DDCD)
- priv->icount.dcd++;
+ port->icount.dcd++;
if (msr & UART_MSR_TERI)
- priv->icount.rng++;
- wake_up_interruptible(&priv->delta_msr_wait);
+ port->icount.rng++;
+ wake_up_interruptible(&port->port.delta_msr_wait);
}
}
@@ -556,22 +481,22 @@ static void ssu100_update_lsr(struct usb_serial_port *port, u8 lsr,
/* we always want to update icount, but we only want to
* update tty_flag for one case */
if (lsr & UART_LSR_BI) {
- priv->icount.brk++;
+ port->icount.brk++;
*tty_flag = TTY_BREAK;
usb_serial_handle_break(port);
}
if (lsr & UART_LSR_PE) {
- priv->icount.parity++;
+ port->icount.parity++;
if (*tty_flag == TTY_NORMAL)
*tty_flag = TTY_PARITY;
}
if (lsr & UART_LSR_FE) {
- priv->icount.frame++;
+ port->icount.frame++;
if (*tty_flag == TTY_NORMAL)
*tty_flag = TTY_FRAME;
}
if (lsr & UART_LSR_OE){
- priv->icount.overrun++;
+ port->icount.overrun++;
if (*tty_flag == TTY_NORMAL)
*tty_flag = TTY_OVERRUN;
}
@@ -628,7 +553,6 @@ static struct usb_serial_driver ssu100_device = {
.id_table = id_table,
.num_ports = 1,
.open = ssu100_open,
- .close = ssu100_close,
.attach = ssu100_attach,
.port_probe = ssu100_port_probe,
.port_remove = ssu100_port_remove,
@@ -636,10 +560,10 @@ static struct usb_serial_driver ssu100_device = {
.process_read_urb = ssu100_process_read_urb,
.tiocmget = ssu100_tiocmget,
.tiocmset = ssu100_tiocmset,
- .get_icount = ssu100_get_icount,
+ .tiocmiwait = usb_serial_generic_tiocmiwait,
+ .get_icount = usb_serial_generic_get_icount,
.ioctl = ssu100_ioctl,
.set_termios = ssu100_set_termios,
- .disconnect = usb_serial_generic_disconnect,
};
static struct usb_serial_driver * const serial_drivers[] = {
diff --git a/drivers/usb/serial/symbolserial.c b/drivers/usb/serial/symbolserial.c
index be05e6caf9a..9b1648945e7 100644
--- a/drivers/usb/serial/symbolserial.c
+++ b/drivers/usb/serial/symbolserial.c
@@ -1,6 +1,7 @@
/*
* Symbol USB barcode to serial driver
*
+ * Copyright (C) 2013 Johan Hovold <jhovold@gmail.com>
* Copyright (C) 2009 Greg Kroah-Hartman <gregkh@suse.de>
* Copyright (C) 2009 Novell Inc.
*
@@ -26,27 +27,17 @@ static const struct usb_device_id id_table[] = {
};
MODULE_DEVICE_TABLE(usb, id_table);
-/* This structure holds all of the individual device information */
struct symbol_private {
- struct usb_device *udev;
- struct usb_serial *serial;
- struct usb_serial_port *port;
- unsigned char *int_buffer;
- struct urb *int_urb;
- int buffer_size;
- u8 bInterval;
- u8 int_address;
spinlock_t lock; /* protects the following flags */
bool throttled;
bool actually_throttled;
- bool rts;
};
static void symbol_int_callback(struct urb *urb)
{
- struct symbol_private *priv = urb->context;
+ struct usb_serial_port *port = urb->context;
+ struct symbol_private *priv = usb_get_serial_port_data(port);
unsigned char *data = urb->transfer_buffer;
- struct usb_serial_port *port = priv->port;
int status = urb->status;
int result;
int data_length;
@@ -84,7 +75,7 @@ static void symbol_int_callback(struct urb *urb)
tty_insert_flip_string(&port->port, &data[1], data_length);
tty_flip_buffer_push(&port->port);
} else {
- dev_dbg(&priv->udev->dev,
+ dev_dbg(&port->dev,
"Improper amount of data received from the device, "
"%d bytes", urb->actual_length);
}
@@ -94,12 +85,7 @@ exit:
/* Continue trying to always read if we should */
if (!priv->throttled) {
- usb_fill_int_urb(priv->int_urb, priv->udev,
- usb_rcvintpipe(priv->udev,
- priv->int_address),
- priv->int_buffer, priv->buffer_size,
- symbol_int_callback, priv, priv->bInterval);
- result = usb_submit_urb(priv->int_urb, GFP_ATOMIC);
+ result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
if (result)
dev_err(&port->dev,
"%s - failed resubmitting read urb, error %d\n",
@@ -118,15 +104,10 @@ static int symbol_open(struct tty_struct *tty, struct usb_serial_port *port)
spin_lock_irqsave(&priv->lock, flags);
priv->throttled = false;
priv->actually_throttled = false;
- priv->port = port;
spin_unlock_irqrestore(&priv->lock, flags);
/* Start reading from the device */
- usb_fill_int_urb(priv->int_urb, priv->udev,
- usb_rcvintpipe(priv->udev, priv->int_address),
- priv->int_buffer, priv->buffer_size,
- symbol_int_callback, priv, priv->bInterval);
- result = usb_submit_urb(priv->int_urb, GFP_KERNEL);
+ result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
if (result)
dev_err(&port->dev,
"%s - failed resubmitting read urb, error %d\n",
@@ -136,10 +117,7 @@ static int symbol_open(struct tty_struct *tty, struct usb_serial_port *port)
static void symbol_close(struct usb_serial_port *port)
{
- struct symbol_private *priv = usb_get_serial_data(port->serial);
-
- /* shutdown our urbs */
- usb_kill_urb(priv->int_urb);
+ usb_kill_urb(port->interrupt_in_urb);
}
static void symbol_throttle(struct tty_struct *tty)
@@ -166,7 +144,7 @@ static void symbol_unthrottle(struct tty_struct *tty)
spin_unlock_irq(&priv->lock);
if (was_throttled) {
- result = usb_submit_urb(priv->int_urb, GFP_KERNEL);
+ result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
if (result)
dev_err(&port->dev,
"%s - failed submitting read urb, error %d\n",
@@ -176,89 +154,36 @@ static void symbol_unthrottle(struct tty_struct *tty)
static int symbol_startup(struct usb_serial *serial)
{
+ if (!serial->num_interrupt_in) {
+ dev_err(&serial->dev->dev, "no interrupt-in endpoint\n");
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+static int symbol_port_probe(struct usb_serial_port *port)
+{
struct symbol_private *priv;
- struct usb_host_interface *intf;
- int i;
- int retval = -ENOMEM;
- bool int_in_found = false;
- /* create our private serial structure */
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
- if (priv == NULL) {
- dev_err(&serial->dev->dev, "%s - Out of memory\n", __func__);
+ if (!priv)
return -ENOMEM;
- }
+
spin_lock_init(&priv->lock);
- priv->serial = serial;
- priv->port = serial->port[0];
- priv->udev = serial->dev;
-
- /* find our interrupt endpoint */
- intf = serial->interface->altsetting;
- for (i = 0; i < intf->desc.bNumEndpoints; ++i) {
- struct usb_endpoint_descriptor *endpoint;
-
- endpoint = &intf->endpoint[i].desc;
- if (!usb_endpoint_is_int_in(endpoint))
- continue;
-
- priv->int_urb = usb_alloc_urb(0, GFP_KERNEL);
- if (!priv->int_urb) {
- dev_err(&priv->udev->dev, "out of memory\n");
- goto error;
- }
-
- priv->buffer_size = usb_endpoint_maxp(endpoint) * 2;
- priv->int_buffer = kmalloc(priv->buffer_size, GFP_KERNEL);
- if (!priv->int_buffer) {
- dev_err(&priv->udev->dev, "out of memory\n");
- goto error;
- }
-
- priv->int_address = endpoint->bEndpointAddress;
- priv->bInterval = endpoint->bInterval;
-
- /* set up our int urb */
- usb_fill_int_urb(priv->int_urb, priv->udev,
- usb_rcvintpipe(priv->udev,
- endpoint->bEndpointAddress),
- priv->int_buffer, priv->buffer_size,
- symbol_int_callback, priv, priv->bInterval);
-
- int_in_found = true;
- break;
- }
- if (!int_in_found) {
- dev_err(&priv->udev->dev,
- "Error - the proper endpoints were not found!\n");
- goto error;
- }
+ usb_set_serial_port_data(port, priv);
- usb_set_serial_data(serial, priv);
return 0;
-
-error:
- usb_free_urb(priv->int_urb);
- kfree(priv->int_buffer);
- kfree(priv);
- return retval;
-}
-
-static void symbol_disconnect(struct usb_serial *serial)
-{
- struct symbol_private *priv = usb_get_serial_data(serial);
-
- usb_kill_urb(priv->int_urb);
- usb_free_urb(priv->int_urb);
}
-static void symbol_release(struct usb_serial *serial)
+static int symbol_port_remove(struct usb_serial_port *port)
{
- struct symbol_private *priv = usb_get_serial_data(serial);
+ struct symbol_private *priv = usb_get_serial_port_data(port);
- kfree(priv->int_buffer);
kfree(priv);
+
+ return 0;
}
static struct usb_serial_driver symbol_device = {
@@ -269,12 +194,13 @@ static struct usb_serial_driver symbol_device = {
.id_table = id_table,
.num_ports = 1,
.attach = symbol_startup,
+ .port_probe = symbol_port_probe,
+ .port_remove = symbol_port_remove,
.open = symbol_open,
.close = symbol_close,
- .disconnect = symbol_disconnect,
- .release = symbol_release,
.throttle = symbol_throttle,
.unthrottle = symbol_unthrottle,
+ .read_int_callback = symbol_int_callback,
};
static struct usb_serial_driver * const serial_drivers[] = {
diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c
index 39cb9b807c3..cac47aef291 100644
--- a/drivers/usb/serial/ti_usb_3410_5052.c
+++ b/drivers/usb/serial/ti_usb_3410_5052.c
@@ -67,14 +67,10 @@
struct ti_port {
int tp_is_open;
__u8 tp_msr;
- __u8 tp_lsr;
__u8 tp_shadow_mcr;
__u8 tp_uart_mode; /* 232 or 485 modes */
unsigned int tp_uart_base_addr;
int tp_flags;
- int tp_closing_wait;/* in .01 secs */
- struct async_icount tp_icount;
- wait_queue_head_t tp_msr_wait; /* wait for msr change */
wait_queue_head_t tp_write_wait;
struct ti_device *tp_tdev;
struct usb_serial_port *tp_port;
@@ -109,8 +105,6 @@ static void ti_throttle(struct tty_struct *tty);
static void ti_unthrottle(struct tty_struct *tty);
static int ti_ioctl(struct tty_struct *tty,
unsigned int cmd, unsigned long arg);
-static int ti_get_icount(struct tty_struct *tty,
- struct serial_icounter_struct *icount);
static void ti_set_termios(struct tty_struct *tty,
struct usb_serial_port *port, struct ktermios *old_termios);
static int ti_tiocmget(struct tty_struct *tty);
@@ -125,15 +119,13 @@ static void ti_recv(struct usb_serial_port *port, unsigned char *data,
int length);
static void ti_send(struct ti_port *tport);
static int ti_set_mcr(struct ti_port *tport, unsigned int mcr);
-static int ti_get_lsr(struct ti_port *tport);
+static int ti_get_lsr(struct ti_port *tport, u8 *lsr);
static int ti_get_serial_info(struct ti_port *tport,
struct serial_struct __user *ret_arg);
static int ti_set_serial_info(struct tty_struct *tty, struct ti_port *tport,
struct serial_struct __user *new_arg);
static void ti_handle_new_msr(struct ti_port *tport, __u8 msr);
-static void ti_drain(struct ti_port *tport, unsigned long timeout, int flush);
-
static void ti_stop_read(struct ti_port *tport, struct tty_struct *tty);
static int ti_restart_read(struct ti_port *tport, struct tty_struct *tty);
@@ -236,7 +228,8 @@ static struct usb_serial_driver ti_1port_device = {
.set_termios = ti_set_termios,
.tiocmget = ti_tiocmget,
.tiocmset = ti_tiocmset,
- .get_icount = ti_get_icount,
+ .tiocmiwait = usb_serial_generic_tiocmiwait,
+ .get_icount = usb_serial_generic_get_icount,
.break_ctl = ti_break,
.read_int_callback = ti_interrupt_callback,
.read_bulk_callback = ti_bulk_in_callback,
@@ -266,7 +259,8 @@ static struct usb_serial_driver ti_2port_device = {
.set_termios = ti_set_termios,
.tiocmget = ti_tiocmget,
.tiocmset = ti_tiocmset,
- .get_icount = ti_get_icount,
+ .tiocmiwait = usb_serial_generic_tiocmiwait,
+ .get_icount = usb_serial_generic_get_icount,
.break_ctl = ti_break,
.read_int_callback = ti_interrupt_callback,
.read_bulk_callback = ti_bulk_in_callback,
@@ -431,8 +425,7 @@ static int ti_port_probe(struct usb_serial_port *port)
tport->tp_uart_base_addr = TI_UART1_BASE_ADDR;
else
tport->tp_uart_base_addr = TI_UART2_BASE_ADDR;
- tport->tp_closing_wait = closing_wait;
- init_waitqueue_head(&tport->tp_msr_wait);
+ port->port.closing_wait = msecs_to_jiffies(10 * closing_wait);
init_waitqueue_head(&tport->tp_write_wait);
if (kfifo_alloc(&tport->write_fifo, TI_WRITE_BUF_SIZE, GFP_KERNEL)) {
kfree(tport);
@@ -482,8 +475,6 @@ static int ti_open(struct tty_struct *tty, struct usb_serial_port *port)
port_number = port->number - port->serial->minor;
- memset(&(tport->tp_icount), 0x00, sizeof(tport->tp_icount));
-
tport->tp_msr = 0;
tport->tp_shadow_mcr |= (TI_MCR_RTS | TI_MCR_DTR);
@@ -587,6 +578,8 @@ static int ti_open(struct tty_struct *tty, struct usb_serial_port *port)
tport->tp_is_open = 1;
++tdev->td_open_port_count;
+ port->port.drain_delay = 3;
+
goto release_lock;
unlink_int_urb:
@@ -606,6 +599,7 @@ static void ti_close(struct usb_serial_port *port)
int port_number;
int status;
int do_unlock;
+ unsigned long flags;
tdev = usb_get_serial_data(port->serial);
tport = usb_get_serial_port_data(port);
@@ -614,11 +608,12 @@ static void ti_close(struct usb_serial_port *port)
tport->tp_is_open = 0;
- ti_drain(tport, (tport->tp_closing_wait*HZ)/100, 1);
-
usb_kill_urb(port->read_urb);
usb_kill_urb(port->write_urb);
tport->tp_write_urb_in_use = 0;
+ spin_lock_irqsave(&tport->tp_lock, flags);
+ kfifo_reset_out(&tport->write_fifo);
+ spin_unlock_irqrestore(&tport->tp_lock, flags);
port_number = port->number - port->serial->minor;
@@ -689,6 +684,8 @@ static int ti_chars_in_buffer(struct tty_struct *tty)
struct ti_port *tport = usb_get_serial_port_data(port);
int chars = 0;
unsigned long flags;
+ int ret;
+ u8 lsr;
if (tport == NULL)
return 0;
@@ -697,6 +694,12 @@ static int ti_chars_in_buffer(struct tty_struct *tty)
chars = kfifo_len(&tport->write_fifo);
spin_unlock_irqrestore(&tport->tp_lock, flags);
+ if (!chars) {
+ ret = ti_get_lsr(tport, &lsr);
+ if (!ret && !(lsr & TI_LSR_TX_EMPTY))
+ chars = 1;
+ }
+
dev_dbg(&port->dev, "%s - returns %d\n", __func__, chars);
return chars;
}
@@ -733,38 +736,11 @@ static void ti_unthrottle(struct tty_struct *tty)
}
}
-static int ti_get_icount(struct tty_struct *tty,
- struct serial_icounter_struct *icount)
-{
- struct usb_serial_port *port = tty->driver_data;
- struct ti_port *tport = usb_get_serial_port_data(port);
- struct async_icount cnow = tport->tp_icount;
-
- dev_dbg(&port->dev, "%s - TIOCGICOUNT RX=%d, TX=%d\n", __func__,
- cnow.rx, cnow.tx);
-
- icount->cts = cnow.cts;
- icount->dsr = cnow.dsr;
- icount->rng = cnow.rng;
- icount->dcd = cnow.dcd;
- icount->rx = cnow.rx;
- icount->tx = cnow.tx;
- icount->frame = cnow.frame;
- icount->overrun = cnow.overrun;
- icount->parity = cnow.parity;
- icount->brk = cnow.brk;
- icount->buf_overrun = cnow.buf_overrun;
-
- return 0;
-}
-
static int ti_ioctl(struct tty_struct *tty,
unsigned int cmd, unsigned long arg)
{
struct usb_serial_port *port = tty->driver_data;
struct ti_port *tport = usb_get_serial_port_data(port);
- struct async_icount cnow;
- struct async_icount cprev;
dev_dbg(&port->dev, "%s - cmd = 0x%04X\n", __func__, cmd);
@@ -780,25 +756,6 @@ static int ti_ioctl(struct tty_struct *tty,
dev_dbg(&port->dev, "%s - TIOCSSERIAL\n", __func__);
return ti_set_serial_info(tty, tport,
(struct serial_struct __user *)arg);
- case TIOCMIWAIT:
- dev_dbg(&port->dev, "%s - TIOCMIWAIT\n", __func__);
- cprev = tport->tp_icount;
- while (1) {
- interruptible_sleep_on(&tport->tp_msr_wait);
- if (signal_pending(current))
- return -ERESTARTSYS;
- cnow = tport->tp_icount;
- if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
- cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
- return -EIO; /* no change => error */
- if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
- ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
- ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) ||
- ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)))
- return 0;
- cprev = cnow;
- }
- break;
}
return -ENOIOCTLCMD;
}
@@ -1016,8 +973,6 @@ static void ti_break(struct tty_struct *tty, int break_state)
if (tport == NULL)
return;
- ti_drain(tport, (tport->tp_closing_wait*HZ)/100, 0);
-
status = ti_write_byte(port, tport->tp_tdev,
tport->tp_uart_base_addr + TI_UART_OFFSET_LCR,
TI_LCR_BREAK, break_state == -1 ? TI_LCR_BREAK : 0);
@@ -1154,7 +1109,7 @@ static void ti_bulk_in_callback(struct urb *urb)
else
ti_recv(port, urb->transfer_buffer, urb->actual_length);
spin_lock(&tport->tp_lock);
- tport->tp_icount.rx += urb->actual_length;
+ port->icount.rx += urb->actual_length;
spin_unlock(&tport->tp_lock);
}
@@ -1227,7 +1182,6 @@ static void ti_send(struct ti_port *tport)
{
int count, result;
struct usb_serial_port *port = tport->tp_port;
- struct tty_struct *tty = tty_port_tty_get(&port->port); /* FIXME */
unsigned long flags;
spin_lock_irqsave(&tport->tp_lock, flags);
@@ -1263,19 +1217,17 @@ static void ti_send(struct ti_port *tport)
/* TODO: reschedule ti_send */
} else {
spin_lock_irqsave(&tport->tp_lock, flags);
- tport->tp_icount.tx += count;
+ port->icount.tx += count;
spin_unlock_irqrestore(&tport->tp_lock, flags);
}
/* more room in the buffer for new writes, wakeup */
- if (tty)
- tty_wakeup(tty);
- tty_kref_put(tty);
+ tty_port_tty_wakeup(&port->port);
+
wake_up_interruptible(&tport->tp_write_wait);
return;
unlock:
spin_unlock_irqrestore(&tport->tp_lock, flags);
- tty_kref_put(tty);
return;
}
@@ -1298,7 +1250,7 @@ static int ti_set_mcr(struct ti_port *tport, unsigned int mcr)
}
-static int ti_get_lsr(struct ti_port *tport)
+static int ti_get_lsr(struct ti_port *tport, u8 *lsr)
{
int size, status;
struct ti_device *tdev = tport->tp_tdev;
@@ -1324,7 +1276,7 @@ static int ti_get_lsr(struct ti_port *tport)
dev_dbg(&port->dev, "%s - lsr 0x%02X\n", __func__, data->bLSR);
- tport->tp_lsr = data->bLSR;
+ *lsr = data->bLSR;
free_data:
kfree(data);
@@ -1337,10 +1289,15 @@ static int ti_get_serial_info(struct ti_port *tport,
{
struct usb_serial_port *port = tport->tp_port;
struct serial_struct ret_serial;
+ unsigned cwait;
if (!ret_arg)
return -EFAULT;
+ cwait = port->port.closing_wait;
+ if (cwait != ASYNC_CLOSING_WAIT_NONE)
+ cwait = jiffies_to_msecs(cwait) / 10;
+
memset(&ret_serial, 0, sizeof(ret_serial));
ret_serial.type = PORT_16550A;
@@ -1349,7 +1306,7 @@ static int ti_get_serial_info(struct ti_port *tport,
ret_serial.flags = tport->tp_flags;
ret_serial.xmit_fifo_size = TI_WRITE_BUF_SIZE;
ret_serial.baud_base = tport->tp_tdev->td_is_3410 ? 921600 : 460800;
- ret_serial.closing_wait = tport->tp_closing_wait;
+ ret_serial.closing_wait = cwait;
if (copy_to_user(ret_arg, &ret_serial, sizeof(*ret_arg)))
return -EFAULT;
@@ -1362,12 +1319,17 @@ static int ti_set_serial_info(struct tty_struct *tty, struct ti_port *tport,
struct serial_struct __user *new_arg)
{
struct serial_struct new_serial;
+ unsigned cwait;
if (copy_from_user(&new_serial, new_arg, sizeof(new_serial)))
return -EFAULT;
+ cwait = new_serial.closing_wait;
+ if (cwait != ASYNC_CLOSING_WAIT_NONE)
+ cwait = msecs_to_jiffies(10 * new_serial.closing_wait);
+
tport->tp_flags = new_serial.flags & TI_SET_SERIAL_FLAGS;
- tport->tp_closing_wait = new_serial.closing_wait;
+ tport->tp_port->port.closing_wait = cwait;
return 0;
}
@@ -1383,7 +1345,7 @@ static void ti_handle_new_msr(struct ti_port *tport, __u8 msr)
if (msr & TI_MSR_DELTA_MASK) {
spin_lock_irqsave(&tport->tp_lock, flags);
- icount = &tport->tp_icount;
+ icount = &tport->tp_port->icount;
if (msr & TI_MSR_DELTA_CTS)
icount->cts++;
if (msr & TI_MSR_DELTA_DSR)
@@ -1392,7 +1354,7 @@ static void ti_handle_new_msr(struct ti_port *tport, __u8 msr)
icount->dcd++;
if (msr & TI_MSR_DELTA_RI)
icount->rng++;
- wake_up_interruptible(&tport->tp_msr_wait);
+ wake_up_interruptible(&tport->tp_port->port.delta_msr_wait);
spin_unlock_irqrestore(&tport->tp_lock, flags);
}
@@ -1412,56 +1374,6 @@ static void ti_handle_new_msr(struct ti_port *tport, __u8 msr)
}
-static void ti_drain(struct ti_port *tport, unsigned long timeout, int flush)
-{
- struct ti_device *tdev = tport->tp_tdev;
- struct usb_serial_port *port = tport->tp_port;
- wait_queue_t wait;
-
- spin_lock_irq(&tport->tp_lock);
-
- /* wait for data to drain from the buffer */
- tdev->td_urb_error = 0;
- init_waitqueue_entry(&wait, current);
- add_wait_queue(&tport->tp_write_wait, &wait);
- for (;;) {
- set_current_state(TASK_INTERRUPTIBLE);
- if (kfifo_len(&tport->write_fifo) == 0
- || timeout == 0 || signal_pending(current)
- || tdev->td_urb_error
- || port->serial->disconnected) /* disconnect */
- break;
- spin_unlock_irq(&tport->tp_lock);
- timeout = schedule_timeout(timeout);
- spin_lock_irq(&tport->tp_lock);
- }
- set_current_state(TASK_RUNNING);
- remove_wait_queue(&tport->tp_write_wait, &wait);
-
- /* flush any remaining data in the buffer */
- if (flush)
- kfifo_reset_out(&tport->write_fifo);
-
- spin_unlock_irq(&tport->tp_lock);
-
- mutex_lock(&port->serial->disc_mutex);
- /* wait for data to drain from the device */
- /* wait for empty tx register, plus 20 ms */
- timeout += jiffies;
- tport->tp_lsr &= ~TI_LSR_TX_EMPTY;
- while ((long)(jiffies - timeout) < 0 && !signal_pending(current)
- && !(tport->tp_lsr&TI_LSR_TX_EMPTY) && !tdev->td_urb_error
- && !port->serial->disconnected) {
- if (ti_get_lsr(tport))
- break;
- mutex_unlock(&port->serial->disc_mutex);
- msleep_interruptible(20);
- mutex_lock(&port->serial->disc_mutex);
- }
- mutex_unlock(&port->serial->disc_mutex);
-}
-
-
static void ti_stop_read(struct ti_port *tport, struct tty_struct *tty)
{
unsigned long flags;
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index a19ed74d770..cf75beb1251 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -1,6 +1,7 @@
/*
* USB Serial Converter driver
*
+ * Copyright (C) 2009 - 2013 Johan Hovold (jhovold@gmail.com)
* Copyright (C) 1999 - 2012 Greg Kroah-Hartman (greg@kroah.com)
* Copyright (C) 2000 Peter Berger (pberger@brimson.com)
* Copyright (C) 2000 Al Borchers (borchers@steinerpoint.com)
@@ -14,7 +15,6 @@
*
* See Documentation/usb/usb-serial.txt for more information on using this
* driver
- *
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
@@ -49,7 +49,6 @@
drivers depend on it.
*/
-/* initially all NULL */
static struct usb_serial *serial_table[SERIAL_TTY_MINORS];
static DEFINE_MUTEX(table_lock);
static LIST_HEAD(usb_serial_driver_list);
@@ -139,7 +138,7 @@ static void destroy_serial(struct kref *kref)
if (serial->minor != SERIAL_TTY_NO_MINOR)
return_serial(serial);
- if (serial->attached)
+ if (serial->attached && serial->type->release)
serial->type->release(serial);
/* Now that nothing is using the ports, they can be freed */
@@ -151,6 +150,7 @@ static void destroy_serial(struct kref *kref)
}
}
+ usb_put_intf(serial->interface);
usb_put_dev(serial->dev);
kfree(serial);
}
@@ -224,7 +224,7 @@ static int serial_install(struct tty_driver *driver, struct tty_struct *tty)
return retval;
}
-static int serial_activate(struct tty_port *tport, struct tty_struct *tty)
+static int serial_port_activate(struct tty_port *tport, struct tty_struct *tty)
{
struct usb_serial_port *port =
container_of(tport, struct usb_serial_port, port);
@@ -248,30 +248,27 @@ static int serial_open(struct tty_struct *tty, struct file *filp)
{
struct usb_serial_port *port = tty->driver_data;
- dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number);
+ dev_dbg(tty->dev, "%s\n", __func__);
+
return tty_port_open(&port->port, tty, filp);
}
/**
- * serial_down - shut down hardware
+ * serial_port_shutdown - shut down hardware
* @tport: tty port to shut down
*
- * Shut down a USB serial port unless it is the console. We never
- * shut down the console hardware as it will always be in use. Serialized
- * against activate by the tport mutex and kept to matching open/close pairs
+ * Shut down a USB serial port. Serialized against activate by the
+ * tport mutex and kept to matching open/close pairs
* of calls by the ASYNCB_INITIALIZED flag.
+ *
+ * Not called if tty is console.
*/
-static void serial_down(struct tty_port *tport)
+static void serial_port_shutdown(struct tty_port *tport)
{
struct usb_serial_port *port =
container_of(tport, struct usb_serial_port, port);
struct usb_serial_driver *drv = port->serial->type;
- /*
- * The console is magical. Do not hang up the console hardware
- * or there will be tears.
- */
- if (port->port.console)
- return;
+
if (drv->close)
drv->close(port);
}
@@ -280,7 +277,8 @@ static void serial_hangup(struct tty_struct *tty)
{
struct usb_serial_port *port = tty->driver_data;
- dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number);
+ dev_dbg(tty->dev, "%s\n", __func__);
+
tty_port_hangup(&port->port);
}
@@ -288,7 +286,8 @@ static void serial_close(struct tty_struct *tty, struct file *filp)
{
struct usb_serial_port *port = tty->driver_data;
- dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number);
+ dev_dbg(tty->dev, "%s\n", __func__);
+
tty_port_close(&port->port, tty, filp);
}
@@ -307,14 +306,14 @@ static void serial_cleanup(struct tty_struct *tty)
struct usb_serial *serial;
struct module *owner;
+ dev_dbg(tty->dev, "%s\n", __func__);
+
/* The console is magical. Do not hang up the console hardware
* or there will be tears.
*/
if (port->port.console)
return;
- dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number);
-
tty->driver_data = NULL;
serial = port->serial;
@@ -338,10 +337,8 @@ static int serial_write(struct tty_struct *tty, const unsigned char *buf,
if (port->serial->dev->state == USB_STATE_NOTATTACHED)
goto exit;
- dev_dbg(tty->dev, "%s - port %d, %d byte(s)\n", __func__,
- port->number, count);
+ dev_dbg(tty->dev, "%s - %d byte(s)\n", __func__, count);
- /* pass on to the driver specific version of this function */
retval = port->serial->type->write(tty, port, buf, count);
if (retval < 0)
retval = usb_translate_errors(retval);
@@ -353,8 +350,8 @@ static int serial_write_room(struct tty_struct *tty)
{
struct usb_serial_port *port = tty->driver_data;
- dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number);
- /* pass on to the driver specific version of this function */
+ dev_dbg(tty->dev, "%s\n", __func__);
+
return port->serial->type->write_room(tty);
}
@@ -364,7 +361,7 @@ static int serial_chars_in_buffer(struct tty_struct *tty)
struct usb_serial *serial = port->serial;
int count = 0;
- dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number);
+ dev_dbg(tty->dev, "%s\n", __func__);
mutex_lock(&serial->disc_mutex);
/* if the device was unplugged then any remaining characters
@@ -382,9 +379,8 @@ static void serial_throttle(struct tty_struct *tty)
{
struct usb_serial_port *port = tty->driver_data;
- dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number);
+ dev_dbg(tty->dev, "%s\n", __func__);
- /* pass on to the driver specific version of this function */
if (port->serial->type->throttle)
port->serial->type->throttle(tty);
}
@@ -393,9 +389,8 @@ static void serial_unthrottle(struct tty_struct *tty)
{
struct usb_serial_port *port = tty->driver_data;
- dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number);
+ dev_dbg(tty->dev, "%s\n", __func__);
- /* pass on to the driver specific version of this function */
if (port->serial->type->unthrottle)
port->serial->type->unthrottle(tty);
}
@@ -406,15 +401,20 @@ static int serial_ioctl(struct tty_struct *tty,
struct usb_serial_port *port = tty->driver_data;
int retval = -ENODEV;
- dev_dbg(tty->dev, "%s - port %d, cmd 0x%.4x\n", __func__,
- port->number, cmd);
+ dev_dbg(tty->dev, "%s - cmd 0x%.4x\n", __func__, cmd);
+
+ switch (cmd) {
+ case TIOCMIWAIT:
+ if (port->serial->type->tiocmiwait)
+ retval = port->serial->type->tiocmiwait(tty, arg);
+ break;
+ default:
+ if (port->serial->type->ioctl)
+ retval = port->serial->type->ioctl(tty, cmd, arg);
+ else
+ retval = -ENOIOCTLCMD;
+ }
- /* pass on to the driver specific version of this function
- if it is available */
- if (port->serial->type->ioctl) {
- retval = port->serial->type->ioctl(tty, cmd, arg);
- } else
- retval = -ENOIOCTLCMD;
return retval;
}
@@ -422,10 +422,8 @@ static void serial_set_termios(struct tty_struct *tty, struct ktermios *old)
{
struct usb_serial_port *port = tty->driver_data;
- dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number);
+ dev_dbg(tty->dev, "%s\n", __func__);
- /* pass on to the driver specific version of this function
- if it is available */
if (port->serial->type->set_termios)
port->serial->type->set_termios(tty, port, old);
else
@@ -436,12 +434,11 @@ static int serial_break(struct tty_struct *tty, int break_state)
{
struct usb_serial_port *port = tty->driver_data;
- dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number);
+ dev_dbg(tty->dev, "%s\n", __func__);
- /* pass on to the driver specific version of this function
- if it is available */
if (port->serial->type->break_ctl)
port->serial->type->break_ctl(tty, break_state);
+
return 0;
}
@@ -495,7 +492,7 @@ static int serial_tiocmget(struct tty_struct *tty)
{
struct usb_serial_port *port = tty->driver_data;
- dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number);
+ dev_dbg(tty->dev, "%s\n", __func__);
if (port->serial->type->tiocmget)
return port->serial->type->tiocmget(tty);
@@ -507,7 +504,7 @@ static int serial_tiocmset(struct tty_struct *tty,
{
struct usb_serial_port *port = tty->driver_data;
- dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number);
+ dev_dbg(tty->dev, "%s\n", __func__);
if (port->serial->type->tiocmset)
return port->serial->type->tiocmset(tty, set, clear);
@@ -519,7 +516,7 @@ static int serial_get_icount(struct tty_struct *tty,
{
struct usb_serial_port *port = tty->driver_data;
- dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number);
+ dev_dbg(tty->dev, "%s\n", __func__);
if (port->serial->type->get_icount)
return port->serial->type->get_icount(tty, icount);
@@ -541,55 +538,43 @@ static void usb_serial_port_work(struct work_struct *work)
{
struct usb_serial_port *port =
container_of(work, struct usb_serial_port, work);
- struct tty_struct *tty;
- tty = tty_port_tty_get(&port->port);
- if (!tty)
- return;
+ tty_port_tty_wakeup(&port->port);
+}
+
+static void usb_serial_port_poison_urbs(struct usb_serial_port *port)
+{
+ int i;
- dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number);
+ for (i = 0; i < ARRAY_SIZE(port->read_urbs); ++i)
+ usb_poison_urb(port->read_urbs[i]);
+ for (i = 0; i < ARRAY_SIZE(port->write_urbs); ++i)
+ usb_poison_urb(port->write_urbs[i]);
- tty_wakeup(tty);
- tty_kref_put(tty);
+ usb_poison_urb(port->interrupt_in_urb);
+ usb_poison_urb(port->interrupt_out_urb);
}
-static void kill_traffic(struct usb_serial_port *port)
+static void usb_serial_port_unpoison_urbs(struct usb_serial_port *port)
{
int i;
for (i = 0; i < ARRAY_SIZE(port->read_urbs); ++i)
- usb_kill_urb(port->read_urbs[i]);
+ usb_unpoison_urb(port->read_urbs[i]);
for (i = 0; i < ARRAY_SIZE(port->write_urbs); ++i)
- usb_kill_urb(port->write_urbs[i]);
- /*
- * This is tricky.
- * Some drivers submit the read_urb in the
- * handler for the write_urb or vice versa
- * this order determines the order in which
- * usb_kill_urb() must be used to reliably
- * kill the URBs. As it is unknown here,
- * both orders must be used in turn.
- * The call below is not redundant.
- */
- usb_kill_urb(port->read_urb);
- usb_kill_urb(port->interrupt_in_urb);
- usb_kill_urb(port->interrupt_out_urb);
+ usb_unpoison_urb(port->write_urbs[i]);
+
+ usb_unpoison_urb(port->interrupt_in_urb);
+ usb_unpoison_urb(port->interrupt_out_urb);
}
-static void port_release(struct device *dev)
+static void usb_serial_port_release(struct device *dev)
{
struct usb_serial_port *port = to_usb_serial_port(dev);
int i;
dev_dbg(dev, "%s\n", __func__);
- /*
- * Stop all the traffic before cancelling the work, so that
- * nobody will restart it by calling usb_serial_port_softint.
- */
- kill_traffic(port);
- cancel_work_sync(&port->work);
-
usb_free_urb(port->interrupt_in_urb);
usb_free_urb(port->interrupt_out_urb);
for (i = 0; i < ARRAY_SIZE(port->read_urbs); ++i) {
@@ -614,13 +599,11 @@ static struct usb_serial *create_serial(struct usb_device *dev,
struct usb_serial *serial;
serial = kzalloc(sizeof(*serial), GFP_KERNEL);
- if (!serial) {
- dev_err(&dev->dev, "%s - out of memory\n", __func__);
+ if (!serial)
return NULL;
- }
serial->dev = usb_get_dev(dev);
serial->type = driver;
- serial->interface = interface;
+ serial->interface = usb_get_intf(interface);
kref_init(&serial->kref);
mutex_init(&serial->disc_mutex);
serial->minor = SERIAL_TTY_NO_MINOR;
@@ -680,7 +663,7 @@ static struct usb_serial_driver *search_serial_device(
return NULL;
}
-static int serial_carrier_raised(struct tty_port *port)
+static int serial_port_carrier_raised(struct tty_port *port)
{
struct usb_serial_port *p = container_of(port, struct usb_serial_port, port);
struct usb_serial_driver *drv = p->serial->type;
@@ -691,7 +674,7 @@ static int serial_carrier_raised(struct tty_port *port)
return 1;
}
-static void serial_dtr_rts(struct tty_port *port, int on)
+static void serial_port_dtr_rts(struct tty_port *port, int on)
{
struct usb_serial_port *p = container_of(port, struct usb_serial_port, port);
struct usb_serial *serial = p->serial;
@@ -711,10 +694,10 @@ static void serial_dtr_rts(struct tty_port *port, int on)
}
static const struct tty_port_operations serial_port_ops = {
- .carrier_raised = serial_carrier_raised,
- .dtr_rts = serial_dtr_rts,
- .activate = serial_activate,
- .shutdown = serial_down,
+ .carrier_raised = serial_port_carrier_raised,
+ .dtr_rts = serial_port_dtr_rts,
+ .activate = serial_port_activate,
+ .shutdown = serial_port_shutdown,
};
static int usb_serial_probe(struct usb_interface *interface,
@@ -761,7 +744,6 @@ static int usb_serial_probe(struct usb_interface *interface,
serial = create_serial(dev, interface, type);
if (!serial) {
module_put(type->driver.owner);
- dev_err(ddev, "%s - out of memory\n", __func__);
return -ENOMEM;
}
@@ -909,7 +891,7 @@ static int usb_serial_probe(struct usb_interface *interface,
port->dev.parent = &interface->dev;
port->dev.driver = NULL;
port->dev.bus = &usb_serial_bus_type;
- port->dev.release = &port_release;
+ port->dev.release = &usb_serial_port_release;
device_initialize(&port->dev);
}
@@ -925,16 +907,12 @@ static int usb_serial_probe(struct usb_interface *interface,
for (j = 0; j < ARRAY_SIZE(port->read_urbs); ++j) {
set_bit(j, &port->read_urbs_free);
port->read_urbs[j] = usb_alloc_urb(0, GFP_KERNEL);
- if (!port->read_urbs[j]) {
- dev_err(ddev, "No free urbs available\n");
+ if (!port->read_urbs[j])
goto probe_error;
- }
port->bulk_in_buffers[j] = kmalloc(buffer_size,
GFP_KERNEL);
- if (!port->bulk_in_buffers[j]) {
- dev_err(ddev, "Couldn't allocate bulk_in_buffer\n");
+ if (!port->bulk_in_buffers[j])
goto probe_error;
- }
usb_fill_bulk_urb(port->read_urbs[j], dev,
usb_rcvbulkpipe(dev,
endpoint->bEndpointAddress),
@@ -961,16 +939,12 @@ static int usb_serial_probe(struct usb_interface *interface,
for (j = 0; j < ARRAY_SIZE(port->write_urbs); ++j) {
set_bit(j, &port->write_urbs_free);
port->write_urbs[j] = usb_alloc_urb(0, GFP_KERNEL);
- if (!port->write_urbs[j]) {
- dev_err(ddev, "No free urbs available\n");
+ if (!port->write_urbs[j])
goto probe_error;
- }
port->bulk_out_buffers[j] = kmalloc(buffer_size,
GFP_KERNEL);
- if (!port->bulk_out_buffers[j]) {
- dev_err(ddev, "Couldn't allocate bulk_out_buffer\n");
+ if (!port->bulk_out_buffers[j])
goto probe_error;
- }
usb_fill_bulk_urb(port->write_urbs[j], dev,
usb_sndbulkpipe(dev,
endpoint->bEndpointAddress),
@@ -988,19 +962,15 @@ static int usb_serial_probe(struct usb_interface *interface,
endpoint = interrupt_in_endpoint[i];
port = serial->port[i];
port->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL);
- if (!port->interrupt_in_urb) {
- dev_err(ddev, "No free urbs available\n");
+ if (!port->interrupt_in_urb)
goto probe_error;
- }
buffer_size = usb_endpoint_maxp(endpoint);
port->interrupt_in_endpointAddress =
endpoint->bEndpointAddress;
port->interrupt_in_buffer = kmalloc(buffer_size,
GFP_KERNEL);
- if (!port->interrupt_in_buffer) {
- dev_err(ddev, "Couldn't allocate interrupt_in_buffer\n");
+ if (!port->interrupt_in_buffer)
goto probe_error;
- }
usb_fill_int_urb(port->interrupt_in_urb, dev,
usb_rcvintpipe(dev,
endpoint->bEndpointAddress),
@@ -1017,20 +987,16 @@ static int usb_serial_probe(struct usb_interface *interface,
endpoint = interrupt_out_endpoint[i];
port = serial->port[i];
port->interrupt_out_urb = usb_alloc_urb(0, GFP_KERNEL);
- if (!port->interrupt_out_urb) {
- dev_err(ddev, "No free urbs available\n");
+ if (!port->interrupt_out_urb)
goto probe_error;
- }
buffer_size = usb_endpoint_maxp(endpoint);
port->interrupt_out_size = buffer_size;
port->interrupt_out_endpointAddress =
endpoint->bEndpointAddress;
port->interrupt_out_buffer = kmalloc(buffer_size,
GFP_KERNEL);
- if (!port->interrupt_out_buffer) {
- dev_err(ddev, "Couldn't allocate interrupt_out_buffer\n");
+ if (!port->interrupt_out_buffer)
goto probe_error;
- }
usb_fill_int_urb(port->interrupt_out_urb, dev,
usb_sndintpipe(dev,
endpoint->bEndpointAddress),
@@ -1119,13 +1085,15 @@ static void usb_serial_disconnect(struct usb_interface *interface)
tty_vhangup(tty);
tty_kref_put(tty);
}
- kill_traffic(port);
+ usb_serial_port_poison_urbs(port);
+ wake_up_interruptible(&port->port.delta_msr_wait);
cancel_work_sync(&port->work);
if (device_is_registered(&port->dev))
device_del(&port->dev);
}
}
- serial->type->disconnect(serial);
+ if (serial->type->disconnect)
+ serial->type->disconnect(serial);
/* let the last holder of this object cause it to be cleaned up */
usb_serial_put(serial);
@@ -1140,6 +1108,11 @@ int usb_serial_suspend(struct usb_interface *intf, pm_message_t message)
serial->suspending = 1;
+ /*
+ * serial->type->suspend() MUST return 0 in system sleep context,
+ * otherwise, the resume callback has to recover device from
+ * previous suspend failure.
+ */
if (serial->type->suspend) {
r = serial->type->suspend(serial, message);
if (r < 0) {
@@ -1151,7 +1124,7 @@ int usb_serial_suspend(struct usb_interface *intf, pm_message_t message)
for (i = 0; i < serial->num_ports; ++i) {
port = serial->port[i];
if (port)
- kill_traffic(port);
+ usb_serial_port_poison_urbs(port);
}
err_out:
@@ -1159,11 +1132,25 @@ err_out:
}
EXPORT_SYMBOL(usb_serial_suspend);
+static void usb_serial_unpoison_port_urbs(struct usb_serial *serial)
+{
+ struct usb_serial_port *port;
+ int i;
+
+ for (i = 0; i < serial->num_ports; ++i) {
+ port = serial->port[i];
+ if (port)
+ usb_serial_port_unpoison_urbs(port);
+ }
+}
+
int usb_serial_resume(struct usb_interface *intf)
{
struct usb_serial *serial = usb_get_intfdata(intf);
int rv;
+ usb_serial_unpoison_port_urbs(serial);
+
serial->suspending = 0;
if (serial->type->resume)
rv = serial->type->resume(serial);
@@ -1179,6 +1166,8 @@ static int usb_serial_reset_resume(struct usb_interface *intf)
struct usb_serial *serial = usb_get_intfdata(intf);
int rv;
+ usb_serial_unpoison_port_urbs(serial);
+
serial->suspending = 0;
if (serial->type->reset_resume)
rv = serial->type->reset_resume(serial);
@@ -1315,12 +1304,12 @@ module_exit(usb_serial_exit);
do { \
if (!type->function) { \
type->function = usb_serial_generic_##function; \
- pr_debug("Had to override the " #function \
- " usb serial operation with the generic one.");\
- } \
+ pr_debug("%s: using generic " #function "\n", \
+ type->driver.name); \
+ } \
} while (0)
-static void fixup_generic(struct usb_serial_driver *device)
+static void usb_serial_operations_init(struct usb_serial_driver *device)
{
set_to_generic_if_null(device, open);
set_to_generic_if_null(device, write);
@@ -1329,8 +1318,6 @@ static void fixup_generic(struct usb_serial_driver *device)
set_to_generic_if_null(device, chars_in_buffer);
set_to_generic_if_null(device, read_bulk_callback);
set_to_generic_if_null(device, write_bulk_callback);
- set_to_generic_if_null(device, disconnect);
- set_to_generic_if_null(device, release);
set_to_generic_if_null(device, process_read_urb);
set_to_generic_if_null(device, prepare_write_buffer);
}
@@ -1342,8 +1329,6 @@ static int usb_serial_register(struct usb_serial_driver *driver)
if (usb_disabled())
return -ENODEV;
- fixup_generic(driver);
-
if (!driver->description)
driver->description = driver->driver.name;
if (!driver->usb_driver) {
@@ -1352,6 +1337,8 @@ static int usb_serial_register(struct usb_serial_driver *driver)
return -EINVAL;
}
+ usb_serial_operations_init(driver);
+
/* Add this device to our list of devices */
mutex_lock(&table_lock);
list_add(&driver->driver_list, &usb_serial_driver_list);
@@ -1469,7 +1456,6 @@ void usb_serial_deregister_drivers(struct usb_serial_driver *const serial_driver
}
EXPORT_SYMBOL_GPL(usb_serial_deregister_drivers);
-/* Module information */
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
diff --git a/drivers/usb/serial/usb_wwan.c b/drivers/usb/serial/usb_wwan.c
index 571965aa1cc..ece326ef63a 100644
--- a/drivers/usb/serial/usb_wwan.c
+++ b/drivers/usb/serial/usb_wwan.c
@@ -421,20 +421,19 @@ void usb_wwan_close(struct usb_serial_port *port)
portdata = usb_get_serial_port_data(port);
- if (serial->dev) {
- /* Stop reading/writing urbs */
- spin_lock_irq(&intfdata->susp_lock);
- portdata->opened = 0;
- spin_unlock_irq(&intfdata->susp_lock);
+ /* Stop reading/writing urbs */
+ spin_lock_irq(&intfdata->susp_lock);
+ portdata->opened = 0;
+ spin_unlock_irq(&intfdata->susp_lock);
- for (i = 0; i < N_IN_URB; i++)
- usb_kill_urb(portdata->in_urbs[i]);
- for (i = 0; i < N_OUT_URB; i++)
- usb_kill_urb(portdata->out_urbs[i]);
- /* balancing - important as an error cannot be handled*/
- usb_autopm_get_interface_no_resume(serial->interface);
- serial->interface->needs_remote_wakeup = 0;
- }
+ for (i = 0; i < N_IN_URB; i++)
+ usb_kill_urb(portdata->in_urbs[i]);
+ for (i = 0; i < N_OUT_URB; i++)
+ usb_kill_urb(portdata->out_urbs[i]);
+
+ /* balancing - important as an error cannot be handled*/
+ usb_autopm_get_interface_no_resume(serial->interface);
+ serial->interface->needs_remote_wakeup = 0;
}
EXPORT_SYMBOL(usb_wwan_close);
diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c
index 1129aa73c23..7573ec8a084 100644
--- a/drivers/usb/serial/visor.c
+++ b/drivers/usb/serial/visor.c
@@ -257,24 +257,18 @@ static void visor_close(struct usb_serial_port *port)
{
unsigned char *transfer_buffer;
- /* shutdown our urbs */
usb_serial_generic_close(port);
usb_kill_urb(port->interrupt_in_urb);
- mutex_lock(&port->serial->disc_mutex);
- if (!port->serial->disconnected) {
- /* Try to send shutdown message, unless the device is gone */
- transfer_buffer = kmalloc(0x12, GFP_KERNEL);
- if (transfer_buffer) {
- usb_control_msg(port->serial->dev,
+ transfer_buffer = kmalloc(0x12, GFP_KERNEL);
+ if (!transfer_buffer)
+ return;
+ usb_control_msg(port->serial->dev,
usb_rcvctrlpipe(port->serial->dev, 0),
VISOR_CLOSE_NOTIFICATION, 0xc2,
0x0000, 0x0000,
transfer_buffer, 0x12, 300);
- kfree(transfer_buffer);
- }
- }
- mutex_unlock(&port->serial->disc_mutex);
+ kfree(transfer_buffer);
}
static void visor_read_int_callback(struct urb *urb)
diff --git a/drivers/usb/serial/wishbone-serial.c b/drivers/usb/serial/wishbone-serial.c
new file mode 100644
index 00000000000..100573c6f19
--- /dev/null
+++ b/drivers/usb/serial/wishbone-serial.c
@@ -0,0 +1,95 @@
+/*
+ * USB Wishbone-Serial adapter driver
+ *
+ * Copyright (C) 2013 Wesley W. Terpstra <w.terpstra@gsi.de>
+ * Copyright (C) 2013 GSI Helmholtz Centre for Heavy Ion Research GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/tty.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/usb/serial.h>
+#include <linux/uaccess.h>
+
+#define GSI_VENDOR_OPENCLOSE 0xB0
+
+static const struct usb_device_id id_table[] = {
+ { USB_DEVICE_AND_INTERFACE_INFO(0x1D50, 0x6062, 0xFF, 0xFF, 0xFF) },
+ { },
+};
+MODULE_DEVICE_TABLE(usb, id_table);
+
+/*
+ * Etherbone must be told that a new stream has begun before data arrives.
+ * This is necessary to restart the negotiation of Wishbone bus parameters.
+ * Similarly, when the stream ends, Etherbone must be told so that the cycle
+ * line can be driven low in the case that userspace failed to do so.
+ */
+static int usb_gsi_openclose(struct usb_serial_port *port, int value)
+{
+ struct usb_device *dev = port->serial->dev;
+
+ return usb_control_msg(
+ dev,
+ usb_sndctrlpipe(dev, 0), /* Send to EP0OUT */
+ GSI_VENDOR_OPENCLOSE,
+ USB_DIR_OUT|USB_TYPE_VENDOR|USB_RECIP_INTERFACE,
+ value, /* wValue = device is open(1) or closed(0) */
+ port->serial->interface->cur_altsetting->desc.bInterfaceNumber,
+ NULL, 0, /* There is no data stage */
+ 5000); /* Timeout till operation fails */
+}
+
+static int wishbone_serial_open(struct tty_struct *tty,
+ struct usb_serial_port *port)
+{
+ int retval;
+
+ retval = usb_gsi_openclose(port, 1);
+ if (retval) {
+ dev_err(&port->serial->dev->dev,
+ "Could not mark device as open (%d)\n",
+ retval);
+ return retval;
+ }
+
+ retval = usb_serial_generic_open(tty, port);
+ if (retval)
+ usb_gsi_openclose(port, 0);
+
+ return retval;
+}
+
+static void wishbone_serial_close(struct usb_serial_port *port)
+{
+ usb_serial_generic_close(port);
+ usb_gsi_openclose(port, 0);
+}
+
+static struct usb_serial_driver wishbone_serial_device = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "wishbone_serial",
+ },
+ .id_table = id_table,
+ .num_ports = 1,
+ .open = &wishbone_serial_open,
+ .close = &wishbone_serial_close,
+};
+
+static struct usb_serial_driver * const serial_drivers[] = {
+ &wishbone_serial_device, NULL
+};
+
+module_usb_serial_driver(serial_drivers, id_table);
+
+MODULE_AUTHOR("Wesley W. Terpstra <w.terpstra@gsi.de>");
+MODULE_DESCRIPTION("USB Wishbone-Serial adapter");
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig
index eab04a6b5fb..8470e1b114f 100644
--- a/drivers/usb/storage/Kconfig
+++ b/drivers/usb/storage/Kconfig
@@ -4,11 +4,10 @@
comment "NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may"
comment "also be needed; see USB_STORAGE Help for more info"
- depends on USB
config USB_STORAGE
tristate "USB Mass Storage support"
- depends on USB && SCSI
+ depends on SCSI
---help---
Say Y here if you want to connect USB mass storage devices to your
computer's USB port. This is the driver you need for USB
@@ -188,7 +187,7 @@ config USB_STORAGE_CYPRESS_ATACB
config USB_STORAGE_ENE_UB6250
tristate "USB ENE card reader support"
- depends on USB && SCSI
+ depends on SCSI
depends on USB_STORAGE
---help---
Say Y here if you wish to control a ENE SD/MS Card reader.
@@ -203,7 +202,7 @@ config USB_STORAGE_ENE_UB6250
config USB_UAS
tristate "USB Attached SCSI"
- depends on USB && SCSI && BROKEN
+ depends on SCSI && BROKEN
help
The USB Attached SCSI protocol is supported by some USB
storage devices. It permits higher performance by supporting
diff --git a/drivers/usb/storage/alauda.c b/drivers/usb/storage/alauda.c
index be5564cc8e0..77a2ddfe648 100644
--- a/drivers/usb/storage/alauda.c
+++ b/drivers/usb/storage/alauda.c
@@ -326,8 +326,7 @@ static int alauda_get_media_status(struct us_data *us, unsigned char *data)
rc = usb_stor_ctrl_transfer(us, us->recv_ctrl_pipe,
command, 0xc0, 0, 1, data, 2);
- US_DEBUGP("alauda_get_media_status: Media status %02X %02X\n",
- data[0], data[1]);
+ usb_stor_dbg(us, "Media status %02X %02X\n", data[0], data[1]);
return rc;
}
@@ -402,7 +401,7 @@ static int alauda_init_media(struct us_data *us)
ready = 1;
}
- US_DEBUGP("alauda_init_media: We are ready for action!\n");
+ usb_stor_dbg(us, "We are ready for action!\n");
if (alauda_ack_media(us) != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
@@ -413,15 +412,15 @@ static int alauda_init_media(struct us_data *us)
return USB_STOR_TRANSPORT_ERROR;
if (data[0] != 0x14) {
- US_DEBUGP("alauda_init_media: Media not ready after ack\n");
+ usb_stor_dbg(us, "Media not ready after ack\n");
return USB_STOR_TRANSPORT_ERROR;
}
if (alauda_get_media_signature(us, data) != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
- US_DEBUGP("alauda_init_media: Media signature: %02X %02X %02X %02X\n",
- data[0], data[1], data[2], data[3]);
+ usb_stor_dbg(us, "Media signature: %02X %02X %02X %02X\n",
+ data[0], data[1], data[2], data[3]);
media_info = alauda_card_find_id(data[1]);
if (media_info == NULL) {
printk(KERN_WARNING
@@ -432,8 +431,8 @@ static int alauda_init_media(struct us_data *us)
}
MEDIA_INFO(us).capacity = 1 << media_info->chipshift;
- US_DEBUGP("Found media with capacity: %ldMB\n",
- MEDIA_INFO(us).capacity >> 20);
+ usb_stor_dbg(us, "Found media with capacity: %ldMB\n",
+ MEDIA_INFO(us).capacity >> 20);
MEDIA_INFO(us).pageshift = media_info->pageshift;
MEDIA_INFO(us).blockshift = media_info->blockshift;
@@ -472,7 +471,7 @@ static int alauda_check_media(struct us_data *us)
/* Check for no media or door open */
if ((status[0] & 0x80) || ((status[0] & 0x1F) == 0x10)
|| ((status[1] & 0x01) == 0)) {
- US_DEBUGP("alauda_check_media: No media, or door open\n");
+ usb_stor_dbg(us, "No media, or door open\n");
alauda_free_maps(&MEDIA_INFO(us));
info->sense_key = 0x02;
info->sense_asc = 0x3A;
@@ -482,7 +481,7 @@ static int alauda_check_media(struct us_data *us)
/* Check for media change */
if (status[0] & 0x08) {
- US_DEBUGP("alauda_check_media: Media change detected\n");
+ usb_stor_dbg(us, "Media change detected\n");
alauda_free_maps(&MEDIA_INFO(us));
alauda_init_media(us);
@@ -518,7 +517,7 @@ static int alauda_check_status2(struct us_data *us)
if (rc != USB_STOR_XFER_GOOD)
return rc;
- US_DEBUGP("alauda_check_status2: %02X %02X %02X\n", data[0], data[1], data[2]);
+ usb_stor_dbg(us, "%02X %02X %02X\n", data[0], data[1], data[2]);
if (data[0] & ALAUDA_STATUS_ERROR)
return USB_STOR_XFER_ERROR;
@@ -584,7 +583,7 @@ static int alauda_read_map(struct us_data *us, unsigned int zone)
goto error;
}
- US_DEBUGP("alauda_read_map: Mapping blocks for zone %d\n", zone);
+ usb_stor_dbg(us, "Mapping blocks for zone %d\n", zone);
/* 1024 PBA's per zone */
for (i = 0; i < zonesize; i++)
@@ -604,7 +603,7 @@ static int alauda_read_map(struct us_data *us, unsigned int zone)
if (data[j] != 0)
goto nonz;
pba_to_lba[i] = UNUSABLE;
- US_DEBUGP("alauda_read_map: PBA %d has no logical mapping\n", blocknum);
+ usb_stor_dbg(us, "PBA %d has no logical mapping\n", blocknum);
continue;
nonz:
@@ -617,19 +616,18 @@ static int alauda_read_map(struct us_data *us, unsigned int zone)
nonff:
/* normal PBAs start with six FFs */
if (j < 6) {
- US_DEBUGP("alauda_read_map: PBA %d has no logical mapping: "
- "reserved area = %02X%02X%02X%02X "
- "data status %02X block status %02X\n",
- blocknum, data[0], data[1], data[2], data[3],
- data[4], data[5]);
+ usb_stor_dbg(us, "PBA %d has no logical mapping: reserved area = %02X%02X%02X%02X data status %02X block status %02X\n",
+ blocknum,
+ data[0], data[1], data[2], data[3],
+ data[4], data[5]);
pba_to_lba[i] = UNUSABLE;
continue;
}
if ((data[6] >> 4) != 0x01) {
- US_DEBUGP("alauda_read_map: PBA %d has invalid address "
- "field %02X%02X/%02X%02X\n",
- blocknum, data[6], data[7], data[11], data[12]);
+ usb_stor_dbg(us, "PBA %d has invalid address field %02X%02X/%02X%02X\n",
+ blocknum, data[6], data[7],
+ data[11], data[12]);
pba_to_lba[i] = UNUSABLE;
continue;
}
@@ -711,7 +709,7 @@ static int alauda_erase_block(struct us_data *us, u16 pba)
};
unsigned char buf[2];
- US_DEBUGP("alauda_erase_block: Erasing PBA %d\n", pba);
+ usb_stor_dbg(us, "Erasing PBA %d\n", pba);
rc = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,
command, 9, NULL);
@@ -723,8 +721,7 @@ static int alauda_erase_block(struct us_data *us, u16 pba)
if (rc != USB_STOR_XFER_GOOD)
return rc;
- US_DEBUGP("alauda_erase_block: Erase result: %02X %02X\n",
- buf[0], buf[1]);
+ usb_stor_dbg(us, "Erase result: %02X %02X\n", buf[0], buf[1]);
return rc;
}
@@ -741,8 +738,7 @@ static int alauda_read_block_raw(struct us_data *us, u16 pba,
PBA_ZONE(pba), 0, PBA_LO(pba) + page, pages, 0, MEDIA_PORT(us)
};
- US_DEBUGP("alauda_read_block: pba %d page %d count %d\n",
- pba, page, pages);
+ usb_stor_dbg(us, "pba %d page %d count %d\n", pba, page, pages);
rc = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,
command, 9, NULL);
@@ -793,7 +789,7 @@ static int alauda_write_block(struct us_data *us, u16 pba, unsigned char *data)
PBA_ZONE(pba), 0, PBA_LO(pba), 32, 0, MEDIA_PORT(us)
};
- US_DEBUGP("alauda_write_block: pba %d\n", pba);
+ usb_stor_dbg(us, "pba %d\n", pba);
rc = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,
command, 9, NULL);
@@ -866,14 +862,14 @@ static int alauda_write_lba(struct us_data *us, u16 lba,
cptr = bptr + pagesize;
nand_compute_ecc(bptr, ecc);
if (!nand_compare_ecc(cptr+13, ecc)) {
- US_DEBUGP("Warning: bad ecc in page %d- of pba %d\n",
- i, pba);
+ usb_stor_dbg(us, "Warning: bad ecc in page %d- of pba %d\n",
+ i, pba);
nand_store_ecc(cptr+13, ecc);
}
nand_compute_ecc(bptr + (pagesize / 2), ecc);
if (!nand_compare_ecc(cptr+8, ecc)) {
- US_DEBUGP("Warning: bad ecc in page %d+ of pba %d\n",
- i, pba);
+ usb_stor_dbg(us, "Warning: bad ecc in page %d+ of pba %d\n",
+ i, pba);
nand_store_ecc(cptr+8, ecc);
}
cptr[6] = cptr[11] = MSB_of(lbap);
@@ -900,8 +896,7 @@ static int alauda_write_lba(struct us_data *us, u16 lba,
new_pba_offset = new_pba - (zone * zonesize);
MEDIA_INFO(us).pba_to_lba[zone][new_pba_offset] = lba;
MEDIA_INFO(us).lba_to_pba[zone][lba_offset] = new_pba;
- US_DEBUGP("alauda_write_lba: Remapped LBA %d to PBA %d\n",
- lba, new_pba);
+ usb_stor_dbg(us, "Remapped LBA %d to PBA %d\n", lba, new_pba);
if (pba != UNDEF) {
unsigned int pba_offset = pba - (zone * zonesize);
@@ -964,8 +959,8 @@ static int alauda_read_data(struct us_data *us, unsigned long address,
/* Not overflowing capacity? */
if (lba >= max_lba) {
- US_DEBUGP("Error: Requested lba %u exceeds "
- "maximum %u\n", lba, max_lba);
+ usb_stor_dbg(us, "Error: Requested lba %u exceeds maximum %u\n",
+ lba, max_lba);
result = USB_STOR_TRANSPORT_ERROR;
break;
}
@@ -978,8 +973,8 @@ static int alauda_read_data(struct us_data *us, unsigned long address,
pba = MEDIA_INFO(us).lba_to_pba[zone][lba_offset];
if (pba == UNDEF) { /* this lba was never written */
- US_DEBUGP("Read %d zero pages (LBA %d) page %d\n",
- pages, lba, page);
+ usb_stor_dbg(us, "Read %d zero pages (LBA %d) page %d\n",
+ pages, lba, page);
/* This is not really an error. It just means
that the block has never been written.
@@ -988,9 +983,8 @@ static int alauda_read_data(struct us_data *us, unsigned long address,
memset(buffer, 0, len);
} else {
- US_DEBUGP("Read %d pages, from PBA %d"
- " (LBA %d) page %d\n",
- pages, pba, lba, page);
+ usb_stor_dbg(us, "Read %d pages, from PBA %d (LBA %d) page %d\n",
+ pages, pba, lba, page);
result = alauda_read_block(us, pba, page, pages, buffer);
if (result != USB_STOR_TRANSPORT_GOOD)
@@ -1066,8 +1060,8 @@ static int alauda_write_data(struct us_data *us, unsigned long address,
/* Not overflowing capacity? */
if (lba >= max_lba) {
- US_DEBUGP("alauda_write_data: Requested lba %u exceeds "
- "maximum %u\n", lba, max_lba);
+ usb_stor_dbg(us, "Requested lba %u exceeds maximum %u\n",
+ lba, max_lba);
result = USB_STOR_TRANSPORT_ERROR;
break;
}
@@ -1122,11 +1116,9 @@ static int init_alauda(struct us_data *us)
nand_init_ecc();
us->extra = kzalloc(sizeof(struct alauda_info), GFP_NOIO);
- if (!us->extra) {
- US_DEBUGP("init_alauda: Gah! Can't allocate storage for"
- "alauda info struct!\n");
+ if (!us->extra)
return USB_STOR_TRANSPORT_ERROR;
- }
+
info = (struct alauda_info *) us->extra;
us->extra_destructor = alauda_info_destructor;
@@ -1147,15 +1139,14 @@ static int alauda_transport(struct scsi_cmnd *srb, struct us_data *us)
};
if (srb->cmnd[0] == INQUIRY) {
- US_DEBUGP("alauda_transport: INQUIRY. "
- "Returning bogus response.\n");
+ usb_stor_dbg(us, "INQUIRY - Returning bogus response\n");
memcpy(ptr, inquiry_response, sizeof(inquiry_response));
fill_inquiry_response(us, ptr, 36);
return USB_STOR_TRANSPORT_GOOD;
}
if (srb->cmnd[0] == TEST_UNIT_READY) {
- US_DEBUGP("alauda_transport: TEST_UNIT_READY.\n");
+ usb_stor_dbg(us, "TEST_UNIT_READY\n");
return alauda_check_media(us);
}
@@ -1193,8 +1184,7 @@ static int alauda_transport(struct scsi_cmnd *srb, struct us_data *us)
page |= short_pack(srb->cmnd[5], srb->cmnd[4]);
pages = short_pack(srb->cmnd[8], srb->cmnd[7]);
- US_DEBUGP("alauda_transport: READ_10: page %d pagect %d\n",
- page, pages);
+ usb_stor_dbg(us, "READ_10: page %d pagect %d\n", page, pages);
return alauda_read_data(us, page, pages);
}
@@ -1211,14 +1201,13 @@ static int alauda_transport(struct scsi_cmnd *srb, struct us_data *us)
page |= short_pack(srb->cmnd[5], srb->cmnd[4]);
pages = short_pack(srb->cmnd[8], srb->cmnd[7]);
- US_DEBUGP("alauda_transport: WRITE_10: page %d pagect %d\n",
- page, pages);
+ usb_stor_dbg(us, "WRITE_10: page %d pagect %d\n", page, pages);
return alauda_write_data(us, page, pages);
}
if (srb->cmnd[0] == REQUEST_SENSE) {
- US_DEBUGP("alauda_transport: REQUEST_SENSE.\n");
+ usb_stor_dbg(us, "REQUEST_SENSE\n");
memset(ptr, 0, 18);
ptr[0] = 0xF0;
@@ -1237,8 +1226,8 @@ static int alauda_transport(struct scsi_cmnd *srb, struct us_data *us)
return USB_STOR_TRANSPORT_GOOD;
}
- US_DEBUGP("alauda_transport: Gah! Unknown command: %d (0x%x)\n",
- srb->cmnd[0], srb->cmnd[0]);
+ usb_stor_dbg(us, "Gah! Unknown command: %d (0x%x)\n",
+ srb->cmnd[0], srb->cmnd[0]);
info->sense_key = 0x05;
info->sense_asc = 0x20;
info->sense_ascq = 0x00;
diff --git a/drivers/usb/storage/cypress_atacb.c b/drivers/usb/storage/cypress_atacb.c
index 070b5c0ebbf..8514a2d82b7 100644
--- a/drivers/usb/storage/cypress_atacb.c
+++ b/drivers/usb/storage/cypress_atacb.c
@@ -159,7 +159,7 @@ static void cypress_atacb_passthrough(struct scsi_cmnd *srb, struct us_data *us)
if (srb->result == SAM_STAT_CHECK_CONDITION &&
memcmp(srb->sense_buffer, usb_stor_sense_invalidCDB,
sizeof(usb_stor_sense_invalidCDB)) == 0) {
- US_DEBUGP("cypress atacb not supported ???\n");
+ usb_stor_dbg(us, "cypress atacb not supported ???\n");
goto end;
}
@@ -248,14 +248,26 @@ static int cypress_probe(struct usb_interface *intf,
{
struct us_data *us;
int result;
+ struct usb_device *device;
result = usb_stor_probe1(&us, intf, id,
(id - cypress_usb_ids) + cypress_unusual_dev_list);
if (result)
return result;
- us->protocol_name = "Transparent SCSI with Cypress ATACB";
- us->proto_handler = cypress_atacb_passthrough;
+ /* Among CY7C68300 chips, the A revision does not support Cypress ATACB
+ * Filter out this revision from EEPROM default descriptor values
+ */
+ device = interface_to_usbdev(intf);
+ if (device->descriptor.iManufacturer != 0x38 ||
+ device->descriptor.iProduct != 0x4e ||
+ device->descriptor.iSerialNumber != 0x64) {
+ us->protocol_name = "Transparent SCSI with Cypress ATACB";
+ us->proto_handler = cypress_atacb_passthrough;
+ } else {
+ us->protocol_name = "Transparent SCSI";
+ us->proto_handler = usb_stor_transparent_scsi_command;
+ }
result = usb_stor_probe2(us);
return result;
diff --git a/drivers/usb/storage/datafab.c b/drivers/usb/storage/datafab.c
index 494fee5af41..7b17c216981 100644
--- a/drivers/usb/storage/datafab.c
+++ b/drivers/usb/storage/datafab.c
@@ -123,7 +123,7 @@ datafab_bulk_read(struct us_data *us, unsigned char *data, unsigned int len) {
if (len == 0)
return USB_STOR_XFER_GOOD;
- US_DEBUGP("datafab_bulk_read: len = %d\n", len);
+ usb_stor_dbg(us, "len = %d\n", len);
return usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
data, len, NULL);
}
@@ -134,7 +134,7 @@ datafab_bulk_write(struct us_data *us, unsigned char *data, unsigned int len) {
if (len == 0)
return USB_STOR_XFER_GOOD;
- US_DEBUGP("datafab_bulk_write: len = %d\n", len);
+ usb_stor_dbg(us, "len = %d\n", len);
return usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,
data, len, NULL);
}
@@ -300,9 +300,8 @@ static int datafab_write_data(struct us_data *us,
goto leave;
if (reply[0] != 0x50 && reply[1] != 0) {
- US_DEBUGP("datafab_write_data: Gah! "
- "write return code: %02x %02x\n",
- reply[0], reply[1]);
+ usb_stor_dbg(us, "Gah! write return code: %02x %02x\n",
+ reply[0], reply[1]);
result = USB_STOR_TRANSPORT_ERROR;
goto leave;
}
@@ -342,7 +341,7 @@ static int datafab_determine_lun(struct us_data *us,
if (!buf)
return USB_STOR_TRANSPORT_ERROR;
- US_DEBUGP("datafab_determine_lun: locating...\n");
+ usb_stor_dbg(us, "locating...\n");
// we'll try 3 times before giving up...
//
@@ -474,16 +473,16 @@ static int datafab_handle_mode_sense(struct us_data *us,
switch (pc) {
case 0x0:
- US_DEBUGP("datafab_handle_mode_sense: Current values\n");
+ usb_stor_dbg(us, "Current values\n");
break;
case 0x1:
- US_DEBUGP("datafab_handle_mode_sense: Changeable values\n");
+ usb_stor_dbg(us, "Changeable values\n");
break;
case 0x2:
- US_DEBUGP("datafab_handle_mode_sense: Default values\n");
+ usb_stor_dbg(us, "Default values\n");
break;
case 0x3:
- US_DEBUGP("datafab_handle_mode_sense: Saves values\n");
+ usb_stor_dbg(us, "Saves values\n");
break;
}
@@ -566,11 +565,9 @@ static int datafab_transport(struct scsi_cmnd *srb, struct us_data *us)
if (!us->extra) {
us->extra = kzalloc(sizeof(struct datafab_info), GFP_NOIO);
- if (!us->extra) {
- US_DEBUGP("datafab_transport: Gah! "
- "Can't allocate storage for Datafab info struct!\n");
+ if (!us->extra)
return USB_STOR_TRANSPORT_ERROR;
- }
+
us->extra_destructor = datafab_info_destructor;
((struct datafab_info *)us->extra)->lun = -1;
}
@@ -578,7 +575,7 @@ static int datafab_transport(struct scsi_cmnd *srb, struct us_data *us)
info = (struct datafab_info *) (us->extra);
if (srb->cmnd[0] == INQUIRY) {
- US_DEBUGP("datafab_transport: INQUIRY. Returning bogus response");
+ usb_stor_dbg(us, "INQUIRY - Returning bogus response\n");
memcpy(ptr, inquiry_reply, sizeof(inquiry_reply));
fill_inquiry_response(us, ptr, 36);
return USB_STOR_TRANSPORT_GOOD;
@@ -590,8 +587,8 @@ static int datafab_transport(struct scsi_cmnd *srb, struct us_data *us)
if (rc != USB_STOR_TRANSPORT_GOOD)
return rc;
- US_DEBUGP("datafab_transport: READ_CAPACITY: %ld sectors, %ld bytes per sector\n",
- info->sectors, info->ssize);
+ usb_stor_dbg(us, "READ_CAPACITY: %ld sectors, %ld bytes per sector\n",
+ info->sectors, info->ssize);
// build the reply
// we need the last sector, not the number of sectors
@@ -603,7 +600,7 @@ static int datafab_transport(struct scsi_cmnd *srb, struct us_data *us)
}
if (srb->cmnd[0] == MODE_SELECT_10) {
- US_DEBUGP("datafab_transport: Gah! MODE_SELECT_10.\n");
+ usb_stor_dbg(us, "Gah! MODE_SELECT_10\n");
return USB_STOR_TRANSPORT_ERROR;
}
@@ -615,7 +612,8 @@ static int datafab_transport(struct scsi_cmnd *srb, struct us_data *us)
blocks = ((u32)(srb->cmnd[7]) << 8) | ((u32)(srb->cmnd[8]));
- US_DEBUGP("datafab_transport: READ_10: read block 0x%04lx count %ld\n", block, blocks);
+ usb_stor_dbg(us, "READ_10: read block 0x%04lx count %ld\n",
+ block, blocks);
return datafab_read_data(us, info, block, blocks);
}
@@ -628,7 +626,8 @@ static int datafab_transport(struct scsi_cmnd *srb, struct us_data *us)
blocks = ((u32)(srb->cmnd[6]) << 24) | ((u32)(srb->cmnd[7]) << 16) |
((u32)(srb->cmnd[8]) << 8) | ((u32)(srb->cmnd[9]));
- US_DEBUGP("datafab_transport: READ_12: read block 0x%04lx count %ld\n", block, blocks);
+ usb_stor_dbg(us, "READ_12: read block 0x%04lx count %ld\n",
+ block, blocks);
return datafab_read_data(us, info, block, blocks);
}
@@ -638,7 +637,8 @@ static int datafab_transport(struct scsi_cmnd *srb, struct us_data *us)
blocks = ((u32)(srb->cmnd[7]) << 8) | ((u32)(srb->cmnd[8]));
- US_DEBUGP("datafab_transport: WRITE_10: write block 0x%04lx count %ld\n", block, blocks);
+ usb_stor_dbg(us, "WRITE_10: write block 0x%04lx count %ld\n",
+ block, blocks);
return datafab_write_data(us, info, block, blocks);
}
@@ -651,17 +651,18 @@ static int datafab_transport(struct scsi_cmnd *srb, struct us_data *us)
blocks = ((u32)(srb->cmnd[6]) << 24) | ((u32)(srb->cmnd[7]) << 16) |
((u32)(srb->cmnd[8]) << 8) | ((u32)(srb->cmnd[9]));
- US_DEBUGP("datafab_transport: WRITE_12: write block 0x%04lx count %ld\n", block, blocks);
+ usb_stor_dbg(us, "WRITE_12: write block 0x%04lx count %ld\n",
+ block, blocks);
return datafab_write_data(us, info, block, blocks);
}
if (srb->cmnd[0] == TEST_UNIT_READY) {
- US_DEBUGP("datafab_transport: TEST_UNIT_READY.\n");
+ usb_stor_dbg(us, "TEST_UNIT_READY\n");
return datafab_id_device(us, info);
}
if (srb->cmnd[0] == REQUEST_SENSE) {
- US_DEBUGP("datafab_transport: REQUEST_SENSE. Returning faked response\n");
+ usb_stor_dbg(us, "REQUEST_SENSE - Returning faked response\n");
// this response is pretty bogus right now. eventually if necessary
// we can set the correct sense data. so far though it hasn't been
@@ -679,12 +680,12 @@ static int datafab_transport(struct scsi_cmnd *srb, struct us_data *us)
}
if (srb->cmnd[0] == MODE_SENSE) {
- US_DEBUGP("datafab_transport: MODE_SENSE_6 detected\n");
+ usb_stor_dbg(us, "MODE_SENSE_6 detected\n");
return datafab_handle_mode_sense(us, srb, 1);
}
if (srb->cmnd[0] == MODE_SENSE_10) {
- US_DEBUGP("datafab_transport: MODE_SENSE_10 detected\n");
+ usb_stor_dbg(us, "MODE_SENSE_10 detected\n");
return datafab_handle_mode_sense(us, srb, 0);
}
@@ -698,7 +699,7 @@ static int datafab_transport(struct scsi_cmnd *srb, struct us_data *us)
if (srb->cmnd[0] == START_STOP) {
/* this is used by sd.c'check_scsidisk_media_change to detect
media change */
- US_DEBUGP("datafab_transport: START_STOP.\n");
+ usb_stor_dbg(us, "START_STOP\n");
/* the first datafab_id_device after a media change returns
an error (determined experimentally) */
rc = datafab_id_device(us, info);
@@ -712,8 +713,8 @@ static int datafab_transport(struct scsi_cmnd *srb, struct us_data *us)
return rc;
}
- US_DEBUGP("datafab_transport: Gah! Unknown command: %d (0x%x)\n",
- srb->cmnd[0], srb->cmnd[0]);
+ usb_stor_dbg(us, "Gah! Unknown command: %d (0x%x)\n",
+ srb->cmnd[0], srb->cmnd[0]);
info->sense_key = 0x05;
info->sense_asc = 0x20;
info->sense_ascq = 0x00;
diff --git a/drivers/usb/storage/debug.c b/drivers/usb/storage/debug.c
index a2b5526c9fa..e08f64780e3 100644
--- a/drivers/usb/storage/debug.c
+++ b/drivers/usb/storage/debug.c
@@ -42,16 +42,19 @@
* 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#include <linux/device.h>
#include <linux/cdrom.h>
+#include <linux/export.h>
#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_dbg.h>
+#include "usb.h"
#include "debug.h"
#include "scsi.h"
-void usb_stor_show_command(struct scsi_cmnd *srb)
+void usb_stor_show_command(const struct us_data *us, struct scsi_cmnd *srb)
{
char *what = NULL;
int i;
@@ -149,18 +152,18 @@ void usb_stor_show_command(struct scsi_cmnd *srb)
case WRITE_LONG_2: what = "WRITE_LONG_2"; break;
default: what = "(unknown command)"; break;
}
- US_DEBUGP("Command %s (%d bytes)\n", what, srb->cmd_len);
- US_DEBUGP("");
+ usb_stor_dbg(us, "Command %s (%d bytes)\n", what, srb->cmd_len);
+ usb_stor_dbg(us, "bytes: ");
for (i = 0; i < srb->cmd_len && i < 16; i++)
US_DEBUGPX(" %02x", srb->cmnd[i]);
US_DEBUGPX("\n");
}
-void usb_stor_show_sense(
- unsigned char key,
- unsigned char asc,
- unsigned char ascq) {
-
+void usb_stor_show_sense(const struct us_data *us,
+ unsigned char key,
+ unsigned char asc,
+ unsigned char ascq)
+{
const char *what, *keystr;
keystr = scsi_sense_key_string(key);
@@ -171,7 +174,22 @@ void usb_stor_show_sense(
if (what == NULL)
what = "(unknown ASC/ASCQ)";
- US_DEBUGP("%s: ", keystr);
+ usb_stor_dbg(us, "%s: ", keystr);
US_DEBUGPX(what, ascq);
US_DEBUGPX("\n");
}
+
+int usb_stor_dbg(const struct us_data *us, const char *fmt, ...)
+{
+ va_list args;
+ int r;
+
+ va_start(args, fmt);
+
+ r = dev_vprintk_emit(7, &us->pusb_dev->dev, fmt, args);
+
+ va_end(args);
+
+ return r;
+}
+EXPORT_SYMBOL_GPL(usb_stor_dbg);
diff --git a/drivers/usb/storage/debug.h b/drivers/usb/storage/debug.h
index dbb985d5242..b1273f03e22 100644
--- a/drivers/usb/storage/debug.h
+++ b/drivers/usb/storage/debug.h
@@ -47,15 +47,22 @@
#define USB_STORAGE "usb-storage: "
#ifdef CONFIG_USB_STORAGE_DEBUG
-void usb_stor_show_command(struct scsi_cmnd *srb);
-void usb_stor_show_sense( unsigned char key,
- unsigned char asc, unsigned char ascq );
-#define US_DEBUGP(x...) printk( KERN_DEBUG USB_STORAGE x )
-#define US_DEBUGPX(x...) printk( x )
-#define US_DEBUG(x) x
+void usb_stor_show_command(const struct us_data *us, struct scsi_cmnd *srb);
+void usb_stor_show_sense(const struct us_data *us, unsigned char key,
+ unsigned char asc, unsigned char ascq);
+__printf(2, 3) int usb_stor_dbg(const struct us_data *us,
+ const char *fmt, ...);
+
+#define US_DEBUGPX(fmt, ...) printk(fmt, ##__VA_ARGS__)
+#define US_DEBUG(x) x
#else
-#define US_DEBUGP(x...)
-#define US_DEBUGPX(x...)
+__printf(2, 3)
+static inline int _usb_stor_dbg(const struct us_data *us,
+ const char *fmt, ...) {return 1;}
+#define usb_stor_dbg(us, fmt, ...) \
+ do { if (0) _usb_stor_dbg(us, fmt, ##__VA_ARGS__); } while (0)
+#define US_DEBUGPX(fmt, ...) \
+ do { if (0) printk(fmt, ##__VA_ARGS__); } while (0)
#define US_DEBUG(x)
#endif
diff --git a/drivers/usb/storage/ene_ub6250.c b/drivers/usb/storage/ene_ub6250.c
index 118b134a1da..1bfc9a6cab5 100644
--- a/drivers/usb/storage/ene_ub6250.c
+++ b/drivers/usb/storage/ene_ub6250.c
@@ -504,12 +504,12 @@ static int ene_send_scsi_cmd(struct us_data *us, u8 fDir, void *buf, int use_sg)
unsigned int cswlen = 0, partial = 0;
unsigned int transfer_length = bcb->DataTransferLength;
- /* US_DEBUGP("transport --- ene_send_scsi_cmd\n"); */
+ /* usb_stor_dbg(us, "transport --- ene_send_scsi_cmd\n"); */
/* send cmd to out endpoint */
result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,
bcb, US_BULK_CB_WRAP_LEN, NULL);
if (result != USB_STOR_XFER_GOOD) {
- US_DEBUGP("send cmd to out endpoint fail ---\n");
+ usb_stor_dbg(us, "send cmd to out endpoint fail ---\n");
return USB_STOR_TRANSPORT_ERROR;
}
@@ -529,7 +529,7 @@ static int ene_send_scsi_cmd(struct us_data *us, u8 fDir, void *buf, int use_sg)
transfer_length, 0, &partial);
}
if (result != USB_STOR_XFER_GOOD) {
- US_DEBUGP("data transfer fail ---\n");
+ usb_stor_dbg(us, "data transfer fail ---\n");
return USB_STOR_TRANSPORT_ERROR;
}
}
@@ -539,14 +539,14 @@ static int ene_send_scsi_cmd(struct us_data *us, u8 fDir, void *buf, int use_sg)
US_BULK_CS_WRAP_LEN, &cswlen);
if (result == USB_STOR_XFER_SHORT && cswlen == 0) {
- US_DEBUGP("Received 0-length CSW; retrying...\n");
+ usb_stor_dbg(us, "Received 0-length CSW; retrying...\n");
result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
bcs, US_BULK_CS_WRAP_LEN, &cswlen);
}
if (result == USB_STOR_XFER_STALLED) {
/* get the status again */
- US_DEBUGP("Attempting to get CSW (2nd try)...\n");
+ usb_stor_dbg(us, "Attempting to get CSW (2nd try)...\n");
result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
bcs, US_BULK_CS_WRAP_LEN, NULL);
}
@@ -626,7 +626,7 @@ static int sd_scsi_read_capacity(struct us_data *us, struct scsi_cmnd *srb)
struct scatterlist *sg = NULL;
struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
- US_DEBUGP("sd_scsi_read_capacity\n");
+ usb_stor_dbg(us, "sd_scsi_read_capacity\n");
if (info->SD_Status.HiCapacity) {
bl_len = 0x200;
if (info->SD_Status.IsMMC)
@@ -639,8 +639,8 @@ static int sd_scsi_read_capacity(struct us_data *us, struct scsi_cmnd *srb)
* (1 << (info->SD_C_SIZE_MULT + 2)) - 1;
}
info->bl_num = bl_num;
- US_DEBUGP("bl_len = %x\n", bl_len);
- US_DEBUGP("bl_num = %x\n", bl_num);
+ usb_stor_dbg(us, "bl_len = %x\n", bl_len);
+ usb_stor_dbg(us, "bl_num = %x\n", bl_num);
/*srb->request_bufflen = 8; */
buf[0] = (bl_num >> 24) & 0xff;
@@ -675,7 +675,7 @@ static int sd_scsi_read(struct us_data *us, struct scsi_cmnd *srb)
result = ene_load_bincode(us, SD_RW_PATTERN);
if (result != USB_STOR_XFER_GOOD) {
- US_DEBUGP("Load SD RW pattern Fail !!\n");
+ usb_stor_dbg(us, "Load SD RW pattern Fail !!\n");
return USB_STOR_TRANSPORT_ERROR;
}
@@ -715,7 +715,7 @@ static int sd_scsi_write(struct us_data *us, struct scsi_cmnd *srb)
result = ene_load_bincode(us, SD_RW_PATTERN);
if (result != USB_STOR_XFER_GOOD) {
- US_DEBUGP("Load SD RW pattern Fail !!\n");
+ usb_stor_dbg(us, "Load SD RW pattern Fail !!\n");
return USB_STOR_TRANSPORT_ERROR;
}
@@ -1493,7 +1493,7 @@ static int ms_scsi_read_capacity(struct us_data *us, struct scsi_cmnd *srb)
struct scatterlist *sg = NULL;
struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
- US_DEBUGP("ms_scsi_read_capacity\n");
+ usb_stor_dbg(us, "ms_scsi_read_capacity\n");
bl_len = 0x200;
if (info->MS_Status.IsMSPro)
bl_num = info->MSP_TotalBlock - 1;
@@ -1501,8 +1501,8 @@ static int ms_scsi_read_capacity(struct us_data *us, struct scsi_cmnd *srb)
bl_num = info->MS_Lib.NumberOfLogBlock * info->MS_Lib.blockSize * 2 - 1;
info->bl_num = bl_num;
- US_DEBUGP("bl_len = %x\n", bl_len);
- US_DEBUGP("bl_num = %x\n", bl_num);
+ usb_stor_dbg(us, "bl_len = %x\n", bl_len);
+ usb_stor_dbg(us, "bl_num = %x\n", bl_num);
/*srb->request_bufflen = 8; */
buf[0] = (bl_num >> 24) & 0xff;
@@ -1654,7 +1654,7 @@ static int ms_scsi_read(struct us_data *us, struct scsi_cmnd *srb)
if (info->MS_Status.IsMSPro) {
result = ene_load_bincode(us, MSP_RW_PATTERN);
if (result != USB_STOR_XFER_GOOD) {
- US_DEBUGP("Load MPS RW pattern Fail !!\n");
+ usb_stor_dbg(us, "Load MPS RW pattern Fail !!\n");
return USB_STOR_TRANSPORT_ERROR;
}
@@ -1854,7 +1854,7 @@ static int ene_get_card_status(struct us_data *us, u8 *buf)
u32 reg4b;
struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
- /*US_DEBUGP("transport --- ENE_ReadSDReg\n");*/
+ /*usb_stor_dbg(us, "transport --- ENE_ReadSDReg\n");*/
reg4b = *(u32 *)&buf[0x18];
info->SD_READ_BL_LEN = (u8)((reg4b >> 8) & 0x0f);
@@ -1894,45 +1894,44 @@ static int ene_load_bincode(struct us_data *us, unsigned char flag)
switch (flag) {
/* For SD */
case SD_INIT1_PATTERN:
- US_DEBUGP("SD_INIT1_PATTERN\n");
+ usb_stor_dbg(us, "SD_INIT1_PATTERN\n");
fw_name = SD_INIT1_FIRMWARE;
break;
case SD_INIT2_PATTERN:
- US_DEBUGP("SD_INIT2_PATTERN\n");
+ usb_stor_dbg(us, "SD_INIT2_PATTERN\n");
fw_name = SD_INIT2_FIRMWARE;
break;
case SD_RW_PATTERN:
- US_DEBUGP("SD_RW_PATTERN\n");
+ usb_stor_dbg(us, "SD_RW_PATTERN\n");
fw_name = SD_RW_FIRMWARE;
break;
/* For MS */
case MS_INIT_PATTERN:
- US_DEBUGP("MS_INIT_PATTERN\n");
+ usb_stor_dbg(us, "MS_INIT_PATTERN\n");
fw_name = MS_INIT_FIRMWARE;
break;
case MSP_RW_PATTERN:
- US_DEBUGP("MSP_RW_PATTERN\n");
+ usb_stor_dbg(us, "MSP_RW_PATTERN\n");
fw_name = MSP_RW_FIRMWARE;
break;
case MS_RW_PATTERN:
- US_DEBUGP("MS_RW_PATTERN\n");
+ usb_stor_dbg(us, "MS_RW_PATTERN\n");
fw_name = MS_RW_FIRMWARE;
break;
default:
- US_DEBUGP("----------- Unknown PATTERN ----------\n");
+ usb_stor_dbg(us, "----------- Unknown PATTERN ----------\n");
goto nofw;
}
err = request_firmware(&sd_fw, fw_name, &us->pusb_dev->dev);
if (err) {
- US_DEBUGP("load firmware %s failed\n", fw_name);
+ usb_stor_dbg(us, "load firmware %s failed\n", fw_name);
goto nofw;
}
buf = kmalloc(sd_fw->size, GFP_KERNEL);
- if (buf == NULL) {
- US_DEBUGP("Malloc memory for fireware failed!\n");
+ if (buf == NULL)
goto nofw;
- }
+
memcpy(buf, sd_fw->data, sd_fw->size);
memset(bcb, 0, sizeof(struct bulk_cb_wrap));
bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
@@ -2116,9 +2115,9 @@ static int ene_ms_init(struct us_data *us)
} else {
ms_card_init(us); /* Card is MS (to ms.c)*/
}
- US_DEBUGP("MS Init Code OK !!\n");
+ usb_stor_dbg(us, "MS Init Code OK !!\n");
} else {
- US_DEBUGP("MS Card Not Ready --- %x\n", buf[0]);
+ usb_stor_dbg(us, "MS Card Not Ready --- %x\n", buf[0]);
return USB_STOR_TRANSPORT_ERROR;
}
@@ -2132,11 +2131,11 @@ static int ene_sd_init(struct us_data *us)
struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
- US_DEBUGP("transport --- ENE_SDInit\n");
+ usb_stor_dbg(us, "transport --- ENE_SDInit\n");
/* SD Init Part-1 */
result = ene_load_bincode(us, SD_INIT1_PATTERN);
if (result != USB_STOR_XFER_GOOD) {
- US_DEBUGP("Load SD Init Code Part-1 Fail !!\n");
+ usb_stor_dbg(us, "Load SD Init Code Part-1 Fail !!\n");
return USB_STOR_TRANSPORT_ERROR;
}
@@ -2147,14 +2146,14 @@ static int ene_sd_init(struct us_data *us)
result = ene_send_scsi_cmd(us, FDIR_READ, NULL, 0);
if (result != USB_STOR_XFER_GOOD) {
- US_DEBUGP("Execution SD Init Code Fail !!\n");
+ usb_stor_dbg(us, "Execution SD Init Code Fail !!\n");
return USB_STOR_TRANSPORT_ERROR;
}
/* SD Init Part-2 */
result = ene_load_bincode(us, SD_INIT2_PATTERN);
if (result != USB_STOR_XFER_GOOD) {
- US_DEBUGP("Load SD Init Code Part-2 Fail !!\n");
+ usb_stor_dbg(us, "Load SD Init Code Part-2 Fail !!\n");
return USB_STOR_TRANSPORT_ERROR;
}
@@ -2166,21 +2165,23 @@ static int ene_sd_init(struct us_data *us)
result = ene_send_scsi_cmd(us, FDIR_READ, &buf, 0);
if (result != USB_STOR_XFER_GOOD) {
- US_DEBUGP("Execution SD Init Code Fail !!\n");
+ usb_stor_dbg(us, "Execution SD Init Code Fail !!\n");
return USB_STOR_TRANSPORT_ERROR;
}
info->SD_Status = *(struct SD_STATUS *)&buf[0];
if (info->SD_Status.Insert && info->SD_Status.Ready) {
+ struct SD_STATUS *s = &info->SD_Status;
+
ene_get_card_status(us, (unsigned char *)&buf);
- US_DEBUGP("Insert = %x\n", info->SD_Status.Insert);
- US_DEBUGP("Ready = %x\n", info->SD_Status.Ready);
- US_DEBUGP("IsMMC = %x\n", info->SD_Status.IsMMC);
- US_DEBUGP("HiCapacity = %x\n", info->SD_Status.HiCapacity);
- US_DEBUGP("HiSpeed = %x\n", info->SD_Status.HiSpeed);
- US_DEBUGP("WtP = %x\n", info->SD_Status.WtP);
+ usb_stor_dbg(us, "Insert = %x\n", s->Insert);
+ usb_stor_dbg(us, "Ready = %x\n", s->Ready);
+ usb_stor_dbg(us, "IsMMC = %x\n", s->IsMMC);
+ usb_stor_dbg(us, "HiCapacity = %x\n", s->HiCapacity);
+ usb_stor_dbg(us, "HiSpeed = %x\n", s->HiSpeed);
+ usb_stor_dbg(us, "WtP = %x\n", s->WtP);
} else {
- US_DEBUGP("SD Card Not Ready --- %x\n", buf[0]);
+ usb_stor_dbg(us, "SD Card Not Ready --- %x\n", buf[0]);
return USB_STOR_TRANSPORT_ERROR;
}
return USB_STOR_TRANSPORT_GOOD;
@@ -2293,7 +2294,7 @@ static int ene_transport(struct scsi_cmnd *srb, struct us_data *us)
int result = 0;
struct ene_ub6250_info *info = (struct ene_ub6250_info *)(us->extra);
- /*US_DEBUG(usb_stor_show_command(srb)); */
+ /*US_DEBUG(usb_stor_show_command(us, srb)); */
scsi_set_resid(srb, 0);
if (unlikely(!(info->SD_Status.Ready || info->MS_Status.Ready))) {
result = ene_init(us);
@@ -2362,7 +2363,6 @@ static int ene_ub6250_resume(struct usb_interface *iface)
mutex_lock(&us->dev_mutex);
- US_DEBUGP("%s\n", __func__);
if (us->suspend_resume_hook)
(us->suspend_resume_hook)(us, US_RESUME);
@@ -2382,7 +2382,7 @@ static int ene_ub6250_reset_resume(struct usb_interface *iface)
u8 tmp = 0;
struct us_data *us = usb_get_intfdata(iface);
struct ene_ub6250_info *info = (struct ene_ub6250_info *)(us->extra);
- US_DEBUGP("%s\n", __func__);
+
/* Report the reset to the SCSI core */
usb_stor_reset_resume(iface);
diff --git a/drivers/usb/storage/freecom.c b/drivers/usb/storage/freecom.c
index e6df087dca9..ef16068b708 100644
--- a/drivers/usb/storage/freecom.c
+++ b/drivers/usb/storage/freecom.c
@@ -40,7 +40,7 @@ MODULE_AUTHOR("David Brown <usb-storage@davidb.org>");
MODULE_LICENSE("GPL");
#ifdef CONFIG_USB_STORAGE_DEBUG
-static void pdump (void *, int);
+static void pdump(struct us_data *us, void *ibuffer, int length);
#endif
/* Bits of HD_STATUS */
@@ -161,20 +161,20 @@ freecom_readdata (struct scsi_cmnd *srb, struct us_data *us,
fxfr->Count = cpu_to_le32 (count);
memset (fxfr->Pad, 0, sizeof (fxfr->Pad));
- US_DEBUGP("Read data Freecom! (c=%d)\n", count);
+ usb_stor_dbg(us, "Read data Freecom! (c=%d)\n", count);
/* Issue the transfer command. */
result = usb_stor_bulk_transfer_buf (us, opipe, fxfr,
FCM_PACKET_LENGTH, NULL);
if (result != USB_STOR_XFER_GOOD) {
- US_DEBUGP ("Freecom readdata transport error\n");
+ usb_stor_dbg(us, "Freecom readdata transport error\n");
return USB_STOR_TRANSPORT_ERROR;
}
/* Now transfer all of our blocks. */
- US_DEBUGP("Start of read\n");
+ usb_stor_dbg(us, "Start of read\n");
result = usb_stor_bulk_srb(us, ipipe, srb);
- US_DEBUGP("freecom_readdata done!\n");
+ usb_stor_dbg(us, "freecom_readdata done!\n");
if (result > USB_STOR_XFER_SHORT)
return USB_STOR_TRANSPORT_ERROR;
@@ -194,21 +194,21 @@ freecom_writedata (struct scsi_cmnd *srb, struct us_data *us,
fxfr->Count = cpu_to_le32 (count);
memset (fxfr->Pad, 0, sizeof (fxfr->Pad));
- US_DEBUGP("Write data Freecom! (c=%d)\n", count);
+ usb_stor_dbg(us, "Write data Freecom! (c=%d)\n", count);
/* Issue the transfer command. */
result = usb_stor_bulk_transfer_buf (us, opipe, fxfr,
FCM_PACKET_LENGTH, NULL);
if (result != USB_STOR_XFER_GOOD) {
- US_DEBUGP ("Freecom writedata transport error\n");
+ usb_stor_dbg(us, "Freecom writedata transport error\n");
return USB_STOR_TRANSPORT_ERROR;
}
/* Now transfer all of our blocks. */
- US_DEBUGP("Start of write\n");
+ usb_stor_dbg(us, "Start of write\n");
result = usb_stor_bulk_srb(us, opipe, srb);
- US_DEBUGP("freecom_writedata done!\n");
+ usb_stor_dbg(us, "freecom_writedata done!\n");
if (result > USB_STOR_XFER_SHORT)
return USB_STOR_TRANSPORT_ERROR;
return USB_STOR_TRANSPORT_GOOD;
@@ -230,7 +230,7 @@ static int freecom_transport(struct scsi_cmnd *srb, struct us_data *us)
fcb = (struct freecom_cb_wrap *) us->iobuf;
fst = (struct freecom_status *) us->iobuf;
- US_DEBUGP("Freecom TRANSPORT STARTED\n");
+ usb_stor_dbg(us, "Freecom TRANSPORT STARTED\n");
/* Get handles for both transports. */
opipe = us->send_bulk_pipe;
@@ -242,7 +242,7 @@ static int freecom_transport(struct scsi_cmnd *srb, struct us_data *us)
memcpy (fcb->Atapi, srb->cmnd, 12);
memset (fcb->Filler, 0, sizeof (fcb->Filler));
- US_DEBUG(pdump (srb->cmnd, 12));
+ US_DEBUG(pdump(us, srb->cmnd, 12));
/* Send it out. */
result = usb_stor_bulk_transfer_buf (us, opipe, fcb,
@@ -252,7 +252,7 @@ static int freecom_transport(struct scsi_cmnd *srb, struct us_data *us)
* USB land. It returns the status in its own registers, which
* come back in the bulk pipe. */
if (result != USB_STOR_XFER_GOOD) {
- US_DEBUGP ("freecom transport error\n");
+ usb_stor_dbg(us, "freecom transport error\n");
return USB_STOR_TRANSPORT_ERROR;
}
@@ -260,11 +260,11 @@ static int freecom_transport(struct scsi_cmnd *srb, struct us_data *us)
* doesn't hurt us to always do it now. */
result = usb_stor_bulk_transfer_buf (us, ipipe, fst,
FCM_STATUS_PACKET_LENGTH, &partial);
- US_DEBUGP("foo Status result %d %u\n", result, partial);
+ usb_stor_dbg(us, "foo Status result %d %u\n", result, partial);
if (result != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
- US_DEBUG(pdump ((void *) fst, partial));
+ US_DEBUG(pdump(us, (void *)fst, partial));
/* The firmware will time-out commands after 20 seconds. Some commands
* can legitimately take longer than this, so we use a different
@@ -275,8 +275,8 @@ static int freecom_transport(struct scsi_cmnd *srb, struct us_data *us)
* may not work, but that is a condition that should never happen.
*/
while (fst->Status & FCM_STATUS_BUSY) {
- US_DEBUGP("20 second USB/ATAPI bridge TIMEOUT occurred!\n");
- US_DEBUGP("fst->Status is %x\n", fst->Status);
+ usb_stor_dbg(us, "20 second USB/ATAPI bridge TIMEOUT occurred!\n");
+ usb_stor_dbg(us, "fst->Status is %x\n", fst->Status);
/* Get the status again */
fcb->Type = FCM_PACKET_STATUS;
@@ -293,7 +293,7 @@ static int freecom_transport(struct scsi_cmnd *srb, struct us_data *us)
* registers, which come back in the bulk pipe.
*/
if (result != USB_STOR_XFER_GOOD) {
- US_DEBUGP ("freecom transport error\n");
+ usb_stor_dbg(us, "freecom transport error\n");
return USB_STOR_TRANSPORT_ERROR;
}
@@ -301,26 +301,26 @@ static int freecom_transport(struct scsi_cmnd *srb, struct us_data *us)
result = usb_stor_bulk_transfer_buf (us, ipipe, fst,
FCM_STATUS_PACKET_LENGTH, &partial);
- US_DEBUGP("bar Status result %d %u\n", result, partial);
+ usb_stor_dbg(us, "bar Status result %d %u\n", result, partial);
if (result != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
- US_DEBUG(pdump ((void *) fst, partial));
+ US_DEBUG(pdump(us, (void *)fst, partial));
}
if (partial != 4)
return USB_STOR_TRANSPORT_ERROR;
if ((fst->Status & 1) != 0) {
- US_DEBUGP("operation failed\n");
+ usb_stor_dbg(us, "operation failed\n");
return USB_STOR_TRANSPORT_FAILED;
}
/* The device might not have as much data available as we
* requested. If you ask for more than the device has, this reads
* and such will hang. */
- US_DEBUGP("Device indicates that it has %d bytes available\n",
- le16_to_cpu (fst->Count));
- US_DEBUGP("SCSI requested %d\n", scsi_bufflen(srb));
+ usb_stor_dbg(us, "Device indicates that it has %d bytes available\n",
+ le16_to_cpu(fst->Count));
+ usb_stor_dbg(us, "SCSI requested %d\n", scsi_bufflen(srb));
/* Find the length we desire to read. */
switch (srb->cmnd[0]) {
@@ -337,7 +337,8 @@ static int freecom_transport(struct scsi_cmnd *srb, struct us_data *us)
/* verify that this amount is legal */
if (length > scsi_bufflen(srb)) {
length = scsi_bufflen(srb);
- US_DEBUGP("Truncating request to match buffer length: %d\n", length);
+ usb_stor_dbg(us, "Truncating request to match buffer length: %d\n",
+ length);
}
/* What we do now depends on what direction the data is supposed to
@@ -351,29 +352,29 @@ static int freecom_transport(struct scsi_cmnd *srb, struct us_data *us)
/* Make sure that the status indicates that the device
* wants data as well. */
if ((fst->Status & DRQ_STAT) == 0 || (fst->Reason & 3) != 2) {
- US_DEBUGP("SCSI wants data, drive doesn't have any\n");
+ usb_stor_dbg(us, "SCSI wants data, drive doesn't have any\n");
return USB_STOR_TRANSPORT_FAILED;
}
result = freecom_readdata (srb, us, ipipe, opipe, length);
if (result != USB_STOR_TRANSPORT_GOOD)
return result;
- US_DEBUGP("FCM: Waiting for status\n");
+ usb_stor_dbg(us, "Waiting for status\n");
result = usb_stor_bulk_transfer_buf (us, ipipe, fst,
FCM_PACKET_LENGTH, &partial);
- US_DEBUG(pdump ((void *) fst, partial));
+ US_DEBUG(pdump(us, (void *)fst, partial));
if (partial != 4 || result > USB_STOR_XFER_SHORT)
return USB_STOR_TRANSPORT_ERROR;
if ((fst->Status & ERR_STAT) != 0) {
- US_DEBUGP("operation failed\n");
+ usb_stor_dbg(us, "operation failed\n");
return USB_STOR_TRANSPORT_FAILED;
}
if ((fst->Reason & 3) != 3) {
- US_DEBUGP("Drive seems still hungry\n");
+ usb_stor_dbg(us, "Drive seems still hungry\n");
return USB_STOR_TRANSPORT_FAILED;
}
- US_DEBUGP("Transfer happy\n");
+ usb_stor_dbg(us, "Transfer happy\n");
break;
case DMA_TO_DEVICE:
@@ -387,22 +388,22 @@ static int freecom_transport(struct scsi_cmnd *srb, struct us_data *us)
if (result != USB_STOR_TRANSPORT_GOOD)
return result;
- US_DEBUGP("FCM: Waiting for status\n");
+ usb_stor_dbg(us, "Waiting for status\n");
result = usb_stor_bulk_transfer_buf (us, ipipe, fst,
FCM_PACKET_LENGTH, &partial);
if (partial != 4 || result > USB_STOR_XFER_SHORT)
return USB_STOR_TRANSPORT_ERROR;
if ((fst->Status & ERR_STAT) != 0) {
- US_DEBUGP("operation failed\n");
+ usb_stor_dbg(us, "operation failed\n");
return USB_STOR_TRANSPORT_FAILED;
}
if ((fst->Reason & 3) != 3) {
- US_DEBUGP("Drive seems still hungry\n");
+ usb_stor_dbg(us, "Drive seems still hungry\n");
return USB_STOR_TRANSPORT_FAILED;
}
- US_DEBUGP("Transfer happy\n");
+ usb_stor_dbg(us, "Transfer happy\n");
break;
@@ -412,8 +413,8 @@ static int freecom_transport(struct scsi_cmnd *srb, struct us_data *us)
default:
/* should never hit here -- filtered in usb.c */
- US_DEBUGP ("freecom unimplemented direction: %d\n",
- us->srb->sc_data_direction);
+ usb_stor_dbg(us, "freecom unimplemented direction: %d\n",
+ us->srb->sc_data_direction);
/* Return fail, SCSI seems to handle this better. */
return USB_STOR_TRANSPORT_FAILED;
break;
@@ -434,7 +435,7 @@ static int init_freecom(struct us_data *us)
result = usb_stor_control_msg(us, us->recv_ctrl_pipe,
0x4c, 0xc0, 0x4346, 0x0, buffer, 0x20, 3*HZ);
buffer[32] = '\0';
- US_DEBUGP("String returned from FC init is: %s\n", buffer);
+ usb_stor_dbg(us, "String returned from FC init is: %s\n", buffer);
/* Special thanks to the people at Freecom for providing me with
* this "magic sequence", which they use in their Windows and MacOS
@@ -445,7 +446,7 @@ static int init_freecom(struct us_data *us)
/* send reset */
result = usb_stor_control_msg(us, us->send_ctrl_pipe,
0x4d, 0x40, 0x24d8, 0x0, NULL, 0x0, 3*HZ);
- US_DEBUGP("result from activate reset is %d\n", result);
+ usb_stor_dbg(us, "result from activate reset is %d\n", result);
/* wait 250ms */
mdelay(250);
@@ -453,7 +454,7 @@ static int init_freecom(struct us_data *us)
/* clear reset */
result = usb_stor_control_msg(us, us->send_ctrl_pipe,
0x4d, 0x40, 0x24f8, 0x0, NULL, 0x0, 3*HZ);
- US_DEBUGP("result from clear reset is %d\n", result);
+ usb_stor_dbg(us, "result from clear reset is %d\n", result);
/* wait 3 seconds */
mdelay(3 * 1000);
@@ -470,7 +471,7 @@ static int usb_stor_freecom_reset(struct us_data *us)
}
#ifdef CONFIG_USB_STORAGE_DEBUG
-static void pdump (void *ibuffer, int length)
+static void pdump(struct us_data *us, void *ibuffer, int length)
{
static char line[80];
int offset = 0;
@@ -490,7 +491,7 @@ static void pdump (void *ibuffer, int length)
line[offset++] = '.';
}
line[offset] = 0;
- US_DEBUGP("%s\n", line);
+ usb_stor_dbg(us, "%s\n", line);
offset = 0;
}
offset += sprintf (line+offset, "%08x:", i);
@@ -517,7 +518,7 @@ static void pdump (void *ibuffer, int length)
line[offset++] = '.';
}
line[offset] = 0;
- US_DEBUGP("%s\n", line);
+ usb_stor_dbg(us, "%s\n", line);
offset = 0;
}
#endif
diff --git a/drivers/usb/storage/initializers.c b/drivers/usb/storage/initializers.c
index 7ab9046ae0e..5a8b5ff1e45 100644
--- a/drivers/usb/storage/initializers.c
+++ b/drivers/usb/storage/initializers.c
@@ -48,12 +48,12 @@ int usb_stor_euscsi_init(struct us_data *us)
{
int result;
- US_DEBUGP("Attempting to init eUSCSI bridge...\n");
+ usb_stor_dbg(us, "Attempting to init eUSCSI bridge...\n");
us->iobuf[0] = 0x1;
result = usb_stor_control_msg(us, us->send_ctrl_pipe,
0x0C, USB_RECIP_INTERFACE | USB_TYPE_VENDOR,
0x01, 0x0, us->iobuf, 0x1, 5000);
- US_DEBUGP("-- result is %d\n", result);
+ usb_stor_dbg(us, "-- result is %d\n", result);
return 0;
}
@@ -68,7 +68,7 @@ int usb_stor_ucr61s2b_init(struct us_data *us)
unsigned int partial;
static char init_string[] = "\xec\x0a\x06\x00$PCCHIPS";
- US_DEBUGP("Sending UCR-61S2B initialization packet...\n");
+ usb_stor_dbg(us, "Sending UCR-61S2B initialization packet...\n");
bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
bcb->Tag = 0;
@@ -83,7 +83,7 @@ int usb_stor_ucr61s2b_init(struct us_data *us)
if (res)
return -EIO;
- US_DEBUGP("Getting status packet...\n");
+ usb_stor_dbg(us, "Getting status packet...\n");
res = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, bcs,
US_BULK_CS_WRAP_LEN, &partial);
if (res)
@@ -92,8 +92,8 @@ int usb_stor_ucr61s2b_init(struct us_data *us)
return 0;
}
-/* This places the HUAWEI usb dongles in multi-port mode */
-static int usb_stor_huawei_feature_init(struct us_data *us)
+/* This places the HUAWEI E220 devices in multi-port mode */
+int usb_stor_huawei_e220_init(struct us_data *us)
{
int result;
@@ -101,78 +101,6 @@ static int usb_stor_huawei_feature_init(struct us_data *us)
USB_REQ_SET_FEATURE,
USB_TYPE_STANDARD | USB_RECIP_DEVICE,
0x01, 0x0, NULL, 0x0, 1000);
- US_DEBUGP("Huawei mode set result is %d\n", result);
+ usb_stor_dbg(us, "Huawei mode set result is %d\n", result);
return 0;
}
-
-/*
- * It will send a scsi switch command called rewind' to huawei dongle.
- * When the dongle receives this command at the first time,
- * it will reboot immediately. After rebooted, it will ignore this command.
- * So it is unnecessary to read its response.
- */
-static int usb_stor_huawei_scsi_init(struct us_data *us)
-{
- int result = 0;
- int act_len = 0;
- struct bulk_cb_wrap *bcbw = (struct bulk_cb_wrap *) us->iobuf;
- char rewind_cmd[] = {0x11, 0x06, 0x20, 0x00, 0x00, 0x01, 0x01, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
-
- bcbw->Signature = cpu_to_le32(US_BULK_CB_SIGN);
- bcbw->Tag = 0;
- bcbw->DataTransferLength = 0;
- bcbw->Flags = bcbw->Lun = 0;
- bcbw->Length = sizeof(rewind_cmd);
- memset(bcbw->CDB, 0, sizeof(bcbw->CDB));
- memcpy(bcbw->CDB, rewind_cmd, sizeof(rewind_cmd));
-
- result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe, bcbw,
- US_BULK_CB_WRAP_LEN, &act_len);
- US_DEBUGP("transfer actual length=%d, result=%d\n", act_len, result);
- return result;
-}
-
-/*
- * It tries to find the supported Huawei USB dongles.
- * In Huawei, they assign the following product IDs
- * for all of their mobile broadband dongles,
- * including the new dongles in the future.
- * So if the product ID is not included in this list,
- * it means it is not Huawei's mobile broadband dongles.
- */
-static int usb_stor_huawei_dongles_pid(struct us_data *us)
-{
- struct usb_interface_descriptor *idesc;
- int idProduct;
-
- idesc = &us->pusb_intf->cur_altsetting->desc;
- idProduct = le16_to_cpu(us->pusb_dev->descriptor.idProduct);
- /* The first port is CDROM,
- * means the dongle in the single port mode,
- * and a switch command is required to be sent. */
- if (idesc && idesc->bInterfaceNumber == 0) {
- if ((idProduct == 0x1001)
- || (idProduct == 0x1003)
- || (idProduct == 0x1004)
- || (idProduct >= 0x1401 && idProduct <= 0x1500)
- || (idProduct >= 0x1505 && idProduct <= 0x1600)
- || (idProduct >= 0x1c02 && idProduct <= 0x2202)) {
- return 1;
- }
- }
- return 0;
-}
-
-int usb_stor_huawei_init(struct us_data *us)
-{
- int result = 0;
-
- if (usb_stor_huawei_dongles_pid(us)) {
- if (le16_to_cpu(us->pusb_dev->descriptor.idProduct) >= 0x1446)
- result = usb_stor_huawei_scsi_init(us);
- else
- result = usb_stor_huawei_feature_init(us);
- }
- return result;
-}
diff --git a/drivers/usb/storage/initializers.h b/drivers/usb/storage/initializers.h
index 5376d4fc76f..529327fbb06 100644
--- a/drivers/usb/storage/initializers.h
+++ b/drivers/usb/storage/initializers.h
@@ -46,5 +46,5 @@ int usb_stor_euscsi_init(struct us_data *us);
* flash reader */
int usb_stor_ucr61s2b_init(struct us_data *us);
-/* This places the HUAWEI usb dongles in multi-port mode */
-int usb_stor_huawei_init(struct us_data *us);
+/* This places the HUAWEI E220 devices in multi-port mode */
+int usb_stor_huawei_e220_init(struct us_data *us);
diff --git a/drivers/usb/storage/isd200.c b/drivers/usb/storage/isd200.c
index ecea4787736..599d8bff26c 100644
--- a/drivers/usb/storage/isd200.c
+++ b/drivers/usb/storage/isd200.c
@@ -503,7 +503,7 @@ static int isd200_action( struct us_data *us, int action,
switch ( action ) {
case ACTION_READ_STATUS:
- US_DEBUGP(" isd200_action(READ_STATUS)\n");
+ usb_stor_dbg(us, " isd200_action(READ_STATUS)\n");
ata.generic.ActionSelect = ACTION_SELECT_0|ACTION_SELECT_2;
ata.generic.RegisterSelect =
REG_CYLINDER_LOW | REG_CYLINDER_HIGH |
@@ -512,7 +512,7 @@ static int isd200_action( struct us_data *us, int action,
break;
case ACTION_ENUM:
- US_DEBUGP(" isd200_action(ENUM,0x%02x)\n",value);
+ usb_stor_dbg(us, " isd200_action(ENUM,0x%02x)\n", value);
ata.generic.ActionSelect = ACTION_SELECT_1|ACTION_SELECT_2|
ACTION_SELECT_3|ACTION_SELECT_4|
ACTION_SELECT_5;
@@ -522,7 +522,7 @@ static int isd200_action( struct us_data *us, int action,
break;
case ACTION_RESET:
- US_DEBUGP(" isd200_action(RESET)\n");
+ usb_stor_dbg(us, " isd200_action(RESET)\n");
ata.generic.ActionSelect = ACTION_SELECT_1|ACTION_SELECT_2|
ACTION_SELECT_3|ACTION_SELECT_4;
ata.generic.RegisterSelect = REG_DEVICE_CONTROL;
@@ -531,7 +531,7 @@ static int isd200_action( struct us_data *us, int action,
break;
case ACTION_REENABLE:
- US_DEBUGP(" isd200_action(REENABLE)\n");
+ usb_stor_dbg(us, " isd200_action(REENABLE)\n");
ata.generic.ActionSelect = ACTION_SELECT_1|ACTION_SELECT_2|
ACTION_SELECT_3|ACTION_SELECT_4;
ata.generic.RegisterSelect = REG_DEVICE_CONTROL;
@@ -540,7 +540,7 @@ static int isd200_action( struct us_data *us, int action,
break;
case ACTION_SOFT_RESET:
- US_DEBUGP(" isd200_action(SOFT_RESET)\n");
+ usb_stor_dbg(us, " isd200_action(SOFT_RESET)\n");
ata.generic.ActionSelect = ACTION_SELECT_1|ACTION_SELECT_5;
ata.generic.RegisterSelect = REG_DEVICE_HEAD | REG_COMMAND;
ata.write.DeviceHeadByte = info->DeviceHead;
@@ -549,7 +549,7 @@ static int isd200_action( struct us_data *us, int action,
break;
case ACTION_IDENTIFY:
- US_DEBUGP(" isd200_action(IDENTIFY)\n");
+ usb_stor_dbg(us, " isd200_action(IDENTIFY)\n");
ata.generic.RegisterSelect = REG_COMMAND;
ata.write.CommandByte = ATA_CMD_ID_ATA;
isd200_set_srb(info, DMA_FROM_DEVICE, info->id,
@@ -557,7 +557,7 @@ static int isd200_action( struct us_data *us, int action,
break;
default:
- US_DEBUGP("Error: Undefined action %d\n",action);
+ usb_stor_dbg(us, "Error: Undefined action %d\n", action);
return ISD200_ERROR;
}
@@ -567,7 +567,8 @@ static int isd200_action( struct us_data *us, int action,
if (status == USB_STOR_TRANSPORT_GOOD)
status = ISD200_GOOD;
else {
- US_DEBUGP(" isd200_action(0x%02x) error: %d\n",action,status);
+ usb_stor_dbg(us, " isd200_action(0x%02x) error: %d\n",
+ action, status);
status = ISD200_ERROR;
/* need to reset device here */
}
@@ -589,17 +590,17 @@ static int isd200_read_regs( struct us_data *us )
int retStatus = ISD200_GOOD;
int transferStatus;
- US_DEBUGP("Entering isd200_IssueATAReadRegs\n");
+ usb_stor_dbg(us, "Entering isd200_IssueATAReadRegs\n");
transferStatus = isd200_action( us, ACTION_READ_STATUS,
info->RegsBuf, sizeof(info->ATARegs) );
if (transferStatus != ISD200_TRANSPORT_GOOD) {
- US_DEBUGP(" Error reading ATA registers\n");
+ usb_stor_dbg(us, " Error reading ATA registers\n");
retStatus = ISD200_ERROR;
} else {
memcpy(info->ATARegs, info->RegsBuf, sizeof(info->ATARegs));
- US_DEBUGP(" Got ATA Register[ATA_REG_ERROR_OFFSET] = 0x%x\n",
- info->ATARegs[ATA_REG_ERROR_OFFSET]);
+ usb_stor_dbg(us, " Got ATA Register[ATA_REG_ERROR_OFFSET] = 0x%x\n",
+ info->ATARegs[ATA_REG_ERROR_OFFSET]);
}
return retStatus;
@@ -629,7 +630,7 @@ static void isd200_invoke_transport( struct us_data *us,
* short-circuit all other processing
*/
if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags)) {
- US_DEBUGP("-- command was aborted\n");
+ usb_stor_dbg(us, "-- command was aborted\n");
goto Handle_Abort;
}
@@ -641,23 +642,23 @@ static void isd200_invoke_transport( struct us_data *us,
break;
case USB_STOR_TRANSPORT_NO_SENSE:
- US_DEBUGP("-- transport indicates protocol failure\n");
+ usb_stor_dbg(us, "-- transport indicates protocol failure\n");
srb->result = SAM_STAT_CHECK_CONDITION;
return;
case USB_STOR_TRANSPORT_FAILED:
- US_DEBUGP("-- transport indicates command failure\n");
+ usb_stor_dbg(us, "-- transport indicates command failure\n");
need_auto_sense = 1;
break;
case USB_STOR_TRANSPORT_ERROR:
- US_DEBUGP("-- transport indicates transport error\n");
+ usb_stor_dbg(us, "-- transport indicates transport error\n");
srb->result = DID_ERROR << 16;
/* Need reset here */
return;
default:
- US_DEBUGP("-- transport indicates unknown error\n");
+ usb_stor_dbg(us, "-- transport indicates unknown error\n");
srb->result = DID_ERROR << 16;
/* Need reset here */
return;
@@ -669,14 +670,14 @@ static void isd200_invoke_transport( struct us_data *us,
(srb->cmnd[0] == MODE_SENSE) ||
(srb->cmnd[0] == LOG_SENSE) ||
(srb->cmnd[0] == MODE_SENSE_10))) {
- US_DEBUGP("-- unexpectedly short transfer\n");
+ usb_stor_dbg(us, "-- unexpectedly short transfer\n");
need_auto_sense = 1;
}
if (need_auto_sense) {
result = isd200_read_regs(us);
if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags)) {
- US_DEBUGP("-- auto-sense aborted\n");
+ usb_stor_dbg(us, "-- auto-sense aborted\n");
goto Handle_Abort;
}
if (result == ISD200_GOOD) {
@@ -710,40 +711,40 @@ static void isd200_invoke_transport( struct us_data *us,
}
#ifdef CONFIG_USB_STORAGE_DEBUG
-static void isd200_log_config( struct isd200_info* info )
+static void isd200_log_config(struct us_data *us, struct isd200_info *info)
{
- US_DEBUGP(" Event Notification: 0x%x\n",
- info->ConfigData.EventNotification);
- US_DEBUGP(" External Clock: 0x%x\n",
- info->ConfigData.ExternalClock);
- US_DEBUGP(" ATA Init Timeout: 0x%x\n",
- info->ConfigData.ATAInitTimeout);
- US_DEBUGP(" ATAPI Command Block Size: 0x%x\n",
- (info->ConfigData.ATAConfig & ATACFG_BLOCKSIZE) >> 6);
- US_DEBUGP(" Master/Slave Selection: 0x%x\n",
- info->ConfigData.ATAConfig & ATACFG_MASTER);
- US_DEBUGP(" ATAPI Reset: 0x%x\n",
- info->ConfigData.ATAConfig & ATACFG_ATAPI_RESET);
- US_DEBUGP(" ATA Timing: 0x%x\n",
- info->ConfigData.ATAConfig & ATACFG_TIMING);
- US_DEBUGP(" ATA Major Command: 0x%x\n",
- info->ConfigData.ATAMajorCommand);
- US_DEBUGP(" ATA Minor Command: 0x%x\n",
- info->ConfigData.ATAMinorCommand);
- US_DEBUGP(" Init Status: 0x%x\n",
- info->ConfigData.ATAExtraConfig & ATACFGE_INIT_STATUS);
- US_DEBUGP(" Config Descriptor 2: 0x%x\n",
- info->ConfigData.ATAExtraConfig & ATACFGE_CONF_DESC2);
- US_DEBUGP(" Skip Device Boot: 0x%x\n",
- info->ConfigData.ATAExtraConfig & ATACFGE_SKIP_BOOT);
- US_DEBUGP(" ATA 3 State Supsend: 0x%x\n",
- info->ConfigData.ATAExtraConfig & ATACFGE_STATE_SUSPEND);
- US_DEBUGP(" Descriptor Override: 0x%x\n",
- info->ConfigData.ATAExtraConfig & ATACFGE_DESC_OVERRIDE);
- US_DEBUGP(" Last LUN Identifier: 0x%x\n",
- info->ConfigData.ATAExtraConfig & ATACFGE_LAST_LUN);
- US_DEBUGP(" SRST Enable: 0x%x\n",
- info->ConfigData.ATAExtraConfig & CFG_CAPABILITY_SRST);
+ usb_stor_dbg(us, " Event Notification: 0x%x\n",
+ info->ConfigData.EventNotification);
+ usb_stor_dbg(us, " External Clock: 0x%x\n",
+ info->ConfigData.ExternalClock);
+ usb_stor_dbg(us, " ATA Init Timeout: 0x%x\n",
+ info->ConfigData.ATAInitTimeout);
+ usb_stor_dbg(us, " ATAPI Command Block Size: 0x%x\n",
+ (info->ConfigData.ATAConfig & ATACFG_BLOCKSIZE) >> 6);
+ usb_stor_dbg(us, " Master/Slave Selection: 0x%x\n",
+ info->ConfigData.ATAConfig & ATACFG_MASTER);
+ usb_stor_dbg(us, " ATAPI Reset: 0x%x\n",
+ info->ConfigData.ATAConfig & ATACFG_ATAPI_RESET);
+ usb_stor_dbg(us, " ATA Timing: 0x%x\n",
+ info->ConfigData.ATAConfig & ATACFG_TIMING);
+ usb_stor_dbg(us, " ATA Major Command: 0x%x\n",
+ info->ConfigData.ATAMajorCommand);
+ usb_stor_dbg(us, " ATA Minor Command: 0x%x\n",
+ info->ConfigData.ATAMinorCommand);
+ usb_stor_dbg(us, " Init Status: 0x%x\n",
+ info->ConfigData.ATAExtraConfig & ATACFGE_INIT_STATUS);
+ usb_stor_dbg(us, " Config Descriptor 2: 0x%x\n",
+ info->ConfigData.ATAExtraConfig & ATACFGE_CONF_DESC2);
+ usb_stor_dbg(us, " Skip Device Boot: 0x%x\n",
+ info->ConfigData.ATAExtraConfig & ATACFGE_SKIP_BOOT);
+ usb_stor_dbg(us, " ATA 3 State Supsend: 0x%x\n",
+ info->ConfigData.ATAExtraConfig & ATACFGE_STATE_SUSPEND);
+ usb_stor_dbg(us, " Descriptor Override: 0x%x\n",
+ info->ConfigData.ATAExtraConfig & ATACFGE_DESC_OVERRIDE);
+ usb_stor_dbg(us, " Last LUN Identifier: 0x%x\n",
+ info->ConfigData.ATAExtraConfig & ATACFGE_LAST_LUN);
+ usb_stor_dbg(us, " SRST Enable: 0x%x\n",
+ info->ConfigData.ATAExtraConfig & CFG_CAPABILITY_SRST);
}
#endif
@@ -762,9 +763,9 @@ static int isd200_write_config( struct us_data *us )
int result;
#ifdef CONFIG_USB_STORAGE_DEBUG
- US_DEBUGP("Entering isd200_write_config\n");
- US_DEBUGP(" Writing the following ISD200 Config Data:\n");
- isd200_log_config(info);
+ usb_stor_dbg(us, "Entering isd200_write_config\n");
+ usb_stor_dbg(us, " Writing the following ISD200 Config Data:\n");
+ isd200_log_config(us, info);
#endif
/* let's send the command via the control pipe */
@@ -779,13 +780,13 @@ static int isd200_write_config( struct us_data *us )
sizeof(info->ConfigData));
if (result >= 0) {
- US_DEBUGP(" ISD200 Config Data was written successfully\n");
+ usb_stor_dbg(us, " ISD200 Config Data was written successfully\n");
} else {
- US_DEBUGP(" Request to write ISD200 Config Data failed!\n");
+ usb_stor_dbg(us, " Request to write ISD200 Config Data failed!\n");
retStatus = ISD200_ERROR;
}
- US_DEBUGP("Leaving isd200_write_config %08X\n", retStatus);
+ usb_stor_dbg(us, "Leaving isd200_write_config %08X\n", retStatus);
return retStatus;
}
@@ -804,7 +805,7 @@ static int isd200_read_config( struct us_data *us )
int retStatus = ISD200_GOOD;
int result;
- US_DEBUGP("Entering isd200_read_config\n");
+ usb_stor_dbg(us, "Entering isd200_read_config\n");
/* read the configuration information from ISD200. Use this to */
/* determine what the special ATA CDB bytes are. */
@@ -821,16 +822,16 @@ static int isd200_read_config( struct us_data *us )
if (result >= 0) {
- US_DEBUGP(" Retrieved the following ISD200 Config Data:\n");
+ usb_stor_dbg(us, " Retrieved the following ISD200 Config Data:\n");
#ifdef CONFIG_USB_STORAGE_DEBUG
- isd200_log_config(info);
+ isd200_log_config(us, info);
#endif
} else {
- US_DEBUGP(" Request to get ISD200 Config Data failed!\n");
+ usb_stor_dbg(us, " Request to get ISD200 Config Data failed!\n");
retStatus = ISD200_ERROR;
}
- US_DEBUGP("Leaving isd200_read_config %08X\n", retStatus);
+ usb_stor_dbg(us, "Leaving isd200_read_config %08X\n", retStatus);
return retStatus;
}
@@ -848,15 +849,15 @@ static int isd200_atapi_soft_reset( struct us_data *us )
int retStatus = ISD200_GOOD;
int transferStatus;
- US_DEBUGP("Entering isd200_atapi_soft_reset\n");
+ usb_stor_dbg(us, "Entering isd200_atapi_soft_reset\n");
transferStatus = isd200_action( us, ACTION_SOFT_RESET, NULL, 0 );
if (transferStatus != ISD200_TRANSPORT_GOOD) {
- US_DEBUGP(" Error issuing Atapi Soft Reset\n");
+ usb_stor_dbg(us, " Error issuing Atapi Soft Reset\n");
retStatus = ISD200_ERROR;
}
- US_DEBUGP("Leaving isd200_atapi_soft_reset %08X\n", retStatus);
+ usb_stor_dbg(us, "Leaving isd200_atapi_soft_reset %08X\n", retStatus);
return retStatus;
}
@@ -874,13 +875,13 @@ static int isd200_srst( struct us_data *us )
int retStatus = ISD200_GOOD;
int transferStatus;
- US_DEBUGP("Entering isd200_SRST\n");
+ usb_stor_dbg(us, "Entering isd200_SRST\n");
transferStatus = isd200_action( us, ACTION_RESET, NULL, 0 );
/* check to see if this request failed */
if (transferStatus != ISD200_TRANSPORT_GOOD) {
- US_DEBUGP(" Error issuing SRST\n");
+ usb_stor_dbg(us, " Error issuing SRST\n");
retStatus = ISD200_ERROR;
} else {
/* delay 10ms to give the drive a chance to see it */
@@ -888,7 +889,7 @@ static int isd200_srst( struct us_data *us )
transferStatus = isd200_action( us, ACTION_REENABLE, NULL, 0 );
if (transferStatus != ISD200_TRANSPORT_GOOD) {
- US_DEBUGP(" Error taking drive out of reset\n");
+ usb_stor_dbg(us, " Error taking drive out of reset\n");
retStatus = ISD200_ERROR;
} else {
/* delay 50ms to give the drive a chance to recover after SRST */
@@ -896,7 +897,7 @@ static int isd200_srst( struct us_data *us )
}
}
- US_DEBUGP("Leaving isd200_srst %08X\n", retStatus);
+ usb_stor_dbg(us, "Leaving isd200_srst %08X\n", retStatus);
return retStatus;
}
@@ -926,10 +927,6 @@ static int isd200_try_enum(struct us_data *us, unsigned char master_slave,
/* loop until we detect !BSY or timeout */
while(1) {
-#ifdef CONFIG_USB_STORAGE_DEBUG
- char* mstr = master_slave == ATA_ADDRESS_DEVHEAD_STD ?
- "Master" : "Slave";
-#endif
status = isd200_action( us, ACTION_ENUM, NULL, master_slave );
if ( status != ISD200_GOOD )
@@ -942,9 +939,13 @@ static int isd200_try_enum(struct us_data *us, unsigned char master_slave,
if (!detect) {
if (regs[ATA_REG_STATUS_OFFSET] & ATA_BUSY) {
- US_DEBUGP(" %s status is still BSY, try again...\n",mstr);
+ usb_stor_dbg(us, " %s status is still BSY, try again...\n",
+ master_slave == ATA_ADDRESS_DEVHEAD_STD ?
+ "Master" : "Slave");
} else {
- US_DEBUGP(" %s status !BSY, continue with next operation\n",mstr);
+ usb_stor_dbg(us, " %s status !BSY, continue with next operation\n",
+ master_slave == ATA_ADDRESS_DEVHEAD_STD ?
+ "Master" : "Slave");
break;
}
}
@@ -953,11 +954,11 @@ static int isd200_try_enum(struct us_data *us, unsigned char master_slave,
/* ATA_ERR (workaround for Archos CD-ROM) */
else if (regs[ATA_REG_STATUS_OFFSET] &
(ATA_BUSY | ATA_DF | ATA_ERR)) {
- US_DEBUGP(" Status indicates it is not ready, try again...\n");
+ usb_stor_dbg(us, " Status indicates it is not ready, try again...\n");
}
/* check for DRDY, ATA devices set DRDY after SRST */
else if (regs[ATA_REG_STATUS_OFFSET] & ATA_DRDY) {
- US_DEBUGP(" Identified ATA device\n");
+ usb_stor_dbg(us, " Identified ATA device\n");
info->DeviceFlags |= DF_ATA_DEVICE;
info->DeviceHead = master_slave;
break;
@@ -978,27 +979,27 @@ static int isd200_try_enum(struct us_data *us, unsigned char master_slave,
*/
if ((master_slave & ATA_ADDRESS_DEVHEAD_SLAVE) &&
!recheckAsMaster) {
- US_DEBUGP(" Identified ATAPI device as slave. Rechecking again as master\n");
+ usb_stor_dbg(us, " Identified ATAPI device as slave. Rechecking again as master\n");
recheckAsMaster = 1;
master_slave = ATA_ADDRESS_DEVHEAD_STD;
} else {
- US_DEBUGP(" Identified ATAPI device\n");
+ usb_stor_dbg(us, " Identified ATAPI device\n");
info->DeviceHead = master_slave;
status = isd200_atapi_soft_reset(us);
break;
}
} else {
- US_DEBUGP(" Not ATA, not ATAPI. Weird.\n");
+ usb_stor_dbg(us, " Not ATA, not ATAPI - Weird\n");
break;
}
/* check for timeout on this request */
if (time_after_eq(jiffies, endTime)) {
if (!detect)
- US_DEBUGP(" BSY check timeout, just continue with next operation...\n");
+ usb_stor_dbg(us, " BSY check timeout, just continue with next operation...\n");
else
- US_DEBUGP(" Device detect timeout!\n");
+ usb_stor_dbg(us, " Device detect timeout!\n");
break;
}
}
@@ -1020,7 +1021,7 @@ static int isd200_manual_enum(struct us_data *us)
struct isd200_info *info = (struct isd200_info *)us->extra;
int retStatus = ISD200_GOOD;
- US_DEBUGP("Entering isd200_manual_enum\n");
+ usb_stor_dbg(us, "Entering isd200_manual_enum\n");
retStatus = isd200_read_config(us);
if (retStatus == ISD200_GOOD) {
@@ -1039,14 +1040,15 @@ static int isd200_manual_enum(struct us_data *us)
isslave = (info->DeviceHead & ATA_ADDRESS_DEVHEAD_SLAVE) ? 1 : 0;
if (!(info->ConfigData.ATAConfig & ATACFG_MASTER)) {
- US_DEBUGP(" Setting Master/Slave selection to %d\n", isslave);
+ usb_stor_dbg(us, " Setting Master/Slave selection to %d\n",
+ isslave);
info->ConfigData.ATAConfig &= 0x3f;
info->ConfigData.ATAConfig |= (isslave<<6);
retStatus = isd200_write_config(us);
}
}
- US_DEBUGP("Leaving isd200_manual_enum %08X\n", retStatus);
+ usb_stor_dbg(us, "Leaving isd200_manual_enum %08X\n", retStatus);
return(retStatus);
}
@@ -1064,35 +1066,35 @@ static void isd200_fix_driveid(u16 *id)
#endif
}
-static void isd200_dump_driveid(u16 *id)
+static void isd200_dump_driveid(struct us_data *us, u16 *id)
{
- US_DEBUGP(" Identify Data Structure:\n");
- US_DEBUGP(" config = 0x%x\n", id[ATA_ID_CONFIG]);
- US_DEBUGP(" cyls = 0x%x\n", id[ATA_ID_CYLS]);
- US_DEBUGP(" heads = 0x%x\n", id[ATA_ID_HEADS]);
- US_DEBUGP(" track_bytes = 0x%x\n", id[4]);
- US_DEBUGP(" sector_bytes = 0x%x\n", id[5]);
- US_DEBUGP(" sectors = 0x%x\n", id[ATA_ID_SECTORS]);
- US_DEBUGP(" serial_no[0] = 0x%x\n", *(char *)&id[ATA_ID_SERNO]);
- US_DEBUGP(" buf_type = 0x%x\n", id[20]);
- US_DEBUGP(" buf_size = 0x%x\n", id[ATA_ID_BUF_SIZE]);
- US_DEBUGP(" ecc_bytes = 0x%x\n", id[22]);
- US_DEBUGP(" fw_rev[0] = 0x%x\n", *(char *)&id[ATA_ID_FW_REV]);
- US_DEBUGP(" model[0] = 0x%x\n", *(char *)&id[ATA_ID_PROD]);
- US_DEBUGP(" max_multsect = 0x%x\n", id[ATA_ID_MAX_MULTSECT] & 0xff);
- US_DEBUGP(" dword_io = 0x%x\n", id[ATA_ID_DWORD_IO]);
- US_DEBUGP(" capability = 0x%x\n", id[ATA_ID_CAPABILITY] >> 8);
- US_DEBUGP(" tPIO = 0x%x\n", id[ATA_ID_OLD_PIO_MODES] >> 8);
- US_DEBUGP(" tDMA = 0x%x\n", id[ATA_ID_OLD_DMA_MODES] >> 8);
- US_DEBUGP(" field_valid = 0x%x\n", id[ATA_ID_FIELD_VALID]);
- US_DEBUGP(" cur_cyls = 0x%x\n", id[ATA_ID_CUR_CYLS]);
- US_DEBUGP(" cur_heads = 0x%x\n", id[ATA_ID_CUR_HEADS]);
- US_DEBUGP(" cur_sectors = 0x%x\n", id[ATA_ID_CUR_SECTORS]);
- US_DEBUGP(" cur_capacity = 0x%x\n", ata_id_u32(id, 57));
- US_DEBUGP(" multsect = 0x%x\n", id[ATA_ID_MULTSECT] & 0xff);
- US_DEBUGP(" lba_capacity = 0x%x\n", ata_id_u32(id, ATA_ID_LBA_CAPACITY));
- US_DEBUGP(" command_set_1 = 0x%x\n", id[ATA_ID_COMMAND_SET_1]);
- US_DEBUGP(" command_set_2 = 0x%x\n", id[ATA_ID_COMMAND_SET_2]);
+ usb_stor_dbg(us, " Identify Data Structure:\n");
+ usb_stor_dbg(us, " config = 0x%x\n", id[ATA_ID_CONFIG]);
+ usb_stor_dbg(us, " cyls = 0x%x\n", id[ATA_ID_CYLS]);
+ usb_stor_dbg(us, " heads = 0x%x\n", id[ATA_ID_HEADS]);
+ usb_stor_dbg(us, " track_bytes = 0x%x\n", id[4]);
+ usb_stor_dbg(us, " sector_bytes = 0x%x\n", id[5]);
+ usb_stor_dbg(us, " sectors = 0x%x\n", id[ATA_ID_SECTORS]);
+ usb_stor_dbg(us, " serial_no[0] = 0x%x\n", *(char *)&id[ATA_ID_SERNO]);
+ usb_stor_dbg(us, " buf_type = 0x%x\n", id[20]);
+ usb_stor_dbg(us, " buf_size = 0x%x\n", id[ATA_ID_BUF_SIZE]);
+ usb_stor_dbg(us, " ecc_bytes = 0x%x\n", id[22]);
+ usb_stor_dbg(us, " fw_rev[0] = 0x%x\n", *(char *)&id[ATA_ID_FW_REV]);
+ usb_stor_dbg(us, " model[0] = 0x%x\n", *(char *)&id[ATA_ID_PROD]);
+ usb_stor_dbg(us, " max_multsect = 0x%x\n", id[ATA_ID_MAX_MULTSECT] & 0xff);
+ usb_stor_dbg(us, " dword_io = 0x%x\n", id[ATA_ID_DWORD_IO]);
+ usb_stor_dbg(us, " capability = 0x%x\n", id[ATA_ID_CAPABILITY] >> 8);
+ usb_stor_dbg(us, " tPIO = 0x%x\n", id[ATA_ID_OLD_PIO_MODES] >> 8);
+ usb_stor_dbg(us, " tDMA = 0x%x\n", id[ATA_ID_OLD_DMA_MODES] >> 8);
+ usb_stor_dbg(us, " field_valid = 0x%x\n", id[ATA_ID_FIELD_VALID]);
+ usb_stor_dbg(us, " cur_cyls = 0x%x\n", id[ATA_ID_CUR_CYLS]);
+ usb_stor_dbg(us, " cur_heads = 0x%x\n", id[ATA_ID_CUR_HEADS]);
+ usb_stor_dbg(us, " cur_sectors = 0x%x\n", id[ATA_ID_CUR_SECTORS]);
+ usb_stor_dbg(us, " cur_capacity = 0x%x\n", ata_id_u32(id, 57));
+ usb_stor_dbg(us, " multsect = 0x%x\n", id[ATA_ID_MULTSECT] & 0xff);
+ usb_stor_dbg(us, " lba_capacity = 0x%x\n", ata_id_u32(id, ATA_ID_LBA_CAPACITY));
+ usb_stor_dbg(us, " command_set_1 = 0x%x\n", id[ATA_ID_COMMAND_SET_1]);
+ usb_stor_dbg(us, " command_set_2 = 0x%x\n", id[ATA_ID_COMMAND_SET_2]);
}
/**************************************************************************
@@ -1109,7 +1111,7 @@ static int isd200_get_inquiry_data( struct us_data *us )
int retStatus = ISD200_GOOD;
u16 *id = info->id;
- US_DEBUGP("Entering isd200_get_inquiry_data\n");
+ usb_stor_dbg(us, "Entering isd200_get_inquiry_data\n");
/* set default to Master */
info->DeviceHead = ATA_ADDRESS_DEVHEAD_STD;
@@ -1127,7 +1129,7 @@ static int isd200_get_inquiry_data( struct us_data *us )
id, ATA_ID_WORDS * 2);
if (transferStatus != ISD200_TRANSPORT_GOOD) {
/* Error issuing ATA Command Identify */
- US_DEBUGP(" Error issuing ATA Command Identify\n");
+ usb_stor_dbg(us, " Error issuing ATA Command Identify\n");
retStatus = ISD200_ERROR;
} else {
/* ATA Command Identify successful */
@@ -1136,7 +1138,7 @@ static int isd200_get_inquiry_data( struct us_data *us )
__u16 *dest;
isd200_fix_driveid(id);
- isd200_dump_driveid(id);
+ isd200_dump_driveid(us, id);
memset(&info->InquiryData, 0, sizeof(info->InquiryData));
@@ -1170,7 +1172,7 @@ static int isd200_get_inquiry_data( struct us_data *us )
/* determine if it supports Media Status Notification */
if (id[ATA_ID_COMMAND_SET_2] & COMMANDSET_MEDIA_STATUS) {
- US_DEBUGP(" Device supports Media Status Notification\n");
+ usb_stor_dbg(us, " Device supports Media Status Notification\n");
/* Indicate that it is enabled, even though it is not
* This allows the lock/unlock of the media to work
@@ -1190,7 +1192,8 @@ static int isd200_get_inquiry_data( struct us_data *us )
us->protocol_name = "Transparent SCSI";
us->proto_handler = usb_stor_transparent_scsi_command;
- US_DEBUGP("Protocol changed to: %s\n", us->protocol_name);
+ usb_stor_dbg(us, "Protocol changed to: %s\n",
+ us->protocol_name);
/* Free driver structure */
us->extra_destructor(info);
@@ -1200,7 +1203,7 @@ static int isd200_get_inquiry_data( struct us_data *us )
}
}
- US_DEBUGP("Leaving isd200_get_inquiry_data %08X\n", retStatus);
+ usb_stor_dbg(us, "Leaving isd200_get_inquiry_data %08X\n", retStatus);
return(retStatus);
}
@@ -1231,7 +1234,7 @@ static int isd200_scsi_to_ata(struct scsi_cmnd *srb, struct us_data *us,
/* SCSI Command */
switch (srb->cmnd[0]) {
case INQUIRY:
- US_DEBUGP(" ATA OUT - INQUIRY\n");
+ usb_stor_dbg(us, " ATA OUT - INQUIRY\n");
/* copy InquiryData */
usb_stor_set_xfer_buf((unsigned char *) &info->InquiryData,
@@ -1241,7 +1244,7 @@ static int isd200_scsi_to_ata(struct scsi_cmnd *srb, struct us_data *us,
break;
case MODE_SENSE:
- US_DEBUGP(" ATA OUT - SCSIOP_MODE_SENSE\n");
+ usb_stor_dbg(us, " ATA OUT - SCSIOP_MODE_SENSE\n");
/* Initialize the return buffer */
usb_stor_set_xfer_buf(senseData, sizeof(senseData), srb);
@@ -1255,14 +1258,14 @@ static int isd200_scsi_to_ata(struct scsi_cmnd *srb, struct us_data *us,
ataCdb->write.CommandByte = ATA_COMMAND_GET_MEDIA_STATUS;
isd200_srb_set_bufflen(srb, 0);
} else {
- US_DEBUGP(" Media Status not supported, just report okay\n");
+ usb_stor_dbg(us, " Media Status not supported, just report okay\n");
srb->result = SAM_STAT_GOOD;
sendToTransport = 0;
}
break;
case TEST_UNIT_READY:
- US_DEBUGP(" ATA OUT - SCSIOP_TEST_UNIT_READY\n");
+ usb_stor_dbg(us, " ATA OUT - SCSIOP_TEST_UNIT_READY\n");
if (info->DeviceFlags & DF_MEDIA_STATUS_ENABLED)
{
@@ -1273,7 +1276,7 @@ static int isd200_scsi_to_ata(struct scsi_cmnd *srb, struct us_data *us,
ataCdb->write.CommandByte = ATA_COMMAND_GET_MEDIA_STATUS;
isd200_srb_set_bufflen(srb, 0);
} else {
- US_DEBUGP(" Media Status not supported, just report okay\n");
+ usb_stor_dbg(us, " Media Status not supported, just report okay\n");
srb->result = SAM_STAT_GOOD;
sendToTransport = 0;
}
@@ -1284,7 +1287,7 @@ static int isd200_scsi_to_ata(struct scsi_cmnd *srb, struct us_data *us,
unsigned long capacity;
struct read_capacity_data readCapacityData;
- US_DEBUGP(" ATA OUT - SCSIOP_READ_CAPACITY\n");
+ usb_stor_dbg(us, " ATA OUT - SCSIOP_READ_CAPACITY\n");
if (ata_id_has_lba(id))
capacity = ata_id_u32(id, ATA_ID_LBA_CAPACITY) - 1;
@@ -1303,7 +1306,7 @@ static int isd200_scsi_to_ata(struct scsi_cmnd *srb, struct us_data *us,
break;
case READ_10:
- US_DEBUGP(" ATA OUT - SCSIOP_READ\n");
+ usb_stor_dbg(us, " ATA OUT - SCSIOP_READ\n");
lba = be32_to_cpu(*(__be32 *)&srb->cmnd[2]);
blockCount = (unsigned long)srb->cmnd[7]<<8 | (unsigned long)srb->cmnd[8];
@@ -1335,7 +1338,7 @@ static int isd200_scsi_to_ata(struct scsi_cmnd *srb, struct us_data *us,
break;
case WRITE_10:
- US_DEBUGP(" ATA OUT - SCSIOP_WRITE\n");
+ usb_stor_dbg(us, " ATA OUT - SCSIOP_WRITE\n");
lba = be32_to_cpu(*(__be32 *)&srb->cmnd[2]);
blockCount = (unsigned long)srb->cmnd[7]<<8 | (unsigned long)srb->cmnd[8];
@@ -1367,10 +1370,11 @@ static int isd200_scsi_to_ata(struct scsi_cmnd *srb, struct us_data *us,
break;
case ALLOW_MEDIUM_REMOVAL:
- US_DEBUGP(" ATA OUT - SCSIOP_MEDIUM_REMOVAL\n");
+ usb_stor_dbg(us, " ATA OUT - SCSIOP_MEDIUM_REMOVAL\n");
if (info->DeviceFlags & DF_REMOVABLE_MEDIA) {
- US_DEBUGP(" srb->cmnd[4] = 0x%X\n", srb->cmnd[4]);
+ usb_stor_dbg(us, " srb->cmnd[4] = 0x%X\n",
+ srb->cmnd[4]);
ataCdb->generic.SignatureByte0 = info->ConfigData.ATAMajorCommand;
ataCdb->generic.SignatureByte1 = info->ConfigData.ATAMinorCommand;
@@ -1380,25 +1384,25 @@ static int isd200_scsi_to_ata(struct scsi_cmnd *srb, struct us_data *us,
ATA_CMD_MEDIA_LOCK : ATA_CMD_MEDIA_UNLOCK;
isd200_srb_set_bufflen(srb, 0);
} else {
- US_DEBUGP(" Not removeable media, just report okay\n");
+ usb_stor_dbg(us, " Not removeable media, just report okay\n");
srb->result = SAM_STAT_GOOD;
sendToTransport = 0;
}
break;
case START_STOP:
- US_DEBUGP(" ATA OUT - SCSIOP_START_STOP_UNIT\n");
- US_DEBUGP(" srb->cmnd[4] = 0x%X\n", srb->cmnd[4]);
+ usb_stor_dbg(us, " ATA OUT - SCSIOP_START_STOP_UNIT\n");
+ usb_stor_dbg(us, " srb->cmnd[4] = 0x%X\n", srb->cmnd[4]);
if ((srb->cmnd[4] & 0x3) == 0x2) {
- US_DEBUGP(" Media Eject\n");
+ usb_stor_dbg(us, " Media Eject\n");
ataCdb->generic.SignatureByte0 = info->ConfigData.ATAMajorCommand;
ataCdb->generic.SignatureByte1 = info->ConfigData.ATAMinorCommand;
ataCdb->generic.TransferBlockSize = 0;
ataCdb->generic.RegisterSelect = REG_COMMAND;
ataCdb->write.CommandByte = ATA_COMMAND_MEDIA_EJECT;
} else if ((srb->cmnd[4] & 0x3) == 0x1) {
- US_DEBUGP(" Get Media Status\n");
+ usb_stor_dbg(us, " Get Media Status\n");
ataCdb->generic.SignatureByte0 = info->ConfigData.ATAMajorCommand;
ataCdb->generic.SignatureByte1 = info->ConfigData.ATAMinorCommand;
ataCdb->generic.TransferBlockSize = 1;
@@ -1406,14 +1410,15 @@ static int isd200_scsi_to_ata(struct scsi_cmnd *srb, struct us_data *us,
ataCdb->write.CommandByte = ATA_COMMAND_GET_MEDIA_STATUS;
isd200_srb_set_bufflen(srb, 0);
} else {
- US_DEBUGP(" Nothing to do, just report okay\n");
+ usb_stor_dbg(us, " Nothing to do, just report okay\n");
srb->result = SAM_STAT_GOOD;
sendToTransport = 0;
}
break;
default:
- US_DEBUGP("Unsupported SCSI command - 0x%X\n", srb->cmnd[0]);
+ usb_stor_dbg(us, "Unsupported SCSI command - 0x%X\n",
+ srb->cmnd[0]);
srb->result = DID_ERROR << 16;
sendToTransport = 0;
break;
@@ -1457,8 +1462,7 @@ static int isd200_init_info(struct us_data *us)
retStatus = ISD200_ERROR;
else {
info->id = kzalloc(ATA_ID_WORDS * 2, GFP_KERNEL);
- info->RegsBuf = (unsigned char *)
- kmalloc(sizeof(info->ATARegs), GFP_KERNEL);
+ info->RegsBuf = kmalloc(sizeof(info->ATARegs), GFP_KERNEL);
info->srb.sense_buffer =
kmalloc(SCSI_SENSE_BUFFERSIZE, GFP_KERNEL);
if (!info->id || !info->RegsBuf || !info->srb.sense_buffer) {
@@ -1471,8 +1475,7 @@ static int isd200_init_info(struct us_data *us)
if (retStatus == ISD200_GOOD) {
us->extra = info;
us->extra_destructor = isd200_free_info_ptrs;
- } else
- US_DEBUGP("ERROR - kmalloc failure\n");
+ }
return retStatus;
}
@@ -1483,19 +1486,19 @@ static int isd200_init_info(struct us_data *us)
static int isd200_Initialization(struct us_data *us)
{
- US_DEBUGP("ISD200 Initialization...\n");
+ usb_stor_dbg(us, "ISD200 Initialization...\n");
/* Initialize ISD200 info struct */
if (isd200_init_info(us) == ISD200_ERROR) {
- US_DEBUGP("ERROR Initializing ISD200 Info struct\n");
+ usb_stor_dbg(us, "ERROR Initializing ISD200 Info struct\n");
} else {
/* Get device specific data */
if (isd200_get_inquiry_data(us) != ISD200_GOOD)
- US_DEBUGP("ISD200 Initialization Failure\n");
+ usb_stor_dbg(us, "ISD200 Initialization Failure\n");
else
- US_DEBUGP("ISD200 Initialization complete\n");
+ usb_stor_dbg(us, "ISD200 Initialization complete\n");
}
return 0;
@@ -1520,7 +1523,7 @@ static void isd200_ata_command(struct scsi_cmnd *srb, struct us_data *us)
/* Make sure driver was initialized */
if (us->extra == NULL)
- US_DEBUGP("ERROR Driver not initialized\n");
+ usb_stor_dbg(us, "ERROR Driver not initialized\n");
scsi_set_resid(srb, 0);
/* scsi_bufflen might change in protocol translation to ata */
diff --git a/drivers/usb/storage/jumpshot.c b/drivers/usb/storage/jumpshot.c
index ddc78780b1a..563078be654 100644
--- a/drivers/usb/storage/jumpshot.c
+++ b/drivers/usb/storage/jumpshot.c
@@ -118,7 +118,7 @@ static inline int jumpshot_bulk_read(struct us_data *us,
if (len == 0)
return USB_STOR_XFER_GOOD;
- US_DEBUGP("jumpshot_bulk_read: len = %d\n", len);
+ usb_stor_dbg(us, "len = %d\n", len);
return usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
data, len, NULL);
}
@@ -131,7 +131,7 @@ static inline int jumpshot_bulk_write(struct us_data *us,
if (len == 0)
return USB_STOR_XFER_GOOD;
- US_DEBUGP("jumpshot_bulk_write: len = %d\n", len);
+ usb_stor_dbg(us, "len = %d\n", len);
return usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,
data, len, NULL);
}
@@ -152,8 +152,7 @@ static int jumpshot_get_status(struct us_data *us)
return USB_STOR_TRANSPORT_ERROR;
if (us->iobuf[0] != 0x50) {
- US_DEBUGP("jumpshot_get_status: 0x%2x\n",
- us->iobuf[0]);
+ usb_stor_dbg(us, "0x%2x\n", us->iobuf[0]);
return USB_STOR_TRANSPORT_ERROR;
}
@@ -218,7 +217,7 @@ static int jumpshot_read_data(struct us_data *us,
if (result != USB_STOR_XFER_GOOD)
goto leave;
- US_DEBUGP("jumpshot_read_data: %d bytes\n", len);
+ usb_stor_dbg(us, "%d bytes\n", len);
// Store the data in the transfer buffer
usb_stor_access_xfer_buf(buffer, len, us->srb,
@@ -314,7 +313,7 @@ static int jumpshot_write_data(struct us_data *us,
} while ((result != USB_STOR_TRANSPORT_GOOD) && (waitcount < 10));
if (result != USB_STOR_TRANSPORT_GOOD)
- US_DEBUGP("jumpshot_write_data: Gah! Waitcount = 10. Bad write!?\n");
+ usb_stor_dbg(us, "Gah! Waitcount = 10. Bad write!?\n");
sector += thistime;
totallen -= len;
@@ -349,8 +348,7 @@ static int jumpshot_id_device(struct us_data *us,
0, 0x20, 0, 6, command, 2);
if (rc != USB_STOR_XFER_GOOD) {
- US_DEBUGP("jumpshot_id_device: Gah! "
- "send_control for read_capacity failed\n");
+ usb_stor_dbg(us, "Gah! send_control for read_capacity failed\n");
rc = USB_STOR_TRANSPORT_ERROR;
goto leave;
}
@@ -400,17 +398,17 @@ static int jumpshot_handle_mode_sense(struct us_data *us,
switch (pc) {
case 0x0:
- US_DEBUGP("jumpshot_handle_mode_sense: Current values\n");
- break;
+ usb_stor_dbg(us, "Current values\n");
+ break;
case 0x1:
- US_DEBUGP("jumpshot_handle_mode_sense: Changeable values\n");
- break;
+ usb_stor_dbg(us, "Changeable values\n");
+ break;
case 0x2:
- US_DEBUGP("jumpshot_handle_mode_sense: Default values\n");
- break;
+ usb_stor_dbg(us, "Default values\n");
+ break;
case 0x3:
- US_DEBUGP("jumpshot_handle_mode_sense: Saves values\n");
- break;
+ usb_stor_dbg(us, "Saves values\n");
+ break;
}
memset(ptr, 0, 8);
@@ -494,17 +492,16 @@ static int jumpshot_transport(struct scsi_cmnd *srb, struct us_data *us)
if (!us->extra) {
us->extra = kzalloc(sizeof(struct jumpshot_info), GFP_NOIO);
- if (!us->extra) {
- US_DEBUGP("jumpshot_transport: Gah! Can't allocate storage for jumpshot info struct!\n");
+ if (!us->extra)
return USB_STOR_TRANSPORT_ERROR;
- }
+
us->extra_destructor = jumpshot_info_destructor;
}
info = (struct jumpshot_info *) (us->extra);
if (srb->cmnd[0] == INQUIRY) {
- US_DEBUGP("jumpshot_transport: INQUIRY. Returning bogus response.\n");
+ usb_stor_dbg(us, "INQUIRY - Returning bogus response\n");
memcpy(ptr, inquiry_response, sizeof(inquiry_response));
fill_inquiry_response(us, ptr, 36);
return USB_STOR_TRANSPORT_GOOD;
@@ -521,8 +518,8 @@ static int jumpshot_transport(struct scsi_cmnd *srb, struct us_data *us)
if (rc != USB_STOR_TRANSPORT_GOOD)
return rc;
- US_DEBUGP("jumpshot_transport: READ_CAPACITY: %ld sectors, %ld bytes per sector\n",
- info->sectors, info->ssize);
+ usb_stor_dbg(us, "READ_CAPACITY: %ld sectors, %ld bytes per sector\n",
+ info->sectors, info->ssize);
// build the reply
//
@@ -534,7 +531,7 @@ static int jumpshot_transport(struct scsi_cmnd *srb, struct us_data *us)
}
if (srb->cmnd[0] == MODE_SELECT_10) {
- US_DEBUGP("jumpshot_transport: Gah! MODE_SELECT_10.\n");
+ usb_stor_dbg(us, "Gah! MODE_SELECT_10\n");
return USB_STOR_TRANSPORT_ERROR;
}
@@ -544,7 +541,8 @@ static int jumpshot_transport(struct scsi_cmnd *srb, struct us_data *us)
blocks = ((u32)(srb->cmnd[7]) << 8) | ((u32)(srb->cmnd[8]));
- US_DEBUGP("jumpshot_transport: READ_10: read block 0x%04lx count %ld\n", block, blocks);
+ usb_stor_dbg(us, "READ_10: read block 0x%04lx count %ld\n",
+ block, blocks);
return jumpshot_read_data(us, info, block, blocks);
}
@@ -557,7 +555,8 @@ static int jumpshot_transport(struct scsi_cmnd *srb, struct us_data *us)
blocks = ((u32)(srb->cmnd[6]) << 24) | ((u32)(srb->cmnd[7]) << 16) |
((u32)(srb->cmnd[8]) << 8) | ((u32)(srb->cmnd[9]));
- US_DEBUGP("jumpshot_transport: READ_12: read block 0x%04lx count %ld\n", block, blocks);
+ usb_stor_dbg(us, "READ_12: read block 0x%04lx count %ld\n",
+ block, blocks);
return jumpshot_read_data(us, info, block, blocks);
}
@@ -567,7 +566,8 @@ static int jumpshot_transport(struct scsi_cmnd *srb, struct us_data *us)
blocks = ((u32)(srb->cmnd[7]) << 8) | ((u32)(srb->cmnd[8]));
- US_DEBUGP("jumpshot_transport: WRITE_10: write block 0x%04lx count %ld\n", block, blocks);
+ usb_stor_dbg(us, "WRITE_10: write block 0x%04lx count %ld\n",
+ block, blocks);
return jumpshot_write_data(us, info, block, blocks);
}
@@ -580,18 +580,19 @@ static int jumpshot_transport(struct scsi_cmnd *srb, struct us_data *us)
blocks = ((u32)(srb->cmnd[6]) << 24) | ((u32)(srb->cmnd[7]) << 16) |
((u32)(srb->cmnd[8]) << 8) | ((u32)(srb->cmnd[9]));
- US_DEBUGP("jumpshot_transport: WRITE_12: write block 0x%04lx count %ld\n", block, blocks);
+ usb_stor_dbg(us, "WRITE_12: write block 0x%04lx count %ld\n",
+ block, blocks);
return jumpshot_write_data(us, info, block, blocks);
}
if (srb->cmnd[0] == TEST_UNIT_READY) {
- US_DEBUGP("jumpshot_transport: TEST_UNIT_READY.\n");
+ usb_stor_dbg(us, "TEST_UNIT_READY\n");
return jumpshot_get_status(us);
}
if (srb->cmnd[0] == REQUEST_SENSE) {
- US_DEBUGP("jumpshot_transport: REQUEST_SENSE.\n");
+ usb_stor_dbg(us, "REQUEST_SENSE\n");
memset(ptr, 0, 18);
ptr[0] = 0xF0;
@@ -605,12 +606,12 @@ static int jumpshot_transport(struct scsi_cmnd *srb, struct us_data *us)
}
if (srb->cmnd[0] == MODE_SENSE) {
- US_DEBUGP("jumpshot_transport: MODE_SENSE_6 detected\n");
+ usb_stor_dbg(us, "MODE_SENSE_6 detected\n");
return jumpshot_handle_mode_sense(us, srb, 1);
}
if (srb->cmnd[0] == MODE_SENSE_10) {
- US_DEBUGP("jumpshot_transport: MODE_SENSE_10 detected\n");
+ usb_stor_dbg(us, "MODE_SENSE_10 detected\n");
return jumpshot_handle_mode_sense(us, srb, 0);
}
@@ -624,7 +625,7 @@ static int jumpshot_transport(struct scsi_cmnd *srb, struct us_data *us)
if (srb->cmnd[0] == START_STOP) {
/* this is used by sd.c'check_scsidisk_media_change to detect
media change */
- US_DEBUGP("jumpshot_transport: START_STOP.\n");
+ usb_stor_dbg(us, "START_STOP\n");
/* the first jumpshot_id_device after a media change returns
an error (determined experimentally) */
rc = jumpshot_id_device(us, info);
@@ -638,8 +639,8 @@ static int jumpshot_transport(struct scsi_cmnd *srb, struct us_data *us)
return rc;
}
- US_DEBUGP("jumpshot_transport: Gah! Unknown command: %d (0x%x)\n",
- srb->cmnd[0], srb->cmnd[0]);
+ usb_stor_dbg(us, "Gah! Unknown command: %d (0x%x)\n",
+ srb->cmnd[0], srb->cmnd[0]);
info->sense_key = 0x05;
info->sense_asc = 0x20;
info->sense_ascq = 0x00;
diff --git a/drivers/usb/storage/karma.c b/drivers/usb/storage/karma.c
index f085ffb606c..94d16ee5e84 100644
--- a/drivers/usb/storage/karma.c
+++ b/drivers/usb/storage/karma.c
@@ -106,7 +106,7 @@ static int rio_karma_send_command(char cmd, struct us_data *us)
static unsigned char seq = 1;
struct karma_data *data = (struct karma_data *) us->extra;
- US_DEBUGP("karma: sending command %04x\n", cmd);
+ usb_stor_dbg(us, "sending command %04x\n", cmd);
memset(us->iobuf, 0, RIO_SEND_LEN);
memcpy(us->iobuf, RIO_PREFIX, RIO_PREFIX_LEN);
us->iobuf[5] = cmd;
@@ -139,10 +139,10 @@ static int rio_karma_send_command(char cmd, struct us_data *us)
if (seq == 0)
seq = 1;
- US_DEBUGP("karma: sent command %04x\n", cmd);
+ usb_stor_dbg(us, "sent command %04x\n", cmd);
return 0;
err:
- US_DEBUGP("karma: command %04x failed\n", cmd);
+ usb_stor_dbg(us, "command %04x failed\n", cmd);
return USB_STOR_TRANSPORT_FAILED;
}
diff --git a/drivers/usb/storage/onetouch.c b/drivers/usb/storage/onetouch.c
index cb79de61f4c..26964895c88 100644
--- a/drivers/usb/storage/onetouch.c
+++ b/drivers/usb/storage/onetouch.c
@@ -195,6 +195,7 @@ static int onetouch_connect_input(struct us_data *ss)
pipe = usb_rcvintpipe(udev, endpoint->bEndpointAddress);
maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe));
+ maxp = min(maxp, ONETOUCH_PKT_LEN);
onetouch = kzalloc(sizeof(struct usb_onetouch), GFP_KERNEL);
input_dev = input_allocate_device();
@@ -245,8 +246,7 @@ static int onetouch_connect_input(struct us_data *ss)
input_dev->open = usb_onetouch_open;
input_dev->close = usb_onetouch_close;
- usb_fill_int_urb(onetouch->irq, udev, pipe, onetouch->data,
- (maxp > 8 ? 8 : maxp),
+ usb_fill_int_urb(onetouch->irq, udev, pipe, onetouch->data, maxp,
usb_onetouch_irq, onetouch, endpoint->bInterval);
onetouch->irq->transfer_dma = onetouch->data_dma;
onetouch->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
diff --git a/drivers/usb/storage/option_ms.c b/drivers/usb/storage/option_ms.c
index e0f76bb0591..b2b35b1d7de 100644
--- a/drivers/usb/storage/option_ms.c
+++ b/drivers/usb/storage/option_ms.c
@@ -50,7 +50,7 @@ static int option_rezero(struct us_data *us)
char *buffer;
int result;
- US_DEBUGP("Option MS: %s", "DEVICE MODE SWITCH\n");
+ usb_stor_dbg(us, "Option MS: %s\n", "DEVICE MODE SWITCH");
buffer = kzalloc(RESPONSE_LEN, GFP_KERNEL);
if (buffer == NULL)
@@ -95,7 +95,7 @@ static int option_inquiry(struct us_data *us)
char *buffer;
int result;
- US_DEBUGP("Option MS: %s", "device inquiry for vendor name\n");
+ usb_stor_dbg(us, "Option MS: %s\n", "device inquiry for vendor name");
buffer = kzalloc(0x24, GFP_KERNEL);
if (buffer == NULL)
@@ -138,31 +138,32 @@ int option_ms_init(struct us_data *us)
{
int result;
- US_DEBUGP("Option MS: option_ms_init called\n");
+ usb_stor_dbg(us, "Option MS: %s\n", "option_ms_init called");
/* Additional test for vendor information via INQUIRY,
* because some vendor/product IDs are ambiguous
*/
result = option_inquiry(us);
if (result != 0) {
- US_DEBUGP("Option MS: vendor is not Option or not determinable,"
- " no action taken\n");
+ usb_stor_dbg(us, "Option MS: %s\n",
+ "vendor is not Option or not determinable, no action taken");
return 0;
} else
- US_DEBUGP("Option MS: this is a genuine Option device,"
- " proceeding\n");
+ usb_stor_dbg(us, "Option MS: %s\n",
+ "this is a genuine Option device, proceeding");
/* Force Modem mode */
if (option_zero_cd == ZCD_FORCE_MODEM) {
- US_DEBUGP("Option MS: %s", "Forcing Modem Mode\n");
+ usb_stor_dbg(us, "Option MS: %s\n", "Forcing Modem Mode");
result = option_rezero(us);
if (result != USB_STOR_XFER_GOOD)
- US_DEBUGP("Option MS: Failed to switch to modem mode.\n");
+ usb_stor_dbg(us, "Option MS: %s\n",
+ "Failed to switch to modem mode");
return -EIO;
} else if (option_zero_cd == ZCD_ALLOW_MS) {
/* Allow Mass Storage mode (keep CD-Rom) */
- US_DEBUGP("Option MS: %s", "Allowing Mass Storage Mode if device"
- " requests it\n");
+ usb_stor_dbg(us, "Option MS: %s\n",
+ "Allowing Mass Storage Mode if device requests it");
}
return 0;
diff --git a/drivers/usb/storage/realtek_cr.c b/drivers/usb/storage/realtek_cr.c
index 6c3586a4c95..4797228747f 100644
--- a/drivers/usb/storage/realtek_cr.c
+++ b/drivers/usb/storage/realtek_cr.c
@@ -254,8 +254,8 @@ static int rts51x_bulk_transport(struct us_data *us, u8 lun,
/* check bulk status */
if (bcs->Signature != cpu_to_le32(US_BULK_CS_SIGN)) {
- US_DEBUGP("Signature mismatch: got %08X, expecting %08X\n",
- le32_to_cpu(bcs->Signature), US_BULK_CS_SIGN);
+ usb_stor_dbg(us, "Signature mismatch: got %08X, expecting %08X\n",
+ le32_to_cpu(bcs->Signature), US_BULK_CS_SIGN);
return USB_STOR_TRANSPORT_ERROR;
}
@@ -351,8 +351,8 @@ static int rts51x_get_max_lun(struct us_data *us)
USB_RECIP_INTERFACE,
0, us->ifnum, us->iobuf, 1, 10 * HZ);
- US_DEBUGP("GetMaxLUN command result is %d, data is %d\n",
- result, us->iobuf[0]);
+ usb_stor_dbg(us, "GetMaxLUN command result is %d, data is %d\n",
+ result, us->iobuf[0]);
/* if we have a successful request, return the result */
if (result > 0)
@@ -371,7 +371,7 @@ static int rts51x_read_mem(struct us_data *us, u16 addr, u8 *data, u16 len)
if (buf == NULL)
return USB_STOR_TRANSPORT_ERROR;
- US_DEBUGP("%s, addr = 0x%x, len = %d\n", __func__, addr, len);
+ usb_stor_dbg(us, "addr = 0x%x, len = %d\n", addr, len);
cmnd[0] = 0xF0;
cmnd[1] = 0x0D;
@@ -402,7 +402,7 @@ static int rts51x_write_mem(struct us_data *us, u16 addr, u8 *data, u16 len)
if (buf == NULL)
return USB_STOR_TRANSPORT_ERROR;
- US_DEBUGP("%s, addr = 0x%x, len = %d\n", __func__, addr, len);
+ usb_stor_dbg(us, "addr = 0x%x, len = %d\n", addr, len);
cmnd[0] = 0xF0;
cmnd[1] = 0x0E;
@@ -431,7 +431,7 @@ static int rts51x_read_status(struct us_data *us,
if (buf == NULL)
return USB_STOR_TRANSPORT_ERROR;
- US_DEBUGP("%s, lun = %d\n", __func__, lun);
+ usb_stor_dbg(us, "lun = %d\n", lun);
cmnd[0] = 0xF0;
cmnd[1] = 0x09;
@@ -458,7 +458,7 @@ static int rts51x_check_status(struct us_data *us, u8 lun)
if (retval != STATUS_SUCCESS)
return -EIO;
- US_DEBUGP("chip->status_len = %d\n", chip->status_len);
+ usb_stor_dbg(us, "chip->status_len = %d\n", chip->status_len);
chip->status[lun].vid = ((u16) buf[0] << 8) | buf[1];
chip->status[lun].pid = ((u16) buf[2] << 8) | buf[3];
@@ -509,7 +509,7 @@ static int __do_config_autodelink(struct us_data *us, u8 *data, u16 len)
u8 cmnd[12] = {0};
u8 *buf;
- US_DEBUGP("%s, addr = 0xfe47, len = %d\n", __FUNCTION__, len);
+ usb_stor_dbg(us, "addr = 0xfe47, len = %d\n", len);
buf = kmemdup(data, len, GFP_NOIO);
if (!buf)
@@ -549,7 +549,7 @@ static int do_config_autodelink(struct us_data *us, int enable, int force)
value &= ~0x03;
}
- US_DEBUGP("In %s,set 0xfe47 to 0x%x\n", __func__, value);
+ usb_stor_dbg(us, "set 0xfe47 to 0x%x\n", value);
/* retval = rts51x_write_mem(us, 0xFE47, &value, 1); */
retval = __do_config_autodelink(us, &value, 1);
@@ -565,8 +565,6 @@ static int config_autodelink_after_power_on(struct us_data *us)
int retval;
u8 value;
- US_DEBUGP("%s: <---\n", __func__);
-
if (!CHK_AUTO_DELINK(chip))
return 0;
@@ -624,8 +622,6 @@ static int config_autodelink_after_power_on(struct us_data *us)
}
}
- US_DEBUGP("%s: --->\n", __func__);
-
return 0;
}
@@ -635,8 +631,6 @@ static int config_autodelink_before_power_down(struct us_data *us)
int retval;
u8 value;
- US_DEBUGP("%s: <---\n", __func__);
-
if (!CHK_AUTO_DELINK(chip))
return 0;
@@ -698,8 +692,6 @@ static int config_autodelink_before_power_down(struct us_data *us)
}
}
- US_DEBUGP("%s: --->\n", __func__);
-
return 0;
}
@@ -709,23 +701,19 @@ static void fw5895_init(struct us_data *us)
int retval;
u8 val;
- US_DEBUGP("%s: <---\n", __func__);
-
if ((PRODUCT_ID(chip) != 0x0158) || (FW_VERSION(chip) != 0x5895)) {
- US_DEBUGP("Not the specified device, return immediately!\n");
+ usb_stor_dbg(us, "Not the specified device, return immediately!\n");
} else {
retval = rts51x_read_mem(us, 0xFD6F, &val, 1);
if (retval == STATUS_SUCCESS && (val & 0x1F) == 0) {
val = 0x1F;
retval = rts51x_write_mem(us, 0xFD70, &val, 1);
if (retval != STATUS_SUCCESS)
- US_DEBUGP("Write memory fail\n");
+ usb_stor_dbg(us, "Write memory fail\n");
} else {
- US_DEBUGP("Read memory fail, OR (val & 0x1F) != 0\n");
+ usb_stor_dbg(us, "Read memory fail, OR (val & 0x1F) != 0\n");
}
}
-
- US_DEBUGP("%s: --->\n", __func__);
}
#ifdef CONFIG_REALTEK_AUTOPM
@@ -735,10 +723,8 @@ static void fw5895_set_mmc_wp(struct us_data *us)
int retval;
u8 buf[13];
- US_DEBUGP("%s: <---\n", __func__);
-
if ((PRODUCT_ID(chip) != 0x0158) || (FW_VERSION(chip) != 0x5895)) {
- US_DEBUGP("Not the specified device, return immediately!\n");
+ usb_stor_dbg(us, "Not the specified device, return immediately!\n");
} else {
retval = rts51x_read_mem(us, 0xFD6F, buf, 1);
if (retval == STATUS_SUCCESS && (buf[0] & 0x24) == 0x24) {
@@ -748,26 +734,24 @@ static void fw5895_set_mmc_wp(struct us_data *us)
buf[0] |= 0x04;
retval = rts51x_write_mem(us, 0xFD70, buf, 1);
if (retval != STATUS_SUCCESS)
- US_DEBUGP("Write memory fail\n");
+ usb_stor_dbg(us, "Write memory fail\n");
} else {
- US_DEBUGP("Read memory fail\n");
+ usb_stor_dbg(us, "Read memory fail\n");
}
} else {
- US_DEBUGP("Read memory fail, OR (buf[0]&0x24)!=0x24\n");
+ usb_stor_dbg(us, "Read memory fail, OR (buf[0]&0x24)!=0x24\n");
}
}
-
- US_DEBUGP("%s: --->\n", __func__);
}
static void rts51x_modi_suspend_timer(struct rts51x_chip *chip)
{
- US_DEBUGP("%s: <---, state:%d\n", __func__, rts51x_get_stat(chip));
+ struct us_data *us = chip->us;
+
+ usb_stor_dbg(us, "state:%d\n", rts51x_get_stat(chip));
chip->timer_expires = jiffies + msecs_to_jiffies(1000*ss_delay);
mod_timer(&chip->rts51x_suspend_timer, chip->timer_expires);
-
- US_DEBUGP("%s: --->\n", __func__);
}
static void rts51x_suspend_timer_fn(unsigned long data)
@@ -775,8 +759,6 @@ static void rts51x_suspend_timer_fn(unsigned long data)
struct rts51x_chip *chip = (struct rts51x_chip *)data;
struct us_data *us = chip->us;
- US_DEBUGP("%s: <---\n", __func__);
-
switch (rts51x_get_stat(chip)) {
case RTS51X_STAT_INIT:
case RTS51X_STAT_RUN:
@@ -784,32 +766,25 @@ static void rts51x_suspend_timer_fn(unsigned long data)
break;
case RTS51X_STAT_IDLE:
case RTS51X_STAT_SS:
- US_DEBUGP("%s: RTS51X_STAT_SS, intf->pm_usage_cnt:%d,"
- "power.usage:%d\n", __func__,
- atomic_read(&us->pusb_intf->pm_usage_cnt),
- atomic_read(&us->pusb_intf->dev.power.usage_count));
+ usb_stor_dbg(us, "RTS51X_STAT_SS, intf->pm_usage_cnt:%d, power.usage:%d\n",
+ atomic_read(&us->pusb_intf->pm_usage_cnt),
+ atomic_read(&us->pusb_intf->dev.power.usage_count));
if (atomic_read(&us->pusb_intf->pm_usage_cnt) > 0) {
- US_DEBUGP("%s: Ready to enter SS state.\n",
- __func__);
+ usb_stor_dbg(us, "Ready to enter SS state\n");
rts51x_set_stat(chip, RTS51X_STAT_SS);
/* ignore mass storage interface's children */
pm_suspend_ignore_children(&us->pusb_intf->dev, true);
usb_autopm_put_interface_async(us->pusb_intf);
- US_DEBUGP("%s: RTS51X_STAT_SS 01,"
- "intf->pm_usage_cnt:%d, power.usage:%d\n",
- __func__,
- atomic_read(&us->pusb_intf->pm_usage_cnt),
- atomic_read(
- &us->pusb_intf->dev.power.usage_count));
+ usb_stor_dbg(us, "RTS51X_STAT_SS 01, intf->pm_usage_cnt:%d, power.usage:%d\n",
+ atomic_read(&us->pusb_intf->pm_usage_cnt),
+ atomic_read(&us->pusb_intf->dev.power.usage_count));
}
break;
default:
- US_DEBUGP("%s: Unknonwn state !!!\n", __func__);
+ usb_stor_dbg(us, "Unknown state !!!\n");
break;
}
-
- US_DEBUGP("%s: --->\n", __func__);
}
static inline int working_scsi(struct scsi_cmnd *srb)
@@ -834,24 +809,21 @@ static void rts51x_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
};
int ret;
- US_DEBUGP("%s: <---\n", __func__);
-
if (working_scsi(srb)) {
- US_DEBUGP("%s: working scsi, intf->pm_usage_cnt:%d,"
- "power.usage:%d\n", __func__,
- atomic_read(&us->pusb_intf->pm_usage_cnt),
- atomic_read(&us->pusb_intf->dev.power.usage_count));
+ usb_stor_dbg(us, "working scsi, intf->pm_usage_cnt:%d, power.usage:%d\n",
+ atomic_read(&us->pusb_intf->pm_usage_cnt),
+ atomic_read(&us->pusb_intf->dev.power.usage_count));
if (atomic_read(&us->pusb_intf->pm_usage_cnt) <= 0) {
ret = usb_autopm_get_interface(us->pusb_intf);
- US_DEBUGP("%s: working scsi, ret=%d\n", __func__, ret);
+ usb_stor_dbg(us, "working scsi, ret=%d\n", ret);
}
if (rts51x_get_stat(chip) != RTS51X_STAT_RUN)
rts51x_set_stat(chip, RTS51X_STAT_RUN);
chip->proto_handler_backup(srb, us);
} else {
if (rts51x_get_stat(chip) == RTS51X_STAT_SS) {
- US_DEBUGP("%s: NOT working scsi\n", __func__);
+ usb_stor_dbg(us, "NOT working scsi\n");
if ((srb->cmnd[0] == TEST_UNIT_READY) &&
(chip->pwr_state == US_SUSPEND)) {
if (TST_LUN_READY(chip, srb->device->lun)) {
@@ -862,8 +834,7 @@ static void rts51x_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
media_not_present,
US_SENSE_SIZE);
}
- US_DEBUGP("%s: TEST_UNIT_READY--->\n",
- __func__);
+ usb_stor_dbg(us, "TEST_UNIT_READY\n");
goto out;
}
if (srb->cmnd[0] == ALLOW_MEDIUM_REMOVAL) {
@@ -876,12 +847,11 @@ static void rts51x_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
} else {
srb->result = SAM_STAT_GOOD;
}
- US_DEBUGP("%s: ALLOW_MEDIUM_REMOVAL--->\n",
- __func__);
+ usb_stor_dbg(us, "ALLOW_MEDIUM_REMOVAL\n");
goto out;
}
} else {
- US_DEBUGP("%s: NOT working scsi, not SS\n", __func__);
+ usb_stor_dbg(us, "NOT working scsi, not SS\n");
chip->proto_handler_backup(srb, us);
/* Check whether card is plugged in */
if (srb->cmnd[0] == TEST_UNIT_READY) {
@@ -901,11 +871,9 @@ static void rts51x_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
}
}
out:
- US_DEBUGP("%s: state:%d\n", __func__, rts51x_get_stat(chip));
+ usb_stor_dbg(us, "state:%d\n", rts51x_get_stat(chip));
if (rts51x_get_stat(chip) == RTS51X_STAT_RUN)
rts51x_modi_suspend_timer(chip);
-
- US_DEBUGP("%s: --->\n", __func__);
}
static int realtek_cr_autosuspend_setup(struct us_data *us)
@@ -923,7 +891,7 @@ static int realtek_cr_autosuspend_setup(struct us_data *us)
retval = rts51x_read_status(us, 0, buf, 16, &(chip->status_len));
if (retval != STATUS_SUCCESS) {
- US_DEBUGP("Read status fail\n");
+ usb_stor_dbg(us, "Read status fail\n");
return -EIO;
}
status = chip->status;
@@ -966,11 +934,13 @@ static int realtek_cr_autosuspend_setup(struct us_data *us)
static void realtek_cr_destructor(void *extra)
{
struct rts51x_chip *chip = (struct rts51x_chip *)extra;
-
- US_DEBUGP("%s: <---\n", __func__);
+ struct us_data *us;
if (!chip)
return;
+
+ us = chip->us;
+
#ifdef CONFIG_REALTEK_AUTOPM
if (ss_en) {
del_timer(&chip->rts51x_suspend_timer);
@@ -985,8 +955,6 @@ static int realtek_cr_suspend(struct usb_interface *iface, pm_message_t message)
{
struct us_data *us = usb_get_intfdata(iface);
- US_DEBUGP("%s: <---\n", __func__);
-
/* wait until no command is running */
mutex_lock(&us->dev_mutex);
@@ -994,8 +962,6 @@ static int realtek_cr_suspend(struct usb_interface *iface, pm_message_t message)
mutex_unlock(&us->dev_mutex);
- US_DEBUGP("%s: --->\n", __func__);
-
return 0;
}
@@ -1003,13 +969,9 @@ static int realtek_cr_resume(struct usb_interface *iface)
{
struct us_data *us = usb_get_intfdata(iface);
- US_DEBUGP("%s: <---\n", __func__);
-
fw5895_init(us);
config_autodelink_after_power_on(us);
- US_DEBUGP("%s: --->\n", __func__);
-
return 0;
}
#else
@@ -1030,7 +992,7 @@ static int init_realtek_cr(struct us_data *us)
us->extra_destructor = realtek_cr_destructor;
us->max_lun = chip->max_lun = rts51x_get_max_lun(us);
- US_DEBUGP("chip->max_lun = %d\n", chip->max_lun);
+ usb_stor_dbg(us, "chip->max_lun = %d\n", chip->max_lun);
size = (chip->max_lun + 1) * sizeof(struct rts51x_status);
chip->status = kzalloc(size, GFP_KERNEL);
@@ -1057,7 +1019,7 @@ static int init_realtek_cr(struct us_data *us)
}
#endif
- US_DEBUGP("chip->flag = 0x%x\n", chip->flag);
+ usb_stor_dbg(us, "chip->flag = 0x%x\n", chip->flag);
(void)config_autodelink_after_power_on(us);
@@ -1079,7 +1041,7 @@ static int realtek_cr_probe(struct usb_interface *intf,
struct us_data *us;
int result;
- US_DEBUGP("Probe Realtek Card Reader!\n");
+ dev_dbg(&intf->dev, "Probe Realtek Card Reader!\n");
result = usb_stor_probe1(&us, intf, id,
(id - realtek_cr_ids) +
diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
index 92f35abee92..4faa982807f 100644
--- a/drivers/usb/storage/scsiglue.c
+++ b/drivers/usb/storage/scsiglue.c
@@ -313,8 +313,6 @@ static int queuecommand_lck(struct scsi_cmnd *srb,
{
struct us_data *us = host_to_us(srb->device->host);
- US_DEBUGP("%s called\n", __func__);
-
/* check for state-transition errors */
if (us->srb != NULL) {
printk(KERN_ERR USB_STORAGE "Error in %s: us->srb = %p\n",
@@ -324,7 +322,7 @@ static int queuecommand_lck(struct scsi_cmnd *srb,
/* fail the command if we are disconnecting */
if (test_bit(US_FLIDX_DISCONNECTING, &us->dflags)) {
- US_DEBUGP("Fail command during disconnect\n");
+ usb_stor_dbg(us, "Fail command during disconnect\n");
srb->result = DID_NO_CONNECT << 16;
done(srb);
return 0;
@@ -349,7 +347,7 @@ static int command_abort(struct scsi_cmnd *srb)
{
struct us_data *us = host_to_us(srb->device->host);
- US_DEBUGP("%s called\n", __func__);
+ usb_stor_dbg(us, "%s called\n", __func__);
/* us->srb together with the TIMED_OUT, RESETTING, and ABORTING
* bits are protected by the host lock. */
@@ -358,7 +356,7 @@ static int command_abort(struct scsi_cmnd *srb)
/* Is this command still active? */
if (us->srb != srb) {
scsi_unlock(us_to_host(us));
- US_DEBUGP ("-- nothing to abort\n");
+ usb_stor_dbg(us, "-- nothing to abort\n");
return FAILED;
}
@@ -386,7 +384,7 @@ static int device_reset(struct scsi_cmnd *srb)
struct us_data *us = host_to_us(srb->device->host);
int result;
- US_DEBUGP("%s called\n", __func__);
+ usb_stor_dbg(us, "%s called\n", __func__);
/* lock the device pointers and do the reset */
mutex_lock(&(us->dev_mutex));
@@ -402,7 +400,8 @@ static int bus_reset(struct scsi_cmnd *srb)
struct us_data *us = host_to_us(srb->device->host);
int result;
- US_DEBUGP("%s called\n", __func__);
+ usb_stor_dbg(us, "%s called\n", __func__);
+
result = usb_stor_port_reset(us);
return result < 0 ? FAILED : SUCCESS;
}
diff --git a/drivers/usb/storage/sddr09.c b/drivers/usb/storage/sddr09.c
index 7bd54e0d512..732027f3320 100644
--- a/drivers/usb/storage/sddr09.c
+++ b/drivers/usb/storage/sddr09.c
@@ -105,8 +105,6 @@ static struct us_unusual_dev sddr09_unusual_dev_list[] = {
#define LSB_of(s) ((s)&0xFF)
#define MSB_of(s) ((s)>>8)
-/* #define US_DEBUGP printk */
-
/*
* First some stuff that does not belong here:
* data on SmartMedia and other cards, completely
@@ -347,7 +345,7 @@ sddr09_test_unit_ready(struct us_data *us) {
result = sddr09_send_scsi_command(us, command, 6);
- US_DEBUGP("sddr09_test_unit_ready returns %d\n", result);
+ usb_stor_dbg(us, "sddr09_test_unit_ready returns %d\n", result);
return result;
}
@@ -423,8 +421,8 @@ sddr09_readX(struct us_data *us, int x, unsigned long fromaddress,
result = sddr09_send_scsi_command(us, command, 12);
if (result) {
- US_DEBUGP("Result for send_control in sddr09_read2%d %d\n",
- x, result);
+ usb_stor_dbg(us, "Result for send_control in sddr09_read2%d %d\n",
+ x, result);
return result;
}
@@ -432,8 +430,8 @@ sddr09_readX(struct us_data *us, int x, unsigned long fromaddress,
buf, bulklen, use_sg, NULL);
if (result != USB_STOR_XFER_GOOD) {
- US_DEBUGP("Result for bulk_transfer in sddr09_read2%d %d\n",
- x, result);
+ usb_stor_dbg(us, "Result for bulk_transfer in sddr09_read2%d %d\n",
+ x, result);
return -EIO;
}
return 0;
@@ -494,8 +492,7 @@ sddr09_read22(struct us_data *us, unsigned long fromaddress,
int nr_of_pages, int pageshift, unsigned char *buf, int use_sg) {
int bulklen = (nr_of_pages << pageshift) + (nr_of_pages << CONTROL_SHIFT);
- US_DEBUGP("sddr09_read22: reading %d pages, %d bytes\n",
- nr_of_pages, bulklen);
+ usb_stor_dbg(us, "reading %d pages, %d bytes\n", nr_of_pages, bulklen);
return sddr09_readX(us, 2, fromaddress, nr_of_pages, bulklen,
buf, use_sg);
}
@@ -538,7 +535,7 @@ sddr09_erase(struct us_data *us, unsigned long Eaddress) {
unsigned char *command = us->iobuf;
int result;
- US_DEBUGP("sddr09_erase: erase address %lu\n", Eaddress);
+ usb_stor_dbg(us, "erase address %lu\n", Eaddress);
memset(command, 0, 12);
command[0] = 0xEA;
@@ -551,8 +548,8 @@ sddr09_erase(struct us_data *us, unsigned long Eaddress) {
result = sddr09_send_scsi_command(us, command, 12);
if (result)
- US_DEBUGP("Result for send_control in sddr09_erase %d\n",
- result);
+ usb_stor_dbg(us, "Result for send_control in sddr09_erase %d\n",
+ result);
return result;
}
@@ -609,8 +606,8 @@ sddr09_writeX(struct us_data *us,
result = sddr09_send_scsi_command(us, command, 12);
if (result) {
- US_DEBUGP("Result for send_control in sddr09_writeX %d\n",
- result);
+ usb_stor_dbg(us, "Result for send_control in sddr09_writeX %d\n",
+ result);
return result;
}
@@ -618,8 +615,8 @@ sddr09_writeX(struct us_data *us,
buf, bulklen, use_sg, NULL);
if (result != USB_STOR_XFER_GOOD) {
- US_DEBUGP("Result for bulk_transfer in sddr09_writeX %d\n",
- result);
+ usb_stor_dbg(us, "Result for bulk_transfer in sddr09_writeX %d\n",
+ result);
return -EIO;
}
return 0;
@@ -687,8 +684,8 @@ sddr09_read_sg_test_only(struct us_data *us) {
result = sddr09_send_scsi_command(us, command, 4*nsg+3);
if (result) {
- US_DEBUGP("Result for send_control in sddr09_read_sg %d\n",
- result);
+ usb_stor_dbg(us, "Result for send_control in sddr09_read_sg %d\n",
+ result);
return result;
}
@@ -700,8 +697,8 @@ sddr09_read_sg_test_only(struct us_data *us) {
buf, bulklen, NULL);
kfree(buf);
if (result != USB_STOR_XFER_GOOD) {
- US_DEBUGP("Result for bulk_transfer in sddr09_read_sg %d\n",
- result);
+ usb_stor_dbg(us, "Result for bulk_transfer in sddr09_read_sg %d\n",
+ result);
return -EIO;
}
@@ -727,7 +724,7 @@ sddr09_read_status(struct us_data *us, unsigned char *status) {
unsigned char *data = us->iobuf;
int result;
- US_DEBUGP("Reading status...\n");
+ usb_stor_dbg(us, "Reading status...\n");
memset(command, 0, 12);
command[0] = 0xEC;
@@ -789,8 +786,8 @@ sddr09_read_data(struct us_data *us,
/* Not overflowing capacity? */
if (lba >= maxlba) {
- US_DEBUGP("Error: Requested lba %u exceeds "
- "maximum %u\n", lba, maxlba);
+ usb_stor_dbg(us, "Error: Requested lba %u exceeds maximum %u\n",
+ lba, maxlba);
result = -EIO;
break;
}
@@ -800,8 +797,8 @@ sddr09_read_data(struct us_data *us,
if (pba == UNDEF) { /* this lba was never written */
- US_DEBUGP("Read %d zero pages (LBA %d) page %d\n",
- pages, lba, page);
+ usb_stor_dbg(us, "Read %d zero pages (LBA %d) page %d\n",
+ pages, lba, page);
/* This is not really an error. It just means
that the block has never been written.
@@ -811,9 +808,8 @@ sddr09_read_data(struct us_data *us,
memset(buffer, 0, len);
} else {
- US_DEBUGP("Read %d pages, from PBA %d"
- " (LBA %d) page %d\n",
- pages, pba, lba, page);
+ usb_stor_dbg(us, "Read %d pages, from PBA %d (LBA %d) page %d\n",
+ pages, pba, lba, page);
address = ((pba << info->blockshift) + page) <<
info->pageshift;
@@ -916,14 +912,14 @@ sddr09_write_lba(struct us_data *us, unsigned int lba,
cptr = bptr + info->pagesize;
nand_compute_ecc(bptr, ecc);
if (!nand_compare_ecc(cptr+13, ecc)) {
- US_DEBUGP("Warning: bad ecc in page %d- of pba %d\n",
- i, pba);
+ usb_stor_dbg(us, "Warning: bad ecc in page %d- of pba %d\n",
+ i, pba);
nand_store_ecc(cptr+13, ecc);
}
nand_compute_ecc(bptr+(info->pagesize / 2), ecc);
if (!nand_compare_ecc(cptr+8, ecc)) {
- US_DEBUGP("Warning: bad ecc in page %d+ of pba %d\n",
- i, pba);
+ usb_stor_dbg(us, "Warning: bad ecc in page %d+ of pba %d\n",
+ i, pba);
nand_store_ecc(cptr+8, ecc);
}
cptr[6] = cptr[11] = MSB_of(lbap);
@@ -943,22 +939,21 @@ sddr09_write_lba(struct us_data *us, unsigned int lba,
nand_store_ecc(cptr+8, ecc);
}
- US_DEBUGP("Rewrite PBA %d (LBA %d)\n", pba, lba);
+ usb_stor_dbg(us, "Rewrite PBA %d (LBA %d)\n", pba, lba);
result = sddr09_write_inplace(us, address>>1, info->blocksize,
info->pageshift, blockbuffer, 0);
- US_DEBUGP("sddr09_write_inplace returns %d\n", result);
+ usb_stor_dbg(us, "sddr09_write_inplace returns %d\n", result);
#if 0
{
unsigned char status = 0;
int result2 = sddr09_read_status(us, &status);
if (result2)
- US_DEBUGP("sddr09_write_inplace: cannot read status\n");
+ usb_stor_dbg(us, "cannot read status\n");
else if (status != 0xc0)
- US_DEBUGP("sddr09_write_inplace: status after write: 0x%x\n",
- status);
+ usb_stor_dbg(us, "status after write: 0x%x\n", status);
}
#endif
@@ -1031,8 +1026,8 @@ sddr09_write_data(struct us_data *us,
/* Not overflowing capacity? */
if (lba >= maxlba) {
- US_DEBUGP("Error: Requested lba %u exceeds "
- "maximum %u\n", lba, maxlba);
+ usb_stor_dbg(us, "Error: Requested lba %u exceeds maximum %u\n",
+ lba, maxlba);
result = -EIO;
break;
}
@@ -1064,8 +1059,8 @@ sddr09_read_control(struct us_data *us,
unsigned char *content,
int use_sg) {
- US_DEBUGP("Read control address %lu, blocks %d\n",
- address, blocks);
+ usb_stor_dbg(us, "Read control address %lu, blocks %d\n",
+ address, blocks);
return sddr09_read21(us, address, blocks,
CONTROL_SHIFT, content, use_sg);
@@ -1111,21 +1106,21 @@ sddr09_get_wp(struct us_data *us, struct sddr09_card_info *info) {
result = sddr09_read_status(us, &status);
if (result) {
- US_DEBUGP("sddr09_get_wp: read_status fails\n");
+ usb_stor_dbg(us, "read_status fails\n");
return result;
}
- US_DEBUGP("sddr09_get_wp: status 0x%02X", status);
+ usb_stor_dbg(us, "status 0x%02X", status);
if ((status & 0x80) == 0) {
info->flags |= SDDR09_WP; /* write protected */
- US_DEBUGP(" WP");
+ US_DEBUGPX(" WP");
}
if (status & 0x40)
- US_DEBUGP(" Ready");
+ US_DEBUGPX(" Ready");
if (status & LUNBITS)
- US_DEBUGP(" Suspended");
+ US_DEBUGPX(" Suspended");
if (status & 0x1)
- US_DEBUGP(" Error");
- US_DEBUGP("\n");
+ US_DEBUGPX(" Error");
+ US_DEBUGPX("\n");
return 0;
}
@@ -1154,12 +1149,12 @@ sddr09_get_cardinfo(struct us_data *us, unsigned char flags) {
char blurbtxt[256];
int result;
- US_DEBUGP("Reading capacity...\n");
+ usb_stor_dbg(us, "Reading capacity...\n");
result = sddr09_read_deviceID(us, deviceID);
if (result) {
- US_DEBUGP("Result of read_deviceID is %d\n", result);
+ usb_stor_dbg(us, "Result of read_deviceID is %d\n", result);
printk(KERN_WARNING "sddr09: could not read card info\n");
return NULL;
}
@@ -1392,7 +1387,7 @@ sddr09_read_map(struct us_data *us) {
lbact += ct;
}
info->lbact = lbact;
- US_DEBUGP("Found %d LBA's\n", lbact);
+ usb_stor_dbg(us, "Found %d LBA's\n", lbact);
result = 0;
done:
@@ -1423,18 +1418,18 @@ sddr09_common_init(struct us_data *us) {
/* set the configuration -- STALL is an acceptable response here */
if (us->pusb_dev->actconfig->desc.bConfigurationValue != 1) {
- US_DEBUGP("active config #%d != 1 ??\n", us->pusb_dev
- ->actconfig->desc.bConfigurationValue);
+ usb_stor_dbg(us, "active config #%d != 1 ??\n",
+ us->pusb_dev->actconfig->desc.bConfigurationValue);
return -EINVAL;
}
result = usb_reset_configuration(us->pusb_dev);
- US_DEBUGP("Result of usb_reset_configuration is %d\n", result);
+ usb_stor_dbg(us, "Result of usb_reset_configuration is %d\n", result);
if (result == -EPIPE) {
- US_DEBUGP("-- stall on control interface\n");
+ usb_stor_dbg(us, "-- stall on control interface\n");
} else if (result != 0) {
/* it's not a stall, but another error -- time to bail */
- US_DEBUGP("-- Unknown error. Rejecting device\n");
+ usb_stor_dbg(us, "-- Unknown error. Rejecting device\n");
return -EINVAL;
}
@@ -1464,20 +1459,20 @@ usb_stor_sddr09_dpcm_init(struct us_data *us) {
result = sddr09_send_command(us, 0x01, USB_DIR_IN, data, 2);
if (result) {
- US_DEBUGP("sddr09_init: send_command fails\n");
+ usb_stor_dbg(us, "send_command fails\n");
return result;
}
- US_DEBUGP("SDDR09init: %02X %02X\n", data[0], data[1]);
+ usb_stor_dbg(us, "%02X %02X\n", data[0], data[1]);
// get 07 02
result = sddr09_send_command(us, 0x08, USB_DIR_IN, data, 2);
if (result) {
- US_DEBUGP("sddr09_init: 2nd send_command fails\n");
+ usb_stor_dbg(us, "2nd send_command fails\n");
return result;
}
- US_DEBUGP("SDDR09init: %02X %02X\n", data[0], data[1]);
+ usb_stor_dbg(us, "%02X %02X\n", data[0], data[1]);
// get 07 00
result = sddr09_request_sense(us, data, 18);
@@ -1507,7 +1502,7 @@ static int dpcm_transport(struct scsi_cmnd *srb, struct us_data *us)
{
int ret;
- US_DEBUGP("dpcm_transport: LUN=%d\n", srb->device->lun);
+ usb_stor_dbg(us, "LUN=%d\n", srb->device->lun);
switch (srb->device->lun) {
case 0:
@@ -1533,8 +1528,7 @@ static int dpcm_transport(struct scsi_cmnd *srb, struct us_data *us)
break;
default:
- US_DEBUGP("dpcm_transport: Invalid LUN %d\n",
- srb->device->lun);
+ usb_stor_dbg(us, "Invalid LUN %d\n", srb->device->lun);
ret = USB_STOR_TRANSPORT_ERROR;
break;
}
@@ -1640,8 +1634,8 @@ static int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us)
or for all pages. */
/* %% We should check DBD %% */
if (modepage == 0x01 || modepage == 0x3F) {
- US_DEBUGP("SDDR09: Dummy up request for "
- "mode page 0x%x\n", modepage);
+ usb_stor_dbg(us, "Dummy up request for mode page 0x%x\n",
+ modepage);
memcpy(ptr, mode_page_01, sizeof(mode_page_01));
((__be16*)ptr)[0] = cpu_to_be16(sizeof(mode_page_01) - 2);
@@ -1667,8 +1661,8 @@ static int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us)
page |= short_pack(srb->cmnd[5], srb->cmnd[4]);
pages = short_pack(srb->cmnd[8], srb->cmnd[7]);
- US_DEBUGP("READ_10: read page %d pagect %d\n",
- page, pages);
+ usb_stor_dbg(us, "READ_10: read page %d pagect %d\n",
+ page, pages);
result = sddr09_read_data(us, page, pages);
return (result == 0 ? USB_STOR_TRANSPORT_GOOD :
@@ -1682,8 +1676,8 @@ static int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us)
page |= short_pack(srb->cmnd[5], srb->cmnd[4]);
pages = short_pack(srb->cmnd[8], srb->cmnd[7]);
- US_DEBUGP("WRITE_10: write page %d pagect %d\n",
- page, pages);
+ usb_stor_dbg(us, "WRITE_10: write page %d pagect %d\n",
+ page, pages);
result = sddr09_write_data(us, page, pages);
return (result == 0 ? USB_STOR_TRANSPORT_GOOD :
@@ -1710,12 +1704,12 @@ static int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us)
for (i=0; i<12; i++)
sprintf(ptr+strlen(ptr), "%02X ", srb->cmnd[i]);
- US_DEBUGP("SDDR09: Send control for command %s\n", ptr);
+ usb_stor_dbg(us, "Send control for command %s\n", ptr);
result = sddr09_send_scsi_command(us, srb->cmnd, 12);
if (result) {
- US_DEBUGP("sddr09_transport: sddr09_send_scsi_command "
- "returns %d\n", result);
+ usb_stor_dbg(us, "sddr09_send_scsi_command returns %d\n",
+ result);
return USB_STOR_TRANSPORT_ERROR;
}
@@ -1727,10 +1721,10 @@ static int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us)
unsigned int pipe = (srb->sc_data_direction == DMA_TO_DEVICE)
? us->send_bulk_pipe : us->recv_bulk_pipe;
- US_DEBUGP("SDDR09: %s %d bytes\n",
- (srb->sc_data_direction == DMA_TO_DEVICE) ?
- "sending" : "receiving",
- scsi_bufflen(srb));
+ usb_stor_dbg(us, "%s %d bytes\n",
+ (srb->sc_data_direction == DMA_TO_DEVICE) ?
+ "sending" : "receiving",
+ scsi_bufflen(srb));
result = usb_stor_bulk_srb(us, pipe, srb);
diff --git a/drivers/usb/storage/sddr55.c b/drivers/usb/storage/sddr55.c
index d278c5a99b7..aacedef9667 100644
--- a/drivers/usb/storage/sddr55.c
+++ b/drivers/usb/storage/sddr55.c
@@ -145,8 +145,7 @@ static int sddr55_status(struct us_data *us)
result = sddr55_bulk_transport(us,
DMA_TO_DEVICE, command, 8);
- US_DEBUGP("Result for send_command in status %d\n",
- result);
+ usb_stor_dbg(us, "Result for send_command in status %d\n", result);
if (result != USB_STOR_XFER_GOOD) {
set_sense_info (4, 0, 0); /* hardware error */
@@ -236,9 +235,8 @@ static int sddr55_read_data(struct us_data *us,
info->blocksize - page);
len = pages << info->pageshift;
- US_DEBUGP("Read %02X pages, from PBA %04X"
- " (LBA %04X) page %02X\n",
- pages, pba, lba, page);
+ usb_stor_dbg(us, "Read %02X pages, from PBA %04X (LBA %04X) page %02X\n",
+ pages, pba, lba, page);
if (pba == NOT_ALLOCATED) {
/* no pba for this lba, fill with zeroes */
@@ -261,8 +259,8 @@ static int sddr55_read_data(struct us_data *us,
result = sddr55_bulk_transport(us,
DMA_TO_DEVICE, command, 8);
- US_DEBUGP("Result for send_command in read_data %d\n",
- result);
+ usb_stor_dbg(us, "Result for send_command in read_data %d\n",
+ result);
if (result != USB_STOR_XFER_GOOD) {
result = USB_STOR_TRANSPORT_ERROR;
@@ -368,9 +366,8 @@ static int sddr55_write_data(struct us_data *us,
usb_stor_access_xfer_buf(buffer, len, us->srb,
&sg, &offset, FROM_XFER_BUF);
- US_DEBUGP("Write %02X pages, to PBA %04X"
- " (LBA %04X) page %02X\n",
- pages, pba, lba, page);
+ usb_stor_dbg(us, "Write %02X pages, to PBA %04X (LBA %04X) page %02X\n",
+ pages, pba, lba, page);
command[4] = 0;
@@ -384,7 +381,7 @@ static int sddr55_write_data(struct us_data *us,
/* set pba to first block in zone lba is in */
pba = (lba / 1000) * 1024;
- US_DEBUGP("No PBA for LBA %04X\n",lba);
+ usb_stor_dbg(us, "No PBA for LBA %04X\n", lba);
if (max_pba > 1024)
max_pba = 1024;
@@ -407,14 +404,15 @@ static int sddr55_write_data(struct us_data *us,
if (pba == -1) {
/* oh dear */
- US_DEBUGP("Couldn't find unallocated block\n");
+ usb_stor_dbg(us, "Couldn't find unallocated block\n");
set_sense_info (3, 0x31, 0); /* medium error */
result = USB_STOR_TRANSPORT_FAILED;
goto leave;
}
- US_DEBUGP("Allocating PBA %04X for LBA %04X\n", pba, lba);
+ usb_stor_dbg(us, "Allocating PBA %04X for LBA %04X\n",
+ pba, lba);
/* set writing to unallocated block flag */
command[4] = 0x40;
@@ -439,8 +437,8 @@ static int sddr55_write_data(struct us_data *us,
DMA_TO_DEVICE, command, 8);
if (result != USB_STOR_XFER_GOOD) {
- US_DEBUGP("Result for send_command in write_data %d\n",
- result);
+ usb_stor_dbg(us, "Result for send_command in write_data %d\n",
+ result);
/* set_sense_info is superfluous here? */
set_sense_info (3, 0x3, 0);/* peripheral write error */
@@ -453,8 +451,8 @@ static int sddr55_write_data(struct us_data *us,
DMA_TO_DEVICE, buffer, len);
if (result != USB_STOR_XFER_GOOD) {
- US_DEBUGP("Result for send_data in write_data %d\n",
- result);
+ usb_stor_dbg(us, "Result for send_data in write_data %d\n",
+ result);
/* set_sense_info is superfluous here? */
set_sense_info (3, 0x3, 0);/* peripheral write error */
@@ -466,8 +464,8 @@ static int sddr55_write_data(struct us_data *us,
result = sddr55_bulk_transport(us, DMA_FROM_DEVICE, status, 6);
if (result != USB_STOR_XFER_GOOD) {
- US_DEBUGP("Result for get_status in write_data %d\n",
- result);
+ usb_stor_dbg(us, "Result for get_status in write_data %d\n",
+ result);
/* set_sense_info is superfluous here? */
set_sense_info (3, 0x3, 0);/* peripheral write error */
@@ -487,8 +485,8 @@ static int sddr55_write_data(struct us_data *us,
goto leave;
}
- US_DEBUGP("Updating maps for LBA %04X: old PBA %04X, new PBA %04X\n",
- lba, pba, new_pba);
+ usb_stor_dbg(us, "Updating maps for LBA %04X: old PBA %04X, new PBA %04X\n",
+ lba, pba, new_pba);
/* update the lba<->pba maps, note new_pba might be the same as pba */
info->lba_to_pba[lba] = new_pba;
@@ -531,8 +529,8 @@ static int sddr55_read_deviceID(struct us_data *us,
command[7] = 0x84;
result = sddr55_bulk_transport(us, DMA_TO_DEVICE, command, 8);
- US_DEBUGP("Result of send_control for device ID is %d\n",
- result);
+ usb_stor_dbg(us, "Result of send_control for device ID is %d\n",
+ result);
if (result != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
@@ -568,20 +566,19 @@ static unsigned long sddr55_get_capacity(struct us_data *us) {
int result;
struct sddr55_card_info *info = (struct sddr55_card_info *)us->extra;
- US_DEBUGP("Reading capacity...\n");
+ usb_stor_dbg(us, "Reading capacity...\n");
result = sddr55_read_deviceID(us,
&manufacturerID,
&deviceID);
- US_DEBUGP("Result of read_deviceID is %d\n",
- result);
+ usb_stor_dbg(us, "Result of read_deviceID is %d\n", result);
if (result != USB_STOR_XFER_GOOD)
return 0;
- US_DEBUGP("Device ID = %02X\n", deviceID);
- US_DEBUGP("Manuf ID = %02X\n", manufacturerID);
+ usb_stor_dbg(us, "Device ID = %02X\n", deviceID);
+ usb_stor_dbg(us, "Manuf ID = %02X\n", manufacturerID);
info->pageshift = 9;
info->smallpageshift = 0;
@@ -753,7 +750,7 @@ static int sddr55_read_map(struct us_data *us) {
}
if (lba<0x10 || (lba>=0x3E0 && lba<0x3EF))
- US_DEBUGP("LBA %04X <-> PBA %04X\n", lba, i);
+ usb_stor_dbg(us, "LBA %04X <-> PBA %04X\n", lba, i);
info->lba_to_pba[lba + zone * 1000] = i;
}
@@ -808,7 +805,10 @@ static int sddr55_transport(struct scsi_cmnd *srb, struct us_data *us)
info = (struct sddr55_card_info *)(us->extra);
if (srb->cmnd[0] == REQUEST_SENSE) {
- US_DEBUGP("SDDR55: request sense %02x/%02x/%02x\n", info->sense_data[2], info->sense_data[12], info->sense_data[13]);
+ usb_stor_dbg(us, "request sense %02x/%02x/%02x\n",
+ info->sense_data[2],
+ info->sense_data[12],
+ info->sense_data[13]);
memcpy (ptr, info->sense_data, sizeof info->sense_data);
ptr[0] = 0x70;
@@ -892,13 +892,11 @@ static int sddr55_transport(struct scsi_cmnd *srb, struct us_data *us)
usb_stor_set_xfer_buf(ptr, sizeof(mode_page_01), srb);
if ( (srb->cmnd[2] & 0x3F) == 0x01 ) {
- US_DEBUGP(
- "SDDR55: Dummy up request for mode page 1\n");
+ usb_stor_dbg(us, "Dummy up request for mode page 1\n");
return USB_STOR_TRANSPORT_GOOD;
} else if ( (srb->cmnd[2] & 0x3F) == 0x3F ) {
- US_DEBUGP(
- "SDDR55: Dummy up request for all mode pages\n");
+ usb_stor_dbg(us, "Dummy up request for all mode pages\n");
return USB_STOR_TRANSPORT_GOOD;
}
@@ -908,10 +906,8 @@ static int sddr55_transport(struct scsi_cmnd *srb, struct us_data *us)
if (srb->cmnd[0] == ALLOW_MEDIUM_REMOVAL) {
- US_DEBUGP(
- "SDDR55: %s medium removal. Not that I can do"
- " anything about it...\n",
- (srb->cmnd[4]&0x03) ? "Prevent" : "Allow");
+ usb_stor_dbg(us, "%s medium removal. Not that I can do anything about it...\n",
+ (srb->cmnd[4]&0x03) ? "Prevent" : "Allow");
return USB_STOR_TRANSPORT_GOOD;
@@ -935,8 +931,8 @@ static int sddr55_transport(struct scsi_cmnd *srb, struct us_data *us)
if (lba >= info->max_log_blks) {
- US_DEBUGP("Error: Requested LBA %04X exceeds maximum "
- "block %04X\n", lba, info->max_log_blks-1);
+ usb_stor_dbg(us, "Error: Requested LBA %04X exceeds maximum block %04X\n",
+ lba, info->max_log_blks - 1);
set_sense_info (5, 0x24, 0); /* invalid field in command */
@@ -946,15 +942,13 @@ static int sddr55_transport(struct scsi_cmnd *srb, struct us_data *us)
pba = info->lba_to_pba[lba];
if (srb->cmnd[0] == WRITE_10) {
- US_DEBUGP("WRITE_10: write block %04X (LBA %04X) page %01X"
- " pages %d\n",
- pba, lba, page, pages);
+ usb_stor_dbg(us, "WRITE_10: write block %04X (LBA %04X) page %01X pages %d\n",
+ pba, lba, page, pages);
return sddr55_write_data(us, lba, page, pages);
} else {
- US_DEBUGP("READ_10: read block %04X (LBA %04X) page %01X"
- " pages %d\n",
- pba, lba, page, pages);
+ usb_stor_dbg(us, "READ_10: read block %04X (LBA %04X) page %01X pages %d\n",
+ pba, lba, page, pages);
return sddr55_read_data(us, lba, page, pages);
}
diff --git a/drivers/usb/storage/shuttle_usbat.c b/drivers/usb/storage/shuttle_usbat.c
index daf2fc58ae0..4ef2a80728f 100644
--- a/drivers/usb/storage/shuttle_usbat.c
+++ b/drivers/usb/storage/shuttle_usbat.c
@@ -271,7 +271,7 @@ static int usbat_bulk_read(struct us_data *us,
if (len == 0)
return USB_STOR_XFER_GOOD;
- US_DEBUGP("usbat_bulk_read: len = %d\n", len);
+ usb_stor_dbg(us, "len = %d\n", len);
return usb_stor_bulk_transfer_sg(us, us->recv_bulk_pipe, buf, len, use_sg, NULL);
}
@@ -286,7 +286,7 @@ static int usbat_bulk_write(struct us_data *us,
if (len == 0)
return USB_STOR_XFER_GOOD;
- US_DEBUGP("usbat_bulk_write: len = %d\n", len);
+ usb_stor_dbg(us, "len = %d\n", len);
return usb_stor_bulk_transfer_sg(us, us->send_bulk_pipe, buf, len, use_sg, NULL);
}
@@ -312,7 +312,7 @@ static int usbat_get_status(struct us_data *us, unsigned char *status)
int rc;
rc = usbat_read(us, USBAT_ATA, USBAT_ATA_STATUS, status);
- US_DEBUGP("usbat_get_status: 0x%02X\n", (unsigned short) (*status));
+ usb_stor_dbg(us, "0x%02X\n", *status);
return rc;
}
@@ -425,7 +425,7 @@ static int usbat_wait_not_busy(struct us_data *us, int minutes)
return USB_STOR_TRANSPORT_FAILED;
if ((*status & 0x80)==0x00) { /* not busy */
- US_DEBUGP("Waited not busy for %d steps\n", i);
+ usb_stor_dbg(us, "Waited not busy for %d steps\n", i);
return USB_STOR_TRANSPORT_GOOD;
}
@@ -439,8 +439,8 @@ static int usbat_wait_not_busy(struct us_data *us, int minutes)
msleep(1000); /* X minutes */
}
- US_DEBUGP("Waited not busy for %d minutes, timing out.\n",
- minutes);
+ usb_stor_dbg(us, "Waited not busy for %d minutes, timing out\n",
+ minutes);
return USB_STOR_TRANSPORT_FAILED;
}
@@ -657,8 +657,9 @@ static int usbat_hp8200e_rw_block_test(struct us_data *us,
if (*status & 0x20) /* device fault */
return USB_STOR_TRANSPORT_FAILED;
- US_DEBUGP("Redoing %s\n",
- direction==DMA_TO_DEVICE ? "write" : "read");
+ usb_stor_dbg(us, "Redoing %s\n",
+ direction == DMA_TO_DEVICE
+ ? "write" : "read");
} else if (result != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
@@ -667,8 +668,8 @@ static int usbat_hp8200e_rw_block_test(struct us_data *us,
}
- US_DEBUGP("Bummer! %s bulk data 20 times failed.\n",
- direction==DMA_TO_DEVICE ? "Writing" : "Reading");
+ usb_stor_dbg(us, "Bummer! %s bulk data 20 times failed\n",
+ direction == DMA_TO_DEVICE ? "Writing" : "Reading");
return USB_STOR_TRANSPORT_FAILED;
}
@@ -827,7 +828,7 @@ static int usbat_read_user_io(struct us_data *us, unsigned char *data_flags)
data_flags,
USBAT_UIO_READ);
- US_DEBUGP("usbat_read_user_io: UIO register reads %02X\n", (unsigned short) (*data_flags));
+ usb_stor_dbg(us, "UIO register reads %02X\n", *data_flags);
return result;
}
@@ -900,10 +901,11 @@ static int usbat_device_enable_cdt(struct us_data *us)
/*
* Determine if media is present.
*/
-static int usbat_flash_check_media_present(unsigned char *uio)
+static int usbat_flash_check_media_present(struct us_data *us,
+ unsigned char *uio)
{
if (*uio & USBAT_UIO_UI0) {
- US_DEBUGP("usbat_flash_check_media_present: no media detected\n");
+ usb_stor_dbg(us, "no media detected\n");
return USBAT_FLASH_MEDIA_NONE;
}
@@ -913,10 +915,11 @@ static int usbat_flash_check_media_present(unsigned char *uio)
/*
* Determine if media has changed since last operation
*/
-static int usbat_flash_check_media_changed(unsigned char *uio)
+static int usbat_flash_check_media_changed(struct us_data *us,
+ unsigned char *uio)
{
if (*uio & USBAT_UIO_0) {
- US_DEBUGP("usbat_flash_check_media_changed: media change detected\n");
+ usb_stor_dbg(us, "media change detected\n");
return USBAT_FLASH_MEDIA_CHANGED;
}
@@ -937,7 +940,7 @@ static int usbat_flash_check_media(struct us_data *us,
return USB_STOR_TRANSPORT_ERROR;
/* Check for media existence */
- rc = usbat_flash_check_media_present(uio);
+ rc = usbat_flash_check_media_present(us, uio);
if (rc == USBAT_FLASH_MEDIA_NONE) {
info->sense_key = 0x02;
info->sense_asc = 0x3A;
@@ -946,7 +949,7 @@ static int usbat_flash_check_media(struct us_data *us,
}
/* Check for media change */
- rc = usbat_flash_check_media_changed(uio);
+ rc = usbat_flash_check_media_changed(us, uio);
if (rc == USBAT_FLASH_MEDIA_CHANGED) {
/* Reset and re-enable card detect */
@@ -1008,11 +1011,11 @@ static int usbat_identify_device(struct us_data *us,
/* Check for error bit, or if the command 'fell through' */
if (status == 0xA1 || !(status & 0x01)) {
/* Device is HP 8200 */
- US_DEBUGP("usbat_identify_device: Detected HP8200 CDRW\n");
+ usb_stor_dbg(us, "Detected HP8200 CDRW\n");
info->devicetype = USBAT_DEV_HP8200;
} else {
/* Device is a CompactFlash reader/writer */
- US_DEBUGP("usbat_identify_device: Detected Flash reader/writer\n");
+ usb_stor_dbg(us, "Detected Flash reader/writer\n");
info->devicetype = USBAT_DEV_FLASH;
}
@@ -1075,7 +1078,7 @@ static int usbat_flash_get_sector_count(struct us_data *us,
/* ATA command : IDENTIFY DEVICE */
rc = usbat_multiple_write(us, registers, command, 3);
if (rc != USB_STOR_XFER_GOOD) {
- US_DEBUGP("usbat_flash_get_sector_count: Gah! identify_device failed\n");
+ usb_stor_dbg(us, "Gah! identify_device failed\n");
rc = USB_STOR_TRANSPORT_ERROR;
goto leave;
}
@@ -1178,7 +1181,7 @@ static int usbat_flash_read_data(struct us_data *us,
if (result != USB_STOR_TRANSPORT_GOOD)
goto leave;
- US_DEBUGP("usbat_flash_read_data: %d bytes\n", len);
+ usb_stor_dbg(us, "%d bytes\n", len);
/* Store the data in the transfer buffer */
usb_stor_access_xfer_buf(buffer, len, us->srb,
@@ -1301,8 +1304,7 @@ static int usbat_hp8200e_handle_read10(struct us_data *us,
unsigned int sg_offset = 0;
struct scatterlist *sg = NULL;
- US_DEBUGP("handle_read10: transfersize %d\n",
- srb->transfersize);
+ usb_stor_dbg(us, "transfersize %d\n", srb->transfersize);
if (scsi_bufflen(srb) < 0x10000) {
@@ -1329,14 +1331,14 @@ static int usbat_hp8200e_handle_read10(struct us_data *us,
len = short_pack(data[7+9], data[7+8]);
len <<= 16;
len |= data[7+7];
- US_DEBUGP("handle_read10: GPCMD_READ_CD: len %d\n", len);
+ usb_stor_dbg(us, "GPCMD_READ_CD: len %d\n", len);
srb->transfersize = scsi_bufflen(srb)/len;
}
if (!srb->transfersize) {
srb->transfersize = 2048; /* A guess */
- US_DEBUGP("handle_read10: transfersize 0, forcing %d\n",
- srb->transfersize);
+ usb_stor_dbg(us, "transfersize 0, forcing %d\n",
+ srb->transfersize);
}
/*
@@ -1346,7 +1348,7 @@ static int usbat_hp8200e_handle_read10(struct us_data *us,
*/
len = (65535/srb->transfersize) * srb->transfersize;
- US_DEBUGP("Max read is %d bytes\n", len);
+ usb_stor_dbg(us, "Max read is %d bytes\n", len);
len = min(len, scsi_bufflen(srb));
buffer = kmalloc(len, GFP_NOIO);
if (buffer == NULL) /* bloody hell! */
@@ -1460,10 +1462,9 @@ static int init_usbat(struct us_data *us, int devicetype)
unsigned char *status = us->iobuf;
us->extra = kzalloc(sizeof(struct usbat_info), GFP_NOIO);
- if (!us->extra) {
- US_DEBUGP("init_usbat: Gah! Can't allocate storage for usbat info struct!\n");
+ if (!us->extra)
return 1;
- }
+
info = (struct usbat_info *) (us->extra);
/* Enable peripheral control signals */
@@ -1473,7 +1474,7 @@ static int init_usbat(struct us_data *us, int devicetype)
if (rc != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
- US_DEBUGP("INIT 1\n");
+ usb_stor_dbg(us, "INIT 1\n");
msleep(2000);
@@ -1481,7 +1482,7 @@ static int init_usbat(struct us_data *us, int devicetype)
if (rc != USB_STOR_TRANSPORT_GOOD)
return rc;
- US_DEBUGP("INIT 2\n");
+ usb_stor_dbg(us, "INIT 2\n");
rc = usbat_read_user_io(us, status);
if (rc != USB_STOR_XFER_GOOD)
@@ -1491,32 +1492,32 @@ static int init_usbat(struct us_data *us, int devicetype)
if (rc != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
- US_DEBUGP("INIT 3\n");
+ usb_stor_dbg(us, "INIT 3\n");
rc = usbat_select_and_test_registers(us);
if (rc != USB_STOR_TRANSPORT_GOOD)
return rc;
- US_DEBUGP("INIT 4\n");
+ usb_stor_dbg(us, "INIT 4\n");
rc = usbat_read_user_io(us, status);
if (rc != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
- US_DEBUGP("INIT 5\n");
+ usb_stor_dbg(us, "INIT 5\n");
/* Enable peripheral control signals and card detect */
rc = usbat_device_enable_cdt(us);
if (rc != USB_STOR_TRANSPORT_GOOD)
return rc;
- US_DEBUGP("INIT 6\n");
+ usb_stor_dbg(us, "INIT 6\n");
rc = usbat_read_user_io(us, status);
if (rc != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
- US_DEBUGP("INIT 7\n");
+ usb_stor_dbg(us, "INIT 7\n");
msleep(1400);
@@ -1524,19 +1525,19 @@ static int init_usbat(struct us_data *us, int devicetype)
if (rc != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
- US_DEBUGP("INIT 8\n");
+ usb_stor_dbg(us, "INIT 8\n");
rc = usbat_select_and_test_registers(us);
if (rc != USB_STOR_TRANSPORT_GOOD)
return rc;
- US_DEBUGP("INIT 9\n");
+ usb_stor_dbg(us, "INIT 9\n");
/* At this point, we need to detect which device we are using */
if (usbat_set_transport(us, info, devicetype))
return USB_STOR_TRANSPORT_ERROR;
- US_DEBUGP("INIT 10\n");
+ usb_stor_dbg(us, "INIT 10\n");
if (usbat_get_device_type(us) == USBAT_DEV_FLASH) {
subcountH = 0x02;
@@ -1547,7 +1548,7 @@ static int init_usbat(struct us_data *us, int devicetype)
if (rc != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
- US_DEBUGP("INIT 11\n");
+ usb_stor_dbg(us, "INIT 11\n");
return USB_STOR_TRANSPORT_GOOD;
}
@@ -1592,7 +1593,7 @@ static int usbat_hp8200e_transport(struct scsi_cmnd *srb, struct us_data *us)
}
result = usbat_get_status(us, status);
- US_DEBUGP("Status = %02X\n", *status);
+ usb_stor_dbg(us, "Status = %02X\n", *status);
if (result != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
if (srb->cmnd[0] == TEST_UNIT_READY)
@@ -1610,7 +1611,7 @@ static int usbat_hp8200e_transport(struct scsi_cmnd *srb, struct us_data *us)
if (result == USB_STOR_TRANSPORT_GOOD) {
transferred += len;
- US_DEBUGP("Wrote %08X bytes\n", transferred);
+ usb_stor_dbg(us, "Wrote %08X bytes\n", transferred);
}
return result;
@@ -1623,8 +1624,8 @@ static int usbat_hp8200e_transport(struct scsi_cmnd *srb, struct us_data *us)
}
if (len > 0xFFFF) {
- US_DEBUGP("Error: len = %08X... what do I do now?\n",
- len);
+ usb_stor_dbg(us, "Error: len = %08X... what do I do now?\n",
+ len);
return USB_STOR_TRANSPORT_ERROR;
}
@@ -1693,7 +1694,7 @@ static int usbat_flash_transport(struct scsi_cmnd * srb, struct us_data *us)
};
if (srb->cmnd[0] == INQUIRY) {
- US_DEBUGP("usbat_flash_transport: INQUIRY. Returning bogus response.\n");
+ usb_stor_dbg(us, "INQUIRY - Returning bogus response\n");
memcpy(ptr, inquiry_response, sizeof(inquiry_response));
fill_inquiry_response(us, ptr, 36);
return USB_STOR_TRANSPORT_GOOD;
@@ -1710,8 +1711,8 @@ static int usbat_flash_transport(struct scsi_cmnd * srb, struct us_data *us)
/* hard coded 512 byte sectors as per ATA spec */
info->ssize = 0x200;
- US_DEBUGP("usbat_flash_transport: READ_CAPACITY: %ld sectors, %ld bytes per sector\n",
- info->sectors, info->ssize);
+ usb_stor_dbg(us, "READ_CAPACITY: %ld sectors, %ld bytes per sector\n",
+ info->sectors, info->ssize);
/*
* build the reply
@@ -1726,7 +1727,7 @@ static int usbat_flash_transport(struct scsi_cmnd * srb, struct us_data *us)
}
if (srb->cmnd[0] == MODE_SELECT_10) {
- US_DEBUGP("usbat_flash_transport: Gah! MODE_SELECT_10.\n");
+ usb_stor_dbg(us, "Gah! MODE_SELECT_10\n");
return USB_STOR_TRANSPORT_ERROR;
}
@@ -1736,7 +1737,8 @@ static int usbat_flash_transport(struct scsi_cmnd * srb, struct us_data *us)
blocks = ((u32)(srb->cmnd[7]) << 8) | ((u32)(srb->cmnd[8]));
- US_DEBUGP("usbat_flash_transport: READ_10: read block 0x%04lx count %ld\n", block, blocks);
+ usb_stor_dbg(us, "READ_10: read block 0x%04lx count %ld\n",
+ block, blocks);
return usbat_flash_read_data(us, info, block, blocks);
}
@@ -1750,7 +1752,8 @@ static int usbat_flash_transport(struct scsi_cmnd * srb, struct us_data *us)
blocks = ((u32)(srb->cmnd[6]) << 24) | ((u32)(srb->cmnd[7]) << 16) |
((u32)(srb->cmnd[8]) << 8) | ((u32)(srb->cmnd[9]));
- US_DEBUGP("usbat_flash_transport: READ_12: read block 0x%04lx count %ld\n", block, blocks);
+ usb_stor_dbg(us, "READ_12: read block 0x%04lx count %ld\n",
+ block, blocks);
return usbat_flash_read_data(us, info, block, blocks);
}
@@ -1760,7 +1763,8 @@ static int usbat_flash_transport(struct scsi_cmnd * srb, struct us_data *us)
blocks = ((u32)(srb->cmnd[7]) << 8) | ((u32)(srb->cmnd[8]));
- US_DEBUGP("usbat_flash_transport: WRITE_10: write block 0x%04lx count %ld\n", block, blocks);
+ usb_stor_dbg(us, "WRITE_10: write block 0x%04lx count %ld\n",
+ block, blocks);
return usbat_flash_write_data(us, info, block, blocks);
}
@@ -1774,13 +1778,14 @@ static int usbat_flash_transport(struct scsi_cmnd * srb, struct us_data *us)
blocks = ((u32)(srb->cmnd[6]) << 24) | ((u32)(srb->cmnd[7]) << 16) |
((u32)(srb->cmnd[8]) << 8) | ((u32)(srb->cmnd[9]));
- US_DEBUGP("usbat_flash_transport: WRITE_12: write block 0x%04lx count %ld\n", block, blocks);
+ usb_stor_dbg(us, "WRITE_12: write block 0x%04lx count %ld\n",
+ block, blocks);
return usbat_flash_write_data(us, info, block, blocks);
}
if (srb->cmnd[0] == TEST_UNIT_READY) {
- US_DEBUGP("usbat_flash_transport: TEST_UNIT_READY.\n");
+ usb_stor_dbg(us, "TEST_UNIT_READY\n");
rc = usbat_flash_check_media(us, info);
if (rc != USB_STOR_TRANSPORT_GOOD)
@@ -1790,7 +1795,7 @@ static int usbat_flash_transport(struct scsi_cmnd * srb, struct us_data *us)
}
if (srb->cmnd[0] == REQUEST_SENSE) {
- US_DEBUGP("usbat_flash_transport: REQUEST_SENSE.\n");
+ usb_stor_dbg(us, "REQUEST_SENSE\n");
memset(ptr, 0, 18);
ptr[0] = 0xF0;
@@ -1811,8 +1816,8 @@ static int usbat_flash_transport(struct scsi_cmnd * srb, struct us_data *us)
return USB_STOR_TRANSPORT_GOOD;
}
- US_DEBUGP("usbat_flash_transport: Gah! Unknown command: %d (0x%x)\n",
- srb->cmnd[0], srb->cmnd[0]);
+ usb_stor_dbg(us, "Gah! Unknown command: %d (0x%x)\n",
+ srb->cmnd[0], srb->cmnd[0]);
info->sense_key = 0x05;
info->sense_asc = 0x20;
info->sense_ascq = 0x00;
diff --git a/drivers/usb/storage/sierra_ms.c b/drivers/usb/storage/sierra_ms.c
index 17e36952bce..2ea657be14c 100644
--- a/drivers/usb/storage/sierra_ms.c
+++ b/drivers/usb/storage/sierra_ms.c
@@ -47,7 +47,7 @@ static bool containsFullLinuxPackage(struct swoc_info *swocInfo)
static int sierra_set_ms_mode(struct usb_device *udev, __u16 eSWocMode)
{
int result;
- US_DEBUGP("SWIMS: %s", "DEVICE MODE SWITCH\n");
+ dev_dbg(&udev->dev, "SWIMS: %s", "DEVICE MODE SWITCH\n");
result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
SWIMS_USB_REQUEST_SetSwocMode, /* __u8 request */
USB_TYPE_VENDOR | USB_DIR_OUT, /* __u8 request type */
@@ -65,7 +65,7 @@ static int sierra_get_swoc_info(struct usb_device *udev,
{
int result;
- US_DEBUGP("SWIMS: Attempting to get TRU-Install info.\n");
+ dev_dbg(&udev->dev, "SWIMS: Attempting to get TRU-Install info\n");
result = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
SWIMS_USB_REQUEST_GetSwocInfo, /* __u8 request */
@@ -81,11 +81,11 @@ static int sierra_get_swoc_info(struct usb_device *udev,
return result;
}
-static void debug_swoc(struct swoc_info *swocInfo)
+static void debug_swoc(const struct device *dev, struct swoc_info *swocInfo)
{
- US_DEBUGP("SWIMS: SWoC Rev: %02d \n", swocInfo->rev);
- US_DEBUGP("SWIMS: Linux SKU: %04X \n", swocInfo->LinuxSKU);
- US_DEBUGP("SWIMS: Linux Version: %04X \n", swocInfo->LinuxVer);
+ dev_dbg(dev, "SWIMS: SWoC Rev: %02d\n", swocInfo->rev);
+ dev_dbg(dev, "SWIMS: Linux SKU: %04X\n", swocInfo->LinuxSKU);
+ dev_dbg(dev, "SWIMS: Linux Version: %04X\n", swocInfo->LinuxVer);
}
@@ -101,18 +101,17 @@ static ssize_t show_truinst(struct device *dev, struct device_attribute *attr,
} else {
swocInfo = kmalloc(sizeof(struct swoc_info), GFP_KERNEL);
if (!swocInfo) {
- US_DEBUGP("SWIMS: Allocation failure\n");
snprintf(buf, PAGE_SIZE, "Error\n");
return -ENOMEM;
}
result = sierra_get_swoc_info(udev, swocInfo);
if (result < 0) {
- US_DEBUGP("SWIMS: failed SWoC query\n");
+ dev_dbg(dev, "SWIMS: failed SWoC query\n");
kfree(swocInfo);
snprintf(buf, PAGE_SIZE, "Error\n");
return -EIO;
}
- debug_swoc(swocInfo);
+ debug_swoc(dev, swocInfo);
result = snprintf(buf, PAGE_SIZE,
"REV=%02d SKU=%04X VER=%04X\n",
swocInfo->rev,
@@ -138,61 +137,55 @@ int sierra_ms_init(struct us_data *us)
sh = us_to_host(us);
scsi_get_host_dev(sh);
- US_DEBUGP("SWIMS: sierra_ms_init called\n");
-
/* Force Modem mode */
if (swi_tru_install == TRU_FORCE_MODEM) {
- US_DEBUGP("SWIMS: %s", "Forcing Modem Mode\n");
+ usb_stor_dbg(us, "SWIMS: Forcing Modem Mode\n");
result = sierra_set_ms_mode(udev, SWIMS_SET_MODE_Modem);
if (result < 0)
- US_DEBUGP("SWIMS: Failed to switch to modem mode.\n");
+ usb_stor_dbg(us, "SWIMS: Failed to switch to modem mode\n");
return -EIO;
}
/* Force Mass Storage mode (keep CD-Rom) */
else if (swi_tru_install == TRU_FORCE_MS) {
- US_DEBUGP("SWIMS: %s", "Forcing Mass Storage Mode\n");
+ usb_stor_dbg(us, "SWIMS: Forcing Mass Storage Mode\n");
goto complete;
}
/* Normal TRU-Install Logic */
else {
- US_DEBUGP("SWIMS: %s", "Normal SWoC Logic\n");
+ usb_stor_dbg(us, "SWIMS: Normal SWoC Logic\n");
swocInfo = kmalloc(sizeof(struct swoc_info),
GFP_KERNEL);
- if (!swocInfo) {
- US_DEBUGP("SWIMS: %s", "Allocation failure\n");
+ if (!swocInfo)
return -ENOMEM;
- }
retries = 3;
do {
retries--;
result = sierra_get_swoc_info(udev, swocInfo);
if (result < 0) {
- US_DEBUGP("SWIMS: %s", "Failed SWoC query\n");
+ usb_stor_dbg(us, "SWIMS: Failed SWoC query\n");
schedule_timeout_uninterruptible(2*HZ);
}
} while (retries && result < 0);
if (result < 0) {
- US_DEBUGP("SWIMS: %s",
- "Completely failed SWoC query\n");
+ usb_stor_dbg(us, "SWIMS: Completely failed SWoC query\n");
kfree(swocInfo);
return -EIO;
}
- debug_swoc(swocInfo);
+ debug_swoc(&us->pusb_dev->dev, swocInfo);
/* If there is not Linux software on the TRU-Install device
* then switch to modem mode
*/
if (!containsFullLinuxPackage(swocInfo)) {
- US_DEBUGP("SWIMS: %s",
- "Switching to Modem Mode\n");
+ usb_stor_dbg(us, "SWIMS: Switching to Modem Mode\n");
result = sierra_set_ms_mode(udev,
SWIMS_SET_MODE_Modem);
if (result < 0)
- US_DEBUGP("SWIMS: Failed to switch modem\n");
+ usb_stor_dbg(us, "SWIMS: Failed to switch modem\n");
kfree(swocInfo);
return -EIO;
}
diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
index c0543c83923..22c7d4360fa 100644
--- a/drivers/usb/storage/transport.c
+++ b/drivers/usb/storage/transport.c
@@ -166,7 +166,7 @@ static int usb_stor_msg_common(struct us_data *us, int timeout)
/* cancel the URB, if it hasn't been cancelled already */
if (test_and_clear_bit(US_FLIDX_URB_ACTIVE, &us->dflags)) {
- US_DEBUGP("-- cancelling URB\n");
+ usb_stor_dbg(us, "-- cancelling URB\n");
usb_unlink_urb(us->current_urb);
}
}
@@ -178,8 +178,8 @@ static int usb_stor_msg_common(struct us_data *us, int timeout)
clear_bit(US_FLIDX_URB_ACTIVE, &us->dflags);
if (timeleft <= 0) {
- US_DEBUGP("%s -- cancelling URB\n",
- timeleft == 0 ? "Timeout" : "Signal");
+ usb_stor_dbg(us, "%s -- cancelling URB\n",
+ timeleft == 0 ? "Timeout" : "Signal");
usb_kill_urb(us->current_urb);
}
@@ -197,9 +197,8 @@ int usb_stor_control_msg(struct us_data *us, unsigned int pipe,
{
int status;
- US_DEBUGP("%s: rq=%02x rqtype=%02x value=%04x index=%02x len=%u\n",
- __func__, request, requesttype,
- value, index, size);
+ usb_stor_dbg(us, "rq=%02x rqtype=%02x value=%04x index=%02x len=%u\n",
+ request, requesttype, value, index, size);
/* fill in the devrequest structure */
us->cr->bRequestType = requesttype;
@@ -249,7 +248,7 @@ int usb_stor_clear_halt(struct us_data *us, unsigned int pipe)
if (result >= 0)
usb_reset_endpoint(us->pusb_dev, endp);
- US_DEBUGP("%s: result = %d\n", __func__, result);
+ usb_stor_dbg(us, "result = %d\n", result);
return result;
}
EXPORT_SYMBOL_GPL(usb_stor_clear_halt);
@@ -265,18 +264,18 @@ EXPORT_SYMBOL_GPL(usb_stor_clear_halt);
static int interpret_urb_result(struct us_data *us, unsigned int pipe,
unsigned int length, int result, unsigned int partial)
{
- US_DEBUGP("Status code %d; transferred %u/%u\n",
- result, partial, length);
+ usb_stor_dbg(us, "Status code %d; transferred %u/%u\n",
+ result, partial, length);
switch (result) {
/* no error code; did we send all the data? */
case 0:
if (partial != length) {
- US_DEBUGP("-- short transfer\n");
+ usb_stor_dbg(us, "-- short transfer\n");
return USB_STOR_XFER_SHORT;
}
- US_DEBUGP("-- transfer complete\n");
+ usb_stor_dbg(us, "-- transfer complete\n");
return USB_STOR_XFER_GOOD;
/* stalled */
@@ -284,39 +283,40 @@ static int interpret_urb_result(struct us_data *us, unsigned int pipe,
/* for control endpoints, (used by CB[I]) a stall indicates
* a failed command */
if (usb_pipecontrol(pipe)) {
- US_DEBUGP("-- stall on control pipe\n");
+ usb_stor_dbg(us, "-- stall on control pipe\n");
return USB_STOR_XFER_STALLED;
}
/* for other sorts of endpoint, clear the stall */
- US_DEBUGP("clearing endpoint halt for pipe 0x%x\n", pipe);
+ usb_stor_dbg(us, "clearing endpoint halt for pipe 0x%x\n",
+ pipe);
if (usb_stor_clear_halt(us, pipe) < 0)
return USB_STOR_XFER_ERROR;
return USB_STOR_XFER_STALLED;
/* babble - the device tried to send more than we wanted to read */
case -EOVERFLOW:
- US_DEBUGP("-- babble\n");
+ usb_stor_dbg(us, "-- babble\n");
return USB_STOR_XFER_LONG;
/* the transfer was cancelled by abort, disconnect, or timeout */
case -ECONNRESET:
- US_DEBUGP("-- transfer cancelled\n");
+ usb_stor_dbg(us, "-- transfer cancelled\n");
return USB_STOR_XFER_ERROR;
/* short scatter-gather read transfer */
case -EREMOTEIO:
- US_DEBUGP("-- short read transfer\n");
+ usb_stor_dbg(us, "-- short read transfer\n");
return USB_STOR_XFER_SHORT;
/* abort or disconnect in progress */
case -EIO:
- US_DEBUGP("-- abort or disconnect in progress\n");
+ usb_stor_dbg(us, "-- abort or disconnect in progress\n");
return USB_STOR_XFER_ERROR;
/* the catch-all error case */
default:
- US_DEBUGP("-- unknown error\n");
+ usb_stor_dbg(us, "-- unknown error\n");
return USB_STOR_XFER_ERROR;
}
}
@@ -331,9 +331,8 @@ int usb_stor_ctrl_transfer(struct us_data *us, unsigned int pipe,
{
int result;
- US_DEBUGP("%s: rq=%02x rqtype=%02x value=%04x index=%02x len=%u\n",
- __func__, request, requesttype,
- value, index, size);
+ usb_stor_dbg(us, "rq=%02x rqtype=%02x value=%04x index=%02x len=%u\n",
+ request, requesttype, value, index, size);
/* fill in the devrequest structure */
us->cr->bRequestType = requesttype;
@@ -367,7 +366,7 @@ static int usb_stor_intr_transfer(struct us_data *us, void *buf,
unsigned int pipe = us->recv_intr_pipe;
unsigned int maxp;
- US_DEBUGP("%s: xfer %u bytes\n", __func__, length);
+ usb_stor_dbg(us, "xfer %u bytes\n", length);
/* calculate the max packet size */
maxp = usb_maxpacket(us->pusb_dev, pipe, usb_pipeout(pipe));
@@ -394,7 +393,7 @@ int usb_stor_bulk_transfer_buf(struct us_data *us, unsigned int pipe,
{
int result;
- US_DEBUGP("%s: xfer %u bytes\n", __func__, length);
+ usb_stor_dbg(us, "xfer %u bytes\n", length);
/* fill and submit the URB */
usb_fill_bulk_urb(us->current_urb, us->pusb_dev, pipe, buf, length,
@@ -426,12 +425,11 @@ static int usb_stor_bulk_transfer_sglist(struct us_data *us, unsigned int pipe,
return USB_STOR_XFER_ERROR;
/* initialize the scatter-gather request block */
- US_DEBUGP("%s: xfer %u bytes, %d entries\n", __func__,
- length, num_sg);
+ usb_stor_dbg(us, "xfer %u bytes, %d entries\n", length, num_sg);
result = usb_sg_init(&us->current_sg, us->pusb_dev, pipe, 0,
sg, num_sg, length, GFP_NOIO);
if (result) {
- US_DEBUGP("usb_sg_init returned %d\n", result);
+ usb_stor_dbg(us, "usb_sg_init returned %d\n", result);
return USB_STOR_XFER_ERROR;
}
@@ -444,7 +442,7 @@ static int usb_stor_bulk_transfer_sglist(struct us_data *us, unsigned int pipe,
/* cancel the request, if it hasn't been cancelled already */
if (test_and_clear_bit(US_FLIDX_SG_ACTIVE, &us->dflags)) {
- US_DEBUGP("-- cancelling sg request\n");
+ usb_stor_dbg(us, "-- cancelling sg request\n");
usb_sg_cancel(&us->current_sg);
}
}
@@ -609,14 +607,14 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
* short-circuit all other processing
*/
if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags)) {
- US_DEBUGP("-- command was aborted\n");
+ usb_stor_dbg(us, "-- command was aborted\n");
srb->result = DID_ABORT << 16;
goto Handle_Errors;
}
/* if there is a transport error, reset and don't auto-sense */
if (result == USB_STOR_TRANSPORT_ERROR) {
- US_DEBUGP("-- transport indicates error, resetting\n");
+ usb_stor_dbg(us, "-- transport indicates error, resetting\n");
srb->result = DID_ERROR << 16;
goto Handle_Errors;
}
@@ -645,7 +643,7 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
*/
if ((us->protocol == USB_PR_CB || us->protocol == USB_PR_DPCM_USB) &&
srb->sc_data_direction != DMA_FROM_DEVICE) {
- US_DEBUGP("-- CB transport device requiring auto-sense\n");
+ usb_stor_dbg(us, "-- CB transport device requiring auto-sense\n");
need_auto_sense = 1;
}
@@ -655,7 +653,7 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
* "failure" and an "error" in the transport mechanism.
*/
if (result == USB_STOR_TRANSPORT_FAILED) {
- US_DEBUGP("-- transport indicates command failure\n");
+ usb_stor_dbg(us, "-- transport indicates command failure\n");
need_auto_sense = 1;
}
@@ -670,7 +668,7 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
!(us->fflags & US_FL_SANE_SENSE) &&
!(us->fflags & US_FL_BAD_SENSE) &&
!(srb->cmnd[2] & 0x20))) {
- US_DEBUGP("-- SAT supported, increasing auto-sense\n");
+ usb_stor_dbg(us, "-- SAT supported, increasing auto-sense\n");
us->fflags |= US_FL_SANE_SENSE;
}
@@ -684,7 +682,7 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
(srb->cmnd[0] == MODE_SENSE) ||
(srb->cmnd[0] == LOG_SENSE) ||
(srb->cmnd[0] == MODE_SENSE_10))) {
- US_DEBUGP("-- unexpectedly short transfer\n");
+ usb_stor_dbg(us, "-- unexpectedly short transfer\n");
}
/* Now, if we need to do the auto-sense, let's do it */
@@ -700,7 +698,7 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
if (us->fflags & US_FL_SANE_SENSE)
sense_size = ~0;
Retry_Sense:
- US_DEBUGP("Issuing auto-REQUEST_SENSE\n");
+ usb_stor_dbg(us, "Issuing auto-REQUEST_SENSE\n");
scsi_eh_prep_cmnd(srb, &ses, NULL, 0, sense_size);
@@ -719,7 +717,7 @@ Retry_Sense:
scsi_eh_restore_cmnd(srb, &ses);
if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags)) {
- US_DEBUGP("-- auto-sense aborted\n");
+ usb_stor_dbg(us, "-- auto-sense aborted\n");
srb->result = DID_ABORT << 16;
/* If SANE_SENSE caused this problem, disable it */
@@ -737,7 +735,7 @@ Retry_Sense:
*/
if (temp_result == USB_STOR_TRANSPORT_FAILED &&
sense_size != US_SENSE_SIZE) {
- US_DEBUGP("-- auto-sense failure, retry small sense\n");
+ usb_stor_dbg(us, "-- auto-sense failure, retry small sense\n");
sense_size = US_SENSE_SIZE;
us->fflags &= ~US_FL_SANE_SENSE;
us->fflags |= US_FL_BAD_SENSE;
@@ -746,7 +744,7 @@ Retry_Sense:
/* Other failures */
if (temp_result != USB_STOR_TRANSPORT_GOOD) {
- US_DEBUGP("-- auto-sense failure\n");
+ usb_stor_dbg(us, "-- auto-sense failure\n");
/* we skip the reset if this happens to be a
* multi-target device, since failure of an
@@ -766,27 +764,28 @@ Retry_Sense:
!(us->fflags & US_FL_SANE_SENSE) &&
!(us->fflags & US_FL_BAD_SENSE) &&
(srb->sense_buffer[0] & 0x7C) == 0x70) {
- US_DEBUGP("-- SANE_SENSE support enabled\n");
+ usb_stor_dbg(us, "-- SANE_SENSE support enabled\n");
us->fflags |= US_FL_SANE_SENSE;
/* Indicate to the user that we truncated their sense
* because we didn't know it supported larger sense.
*/
- US_DEBUGP("-- Sense data truncated to %i from %i\n",
- US_SENSE_SIZE,
- srb->sense_buffer[7] + 8);
+ usb_stor_dbg(us, "-- Sense data truncated to %i from %i\n",
+ US_SENSE_SIZE,
+ srb->sense_buffer[7] + 8);
srb->sense_buffer[7] = (US_SENSE_SIZE - 8);
}
scsi_normalize_sense(srb->sense_buffer, SCSI_SENSE_BUFFERSIZE,
&sshdr);
- US_DEBUGP("-- Result from auto-sense is %d\n", temp_result);
- US_DEBUGP("-- code: 0x%x, key: 0x%x, ASC: 0x%x, ASCQ: 0x%x\n",
- sshdr.response_code, sshdr.sense_key,
- sshdr.asc, sshdr.ascq);
+ usb_stor_dbg(us, "-- Result from auto-sense is %d\n",
+ temp_result);
+ usb_stor_dbg(us, "-- code: 0x%x, key: 0x%x, ASC: 0x%x, ASCQ: 0x%x\n",
+ sshdr.response_code, sshdr.sense_key,
+ sshdr.asc, sshdr.ascq);
#ifdef CONFIG_USB_STORAGE_DEBUG
- usb_stor_show_sense(sshdr.sense_key, sshdr.asc, sshdr.ascq);
+ usb_stor_show_sense(us, sshdr.sense_key, sshdr.asc, sshdr.ascq);
#endif
/* set the result so the higher layers expect this data */
@@ -892,20 +891,18 @@ Retry_Sense:
/* Stop the current URB transfer */
void usb_stor_stop_transport(struct us_data *us)
{
- US_DEBUGP("%s called\n", __func__);
-
/* If the state machine is blocked waiting for an URB,
* let's wake it up. The test_and_clear_bit() call
* guarantees that if a URB has just been submitted,
* it won't be cancelled more than once. */
if (test_and_clear_bit(US_FLIDX_URB_ACTIVE, &us->dflags)) {
- US_DEBUGP("-- cancelling URB\n");
+ usb_stor_dbg(us, "-- cancelling URB\n");
usb_unlink_urb(us->current_urb);
}
/* If we are waiting for a scatter-gather operation, cancel it. */
if (test_and_clear_bit(US_FLIDX_SG_ACTIVE, &us->dflags)) {
- US_DEBUGP("-- cancelling sg request\n");
+ usb_stor_dbg(us, "-- cancelling sg request\n");
usb_sg_cancel(&us->current_sg);
}
}
@@ -928,7 +925,8 @@ int usb_stor_CB_transport(struct scsi_cmnd *srb, struct us_data *us)
us->ifnum, srb->cmnd, srb->cmd_len);
/* check the return code for the command */
- US_DEBUGP("Call to usb_stor_ctrl_transfer() returned %d\n", result);
+ usb_stor_dbg(us, "Call to usb_stor_ctrl_transfer() returned %d\n",
+ result);
/* if we stalled the command, it means command failed */
if (result == USB_STOR_XFER_STALLED) {
@@ -946,7 +944,7 @@ int usb_stor_CB_transport(struct scsi_cmnd *srb, struct us_data *us)
pipe = srb->sc_data_direction == DMA_FROM_DEVICE ?
us->recv_bulk_pipe : us->send_bulk_pipe;
result = usb_stor_bulk_srb(us, pipe, srb);
- US_DEBUGP("CBI data stage result is 0x%x\n", result);
+ usb_stor_dbg(us, "CBI data stage result is 0x%x\n", result);
/* if we stalled the data transfer it means command failed */
if (result == USB_STOR_XFER_STALLED)
@@ -964,8 +962,8 @@ int usb_stor_CB_transport(struct scsi_cmnd *srb, struct us_data *us)
return USB_STOR_TRANSPORT_GOOD;
result = usb_stor_intr_transfer(us, us->iobuf, 2);
- US_DEBUGP("Got interrupt data (0x%x, 0x%x)\n",
- us->iobuf[0], us->iobuf[1]);
+ usb_stor_dbg(us, "Got interrupt data (0x%x, 0x%x)\n",
+ us->iobuf[0], us->iobuf[1]);
if (result != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
@@ -992,8 +990,8 @@ int usb_stor_CB_transport(struct scsi_cmnd *srb, struct us_data *us)
* into the first byte -- so if it's non-zero, call it a failure.
*/
if (us->iobuf[0]) {
- US_DEBUGP("CBI IRQ data showed reserved bType 0x%x\n",
- us->iobuf[0]);
+ usb_stor_dbg(us, "CBI IRQ data showed reserved bType 0x%x\n",
+ us->iobuf[0]);
goto Failed;
}
@@ -1034,8 +1032,8 @@ int usb_stor_Bulk_max_lun(struct us_data *us)
USB_RECIP_INTERFACE,
0, us->ifnum, us->iobuf, 1, 10*HZ);
- US_DEBUGP("GetMaxLUN command result is %d, data is %d\n",
- result, us->iobuf[0]);
+ usb_stor_dbg(us, "GetMaxLUN command result is %d, data is %d\n",
+ result, us->iobuf[0]);
/* if we have a successful request, return the result */
if (result > 0)
@@ -1084,14 +1082,14 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us)
memcpy(bcb->CDB, srb->cmnd, bcb->Length);
/* send it to out endpoint */
- US_DEBUGP("Bulk Command S 0x%x T 0x%x L %d F %d Trg %d LUN %d CL %d\n",
- le32_to_cpu(bcb->Signature), bcb->Tag,
- le32_to_cpu(bcb->DataTransferLength), bcb->Flags,
- (bcb->Lun >> 4), (bcb->Lun & 0x0F),
- bcb->Length);
+ usb_stor_dbg(us, "Bulk Command S 0x%x T 0x%x L %d F %d Trg %d LUN %d CL %d\n",
+ le32_to_cpu(bcb->Signature), bcb->Tag,
+ le32_to_cpu(bcb->DataTransferLength), bcb->Flags,
+ (bcb->Lun >> 4), (bcb->Lun & 0x0F),
+ bcb->Length);
result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,
bcb, cbwlen, NULL);
- US_DEBUGP("Bulk command transfer result=%d\n", result);
+ usb_stor_dbg(us, "Bulk command transfer result=%d\n", result);
if (result != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
@@ -1108,7 +1106,7 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us)
unsigned int pipe = srb->sc_data_direction == DMA_FROM_DEVICE ?
us->recv_bulk_pipe : us->send_bulk_pipe;
result = usb_stor_bulk_srb(us, pipe, srb);
- US_DEBUGP("Bulk data transfer result 0x%x\n", result);
+ usb_stor_dbg(us, "Bulk data transfer result 0x%x\n", result);
if (result == USB_STOR_XFER_ERROR)
return USB_STOR_TRANSPORT_ERROR;
@@ -1127,7 +1125,7 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us)
*/
/* get CSW for device status */
- US_DEBUGP("Attempting to get CSW...\n");
+ usb_stor_dbg(us, "Attempting to get CSW...\n");
result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
bcs, US_BULK_CS_WRAP_LEN, &cswlen);
@@ -1136,7 +1134,7 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us)
* CSWs. If we encounter such a thing, try to read the CSW again.
*/
if (result == USB_STOR_XFER_SHORT && cswlen == 0) {
- US_DEBUGP("Received 0-length CSW; retrying...\n");
+ usb_stor_dbg(us, "Received 0-length CSW; retrying...\n");
result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
bcs, US_BULK_CS_WRAP_LEN, &cswlen);
}
@@ -1145,24 +1143,24 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us)
if (result == USB_STOR_XFER_STALLED) {
/* get the status again */
- US_DEBUGP("Attempting to get CSW (2nd try)...\n");
+ usb_stor_dbg(us, "Attempting to get CSW (2nd try)...\n");
result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
bcs, US_BULK_CS_WRAP_LEN, NULL);
}
/* if we still have a failure at this point, we're in trouble */
- US_DEBUGP("Bulk status result = %d\n", result);
+ usb_stor_dbg(us, "Bulk status result = %d\n", result);
if (result != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
/* check bulk status */
residue = le32_to_cpu(bcs->Residue);
- US_DEBUGP("Bulk Status S 0x%x T 0x%x R %u Stat 0x%x\n",
- le32_to_cpu(bcs->Signature), bcs->Tag,
- residue, bcs->Status);
+ usb_stor_dbg(us, "Bulk Status S 0x%x T 0x%x R %u Stat 0x%x\n",
+ le32_to_cpu(bcs->Signature), bcs->Tag,
+ residue, bcs->Status);
if (!(bcs->Tag == us->tag || (us->fflags & US_FL_BULK_IGNORE_TAG)) ||
bcs->Status > US_BULK_STAT_PHASE) {
- US_DEBUGP("Bulk logical error\n");
+ usb_stor_dbg(us, "Bulk logical error\n");
return USB_STOR_TRANSPORT_ERROR;
}
@@ -1173,12 +1171,12 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us)
if (!us->bcs_signature) {
us->bcs_signature = bcs->Signature;
if (us->bcs_signature != cpu_to_le32(US_BULK_CS_SIGN))
- US_DEBUGP("Learnt BCS signature 0x%08X\n",
- le32_to_cpu(us->bcs_signature));
+ usb_stor_dbg(us, "Learnt BCS signature 0x%08X\n",
+ le32_to_cpu(us->bcs_signature));
} else if (bcs->Signature != us->bcs_signature) {
- US_DEBUGP("Signature mismatch: got %08X, expecting %08X\n",
- le32_to_cpu(bcs->Signature),
- le32_to_cpu(us->bcs_signature));
+ usb_stor_dbg(us, "Signature mismatch: got %08X, expecting %08X\n",
+ le32_to_cpu(bcs->Signature),
+ le32_to_cpu(us->bcs_signature));
return USB_STOR_TRANSPORT_ERROR;
}
@@ -1255,7 +1253,7 @@ static int usb_stor_reset_common(struct us_data *us,
int result2;
if (test_bit(US_FLIDX_DISCONNECTING, &us->dflags)) {
- US_DEBUGP("No reset during disconnect\n");
+ usb_stor_dbg(us, "No reset during disconnect\n");
return -EIO;
}
@@ -1263,7 +1261,7 @@ static int usb_stor_reset_common(struct us_data *us,
request, requesttype, value, index, data, size,
5*HZ);
if (result < 0) {
- US_DEBUGP("Soft reset failed: %d\n", result);
+ usb_stor_dbg(us, "Soft reset failed: %d\n", result);
return result;
}
@@ -1273,23 +1271,23 @@ static int usb_stor_reset_common(struct us_data *us,
test_bit(US_FLIDX_DISCONNECTING, &us->dflags),
HZ*6);
if (test_bit(US_FLIDX_DISCONNECTING, &us->dflags)) {
- US_DEBUGP("Reset interrupted by disconnect\n");
+ usb_stor_dbg(us, "Reset interrupted by disconnect\n");
return -EIO;
}
- US_DEBUGP("Soft reset: clearing bulk-in endpoint halt\n");
+ usb_stor_dbg(us, "Soft reset: clearing bulk-in endpoint halt\n");
result = usb_stor_clear_halt(us, us->recv_bulk_pipe);
- US_DEBUGP("Soft reset: clearing bulk-out endpoint halt\n");
+ usb_stor_dbg(us, "Soft reset: clearing bulk-out endpoint halt\n");
result2 = usb_stor_clear_halt(us, us->send_bulk_pipe);
/* return a result code based on the result of the clear-halts */
if (result >= 0)
result = result2;
if (result < 0)
- US_DEBUGP("Soft reset failed\n");
+ usb_stor_dbg(us, "Soft reset failed\n");
else
- US_DEBUGP("Soft reset done\n");
+ usb_stor_dbg(us, "Soft reset done\n");
return result;
}
@@ -1299,8 +1297,6 @@ static int usb_stor_reset_common(struct us_data *us,
int usb_stor_CB_reset(struct us_data *us)
{
- US_DEBUGP("%s called\n", __func__);
-
memset(us->iobuf, 0xFF, CB_RESET_CMD_SIZE);
us->iobuf[0] = SEND_DIAGNOSTIC;
us->iobuf[1] = 4;
@@ -1315,8 +1311,6 @@ EXPORT_SYMBOL_GPL(usb_stor_CB_reset);
*/
int usb_stor_Bulk_reset(struct us_data *us)
{
- US_DEBUGP("%s called\n", __func__);
-
return usb_stor_reset_common(us, US_BULK_RESET_REQUEST,
USB_TYPE_CLASS | USB_RECIP_INTERFACE,
0, us->ifnum, NULL, 0);
@@ -1336,16 +1330,17 @@ int usb_stor_port_reset(struct us_data *us)
result = usb_lock_device_for_reset(us->pusb_dev, us->pusb_intf);
if (result < 0)
- US_DEBUGP("unable to lock device for reset: %d\n", result);
+ usb_stor_dbg(us, "unable to lock device for reset: %d\n",
+ result);
else {
/* Were we disconnected while waiting for the lock? */
if (test_bit(US_FLIDX_DISCONNECTING, &us->dflags)) {
result = -EIO;
- US_DEBUGP("No reset during disconnect\n");
+ usb_stor_dbg(us, "No reset during disconnect\n");
} else {
result = usb_reset_device(us->pusb_dev);
- US_DEBUGP("usb_reset_device returns %d\n",
- result);
+ usb_stor_dbg(us, "usb_reset_device returns %d\n",
+ result);
}
usb_unlock_device(us->pusb_dev);
}
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
index 72923b56bbf..1799335288b 100644
--- a/drivers/usb/storage/unusual_devs.h
+++ b/drivers/usb/storage/unusual_devs.h
@@ -53,6 +53,14 @@
* as opposed to devices that do something strangely or wrongly.
*/
+/* In-kernel mode switching is deprecated. Do not add new devices to
+ * this list for the sole purpose of switching them to a different
+ * mode. Existing userspace solutions are superior.
+ *
+ * New mode switching devices should instead be added to the database
+ * maintained at http://www.draisberghof.de/usb_modeswitch/
+ */
+
#if !defined(CONFIG_USB_STORAGE_SDDR09) && \
!defined(CONFIG_USB_STORAGE_SDDR09_MODULE)
#define NO_SDDR09
@@ -488,6 +496,13 @@ UNUSUAL_DEV( 0x04e8, 0x5122, 0x0000, 0x9999,
USB_SC_DEVICE, USB_PR_DEVICE, NULL,
US_FL_MAX_SECTORS_64 | US_FL_BULK_IGNORE_TAG),
+/* Added by Dmitry Artamonow <mad_soft@inbox.ru> */
+UNUSUAL_DEV( 0x04e8, 0x5136, 0x0000, 0x9999,
+ "Samsung",
+ "YP-Z3",
+ USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+ US_FL_MAX_SECTORS_64),
+
/* Entry and supporting patch by Theodore Kilgore <kilgota@auburn.edu>.
* Device uses standards-violating 32-byte Bulk Command Block Wrappers and
* reports itself as "Proprietary SCSI Bulk." Cf. device entry 0x084d:0x0011.
@@ -1527,10 +1542,335 @@ UNUSUAL_DEV( 0x1210, 0x0003, 0x0100, 0x0100,
/* Reported by fangxiaozhi <huananhu@huawei.com>
* This brings the HUAWEI data card devices into multi-port mode
*/
-UNUSUAL_VENDOR_INTF(0x12d1, 0x08, 0x06, 0x50,
+UNUSUAL_DEV( 0x12d1, 0x1001, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x1003, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x1004, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x1401, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x1402, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x1403, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x1404, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x1405, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x1406, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x1407, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x1408, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x1409, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x140A, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x140B, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x140C, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x140D, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x140E, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x140F, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x1410, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x1411, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x1412, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x1413, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x1414, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x1415, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x1416, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x1417, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x1418, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x1419, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x141A, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x141B, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x141C, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x141D, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x141E, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x141F, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x1420, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x1421, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x1422, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x1423, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x1424, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x1425, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x1426, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x1427, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x1428, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x1429, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x142A, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x142B, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x142C, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x142D, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x142E, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x142F, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x1430, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x1431, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x1432, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x1433, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x1434, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x1435, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x1436, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x1437, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x1438, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x1439, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x143A, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x143B, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x143C, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x143D, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x143E, 0x0000, 0x0000,
+ "HUAWEI MOBILE",
+ "Mass Storage",
+ USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+ 0),
+UNUSUAL_DEV( 0x12d1, 0x143F, 0x0000, 0x0000,
"HUAWEI MOBILE",
"Mass Storage",
- USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_init,
+ USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
0),
/* Reported by Vilius Bilinkevicius <vilisas AT xxx DOT lt) */
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
index d6bee407af0..5c4fe0749af 100644
--- a/drivers/usb/storage/usb.c
+++ b/drivers/usb/storage/usb.c
@@ -183,7 +183,6 @@ int usb_stor_suspend(struct usb_interface *iface, pm_message_t message)
/* Wait until no command is running */
mutex_lock(&us->dev_mutex);
- US_DEBUGP("%s\n", __func__);
if (us->suspend_resume_hook)
(us->suspend_resume_hook)(us, US_SUSPEND);
@@ -201,7 +200,6 @@ int usb_stor_resume(struct usb_interface *iface)
mutex_lock(&us->dev_mutex);
- US_DEBUGP("%s\n", __func__);
if (us->suspend_resume_hook)
(us->suspend_resume_hook)(us, US_RESUME);
@@ -214,8 +212,6 @@ int usb_stor_reset_resume(struct usb_interface *iface)
{
struct us_data *us = usb_get_intfdata(iface);
- US_DEBUGP("%s\n", __func__);
-
/* Report the reset to the SCSI core */
usb_stor_report_bus_reset(us);
@@ -236,8 +232,6 @@ int usb_stor_pre_reset(struct usb_interface *iface)
{
struct us_data *us = usb_get_intfdata(iface);
- US_DEBUGP("%s\n", __func__);
-
/* Make sure no command runs during the reset */
mutex_lock(&us->dev_mutex);
return 0;
@@ -248,8 +242,6 @@ int usb_stor_post_reset(struct usb_interface *iface)
{
struct us_data *us = usb_get_intfdata(iface);
- US_DEBUGP("%s\n", __func__);
-
/* Report the reset to the SCSI core */
usb_stor_report_bus_reset(us);
@@ -311,11 +303,11 @@ static int usb_stor_control_thread(void * __us)
struct Scsi_Host *host = us_to_host(us);
for (;;) {
- US_DEBUGP("*** thread sleeping.\n");
+ usb_stor_dbg(us, "*** thread sleeping\n");
if (wait_for_completion_interruptible(&us->cmnd_ready))
break;
- US_DEBUGP("*** thread awakened.\n");
+ usb_stor_dbg(us, "*** thread awakened\n");
/* lock the device pointers */
mutex_lock(&(us->dev_mutex));
@@ -327,7 +319,7 @@ static int usb_stor_control_thread(void * __us)
if (us->srb == NULL) {
scsi_unlock(host);
mutex_unlock(&us->dev_mutex);
- US_DEBUGP("-- exiting\n");
+ usb_stor_dbg(us, "-- exiting\n");
break;
}
@@ -343,7 +335,7 @@ static int usb_stor_control_thread(void * __us)
* is UNKNOWN
*/
if (us->srb->sc_data_direction == DMA_BIDIRECTIONAL) {
- US_DEBUGP("UNKNOWN data direction\n");
+ usb_stor_dbg(us, "UNKNOWN data direction\n");
us->srb->result = DID_ERROR << 16;
}
@@ -352,14 +344,14 @@ static int usb_stor_control_thread(void * __us)
*/
else if (us->srb->device->id &&
!(us->fflags & US_FL_SCM_MULT_TARG)) {
- US_DEBUGP("Bad target number (%d:%d)\n",
- us->srb->device->id, us->srb->device->lun);
+ usb_stor_dbg(us, "Bad target number (%d:%d)\n",
+ us->srb->device->id, us->srb->device->lun);
us->srb->result = DID_BAD_TARGET << 16;
}
else if (us->srb->device->lun > us->max_lun) {
- US_DEBUGP("Bad LUN (%d:%d)\n",
- us->srb->device->id, us->srb->device->lun);
+ usb_stor_dbg(us, "Bad LUN (%d:%d)\n",
+ us->srb->device->id, us->srb->device->lun);
us->srb->result = DID_BAD_TARGET << 16;
}
@@ -371,14 +363,14 @@ static int usb_stor_control_thread(void * __us)
0x00, 0x80, 0x02, 0x02,
0x1F, 0x00, 0x00, 0x00};
- US_DEBUGP("Faking INQUIRY command\n");
+ usb_stor_dbg(us, "Faking INQUIRY command\n");
fill_inquiry_response(us, data_ptr, 36);
us->srb->result = SAM_STAT_GOOD;
}
/* we've got a command, let's do it! */
else {
- US_DEBUG(usb_stor_show_command(us->srb));
+ US_DEBUG(usb_stor_show_command(us, us->srb));
us->proto_handler(us->srb, us);
usb_mark_last_busy(us->pusb_dev);
}
@@ -388,12 +380,12 @@ static int usb_stor_control_thread(void * __us)
/* indicate that the command is done */
if (us->srb->result != DID_ABORT << 16) {
- US_DEBUGP("scsi cmd done, result=0x%x\n",
- us->srb->result);
+ usb_stor_dbg(us, "scsi cmd done, result=0x%x\n",
+ us->srb->result);
us->srb->scsi_done(us->srb);
} else {
SkipForAbort:
- US_DEBUGP("scsi command aborted\n");
+ usb_stor_dbg(us, "scsi command aborted\n");
}
/* If an abort request was received we need to signal that
@@ -435,34 +427,30 @@ SkipForAbort:
/* Associate our private data with the USB device */
static int associate_dev(struct us_data *us, struct usb_interface *intf)
{
- US_DEBUGP("-- %s\n", __func__);
-
/* Fill in the device-related fields */
us->pusb_dev = interface_to_usbdev(intf);
us->pusb_intf = intf;
us->ifnum = intf->cur_altsetting->desc.bInterfaceNumber;
- US_DEBUGP("Vendor: 0x%04x, Product: 0x%04x, Revision: 0x%04x\n",
- le16_to_cpu(us->pusb_dev->descriptor.idVendor),
- le16_to_cpu(us->pusb_dev->descriptor.idProduct),
- le16_to_cpu(us->pusb_dev->descriptor.bcdDevice));
- US_DEBUGP("Interface Subclass: 0x%02x, Protocol: 0x%02x\n",
- intf->cur_altsetting->desc.bInterfaceSubClass,
- intf->cur_altsetting->desc.bInterfaceProtocol);
+ usb_stor_dbg(us, "Vendor: 0x%04x, Product: 0x%04x, Revision: 0x%04x\n",
+ le16_to_cpu(us->pusb_dev->descriptor.idVendor),
+ le16_to_cpu(us->pusb_dev->descriptor.idProduct),
+ le16_to_cpu(us->pusb_dev->descriptor.bcdDevice));
+ usb_stor_dbg(us, "Interface Subclass: 0x%02x, Protocol: 0x%02x\n",
+ intf->cur_altsetting->desc.bInterfaceSubClass,
+ intf->cur_altsetting->desc.bInterfaceProtocol);
/* Store our private data in the interface */
usb_set_intfdata(intf, us);
/* Allocate the control/setup and DMA-mapped buffers */
us->cr = kmalloc(sizeof(*us->cr), GFP_KERNEL);
- if (!us->cr) {
- US_DEBUGP("usb_ctrlrequest allocation failed\n");
+ if (!us->cr)
return -ENOMEM;
- }
us->iobuf = usb_alloc_coherent(us->pusb_dev, US_IOBUF_SIZE,
GFP_KERNEL, &us->iobuf_dma);
if (!us->iobuf) {
- US_DEBUGP("I/O buffer allocation failed\n");
+ usb_stor_dbg(us, "I/O buffer allocation failed\n");
return -ENOMEM;
}
return 0;
@@ -738,7 +726,7 @@ static int get_pipes(struct us_data *us)
}
if (!ep_in || !ep_out || (us->protocol == USB_PR_CBI && !ep_int)) {
- US_DEBUGP("Endpoint sanity check failed! Rejecting dev.\n");
+ usb_stor_dbg(us, "Endpoint sanity check failed! Rejecting dev.\n");
return -EIO;
}
@@ -765,7 +753,7 @@ static int usb_stor_acquire_resources(struct us_data *us)
us->current_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!us->current_urb) {
- US_DEBUGP("URB allocation failed\n");
+ usb_stor_dbg(us, "URB allocation failed\n");
return -ENOMEM;
}
@@ -792,20 +780,18 @@ static int usb_stor_acquire_resources(struct us_data *us)
/* Release all our dynamic resources */
static void usb_stor_release_resources(struct us_data *us)
{
- US_DEBUGP("-- %s\n", __func__);
-
/* Tell the control thread to exit. The SCSI host must
* already have been removed and the DISCONNECTING flag set
* so that we won't accept any more commands.
*/
- US_DEBUGP("-- sending exit command to thread\n");
+ usb_stor_dbg(us, "-- sending exit command to thread\n");
complete(&us->cmnd_ready);
if (us->ctl_thread)
kthread_stop(us->ctl_thread);
/* Call the destructor routine, if it exists */
if (us->extra_destructor) {
- US_DEBUGP("-- calling extra_destructor()\n");
+ usb_stor_dbg(us, "-- calling extra_destructor()\n");
us->extra_destructor(us->extra);
}
@@ -817,8 +803,6 @@ static void usb_stor_release_resources(struct us_data *us)
/* Dissociate from the USB device */
static void dissociate_dev(struct us_data *us)
{
- US_DEBUGP("-- %s\n", __func__);
-
/* Free the buffers */
kfree(us->cr);
usb_free_coherent(us->pusb_dev, US_IOBUF_SIZE, us->iobuf, us->iobuf_dma);
@@ -918,7 +902,7 @@ int usb_stor_probe1(struct us_data **pus,
struct us_data *us;
int result;
- US_DEBUGP("USB Mass Storage device detected\n");
+ dev_info(&intf->dev, "USB Mass Storage device detected\n");
/*
* Ask the SCSI layer to allocate a host structure, with extra
@@ -926,8 +910,7 @@ int usb_stor_probe1(struct us_data **pus,
*/
host = scsi_host_alloc(&usb_stor_host_template, sizeof(*us));
if (!host) {
- dev_warn(&intf->dev,
- "Unable to allocate the scsi host\n");
+ dev_warn(&intf->dev, "Unable to allocate the scsi host\n");
return -ENOMEM;
}
@@ -964,7 +947,7 @@ int usb_stor_probe1(struct us_data **pus,
return 0;
BadDevice:
- US_DEBUGP("storage_probe() failed\n");
+ usb_stor_dbg(us, "storage_probe() failed\n");
release_everything(us);
return result;
}
@@ -981,8 +964,8 @@ int usb_stor_probe2(struct us_data *us)
result = -ENXIO;
goto BadDevice;
}
- US_DEBUGP("Transport: %s\n", us->transport_name);
- US_DEBUGP("Protocol: %s\n", us->protocol_name);
+ usb_stor_dbg(us, "Transport: %s\n", us->transport_name);
+ usb_stor_dbg(us, "Protocol: %s\n", us->protocol_name);
/* fix for single-lun devices */
if (us->fflags & US_FL_SINGLE_LUN)
@@ -1028,7 +1011,7 @@ int usb_stor_probe2(struct us_data *us)
/* We come here if there are any problems */
BadDevice:
- US_DEBUGP("storage_probe() failed\n");
+ usb_stor_dbg(us, "storage_probe() failed\n");
release_everything(us);
return result;
}
@@ -1039,7 +1022,6 @@ void usb_stor_disconnect(struct usb_interface *intf)
{
struct us_data *us = usb_get_intfdata(intf);
- US_DEBUGP("storage_disconnect() called\n");
quiesce_and_remove_host(us);
release_everything(us);
}
@@ -1075,8 +1057,7 @@ static int storage_probe(struct usb_interface *intf,
} else {
unusual_dev = &for_dynamic_ids;
- US_DEBUGP("%s %s 0x%04x 0x%04x\n", "Use Bulk-Only transport",
- "with the Transparent SCSI protocol for dynamic id:",
+ dev_dbg(&intf->dev, "Use Bulk-Only transport with the Transparent SCSI protocol for dynamic id: 0x%04x 0x%04x\n",
id->idVendor, id->idProduct);
}
@@ -1090,10 +1071,6 @@ static int storage_probe(struct usb_interface *intf,
return result;
}
-/***********************************************************************
- * Initialization and registration
- ***********************************************************************/
-
static struct usb_driver usb_storage_driver = {
.name = "usb-storage",
.probe = storage_probe,
@@ -1108,30 +1085,4 @@ static struct usb_driver usb_storage_driver = {
.soft_unbind = 1,
};
-static int __init usb_stor_init(void)
-{
- int retval;
-
- pr_info("Initializing USB Mass Storage driver...\n");
-
- /* register the driver, return usb_register return code if error */
- retval = usb_register(&usb_storage_driver);
- if (retval == 0)
- pr_info("USB Mass Storage support registered.\n");
- return retval;
-}
-
-static void __exit usb_stor_exit(void)
-{
- US_DEBUGP("usb_stor_exit() called\n");
-
- /* Deregister the driver
- * This will cause disconnect() to be called for each
- * attached unit
- */
- US_DEBUGP("-- calling usb_deregister()\n");
- usb_deregister(&usb_storage_driver) ;
-}
-
-module_init(usb_stor_init);
-module_exit(usb_stor_exit);
+module_usb_driver(usb_storage_driver);
diff --git a/drivers/usb/usb-common.c b/drivers/usb/usb-common.c
index d29503e954a..0db0a919d72 100644
--- a/drivers/usb/usb-common.c
+++ b/drivers/usb/usb-common.c
@@ -14,6 +14,32 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/usb/ch9.h>
+#include <linux/usb/otg.h>
+
+const char *usb_otg_state_string(enum usb_otg_state state)
+{
+ static const char *const names[] = {
+ [OTG_STATE_A_IDLE] = "a_idle",
+ [OTG_STATE_A_WAIT_VRISE] = "a_wait_vrise",
+ [OTG_STATE_A_WAIT_BCON] = "a_wait_bcon",
+ [OTG_STATE_A_HOST] = "a_host",
+ [OTG_STATE_A_SUSPEND] = "a_suspend",
+ [OTG_STATE_A_PERIPHERAL] = "a_peripheral",
+ [OTG_STATE_A_WAIT_VFALL] = "a_wait_vfall",
+ [OTG_STATE_A_VBUS_ERR] = "a_vbus_err",
+ [OTG_STATE_B_IDLE] = "b_idle",
+ [OTG_STATE_B_SRP_INIT] = "b_srp_init",
+ [OTG_STATE_B_PERIPHERAL] = "b_peripheral",
+ [OTG_STATE_B_WAIT_ACON] = "b_wait_acon",
+ [OTG_STATE_B_HOST] = "b_host",
+ };
+
+ if (state < 0 || state >= ARRAY_SIZE(names))
+ return "UNDEFINED";
+
+ return names[state];
+}
+EXPORT_SYMBOL_GPL(usb_otg_state_string);
const char *usb_speed_string(enum usb_device_speed speed)
{
@@ -32,4 +58,25 @@ const char *usb_speed_string(enum usb_device_speed speed)
}
EXPORT_SYMBOL_GPL(usb_speed_string);
+const char *usb_state_string(enum usb_device_state state)
+{
+ static const char *const names[] = {
+ [USB_STATE_NOTATTACHED] = "not attached",
+ [USB_STATE_ATTACHED] = "attached",
+ [USB_STATE_POWERED] = "powered",
+ [USB_STATE_RECONNECTING] = "reconnecting",
+ [USB_STATE_UNAUTHENTICATED] = "unauthenticated",
+ [USB_STATE_DEFAULT] = "default",
+ [USB_STATE_ADDRESS] = "addresssed",
+ [USB_STATE_CONFIGURED] = "configured",
+ [USB_STATE_SUSPENDED] = "suspended",
+ };
+
+ if (state < 0 || state >= ARRAY_SIZE(names))
+ return "UNKNOWN";
+
+ return names[state];
+}
+EXPORT_SYMBOL_GPL(usb_state_string);
+
MODULE_LICENSE("GPL");
diff --git a/drivers/usb/usb-skeleton.c b/drivers/usb/usb-skeleton.c
index ce310170829..7ed3b039dbe 100644
--- a/drivers/usb/usb-skeleton.c
+++ b/drivers/usb/usb-skeleton.c
@@ -61,11 +61,10 @@ struct usb_skel {
__u8 bulk_out_endpointAddr; /* the address of the bulk out endpoint */
int errors; /* the last request tanked */
bool ongoing_read; /* a read is going on */
- bool processed_urb; /* indicates we haven't processed the urb */
spinlock_t err_lock; /* lock for errors */
struct kref kref;
struct mutex io_mutex; /* synchronize I/O with disconnect */
- struct completion bulk_in_completion; /* to wait for an ongoing read */
+ wait_queue_head_t bulk_in_wait; /* to wait for an ongoing read */
};
#define to_skel_dev(d) container_of(d, struct usb_skel, kref)
@@ -185,7 +184,7 @@ static void skel_read_bulk_callback(struct urb *urb)
dev->ongoing_read = 0;
spin_unlock(&dev->err_lock);
- complete(&dev->bulk_in_completion);
+ wake_up_interruptible(&dev->bulk_in_wait);
}
static int skel_do_read_io(struct usb_skel *dev, size_t count)
@@ -206,13 +205,16 @@ static int skel_do_read_io(struct usb_skel *dev, size_t count)
dev->ongoing_read = 1;
spin_unlock_irq(&dev->err_lock);
+ /* submit bulk in urb, which means no data to deliver */
+ dev->bulk_in_filled = 0;
+ dev->bulk_in_copied = 0;
+
/* do it */
rv = usb_submit_urb(dev->bulk_in_urb, GFP_KERNEL);
if (rv < 0) {
dev_err(&dev->interface->dev,
"%s - failed submitting read urb, error %d\n",
__func__, rv);
- dev->bulk_in_filled = 0;
rv = (rv == -ENOMEM) ? rv : -EIO;
spin_lock_irq(&dev->err_lock);
dev->ongoing_read = 0;
@@ -261,25 +263,9 @@ retry:
* IO may take forever
* hence wait in an interruptible state
*/
- rv = wait_for_completion_interruptible(&dev->bulk_in_completion);
+ rv = wait_event_interruptible(dev->bulk_in_wait, (!dev->ongoing_read));
if (rv < 0)
goto exit;
- /*
- * by waiting we also semiprocessed the urb
- * we must finish now
- */
- dev->bulk_in_copied = 0;
- dev->processed_urb = 1;
- }
-
- if (!dev->processed_urb) {
- /*
- * the URB hasn't been processed
- * do it now
- */
- wait_for_completion(&dev->bulk_in_completion);
- dev->bulk_in_copied = 0;
- dev->processed_urb = 1;
}
/* errors must be reported */
@@ -289,8 +275,6 @@ retry:
dev->errors = 0;
/* to preserve notifications about reset */
rv = (rv == -EPIPE) ? rv : -EIO;
- /* no data to deliver */
- dev->bulk_in_filled = 0;
/* report it */
goto exit;
}
@@ -526,7 +510,7 @@ static int skel_probe(struct usb_interface *interface,
mutex_init(&dev->io_mutex);
spin_lock_init(&dev->err_lock);
init_usb_anchor(&dev->submitted);
- init_completion(&dev->bulk_in_completion);
+ init_waitqueue_head(&dev->bulk_in_wait);
dev->udev = usb_get_dev(interface_to_usbdev(interface));
dev->interface = interface;
diff --git a/drivers/usb/wusbcore/Kconfig b/drivers/usb/wusbcore/Kconfig
index 8bf19760d44..0e17b966e1b 100644
--- a/drivers/usb/wusbcore/Kconfig
+++ b/drivers/usb/wusbcore/Kconfig
@@ -3,7 +3,6 @@
#
config USB_WUSB
tristate "Enable Wireless USB extensions"
- depends on USB
depends on PCI
depends on UWB
select CRYPTO
@@ -19,7 +18,6 @@ config USB_WUSB
config USB_WUSB_CBAF
tristate "Support WUSB Cable Based Association (CBA)"
- depends on USB
help
Some WUSB devices support Cable Based Association. It's used to
enable the secure communication between the host and the