summaryrefslogtreecommitdiff
path: root/drivers/usb
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/c67x00/c67x00-drv.c6
-rw-r--r--drivers/usb/chipidea/Kconfig1
-rw-r--r--drivers/usb/chipidea/ci13xxx_imx.c8
-rw-r--r--drivers/usb/chipidea/ci13xxx_msm.c6
-rw-r--r--drivers/usb/chipidea/ci13xxx_pci.c6
-rw-r--r--drivers/usb/chipidea/core.c9
-rw-r--r--drivers/usb/chipidea/debug.c3
-rw-r--r--drivers/usb/chipidea/host.c67
-rw-r--r--drivers/usb/chipidea/usbmisc_imx6q.c6
-rw-r--r--drivers/usb/class/cdc-acm.c38
-rw-r--r--drivers/usb/core/devices.c18
-rw-r--r--drivers/usb/core/driver.c25
-rw-r--r--drivers/usb/core/generic.c7
-rw-r--r--drivers/usb/core/hcd.c35
-rw-r--r--drivers/usb/core/hub.c97
-rw-r--r--drivers/usb/core/message.c66
-rw-r--r--drivers/usb/core/urb.c29
-rw-r--r--drivers/usb/core/usb.c13
-rw-r--r--drivers/usb/dwc3/Makefile14
-rw-r--r--drivers/usb/dwc3/core.c96
-rw-r--r--drivers/usb/dwc3/core.h3
-rw-r--r--drivers/usb/dwc3/debugfs.c4
-rw-r--r--drivers/usb/dwc3/dwc3-exynos.c57
-rw-r--r--drivers/usb/dwc3/dwc3-omap.c24
-rw-r--r--drivers/usb/dwc3/dwc3-pci.c24
-rw-r--r--drivers/usb/dwc3/gadget.c4
-rw-r--r--drivers/usb/early/ehci-dbgp.c15
-rw-r--r--drivers/usb/gadget/Kconfig29
-rw-r--r--drivers/usb/gadget/Makefile2
-rw-r--r--drivers/usb/gadget/at91_udc.c4
-rw-r--r--drivers/usb/gadget/bcm63xx_udc.c6
-rw-r--r--drivers/usb/gadget/composite.c8
-rw-r--r--drivers/usb/gadget/config.c39
-rw-r--r--drivers/usb/gadget/dummy_hcd.c170
-rw-r--r--drivers/usb/gadget/f_acm.c79
-rw-r--r--drivers/usb/gadget/f_ecm.c112
-rw-r--r--drivers/usb/gadget/f_eem.c51
-rw-r--r--drivers/usb/gadget/f_fs.c4
-rw-r--r--drivers/usb/gadget/f_hid.c30
-rw-r--r--drivers/usb/gadget/f_loopback.c28
-rw-r--r--drivers/usb/gadget/f_mass_storage.c63
-rw-r--r--drivers/usb/gadget/f_midi.c14
-rw-r--r--drivers/usb/gadget/f_ncm.c94
-rw-r--r--drivers/usb/gadget/f_obex.c42
-rw-r--r--drivers/usb/gadget/f_phonet.c21
-rw-r--r--drivers/usb/gadget/f_rndis.c94
-rw-r--r--drivers/usb/gadget/f_serial.c38
-rw-r--r--drivers/usb/gadget/f_sourcesink.c104
-rw-r--r--drivers/usb/gadget/f_subset.c75
-rw-r--r--drivers/usb/gadget/f_uac1.c23
-rw-r--r--drivers/usb/gadget/f_uac2.c222
-rw-r--r--drivers/usb/gadget/f_uvc.c138
-rw-r--r--drivers/usb/gadget/file_storage.c3656
-rw-r--r--drivers/usb/gadget/fsl_qe_udc.c14
-rw-r--r--drivers/usb/gadget/fsl_udc_core.c2
-rw-r--r--drivers/usb/gadget/hid.c4
-rw-r--r--drivers/usb/gadget/inode.c3
-rw-r--r--drivers/usb/gadget/lpc32xx_udc.c6
-rw-r--r--drivers/usb/gadget/mv_u3d_core.c2
-rw-r--r--drivers/usb/gadget/mv_udc_core.c4
-rw-r--r--drivers/usb/gadget/net2272.c29
-rw-r--r--drivers/usb/gadget/net2280.c2
-rw-r--r--drivers/usb/gadget/omap_udc.c10
-rw-r--r--drivers/usb/gadget/printer.c12
-rw-r--r--drivers/usb/gadget/pxa27x_udc.h2
-rw-r--r--drivers/usb/gadget/s3c-hsotg.c12
-rw-r--r--drivers/usb/gadget/s3c-hsudc.c2
-rw-r--r--drivers/usb/gadget/storage_common.c165
-rw-r--r--drivers/usb/gadget/tcm_usb_gadget.c13
-rw-r--r--drivers/usb/gadget/u_ether.c3
-rw-r--r--drivers/usb/gadget/u_serial.c5
-rw-r--r--drivers/usb/gadget/udc-core.c11
-rw-r--r--drivers/usb/host/Kconfig35
-rw-r--r--drivers/usb/host/Makefile4
-rw-r--r--drivers/usb/host/alchemy-common.c614
-rw-r--r--drivers/usb/host/bcma-hcd.c15
-rw-r--r--drivers/usb/host/ehci-atmel.c15
-rw-r--r--drivers/usb/host/ehci-au1xxx.c184
-rw-r--r--drivers/usb/host/ehci-cns3xxx.c155
-rw-r--r--drivers/usb/host/ehci-dbg.c112
-rw-r--r--drivers/usb/host/ehci-fsl.c1
-rw-r--r--drivers/usb/host/ehci-grlib.c20
-rw-r--r--drivers/usb/host/ehci-hcd.c204
-rw-r--r--drivers/usb/host/ehci-hub.c47
-rw-r--r--drivers/usb/host/ehci-ixp4xx.c139
-rw-r--r--drivers/usb/host/ehci-lpm.c84
-rw-r--r--drivers/usb/host/ehci-ls1x.c147
-rw-r--r--drivers/usb/host/ehci-msm.c5
-rw-r--r--drivers/usb/host/ehci-mxc.c10
-rw-r--r--drivers/usb/host/ehci-octeon.c3
-rw-r--r--drivers/usb/host/ehci-omap.c3
-rw-r--r--drivers/usb/host/ehci-orion.c20
-rw-r--r--drivers/usb/host/ehci-pci.c132
-rw-r--r--drivers/usb/host/ehci-platform.c102
-rw-r--r--drivers/usb/host/ehci-pmcmsp.c1
-rw-r--r--drivers/usb/host/ehci-ppc-of.c4
-rw-r--r--drivers/usb/host/ehci-ps3.c2
-rw-r--r--drivers/usb/host/ehci-q.c12
-rw-r--r--drivers/usb/host/ehci-s5p.c16
-rw-r--r--drivers/usb/host/ehci-sched.c136
-rw-r--r--drivers/usb/host/ehci-sh.c9
-rw-r--r--drivers/usb/host/ehci-spear.c59
-rw-r--r--drivers/usb/host/ehci-tegra.c18
-rw-r--r--drivers/usb/host/ehci-vt8500.c21
-rw-r--r--drivers/usb/host/ehci-w90x900.c10
-rw-r--r--drivers/usb/host/ehci-xilinx-of.c2
-rw-r--r--drivers/usb/host/ehci-xls.c142
-rw-r--r--drivers/usb/host/ehci.h45
-rw-r--r--drivers/usb/host/fhci-hcd.c8
-rw-r--r--drivers/usb/host/fsl-mph-dr-of.c16
-rw-r--r--drivers/usb/host/imx21-hcd.c2
-rw-r--r--drivers/usb/host/isp116x-hcd.c2
-rw-r--r--drivers/usb/host/isp1362-hcd.c6
-rw-r--r--drivers/usb/host/isp1760-if.c15
-rw-r--r--drivers/usb/host/ohci-at91.c22
-rw-r--r--drivers/usb/host/ohci-au1xxx.c234
-rw-r--r--drivers/usb/host/ohci-cns3xxx.c166
-rw-r--r--drivers/usb/host/ohci-ep93xx.c4
-rw-r--r--drivers/usb/host/ohci-exynos.c38
-rw-r--r--drivers/usb/host/ohci-hcd.c139
-rw-r--r--drivers/usb/host/ohci-hub.c42
-rw-r--r--drivers/usb/host/ohci-jz4740.c6
-rw-r--r--drivers/usb/host/ohci-nxp.c4
-rw-r--r--drivers/usb/host/ohci-octeon.c2
-rw-r--r--drivers/usb/host/ohci-omap.c2
-rw-r--r--drivers/usb/host/ohci-omap3.c6
-rw-r--r--drivers/usb/host/ohci-pci.c49
-rw-r--r--drivers/usb/host/ohci-platform.c34
-rw-r--r--drivers/usb/host/ohci-pnx8550.c243
-rw-r--r--drivers/usb/host/ohci-ppc-of.c4
-rw-r--r--drivers/usb/host/ohci-ppc-soc.c216
-rw-r--r--drivers/usb/host/ohci-ps3.c4
-rw-r--r--drivers/usb/host/ohci-pxa27x.c8
-rw-r--r--drivers/usb/host/ohci-q.c23
-rw-r--r--drivers/usb/host/ohci-s3c2410.c41
-rw-r--r--drivers/usb/host/ohci-sa1111.c2
-rw-r--r--drivers/usb/host/ohci-sh.c141
-rw-r--r--drivers/usb/host/ohci-sm501.c2
-rw-r--r--drivers/usb/host/ohci-spear.c50
-rw-r--r--drivers/usb/host/ohci-tmio.c8
-rw-r--r--drivers/usb/host/ohci-xls.c152
-rw-r--r--drivers/usb/host/pci-quirks.c20
-rw-r--r--drivers/usb/host/r8a66597-hcd.c12
-rw-r--r--drivers/usb/host/sl811-hcd.c6
-rw-r--r--drivers/usb/host/ssb-hcd.c19
-rw-r--r--drivers/usb/host/u132-hcd.c6
-rw-r--r--drivers/usb/host/uhci-grlib.c2
-rw-r--r--drivers/usb/host/uhci-platform.c2
-rw-r--r--drivers/usb/host/uhci-q.c73
-rw-r--r--drivers/usb/host/xhci-mem.c9
-rw-r--r--drivers/usb/host/xhci-pci.c16
-rw-r--r--drivers/usb/host/xhci-ring.c34
-rw-r--r--drivers/usb/host/xhci.c32
-rw-r--r--drivers/usb/host/xhci.h2
-rw-r--r--drivers/usb/misc/Kconfig1
-rw-r--r--drivers/usb/misc/ezusb.c38
-rw-r--r--drivers/usb/misc/usbtest.c4
-rw-r--r--drivers/usb/musb/am35x.c40
-rw-r--r--drivers/usb/musb/blackfin.c38
-rw-r--r--drivers/usb/musb/cppi_dma.c4
-rw-r--r--drivers/usb/musb/da8xx.c40
-rw-r--r--drivers/usb/musb/davinci.c40
-rw-r--r--drivers/usb/musb/musb_core.c137
-rw-r--r--drivers/usb/musb/musb_core.h5
-rw-r--r--drivers/usb/musb/musb_debugfs.c2
-rw-r--r--drivers/usb/musb/musb_dma.h3
-rw-r--r--drivers/usb/musb/musb_dsps.c141
-rw-r--r--drivers/usb/musb/musb_gadget.c66
-rw-r--r--drivers/usb/musb/musb_gadget_ep0.c6
-rw-r--r--drivers/usb/musb/musb_host.c2
-rw-r--r--drivers/usb/musb/musbhsdma.c3
-rw-r--r--drivers/usb/musb/musbhsdma.h4
-rw-r--r--drivers/usb/musb/omap2430.c52
-rw-r--r--drivers/usb/musb/tusb6010.c40
-rw-r--r--drivers/usb/musb/tusb6010_omap.c3
-rw-r--r--drivers/usb/musb/ux500.c62
-rw-r--r--drivers/usb/musb/ux500_dma.c3
-rw-r--r--drivers/usb/otg/Kconfig4
-rw-r--r--drivers/usb/otg/ab8500-usb.c6
-rw-r--r--drivers/usb/otg/fsl_otg.c6
-rw-r--r--drivers/usb/otg/isp1301_omap.c2
-rw-r--r--drivers/usb/otg/msm_otg.c4
-rw-r--r--drivers/usb/otg/mv_otg.c14
-rw-r--r--drivers/usb/otg/mxs-phy.c59
-rw-r--r--drivers/usb/otg/nop-usb-xceiv.c6
-rw-r--r--drivers/usb/otg/twl4030-usb.c48
-rw-r--r--drivers/usb/otg/twl6030-usb.c2
-rw-r--r--drivers/usb/phy/Kconfig12
-rw-r--r--drivers/usb/phy/Makefile1
-rw-r--r--drivers/usb/phy/mv_u3d_phy.c4
-rw-r--r--drivers/usb/phy/omap-usb2.c6
-rw-r--r--drivers/usb/phy/rcar-phy.c220
-rw-r--r--drivers/usb/phy/tegra_usb_phy.c4
-rw-r--r--drivers/usb/renesas_usbhs/common.c9
-rw-r--r--drivers/usb/renesas_usbhs/common.h1
-rw-r--r--drivers/usb/renesas_usbhs/fifo.c14
-rw-r--r--drivers/usb/renesas_usbhs/mod.c3
-rw-r--r--drivers/usb/renesas_usbhs/mod_gadget.c11
-rw-r--r--drivers/usb/renesas_usbhs/mod_host.c45
-rw-r--r--drivers/usb/renesas_usbhs/pipe.c101
-rw-r--r--drivers/usb/renesas_usbhs/pipe.h1
-rw-r--r--drivers/usb/serial/aircable.c5
-rw-r--r--drivers/usb/serial/ark3116.c5
-rw-r--r--drivers/usb/serial/belkin_sa.c5
-rw-r--r--drivers/usb/serial/bus.c10
-rw-r--r--drivers/usb/serial/cp210x.c37
-rw-r--r--drivers/usb/serial/cyberjack.c5
-rw-r--r--drivers/usb/serial/cypress_m8.c5
-rw-r--r--drivers/usb/serial/digi_acceleport.c4
-rw-r--r--drivers/usb/serial/empeg.c4
-rw-r--r--drivers/usb/serial/ftdi_sio.c82
-rw-r--r--drivers/usb/serial/ftdi_sio_ids.h6
-rw-r--r--drivers/usb/serial/generic.c1
-rw-r--r--drivers/usb/serial/hp4x.c5
-rw-r--r--drivers/usb/serial/io_edgeport.c4
-rw-r--r--drivers/usb/serial/io_ti.c4
-rw-r--r--drivers/usb/serial/ipaq.c5
-rw-r--r--drivers/usb/serial/ipw.c4
-rw-r--r--drivers/usb/serial/iuu_phoenix.c8
-rw-r--r--drivers/usb/serial/keyspan.c7
-rw-r--r--drivers/usb/serial/keyspan_pda.c4
-rw-r--r--drivers/usb/serial/kl5kusb105.c4
-rw-r--r--drivers/usb/serial/kobil_sct.c2
-rw-r--r--drivers/usb/serial/mct_u232.c4
-rw-r--r--drivers/usb/serial/metro-usb.c2
-rw-r--r--drivers/usb/serial/mos7720.c4
-rw-r--r--drivers/usb/serial/mos7840.c4
-rw-r--r--drivers/usb/serial/omninet.c4
-rw-r--r--drivers/usb/serial/opticon.c351
-rw-r--r--drivers/usb/serial/option.c122
-rw-r--r--drivers/usb/serial/oti6858.c2
-rw-r--r--drivers/usb/serial/quatech2.c2
-rw-r--r--drivers/usb/serial/siemens_mpi.c2
-rw-r--r--drivers/usb/serial/sierra.c3
-rw-r--r--drivers/usb/serial/spcp8x5.c4
-rw-r--r--drivers/usb/serial/ssu100.c2
-rw-r--r--drivers/usb/serial/usb-serial.c1
-rw-r--r--drivers/usb/serial/usb_wwan.c12
-rw-r--r--drivers/usb/serial/vivopay-serial.c3
-rw-r--r--drivers/usb/storage/Kconfig2
-rw-r--r--drivers/usb/storage/realtek_cr.c2
-rw-r--r--drivers/usb/storage/scsiglue.c6
-rw-r--r--drivers/usb/storage/usb.c1
-rw-r--r--drivers/usb/usb-skeleton.c13
-rw-r--r--drivers/usb/wusbcore/devconnect.c13
245 files changed, 2809 insertions, 9863 deletions
diff --git a/drivers/usb/c67x00/c67x00-drv.c b/drivers/usb/c67x00/c67x00-drv.c
index 6f3b6e267398..fe815ecd557e 100644
--- a/drivers/usb/c67x00/c67x00-drv.c
+++ b/drivers/usb/c67x00/c67x00-drv.c
@@ -116,7 +116,7 @@ static irqreturn_t c67x00_irq(int irq, void *__dev)
/* ------------------------------------------------------------------------- */
-static int __devinit c67x00_drv_probe(struct platform_device *pdev)
+static int c67x00_drv_probe(struct platform_device *pdev)
{
struct c67x00_device *c67x00;
struct c67x00_platform_data *pdata;
@@ -191,7 +191,7 @@ static int __devinit c67x00_drv_probe(struct platform_device *pdev)
return ret;
}
-static int __devexit c67x00_drv_remove(struct platform_device *pdev)
+static int c67x00_drv_remove(struct platform_device *pdev)
{
struct c67x00_device *c67x00 = platform_get_drvdata(pdev);
struct resource *res;
@@ -219,7 +219,7 @@ static int __devexit c67x00_drv_remove(struct platform_device *pdev)
static struct platform_driver c67x00_driver = {
.probe = c67x00_drv_probe,
- .remove = __devexit_p(c67x00_drv_remove),
+ .remove = c67x00_drv_remove,
.driver = {
.owner = THIS_MODULE,
.name = "c67x00",
diff --git a/drivers/usb/chipidea/Kconfig b/drivers/usb/chipidea/Kconfig
index 1ea932a13685..608a2aeb400c 100644
--- a/drivers/usb/chipidea/Kconfig
+++ b/drivers/usb/chipidea/Kconfig
@@ -20,6 +20,7 @@ config USB_CHIPIDEA_UDC
config USB_CHIPIDEA_HOST
bool "ChipIdea host controller"
depends on USB=y || USB=USB_CHIPIDEA
+ depends on USB_EHCI_HCD
select USB_EHCI_ROOT_HUB_TT
help
Say Y here to enable host controller functionality of the
diff --git a/drivers/usb/chipidea/ci13xxx_imx.c b/drivers/usb/chipidea/ci13xxx_imx.c
index 0f5ca4bea17f..8c291220be7f 100644
--- a/drivers/usb/chipidea/ci13xxx_imx.c
+++ b/drivers/usb/chipidea/ci13xxx_imx.c
@@ -85,7 +85,7 @@ EXPORT_SYMBOL_GPL(usbmisc_get_init_data);
/* End of common functions shared by usbmisc drivers*/
-static struct ci13xxx_platform_data ci13xxx_imx_platdata __devinitdata = {
+static struct ci13xxx_platform_data ci13xxx_imx_platdata = {
.name = "ci13xxx_imx",
.flags = CI13XXX_REQUIRE_TRANSCEIVER |
CI13XXX_PULLUP_ON_VBUS |
@@ -93,7 +93,7 @@ static struct ci13xxx_platform_data ci13xxx_imx_platdata __devinitdata = {
.capoffset = DEF_CAPOFFSET,
};
-static int __devinit ci13xxx_imx_probe(struct platform_device *pdev)
+static int ci13xxx_imx_probe(struct platform_device *pdev)
{
struct ci13xxx_imx_data *data;
struct platform_device *plat_ci, *phy_pdev;
@@ -220,7 +220,7 @@ put_np:
return ret;
}
-static int __devexit ci13xxx_imx_remove(struct platform_device *pdev)
+static int ci13xxx_imx_remove(struct platform_device *pdev)
{
struct ci13xxx_imx_data *data = platform_get_drvdata(pdev);
@@ -252,7 +252,7 @@ MODULE_DEVICE_TABLE(of, ci13xxx_imx_dt_ids);
static struct platform_driver ci13xxx_imx_driver = {
.probe = ci13xxx_imx_probe,
- .remove = __devexit_p(ci13xxx_imx_remove),
+ .remove = ci13xxx_imx_remove,
.driver = {
.name = "imx_usb",
.owner = THIS_MODULE,
diff --git a/drivers/usb/chipidea/ci13xxx_msm.c b/drivers/usb/chipidea/ci13xxx_msm.c
index b01feb3be92e..7d16681fd3d2 100644
--- a/drivers/usb/chipidea/ci13xxx_msm.c
+++ b/drivers/usb/chipidea/ci13xxx_msm.c
@@ -55,7 +55,7 @@ static struct ci13xxx_platform_data ci13xxx_msm_platdata = {
.notify_event = ci13xxx_msm_notify_event,
};
-static int __devinit ci13xxx_msm_probe(struct platform_device *pdev)
+static int ci13xxx_msm_probe(struct platform_device *pdev)
{
struct platform_device *plat_ci;
@@ -77,7 +77,7 @@ static int __devinit ci13xxx_msm_probe(struct platform_device *pdev)
return 0;
}
-static int __devexit ci13xxx_msm_remove(struct platform_device *pdev)
+static int ci13xxx_msm_remove(struct platform_device *pdev)
{
struct platform_device *plat_ci = platform_get_drvdata(pdev);
@@ -89,7 +89,7 @@ static int __devexit ci13xxx_msm_remove(struct platform_device *pdev)
static struct platform_driver ci13xxx_msm_driver = {
.probe = ci13xxx_msm_probe,
- .remove = __devexit_p(ci13xxx_msm_remove),
+ .remove = ci13xxx_msm_remove,
.driver = { .name = "msm_hsusb", },
};
diff --git a/drivers/usb/chipidea/ci13xxx_pci.c b/drivers/usb/chipidea/ci13xxx_pci.c
index 918e14971f2b..9b227e39299a 100644
--- a/drivers/usb/chipidea/ci13xxx_pci.c
+++ b/drivers/usb/chipidea/ci13xxx_pci.c
@@ -48,7 +48,7 @@ struct ci13xxx_platform_data penwell_pci_platdata = {
* Allocates basic PCI resources for this USB device controller, and then
* invokes the udc_probe() method to start the UDC associated with it
*/
-static int __devinit ci13xxx_pci_probe(struct pci_dev *pdev,
+static int ci13xxx_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{
struct ci13xxx_platform_data *platdata = (void *)id->driver_data;
@@ -107,7 +107,7 @@ static int __devinit ci13xxx_pci_probe(struct pci_dev *pdev,
* first invoking the udc_remove() and then releases
* all PCI resources allocated for this USB device controller
*/
-static void __devexit ci13xxx_pci_remove(struct pci_dev *pdev)
+static void ci13xxx_pci_remove(struct pci_dev *pdev)
{
struct platform_device *plat_ci = pci_get_drvdata(pdev);
@@ -147,7 +147,7 @@ static struct pci_driver ci13xxx_pci_driver = {
.name = UDC_DRIVER_NAME,
.id_table = ci13xxx_pci_id_table,
.probe = ci13xxx_pci_probe,
- .remove = __devexit_p(ci13xxx_pci_remove),
+ .remove = ci13xxx_pci_remove,
};
module_pci_driver(ci13xxx_pci_driver);
diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c
index f69d029b4607..aebf695a9344 100644
--- a/drivers/usb/chipidea/core.c
+++ b/drivers/usb/chipidea/core.c
@@ -385,12 +385,13 @@ EXPORT_SYMBOL_GPL(ci13xxx_add_device);
void ci13xxx_remove_device(struct platform_device *pdev)
{
+ int id = pdev->id;
platform_device_unregister(pdev);
- ida_simple_remove(&ci_ida, pdev->id);
+ ida_simple_remove(&ci_ida, id);
}
EXPORT_SYMBOL_GPL(ci13xxx_remove_device);
-static int __devinit ci_hdrc_probe(struct platform_device *pdev)
+static int ci_hdrc_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct ci13xxx *ci;
@@ -508,7 +509,7 @@ rm_wq:
return ret;
}
-static int __devexit ci_hdrc_remove(struct platform_device *pdev)
+static int ci_hdrc_remove(struct platform_device *pdev)
{
struct ci13xxx *ci = platform_get_drvdata(pdev);
@@ -523,7 +524,7 @@ static int __devexit ci_hdrc_remove(struct platform_device *pdev)
static struct platform_driver ci_hdrc_driver = {
.probe = ci_hdrc_probe,
- .remove = __devexit_p(ci_hdrc_remove),
+ .remove = ci_hdrc_remove,
.driver = {
.name = "ci_hdrc",
},
diff --git a/drivers/usb/chipidea/debug.c b/drivers/usb/chipidea/debug.c
index c6f50a257565..3bc244d2636a 100644
--- a/drivers/usb/chipidea/debug.c
+++ b/drivers/usb/chipidea/debug.c
@@ -160,9 +160,6 @@ static ssize_t show_device(struct device *dev, struct device_attribute *attr,
gadget->speed);
n += scnprintf(buf + n, PAGE_SIZE - n, "max_speed = %d\n",
gadget->max_speed);
- /* TODO: Scheduled for removal in 3.8. */
- n += scnprintf(buf + n, PAGE_SIZE - n, "is_dualspeed = %d\n",
- gadget_is_dualspeed(gadget));
n += scnprintf(buf + n, PAGE_SIZE - n, "is_otg = %d\n",
gadget->is_otg);
n += scnprintf(buf + n, PAGE_SIZE - n, "is_a_peripheral = %d\n",
diff --git a/drivers/usb/chipidea/host.c b/drivers/usb/chipidea/host.c
index ebff9f4f56ec..caecad9213f5 100644
--- a/drivers/usb/chipidea/host.c
+++ b/drivers/usb/chipidea/host.c
@@ -20,77 +20,18 @@
*/
#include <linux/kernel.h>
+#include <linux/io.h>
#include <linux/usb.h>
#include <linux/usb/hcd.h>
#include <linux/usb/chipidea.h>
-#define CHIPIDEA_EHCI
-#include "../host/ehci-hcd.c"
+#include "../host/ehci.h"
#include "ci.h"
#include "bits.h"
#include "host.h"
-static int ci_ehci_setup(struct usb_hcd *hcd)
-{
- struct ehci_hcd *ehci = hcd_to_ehci(hcd);
- int ret;
-
- hcd->has_tt = 1;
-
- ret = ehci_setup(hcd);
- if (ret)
- return ret;
-
- ehci_port_power(ehci, 0);
-
- return ret;
-}
-
-static const struct hc_driver ci_ehci_hc_driver = {
- .description = "ehci_hcd",
- .product_desc = "ChipIdea HDRC EHCI",
- .hcd_priv_size = sizeof(struct ehci_hcd),
-
- /*
- * generic hardware linkage
- */
- .irq = ehci_irq,
- .flags = HCD_MEMORY | HCD_USB2,
-
- /*
- * basic lifecycle operations
- */
- .reset = ci_ehci_setup,
- .start = ehci_run,
- .stop = ehci_stop,
- .shutdown = ehci_shutdown,
-
- /*
- * managing i/o requests and associated device resources
- */
- .urb_enqueue = ehci_urb_enqueue,
- .urb_dequeue = ehci_urb_dequeue,
- .endpoint_disable = ehci_endpoint_disable,
- .endpoint_reset = ehci_endpoint_reset,
-
- /*
- * scheduling support
- */
- .get_frame_number = ehci_get_frame,
-
- /*
- * root hub support
- */
- .hub_status_data = ehci_hub_status_data,
- .hub_control = ehci_hub_control,
- .bus_suspend = ehci_bus_suspend,
- .bus_resume = ehci_bus_resume,
- .relinquish_port = ehci_relinquish_port,
- .port_handed_over = ehci_port_handed_over,
-
- .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
-};
+static struct hc_driver __read_mostly ci_ehci_hc_driver;
static irqreturn_t host_irq(struct ci13xxx *ci)
{
@@ -157,5 +98,7 @@ int ci_hdrc_host_init(struct ci13xxx *ci)
rdrv->name = "host";
ci->roles[CI_ROLE_HOST] = rdrv;
+ ehci_init_driver(&ci_ehci_hc_driver, NULL);
+
return 0;
}
diff --git a/drivers/usb/chipidea/usbmisc_imx6q.c b/drivers/usb/chipidea/usbmisc_imx6q.c
index 416e3fc58fd0..845efe29e6b9 100644
--- a/drivers/usb/chipidea/usbmisc_imx6q.c
+++ b/drivers/usb/chipidea/usbmisc_imx6q.c
@@ -82,7 +82,7 @@ static const struct of_device_id usbmisc_imx6q_dt_ids[] = {
{ /* sentinel */ }
};
-static int __devinit usbmisc_imx6q_probe(struct platform_device *pdev)
+static int usbmisc_imx6q_probe(struct platform_device *pdev)
{
struct resource *res;
struct imx6q_usbmisc *data;
@@ -127,7 +127,7 @@ static int __devinit usbmisc_imx6q_probe(struct platform_device *pdev)
return 0;
}
-static int __devexit usbmisc_imx6q_remove(struct platform_device *pdev)
+static int usbmisc_imx6q_remove(struct platform_device *pdev)
{
usbmisc_unset_ops(&imx6q_usbmisc_ops);
clk_disable_unprepare(usbmisc->clk);
@@ -136,7 +136,7 @@ static int __devexit usbmisc_imx6q_remove(struct platform_device *pdev)
static struct platform_driver usbmisc_imx6q_driver = {
.probe = usbmisc_imx6q_probe,
- .remove = __devexit_p(usbmisc_imx6q_remove),
+ .remove = usbmisc_imx6q_remove,
.driver = {
.name = "usbmisc_imx6q",
.owner = THIS_MODULE,
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index 6e49ec6f3adc..8d809a811e16 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -787,6 +787,10 @@ static int get_serial_info(struct acm *acm, struct serial_struct __user *info)
tmp.flags = ASYNC_LOW_LATENCY;
tmp.xmit_fifo_size = acm->writesize;
tmp.baud_base = le32_to_cpu(acm->line.dwDTERate);
+ tmp.close_delay = acm->port.close_delay / 10;
+ tmp.closing_wait = acm->port.closing_wait == ASYNC_CLOSING_WAIT_NONE ?
+ ASYNC_CLOSING_WAIT_NONE :
+ acm->port.closing_wait / 10;
if (copy_to_user(info, &tmp, sizeof(tmp)))
return -EFAULT;
@@ -794,6 +798,37 @@ static int get_serial_info(struct acm *acm, struct serial_struct __user *info)
return 0;
}
+static int set_serial_info(struct acm *acm,
+ struct serial_struct __user *newinfo)
+{
+ struct serial_struct new_serial;
+ unsigned int closing_wait, close_delay;
+ int retval = 0;
+
+ if (copy_from_user(&new_serial, newinfo, sizeof(new_serial)))
+ return -EFAULT;
+
+ close_delay = new_serial.close_delay * 10;
+ closing_wait = new_serial.closing_wait == ASYNC_CLOSING_WAIT_NONE ?
+ ASYNC_CLOSING_WAIT_NONE : new_serial.closing_wait * 10;
+
+ mutex_lock(&acm->port.mutex);
+
+ if (!capable(CAP_SYS_ADMIN)) {
+ if ((close_delay != acm->port.close_delay) ||
+ (closing_wait != acm->port.closing_wait))
+ retval = -EPERM;
+ else
+ retval = -EOPNOTSUPP;
+ } else {
+ acm->port.close_delay = close_delay;
+ acm->port.closing_wait = closing_wait;
+ }
+
+ mutex_unlock(&acm->port.mutex);
+ return retval;
+}
+
static int acm_tty_ioctl(struct tty_struct *tty,
unsigned int cmd, unsigned long arg)
{
@@ -804,6 +839,9 @@ static int acm_tty_ioctl(struct tty_struct *tty,
case TIOCGSERIAL: /* gets serial port data */
rv = get_serial_info(acm, (struct serial_struct __user *) arg);
break;
+ case TIOCSSERIAL:
+ rv = set_serial_info(acm, (struct serial_struct __user *) arg);
+ break;
}
return rv;
diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c
index f460de31acee..cbacea933b18 100644
--- a/drivers/usb/core/devices.c
+++ b/drivers/usb/core/devices.c
@@ -591,16 +591,14 @@ static ssize_t usb_device_dump(char __user **buffer, size_t *nbytes,
/* Now look at all of this device's children. */
usb_hub_for_each_child(usbdev, chix, childdev) {
- if (childdev) {
- usb_lock_device(childdev);
- ret = usb_device_dump(buffer, nbytes, skip_bytes,
- file_offset, childdev, bus,
- level + 1, chix - 1, ++cnt);
- usb_unlock_device(childdev);
- if (ret == -EFAULT)
- return total_written;
- total_written += ret;
- }
+ usb_lock_device(childdev);
+ ret = usb_device_dump(buffer, nbytes, skip_bytes,
+ file_offset, childdev, bus,
+ level + 1, chix - 1, ++cnt);
+ usb_unlock_device(childdev);
+ if (ret == -EFAULT)
+ return total_written;
+ total_written += ret;
}
return total_written;
}
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index 6056db7af410..88dde95b6795 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -32,8 +32,6 @@
#include "usb.h"
-#ifdef CONFIG_HOTPLUG
-
/*
* Adds a new dynamic USBdevice ID to this driver,
* and cause the driver to probe for all devices again.
@@ -194,20 +192,6 @@ static void usb_free_dynids(struct usb_driver *usb_drv)
}
spin_unlock(&usb_drv->dynids.lock);
}
-#else
-static inline int usb_create_newid_files(struct usb_driver *usb_drv)
-{
- return 0;
-}
-
-static void usb_remove_newid_files(struct usb_driver *usb_drv)
-{
-}
-
-static inline void usb_free_dynids(struct usb_driver *usb_drv)
-{
-}
-#endif
static const struct usb_device_id *usb_match_dynamic_id(struct usb_interface *intf,
struct usb_driver *drv)
@@ -790,7 +774,6 @@ static int usb_device_match(struct device *dev, struct device_driver *drv)
return 0;
}
-#ifdef CONFIG_HOTPLUG
static int usb_uevent(struct device *dev, struct kobj_uevent_env *env)
{
struct usb_device *usb_dev;
@@ -832,14 +815,6 @@ static int usb_uevent(struct device *dev, struct kobj_uevent_env *env)
return 0;
}
-#else
-
-static int usb_uevent(struct device *dev, struct kobj_uevent_env *env)
-{
- return -ENODEV;
-}
-#endif /* CONFIG_HOTPLUG */
-
/**
* usb_register_device_driver - register a USB device (not interface) driver
* @new_udriver: USB operations for the device driver
diff --git a/drivers/usb/core/generic.c b/drivers/usb/core/generic.c
index 69ecd3c92311..eff2010eb63f 100644
--- a/drivers/usb/core/generic.c
+++ b/drivers/usb/core/generic.c
@@ -47,6 +47,9 @@ int usb_choose_configuration(struct usb_device *udev)
int insufficient_power = 0;
struct usb_host_config *c, *best;
+ if (usb_device_is_owned(udev))
+ return 0;
+
best = NULL;
c = udev->config;
num_configs = udev->descriptor.bNumConfigurations;
@@ -160,9 +163,7 @@ static int generic_probe(struct usb_device *udev)
/* Choose and set the configuration. This registers the interfaces
* with the driver core and lets interface drivers bind to them.
*/
- if (usb_device_is_owned(udev))
- ; /* Don't configure if the device is owned */
- else if (udev->authorized == 0)
+ if (udev->authorized == 0)
dev_err(&udev->dev, "Device is not authorized for usage\n");
else {
c = usb_choose_configuration(udev);
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 1e741bca0265..4225d5e72131 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -2039,8 +2039,9 @@ int hcd_bus_resume(struct usb_device *rhdev, pm_message_t msg)
status = hcd->driver->bus_resume(hcd);
clear_bit(HCD_FLAG_WAKEUP_PENDING, &hcd->flags);
if (status == 0) {
- /* TRSMRCY = 10 msec */
- msleep(10);
+ struct usb_device *udev;
+ int port1;
+
spin_lock_irq(&hcd_root_hub_lock);
if (!HCD_DEAD(hcd)) {
usb_set_device_state(rhdev, rhdev->actconfig
@@ -2050,6 +2051,20 @@ int hcd_bus_resume(struct usb_device *rhdev, pm_message_t msg)
hcd->state = HC_STATE_RUNNING;
}
spin_unlock_irq(&hcd_root_hub_lock);
+
+ /*
+ * Check whether any of the enabled ports on the root hub are
+ * unsuspended. If they are then a TRSMRCY delay is needed
+ * (this is what the USB-2 spec calls a "global resume").
+ * Otherwise we can skip the delay.
+ */
+ usb_hub_for_each_child(rhdev, port1, udev) {
+ if (udev->state != USB_STATE_NOTATTACHED &&
+ !udev->port_is_suspended) {
+ usleep_range(10000, 11000); /* TRSMRCY */
+ break;
+ }
+ }
} else {
hcd->state = old_state;
dev_dbg(&rhdev->dev, "bus %s fail, err %d\n",
@@ -2151,8 +2166,15 @@ EXPORT_SYMBOL_GPL(usb_bus_start_enum);
irqreturn_t usb_hcd_irq (int irq, void *__hcd)
{
struct usb_hcd *hcd = __hcd;
+ unsigned long flags;
irqreturn_t rc;
+ /* IRQF_DISABLED doesn't work correctly with shared IRQs
+ * when the first handler doesn't use it. So let's just
+ * assume it's never used.
+ */
+ local_irq_save(flags);
+
if (unlikely(HCD_DEAD(hcd) || !HCD_HW_ACCESSIBLE(hcd)))
rc = IRQ_NONE;
else if (hcd->driver->irq(hcd) == IRQ_NONE)
@@ -2160,6 +2182,7 @@ irqreturn_t usb_hcd_irq (int irq, void *__hcd)
else
rc = IRQ_HANDLED;
+ local_irq_restore(flags);
return rc;
}
EXPORT_SYMBOL_GPL(usb_hcd_irq);
@@ -2347,6 +2370,14 @@ static int usb_hcd_request_irqs(struct usb_hcd *hcd,
int retval;
if (hcd->driver->irq) {
+
+ /* IRQF_DISABLED doesn't work as advertised when used together
+ * with IRQF_SHARED. As usb_hcd_irq() will always disable
+ * interrupts we can remove it here.
+ */
+ if (irqflags & IRQF_SHARED)
+ irqflags &= ~IRQF_DISABLED;
+
snprintf(hcd->irq_descr, sizeof(hcd->irq_descr), "%s:usb%d",
hcd->driver->description, hcd->self.busnum);
retval = request_irq(irqnum, &usb_hcd_irq, irqflags,
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 1af04bdeaf0c..a815fd2cc5e7 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -39,6 +39,9 @@
#endif
#endif
+#define USB_VENDOR_GENESYS_LOGIC 0x05e3
+#define HUB_QUIRK_CHECK_PORT_AUTOSUSPEND 0x01
+
struct usb_port {
struct usb_device *child;
struct device dev;
@@ -86,6 +89,8 @@ struct usb_hub {
unsigned quiescing:1;
unsigned disconnected:1;
+ unsigned quirk_check_port_auto_suspend:1;
+
unsigned has_indicators:1;
u8 indicator[USB_MAXCHILDREN];
struct delayed_work leds;
@@ -736,7 +741,6 @@ static void hub_tt_work(struct work_struct *work)
struct usb_hub *hub =
container_of(work, struct usb_hub, tt.clear_work);
unsigned long flags;
- int limit = 100;
spin_lock_irqsave (&hub->tt.lock, flags);
while (!list_empty(&hub->tt.clear_list)) {
@@ -746,9 +750,6 @@ static void hub_tt_work(struct work_struct *work)
const struct hc_driver *drv;
int status;
- if (!hub->quiescing && --limit < 0)
- break;
-
next = hub->tt.clear_list.next;
clear = list_entry (next, struct usb_tt_clear, clear_list);
list_del (&clear->clear_list);
@@ -1612,6 +1613,41 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id)
desc = intf->cur_altsetting;
hdev = interface_to_usbdev(intf);
+ /*
+ * Set default autosuspend delay as 0 to speedup bus suspend,
+ * based on the below considerations:
+ *
+ * - Unlike other drivers, the hub driver does not rely on the
+ * autosuspend delay to provide enough time to handle a wakeup
+ * event, and the submitted status URB is just to check future
+ * change on hub downstream ports, so it is safe to do it.
+ *
+ * - The patch might cause one or more auto supend/resume for
+ * below very rare devices when they are plugged into hub
+ * first time:
+ *
+ * devices having trouble initializing, and disconnect
+ * themselves from the bus and then reconnect a second
+ * or so later
+ *
+ * devices just for downloading firmware, and disconnects
+ * themselves after completing it
+ *
+ * For these quite rare devices, their drivers may change the
+ * autosuspend delay of their parent hub in the probe() to one
+ * appropriate value to avoid the subtle problem if someone
+ * does care it.
+ *
+ * - The patch may cause one or more auto suspend/resume on
+ * hub during running 'lsusb', but it is probably too
+ * infrequent to worry about.
+ *
+ * - Change autosuspend delay of hub can avoid unnecessary auto
+ * suspend timer for hub, also may decrease power consumption
+ * of USB bus.
+ */
+ pm_runtime_set_autosuspend_delay(&hdev->dev, 0);
+
/* Hubs have proper suspend/resume support. */
usb_enable_autosuspend(hdev);
@@ -1670,6 +1706,9 @@ descriptor_error:
if (hdev->speed == USB_SPEED_HIGH)
highspeed_hubs++;
+ if (id->driver_info & HUB_QUIRK_CHECK_PORT_AUTOSUSPEND)
+ hub->quirk_check_port_auto_suspend = 1;
+
if (hub_configure(hub, endpoint) >= 0)
return 0;
@@ -2012,7 +2051,7 @@ static void show_string(struct usb_device *udev, char *id, char *string)
{
if (!string)
return;
- dev_printk(KERN_INFO, &udev->dev, "%s: %s\n", id, string);
+ dev_info(&udev->dev, "%s: %s\n", id, string);
}
static void announce_device(struct usb_device *udev)
@@ -2879,6 +2918,7 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
(PMSG_IS_AUTO(msg) ? "auto-" : ""),
udev->do_remote_wakeup);
usb_set_device_state(udev, USB_STATE_SUSPENDED);
+ udev->port_is_suspended = 1;
msleep(10);
}
usb_mark_last_busy(hub->hdev);
@@ -3043,6 +3083,7 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg)
SuspendCleared:
if (status == 0) {
+ udev->port_is_suspended = 0;
if (hub_is_superspeed(hub->hdev)) {
if (portchange & USB_PORT_STAT_C_LINK_STATE)
clear_port_feature(hub->hdev, port1,
@@ -3126,6 +3167,21 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg)
#endif
+static int check_ports_changed(struct usb_hub *hub)
+{
+ int port1;
+
+ for (port1 = 1; port1 <= hub->hdev->maxchild; ++port1) {
+ u16 portstatus, portchange;
+ int status;
+
+ status = hub_port_status(hub, port1, &portstatus, &portchange);
+ if (!status && portchange)
+ return 1;
+ }
+ return 0;
+}
+
static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
{
struct usb_hub *hub = usb_get_intfdata (intf);
@@ -3144,6 +3200,16 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
return -EBUSY;
}
}
+
+ if (hdev->do_remote_wakeup && hub->quirk_check_port_auto_suspend) {
+ /* check if there are changes pending on hub ports */
+ if (check_ports_changed(hub)) {
+ if (PMSG_IS_AUTO(msg))
+ return -EBUSY;
+ pm_wakeup_event(&hdev->dev, 2000);
+ }
+ }
+
if (hub_is_superspeed(hdev) && hdev->do_remote_wakeup) {
/* Enable hub to send remote wakeup for all ports. */
for (port1 = 1; port1 <= hdev->maxchild; port1++) {
@@ -3972,6 +4038,9 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
if (retval)
goto fail;
+ if (hcd->phy && !hdev->parent)
+ usb_phy_notify_connect(hcd->phy, udev->speed);
+
/*
* Some superspeed devices have finished the link training process
* and attached to a superspeed hub port, but the device descriptor
@@ -4166,8 +4235,12 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
}
/* Disconnect any existing devices under this port */
- if (udev)
+ if (udev) {
+ if (hcd->phy && !hdev->parent &&
+ !(portstatus & USB_PORT_STAT_CONNECTION))
+ usb_phy_notify_disconnect(hcd->phy, udev->speed);
usb_disconnect(&hub->ports[port1 - 1]->child);
+ }
clear_bit(port1, hub->change_bits);
/* We can forget about a "removed" device when there's a physical
@@ -4190,13 +4263,6 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
}
}
- if (hcd->phy && !hdev->parent) {
- if (portstatus & USB_PORT_STAT_CONNECTION)
- usb_phy_notify_connect(hcd->phy, port1);
- else
- usb_phy_notify_disconnect(hcd->phy, port1);
- }
-
/* Return now if debouncing failed or nothing is connected or
* the device was "removed".
*/
@@ -4648,6 +4714,11 @@ static int hub_thread(void *__unused)
}
static const struct usb_device_id hub_id_table[] = {
+ { .match_flags = USB_DEVICE_ID_MATCH_VENDOR
+ | USB_DEVICE_ID_MATCH_INT_CLASS,
+ .idVendor = USB_VENDOR_GENESYS_LOGIC,
+ .bInterfaceClass = USB_CLASS_HUB,
+ .driver_info = HUB_QUIRK_CHECK_PORT_AUTOSUSPEND},
{ .match_flags = USB_DEVICE_ID_MATCH_DEV_CLASS,
.bDeviceClass = USB_CLASS_HUB},
{ .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS,
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index 1ed5afd91e6d..131f73649b60 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -1540,7 +1540,6 @@ static void usb_release_interface(struct device *dev)
kfree(intf);
}
-#ifdef CONFIG_HOTPLUG
static int usb_if_uevent(struct device *dev, struct kobj_uevent_env *env)
{
struct usb_device *usb_dev;
@@ -1575,14 +1574,6 @@ static int usb_if_uevent(struct device *dev, struct kobj_uevent_env *env)
return 0;
}
-#else
-
-static int usb_if_uevent(struct device *dev, struct kobj_uevent_env *env)
-{
- return -ENODEV;
-}
-#endif /* CONFIG_HOTPLUG */
-
struct device_type usb_if_device_type = {
.name = "usb_interface",
.release = usb_release_interface,
@@ -1795,7 +1786,8 @@ free_interfaces:
if (dev->actconfig && usb_disable_lpm(dev)) {
dev_err(&dev->dev, "%s Failed to disable LPM\n.", __func__);
mutex_unlock(hcd->bandwidth_mutex);
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto free_interfaces;
}
ret = usb_hcd_alloc_bandwidth(dev, cp, NULL, NULL);
if (ret < 0) {
@@ -1806,29 +1798,8 @@ free_interfaces:
goto free_interfaces;
}
- ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
- USB_REQ_SET_CONFIGURATION, 0, configuration, 0,
- NULL, 0, USB_CTRL_SET_TIMEOUT);
- if (ret < 0) {
- /* All the old state is gone, so what else can we do?
- * The device is probably useless now anyway.
- */
- cp = NULL;
- }
-
- dev->actconfig = cp;
- if (!cp) {
- usb_set_device_state(dev, USB_STATE_ADDRESS);
- usb_hcd_alloc_bandwidth(dev, NULL, NULL, NULL);
- /* Leave LPM disabled while the device is unconfigured. */
- mutex_unlock(hcd->bandwidth_mutex);
- usb_autosuspend_device(dev);
- goto free_interfaces;
- }
- mutex_unlock(hcd->bandwidth_mutex);
- usb_set_device_state(dev, USB_STATE_CONFIGURED);
-
- /* Initialize the new interface structures and the
+ /*
+ * Initialize the new interface structures and the
* hc/hcd/usbcore interface/endpoint state.
*/
for (i = 0; i < nintf; ++i) {
@@ -1872,6 +1843,35 @@ free_interfaces:
}
kfree(new_interfaces);
+ ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+ USB_REQ_SET_CONFIGURATION, 0, configuration, 0,
+ NULL, 0, USB_CTRL_SET_TIMEOUT);
+ if (ret < 0 && cp) {
+ /*
+ * All the old state is gone, so what else can we do?
+ * The device is probably useless now anyway.
+ */
+ usb_hcd_alloc_bandwidth(dev, NULL, NULL, NULL);
+ for (i = 0; i < nintf; ++i) {
+ usb_disable_interface(dev, cp->interface[i], true);
+ put_device(&cp->interface[i]->dev);
+ cp->interface[i] = NULL;
+ }
+ cp = NULL;
+ }
+
+ dev->actconfig = cp;
+ mutex_unlock(hcd->bandwidth_mutex);
+
+ if (!cp) {
+ usb_set_device_state(dev, USB_STATE_ADDRESS);
+
+ /* Leave LPM disabled while the device is unconfigured. */
+ usb_autosuspend_device(dev);
+ return ret;
+ }
+ usb_set_device_state(dev, USB_STATE_CONFIGURED);
+
if (cp->string == NULL &&
!(dev->quirks & USB_QUIRK_CONFIG_INTF_STRINGS))
cp->string = usb_cache_string(dev, cp->desc.iConfiguration);
diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
index 9d912bfdcffe..e0d9d948218c 100644
--- a/drivers/usb/core/urb.c
+++ b/drivers/usb/core/urb.c
@@ -214,9 +214,25 @@ EXPORT_SYMBOL_GPL(usb_unanchor_urb);
* urb->interval is modified to reflect the actual transfer period used
* (normally some power of two units). And for isochronous urbs,
* urb->start_frame is modified to reflect when the URB's transfers were
- * scheduled to start. Not all isochronous transfer scheduling policies
- * will work, but most host controller drivers should easily handle ISO
- * queues going from now until 10-200 msec into the future.
+ * scheduled to start.
+ *
+ * Not all isochronous transfer scheduling policies will work, but most
+ * host controller drivers should easily handle ISO queues going from now
+ * until 10-200 msec into the future. Drivers should try to keep at
+ * least one or two msec of data in the queue; many controllers require
+ * that new transfers start at least 1 msec in the future when they are
+ * added. If the driver is unable to keep up and the queue empties out,
+ * the behavior for new submissions is governed by the URB_ISO_ASAP flag.
+ * If the flag is set, or if the queue is idle, then the URB is always
+ * assigned to the first available (and not yet expired) slot in the
+ * endpoint's schedule. If the flag is not set and the queue is active
+ * then the URB is always assigned to the next slot in the schedule
+ * following the end of the endpoint's previous URB, even if that slot is
+ * in the past. When a packet is assigned in this way to a slot that has
+ * already expired, the packet is not transmitted and the corresponding
+ * usb_iso_packet_descriptor's status field will return -EXDEV. If this
+ * would happen to all the packets in the URB, submission fails with a
+ * -EXDEV error code.
*
* For control endpoints, the synchronous usb_control_msg() call is
* often used (in non-interrupt context) instead of this call.
@@ -305,8 +321,13 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
struct usb_host_endpoint *ep;
int is_out;
- if (!urb || urb->hcpriv || !urb->complete)
+ if (!urb || !urb->complete)
return -EINVAL;
+ if (urb->hcpriv) {
+ WARN_ONCE(1, "URB %p submitted while active\n", urb);
+ return -EBUSY;
+ }
+
dev = urb->dev;
if ((!dev) || (dev->state < USB_STATE_UNAUTHENTICATED))
return -ENODEV;
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index cd8fb44a3e16..f81b92572735 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -233,7 +233,6 @@ static void usb_release_dev(struct device *dev)
kfree(udev);
}
-#ifdef CONFIG_HOTPLUG
static int usb_dev_uevent(struct device *dev, struct kobj_uevent_env *env)
{
struct usb_device *usb_dev;
@@ -249,14 +248,6 @@ static int usb_dev_uevent(struct device *dev, struct kobj_uevent_env *env)
return 0;
}
-#else
-
-static int usb_dev_uevent(struct device *dev, struct kobj_uevent_env *env)
-{
- return -ENODEV;
-}
-#endif /* CONFIG_HOTPLUG */
-
#ifdef CONFIG_PM
/* USB device Power-Management thunks.
@@ -370,14 +361,14 @@ struct usb_device *usb_alloc_dev(struct usb_device *parent,
struct usb_bus *bus, unsigned port1)
{
struct usb_device *dev;
- struct usb_hcd *usb_hcd = container_of(bus, struct usb_hcd, self);
+ struct usb_hcd *usb_hcd = bus_to_hcd(bus);
unsigned root_hub = 0;
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (!dev)
return NULL;
- if (!usb_get_hcd(bus_to_hcd(bus))) {
+ if (!usb_get_hcd(usb_hcd)) {
kfree(dev);
return NULL;
}
diff --git a/drivers/usb/dwc3/Makefile b/drivers/usb/dwc3/Makefile
index d441fe4c180b..4502648b8171 100644
--- a/drivers/usb/dwc3/Makefile
+++ b/drivers/usb/dwc3/Makefile
@@ -27,19 +27,7 @@ endif
##
obj-$(CONFIG_USB_DWC3) += dwc3-omap.o
-
-##
-# REVISIT Samsung Exynos platform needs the clk API which isn't
-# defined on all architectures. If we allow dwc3-exynos.c compile
-# always we will fail the linking phase on those architectures
-# which don't provide clk api implementation and that's unnaceptable.
-#
-# When Samsung's platform start supporting pm_runtime, this check
-# for HAVE_CLK should be removed.
-##
-ifneq ($(CONFIG_HAVE_CLK),)
- obj-$(CONFIG_USB_DWC3) += dwc3-exynos.o
-endif
+obj-$(CONFIG_USB_DWC3) += dwc3-exynos.o
ifneq ($(CONFIG_PCI),)
obj-$(CONFIG_USB_DWC3) += dwc3-pci.o
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index c14ebc975ba4..3a4004a620ad 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -66,45 +66,6 @@ MODULE_PARM_DESC(maximum_speed, "Maximum supported speed.");
/* -------------------------------------------------------------------------- */
-#define DWC3_DEVS_POSSIBLE 32
-
-static DECLARE_BITMAP(dwc3_devs, DWC3_DEVS_POSSIBLE);
-
-int dwc3_get_device_id(void)
-{
- int id;
-
-again:
- id = find_first_zero_bit(dwc3_devs, DWC3_DEVS_POSSIBLE);
- if (id < DWC3_DEVS_POSSIBLE) {
- int old;
-
- old = test_and_set_bit(id, dwc3_devs);
- if (old)
- goto again;
- } else {
- pr_err("dwc3: no space for new device\n");
- id = -ENOMEM;
- }
-
- return id;
-}
-EXPORT_SYMBOL_GPL(dwc3_get_device_id);
-
-void dwc3_put_device_id(int id)
-{
- int ret;
-
- if (id < 0)
- return;
-
- ret = test_bit(id, dwc3_devs);
- WARN(!ret, "dwc3: ID %d not in use\n", id);
- smp_mb__before_clear_bit();
- clear_bit(id, dwc3_devs);
-}
-EXPORT_SYMBOL_GPL(dwc3_put_device_id);
-
void dwc3_set_mode(struct dwc3 *dwc, u32 mode)
{
u32 reg;
@@ -169,7 +130,6 @@ static void dwc3_free_one_event_buffer(struct dwc3 *dwc,
struct dwc3_event_buffer *evt)
{
dma_free_coherent(dwc->dev, evt->length, evt->buf, evt->dma);
- kfree(evt);
}
/**
@@ -180,12 +140,11 @@ 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 *__devinit
-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;
- evt = kzalloc(sizeof(*evt), GFP_KERNEL);
+ evt = devm_kzalloc(dwc->dev, sizeof(*evt), GFP_KERNEL);
if (!evt)
return ERR_PTR(-ENOMEM);
@@ -193,10 +152,8 @@ dwc3_alloc_one_event_buffer(struct dwc3 *dwc, unsigned length)
evt->length = length;
evt->buf = dma_alloc_coherent(dwc->dev, length,
&evt->dma, GFP_KERNEL);
- if (!evt->buf) {
- kfree(evt);
+ if (!evt->buf)
return ERR_PTR(-ENOMEM);
- }
return evt;
}
@@ -215,8 +172,6 @@ static void dwc3_free_event_buffers(struct dwc3 *dwc)
if (evt)
dwc3_free_one_event_buffer(dwc, evt);
}
-
- kfree(dwc->ev_buffs);
}
/**
@@ -227,7 +182,7 @@ static void dwc3_free_event_buffers(struct dwc3 *dwc)
* Returns 0 on success otherwise negative errno. In the error case, dwc
* may contain some buffers allocated but not all which were requested.
*/
-static int __devinit dwc3_alloc_event_buffers(struct dwc3 *dwc, unsigned length)
+static int dwc3_alloc_event_buffers(struct dwc3 *dwc, unsigned length)
{
int num;
int i;
@@ -235,7 +190,8 @@ static int __devinit dwc3_alloc_event_buffers(struct dwc3 *dwc, unsigned length)
num = DWC3_NUM_INT(dwc->hwparams.hwparams1);
dwc->num_event_buffers = num;
- dwc->ev_buffs = kzalloc(sizeof(*dwc->ev_buffs) * num, GFP_KERNEL);
+ dwc->ev_buffs = devm_kzalloc(dwc->dev, sizeof(*dwc->ev_buffs) * num,
+ GFP_KERNEL);
if (!dwc->ev_buffs) {
dev_err(dwc->dev, "can't allocate event buffers array\n");
return -ENOMEM;
@@ -303,7 +259,7 @@ static void dwc3_event_buffers_cleanup(struct dwc3 *dwc)
}
}
-static void __devinit dwc3_cache_hwparams(struct dwc3 *dwc)
+static void dwc3_cache_hwparams(struct dwc3 *dwc)
{
struct dwc3_hwparams *parms = &dwc->hwparams;
@@ -324,7 +280,7 @@ static void __devinit dwc3_cache_hwparams(struct dwc3 *dwc)
*
* Returns 0 on success otherwise negative errno.
*/
-static int __devinit dwc3_core_init(struct dwc3 *dwc)
+static int dwc3_core_init(struct dwc3 *dwc)
{
unsigned long timeout;
u32 reg;
@@ -358,8 +314,6 @@ static int __devinit dwc3_core_init(struct dwc3 *dwc)
dwc3_core_soft_reset(dwc);
- dwc3_cache_hwparams(dwc);
-
reg = dwc3_readl(dwc->regs, DWC3_GCTL);
reg &= ~DWC3_GCTL_SCALEDOWN_MASK;
reg &= ~DWC3_GCTL_DISSCRAMBLE;
@@ -383,24 +337,14 @@ static int __devinit dwc3_core_init(struct dwc3 *dwc)
dwc3_writel(dwc->regs, DWC3_GCTL, reg);
- ret = dwc3_alloc_event_buffers(dwc, DWC3_EVENT_BUFFERS_SIZE);
- if (ret) {
- dev_err(dwc->dev, "failed to allocate event buffers\n");
- ret = -ENOMEM;
- goto err1;
- }
-
ret = dwc3_event_buffers_setup(dwc);
if (ret) {
dev_err(dwc->dev, "failed to setup event buffers\n");
- goto err1;
+ goto err0;
}
return 0;
-err1:
- dwc3_free_event_buffers(dwc);
-
err0:
return ret;
}
@@ -408,16 +352,14 @@ err0:
static void dwc3_core_exit(struct dwc3 *dwc)
{
dwc3_event_buffers_cleanup(dwc);
- dwc3_free_event_buffers(dwc);
usb_phy_shutdown(dwc->usb2_phy);
usb_phy_shutdown(dwc->usb3_phy);
-
}
#define DWC3_ALIGN_MASK (16 - 1)
-static int __devinit dwc3_probe(struct platform_device *pdev)
+static int dwc3_probe(struct platform_device *pdev)
{
struct device_node *node = pdev->dev.of_node;
struct resource *res;
@@ -515,10 +457,19 @@ static int __devinit dwc3_probe(struct platform_device *pdev)
pm_runtime_get_sync(dev);
pm_runtime_forbid(dev);
+ dwc3_cache_hwparams(dwc);
+
+ ret = dwc3_alloc_event_buffers(dwc, DWC3_EVENT_BUFFERS_SIZE);
+ if (ret) {
+ dev_err(dwc->dev, "failed to allocate event buffers\n");
+ ret = -ENOMEM;
+ goto err0;
+ }
+
ret = dwc3_core_init(dwc);
if (ret) {
dev_err(dev, "failed to initialize core\n");
- return ret;
+ goto err0;
}
mode = DWC3_MODE(dwc->hwparams.hwparams0);
@@ -590,10 +541,13 @@ err2:
err1:
dwc3_core_exit(dwc);
+err0:
+ dwc3_free_event_buffers(dwc);
+
return ret;
}
-static int __devexit dwc3_remove(struct platform_device *pdev)
+static int dwc3_remove(struct platform_device *pdev)
{
struct dwc3 *dwc = platform_get_drvdata(pdev);
struct resource *res;
@@ -628,7 +582,7 @@ static int __devexit dwc3_remove(struct platform_device *pdev)
static struct platform_driver dwc3_driver = {
.probe = dwc3_probe,
- .remove = __devexit_p(dwc3_remove),
+ .remove = dwc3_remove,
.driver = {
.name = "dwc3",
},
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index 243affc93431..499956344262 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -868,7 +868,4 @@ void dwc3_host_exit(struct dwc3 *dwc);
int dwc3_gadget_init(struct dwc3 *dwc);
void dwc3_gadget_exit(struct dwc3 *dwc);
-extern int dwc3_get_device_id(void);
-extern void dwc3_put_device_id(int id);
-
#endif /* __DRIVERS_USB_DWC3_CORE_H */
diff --git a/drivers/usb/dwc3/debugfs.c b/drivers/usb/dwc3/debugfs.c
index d4a30f118724..92604b4f9712 100644
--- a/drivers/usb/dwc3/debugfs.c
+++ b/drivers/usb/dwc3/debugfs.c
@@ -652,7 +652,7 @@ static const struct file_operations dwc3_link_state_fops = {
.release = single_release,
};
-int __devinit dwc3_debugfs_init(struct dwc3 *dwc)
+int dwc3_debugfs_init(struct dwc3 *dwc)
{
struct dentry *root;
struct dentry *file;
@@ -703,7 +703,7 @@ err0:
return ret;
}
-void __devexit dwc3_debugfs_exit(struct dwc3 *dwc)
+void dwc3_debugfs_exit(struct dwc3 *dwc)
{
debugfs_remove_recursive(dwc->root);
dwc->root = NULL;
diff --git a/drivers/usb/dwc3/dwc3-exynos.c b/drivers/usb/dwc3/dwc3-exynos.c
index ca6597853f90..aae5328ac771 100644
--- a/drivers/usb/dwc3/dwc3-exynos.c
+++ b/drivers/usb/dwc3/dwc3-exynos.c
@@ -21,6 +21,7 @@
#include <linux/clk.h>
#include <linux/usb/otg.h>
#include <linux/usb/nop-usb-xceiv.h>
+#include <linux/of.h>
#include "core.h"
@@ -33,7 +34,7 @@ struct dwc3_exynos {
struct clk *clk;
};
-static int __devinit dwc3_exynos_register_phys(struct dwc3_exynos *exynos)
+static int dwc3_exynos_register_phys(struct dwc3_exynos *exynos)
{
struct nop_usb_xceiv_platform_data pdata;
struct platform_device *pdev;
@@ -87,14 +88,14 @@ err1:
return ret;
}
-static int __devinit dwc3_exynos_probe(struct platform_device *pdev)
+static u64 dwc3_exynos_dma_mask = DMA_BIT_MASK(32);
+
+static int dwc3_exynos_probe(struct platform_device *pdev)
{
- struct dwc3_exynos_data *pdata = pdev->dev.platform_data;
struct platform_device *dwc3;
struct dwc3_exynos *exynos;
struct clk *clk;
- int devid;
int ret = -ENOMEM;
exynos = kzalloc(sizeof(*exynos), GFP_KERNEL);
@@ -103,11 +104,15 @@ static int __devinit dwc3_exynos_probe(struct platform_device *pdev)
goto err0;
}
- platform_set_drvdata(pdev, exynos);
+ /*
+ * Right now device-tree probed devices don't get dma_mask set.
+ * Since shared usb code relies on it, set it here for now.
+ * Once we move to full device tree support this will vanish off.
+ */
+ if (!pdev->dev.dma_mask)
+ pdev->dev.dma_mask = &dwc3_exynos_dma_mask;
- devid = dwc3_get_device_id();
- if (devid < 0)
- goto err1;
+ platform_set_drvdata(pdev, exynos);
ret = dwc3_exynos_register_phys(exynos);
if (ret) {
@@ -115,10 +120,10 @@ static int __devinit dwc3_exynos_probe(struct platform_device *pdev)
goto err1;
}
- dwc3 = platform_device_alloc("dwc3", devid);
+ dwc3 = platform_device_alloc("dwc3", PLATFORM_DEVID_AUTO);
if (!dwc3) {
dev_err(&pdev->dev, "couldn't allocate dwc3 device\n");
- goto err2;
+ goto err1;
}
clk = clk_get(&pdev->dev, "usbdrd30");
@@ -139,14 +144,6 @@ static int __devinit dwc3_exynos_probe(struct platform_device *pdev)
clk_enable(exynos->clk);
- /* PHY initialization */
- if (!pdata) {
- dev_dbg(&pdev->dev, "missing platform data\n");
- } else {
- if (pdata->phy_init)
- pdata->phy_init(pdev, pdata->phy_type);
- }
-
ret = platform_device_add_resources(dwc3, pdev->resource,
pdev->num_resources);
if (ret) {
@@ -163,35 +160,24 @@ static int __devinit dwc3_exynos_probe(struct platform_device *pdev)
return 0;
err4:
- if (pdata && pdata->phy_exit)
- pdata->phy_exit(pdev, pdata->phy_type);
-
clk_disable(clk);
clk_put(clk);
err3:
platform_device_put(dwc3);
-err2:
- dwc3_put_device_id(devid);
err1:
kfree(exynos);
err0:
return ret;
}
-static int __devexit dwc3_exynos_remove(struct platform_device *pdev)
+static int dwc3_exynos_remove(struct platform_device *pdev)
{
struct dwc3_exynos *exynos = platform_get_drvdata(pdev);
- struct dwc3_exynos_data *pdata = pdev->dev.platform_data;
platform_device_unregister(exynos->dwc3);
platform_device_unregister(exynos->usb2_phy);
platform_device_unregister(exynos->usb3_phy);
- dwc3_put_device_id(exynos->dwc3->id);
-
- if (pdata && pdata->phy_exit)
- pdata->phy_exit(pdev, pdata->phy_type);
-
clk_disable(exynos->clk);
clk_put(exynos->clk);
@@ -200,11 +186,20 @@ static int __devexit dwc3_exynos_remove(struct platform_device *pdev)
return 0;
}
+#ifdef CONFIG_OF
+static const struct of_device_id exynos_dwc3_match[] = {
+ { .compatible = "samsung,exynos-dwc3" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, exynos_dwc3_match);
+#endif
+
static struct platform_driver dwc3_exynos_driver = {
.probe = dwc3_exynos_probe,
- .remove = __devexit_p(dwc3_exynos_remove),
+ .remove = dwc3_exynos_remove,
.driver = {
.name = "exynos-dwc3",
+ .of_match_table = of_match_ptr(exynos_dwc3_match),
},
};
diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c
index ee57a10d90d0..f31867fd2574 100644
--- a/drivers/usb/dwc3/dwc3-omap.c
+++ b/drivers/usb/dwc3/dwc3-omap.c
@@ -157,7 +157,7 @@ static inline void dwc3_omap_writel(void __iomem *base, u32 offset, u32 value)
writel(value, base + offset);
}
-static int __devinit dwc3_omap_register_phys(struct dwc3_omap *omap)
+static int dwc3_omap_register_phys(struct dwc3_omap *omap)
{
struct nop_usb_xceiv_platform_data pdata;
struct platform_device *pdev;
@@ -262,7 +262,7 @@ static irqreturn_t dwc3_omap_interrupt(int irq, void *_omap)
return IRQ_HANDLED;
}
-static int __devinit dwc3_omap_probe(struct platform_device *pdev)
+static int dwc3_omap_probe(struct platform_device *pdev)
{
struct dwc3_omap_data *pdata = pdev->dev.platform_data;
struct device_node *node = pdev->dev.of_node;
@@ -272,7 +272,6 @@ static int __devinit dwc3_omap_probe(struct platform_device *pdev)
struct resource *res;
struct device *dev = &pdev->dev;
- int devid;
int size;
int ret = -ENOMEM;
int irq;
@@ -315,14 +314,10 @@ static int __devinit dwc3_omap_probe(struct platform_device *pdev)
return ret;
}
- devid = dwc3_get_device_id();
- if (devid < 0)
- return -ENODEV;
-
- dwc3 = platform_device_alloc("dwc3", devid);
+ dwc3 = platform_device_alloc("dwc3", PLATFORM_DEVID_AUTO);
if (!dwc3) {
dev_err(dev, "couldn't allocate dwc3 device\n");
- goto err1;
+ return -ENOMEM;
}
context = devm_kzalloc(dev, resource_size(res), GFP_KERNEL);
@@ -423,23 +418,16 @@ static int __devinit dwc3_omap_probe(struct platform_device *pdev)
err2:
platform_device_put(dwc3);
-
-err1:
- dwc3_put_device_id(devid);
-
return ret;
}
-static int __devexit dwc3_omap_remove(struct platform_device *pdev)
+static int dwc3_omap_remove(struct platform_device *pdev)
{
struct dwc3_omap *omap = platform_get_drvdata(pdev);
platform_device_unregister(omap->dwc3);
platform_device_unregister(omap->usb2_phy);
platform_device_unregister(omap->usb3_phy);
-
- dwc3_put_device_id(omap->dwc3->id);
-
return 0;
}
@@ -453,7 +441,7 @@ MODULE_DEVICE_TABLE(of, of_dwc3_matach);
static struct platform_driver dwc3_omap_driver = {
.probe = dwc3_omap_probe,
- .remove = __devexit_p(dwc3_omap_remove),
+ .remove = dwc3_omap_remove,
.driver = {
.name = "omap-dwc3",
.of_match_table = of_dwc3_matach,
diff --git a/drivers/usb/dwc3/dwc3-pci.c b/drivers/usb/dwc3/dwc3-pci.c
index 94f550e37f98..7d70f44567d2 100644
--- a/drivers/usb/dwc3/dwc3-pci.c
+++ b/drivers/usb/dwc3/dwc3-pci.c
@@ -58,7 +58,7 @@ struct dwc3_pci {
struct platform_device *usb3_phy;
};
-static int __devinit dwc3_pci_register_phys(struct dwc3_pci *glue)
+static int dwc3_pci_register_phys(struct dwc3_pci *glue)
{
struct nop_usb_xceiv_platform_data pdata;
struct platform_device *pdev;
@@ -112,14 +112,13 @@ err1:
return ret;
}
-static int __devinit dwc3_pci_probe(struct pci_dev *pci,
+static int dwc3_pci_probe(struct pci_dev *pci,
const struct pci_device_id *id)
{
struct resource res[2];
struct platform_device *dwc3;
struct dwc3_pci *glue;
int ret = -ENOMEM;
- int devid;
struct device *dev = &pci->dev;
glue = devm_kzalloc(dev, sizeof(*glue), GFP_KERNEL);
@@ -145,13 +144,7 @@ static int __devinit dwc3_pci_probe(struct pci_dev *pci,
return ret;
}
- devid = dwc3_get_device_id();
- if (devid < 0) {
- ret = -ENOMEM;
- goto err1;
- }
-
- dwc3 = platform_device_alloc("dwc3", devid);
+ dwc3 = platform_device_alloc("dwc3", PLATFORM_DEVID_AUTO);
if (!dwc3) {
dev_err(dev, "couldn't allocate dwc3 device\n");
ret = -ENOMEM;
@@ -172,7 +165,7 @@ static int __devinit dwc3_pci_probe(struct pci_dev *pci,
ret = platform_device_add_resources(dwc3, res, ARRAY_SIZE(res));
if (ret) {
dev_err(dev, "couldn't add resources to dwc3 device\n");
- goto err2;
+ goto err1;
}
pci_set_drvdata(pci, glue);
@@ -195,23 +188,18 @@ static int __devinit dwc3_pci_probe(struct pci_dev *pci,
err3:
pci_set_drvdata(pci, NULL);
platform_device_put(dwc3);
-
-err2:
- dwc3_put_device_id(devid);
-
err1:
pci_disable_device(pci);
return ret;
}
-static void __devexit dwc3_pci_remove(struct pci_dev *pci)
+static void dwc3_pci_remove(struct pci_dev *pci)
{
struct dwc3_pci *glue = pci_get_drvdata(pci);
platform_device_unregister(glue->usb2_phy);
platform_device_unregister(glue->usb3_phy);
- dwc3_put_device_id(glue->dwc3->id);
platform_device_unregister(glue->dwc3);
pci_set_drvdata(pci, NULL);
pci_disable_device(pci);
@@ -230,7 +218,7 @@ static struct pci_driver dwc3_pci_driver = {
.name = "dwc3-pci",
.id_table = dwc3_pci_id_table,
.probe = dwc3_pci_probe,
- .remove = __devexit_p(dwc3_pci_remove),
+ .remove = dwc3_pci_remove,
};
MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>");
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 7b7deddf6a52..2e43b332aae8 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -1579,7 +1579,7 @@ static const struct usb_gadget_ops dwc3_gadget_ops = {
/* -------------------------------------------------------------------------- */
-static int __devinit dwc3_gadget_init_endpoints(struct dwc3 *dwc)
+static int dwc3_gadget_init_endpoints(struct dwc3 *dwc)
{
struct dwc3_ep *dep;
u8 epnum;
@@ -2374,7 +2374,7 @@ static irqreturn_t dwc3_interrupt(int irq, void *_dwc)
*
* Returns 0 on success otherwise negative errno.
*/
-int __devinit dwc3_gadget_init(struct dwc3 *dwc)
+int dwc3_gadget_init(struct dwc3 *dwc)
{
u32 reg;
int ret;
diff --git a/drivers/usb/early/ehci-dbgp.c b/drivers/usb/early/ehci-dbgp.c
index e426ad626d74..5e29ddeb4d33 100644
--- a/drivers/usb/early/ehci-dbgp.c
+++ b/drivers/usb/early/ehci-dbgp.c
@@ -20,6 +20,7 @@
#include <linux/usb/ehci_def.h>
#include <linux/delay.h>
#include <linux/serial_core.h>
+#include <linux/kconfig.h>
#include <linux/kgdb.h>
#include <linux/kthread.h>
#include <asm/io.h>
@@ -614,12 +615,6 @@ err:
return -ENODEV;
}
-int dbgp_external_startup(struct usb_hcd *hcd)
-{
- return xen_dbgp_external_startup(hcd) ?: _dbgp_external_startup();
-}
-EXPORT_SYMBOL_GPL(dbgp_external_startup);
-
static int ehci_reset_port(int port)
{
u32 portsc;
@@ -979,6 +974,7 @@ struct console early_dbgp_console = {
.index = -1,
};
+#if IS_ENABLED(CONFIG_USB)
int dbgp_reset_prep(struct usb_hcd *hcd)
{
int ret = xen_dbgp_reset_prep(hcd);
@@ -1007,6 +1003,13 @@ int dbgp_reset_prep(struct usb_hcd *hcd)
}
EXPORT_SYMBOL_GPL(dbgp_reset_prep);
+int dbgp_external_startup(struct usb_hcd *hcd)
+{
+ return xen_dbgp_external_startup(hcd) ?: _dbgp_external_startup();
+}
+EXPORT_SYMBOL_GPL(dbgp_external_startup);
+#endif /* USB */
+
#ifdef CONFIG_KGDB
static char kgdbdbgp_buf[DBGP_MAX_PACKET];
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index e0ff51b89529..14625fd2cecd 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -721,31 +721,6 @@ config USB_FUNCTIONFS_GENERIC
Include a configuration with the Function Filesystem alone with
no Ethernet interface.
-config USB_FILE_STORAGE
- tristate "File-backed Storage Gadget (DEPRECATED)"
- depends on BLOCK
- help
- The File-backed Storage Gadget acts as a USB Mass Storage
- disk drive. As its storage repository it can use a regular
- file or a block device (in much the same way as the "loop"
- device driver), specified as a module parameter.
-
- Say "y" to link the driver statically, or "m" to build a
- dynamically linked module called "g_file_storage".
-
- NOTE: This driver is deprecated. Its replacement is the
- Mass Storage Gadget.
-
-config USB_FILE_STORAGE_TEST
- bool "File-backed Storage Gadget testing version"
- depends on USB_FILE_STORAGE
- default n
- help
- Say "y" to generate the larger testing version of the
- File-backed Storage Gadget, useful for probing the
- behavior of USB Mass Storage hosts. Not needed for
- normal operation.
-
config USB_MASS_STORAGE
tristate "Mass Storage Gadget"
depends on BLOCK
@@ -756,8 +731,8 @@ config USB_MASS_STORAGE
device (in much the same way as the "loop" device driver),
specified as a module parameter or sysfs option.
- This driver is an updated replacement for the deprecated
- File-backed Storage Gadget (g_file_storage).
+ This driver is a replacement for now removed File-backed
+ Storage Gadget (g_file_storage).
Say "y" to link the driver statically, or "m" to build
a dynamically linked module called "g_mass_storage".
diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
index 307be5fa824c..8b4acfd92aa3 100644
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -44,7 +44,6 @@ g_ether-y := ether.o
g_serial-y := serial.o
g_midi-y := gmidi.o
gadgetfs-y := inode.o
-g_file_storage-y := file_storage.o
g_mass_storage-y := mass_storage.o
g_printer-y := printer.o
g_cdc-y := cdc2.o
@@ -62,7 +61,6 @@ obj-$(CONFIG_USB_AUDIO) += g_audio.o
obj-$(CONFIG_USB_ETH) += g_ether.o
obj-$(CONFIG_USB_GADGETFS) += gadgetfs.o
obj-$(CONFIG_USB_FUNCTIONFS) += g_ffs.o
-obj-$(CONFIG_USB_FILE_STORAGE) += g_file_storage.o
obj-$(CONFIG_USB_MASS_STORAGE) += g_mass_storage.o
obj-$(CONFIG_USB_G_SERIAL) += g_serial.o
obj-$(CONFIG_USB_G_PRINTER) += g_printer.o
diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c
index 89d90b5fb787..e6135faabc3a 100644
--- a/drivers/usb/gadget/at91_udc.c
+++ b/drivers/usb/gadget/at91_udc.c
@@ -1673,7 +1673,7 @@ static void at91udc_shutdown(struct platform_device *dev)
spin_unlock_irqrestore(&udc->lock, flags);
}
-static void __devinit at91udc_of_init(struct at91_udc *udc,
+static void at91udc_of_init(struct at91_udc *udc,
struct device_node *np)
{
struct at91_udc_data *board = &udc->board;
@@ -1693,7 +1693,7 @@ static void __devinit at91udc_of_init(struct at91_udc *udc,
board->pullup_active_low = (flags & OF_GPIO_ACTIVE_LOW) ? 1 : 0;
}
-static int __devinit at91udc_probe(struct platform_device *pdev)
+static int at91udc_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct at91_udc *udc;
diff --git a/drivers/usb/gadget/bcm63xx_udc.c b/drivers/usb/gadget/bcm63xx_udc.c
index 9ca792224cd4..47a49931361e 100644
--- a/drivers/usb/gadget/bcm63xx_udc.c
+++ b/drivers/usb/gadget/bcm63xx_udc.c
@@ -2323,7 +2323,7 @@ static void bcm63xx_udc_gadget_release(struct device *dev)
* Note that platform data is required, because pd.port_no varies from chip
* to chip and is used to switch the correct USB port to device mode.
*/
-static int __devinit bcm63xx_udc_probe(struct platform_device *pdev)
+static int bcm63xx_udc_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct bcm63xx_usbd_platform_data *pd = dev->platform_data;
@@ -2433,7 +2433,7 @@ out_uninit:
* bcm63xx_udc_remove - Remove the device from the system.
* @pdev: Platform device struct from the bcm63xx BSP code.
*/
-static int __devexit bcm63xx_udc_remove(struct platform_device *pdev)
+static int bcm63xx_udc_remove(struct platform_device *pdev)
{
struct bcm63xx_udc *udc = platform_get_drvdata(pdev);
@@ -2450,7 +2450,7 @@ static int __devexit bcm63xx_udc_remove(struct platform_device *pdev)
static struct platform_driver bcm63xx_udc_driver = {
.probe = bcm63xx_udc_probe,
- .remove = __devexit_p(bcm63xx_udc_remove),
+ .remove = bcm63xx_udc_remove,
.driver = {
.name = DRV_MODULE_NAME,
.owner = THIS_MODULE,
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index 957f973dd96a..2a6bfe759c29 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -107,7 +107,7 @@ int config_ep_by_speed(struct usb_gadget *g,
}
/* else: fall through */
default:
- speed_desc = f->descriptors;
+ speed_desc = f->fs_descriptors;
}
/* find descriptors */
for_each_ep_desc(speed_desc, d_spd) {
@@ -200,7 +200,7 @@ int usb_add_function(struct usb_configuration *config,
* as full speed ... it's the function drivers that will need
* to avoid bulk and ISO transfers.
*/
- if (!config->fullspeed && function->descriptors)
+ if (!config->fullspeed && function->fs_descriptors)
config->fullspeed = true;
if (!config->highspeed && function->hs_descriptors)
config->highspeed = true;
@@ -363,7 +363,7 @@ static int config_buf(struct usb_configuration *config,
descriptors = f->hs_descriptors;
break;
default:
- descriptors = f->descriptors;
+ descriptors = f->fs_descriptors;
}
if (!descriptors)
@@ -620,7 +620,7 @@ static int set_config(struct usb_composite_dev *cdev,
descriptors = f->hs_descriptors;
break;
default:
- descriptors = f->descriptors;
+ descriptors = f->fs_descriptors;
}
for (; *descriptors; ++descriptors) {
diff --git a/drivers/usb/gadget/config.c b/drivers/usb/gadget/config.c
index e3a98929d346..34e12fc52c23 100644
--- a/drivers/usb/gadget/config.c
+++ b/drivers/usb/gadget/config.c
@@ -19,7 +19,7 @@
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
-
+#include <linux/usb/composite.h>
/**
* usb_descriptor_fillbuf - fill buffer with descriptors
@@ -158,3 +158,40 @@ usb_copy_descriptors(struct usb_descriptor_header **src)
return ret;
}
EXPORT_SYMBOL_GPL(usb_copy_descriptors);
+
+int usb_assign_descriptors(struct usb_function *f,
+ struct usb_descriptor_header **fs,
+ struct usb_descriptor_header **hs,
+ struct usb_descriptor_header **ss)
+{
+ struct usb_gadget *g = f->config->cdev->gadget;
+
+ if (fs) {
+ f->fs_descriptors = usb_copy_descriptors(fs);
+ if (!f->fs_descriptors)
+ goto err;
+ }
+ if (hs && gadget_is_dualspeed(g)) {
+ f->hs_descriptors = usb_copy_descriptors(hs);
+ if (!f->hs_descriptors)
+ goto err;
+ }
+ if (ss && gadget_is_superspeed(g)) {
+ f->ss_descriptors = usb_copy_descriptors(ss);
+ if (!f->ss_descriptors)
+ goto err;
+ }
+ return 0;
+err:
+ usb_free_all_descriptors(f);
+ return -ENOMEM;
+}
+EXPORT_SYMBOL_GPL(usb_assign_descriptors);
+
+void usb_free_all_descriptors(struct usb_function *f)
+{
+ usb_free_descriptors(f->fs_descriptors);
+ usb_free_descriptors(f->hs_descriptors);
+ usb_free_descriptors(f->ss_descriptors);
+}
+EXPORT_SYMBOL_GPL(usb_free_all_descriptors);
diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
index 0f7541be28f3..95d584dbed13 100644
--- a/drivers/usb/gadget/dummy_hcd.c
+++ b/drivers/usb/gadget/dummy_hcd.c
@@ -63,16 +63,20 @@ MODULE_LICENSE("GPL");
struct dummy_hcd_module_parameters {
bool is_super_speed;
bool is_high_speed;
+ unsigned int num;
};
static struct dummy_hcd_module_parameters mod_data = {
.is_super_speed = false,
.is_high_speed = true,
+ .num = 1,
};
module_param_named(is_super_speed, mod_data.is_super_speed, bool, S_IRUGO);
MODULE_PARM_DESC(is_super_speed, "true to simulate SuperSpeed connection");
module_param_named(is_high_speed, mod_data.is_high_speed, bool, S_IRUGO);
MODULE_PARM_DESC(is_high_speed, "true to simulate HighSpeed connection");
+module_param_named(num, mod_data.num, uint, S_IRUGO);
+MODULE_PARM_DESC(num, "number of emulated controllers");
/*-------------------------------------------------------------------------*/
/* gadget side driver data structres */
@@ -238,8 +242,6 @@ static inline struct dummy *gadget_dev_to_dummy(struct device *dev)
return container_of(dev, struct dummy, gadget.dev);
}
-static struct dummy the_controller;
-
/*-------------------------------------------------------------------------*/
/* SLAVE/GADGET SIDE UTILITY ROUTINES */
@@ -973,9 +975,10 @@ static void init_dummy_udc_hw(struct dummy *dum)
static int dummy_udc_probe(struct platform_device *pdev)
{
- struct dummy *dum = &the_controller;
+ struct dummy *dum;
int rc;
+ dum = *((void **)dev_get_platdata(&pdev->dev));
dum->gadget.name = gadget_name;
dum->gadget.ops = &dummy_ops;
dum->gadget.max_speed = USB_SPEED_SUPER;
@@ -2398,10 +2401,13 @@ static int dummy_h_get_frame(struct usb_hcd *hcd)
static int dummy_setup(struct usb_hcd *hcd)
{
+ struct dummy *dum;
+
+ dum = *((void **)dev_get_platdata(hcd->self.controller));
hcd->self.sg_tablesize = ~0;
if (usb_hcd_is_primary_hcd(hcd)) {
- the_controller.hs_hcd = hcd_to_dummy_hcd(hcd);
- the_controller.hs_hcd->dum = &the_controller;
+ dum->hs_hcd = hcd_to_dummy_hcd(hcd);
+ dum->hs_hcd->dum = dum;
/*
* Mark the first roothub as being USB 2.0.
* The USB 3.0 roothub will be registered later by
@@ -2410,8 +2416,8 @@ static int dummy_setup(struct usb_hcd *hcd)
hcd->speed = HCD_USB2;
hcd->self.root_hub->speed = USB_SPEED_HIGH;
} else {
- the_controller.ss_hcd = hcd_to_dummy_hcd(hcd);
- the_controller.ss_hcd->dum = &the_controller;
+ dum->ss_hcd = hcd_to_dummy_hcd(hcd);
+ dum->ss_hcd->dum = dum;
hcd->speed = HCD_USB3;
hcd->self.root_hub->speed = USB_SPEED_SUPER;
}
@@ -2524,11 +2530,13 @@ static struct hc_driver dummy_hcd = {
static int dummy_hcd_probe(struct platform_device *pdev)
{
+ struct dummy *dum;
struct usb_hcd *hs_hcd;
struct usb_hcd *ss_hcd;
int retval;
dev_info(&pdev->dev, "%s, driver " DRIVER_VERSION "\n", driver_desc);
+ dum = *((void **)dev_get_platdata(&pdev->dev));
if (!mod_data.is_super_speed)
dummy_hcd.flags = HCD_USB2;
@@ -2561,7 +2569,7 @@ dealloc_usb2_hcd:
usb_remove_hcd(hs_hcd);
put_usb2_hcd:
usb_put_hcd(hs_hcd);
- the_controller.hs_hcd = the_controller.ss_hcd = NULL;
+ dum->hs_hcd = dum->ss_hcd = NULL;
return retval;
}
@@ -2579,8 +2587,8 @@ static int dummy_hcd_remove(struct platform_device *pdev)
usb_remove_hcd(dummy_hcd_to_hcd(dum->hs_hcd));
usb_put_hcd(dummy_hcd_to_hcd(dum->hs_hcd));
- the_controller.hs_hcd = NULL;
- the_controller.ss_hcd = NULL;
+ dum->hs_hcd = NULL;
+ dum->ss_hcd = NULL;
return 0;
}
@@ -2627,13 +2635,15 @@ static struct platform_driver dummy_hcd_driver = {
};
/*-------------------------------------------------------------------------*/
-
-static struct platform_device *the_udc_pdev;
-static struct platform_device *the_hcd_pdev;
+#define MAX_NUM_UDC 2
+static struct platform_device *the_udc_pdev[MAX_NUM_UDC];
+static struct platform_device *the_hcd_pdev[MAX_NUM_UDC];
static int __init init(void)
{
int retval = -ENOMEM;
+ int i;
+ struct dummy *dum[MAX_NUM_UDC];
if (usb_disabled())
return -ENODEV;
@@ -2641,65 +2651,129 @@ static int __init init(void)
if (!mod_data.is_high_speed && mod_data.is_super_speed)
return -EINVAL;
- the_hcd_pdev = platform_device_alloc(driver_name, -1);
- if (!the_hcd_pdev)
- return retval;
- the_udc_pdev = platform_device_alloc(gadget_name, -1);
- if (!the_udc_pdev)
- goto err_alloc_udc;
+ if (mod_data.num < 1 || mod_data.num > MAX_NUM_UDC) {
+ pr_err("Number of emulated UDC must be in range of 1…%d\n",
+ MAX_NUM_UDC);
+ return -EINVAL;
+ }
+
+ for (i = 0; i < mod_data.num; i++) {
+ the_hcd_pdev[i] = platform_device_alloc(driver_name, i);
+ if (!the_hcd_pdev[i]) {
+ i--;
+ while (i >= 0)
+ platform_device_put(the_hcd_pdev[i--]);
+ return retval;
+ }
+ }
+ for (i = 0; i < mod_data.num; i++) {
+ the_udc_pdev[i] = platform_device_alloc(gadget_name, i);
+ if (!the_udc_pdev[i]) {
+ i--;
+ while (i >= 0)
+ platform_device_put(the_udc_pdev[i--]);
+ goto err_alloc_udc;
+ }
+ }
+ for (i = 0; i < mod_data.num; i++) {
+ dum[i] = kzalloc(sizeof(struct dummy), GFP_KERNEL);
+ if (!dum[i])
+ goto err_add_pdata;
+ retval = platform_device_add_data(the_hcd_pdev[i], &dum[i],
+ sizeof(void *));
+ if (retval)
+ goto err_add_pdata;
+ retval = platform_device_add_data(the_udc_pdev[i], &dum[i],
+ sizeof(void *));
+ if (retval)
+ goto err_add_pdata;
+ }
retval = platform_driver_register(&dummy_hcd_driver);
if (retval < 0)
- goto err_register_hcd_driver;
+ goto err_add_pdata;
retval = platform_driver_register(&dummy_udc_driver);
if (retval < 0)
goto err_register_udc_driver;
- retval = platform_device_add(the_hcd_pdev);
- if (retval < 0)
- goto err_add_hcd;
- if (!the_controller.hs_hcd ||
- (!the_controller.ss_hcd && mod_data.is_super_speed)) {
- /*
- * The hcd was added successfully but its probe function failed
- * for some reason.
- */
- retval = -EINVAL;
- goto err_add_udc;
+ for (i = 0; i < mod_data.num; i++) {
+ retval = platform_device_add(the_hcd_pdev[i]);
+ if (retval < 0) {
+ i--;
+ while (i >= 0)
+ platform_device_del(the_hcd_pdev[i--]);
+ goto err_add_hcd;
+ }
}
- retval = platform_device_add(the_udc_pdev);
- if (retval < 0)
- goto err_add_udc;
- if (!platform_get_drvdata(the_udc_pdev)) {
- /*
- * The udc was added successfully but its probe function failed
- * for some reason.
- */
- retval = -EINVAL;
- goto err_probe_udc;
+ for (i = 0; i < mod_data.num; i++) {
+ if (!dum[i]->hs_hcd ||
+ (!dum[i]->ss_hcd && mod_data.is_super_speed)) {
+ /*
+ * The hcd was added successfully but its probe
+ * function failed for some reason.
+ */
+ retval = -EINVAL;
+ goto err_add_udc;
+ }
+ }
+
+ for (i = 0; i < mod_data.num; i++) {
+ retval = platform_device_add(the_udc_pdev[i]);
+ if (retval < 0) {
+ i--;
+ while (i >= 0)
+ platform_device_del(the_udc_pdev[i]);
+ goto err_add_udc;
+ }
+ }
+
+ for (i = 0; i < mod_data.num; i++) {
+ if (!platform_get_drvdata(the_udc_pdev[i])) {
+ /*
+ * The udc was added successfully but its probe
+ * function failed for some reason.
+ */
+ retval = -EINVAL;
+ goto err_probe_udc;
+ }
}
return retval;
err_probe_udc:
- platform_device_del(the_udc_pdev);
+ for (i = 0; i < mod_data.num; i++)
+ platform_device_del(the_udc_pdev[i]);
err_add_udc:
- platform_device_del(the_hcd_pdev);
+ for (i = 0; i < mod_data.num; i++)
+ platform_device_del(the_hcd_pdev[i]);
err_add_hcd:
platform_driver_unregister(&dummy_udc_driver);
err_register_udc_driver:
platform_driver_unregister(&dummy_hcd_driver);
-err_register_hcd_driver:
- platform_device_put(the_udc_pdev);
+err_add_pdata:
+ for (i = 0; i < mod_data.num; i++)
+ kfree(dum[i]);
+ for (i = 0; i < mod_data.num; i++)
+ platform_device_put(the_udc_pdev[i]);
err_alloc_udc:
- platform_device_put(the_hcd_pdev);
+ for (i = 0; i < mod_data.num; i++)
+ platform_device_put(the_hcd_pdev[i]);
return retval;
}
module_init(init);
static void __exit cleanup(void)
{
- platform_device_unregister(the_udc_pdev);
- platform_device_unregister(the_hcd_pdev);
+ int i;
+
+ for (i = 0; i < mod_data.num; i++) {
+ struct dummy *dum;
+
+ dum = *((void **)dev_get_platdata(&the_udc_pdev[i]->dev));
+
+ platform_device_unregister(the_udc_pdev[i]);
+ platform_device_unregister(the_hcd_pdev[i]);
+ kfree(dum);
+ }
platform_driver_unregister(&dummy_udc_driver);
platform_driver_unregister(&dummy_hcd_driver);
}
diff --git a/drivers/usb/gadget/f_acm.c b/drivers/usb/gadget/f_acm.c
index d672250a61fa..549174466c21 100644
--- a/drivers/usb/gadget/f_acm.c
+++ b/drivers/usb/gadget/f_acm.c
@@ -87,7 +87,7 @@ static inline struct f_acm *port_to_acm(struct gserial *p)
/* notification endpoint uses smallish and infrequent fixed-size messages */
-#define GS_LOG2_NOTIFY_INTERVAL 5 /* 1 << 5 == 32 msec */
+#define GS_NOTIFY_INTERVAL_MS 32
#define GS_NOTIFY_MAXPACKET 10 /* notification + 2 bytes */
/* interface and class descriptors: */
@@ -167,7 +167,7 @@ static struct usb_endpoint_descriptor acm_fs_notify_desc = {
.bEndpointAddress = USB_DIR_IN,
.bmAttributes = USB_ENDPOINT_XFER_INT,
.wMaxPacketSize = cpu_to_le16(GS_NOTIFY_MAXPACKET),
- .bInterval = 1 << GS_LOG2_NOTIFY_INTERVAL,
+ .bInterval = GS_NOTIFY_INTERVAL_MS,
};
static struct usb_endpoint_descriptor acm_fs_in_desc = {
@@ -199,14 +199,13 @@ static struct usb_descriptor_header *acm_fs_function[] = {
};
/* high speed support: */
-
static struct usb_endpoint_descriptor acm_hs_notify_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = USB_DIR_IN,
.bmAttributes = USB_ENDPOINT_XFER_INT,
.wMaxPacketSize = cpu_to_le16(GS_NOTIFY_MAXPACKET),
- .bInterval = GS_LOG2_NOTIFY_INTERVAL+4,
+ .bInterval = USB_MS_TO_HS_INTERVAL(GS_NOTIFY_INTERVAL_MS),
};
static struct usb_endpoint_descriptor acm_hs_in_desc = {
@@ -659,37 +658,22 @@ acm_bind(struct usb_configuration *c, struct usb_function *f)
acm->notify_req->complete = acm_cdc_notify_complete;
acm->notify_req->context = acm;
- /* copy descriptors */
- f->descriptors = usb_copy_descriptors(acm_fs_function);
- if (!f->descriptors)
- goto fail;
-
/* support all relevant hardware speeds... we expect that when
* hardware is dual speed, all bulk-capable endpoints work at
* both speeds
*/
- if (gadget_is_dualspeed(c->cdev->gadget)) {
- acm_hs_in_desc.bEndpointAddress =
- acm_fs_in_desc.bEndpointAddress;
- acm_hs_out_desc.bEndpointAddress =
- acm_fs_out_desc.bEndpointAddress;
- acm_hs_notify_desc.bEndpointAddress =
- acm_fs_notify_desc.bEndpointAddress;
-
- /* copy descriptors */
- f->hs_descriptors = usb_copy_descriptors(acm_hs_function);
- }
- if (gadget_is_superspeed(c->cdev->gadget)) {
- acm_ss_in_desc.bEndpointAddress =
- acm_fs_in_desc.bEndpointAddress;
- acm_ss_out_desc.bEndpointAddress =
- acm_fs_out_desc.bEndpointAddress;
-
- /* copy descriptors, and track endpoint copies */
- f->ss_descriptors = usb_copy_descriptors(acm_ss_function);
- if (!f->ss_descriptors)
- goto fail;
- }
+ acm_hs_in_desc.bEndpointAddress = acm_fs_in_desc.bEndpointAddress;
+ acm_hs_out_desc.bEndpointAddress = acm_fs_out_desc.bEndpointAddress;
+ acm_hs_notify_desc.bEndpointAddress =
+ acm_fs_notify_desc.bEndpointAddress;
+
+ acm_ss_in_desc.bEndpointAddress = acm_fs_in_desc.bEndpointAddress;
+ acm_ss_out_desc.bEndpointAddress = acm_fs_out_desc.bEndpointAddress;
+
+ status = usb_assign_descriptors(f, acm_fs_function, acm_hs_function,
+ acm_ss_function);
+ if (status)
+ goto fail;
DBG(cdev, "acm ttyGS%d: %s speed IN/%s OUT/%s NOTIFY/%s\n",
acm->port_num,
@@ -721,11 +705,8 @@ acm_unbind(struct usb_configuration *c, struct usb_function *f)
{
struct f_acm *acm = func_to_acm(f);
- if (gadget_is_dualspeed(c->cdev->gadget))
- usb_free_descriptors(f->hs_descriptors);
- if (gadget_is_superspeed(c->cdev->gadget))
- usb_free_descriptors(f->ss_descriptors);
- usb_free_descriptors(f->descriptors);
+ acm_string_defs[0].id = 0;
+ usb_free_all_descriptors(f);
gs_free_req(acm->notify, acm->notify_req);
kfree(acm);
}
@@ -762,27 +743,15 @@ int acm_bind_config(struct usb_configuration *c, u8 port_num)
*/
/* maybe allocate device-global string IDs, and patch descriptors */
- if (acm_string_defs[ACM_CTRL_IDX].id == 0) {
- status = usb_string_id(c->cdev);
+ if (acm_string_defs[0].id == 0) {
+ status = usb_string_ids_tab(c->cdev, acm_string_defs);
if (status < 0)
return status;
- acm_string_defs[ACM_CTRL_IDX].id = status;
-
- acm_control_interface_desc.iInterface = status;
-
- status = usb_string_id(c->cdev);
- if (status < 0)
- return status;
- acm_string_defs[ACM_DATA_IDX].id = status;
-
- acm_data_interface_desc.iInterface = status;
-
- status = usb_string_id(c->cdev);
- if (status < 0)
- return status;
- acm_string_defs[ACM_IAD_IDX].id = status;
-
- acm_iad_descriptor.iFunction = status;
+ acm_control_interface_desc.iInterface =
+ acm_string_defs[ACM_CTRL_IDX].id;
+ acm_data_interface_desc.iInterface =
+ acm_string_defs[ACM_DATA_IDX].id;
+ acm_iad_descriptor.iFunction = acm_string_defs[ACM_IAD_IDX].id;
}
/* allocate and initialize one new instance */
diff --git a/drivers/usb/gadget/f_ecm.c b/drivers/usb/gadget/f_ecm.c
index 95bc94f8e570..83420a310fb7 100644
--- a/drivers/usb/gadget/f_ecm.c
+++ b/drivers/usb/gadget/f_ecm.c
@@ -91,7 +91,7 @@ static inline unsigned ecm_bitrate(struct usb_gadget *g)
* encapsulated commands (vendor-specific, using control-OUT).
*/
-#define LOG2_STATUS_INTERVAL_MSEC 5 /* 1 << 5 == 32 msec */
+#define ECM_STATUS_INTERVAL_MS 32
#define ECM_STATUS_BYTECOUNT 16 /* 8 byte header + data */
@@ -192,7 +192,7 @@ static struct usb_endpoint_descriptor fs_ecm_notify_desc = {
.bEndpointAddress = USB_DIR_IN,
.bmAttributes = USB_ENDPOINT_XFER_INT,
.wMaxPacketSize = cpu_to_le16(ECM_STATUS_BYTECOUNT),
- .bInterval = 1 << LOG2_STATUS_INTERVAL_MSEC,
+ .bInterval = ECM_STATUS_INTERVAL_MS,
};
static struct usb_endpoint_descriptor fs_ecm_in_desc = {
@@ -239,7 +239,7 @@ static struct usb_endpoint_descriptor hs_ecm_notify_desc = {
.bEndpointAddress = USB_DIR_IN,
.bmAttributes = USB_ENDPOINT_XFER_INT,
.wMaxPacketSize = cpu_to_le16(ECM_STATUS_BYTECOUNT),
- .bInterval = LOG2_STATUS_INTERVAL_MSEC + 4,
+ .bInterval = USB_MS_TO_HS_INTERVAL(ECM_STATUS_INTERVAL_MS),
};
static struct usb_endpoint_descriptor hs_ecm_in_desc = {
@@ -288,7 +288,7 @@ static struct usb_endpoint_descriptor ss_ecm_notify_desc = {
.bEndpointAddress = USB_DIR_IN,
.bmAttributes = USB_ENDPOINT_XFER_INT,
.wMaxPacketSize = cpu_to_le16(ECM_STATUS_BYTECOUNT),
- .bInterval = LOG2_STATUS_INTERVAL_MSEC + 4,
+ .bInterval = USB_MS_TO_HS_INTERVAL(ECM_STATUS_INTERVAL_MS),
};
static struct usb_ss_ep_comp_descriptor ss_ecm_intr_comp_desc = {
@@ -330,6 +330,7 @@ static struct usb_ss_ep_comp_descriptor ss_ecm_bulk_comp_desc = {
static struct usb_descriptor_header *ecm_ss_function[] = {
/* CDC ECM control descriptors */
+ (struct usb_descriptor_header *) &ecm_iad_descriptor,
(struct usb_descriptor_header *) &ecm_control_intf,
(struct usb_descriptor_header *) &ecm_header_desc,
(struct usb_descriptor_header *) &ecm_union_desc,
@@ -353,7 +354,7 @@ static struct usb_descriptor_header *ecm_ss_function[] = {
static struct usb_string ecm_string_defs[] = {
[0].s = "CDC Ethernet Control Model (ECM)",
- [1].s = NULL /* DYNAMIC */,
+ [1].s = "",
[2].s = "CDC Ethernet Data",
[3].s = "CDC ECM",
{ } /* end of list */
@@ -742,42 +743,24 @@ ecm_bind(struct usb_configuration *c, struct usb_function *f)
ecm->notify_req->context = ecm;
ecm->notify_req->complete = ecm_notify_complete;
- /* copy descriptors, and track endpoint copies */
- f->descriptors = usb_copy_descriptors(ecm_fs_function);
- if (!f->descriptors)
- goto fail;
-
/* support all relevant hardware speeds... we expect that when
* hardware is dual speed, all bulk-capable endpoints work at
* both speeds
*/
- if (gadget_is_dualspeed(c->cdev->gadget)) {
- hs_ecm_in_desc.bEndpointAddress =
- fs_ecm_in_desc.bEndpointAddress;
- hs_ecm_out_desc.bEndpointAddress =
- fs_ecm_out_desc.bEndpointAddress;
- hs_ecm_notify_desc.bEndpointAddress =
- fs_ecm_notify_desc.bEndpointAddress;
-
- /* copy descriptors, and track endpoint copies */
- f->hs_descriptors = usb_copy_descriptors(ecm_hs_function);
- if (!f->hs_descriptors)
- goto fail;
- }
-
- if (gadget_is_superspeed(c->cdev->gadget)) {
- ss_ecm_in_desc.bEndpointAddress =
- fs_ecm_in_desc.bEndpointAddress;
- ss_ecm_out_desc.bEndpointAddress =
- fs_ecm_out_desc.bEndpointAddress;
- ss_ecm_notify_desc.bEndpointAddress =
- fs_ecm_notify_desc.bEndpointAddress;
-
- /* copy descriptors, and track endpoint copies */
- f->ss_descriptors = usb_copy_descriptors(ecm_ss_function);
- if (!f->ss_descriptors)
- goto fail;
- }
+ hs_ecm_in_desc.bEndpointAddress = fs_ecm_in_desc.bEndpointAddress;
+ hs_ecm_out_desc.bEndpointAddress = fs_ecm_out_desc.bEndpointAddress;
+ hs_ecm_notify_desc.bEndpointAddress =
+ fs_ecm_notify_desc.bEndpointAddress;
+
+ ss_ecm_in_desc.bEndpointAddress = fs_ecm_in_desc.bEndpointAddress;
+ ss_ecm_out_desc.bEndpointAddress = fs_ecm_out_desc.bEndpointAddress;
+ ss_ecm_notify_desc.bEndpointAddress =
+ fs_ecm_notify_desc.bEndpointAddress;
+
+ status = usb_assign_descriptors(f, ecm_fs_function, ecm_hs_function,
+ ecm_ss_function);
+ if (status)
+ goto fail;
/* NOTE: all that is done without knowing or caring about
* the network link ... which is unavailable to this code
@@ -795,11 +778,6 @@ ecm_bind(struct usb_configuration *c, struct usb_function *f)
return 0;
fail:
- if (f->descriptors)
- usb_free_descriptors(f->descriptors);
- if (f->hs_descriptors)
- usb_free_descriptors(f->hs_descriptors);
-
if (ecm->notify_req) {
kfree(ecm->notify_req->buf);
usb_ep_free_request(ecm->notify, ecm->notify_req);
@@ -808,9 +786,9 @@ fail:
/* we might as well release our claims on endpoints */
if (ecm->notify)
ecm->notify->driver_data = NULL;
- if (ecm->port.out_ep->desc)
+ if (ecm->port.out_ep)
ecm->port.out_ep->driver_data = NULL;
- if (ecm->port.in_ep->desc)
+ if (ecm->port.in_ep)
ecm->port.in_ep->driver_data = NULL;
ERROR(cdev, "%s: can't bind, err %d\n", f->name, status);
@@ -825,16 +803,11 @@ ecm_unbind(struct usb_configuration *c, struct usb_function *f)
DBG(c->cdev, "ecm unbind\n");
- if (gadget_is_superspeed(c->cdev->gadget))
- usb_free_descriptors(f->ss_descriptors);
- if (gadget_is_dualspeed(c->cdev->gadget))
- usb_free_descriptors(f->hs_descriptors);
- usb_free_descriptors(f->descriptors);
+ ecm_string_defs[0].id = 0;
+ usb_free_all_descriptors(f);
kfree(ecm->notify_req->buf);
usb_ep_free_request(ecm->notify, ecm->notify_req);
-
- ecm_string_defs[1].s = NULL;
kfree(ecm);
}
@@ -859,36 +832,15 @@ ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
if (!can_support_ecm(c->cdev->gadget) || !ethaddr)
return -EINVAL;
- /* maybe allocate device-global string IDs */
if (ecm_string_defs[0].id == 0) {
-
- /* control interface label */
- status = usb_string_id(c->cdev);
- if (status < 0)
- return status;
- ecm_string_defs[0].id = status;
- ecm_control_intf.iInterface = status;
-
- /* data interface label */
- status = usb_string_id(c->cdev);
- if (status < 0)
+ status = usb_string_ids_tab(c->cdev, ecm_string_defs);
+ if (status)
return status;
- ecm_string_defs[2].id = status;
- ecm_data_intf.iInterface = status;
- /* MAC address */
- status = usb_string_id(c->cdev);
- if (status < 0)
- return status;
- ecm_string_defs[1].id = status;
- ecm_desc.iMACAddress = status;
-
- /* IAD label */
- status = usb_string_id(c->cdev);
- if (status < 0)
- return status;
- ecm_string_defs[3].id = status;
- ecm_iad_descriptor.iFunction = status;
+ ecm_control_intf.iInterface = ecm_string_defs[0].id;
+ ecm_data_intf.iInterface = ecm_string_defs[2].id;
+ ecm_desc.iMACAddress = ecm_string_defs[1].id;
+ ecm_iad_descriptor.iFunction = ecm_string_defs[3].id;
}
/* allocate and initialize one new instance */
@@ -913,9 +865,7 @@ ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
ecm->port.func.disable = ecm_disable;
status = usb_add_function(c, &ecm->port.func);
- if (status) {
- ecm_string_defs[1].s = NULL;
+ if (status)
kfree(ecm);
- }
return status;
}
diff --git a/drivers/usb/gadget/f_eem.c b/drivers/usb/gadget/f_eem.c
index 1a7b2dd7d408..cf0ebee85563 100644
--- a/drivers/usb/gadget/f_eem.c
+++ b/drivers/usb/gadget/f_eem.c
@@ -274,38 +274,20 @@ eem_bind(struct usb_configuration *c, struct usb_function *f)
status = -ENOMEM;
- /* copy descriptors, and track endpoint copies */
- f->descriptors = usb_copy_descriptors(eem_fs_function);
- if (!f->descriptors)
- goto fail;
-
/* support all relevant hardware speeds... we expect that when
* hardware is dual speed, all bulk-capable endpoints work at
* both speeds
*/
- if (gadget_is_dualspeed(c->cdev->gadget)) {
- eem_hs_in_desc.bEndpointAddress =
- eem_fs_in_desc.bEndpointAddress;
- eem_hs_out_desc.bEndpointAddress =
- eem_fs_out_desc.bEndpointAddress;
-
- /* copy descriptors, and track endpoint copies */
- f->hs_descriptors = usb_copy_descriptors(eem_hs_function);
- if (!f->hs_descriptors)
- goto fail;
- }
+ eem_hs_in_desc.bEndpointAddress = eem_fs_in_desc.bEndpointAddress;
+ eem_hs_out_desc.bEndpointAddress = eem_fs_out_desc.bEndpointAddress;
- if (gadget_is_superspeed(c->cdev->gadget)) {
- eem_ss_in_desc.bEndpointAddress =
- eem_fs_in_desc.bEndpointAddress;
- eem_ss_out_desc.bEndpointAddress =
- eem_fs_out_desc.bEndpointAddress;
+ eem_ss_in_desc.bEndpointAddress = eem_fs_in_desc.bEndpointAddress;
+ eem_ss_out_desc.bEndpointAddress = eem_fs_out_desc.bEndpointAddress;
- /* copy descriptors, and track endpoint copies */
- f->ss_descriptors = usb_copy_descriptors(eem_ss_function);
- if (!f->ss_descriptors)
- goto fail;
- }
+ status = usb_assign_descriptors(f, eem_fs_function, eem_hs_function,
+ eem_ss_function);
+ if (status)
+ goto fail;
DBG(cdev, "CDC Ethernet (EEM): %s speed IN/%s OUT/%s\n",
gadget_is_superspeed(c->cdev->gadget) ? "super" :
@@ -314,15 +296,10 @@ eem_bind(struct usb_configuration *c, struct usb_function *f)
return 0;
fail:
- if (f->descriptors)
- usb_free_descriptors(f->descriptors);
- if (f->hs_descriptors)
- usb_free_descriptors(f->hs_descriptors);
-
- /* we might as well release our claims on endpoints */
- if (eem->port.out_ep->desc)
+ usb_free_all_descriptors(f);
+ if (eem->port.out_ep)
eem->port.out_ep->driver_data = NULL;
- if (eem->port.in_ep->desc)
+ if (eem->port.in_ep)
eem->port.in_ep->driver_data = NULL;
ERROR(cdev, "%s: can't bind, err %d\n", f->name, status);
@@ -337,11 +314,7 @@ eem_unbind(struct usb_configuration *c, struct usb_function *f)
DBG(c->cdev, "eem unbind\n");
- if (gadget_is_superspeed(c->cdev->gadget))
- usb_free_descriptors(f->ss_descriptors);
- if (gadget_is_dualspeed(c->cdev->gadget))
- usb_free_descriptors(f->hs_descriptors);
- usb_free_descriptors(f->descriptors);
+ usb_free_all_descriptors(f);
kfree(eem);
}
diff --git a/drivers/usb/gadget/f_fs.c b/drivers/usb/gadget/f_fs.c
index 64c4ec10d1fc..4a6961c517f2 100644
--- a/drivers/usb/gadget/f_fs.c
+++ b/drivers/usb/gadget/f_fs.c
@@ -2097,7 +2097,7 @@ static int __ffs_func_bind_do_descs(enum ffs_entity_type type, u8 *valuep,
if (isHS)
func->function.hs_descriptors[(long)valuep] = desc;
else
- func->function.descriptors[(long)valuep] = desc;
+ func->function.fs_descriptors[(long)valuep] = desc;
if (!desc || desc->bDescriptorType != USB_DT_ENDPOINT)
return 0;
@@ -2249,7 +2249,7 @@ static int ffs_func_bind(struct usb_configuration *c,
* numbers without worrying that it may be described later on.
*/
if (likely(full)) {
- func->function.descriptors = data->fs_descs;
+ func->function.fs_descriptors = data->fs_descs;
ret = ffs_do_descs(ffs->fs_descs_count,
data->raw_descs,
sizeof data->raw_descs,
diff --git a/drivers/usb/gadget/f_hid.c b/drivers/usb/gadget/f_hid.c
index 511e527178e2..6e69a8e8d22a 100644
--- a/drivers/usb/gadget/f_hid.c
+++ b/drivers/usb/gadget/f_hid.c
@@ -573,7 +573,6 @@ static int __init hidg_bind(struct usb_configuration *c, struct usb_function *f)
goto fail;
hidg_interface_desc.bInterfaceNumber = status;
-
/* allocate instance-specific endpoints */
status = -ENODEV;
ep = usb_ep_autoconfig(c->cdev->gadget, &hidg_fs_in_ep_desc);
@@ -609,20 +608,15 @@ static int __init hidg_bind(struct usb_configuration *c, struct usb_function *f)
hidg_desc.desc[0].wDescriptorLength =
cpu_to_le16(hidg->report_desc_length);
- /* copy descriptors */
- f->descriptors = usb_copy_descriptors(hidg_fs_descriptors);
- if (!f->descriptors)
- goto fail;
+ hidg_hs_in_ep_desc.bEndpointAddress =
+ hidg_fs_in_ep_desc.bEndpointAddress;
+ hidg_hs_out_ep_desc.bEndpointAddress =
+ hidg_fs_out_ep_desc.bEndpointAddress;
- if (gadget_is_dualspeed(c->cdev->gadget)) {
- hidg_hs_in_ep_desc.bEndpointAddress =
- hidg_fs_in_ep_desc.bEndpointAddress;
- hidg_hs_out_ep_desc.bEndpointAddress =
- hidg_fs_out_ep_desc.bEndpointAddress;
- f->hs_descriptors = usb_copy_descriptors(hidg_hs_descriptors);
- if (!f->hs_descriptors)
- goto fail;
- }
+ status = usb_assign_descriptors(f, hidg_fs_descriptors,
+ hidg_hs_descriptors, NULL);
+ if (status)
+ goto fail;
mutex_init(&hidg->lock);
spin_lock_init(&hidg->spinlock);
@@ -649,9 +643,7 @@ fail:
usb_ep_free_request(hidg->in_ep, hidg->req);
}
- usb_free_descriptors(f->hs_descriptors);
- usb_free_descriptors(f->descriptors);
-
+ usb_free_all_descriptors(f);
return status;
}
@@ -668,9 +660,7 @@ static void hidg_unbind(struct usb_configuration *c, struct usb_function *f)
kfree(hidg->req->buf);
usb_ep_free_request(hidg->in_ep, hidg->req);
- /* free descriptors copies */
- usb_free_descriptors(f->hs_descriptors);
- usb_free_descriptors(f->descriptors);
+ usb_free_all_descriptors(f);
kfree(hidg->report_desc);
kfree(hidg);
diff --git a/drivers/usb/gadget/f_loopback.c b/drivers/usb/gadget/f_loopback.c
index 7275706caeb0..bb39cb2bb3a3 100644
--- a/drivers/usb/gadget/f_loopback.c
+++ b/drivers/usb/gadget/f_loopback.c
@@ -177,6 +177,7 @@ loopback_bind(struct usb_configuration *c, struct usb_function *f)
struct usb_composite_dev *cdev = c->cdev;
struct f_loopback *loop = func_to_loop(f);
int id;
+ int ret;
/* allocate interface ID(s) */
id = usb_interface_id(c, f);
@@ -201,22 +202,19 @@ autoconf_fail:
loop->out_ep->driver_data = cdev; /* claim */
/* support high speed hardware */
- if (gadget_is_dualspeed(c->cdev->gadget)) {
- hs_loop_source_desc.bEndpointAddress =
- fs_loop_source_desc.bEndpointAddress;
- hs_loop_sink_desc.bEndpointAddress =
- fs_loop_sink_desc.bEndpointAddress;
- f->hs_descriptors = hs_loopback_descs;
- }
+ hs_loop_source_desc.bEndpointAddress =
+ fs_loop_source_desc.bEndpointAddress;
+ hs_loop_sink_desc.bEndpointAddress = fs_loop_sink_desc.bEndpointAddress;
/* support super speed hardware */
- if (gadget_is_superspeed(c->cdev->gadget)) {
- ss_loop_source_desc.bEndpointAddress =
- fs_loop_source_desc.bEndpointAddress;
- ss_loop_sink_desc.bEndpointAddress =
- fs_loop_sink_desc.bEndpointAddress;
- f->ss_descriptors = ss_loopback_descs;
- }
+ ss_loop_source_desc.bEndpointAddress =
+ fs_loop_source_desc.bEndpointAddress;
+ ss_loop_sink_desc.bEndpointAddress = fs_loop_sink_desc.bEndpointAddress;
+
+ ret = usb_assign_descriptors(f, fs_loopback_descs, hs_loopback_descs,
+ ss_loopback_descs);
+ if (ret)
+ return ret;
DBG(cdev, "%s speed %s: IN/%s, OUT/%s\n",
(gadget_is_superspeed(c->cdev->gadget) ? "super" :
@@ -228,6 +226,7 @@ autoconf_fail:
static void
loopback_unbind(struct usb_configuration *c, struct usb_function *f)
{
+ usb_free_all_descriptors(f);
kfree(func_to_loop(f));
}
@@ -379,7 +378,6 @@ static int __init loopback_bind_config(struct usb_configuration *c)
return -ENOMEM;
loop->function.name = "loopback";
- loop->function.descriptors = fs_loopback_descs;
loop->function.bind = loopback_bind;
loop->function.unbind = loopback_unbind;
loop->function.set_alt = loopback_set_alt;
diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c
index 3a7668bde3ef..5d027b3e1ef0 100644
--- a/drivers/usb/gadget/f_mass_storage.c
+++ b/drivers/usb/gadget/f_mass_storage.c
@@ -228,10 +228,6 @@
static const char fsg_string_interface[] = "Mass Storage";
-#define FSG_NO_DEVICE_STRINGS 1
-#define FSG_NO_OTG 1
-#define FSG_NO_INTR_EP 1
-
#include "storage_common.c"
@@ -2904,9 +2900,7 @@ static void fsg_unbind(struct usb_configuration *c, struct usb_function *f)
}
fsg_common_put(common);
- usb_free_descriptors(fsg->function.descriptors);
- usb_free_descriptors(fsg->function.hs_descriptors);
- usb_free_descriptors(fsg->function.ss_descriptors);
+ usb_free_all_descriptors(&fsg->function);
kfree(fsg);
}
@@ -2916,6 +2910,8 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f)
struct usb_gadget *gadget = c->cdev->gadget;
int i;
struct usb_ep *ep;
+ unsigned max_burst;
+ int ret;
fsg->gadget = gadget;
@@ -2939,45 +2935,27 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f)
ep->driver_data = fsg->common; /* claim the endpoint */
fsg->bulk_out = ep;
- /* Copy descriptors */
- f->descriptors = usb_copy_descriptors(fsg_fs_function);
- if (unlikely(!f->descriptors))
- return -ENOMEM;
-
- if (gadget_is_dualspeed(gadget)) {
- /* Assume endpoint addresses are the same for both speeds */
- fsg_hs_bulk_in_desc.bEndpointAddress =
- fsg_fs_bulk_in_desc.bEndpointAddress;
- fsg_hs_bulk_out_desc.bEndpointAddress =
- fsg_fs_bulk_out_desc.bEndpointAddress;
- f->hs_descriptors = usb_copy_descriptors(fsg_hs_function);
- if (unlikely(!f->hs_descriptors)) {
- usb_free_descriptors(f->descriptors);
- return -ENOMEM;
- }
- }
-
- if (gadget_is_superspeed(gadget)) {
- unsigned max_burst;
+ /* Assume endpoint addresses are the same for both speeds */
+ fsg_hs_bulk_in_desc.bEndpointAddress =
+ fsg_fs_bulk_in_desc.bEndpointAddress;
+ fsg_hs_bulk_out_desc.bEndpointAddress =
+ fsg_fs_bulk_out_desc.bEndpointAddress;
- /* Calculate bMaxBurst, we know packet size is 1024 */
- max_burst = min_t(unsigned, FSG_BUFLEN / 1024, 15);
+ /* Calculate bMaxBurst, we know packet size is 1024 */
+ max_burst = min_t(unsigned, FSG_BUFLEN / 1024, 15);
- fsg_ss_bulk_in_desc.bEndpointAddress =
- fsg_fs_bulk_in_desc.bEndpointAddress;
- fsg_ss_bulk_in_comp_desc.bMaxBurst = max_burst;
+ fsg_ss_bulk_in_desc.bEndpointAddress =
+ fsg_fs_bulk_in_desc.bEndpointAddress;
+ fsg_ss_bulk_in_comp_desc.bMaxBurst = max_burst;
- fsg_ss_bulk_out_desc.bEndpointAddress =
- fsg_fs_bulk_out_desc.bEndpointAddress;
- fsg_ss_bulk_out_comp_desc.bMaxBurst = max_burst;
+ fsg_ss_bulk_out_desc.bEndpointAddress =
+ fsg_fs_bulk_out_desc.bEndpointAddress;
+ fsg_ss_bulk_out_comp_desc.bMaxBurst = max_burst;
- f->ss_descriptors = usb_copy_descriptors(fsg_ss_function);
- if (unlikely(!f->ss_descriptors)) {
- usb_free_descriptors(f->hs_descriptors);
- usb_free_descriptors(f->descriptors);
- return -ENOMEM;
- }
- }
+ ret = usb_assign_descriptors(f, fsg_fs_function, fsg_hs_function,
+ fsg_ss_function);
+ if (ret)
+ goto autoconf_fail;
return 0;
@@ -2986,7 +2964,6 @@ autoconf_fail:
return -ENOTSUPP;
}
-
/****************************** ADD FUNCTION ******************************/
static struct usb_gadget_strings *fsg_strings_array[] = {
diff --git a/drivers/usb/gadget/f_midi.c b/drivers/usb/gadget/f_midi.c
index 8ed1259fe80d..263e721c2694 100644
--- a/drivers/usb/gadget/f_midi.c
+++ b/drivers/usb/gadget/f_midi.c
@@ -414,7 +414,7 @@ static void f_midi_unbind(struct usb_configuration *c, struct usb_function *f)
kfree(midi->id);
midi->id = NULL;
- usb_free_descriptors(f->descriptors);
+ usb_free_all_descriptors(f);
kfree(midi);
}
@@ -881,19 +881,25 @@ f_midi_bind(struct usb_configuration *c, struct usb_function *f)
* both speeds
*/
/* copy descriptors, and track endpoint copies */
+ f->fs_descriptors = usb_copy_descriptors(midi_function);
+ if (!f->fs_descriptors)
+ goto fail_f_midi;
+
if (gadget_is_dualspeed(c->cdev->gadget)) {
- c->highspeed = true;
bulk_in_desc.wMaxPacketSize = cpu_to_le16(512);
bulk_out_desc.wMaxPacketSize = cpu_to_le16(512);
f->hs_descriptors = usb_copy_descriptors(midi_function);
- } else {
- f->descriptors = usb_copy_descriptors(midi_function);
+ if (!f->hs_descriptors)
+ goto fail_f_midi;
}
kfree(midi_function);
return 0;
+fail_f_midi:
+ kfree(midi_function);
+ usb_free_descriptors(f->hs_descriptors);
fail:
/* we might as well release our claims on endpoints */
if (midi->out_ep)
diff --git a/drivers/usb/gadget/f_ncm.c b/drivers/usb/gadget/f_ncm.c
index b651b529c67f..6c8362f937be 100644
--- a/drivers/usb/gadget/f_ncm.c
+++ b/drivers/usb/gadget/f_ncm.c
@@ -102,7 +102,7 @@ static inline unsigned ncm_bitrate(struct usb_gadget *g)
USB_CDC_NCM_NTB32_SUPPORTED)
static struct usb_cdc_ncm_ntb_parameters ntb_parameters = {
- .wLength = sizeof ntb_parameters,
+ .wLength = cpu_to_le16(sizeof(ntb_parameters)),
.bmNtbFormatsSupported = cpu_to_le16(FORMATS_SUPPORTED),
.dwNtbInMaxSize = cpu_to_le32(NTB_DEFAULT_IN_SIZE),
.wNdpInDivisor = cpu_to_le16(4),
@@ -121,7 +121,7 @@ static struct usb_cdc_ncm_ntb_parameters ntb_parameters = {
* waste less bandwidth.
*/
-#define LOG2_STATUS_INTERVAL_MSEC 5 /* 1 << 5 == 32 msec */
+#define NCM_STATUS_INTERVAL_MS 32
#define NCM_STATUS_BYTECOUNT 16 /* 8 byte header + data */
static struct usb_interface_assoc_descriptor ncm_iad_desc __initdata = {
@@ -230,7 +230,7 @@ static struct usb_endpoint_descriptor fs_ncm_notify_desc __initdata = {
.bEndpointAddress = USB_DIR_IN,
.bmAttributes = USB_ENDPOINT_XFER_INT,
.wMaxPacketSize = cpu_to_le16(NCM_STATUS_BYTECOUNT),
- .bInterval = 1 << LOG2_STATUS_INTERVAL_MSEC,
+ .bInterval = NCM_STATUS_INTERVAL_MS,
};
static struct usb_endpoint_descriptor fs_ncm_in_desc __initdata = {
@@ -275,7 +275,7 @@ static struct usb_endpoint_descriptor hs_ncm_notify_desc __initdata = {
.bEndpointAddress = USB_DIR_IN,
.bmAttributes = USB_ENDPOINT_XFER_INT,
.wMaxPacketSize = cpu_to_le16(NCM_STATUS_BYTECOUNT),
- .bInterval = LOG2_STATUS_INTERVAL_MSEC + 4,
+ .bInterval = USB_MS_TO_HS_INTERVAL(NCM_STATUS_INTERVAL_MS),
};
static struct usb_endpoint_descriptor hs_ncm_in_desc __initdata = {
.bLength = USB_DT_ENDPOINT_SIZE,
@@ -321,7 +321,7 @@ static struct usb_descriptor_header *ncm_hs_function[] __initdata = {
static struct usb_string ncm_string_defs[] = {
[STRING_CTRL_IDX].s = "CDC Network Control Model (NCM)",
- [STRING_MAC_IDX].s = NULL /* DYNAMIC */,
+ [STRING_MAC_IDX].s = "",
[STRING_DATA_IDX].s = "CDC Network Data",
[STRING_IAD_IDX].s = "CDC NCM",
{ } /* end of list */
@@ -869,15 +869,19 @@ static struct sk_buff *ncm_wrap_ntb(struct gether *port,
struct sk_buff *skb2;
int ncb_len = 0;
__le16 *tmp;
- int div = ntb_parameters.wNdpInDivisor;
- int rem = ntb_parameters.wNdpInPayloadRemainder;
+ int div;
+ int rem;
int pad;
- int ndp_align = ntb_parameters.wNdpInAlignment;
+ int ndp_align;
int ndp_pad;
unsigned max_size = ncm->port.fixed_in_len;
struct ndp_parser_opts *opts = ncm->parser_opts;
unsigned crc_len = ncm->is_crc ? sizeof(uint32_t) : 0;
+ div = le16_to_cpu(ntb_parameters.wNdpInDivisor);
+ rem = le16_to_cpu(ntb_parameters.wNdpInPayloadRemainder);
+ ndp_align = le16_to_cpu(ntb_parameters.wNdpInAlignment);
+
ncb_len += opts->nth_size;
ndp_pad = ALIGN(ncb_len, ndp_align) - ncb_len;
ncb_len += ndp_pad;
@@ -1208,30 +1212,18 @@ ncm_bind(struct usb_configuration *c, struct usb_function *f)
ncm->notify_req->context = ncm;
ncm->notify_req->complete = ncm_notify_complete;
- /* copy descriptors, and track endpoint copies */
- f->descriptors = usb_copy_descriptors(ncm_fs_function);
- if (!f->descriptors)
- goto fail;
-
/*
* support all relevant hardware speeds... we expect that when
* hardware is dual speed, all bulk-capable endpoints work at
* both speeds
*/
- if (gadget_is_dualspeed(c->cdev->gadget)) {
- hs_ncm_in_desc.bEndpointAddress =
- fs_ncm_in_desc.bEndpointAddress;
- hs_ncm_out_desc.bEndpointAddress =
- fs_ncm_out_desc.bEndpointAddress;
- hs_ncm_notify_desc.bEndpointAddress =
- fs_ncm_notify_desc.bEndpointAddress;
-
- /* copy descriptors, and track endpoint copies */
- f->hs_descriptors = usb_copy_descriptors(ncm_hs_function);
- if (!f->hs_descriptors)
- goto fail;
- }
+ hs_ncm_in_desc.bEndpointAddress = fs_ncm_in_desc.bEndpointAddress;
+ hs_ncm_out_desc.bEndpointAddress = fs_ncm_out_desc.bEndpointAddress;
+ hs_ncm_notify_desc.bEndpointAddress =
+ fs_ncm_notify_desc.bEndpointAddress;
+ status = usb_assign_descriptors(f, ncm_fs_function, ncm_hs_function,
+ NULL);
/*
* NOTE: all that is done without knowing or caring about
* the network link ... which is unavailable to this code
@@ -1248,9 +1240,7 @@ ncm_bind(struct usb_configuration *c, struct usb_function *f)
return 0;
fail:
- if (f->descriptors)
- usb_free_descriptors(f->descriptors);
-
+ usb_free_all_descriptors(f);
if (ncm->notify_req) {
kfree(ncm->notify_req->buf);
usb_ep_free_request(ncm->notify, ncm->notify_req);
@@ -1259,9 +1249,9 @@ fail:
/* we might as well release our claims on endpoints */
if (ncm->notify)
ncm->notify->driver_data = NULL;
- if (ncm->port.out_ep->desc)
+ if (ncm->port.out_ep)
ncm->port.out_ep->driver_data = NULL;
- if (ncm->port.in_ep->desc)
+ if (ncm->port.in_ep)
ncm->port.in_ep->driver_data = NULL;
ERROR(cdev, "%s: can't bind, err %d\n", f->name, status);
@@ -1276,14 +1266,12 @@ ncm_unbind(struct usb_configuration *c, struct usb_function *f)
DBG(c->cdev, "ncm unbind\n");
- if (gadget_is_dualspeed(c->cdev->gadget))
- usb_free_descriptors(f->hs_descriptors);
- usb_free_descriptors(f->descriptors);
+ ncm_string_defs[0].id = 0;
+ usb_free_all_descriptors(f);
kfree(ncm->notify_req->buf);
usb_ep_free_request(ncm->notify, ncm->notify_req);
- ncm_string_defs[1].s = NULL;
kfree(ncm);
}
@@ -1307,37 +1295,19 @@ int __init ncm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
if (!can_support_ecm(c->cdev->gadget) || !ethaddr)
return -EINVAL;
- /* maybe allocate device-global string IDs */
if (ncm_string_defs[0].id == 0) {
-
- /* control interface label */
- status = usb_string_id(c->cdev);
+ status = usb_string_ids_tab(c->cdev, ncm_string_defs);
if (status < 0)
return status;
- ncm_string_defs[STRING_CTRL_IDX].id = status;
- ncm_control_intf.iInterface = status;
+ ncm_control_intf.iInterface =
+ ncm_string_defs[STRING_CTRL_IDX].id;
- /* data interface label */
- status = usb_string_id(c->cdev);
- if (status < 0)
- return status;
- ncm_string_defs[STRING_DATA_IDX].id = status;
+ status = ncm_string_defs[STRING_DATA_IDX].id;
ncm_data_nop_intf.iInterface = status;
ncm_data_intf.iInterface = status;
- /* MAC address */
- status = usb_string_id(c->cdev);
- if (status < 0)
- return status;
- ncm_string_defs[STRING_MAC_IDX].id = status;
- ecm_desc.iMACAddress = status;
-
- /* IAD */
- status = usb_string_id(c->cdev);
- if (status < 0)
- return status;
- ncm_string_defs[STRING_IAD_IDX].id = status;
- ncm_iad_desc.iFunction = status;
+ ecm_desc.iMACAddress = ncm_string_defs[STRING_MAC_IDX].id;
+ ncm_iad_desc.iFunction = ncm_string_defs[STRING_IAD_IDX].id;
}
/* allocate and initialize one new instance */
@@ -1347,7 +1317,7 @@ int __init ncm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
/* export host's Ethernet address in CDC format */
snprintf(ncm->ethaddr, sizeof ncm->ethaddr, "%pm", ethaddr);
- ncm_string_defs[1].s = ncm->ethaddr;
+ ncm_string_defs[STRING_MAC_IDX].s = ncm->ethaddr;
spin_lock_init(&ncm->lock);
ncm_reset_values(ncm);
@@ -1367,9 +1337,7 @@ int __init ncm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
ncm->port.unwrap = ncm_unwrap_ntb;
status = usb_add_function(c, &ncm->port.func);
- if (status) {
- ncm_string_defs[1].s = NULL;
+ if (status)
kfree(ncm);
- }
return status;
}
diff --git a/drivers/usb/gadget/f_obex.c b/drivers/usb/gadget/f_obex.c
index 5f400f66aa9b..d8dd8782768c 100644
--- a/drivers/usb/gadget/f_obex.c
+++ b/drivers/usb/gadget/f_obex.c
@@ -331,23 +331,19 @@ obex_bind(struct usb_configuration *c, struct usb_function *f)
obex->port.out = ep;
ep->driver_data = cdev; /* claim */
- /* copy descriptors, and track endpoint copies */
- f->descriptors = usb_copy_descriptors(fs_function);
-
/* support all relevant hardware speeds... we expect that when
* hardware is dual speed, all bulk-capable endpoints work at
* both speeds
*/
- if (gadget_is_dualspeed(c->cdev->gadget)) {
- obex_hs_ep_in_desc.bEndpointAddress =
- obex_fs_ep_in_desc.bEndpointAddress;
- obex_hs_ep_out_desc.bEndpointAddress =
- obex_fs_ep_out_desc.bEndpointAddress;
+ obex_hs_ep_in_desc.bEndpointAddress =
+ obex_fs_ep_in_desc.bEndpointAddress;
+ obex_hs_ep_out_desc.bEndpointAddress =
+ obex_fs_ep_out_desc.bEndpointAddress;
- /* copy descriptors, and track endpoint copies */
- f->hs_descriptors = usb_copy_descriptors(hs_function);
- }
+ status = usb_assign_descriptors(f, fs_function, hs_function, NULL);
+ if (status)
+ goto fail;
/* Avoid letting this gadget enumerate until the userspace
* OBEX server is active.
@@ -368,6 +364,7 @@ obex_bind(struct usb_configuration *c, struct usb_function *f)
return 0;
fail:
+ usb_free_all_descriptors(f);
/* we might as well release our claims on endpoints */
if (obex->port.out)
obex->port.out->driver_data = NULL;
@@ -382,9 +379,8 @@ fail:
static void
obex_unbind(struct usb_configuration *c, struct usb_function *f)
{
- if (gadget_is_dualspeed(c->cdev->gadget))
- usb_free_descriptors(f->hs_descriptors);
- usb_free_descriptors(f->descriptors);
+ obex_string_defs[OBEX_CTRL_IDX].id = 0;
+ usb_free_all_descriptors(f);
kfree(func_to_obex(f));
}
@@ -423,22 +419,16 @@ int __init obex_bind_config(struct usb_configuration *c, u8 port_num)
if (!can_support_obex(c))
return -EINVAL;
- /* maybe allocate device-global string IDs, and patch descriptors */
if (obex_string_defs[OBEX_CTRL_IDX].id == 0) {
- status = usb_string_id(c->cdev);
- if (status < 0)
- return status;
- obex_string_defs[OBEX_CTRL_IDX].id = status;
-
- obex_control_intf.iInterface = status;
-
- status = usb_string_id(c->cdev);
+ status = usb_string_ids_tab(c->cdev, obex_string_defs);
if (status < 0)
return status;
- obex_string_defs[OBEX_DATA_IDX].id = status;
+ obex_control_intf.iInterface =
+ obex_string_defs[OBEX_CTRL_IDX].id;
- obex_data_nop_intf.iInterface =
- obex_data_intf.iInterface = status;
+ status = obex_string_defs[OBEX_DATA_IDX].id;
+ obex_data_nop_intf.iInterface = status;
+ obex_data_intf.iInterface = status;
}
/* allocate and initialize one new instance */
diff --git a/drivers/usb/gadget/f_phonet.c b/drivers/usb/gadget/f_phonet.c
index 8ee9268fe253..b21ab558b6c0 100644
--- a/drivers/usb/gadget/f_phonet.c
+++ b/drivers/usb/gadget/f_phonet.c
@@ -515,14 +515,14 @@ int pn_bind(struct usb_configuration *c, struct usb_function *f)
fp->in_ep = ep;
ep->driver_data = fp; /* Claim */
- pn_hs_sink_desc.bEndpointAddress =
- pn_fs_sink_desc.bEndpointAddress;
- pn_hs_source_desc.bEndpointAddress =
- pn_fs_source_desc.bEndpointAddress;
+ pn_hs_sink_desc.bEndpointAddress = pn_fs_sink_desc.bEndpointAddress;
+ pn_hs_source_desc.bEndpointAddress = pn_fs_source_desc.bEndpointAddress;
/* Do not try to bind Phonet twice... */
- fp->function.descriptors = fs_pn_function;
- fp->function.hs_descriptors = hs_pn_function;
+ status = usb_assign_descriptors(f, fs_pn_function, hs_pn_function,
+ NULL);
+ if (status)
+ goto err;
/* Incoming USB requests */
status = -ENOMEM;
@@ -531,7 +531,7 @@ int pn_bind(struct usb_configuration *c, struct usb_function *f)
req = usb_ep_alloc_request(fp->out_ep, GFP_KERNEL);
if (!req)
- goto err;
+ goto err_req;
req->complete = pn_rx_complete;
fp->out_reqv[i] = req;
@@ -540,14 +540,18 @@ int pn_bind(struct usb_configuration *c, struct usb_function *f)
/* Outgoing USB requests */
fp->in_req = usb_ep_alloc_request(fp->in_ep, GFP_KERNEL);
if (!fp->in_req)
- goto err;
+ goto err_req;
INFO(cdev, "USB CDC Phonet function\n");
INFO(cdev, "using %s, OUT %s, IN %s\n", cdev->gadget->name,
fp->out_ep->name, fp->in_ep->name);
return 0;
+err_req:
+ for (i = 0; i < phonet_rxq_size && fp->out_reqv[i]; i++)
+ usb_ep_free_request(fp->out_ep, fp->out_reqv[i]);
err:
+ usb_free_all_descriptors(f);
if (fp->out_ep)
fp->out_ep->driver_data = NULL;
if (fp->in_ep)
@@ -569,6 +573,7 @@ pn_unbind(struct usb_configuration *c, struct usb_function *f)
if (fp->out_reqv[i])
usb_ep_free_request(fp->out_ep, fp->out_reqv[i]);
+ usb_free_all_descriptors(f);
kfree(fp);
}
diff --git a/drivers/usb/gadget/f_rndis.c b/drivers/usb/gadget/f_rndis.c
index b1681e45aca7..71beeb833558 100644
--- a/drivers/usb/gadget/f_rndis.c
+++ b/drivers/usb/gadget/f_rndis.c
@@ -101,7 +101,7 @@ static unsigned int bitrate(struct usb_gadget *g)
/*
*/
-#define LOG2_STATUS_INTERVAL_MSEC 5 /* 1 << 5 == 32 msec */
+#define RNDIS_STATUS_INTERVAL_MS 32
#define STATUS_BYTECOUNT 8 /* 8 bytes data */
@@ -190,7 +190,7 @@ static struct usb_endpoint_descriptor fs_notify_desc = {
.bEndpointAddress = USB_DIR_IN,
.bmAttributes = USB_ENDPOINT_XFER_INT,
.wMaxPacketSize = cpu_to_le16(STATUS_BYTECOUNT),
- .bInterval = 1 << LOG2_STATUS_INTERVAL_MSEC,
+ .bInterval = RNDIS_STATUS_INTERVAL_MS,
};
static struct usb_endpoint_descriptor fs_in_desc = {
@@ -236,7 +236,7 @@ static struct usb_endpoint_descriptor hs_notify_desc = {
.bEndpointAddress = USB_DIR_IN,
.bmAttributes = USB_ENDPOINT_XFER_INT,
.wMaxPacketSize = cpu_to_le16(STATUS_BYTECOUNT),
- .bInterval = LOG2_STATUS_INTERVAL_MSEC + 4,
+ .bInterval = USB_MS_TO_HS_INTERVAL(RNDIS_STATUS_INTERVAL_MS)
};
static struct usb_endpoint_descriptor hs_in_desc = {
@@ -284,7 +284,7 @@ static struct usb_endpoint_descriptor ss_notify_desc = {
.bEndpointAddress = USB_DIR_IN,
.bmAttributes = USB_ENDPOINT_XFER_INT,
.wMaxPacketSize = cpu_to_le16(STATUS_BYTECOUNT),
- .bInterval = LOG2_STATUS_INTERVAL_MSEC + 4,
+ .bInterval = USB_MS_TO_HS_INTERVAL(RNDIS_STATUS_INTERVAL_MS)
};
static struct usb_ss_ep_comp_descriptor ss_intr_comp_desc = {
@@ -722,42 +722,22 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f)
rndis->notify_req->context = rndis;
rndis->notify_req->complete = rndis_response_complete;
- /* copy descriptors, and track endpoint copies */
- f->descriptors = usb_copy_descriptors(eth_fs_function);
- if (!f->descriptors)
- goto fail;
-
/* support all relevant hardware speeds... we expect that when
* hardware is dual speed, all bulk-capable endpoints work at
* both speeds
*/
- if (gadget_is_dualspeed(c->cdev->gadget)) {
- hs_in_desc.bEndpointAddress =
- fs_in_desc.bEndpointAddress;
- hs_out_desc.bEndpointAddress =
- fs_out_desc.bEndpointAddress;
- hs_notify_desc.bEndpointAddress =
- fs_notify_desc.bEndpointAddress;
-
- /* copy descriptors, and track endpoint copies */
- f->hs_descriptors = usb_copy_descriptors(eth_hs_function);
- if (!f->hs_descriptors)
- goto fail;
- }
+ hs_in_desc.bEndpointAddress = fs_in_desc.bEndpointAddress;
+ hs_out_desc.bEndpointAddress = fs_out_desc.bEndpointAddress;
+ hs_notify_desc.bEndpointAddress = fs_notify_desc.bEndpointAddress;
- if (gadget_is_superspeed(c->cdev->gadget)) {
- ss_in_desc.bEndpointAddress =
- fs_in_desc.bEndpointAddress;
- ss_out_desc.bEndpointAddress =
- fs_out_desc.bEndpointAddress;
- ss_notify_desc.bEndpointAddress =
- fs_notify_desc.bEndpointAddress;
-
- /* copy descriptors, and track endpoint copies */
- f->ss_descriptors = usb_copy_descriptors(eth_ss_function);
- if (!f->ss_descriptors)
- goto fail;
- }
+ ss_in_desc.bEndpointAddress = fs_in_desc.bEndpointAddress;
+ ss_out_desc.bEndpointAddress = fs_out_desc.bEndpointAddress;
+ ss_notify_desc.bEndpointAddress = fs_notify_desc.bEndpointAddress;
+
+ status = usb_assign_descriptors(f, eth_fs_function, eth_hs_function,
+ eth_ss_function);
+ if (status)
+ goto fail;
rndis->port.open = rndis_open;
rndis->port.close = rndis_close;
@@ -788,12 +768,7 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f)
return 0;
fail:
- if (gadget_is_superspeed(c->cdev->gadget) && f->ss_descriptors)
- usb_free_descriptors(f->ss_descriptors);
- if (gadget_is_dualspeed(c->cdev->gadget) && f->hs_descriptors)
- usb_free_descriptors(f->hs_descriptors);
- if (f->descriptors)
- usb_free_descriptors(f->descriptors);
+ usb_free_all_descriptors(f);
if (rndis->notify_req) {
kfree(rndis->notify_req->buf);
@@ -803,9 +778,9 @@ fail:
/* we might as well release our claims on endpoints */
if (rndis->notify)
rndis->notify->driver_data = NULL;
- if (rndis->port.out_ep->desc)
+ if (rndis->port.out_ep)
rndis->port.out_ep->driver_data = NULL;
- if (rndis->port.in_ep->desc)
+ if (rndis->port.in_ep)
rndis->port.in_ep->driver_data = NULL;
ERROR(cdev, "%s: can't bind, err %d\n", f->name, status);
@@ -820,13 +795,9 @@ rndis_unbind(struct usb_configuration *c, struct usb_function *f)
rndis_deregister(rndis->config);
rndis_exit();
- rndis_string_defs[0].id = 0;
- if (gadget_is_superspeed(c->cdev->gadget))
- usb_free_descriptors(f->ss_descriptors);
- if (gadget_is_dualspeed(c->cdev->gadget))
- usb_free_descriptors(f->hs_descriptors);
- usb_free_descriptors(f->descriptors);
+ rndis_string_defs[0].id = 0;
+ usb_free_all_descriptors(f);
kfree(rndis->notify_req->buf);
usb_ep_free_request(rndis->notify, rndis->notify_req);
@@ -851,34 +822,19 @@ rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
if (!can_support_rndis(c) || !ethaddr)
return -EINVAL;
- /* maybe allocate device-global string IDs */
if (rndis_string_defs[0].id == 0) {
-
/* ... and setup RNDIS itself */
status = rndis_init();
if (status < 0)
return status;
- /* control interface label */
- status = usb_string_id(c->cdev);
- if (status < 0)
+ status = usb_string_ids_tab(c->cdev, rndis_string_defs);
+ if (status)
return status;
- rndis_string_defs[0].id = status;
- rndis_control_intf.iInterface = status;
- /* data interface label */
- status = usb_string_id(c->cdev);
- if (status < 0)
- return status;
- rndis_string_defs[1].id = status;
- rndis_data_intf.iInterface = status;
-
- /* IAD iFunction label */
- status = usb_string_id(c->cdev);
- if (status < 0)
- return status;
- rndis_string_defs[2].id = status;
- rndis_iad_descriptor.iFunction = status;
+ rndis_control_intf.iInterface = rndis_string_defs[0].id;
+ rndis_data_intf.iInterface = rndis_string_defs[1].id;
+ rndis_iad_descriptor.iFunction = rndis_string_defs[2].id;
}
/* allocate and initialize one new instance */
diff --git a/drivers/usb/gadget/f_serial.c b/drivers/usb/gadget/f_serial.c
index 07197d63d9b1..98fa7795df5f 100644
--- a/drivers/usb/gadget/f_serial.c
+++ b/drivers/usb/gadget/f_serial.c
@@ -213,34 +213,20 @@ gser_bind(struct usb_configuration *c, struct usb_function *f)
gser->port.out = ep;
ep->driver_data = cdev; /* claim */
- /* copy descriptors, and track endpoint copies */
- f->descriptors = usb_copy_descriptors(gser_fs_function);
-
/* support all relevant hardware speeds... we expect that when
* hardware is dual speed, all bulk-capable endpoints work at
* both speeds
*/
- if (gadget_is_dualspeed(c->cdev->gadget)) {
- gser_hs_in_desc.bEndpointAddress =
- gser_fs_in_desc.bEndpointAddress;
- gser_hs_out_desc.bEndpointAddress =
- gser_fs_out_desc.bEndpointAddress;
-
- /* copy descriptors, and track endpoint copies */
- f->hs_descriptors = usb_copy_descriptors(gser_hs_function);
- }
- if (gadget_is_superspeed(c->cdev->gadget)) {
- gser_ss_in_desc.bEndpointAddress =
- gser_fs_in_desc.bEndpointAddress;
- gser_ss_out_desc.bEndpointAddress =
- gser_fs_out_desc.bEndpointAddress;
-
- /* copy descriptors, and track endpoint copies */
- f->ss_descriptors = usb_copy_descriptors(gser_ss_function);
- if (!f->ss_descriptors)
- goto fail;
- }
+ gser_hs_in_desc.bEndpointAddress = gser_fs_in_desc.bEndpointAddress;
+ gser_hs_out_desc.bEndpointAddress = gser_fs_out_desc.bEndpointAddress;
+ gser_ss_in_desc.bEndpointAddress = gser_fs_in_desc.bEndpointAddress;
+ gser_ss_out_desc.bEndpointAddress = gser_fs_out_desc.bEndpointAddress;
+
+ status = usb_assign_descriptors(f, gser_fs_function, gser_hs_function,
+ gser_ss_function);
+ if (status)
+ goto fail;
DBG(cdev, "generic ttyGS%d: %s speed IN/%s OUT/%s\n",
gser->port_num,
gadget_is_superspeed(c->cdev->gadget) ? "super" :
@@ -263,11 +249,7 @@ fail:
static void
gser_unbind(struct usb_configuration *c, struct usb_function *f)
{
- if (gadget_is_dualspeed(c->cdev->gadget))
- usb_free_descriptors(f->hs_descriptors);
- if (gadget_is_superspeed(c->cdev->gadget))
- usb_free_descriptors(f->ss_descriptors);
- usb_free_descriptors(f->descriptors);
+ usb_free_all_descriptors(f);
kfree(func_to_gser(f));
}
diff --git a/drivers/usb/gadget/f_sourcesink.c b/drivers/usb/gadget/f_sourcesink.c
index 3c126fde6e7e..102d49beb9df 100644
--- a/drivers/usb/gadget/f_sourcesink.c
+++ b/drivers/usb/gadget/f_sourcesink.c
@@ -319,6 +319,7 @@ sourcesink_bind(struct usb_configuration *c, struct usb_function *f)
struct usb_composite_dev *cdev = c->cdev;
struct f_sourcesink *ss = func_to_ss(f);
int id;
+ int ret;
/* allocate interface ID(s) */
id = usb_interface_id(c, f);
@@ -387,64 +388,57 @@ no_iso:
isoc_maxpacket = 1024;
/* support high speed hardware */
- if (gadget_is_dualspeed(c->cdev->gadget)) {
- hs_source_desc.bEndpointAddress =
- fs_source_desc.bEndpointAddress;
- hs_sink_desc.bEndpointAddress =
- fs_sink_desc.bEndpointAddress;
+ hs_source_desc.bEndpointAddress = fs_source_desc.bEndpointAddress;
+ hs_sink_desc.bEndpointAddress = fs_sink_desc.bEndpointAddress;
- /*
- * Fill in the HS isoc descriptors from the module parameters.
- * We assume that the user knows what they are doing and won't
- * give parameters that their UDC doesn't support.
- */
- hs_iso_source_desc.wMaxPacketSize = isoc_maxpacket;
- hs_iso_source_desc.wMaxPacketSize |= isoc_mult << 11;
- hs_iso_source_desc.bInterval = isoc_interval;
- hs_iso_source_desc.bEndpointAddress =
- fs_iso_source_desc.bEndpointAddress;
-
- hs_iso_sink_desc.wMaxPacketSize = isoc_maxpacket;
- hs_iso_sink_desc.wMaxPacketSize |= isoc_mult << 11;
- hs_iso_sink_desc.bInterval = isoc_interval;
- hs_iso_sink_desc.bEndpointAddress =
- fs_iso_sink_desc.bEndpointAddress;
-
- f->hs_descriptors = hs_source_sink_descs;
- }
+ /*
+ * Fill in the HS isoc descriptors from the module parameters.
+ * We assume that the user knows what they are doing and won't
+ * give parameters that their UDC doesn't support.
+ */
+ hs_iso_source_desc.wMaxPacketSize = isoc_maxpacket;
+ hs_iso_source_desc.wMaxPacketSize |= isoc_mult << 11;
+ hs_iso_source_desc.bInterval = isoc_interval;
+ hs_iso_source_desc.bEndpointAddress =
+ fs_iso_source_desc.bEndpointAddress;
+
+ hs_iso_sink_desc.wMaxPacketSize = isoc_maxpacket;
+ hs_iso_sink_desc.wMaxPacketSize |= isoc_mult << 11;
+ hs_iso_sink_desc.bInterval = isoc_interval;
+ hs_iso_sink_desc.bEndpointAddress = fs_iso_sink_desc.bEndpointAddress;
/* support super speed hardware */
- if (gadget_is_superspeed(c->cdev->gadget)) {
- ss_source_desc.bEndpointAddress =
- fs_source_desc.bEndpointAddress;
- ss_sink_desc.bEndpointAddress =
- fs_sink_desc.bEndpointAddress;
+ ss_source_desc.bEndpointAddress =
+ fs_source_desc.bEndpointAddress;
+ ss_sink_desc.bEndpointAddress =
+ fs_sink_desc.bEndpointAddress;
- /*
- * Fill in the SS isoc descriptors from the module parameters.
- * We assume that the user knows what they are doing and won't
- * give parameters that their UDC doesn't support.
- */
- ss_iso_source_desc.wMaxPacketSize = isoc_maxpacket;
- ss_iso_source_desc.bInterval = isoc_interval;
- ss_iso_source_comp_desc.bmAttributes = isoc_mult;
- ss_iso_source_comp_desc.bMaxBurst = isoc_maxburst;
- ss_iso_source_comp_desc.wBytesPerInterval =
- isoc_maxpacket * (isoc_mult + 1) * (isoc_maxburst + 1);
- ss_iso_source_desc.bEndpointAddress =
- fs_iso_source_desc.bEndpointAddress;
-
- ss_iso_sink_desc.wMaxPacketSize = isoc_maxpacket;
- ss_iso_sink_desc.bInterval = isoc_interval;
- ss_iso_sink_comp_desc.bmAttributes = isoc_mult;
- ss_iso_sink_comp_desc.bMaxBurst = isoc_maxburst;
- ss_iso_sink_comp_desc.wBytesPerInterval =
- isoc_maxpacket * (isoc_mult + 1) * (isoc_maxburst + 1);
- ss_iso_sink_desc.bEndpointAddress =
- fs_iso_sink_desc.bEndpointAddress;
-
- f->ss_descriptors = ss_source_sink_descs;
- }
+ /*
+ * Fill in the SS isoc descriptors from the module parameters.
+ * We assume that the user knows what they are doing and won't
+ * give parameters that their UDC doesn't support.
+ */
+ ss_iso_source_desc.wMaxPacketSize = isoc_maxpacket;
+ ss_iso_source_desc.bInterval = isoc_interval;
+ ss_iso_source_comp_desc.bmAttributes = isoc_mult;
+ ss_iso_source_comp_desc.bMaxBurst = isoc_maxburst;
+ ss_iso_source_comp_desc.wBytesPerInterval =
+ isoc_maxpacket * (isoc_mult + 1) * (isoc_maxburst + 1);
+ ss_iso_source_desc.bEndpointAddress =
+ fs_iso_source_desc.bEndpointAddress;
+
+ ss_iso_sink_desc.wMaxPacketSize = isoc_maxpacket;
+ ss_iso_sink_desc.bInterval = isoc_interval;
+ ss_iso_sink_comp_desc.bmAttributes = isoc_mult;
+ ss_iso_sink_comp_desc.bMaxBurst = isoc_maxburst;
+ ss_iso_sink_comp_desc.wBytesPerInterval =
+ isoc_maxpacket * (isoc_mult + 1) * (isoc_maxburst + 1);
+ ss_iso_sink_desc.bEndpointAddress = fs_iso_sink_desc.bEndpointAddress;
+
+ ret = usb_assign_descriptors(f, fs_source_sink_descs,
+ hs_source_sink_descs, ss_source_sink_descs);
+ if (ret)
+ return ret;
DBG(cdev, "%s speed %s: IN/%s, OUT/%s, ISO-IN/%s, ISO-OUT/%s\n",
(gadget_is_superspeed(c->cdev->gadget) ? "super" :
@@ -458,6 +452,7 @@ no_iso:
static void
sourcesink_unbind(struct usb_configuration *c, struct usb_function *f)
{
+ usb_free_all_descriptors(f);
kfree(func_to_ss(f));
}
@@ -773,7 +768,6 @@ static int __init sourcesink_bind_config(struct usb_configuration *c)
return -ENOMEM;
ss->function.name = "source/sink";
- ss->function.descriptors = fs_source_sink_descs;
ss->function.bind = sourcesink_bind;
ss->function.unbind = sourcesink_unbind;
ss->function.set_alt = sourcesink_set_alt;
diff --git a/drivers/usb/gadget/f_subset.c b/drivers/usb/gadget/f_subset.c
index 4060c0bd9785..f172bd152fbb 100644
--- a/drivers/usb/gadget/f_subset.c
+++ b/drivers/usb/gadget/f_subset.c
@@ -236,7 +236,7 @@ static struct usb_descriptor_header *ss_eth_function[] = {
static struct usb_string geth_string_defs[] = {
[0].s = "CDC Ethernet Subset/SAFE",
- [1].s = NULL /* DYNAMIC */,
+ [1].s = "",
{ } /* end of list */
};
@@ -319,38 +319,22 @@ geth_bind(struct usb_configuration *c, struct usb_function *f)
geth->port.out_ep = ep;
ep->driver_data = cdev; /* claim */
- /* copy descriptors, and track endpoint copies */
- f->descriptors = usb_copy_descriptors(fs_eth_function);
- if (!f->descriptors)
- goto fail;
-
/* support all relevant hardware speeds... we expect that when
* hardware is dual speed, all bulk-capable endpoints work at
* both speeds
*/
- if (gadget_is_dualspeed(c->cdev->gadget)) {
- hs_subset_in_desc.bEndpointAddress =
- fs_subset_in_desc.bEndpointAddress;
- hs_subset_out_desc.bEndpointAddress =
- fs_subset_out_desc.bEndpointAddress;
-
- /* copy descriptors, and track endpoint copies */
- f->hs_descriptors = usb_copy_descriptors(hs_eth_function);
- if (!f->hs_descriptors)
- goto fail;
- }
+ hs_subset_in_desc.bEndpointAddress = fs_subset_in_desc.bEndpointAddress;
+ hs_subset_out_desc.bEndpointAddress =
+ fs_subset_out_desc.bEndpointAddress;
- if (gadget_is_superspeed(c->cdev->gadget)) {
- ss_subset_in_desc.bEndpointAddress =
- fs_subset_in_desc.bEndpointAddress;
- ss_subset_out_desc.bEndpointAddress =
- fs_subset_out_desc.bEndpointAddress;
+ ss_subset_in_desc.bEndpointAddress = fs_subset_in_desc.bEndpointAddress;
+ ss_subset_out_desc.bEndpointAddress =
+ fs_subset_out_desc.bEndpointAddress;
- /* copy descriptors, and track endpoint copies */
- f->ss_descriptors = usb_copy_descriptors(ss_eth_function);
- if (!f->ss_descriptors)
- goto fail;
- }
+ status = usb_assign_descriptors(f, fs_eth_function, hs_eth_function,
+ ss_eth_function);
+ if (status)
+ goto fail;
/* NOTE: all that is done without knowing or caring about
* the network link ... which is unavailable to this code
@@ -364,15 +348,11 @@ geth_bind(struct usb_configuration *c, struct usb_function *f)
return 0;
fail:
- if (f->descriptors)
- usb_free_descriptors(f->descriptors);
- if (f->hs_descriptors)
- usb_free_descriptors(f->hs_descriptors);
-
+ usb_free_all_descriptors(f);
/* we might as well release our claims on endpoints */
- if (geth->port.out_ep->desc)
+ if (geth->port.out_ep)
geth->port.out_ep->driver_data = NULL;
- if (geth->port.in_ep->desc)
+ if (geth->port.in_ep)
geth->port.in_ep->driver_data = NULL;
ERROR(cdev, "%s: can't bind, err %d\n", f->name, status);
@@ -383,12 +363,8 @@ fail:
static void
geth_unbind(struct usb_configuration *c, struct usb_function *f)
{
- if (gadget_is_superspeed(c->cdev->gadget))
- usb_free_descriptors(f->ss_descriptors);
- if (gadget_is_dualspeed(c->cdev->gadget))
- usb_free_descriptors(f->hs_descriptors);
- usb_free_descriptors(f->descriptors);
- geth_string_defs[1].s = NULL;
+ geth_string_defs[0].id = 0;
+ usb_free_all_descriptors(f);
kfree(func_to_geth(f));
}
@@ -414,20 +390,11 @@ int geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
/* maybe allocate device-global string IDs */
if (geth_string_defs[0].id == 0) {
-
- /* interface label */
- status = usb_string_id(c->cdev);
+ status = usb_string_ids_tab(c->cdev, geth_string_defs);
if (status < 0)
return status;
- geth_string_defs[0].id = status;
- subset_data_intf.iInterface = status;
-
- /* MAC address */
- status = usb_string_id(c->cdev);
- if (status < 0)
- return status;
- geth_string_defs[1].id = status;
- ether_desc.iMACAddress = status;
+ subset_data_intf.iInterface = geth_string_defs[0].id;
+ ether_desc.iMACAddress = geth_string_defs[1].id;
}
/* allocate and initialize one new instance */
@@ -449,9 +416,7 @@ int geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
geth->port.func.disable = geth_disable;
status = usb_add_function(c, &geth->port.func);
- if (status) {
- geth_string_defs[1].s = NULL;
+ if (status)
kfree(geth);
- }
return status;
}
diff --git a/drivers/usb/gadget/f_uac1.c b/drivers/usb/gadget/f_uac1.c
index 1a5dcd5565e3..f570e667a640 100644
--- a/drivers/usb/gadget/f_uac1.c
+++ b/drivers/usb/gadget/f_uac1.c
@@ -630,7 +630,7 @@ f_audio_bind(struct usb_configuration *c, struct usb_function *f)
struct usb_composite_dev *cdev = c->cdev;
struct f_audio *audio = func_to_audio(f);
int status;
- struct usb_ep *ep;
+ struct usb_ep *ep = NULL;
f_audio_build_desc(audio);
@@ -659,22 +659,14 @@ f_audio_bind(struct usb_configuration *c, struct usb_function *f)
status = -ENOMEM;
/* copy descriptors, and track endpoint copies */
- f->descriptors = usb_copy_descriptors(f_audio_desc);
-
- /*
- * support all relevant hardware speeds... we expect that when
- * hardware is dual speed, all bulk-capable endpoints work at
- * both speeds
- */
- if (gadget_is_dualspeed(c->cdev->gadget)) {
- c->highspeed = true;
- f->hs_descriptors = usb_copy_descriptors(f_audio_desc);
- }
-
+ status = usb_assign_descriptors(f, f_audio_desc, f_audio_desc, NULL);
+ if (status)
+ goto fail;
return 0;
fail:
-
+ if (ep)
+ ep->driver_data = NULL;
return status;
}
@@ -683,8 +675,7 @@ f_audio_unbind(struct usb_configuration *c, struct usb_function *f)
{
struct f_audio *audio = func_to_audio(f);
- usb_free_descriptors(f->descriptors);
- usb_free_descriptors(f->hs_descriptors);
+ usb_free_all_descriptors(f);
kfree(audio);
}
diff --git a/drivers/usb/gadget/f_uac2.c b/drivers/usb/gadget/f_uac2.c
index d3c6cffccb72..d7da258fa3f6 100644
--- a/drivers/usb/gadget/f_uac2.c
+++ b/drivers/usb/gadget/f_uac2.c
@@ -50,13 +50,6 @@ static int c_ssize = 2;
module_param(c_ssize, uint, S_IRUGO);
MODULE_PARM_DESC(c_ssize, "Capture Sample Size(bytes)");
-#define DMA_ADDR_INVALID (~(dma_addr_t)0)
-
-#define ALT_SET(x, a) do {(x) &= ~0xff; (x) |= (a); } while (0)
-#define ALT_GET(x) ((x) & 0xff)
-#define INTF_SET(x, i) do {(x) &= 0xff; (x) |= ((i) << 8); } while (0)
-#define INTF_GET(x) ((x >> 8) & 0xff)
-
/* Keep everyone on toes */
#define USB_XFERS 2
@@ -144,8 +137,9 @@ static struct snd_pcm_hardware uac2_pcm_hardware = {
};
struct audio_dev {
- /* Currently active {Interface[15:8] | AltSettings[7:0]} */
- __u16 ac_alt, as_out_alt, as_in_alt;
+ u8 ac_intf, ac_alt;
+ u8 as_out_intf, as_out_alt;
+ u8 as_in_intf, as_in_alt;
struct usb_ep *in_ep, *out_ep;
struct usb_function func;
@@ -408,7 +402,7 @@ static struct snd_pcm_ops uac2_pcm_ops = {
.prepare = uac2_pcm_null,
};
-static int __devinit snd_uac2_probe(struct platform_device *pdev)
+static int snd_uac2_probe(struct platform_device *pdev)
{
struct snd_uac2_chip *uac2 = pdev_to_uac2(pdev);
struct snd_card *card;
@@ -526,32 +520,22 @@ enum {
STR_AS_IN_ALT1,
};
-static const char ifassoc[] = "Source/Sink";
-static const char ifctrl[] = "Topology Control";
static char clksrc_in[8];
static char clksrc_out[8];
-static const char usb_it[] = "USBH Out";
-static const char io_it[] = "USBD Out";
-static const char usb_ot[] = "USBH In";
-static const char io_ot[] = "USBD In";
-static const char out_alt0[] = "Playback Inactive";
-static const char out_alt1[] = "Playback Active";
-static const char in_alt0[] = "Capture Inactive";
-static const char in_alt1[] = "Capture Active";
static struct usb_string strings_fn[] = {
- [STR_ASSOC].s = ifassoc,
- [STR_IF_CTRL].s = ifctrl,
+ [STR_ASSOC].s = "Source/Sink",
+ [STR_IF_CTRL].s = "Topology Control",
[STR_CLKSRC_IN].s = clksrc_in,
[STR_CLKSRC_OUT].s = clksrc_out,
- [STR_USB_IT].s = usb_it,
- [STR_IO_IT].s = io_it,
- [STR_USB_OT].s = usb_ot,
- [STR_IO_OT].s = io_ot,
- [STR_AS_OUT_ALT0].s = out_alt0,
- [STR_AS_OUT_ALT1].s = out_alt1,
- [STR_AS_IN_ALT0].s = in_alt0,
- [STR_AS_IN_ALT1].s = in_alt1,
+ [STR_USB_IT].s = "USBH Out",
+ [STR_IO_IT].s = "USBD Out",
+ [STR_USB_OT].s = "USBH In",
+ [STR_IO_OT].s = "USBD In",
+ [STR_AS_OUT_ALT0].s = "Playback Inactive",
+ [STR_AS_OUT_ALT1].s = "Playback Active",
+ [STR_AS_IN_ALT0].s = "Capture Inactive",
+ [STR_AS_IN_ALT1].s = "Capture Active",
{ },
};
@@ -952,8 +936,8 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)
return ret;
}
std_ac_if_desc.bInterfaceNumber = ret;
- ALT_SET(agdev->ac_alt, 0);
- INTF_SET(agdev->ac_alt, ret);
+ agdev->ac_intf = ret;
+ agdev->ac_alt = 0;
ret = usb_interface_id(cfg, fn);
if (ret < 0) {
@@ -963,8 +947,8 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)
}
std_as_out_if0_desc.bInterfaceNumber = ret;
std_as_out_if1_desc.bInterfaceNumber = ret;
- ALT_SET(agdev->as_out_alt, 0);
- INTF_SET(agdev->as_out_alt, ret);
+ agdev->as_out_intf = ret;
+ agdev->as_out_alt = 0;
ret = usb_interface_id(cfg, fn);
if (ret < 0) {
@@ -974,19 +958,23 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)
}
std_as_in_if0_desc.bInterfaceNumber = ret;
std_as_in_if1_desc.bInterfaceNumber = ret;
- ALT_SET(agdev->as_in_alt, 0);
- INTF_SET(agdev->as_in_alt, ret);
+ agdev->as_in_intf = ret;
+ agdev->as_in_alt = 0;
agdev->out_ep = usb_ep_autoconfig(gadget, &fs_epout_desc);
- if (!agdev->out_ep)
+ if (!agdev->out_ep) {
dev_err(&uac2->pdev.dev,
"%s:%d Error!\n", __func__, __LINE__);
+ goto err;
+ }
agdev->out_ep->driver_data = agdev;
agdev->in_ep = usb_ep_autoconfig(gadget, &fs_epin_desc);
- if (!agdev->in_ep)
+ if (!agdev->in_ep) {
dev_err(&uac2->pdev.dev,
"%s:%d Error!\n", __func__, __LINE__);
+ goto err;
+ }
agdev->in_ep->driver_data = agdev;
hs_epout_desc.bEndpointAddress = fs_epout_desc.bEndpointAddress;
@@ -994,9 +982,9 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)
hs_epin_desc.bEndpointAddress = fs_epin_desc.bEndpointAddress;
hs_epin_desc.wMaxPacketSize = fs_epin_desc.wMaxPacketSize;
- fn->descriptors = usb_copy_descriptors(fs_audio_desc);
- if (gadget_is_dualspeed(gadget))
- fn->hs_descriptors = usb_copy_descriptors(hs_audio_desc);
+ ret = usb_assign_descriptors(fn, fs_audio_desc, hs_audio_desc, NULL);
+ if (ret)
+ goto err;
prm = &agdev->uac2.c_prm;
prm->max_psize = hs_epout_desc.wMaxPacketSize;
@@ -1005,6 +993,7 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)
prm->max_psize = 0;
dev_err(&uac2->pdev.dev,
"%s:%d Error!\n", __func__, __LINE__);
+ goto err;
}
prm = &agdev->uac2.p_prm;
@@ -1014,17 +1003,28 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)
prm->max_psize = 0;
dev_err(&uac2->pdev.dev,
"%s:%d Error!\n", __func__, __LINE__);
+ goto err;
}
- return alsa_uac2_init(agdev);
+ ret = alsa_uac2_init(agdev);
+ if (ret)
+ goto err;
+ return 0;
+err:
+ kfree(agdev->uac2.p_prm.rbuf);
+ kfree(agdev->uac2.c_prm.rbuf);
+ usb_free_all_descriptors(fn);
+ if (agdev->in_ep)
+ agdev->in_ep->driver_data = NULL;
+ if (agdev->out_ep)
+ agdev->out_ep->driver_data = NULL;
+ return -EINVAL;
}
static void
afunc_unbind(struct usb_configuration *cfg, struct usb_function *fn)
{
struct audio_dev *agdev = func_to_agdev(fn);
- struct usb_composite_dev *cdev = cfg->cdev;
- struct usb_gadget *gadget = cdev->gadget;
struct uac2_rtd_params *prm;
alsa_uac2_exit(agdev);
@@ -1034,10 +1034,7 @@ afunc_unbind(struct usb_configuration *cfg, struct usb_function *fn)
prm = &agdev->uac2.c_prm;
kfree(prm->rbuf);
-
- if (gadget_is_dualspeed(gadget))
- usb_free_descriptors(fn->hs_descriptors);
- usb_free_descriptors(fn->descriptors);
+ usb_free_all_descriptors(fn);
if (agdev->in_ep)
agdev->in_ep->driver_data = NULL;
@@ -1064,7 +1061,7 @@ afunc_set_alt(struct usb_function *fn, unsigned intf, unsigned alt)
return -EINVAL;
}
- if (intf == INTF_GET(agdev->ac_alt)) {
+ if (intf == agdev->ac_intf) {
/* Control I/f has only 1 AltSetting - 0 */
if (alt) {
dev_err(&uac2->pdev.dev,
@@ -1074,16 +1071,16 @@ afunc_set_alt(struct usb_function *fn, unsigned intf, unsigned alt)
return 0;
}
- if (intf == INTF_GET(agdev->as_out_alt)) {
+ if (intf == agdev->as_out_intf) {
ep = agdev->out_ep;
prm = &uac2->c_prm;
config_ep_by_speed(gadget, fn, ep);
- ALT_SET(agdev->as_out_alt, alt);
- } else if (intf == INTF_GET(agdev->as_in_alt)) {
+ agdev->as_out_alt = alt;
+ } else if (intf == agdev->as_in_intf) {
ep = agdev->in_ep;
prm = &uac2->p_prm;
config_ep_by_speed(gadget, fn, ep);
- ALT_SET(agdev->as_in_alt, alt);
+ agdev->as_in_alt = alt;
} else {
dev_err(&uac2->pdev.dev,
"%s:%d Error!\n", __func__, __LINE__);
@@ -1117,7 +1114,6 @@ afunc_set_alt(struct usb_function *fn, unsigned intf, unsigned alt)
prm->ureq[i].pp = prm;
req->zero = 0;
- req->dma = DMA_ADDR_INVALID;
req->context = &prm->ureq[i];
req->length = prm->max_psize;
req->complete = agdev_iso_complete;
@@ -1136,12 +1132,12 @@ afunc_get_alt(struct usb_function *fn, unsigned intf)
struct audio_dev *agdev = func_to_agdev(fn);
struct snd_uac2_chip *uac2 = &agdev->uac2;
- if (intf == INTF_GET(agdev->ac_alt))
- return ALT_GET(agdev->ac_alt);
- else if (intf == INTF_GET(agdev->as_out_alt))
- return ALT_GET(agdev->as_out_alt);
- else if (intf == INTF_GET(agdev->as_in_alt))
- return ALT_GET(agdev->as_in_alt);
+ if (intf == agdev->ac_intf)
+ return agdev->ac_alt;
+ else if (intf == agdev->as_out_intf)
+ return agdev->as_out_alt;
+ else if (intf == agdev->as_in_intf)
+ return agdev->as_in_alt;
else
dev_err(&uac2->pdev.dev,
"%s:%d Invalid Interface %d!\n",
@@ -1157,10 +1153,10 @@ afunc_disable(struct usb_function *fn)
struct snd_uac2_chip *uac2 = &agdev->uac2;
free_ep(&uac2->p_prm, agdev->in_ep);
- ALT_SET(agdev->as_in_alt, 0);
+ agdev->as_in_alt = 0;
free_ep(&uac2->c_prm, agdev->out_ep);
- ALT_SET(agdev->as_out_alt, 0);
+ agdev->as_out_alt = 0;
}
static int
@@ -1267,7 +1263,7 @@ setup_rq_inf(struct usb_function *fn, const struct usb_ctrlrequest *cr)
u16 w_index = le16_to_cpu(cr->wIndex);
u8 intf = w_index & 0xff;
- if (intf != INTF_GET(agdev->ac_alt)) {
+ if (intf != agdev->ac_intf) {
dev_err(&uac2->pdev.dev,
"%s:%d Error!\n", __func__, __LINE__);
return -EOPNOTSUPP;
@@ -1316,7 +1312,7 @@ afunc_setup(struct usb_function *fn, const struct usb_ctrlrequest *cr)
static int audio_bind_config(struct usb_configuration *cfg)
{
- int id, res;
+ int res;
agdev_g = kzalloc(sizeof *agdev_g, GFP_KERNEL);
if (agdev_g == NULL) {
@@ -1324,89 +1320,21 @@ static int audio_bind_config(struct usb_configuration *cfg)
return -ENOMEM;
}
- id = usb_string_id(cfg->cdev);
- if (id < 0)
- return id;
-
- strings_fn[STR_ASSOC].id = id;
- iad_desc.iFunction = id,
-
- id = usb_string_id(cfg->cdev);
- if (id < 0)
- return id;
-
- strings_fn[STR_IF_CTRL].id = id;
- std_ac_if_desc.iInterface = id,
-
- id = usb_string_id(cfg->cdev);
- if (id < 0)
- return id;
-
- strings_fn[STR_CLKSRC_IN].id = id;
- in_clk_src_desc.iClockSource = id,
-
- id = usb_string_id(cfg->cdev);
- if (id < 0)
- return id;
-
- strings_fn[STR_CLKSRC_OUT].id = id;
- out_clk_src_desc.iClockSource = id,
-
- id = usb_string_id(cfg->cdev);
- if (id < 0)
- return id;
-
- strings_fn[STR_USB_IT].id = id;
- usb_out_it_desc.iTerminal = id,
-
- id = usb_string_id(cfg->cdev);
- if (id < 0)
- return id;
-
- strings_fn[STR_IO_IT].id = id;
- io_in_it_desc.iTerminal = id;
-
- id = usb_string_id(cfg->cdev);
- if (id < 0)
- return id;
-
- strings_fn[STR_USB_OT].id = id;
- usb_in_ot_desc.iTerminal = id;
-
- id = usb_string_id(cfg->cdev);
- if (id < 0)
- return id;
-
- strings_fn[STR_IO_OT].id = id;
- io_out_ot_desc.iTerminal = id;
-
- id = usb_string_id(cfg->cdev);
- if (id < 0)
- return id;
-
- strings_fn[STR_AS_OUT_ALT0].id = id;
- std_as_out_if0_desc.iInterface = id;
-
- id = usb_string_id(cfg->cdev);
- if (id < 0)
- return id;
-
- strings_fn[STR_AS_OUT_ALT1].id = id;
- std_as_out_if1_desc.iInterface = id;
-
- id = usb_string_id(cfg->cdev);
- if (id < 0)
- return id;
-
- strings_fn[STR_AS_IN_ALT0].id = id;
- std_as_in_if0_desc.iInterface = id;
-
- id = usb_string_id(cfg->cdev);
- if (id < 0)
- return id;
-
- strings_fn[STR_AS_IN_ALT1].id = id;
- std_as_in_if1_desc.iInterface = id;
+ res = usb_string_ids_tab(cfg->cdev, strings_fn);
+ if (res)
+ return res;
+ iad_desc.iFunction = strings_fn[STR_ASSOC].id;
+ std_ac_if_desc.iInterface = strings_fn[STR_IF_CTRL].id;
+ in_clk_src_desc.iClockSource = strings_fn[STR_CLKSRC_IN].id;
+ out_clk_src_desc.iClockSource = strings_fn[STR_CLKSRC_OUT].id;
+ usb_out_it_desc.iTerminal = strings_fn[STR_USB_IT].id;
+ io_in_it_desc.iTerminal = strings_fn[STR_IO_IT].id;
+ usb_in_ot_desc.iTerminal = strings_fn[STR_USB_OT].id;
+ io_out_ot_desc.iTerminal = strings_fn[STR_IO_OT].id;
+ std_as_out_if0_desc.iInterface = strings_fn[STR_AS_OUT_ALT0].id;
+ std_as_out_if1_desc.iInterface = strings_fn[STR_AS_OUT_ALT1].id;
+ std_as_in_if0_desc.iInterface = strings_fn[STR_AS_IN_ALT0].id;
+ std_as_in_if1_desc.iInterface = strings_fn[STR_AS_IN_ALT1].id;
agdev_g->func.name = "uac2_func";
agdev_g->func.strings = fn_strings;
diff --git a/drivers/usb/gadget/f_uvc.c b/drivers/usb/gadget/f_uvc.c
index 2a8bf0655c60..5b629876941b 100644
--- a/drivers/usb/gadget/f_uvc.c
+++ b/drivers/usb/gadget/f_uvc.c
@@ -417,7 +417,6 @@ uvc_register_video(struct uvc_device *uvc)
return -ENOMEM;
video->parent = &cdev->gadget->dev;
- video->minor = -1;
video->fops = &uvc_v4l2_fops;
video->release = video_device_release;
strncpy(video->name, cdev->gadget->name, sizeof(video->name));
@@ -577,27 +576,15 @@ uvc_function_unbind(struct usb_configuration *c, struct usb_function *f)
INFO(cdev, "uvc_function_unbind\n");
- if (uvc->vdev) {
- if (uvc->vdev->minor == -1)
- video_device_release(uvc->vdev);
- else
- video_unregister_device(uvc->vdev);
- uvc->vdev = NULL;
- }
+ video_unregister_device(uvc->vdev);
+ uvc->control_ep->driver_data = NULL;
+ uvc->video.ep->driver_data = NULL;
- if (uvc->control_ep)
- uvc->control_ep->driver_data = NULL;
- if (uvc->video.ep)
- uvc->video.ep->driver_data = NULL;
-
- if (uvc->control_req) {
- usb_ep_free_request(cdev->gadget->ep0, uvc->control_req);
- kfree(uvc->control_buf);
- }
+ uvc_en_us_strings[UVC_STRING_ASSOCIATION_IDX].id = 0;
+ usb_ep_free_request(cdev->gadget->ep0, uvc->control_req);
+ kfree(uvc->control_buf);
- kfree(f->descriptors);
- kfree(f->hs_descriptors);
- kfree(f->ss_descriptors);
+ usb_free_all_descriptors(f);
kfree(uvc);
}
@@ -663,49 +650,40 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f)
/* sanity check the streaming endpoint module parameters */
if (streaming_maxpacket > 1024)
streaming_maxpacket = 1024;
+ /*
+ * Fill in the HS descriptors from the module parameters for the Video
+ * Streaming endpoint.
+ * NOTE: We assume that the user knows what they are doing and won't
+ * give parameters that their UDC doesn't support.
+ */
+ uvc_hs_streaming_ep.wMaxPacketSize = streaming_maxpacket;
+ uvc_hs_streaming_ep.wMaxPacketSize |= streaming_mult << 11;
+ uvc_hs_streaming_ep.bInterval = streaming_interval;
+ uvc_hs_streaming_ep.bEndpointAddress =
+ uvc_fs_streaming_ep.bEndpointAddress;
- /* Copy descriptors for FS. */
- f->descriptors = uvc_copy_descriptors(uvc, USB_SPEED_FULL);
-
- /* support high speed hardware */
- if (gadget_is_dualspeed(cdev->gadget)) {
- /*
- * Fill in the HS descriptors from the module parameters for the
- * Video Streaming endpoint.
- * NOTE: We assume that the user knows what they are doing and
- * won't give parameters that their UDC doesn't support.
- */
- uvc_hs_streaming_ep.wMaxPacketSize = streaming_maxpacket;
- uvc_hs_streaming_ep.wMaxPacketSize |= streaming_mult << 11;
- uvc_hs_streaming_ep.bInterval = streaming_interval;
- uvc_hs_streaming_ep.bEndpointAddress =
- uvc_fs_streaming_ep.bEndpointAddress;
-
- /* Copy descriptors. */
- f->hs_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_HIGH);
- }
+ /*
+ * Fill in the SS descriptors from the module parameters for the Video
+ * Streaming endpoint.
+ * NOTE: We assume that the user knows what they are doing and won't
+ * give parameters that their UDC doesn't support.
+ */
+ uvc_ss_streaming_ep.wMaxPacketSize = streaming_maxpacket;
+ uvc_ss_streaming_ep.bInterval = streaming_interval;
+ uvc_ss_streaming_comp.bmAttributes = streaming_mult;
+ uvc_ss_streaming_comp.bMaxBurst = streaming_maxburst;
+ uvc_ss_streaming_comp.wBytesPerInterval =
+ streaming_maxpacket * (streaming_mult + 1) *
+ (streaming_maxburst + 1);
+ uvc_ss_streaming_ep.bEndpointAddress =
+ uvc_fs_streaming_ep.bEndpointAddress;
- /* support super speed hardware */
- if (gadget_is_superspeed(c->cdev->gadget)) {
- /*
- * Fill in the SS descriptors from the module parameters for the
- * Video Streaming endpoint.
- * NOTE: We assume that the user knows what they are doing and
- * won't give parameters that their UDC doesn't support.
- */
- uvc_ss_streaming_ep.wMaxPacketSize = streaming_maxpacket;
- uvc_ss_streaming_ep.bInterval = streaming_interval;
- uvc_ss_streaming_comp.bmAttributes = streaming_mult;
- uvc_ss_streaming_comp.bMaxBurst = streaming_maxburst;
- uvc_ss_streaming_comp.wBytesPerInterval =
- streaming_maxpacket * (streaming_mult + 1) *
- (streaming_maxburst + 1);
- uvc_ss_streaming_ep.bEndpointAddress =
- uvc_fs_streaming_ep.bEndpointAddress;
-
- /* Copy descriptors. */
+ /* Copy descriptors */
+ f->fs_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_FULL);
+ if (gadget_is_dualspeed(cdev->gadget))
+ f->hs_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_HIGH);
+ if (gadget_is_superspeed(c->cdev->gadget))
f->ss_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_SUPER);
- }
/* Preallocate control endpoint request. */
uvc->control_req = usb_ep_alloc_request(cdev->gadget->ep0, GFP_KERNEL);
@@ -740,7 +718,20 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f)
return 0;
error:
- uvc_function_unbind(c, f);
+ if (uvc->vdev)
+ video_device_release(uvc->vdev);
+
+ if (uvc->control_ep)
+ uvc->control_ep->driver_data = NULL;
+ if (uvc->video.ep)
+ uvc->video.ep->driver_data = NULL;
+
+ if (uvc->control_req) {
+ usb_ep_free_request(cdev->gadget->ep0, uvc->control_req);
+ kfree(uvc->control_buf);
+ }
+
+ usb_free_all_descriptors(f);
return ret;
}
@@ -808,25 +799,16 @@ uvc_bind_config(struct usb_configuration *c,
uvc->desc.hs_streaming = hs_streaming;
uvc->desc.ss_streaming = ss_streaming;
- /* maybe allocate device-global string IDs, and patch descriptors */
+ /* Allocate string descriptor numbers. */
if (uvc_en_us_strings[UVC_STRING_ASSOCIATION_IDX].id == 0) {
- /* Allocate string descriptor numbers. */
- ret = usb_string_id(c->cdev);
- if (ret < 0)
- goto error;
- uvc_en_us_strings[UVC_STRING_ASSOCIATION_IDX].id = ret;
- uvc_iad.iFunction = ret;
-
- ret = usb_string_id(c->cdev);
- if (ret < 0)
- goto error;
- uvc_en_us_strings[UVC_STRING_CONTROL_IDX].id = ret;
- uvc_control_intf.iInterface = ret;
-
- ret = usb_string_id(c->cdev);
- if (ret < 0)
+ ret = usb_string_ids_tab(c->cdev, uvc_en_us_strings);
+ if (ret)
goto error;
- uvc_en_us_strings[UVC_STRING_STREAMING_IDX].id = ret;
+ uvc_iad.iFunction =
+ uvc_en_us_strings[UVC_STRING_ASSOCIATION_IDX].id;
+ uvc_control_intf.iInterface =
+ uvc_en_us_strings[UVC_STRING_CONTROL_IDX].id;
+ ret = uvc_en_us_strings[UVC_STRING_STREAMING_IDX].id;
uvc_streaming_intf_alt0.iInterface = ret;
uvc_streaming_intf_alt1.iInterface = ret;
}
diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
deleted file mode 100644
index 3f7d640b6758..000000000000
--- a/drivers/usb/gadget/file_storage.c
+++ /dev/null
@@ -1,3656 +0,0 @@
-/*
- * file_storage.c -- File-backed USB Storage Gadget, for USB development
- *
- * Copyright (C) 2003-2008 Alan Stern
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions, and the following disclaimer,
- * without modification.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. The names of the above-listed copyright holders may not be used
- * to endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") as published by the Free Software
- * Foundation, either version 2 of that License or (at your option) any
- * later version.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-/*
- * The File-backed Storage Gadget acts as a USB Mass Storage device,
- * appearing to the host as a disk drive or as a CD-ROM drive. In addition
- * to providing an example of a genuinely useful gadget driver for a USB
- * device, it also illustrates a technique of double-buffering for increased
- * throughput. Last but not least, it gives an easy way to probe the
- * behavior of the Mass Storage drivers in a USB host.
- *
- * Backing storage is provided by a regular file or a block device, specified
- * by the "file" module parameter. Access can be limited to read-only by
- * setting the optional "ro" module parameter. (For CD-ROM emulation,
- * access is always read-only.) The gadget will indicate that it has
- * removable media if the optional "removable" module parameter is set.
- *
- * The gadget supports the Control-Bulk (CB), Control-Bulk-Interrupt (CBI),
- * and Bulk-Only (also known as Bulk-Bulk-Bulk or BBB) transports, selected
- * by the optional "transport" module parameter. It also supports the
- * following protocols: RBC (0x01), ATAPI or SFF-8020i (0x02), QIC-157 (0c03),
- * UFI (0x04), SFF-8070i (0x05), and transparent SCSI (0x06), selected by
- * the optional "protocol" module parameter. In addition, the default
- * Vendor ID, Product ID, release number and serial number can be overridden.
- *
- * There is support for multiple logical units (LUNs), each of which has
- * its own backing file. The number of LUNs can be set using the optional
- * "luns" module parameter (anywhere from 1 to 8), and the corresponding
- * files are specified using comma-separated lists for "file" and "ro".
- * The default number of LUNs is taken from the number of "file" elements;
- * it is 1 if "file" is not given. If "removable" is not set then a backing
- * file must be specified for each LUN. If it is set, then an unspecified
- * or empty backing filename means the LUN's medium is not loaded. Ideally
- * each LUN would be settable independently as a disk drive or a CD-ROM
- * drive, but currently all LUNs have to be the same type. The CD-ROM
- * emulation includes a single data track and no audio tracks; hence there
- * need be only one backing file per LUN.
- *
- * Requirements are modest; only a bulk-in and a bulk-out endpoint are
- * needed (an interrupt-out endpoint is also needed for CBI). The memory
- * requirement amounts to two 16K buffers, size configurable by a parameter.
- * Support is included for both full-speed and high-speed operation.
- *
- * Note that the driver is slightly non-portable in that it assumes a
- * single memory/DMA buffer will be useable for bulk-in, bulk-out, and
- * interrupt-in endpoints. With most device controllers this isn't an
- * issue, but there may be some with hardware restrictions that prevent
- * a buffer from being used by more than one endpoint.
- *
- * Module options:
- *
- * file=filename[,filename...]
- * Required if "removable" is not set, names of
- * the files or block devices used for
- * backing storage
- * serial=HHHH... Required serial number (string of hex chars)
- * ro=b[,b...] Default false, booleans for read-only access
- * removable Default false, boolean for removable media
- * luns=N Default N = number of filenames, number of
- * LUNs to support
- * nofua=b[,b...] Default false, booleans for ignore FUA flag
- * in SCSI WRITE(10,12) commands
- * stall Default determined according to the type of
- * USB device controller (usually true),
- * boolean to permit the driver to halt
- * bulk endpoints
- * cdrom Default false, boolean for whether to emulate
- * a CD-ROM drive
- * transport=XXX Default BBB, transport name (CB, CBI, or BBB)
- * protocol=YYY Default SCSI, protocol name (RBC, 8020 or
- * ATAPI, QIC, UFI, 8070, or SCSI;
- * also 1 - 6)
- * vendor=0xVVVV Default 0x0525 (NetChip), USB Vendor ID
- * product=0xPPPP Default 0xa4a5 (FSG), USB Product ID
- * release=0xRRRR Override the USB release number (bcdDevice)
- * buflen=N Default N=16384, buffer size used (will be
- * rounded down to a multiple of
- * PAGE_CACHE_SIZE)
- *
- * If CONFIG_USB_FILE_STORAGE_TEST is not set, only the "file", "serial", "ro",
- * "removable", "luns", "nofua", "stall", and "cdrom" options are available;
- * default values are used for everything else.
- *
- * The pathnames of the backing files and the ro settings are available in
- * the attribute files "file", "nofua", and "ro" in the lun<n> subdirectory of
- * the gadget's sysfs directory. If the "removable" option is set, writing to
- * these files will simulate ejecting/loading the medium (writing an empty
- * line means eject) and adjusting a write-enable tab. Changes to the ro
- * setting are not allowed when the medium is loaded or if CD-ROM emulation
- * is being used.
- *
- * This gadget driver is heavily based on "Gadget Zero" by David Brownell.
- * The driver's SCSI command interface was based on the "Information
- * technology - Small Computer System Interface - 2" document from
- * X3T9.2 Project 375D, Revision 10L, 7-SEP-93, available at
- * <http://www.t10.org/ftp/t10/drafts/s2/s2-r10l.pdf>. The single exception
- * is opcode 0x23 (READ FORMAT CAPACITIES), which was based on the
- * "Universal Serial Bus Mass Storage Class UFI Command Specification"
- * document, Revision 1.0, December 14, 1998, available at
- * <http://www.usb.org/developers/devclass_docs/usbmass-ufi10.pdf>.
- */
-
-
-/*
- * Driver Design
- *
- * The FSG driver is fairly straightforward. There is a main kernel
- * thread that handles most of the work. Interrupt routines field
- * callbacks from the controller driver: bulk- and interrupt-request
- * completion notifications, endpoint-0 events, and disconnect events.
- * Completion events are passed to the main thread by wakeup calls. Many
- * ep0 requests are handled at interrupt time, but SetInterface,
- * SetConfiguration, and device reset requests are forwarded to the
- * thread in the form of "exceptions" using SIGUSR1 signals (since they
- * should interrupt any ongoing file I/O operations).
- *
- * The thread's main routine implements the standard command/data/status
- * parts of a SCSI interaction. It and its subroutines are full of tests
- * for pending signals/exceptions -- all this polling is necessary since
- * the kernel has no setjmp/longjmp equivalents. (Maybe this is an
- * indication that the driver really wants to be running in userspace.)
- * An important point is that so long as the thread is alive it keeps an
- * open reference to the backing file. This will prevent unmounting
- * the backing file's underlying filesystem and could cause problems
- * during system shutdown, for example. To prevent such problems, the
- * thread catches INT, TERM, and KILL signals and converts them into
- * an EXIT exception.
- *
- * In normal operation the main thread is started during the gadget's
- * fsg_bind() callback and stopped during fsg_unbind(). But it can also
- * exit when it receives a signal, and there's no point leaving the
- * gadget running when the thread is dead. So just before the thread
- * exits, it deregisters the gadget driver. This makes things a little
- * tricky: The driver is deregistered at two places, and the exiting
- * thread can indirectly call fsg_unbind() which in turn can tell the
- * thread to exit. The first problem is resolved through the use of the
- * REGISTERED atomic bitflag; the driver will only be deregistered once.
- * The second problem is resolved by having fsg_unbind() check
- * fsg->state; it won't try to stop the thread if the state is already
- * FSG_STATE_TERMINATED.
- *
- * To provide maximum throughput, the driver uses a circular pipeline of
- * buffer heads (struct fsg_buffhd). In principle the pipeline can be
- * arbitrarily long; in practice the benefits don't justify having more
- * than 2 stages (i.e., double buffering). But it helps to think of the
- * pipeline as being a long one. Each buffer head contains a bulk-in and
- * a bulk-out request pointer (since the buffer can be used for both
- * output and input -- directions always are given from the host's
- * point of view) as well as a pointer to the buffer and various state
- * variables.
- *
- * Use of the pipeline follows a simple protocol. There is a variable
- * (fsg->next_buffhd_to_fill) that points to the next buffer head to use.
- * At any time that buffer head may still be in use from an earlier
- * request, so each buffer head has a state variable indicating whether
- * it is EMPTY, FULL, or BUSY. Typical use involves waiting for the
- * buffer head to be EMPTY, filling the buffer either by file I/O or by
- * USB I/O (during which the buffer head is BUSY), and marking the buffer
- * head FULL when the I/O is complete. Then the buffer will be emptied
- * (again possibly by USB I/O, during which it is marked BUSY) and
- * finally marked EMPTY again (possibly by a completion routine).
- *
- * A module parameter tells the driver to avoid stalling the bulk
- * endpoints wherever the transport specification allows. This is
- * necessary for some UDCs like the SuperH, which cannot reliably clear a
- * halt on a bulk endpoint. However, under certain circumstances the
- * Bulk-only specification requires a stall. In such cases the driver
- * will halt the endpoint and set a flag indicating that it should clear
- * the halt in software during the next device reset. Hopefully this
- * will permit everything to work correctly. Furthermore, although the
- * specification allows the bulk-out endpoint to halt when the host sends
- * too much data, implementing this would cause an unavoidable race.
- * The driver will always use the "no-stall" approach for OUT transfers.
- *
- * One subtle point concerns sending status-stage responses for ep0
- * requests. Some of these requests, such as device reset, can involve
- * interrupting an ongoing file I/O operation, which might take an
- * arbitrarily long time. During that delay the host might give up on
- * the original ep0 request and issue a new one. When that happens the
- * driver should not notify the host about completion of the original
- * request, as the host will no longer be waiting for it. So the driver
- * assigns to each ep0 request a unique tag, and it keeps track of the
- * tag value of the request associated with a long-running exception
- * (device-reset, interface-change, or configuration-change). When the
- * exception handler is finished, the status-stage response is submitted
- * only if the current ep0 request tag is equal to the exception request
- * tag. Thus only the most recently received ep0 request will get a
- * status-stage response.
- *
- * Warning: This driver source file is too long. It ought to be split up
- * into a header file plus about 3 separate .c files, to handle the details
- * of the Gadget, USB Mass Storage, and SCSI protocols.
- */
-
-
-/* #define VERBOSE_DEBUG */
-/* #define DUMP_MSGS */
-
-
-#include <linux/blkdev.h>
-#include <linux/completion.h>
-#include <linux/dcache.h>
-#include <linux/delay.h>
-#include <linux/device.h>
-#include <linux/fcntl.h>
-#include <linux/file.h>
-#include <linux/fs.h>
-#include <linux/kref.h>
-#include <linux/kthread.h>
-#include <linux/limits.h>
-#include <linux/module.h>
-#include <linux/rwsem.h>
-#include <linux/slab.h>
-#include <linux/spinlock.h>
-#include <linux/string.h>
-#include <linux/freezer.h>
-#include <linux/utsname.h>
-
-#include <linux/usb/composite.h>
-#include <linux/usb/ch9.h>
-#include <linux/usb/gadget.h>
-
-#include "gadget_chips.h"
-
-#define DRIVER_DESC "File-backed Storage Gadget"
-#define DRIVER_NAME "g_file_storage"
-#define DRIVER_VERSION "1 September 2010"
-
-static char fsg_string_manufacturer[64];
-static const char fsg_string_product[] = DRIVER_DESC;
-static const char fsg_string_config[] = "Self-powered";
-static const char fsg_string_interface[] = "Mass Storage";
-
-
-#include "storage_common.c"
-
-
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_AUTHOR("Alan Stern");
-MODULE_LICENSE("Dual BSD/GPL");
-
-/*
- * This driver assumes self-powered hardware and has no way for users to
- * trigger remote wakeup. It uses autoconfiguration to select endpoints
- * and endpoint addresses.
- */
-
-
-/*-------------------------------------------------------------------------*/
-
-
-/* Encapsulate the module parameter settings */
-
-static struct {
- char *file[FSG_MAX_LUNS];
- char *serial;
- bool ro[FSG_MAX_LUNS];
- bool nofua[FSG_MAX_LUNS];
- unsigned int num_filenames;
- unsigned int num_ros;
- unsigned int num_nofuas;
- unsigned int nluns;
-
- bool removable;
- bool can_stall;
- bool cdrom;
-
- char *transport_parm;
- char *protocol_parm;
- unsigned short vendor;
- unsigned short product;
- unsigned short release;
- unsigned int buflen;
-
- int transport_type;
- char *transport_name;
- int protocol_type;
- char *protocol_name;
-
-} mod_data = { // Default values
- .transport_parm = "BBB",
- .protocol_parm = "SCSI",
- .removable = 0,
- .can_stall = 1,
- .cdrom = 0,
- .vendor = FSG_VENDOR_ID,
- .product = FSG_PRODUCT_ID,
- .release = 0xffff, // Use controller chip type
- .buflen = 16384,
- };
-
-
-module_param_array_named(file, mod_data.file, charp, &mod_data.num_filenames,
- S_IRUGO);
-MODULE_PARM_DESC(file, "names of backing files or devices");
-
-module_param_named(serial, mod_data.serial, charp, S_IRUGO);
-MODULE_PARM_DESC(serial, "USB serial number");
-
-module_param_array_named(ro, mod_data.ro, bool, &mod_data.num_ros, S_IRUGO);
-MODULE_PARM_DESC(ro, "true to force read-only");
-
-module_param_array_named(nofua, mod_data.nofua, bool, &mod_data.num_nofuas,
- S_IRUGO);
-MODULE_PARM_DESC(nofua, "true to ignore SCSI WRITE(10,12) FUA bit");
-
-module_param_named(luns, mod_data.nluns, uint, S_IRUGO);
-MODULE_PARM_DESC(luns, "number of LUNs");
-
-module_param_named(removable, mod_data.removable, bool, S_IRUGO);
-MODULE_PARM_DESC(removable, "true to simulate removable media");
-
-module_param_named(stall, mod_data.can_stall, bool, S_IRUGO);
-MODULE_PARM_DESC(stall, "false to prevent bulk stalls");
-
-module_param_named(cdrom, mod_data.cdrom, bool, S_IRUGO);
-MODULE_PARM_DESC(cdrom, "true to emulate cdrom instead of disk");
-
-/* In the non-TEST version, only the module parameters listed above
- * are available. */
-#ifdef CONFIG_USB_FILE_STORAGE_TEST
-
-module_param_named(transport, mod_data.transport_parm, charp, S_IRUGO);
-MODULE_PARM_DESC(transport, "type of transport (BBB, CBI, or CB)");
-
-module_param_named(protocol, mod_data.protocol_parm, charp, S_IRUGO);
-MODULE_PARM_DESC(protocol, "type of protocol (RBC, 8020, QIC, UFI, "
- "8070, or SCSI)");
-
-module_param_named(vendor, mod_data.vendor, ushort, S_IRUGO);
-MODULE_PARM_DESC(vendor, "USB Vendor ID");
-
-module_param_named(product, mod_data.product, ushort, S_IRUGO);
-MODULE_PARM_DESC(product, "USB Product ID");
-
-module_param_named(release, mod_data.release, ushort, S_IRUGO);
-MODULE_PARM_DESC(release, "USB release number");
-
-module_param_named(buflen, mod_data.buflen, uint, S_IRUGO);
-MODULE_PARM_DESC(buflen, "I/O buffer size");
-
-#endif /* CONFIG_USB_FILE_STORAGE_TEST */
-
-
-/*
- * These definitions will permit the compiler to avoid generating code for
- * parts of the driver that aren't used in the non-TEST version. Even gcc
- * can recognize when a test of a constant expression yields a dead code
- * path.
- */
-
-#ifdef CONFIG_USB_FILE_STORAGE_TEST
-
-#define transport_is_bbb() (mod_data.transport_type == USB_PR_BULK)
-#define transport_is_cbi() (mod_data.transport_type == USB_PR_CBI)
-#define protocol_is_scsi() (mod_data.protocol_type == USB_SC_SCSI)
-
-#else
-
-#define transport_is_bbb() 1
-#define transport_is_cbi() 0
-#define protocol_is_scsi() 1
-
-#endif /* CONFIG_USB_FILE_STORAGE_TEST */
-
-
-/*-------------------------------------------------------------------------*/
-
-
-struct fsg_dev {
- /* lock protects: state, all the req_busy's, and cbbuf_cmnd */
- spinlock_t lock;
- struct usb_gadget *gadget;
-
- /* filesem protects: backing files in use */
- struct rw_semaphore filesem;
-
- /* reference counting: wait until all LUNs are released */
- struct kref ref;
-
- struct usb_ep *ep0; // Handy copy of gadget->ep0
- struct usb_request *ep0req; // For control responses
- unsigned int ep0_req_tag;
- const char *ep0req_name;
-
- struct usb_request *intreq; // For interrupt responses
- int intreq_busy;
- struct fsg_buffhd *intr_buffhd;
-
- unsigned int bulk_out_maxpacket;
- enum fsg_state state; // For exception handling
- unsigned int exception_req_tag;
-
- u8 config, new_config;
-
- unsigned int running : 1;
- unsigned int bulk_in_enabled : 1;
- unsigned int bulk_out_enabled : 1;
- unsigned int intr_in_enabled : 1;
- unsigned int phase_error : 1;
- unsigned int short_packet_received : 1;
- unsigned int bad_lun_okay : 1;
-
- unsigned long atomic_bitflags;
-#define REGISTERED 0
-#define IGNORE_BULK_OUT 1
-#define SUSPENDED 2
-
- struct usb_ep *bulk_in;
- struct usb_ep *bulk_out;
- struct usb_ep *intr_in;
-
- struct fsg_buffhd *next_buffhd_to_fill;
- struct fsg_buffhd *next_buffhd_to_drain;
-
- int thread_wakeup_needed;
- struct completion thread_notifier;
- struct task_struct *thread_task;
-
- int cmnd_size;
- u8 cmnd[MAX_COMMAND_SIZE];
- enum data_direction data_dir;
- u32 data_size;
- u32 data_size_from_cmnd;
- u32 tag;
- unsigned int lun;
- u32 residue;
- u32 usb_amount_left;
-
- /* The CB protocol offers no way for a host to know when a command
- * has completed. As a result the next command may arrive early,
- * and we will still have to handle it. For that reason we need
- * a buffer to store new commands when using CB (or CBI, which
- * does not oblige a host to wait for command completion either). */
- int cbbuf_cmnd_size;
- u8 cbbuf_cmnd[MAX_COMMAND_SIZE];
-
- unsigned int nluns;
- struct fsg_lun *luns;
- struct fsg_lun *curlun;
- /* Must be the last entry */
- struct fsg_buffhd buffhds[];
-};
-
-typedef void (*fsg_routine_t)(struct fsg_dev *);
-
-static int exception_in_progress(struct fsg_dev *fsg)
-{
- return (fsg->state > FSG_STATE_IDLE);
-}
-
-/* Make bulk-out requests be divisible by the maxpacket size */
-static void set_bulk_out_req_length(struct fsg_dev *fsg,
- struct fsg_buffhd *bh, unsigned int length)
-{
- unsigned int rem;
-
- bh->bulk_out_intended_length = length;
- rem = length % fsg->bulk_out_maxpacket;
- if (rem > 0)
- length += fsg->bulk_out_maxpacket - rem;
- bh->outreq->length = length;
-}
-
-static struct fsg_dev *the_fsg;
-static struct usb_gadget_driver fsg_driver;
-
-
-/*-------------------------------------------------------------------------*/
-
-static int fsg_set_halt(struct fsg_dev *fsg, struct usb_ep *ep)
-{
- const char *name;
-
- if (ep == fsg->bulk_in)
- name = "bulk-in";
- else if (ep == fsg->bulk_out)
- name = "bulk-out";
- else
- name = ep->name;
- DBG(fsg, "%s set halt\n", name);
- return usb_ep_set_halt(ep);
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * DESCRIPTORS ... most are static, but strings and (full) configuration
- * descriptors are built on demand. Also the (static) config and interface
- * descriptors are adjusted during fsg_bind().
- */
-
-/* There is only one configuration. */
-#define CONFIG_VALUE 1
-
-static struct usb_device_descriptor
-device_desc = {
- .bLength = sizeof device_desc,
- .bDescriptorType = USB_DT_DEVICE,
-
- .bcdUSB = cpu_to_le16(0x0200),
- .bDeviceClass = USB_CLASS_PER_INTERFACE,
-
- /* The next three values can be overridden by module parameters */
- .idVendor = cpu_to_le16(FSG_VENDOR_ID),
- .idProduct = cpu_to_le16(FSG_PRODUCT_ID),
- .bcdDevice = cpu_to_le16(0xffff),
-
- .iManufacturer = FSG_STRING_MANUFACTURER,
- .iProduct = FSG_STRING_PRODUCT,
- .iSerialNumber = FSG_STRING_SERIAL,
- .bNumConfigurations = 1,
-};
-
-static struct usb_config_descriptor
-config_desc = {
- .bLength = sizeof config_desc,
- .bDescriptorType = USB_DT_CONFIG,
-
- /* wTotalLength computed by usb_gadget_config_buf() */
- .bNumInterfaces = 1,
- .bConfigurationValue = CONFIG_VALUE,
- .iConfiguration = FSG_STRING_CONFIG,
- .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
- .bMaxPower = CONFIG_USB_GADGET_VBUS_DRAW / 2,
-};
-
-
-static struct usb_qualifier_descriptor
-dev_qualifier = {
- .bLength = sizeof dev_qualifier,
- .bDescriptorType = USB_DT_DEVICE_QUALIFIER,
-
- .bcdUSB = cpu_to_le16(0x0200),
- .bDeviceClass = USB_CLASS_PER_INTERFACE,
-
- .bNumConfigurations = 1,
-};
-
-static int populate_bos(struct fsg_dev *fsg, u8 *buf)
-{
- memcpy(buf, &fsg_bos_desc, USB_DT_BOS_SIZE);
- buf += USB_DT_BOS_SIZE;
-
- memcpy(buf, &fsg_ext_cap_desc, USB_DT_USB_EXT_CAP_SIZE);
- buf += USB_DT_USB_EXT_CAP_SIZE;
-
- memcpy(buf, &fsg_ss_cap_desc, USB_DT_USB_SS_CAP_SIZE);
-
- return USB_DT_BOS_SIZE + USB_DT_USB_SS_CAP_SIZE
- + USB_DT_USB_EXT_CAP_SIZE;
-}
-
-/*
- * Config descriptors must agree with the code that sets configurations
- * and with code managing interfaces and their altsettings. They must
- * also handle different speeds and other-speed requests.
- */
-static int populate_config_buf(struct usb_gadget *gadget,
- u8 *buf, u8 type, unsigned index)
-{
- enum usb_device_speed speed = gadget->speed;
- int len;
- const struct usb_descriptor_header **function;
-
- if (index > 0)
- return -EINVAL;
-
- if (gadget_is_dualspeed(gadget) && type == USB_DT_OTHER_SPEED_CONFIG)
- speed = (USB_SPEED_FULL + USB_SPEED_HIGH) - speed;
- function = gadget_is_dualspeed(gadget) && speed == USB_SPEED_HIGH
- ? (const struct usb_descriptor_header **)fsg_hs_function
- : (const struct usb_descriptor_header **)fsg_fs_function;
-
- /* for now, don't advertise srp-only devices */
- if (!gadget_is_otg(gadget))
- function++;
-
- len = usb_gadget_config_buf(&config_desc, buf, EP0_BUFSIZE, function);
- ((struct usb_config_descriptor *) buf)->bDescriptorType = type;
- return len;
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-/* These routines may be called in process context or in_irq */
-
-/* Caller must hold fsg->lock */
-static void wakeup_thread(struct fsg_dev *fsg)
-{
- /* Tell the main thread that something has happened */
- fsg->thread_wakeup_needed = 1;
- if (fsg->thread_task)
- wake_up_process(fsg->thread_task);
-}
-
-
-static void raise_exception(struct fsg_dev *fsg, enum fsg_state new_state)
-{
- unsigned long flags;
-
- /* Do nothing if a higher-priority exception is already in progress.
- * If a lower-or-equal priority exception is in progress, preempt it
- * and notify the main thread by sending it a signal. */
- spin_lock_irqsave(&fsg->lock, flags);
- if (fsg->state <= new_state) {
- fsg->exception_req_tag = fsg->ep0_req_tag;
- fsg->state = new_state;
- if (fsg->thread_task)
- send_sig_info(SIGUSR1, SEND_SIG_FORCED,
- fsg->thread_task);
- }
- spin_unlock_irqrestore(&fsg->lock, flags);
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-/* The disconnect callback and ep0 routines. These always run in_irq,
- * except that ep0_queue() is called in the main thread to acknowledge
- * completion of various requests: set config, set interface, and
- * Bulk-only device reset. */
-
-static void fsg_disconnect(struct usb_gadget *gadget)
-{
- struct fsg_dev *fsg = get_gadget_data(gadget);
-
- DBG(fsg, "disconnect or port reset\n");
- raise_exception(fsg, FSG_STATE_DISCONNECT);
-}
-
-
-static int ep0_queue(struct fsg_dev *fsg)
-{
- int rc;
-
- rc = usb_ep_queue(fsg->ep0, fsg->ep0req, GFP_ATOMIC);
- if (rc != 0 && rc != -ESHUTDOWN) {
-
- /* We can't do much more than wait for a reset */
- WARNING(fsg, "error in submission: %s --> %d\n",
- fsg->ep0->name, rc);
- }
- return rc;
-}
-
-static void ep0_complete(struct usb_ep *ep, struct usb_request *req)
-{
- struct fsg_dev *fsg = ep->driver_data;
-
- if (req->actual > 0)
- dump_msg(fsg, fsg->ep0req_name, req->buf, req->actual);
- if (req->status || req->actual != req->length)
- DBG(fsg, "%s --> %d, %u/%u\n", __func__,
- req->status, req->actual, req->length);
- if (req->status == -ECONNRESET) // Request was cancelled
- usb_ep_fifo_flush(ep);
-
- if (req->status == 0 && req->context)
- ((fsg_routine_t) (req->context))(fsg);
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-/* Bulk and interrupt endpoint completion handlers.
- * These always run in_irq. */
-
-static void bulk_in_complete(struct usb_ep *ep, struct usb_request *req)
-{
- struct fsg_dev *fsg = ep->driver_data;
- struct fsg_buffhd *bh = req->context;
-
- if (req->status || req->actual != req->length)
- DBG(fsg, "%s --> %d, %u/%u\n", __func__,
- req->status, req->actual, req->length);
- if (req->status == -ECONNRESET) // Request was cancelled
- usb_ep_fifo_flush(ep);
-
- /* Hold the lock while we update the request and buffer states */
- smp_wmb();
- spin_lock(&fsg->lock);
- bh->inreq_busy = 0;
- bh->state = BUF_STATE_EMPTY;
- wakeup_thread(fsg);
- spin_unlock(&fsg->lock);
-}
-
-static void bulk_out_complete(struct usb_ep *ep, struct usb_request *req)
-{
- struct fsg_dev *fsg = ep->driver_data;
- struct fsg_buffhd *bh = req->context;
-
- dump_msg(fsg, "bulk-out", req->buf, req->actual);
- if (req->status || req->actual != bh->bulk_out_intended_length)
- DBG(fsg, "%s --> %d, %u/%u\n", __func__,
- req->status, req->actual,
- bh->bulk_out_intended_length);
- if (req->status == -ECONNRESET) // Request was cancelled
- usb_ep_fifo_flush(ep);
-
- /* Hold the lock while we update the request and buffer states */
- smp_wmb();
- spin_lock(&fsg->lock);
- bh->outreq_busy = 0;
- bh->state = BUF_STATE_FULL;
- wakeup_thread(fsg);
- spin_unlock(&fsg->lock);
-}
-
-
-#ifdef CONFIG_USB_FILE_STORAGE_TEST
-static void intr_in_complete(struct usb_ep *ep, struct usb_request *req)
-{
- struct fsg_dev *fsg = ep->driver_data;
- struct fsg_buffhd *bh = req->context;
-
- if (req->status || req->actual != req->length)
- DBG(fsg, "%s --> %d, %u/%u\n", __func__,
- req->status, req->actual, req->length);
- if (req->status == -ECONNRESET) // Request was cancelled
- usb_ep_fifo_flush(ep);
-
- /* Hold the lock while we update the request and buffer states */
- smp_wmb();
- spin_lock(&fsg->lock);
- fsg->intreq_busy = 0;
- bh->state = BUF_STATE_EMPTY;
- wakeup_thread(fsg);
- spin_unlock(&fsg->lock);
-}
-
-#else
-static void intr_in_complete(struct usb_ep *ep, struct usb_request *req)
-{}
-#endif /* CONFIG_USB_FILE_STORAGE_TEST */
-
-
-/*-------------------------------------------------------------------------*/
-
-/* Ep0 class-specific handlers. These always run in_irq. */
-
-#ifdef CONFIG_USB_FILE_STORAGE_TEST
-static void received_cbi_adsc(struct fsg_dev *fsg, struct fsg_buffhd *bh)
-{
- struct usb_request *req = fsg->ep0req;
- static u8 cbi_reset_cmnd[6] = {
- SEND_DIAGNOSTIC, 4, 0xff, 0xff, 0xff, 0xff};
-
- /* Error in command transfer? */
- if (req->status || req->length != req->actual ||
- req->actual < 6 || req->actual > MAX_COMMAND_SIZE) {
-
- /* Not all controllers allow a protocol stall after
- * receiving control-out data, but we'll try anyway. */
- fsg_set_halt(fsg, fsg->ep0);
- return; // Wait for reset
- }
-
- /* Is it the special reset command? */
- if (req->actual >= sizeof cbi_reset_cmnd &&
- memcmp(req->buf, cbi_reset_cmnd,
- sizeof cbi_reset_cmnd) == 0) {
-
- /* Raise an exception to stop the current operation
- * and reinitialize our state. */
- DBG(fsg, "cbi reset request\n");
- raise_exception(fsg, FSG_STATE_RESET);
- return;
- }
-
- VDBG(fsg, "CB[I] accept device-specific command\n");
- spin_lock(&fsg->lock);
-
- /* Save the command for later */
- if (fsg->cbbuf_cmnd_size)
- WARNING(fsg, "CB[I] overwriting previous command\n");
- fsg->cbbuf_cmnd_size = req->actual;
- memcpy(fsg->cbbuf_cmnd, req->buf, fsg->cbbuf_cmnd_size);
-
- wakeup_thread(fsg);
- spin_unlock(&fsg->lock);
-}
-
-#else
-static void received_cbi_adsc(struct fsg_dev *fsg, struct fsg_buffhd *bh)
-{}
-#endif /* CONFIG_USB_FILE_STORAGE_TEST */
-
-
-static int class_setup_req(struct fsg_dev *fsg,
- const struct usb_ctrlrequest *ctrl)
-{
- struct usb_request *req = fsg->ep0req;
- int value = -EOPNOTSUPP;
- u16 w_index = le16_to_cpu(ctrl->wIndex);
- u16 w_value = le16_to_cpu(ctrl->wValue);
- u16 w_length = le16_to_cpu(ctrl->wLength);
-
- if (!fsg->config)
- return value;
-
- /* Handle Bulk-only class-specific requests */
- if (transport_is_bbb()) {
- switch (ctrl->bRequest) {
-
- case US_BULK_RESET_REQUEST:
- if (ctrl->bRequestType != (USB_DIR_OUT |
- USB_TYPE_CLASS | USB_RECIP_INTERFACE))
- break;
- if (w_index != 0 || w_value != 0 || w_length != 0) {
- value = -EDOM;
- break;
- }
-
- /* Raise an exception to stop the current operation
- * and reinitialize our state. */
- DBG(fsg, "bulk reset request\n");
- raise_exception(fsg, FSG_STATE_RESET);
- value = DELAYED_STATUS;
- break;
-
- case US_BULK_GET_MAX_LUN:
- if (ctrl->bRequestType != (USB_DIR_IN |
- USB_TYPE_CLASS | USB_RECIP_INTERFACE))
- break;
- if (w_index != 0 || w_value != 0 || w_length != 1) {
- value = -EDOM;
- break;
- }
- VDBG(fsg, "get max LUN\n");
- *(u8 *) req->buf = fsg->nluns - 1;
- value = 1;
- break;
- }
- }
-
- /* Handle CBI class-specific requests */
- else {
- switch (ctrl->bRequest) {
-
- case USB_CBI_ADSC_REQUEST:
- if (ctrl->bRequestType != (USB_DIR_OUT |
- USB_TYPE_CLASS | USB_RECIP_INTERFACE))
- break;
- if (w_index != 0 || w_value != 0) {
- value = -EDOM;
- break;
- }
- if (w_length > MAX_COMMAND_SIZE) {
- value = -EOVERFLOW;
- break;
- }
- value = w_length;
- fsg->ep0req->context = received_cbi_adsc;
- break;
- }
- }
-
- if (value == -EOPNOTSUPP)
- VDBG(fsg,
- "unknown class-specific control req "
- "%02x.%02x v%04x i%04x l%u\n",
- ctrl->bRequestType, ctrl->bRequest,
- le16_to_cpu(ctrl->wValue), w_index, w_length);
- return value;
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-/* Ep0 standard request handlers. These always run in_irq. */
-
-static int standard_setup_req(struct fsg_dev *fsg,
- const struct usb_ctrlrequest *ctrl)
-{
- struct usb_request *req = fsg->ep0req;
- int value = -EOPNOTSUPP;
- u16 w_index = le16_to_cpu(ctrl->wIndex);
- u16 w_value = le16_to_cpu(ctrl->wValue);
-
- /* Usually this just stores reply data in the pre-allocated ep0 buffer,
- * but config change events will also reconfigure hardware. */
- switch (ctrl->bRequest) {
-
- case USB_REQ_GET_DESCRIPTOR:
- if (ctrl->bRequestType != (USB_DIR_IN | USB_TYPE_STANDARD |
- USB_RECIP_DEVICE))
- break;
- switch (w_value >> 8) {
-
- case USB_DT_DEVICE:
- VDBG(fsg, "get device descriptor\n");
- device_desc.bMaxPacketSize0 = fsg->ep0->maxpacket;
- value = sizeof device_desc;
- memcpy(req->buf, &device_desc, value);
- break;
- case USB_DT_DEVICE_QUALIFIER:
- VDBG(fsg, "get device qualifier\n");
- if (!gadget_is_dualspeed(fsg->gadget) ||
- fsg->gadget->speed == USB_SPEED_SUPER)
- break;
- /*
- * Assume ep0 uses the same maxpacket value for both
- * speeds
- */
- dev_qualifier.bMaxPacketSize0 = fsg->ep0->maxpacket;
- value = sizeof dev_qualifier;
- memcpy(req->buf, &dev_qualifier, value);
- break;
-
- case USB_DT_OTHER_SPEED_CONFIG:
- VDBG(fsg, "get other-speed config descriptor\n");
- if (!gadget_is_dualspeed(fsg->gadget) ||
- fsg->gadget->speed == USB_SPEED_SUPER)
- break;
- goto get_config;
- case USB_DT_CONFIG:
- VDBG(fsg, "get configuration descriptor\n");
-get_config:
- value = populate_config_buf(fsg->gadget,
- req->buf,
- w_value >> 8,
- w_value & 0xff);
- break;
-
- case USB_DT_STRING:
- VDBG(fsg, "get string descriptor\n");
-
- /* wIndex == language code */
- value = usb_gadget_get_string(&fsg_stringtab,
- w_value & 0xff, req->buf);
- break;
-
- case USB_DT_BOS:
- VDBG(fsg, "get bos descriptor\n");
-
- if (gadget_is_superspeed(fsg->gadget))
- value = populate_bos(fsg, req->buf);
- break;
- }
-
- break;
-
- /* One config, two speeds */
- case USB_REQ_SET_CONFIGURATION:
- if (ctrl->bRequestType != (USB_DIR_OUT | USB_TYPE_STANDARD |
- USB_RECIP_DEVICE))
- break;
- VDBG(fsg, "set configuration\n");
- if (w_value == CONFIG_VALUE || w_value == 0) {
- fsg->new_config = w_value;
-
- /* Raise an exception to wipe out previous transaction
- * state (queued bufs, etc) and set the new config. */
- raise_exception(fsg, FSG_STATE_CONFIG_CHANGE);
- value = DELAYED_STATUS;
- }
- break;
- case USB_REQ_GET_CONFIGURATION:
- if (ctrl->bRequestType != (USB_DIR_IN | USB_TYPE_STANDARD |
- USB_RECIP_DEVICE))
- break;
- VDBG(fsg, "get configuration\n");
- *(u8 *) req->buf = fsg->config;
- value = 1;
- break;
-
- case USB_REQ_SET_INTERFACE:
- if (ctrl->bRequestType != (USB_DIR_OUT| USB_TYPE_STANDARD |
- USB_RECIP_INTERFACE))
- break;
- if (fsg->config && w_index == 0) {
-
- /* Raise an exception to wipe out previous transaction
- * state (queued bufs, etc) and install the new
- * interface altsetting. */
- raise_exception(fsg, FSG_STATE_INTERFACE_CHANGE);
- value = DELAYED_STATUS;
- }
- break;
- case USB_REQ_GET_INTERFACE:
- if (ctrl->bRequestType != (USB_DIR_IN | USB_TYPE_STANDARD |
- USB_RECIP_INTERFACE))
- break;
- if (!fsg->config)
- break;
- if (w_index != 0) {
- value = -EDOM;
- break;
- }
- VDBG(fsg, "get interface\n");
- *(u8 *) req->buf = 0;
- value = 1;
- break;
-
- default:
- VDBG(fsg,
- "unknown control req %02x.%02x v%04x i%04x l%u\n",
- ctrl->bRequestType, ctrl->bRequest,
- w_value, w_index, le16_to_cpu(ctrl->wLength));
- }
-
- return value;
-}
-
-
-static int fsg_setup(struct usb_gadget *gadget,
- const struct usb_ctrlrequest *ctrl)
-{
- struct fsg_dev *fsg = get_gadget_data(gadget);
- int rc;
- int w_length = le16_to_cpu(ctrl->wLength);
-
- ++fsg->ep0_req_tag; // Record arrival of a new request
- fsg->ep0req->context = NULL;
- fsg->ep0req->length = 0;
- dump_msg(fsg, "ep0-setup", (u8 *) ctrl, sizeof(*ctrl));
-
- if ((ctrl->bRequestType & USB_TYPE_MASK) == USB_TYPE_CLASS)
- rc = class_setup_req(fsg, ctrl);
- else
- rc = standard_setup_req(fsg, ctrl);
-
- /* Respond with data/status or defer until later? */
- if (rc >= 0 && rc != DELAYED_STATUS) {
- rc = min(rc, w_length);
- fsg->ep0req->length = rc;
- fsg->ep0req->zero = rc < w_length;
- fsg->ep0req_name = (ctrl->bRequestType & USB_DIR_IN ?
- "ep0-in" : "ep0-out");
- rc = ep0_queue(fsg);
- }
-
- /* Device either stalls (rc < 0) or reports success */
- return rc;
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-/* All the following routines run in process context */
-
-
-/* Use this for bulk or interrupt transfers, not ep0 */
-static void start_transfer(struct fsg_dev *fsg, struct usb_ep *ep,
- struct usb_request *req, int *pbusy,
- enum fsg_buffer_state *state)
-{
- int rc;
-
- if (ep == fsg->bulk_in)
- dump_msg(fsg, "bulk-in", req->buf, req->length);
- else if (ep == fsg->intr_in)
- dump_msg(fsg, "intr-in", req->buf, req->length);
-
- spin_lock_irq(&fsg->lock);
- *pbusy = 1;
- *state = BUF_STATE_BUSY;
- spin_unlock_irq(&fsg->lock);
- rc = usb_ep_queue(ep, req, GFP_KERNEL);
- if (rc != 0) {
- *pbusy = 0;
- *state = BUF_STATE_EMPTY;
-
- /* We can't do much more than wait for a reset */
-
- /* Note: currently the net2280 driver fails zero-length
- * submissions if DMA is enabled. */
- if (rc != -ESHUTDOWN && !(rc == -EOPNOTSUPP &&
- req->length == 0))
- WARNING(fsg, "error in submission: %s --> %d\n",
- ep->name, rc);
- }
-}
-
-
-static int sleep_thread(struct fsg_dev *fsg)
-{
- int rc = 0;
-
- /* Wait until a signal arrives or we are woken up */
- for (;;) {
- try_to_freeze();
- set_current_state(TASK_INTERRUPTIBLE);
- if (signal_pending(current)) {
- rc = -EINTR;
- break;
- }
- if (fsg->thread_wakeup_needed)
- break;
- schedule();
- }
- __set_current_state(TASK_RUNNING);
- fsg->thread_wakeup_needed = 0;
- return rc;
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-static int do_read(struct fsg_dev *fsg)
-{
- struct fsg_lun *curlun = fsg->curlun;
- u32 lba;
- struct fsg_buffhd *bh;
- int rc;
- u32 amount_left;
- loff_t file_offset, file_offset_tmp;
- unsigned int amount;
- ssize_t nread;
-
- /* Get the starting Logical Block Address and check that it's
- * not too big */
- if (fsg->cmnd[0] == READ_6)
- lba = get_unaligned_be24(&fsg->cmnd[1]);
- else {
- lba = get_unaligned_be32(&fsg->cmnd[2]);
-
- /* We allow DPO (Disable Page Out = don't save data in the
- * cache) and FUA (Force Unit Access = don't read from the
- * cache), but we don't implement them. */
- if ((fsg->cmnd[1] & ~0x18) != 0) {
- curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
- return -EINVAL;
- }
- }
- if (lba >= curlun->num_sectors) {
- curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
- return -EINVAL;
- }
- file_offset = ((loff_t) lba) << curlun->blkbits;
-
- /* Carry out the file reads */
- amount_left = fsg->data_size_from_cmnd;
- if (unlikely(amount_left == 0))
- return -EIO; // No default reply
-
- for (;;) {
-
- /* Figure out how much we need to read:
- * Try to read the remaining amount.
- * But don't read more than the buffer size.
- * And don't try to read past the end of the file.
- */
- amount = min((unsigned int) amount_left, mod_data.buflen);
- amount = min((loff_t) amount,
- curlun->file_length - file_offset);
-
- /* Wait for the next buffer to become available */
- bh = fsg->next_buffhd_to_fill;
- while (bh->state != BUF_STATE_EMPTY) {
- rc = sleep_thread(fsg);
- if (rc)
- return rc;
- }
-
- /* If we were asked to read past the end of file,
- * end with an empty buffer. */
- if (amount == 0) {
- curlun->sense_data =
- SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
- curlun->sense_data_info = file_offset >> curlun->blkbits;
- curlun->info_valid = 1;
- bh->inreq->length = 0;
- bh->state = BUF_STATE_FULL;
- break;
- }
-
- /* Perform the read */
- file_offset_tmp = file_offset;
- nread = vfs_read(curlun->filp,
- (char __user *) bh->buf,
- amount, &file_offset_tmp);
- VLDBG(curlun, "file read %u @ %llu -> %d\n", amount,
- (unsigned long long) file_offset,
- (int) nread);
- if (signal_pending(current))
- return -EINTR;
-
- if (nread < 0) {
- LDBG(curlun, "error in file read: %d\n",
- (int) nread);
- nread = 0;
- } else if (nread < amount) {
- LDBG(curlun, "partial file read: %d/%u\n",
- (int) nread, amount);
- nread = round_down(nread, curlun->blksize);
- }
- file_offset += nread;
- amount_left -= nread;
- fsg->residue -= nread;
-
- /* Except at the end of the transfer, nread will be
- * equal to the buffer size, which is divisible by the
- * bulk-in maxpacket size.
- */
- bh->inreq->length = nread;
- bh->state = BUF_STATE_FULL;
-
- /* If an error occurred, report it and its position */
- if (nread < amount) {
- curlun->sense_data = SS_UNRECOVERED_READ_ERROR;
- curlun->sense_data_info = file_offset >> curlun->blkbits;
- curlun->info_valid = 1;
- break;
- }
-
- if (amount_left == 0)
- break; // No more left to read
-
- /* Send this buffer and go read some more */
- bh->inreq->zero = 0;
- start_transfer(fsg, fsg->bulk_in, bh->inreq,
- &bh->inreq_busy, &bh->state);
- fsg->next_buffhd_to_fill = bh->next;
- }
-
- return -EIO; // No default reply
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-static int do_write(struct fsg_dev *fsg)
-{
- struct fsg_lun *curlun = fsg->curlun;
- u32 lba;
- struct fsg_buffhd *bh;
- int get_some_more;
- u32 amount_left_to_req, amount_left_to_write;
- loff_t usb_offset, file_offset, file_offset_tmp;
- unsigned int amount;
- ssize_t nwritten;
- int rc;
-
- if (curlun->ro) {
- curlun->sense_data = SS_WRITE_PROTECTED;
- return -EINVAL;
- }
- spin_lock(&curlun->filp->f_lock);
- curlun->filp->f_flags &= ~O_SYNC; // Default is not to wait
- spin_unlock(&curlun->filp->f_lock);
-
- /* Get the starting Logical Block Address and check that it's
- * not too big */
- if (fsg->cmnd[0] == WRITE_6)
- lba = get_unaligned_be24(&fsg->cmnd[1]);
- else {
- lba = get_unaligned_be32(&fsg->cmnd[2]);
-
- /* We allow DPO (Disable Page Out = don't save data in the
- * cache) and FUA (Force Unit Access = write directly to the
- * medium). We don't implement DPO; we implement FUA by
- * performing synchronous output. */
- if ((fsg->cmnd[1] & ~0x18) != 0) {
- curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
- return -EINVAL;
- }
- /* FUA */
- if (!curlun->nofua && (fsg->cmnd[1] & 0x08)) {
- spin_lock(&curlun->filp->f_lock);
- curlun->filp->f_flags |= O_DSYNC;
- spin_unlock(&curlun->filp->f_lock);
- }
- }
- if (lba >= curlun->num_sectors) {
- curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
- return -EINVAL;
- }
-
- /* Carry out the file writes */
- get_some_more = 1;
- file_offset = usb_offset = ((loff_t) lba) << curlun->blkbits;
- amount_left_to_req = amount_left_to_write = fsg->data_size_from_cmnd;
-
- while (amount_left_to_write > 0) {
-
- /* Queue a request for more data from the host */
- bh = fsg->next_buffhd_to_fill;
- if (bh->state == BUF_STATE_EMPTY && get_some_more) {
-
- /* Figure out how much we want to get:
- * Try to get the remaining amount,
- * but not more than the buffer size.
- */
- amount = min(amount_left_to_req, mod_data.buflen);
-
- /* Beyond the end of the backing file? */
- if (usb_offset >= curlun->file_length) {
- get_some_more = 0;
- curlun->sense_data =
- SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
- curlun->sense_data_info = usb_offset >> curlun->blkbits;
- curlun->info_valid = 1;
- continue;
- }
-
- /* Get the next buffer */
- usb_offset += amount;
- fsg->usb_amount_left -= amount;
- amount_left_to_req -= amount;
- if (amount_left_to_req == 0)
- get_some_more = 0;
-
- /* Except at the end of the transfer, amount will be
- * equal to the buffer size, which is divisible by
- * the bulk-out maxpacket size.
- */
- set_bulk_out_req_length(fsg, bh, amount);
- start_transfer(fsg, fsg->bulk_out, bh->outreq,
- &bh->outreq_busy, &bh->state);
- fsg->next_buffhd_to_fill = bh->next;
- continue;
- }
-
- /* Write the received data to the backing file */
- bh = fsg->next_buffhd_to_drain;
- if (bh->state == BUF_STATE_EMPTY && !get_some_more)
- break; // We stopped early
- if (bh->state == BUF_STATE_FULL) {
- smp_rmb();
- fsg->next_buffhd_to_drain = bh->next;
- bh->state = BUF_STATE_EMPTY;
-
- /* Did something go wrong with the transfer? */
- if (bh->outreq->status != 0) {
- curlun->sense_data = SS_COMMUNICATION_FAILURE;
- curlun->sense_data_info = file_offset >> curlun->blkbits;
- curlun->info_valid = 1;
- break;
- }
-
- amount = bh->outreq->actual;
- if (curlun->file_length - file_offset < amount) {
- LERROR(curlun,
- "write %u @ %llu beyond end %llu\n",
- amount, (unsigned long long) file_offset,
- (unsigned long long) curlun->file_length);
- amount = curlun->file_length - file_offset;
- }
-
- /* Don't accept excess data. The spec doesn't say
- * what to do in this case. We'll ignore the error.
- */
- amount = min(amount, bh->bulk_out_intended_length);
-
- /* Don't write a partial block */
- amount = round_down(amount, curlun->blksize);
- if (amount == 0)
- goto empty_write;
-
- /* Perform the write */
- file_offset_tmp = file_offset;
- nwritten = vfs_write(curlun->filp,
- (char __user *) bh->buf,
- amount, &file_offset_tmp);
- VLDBG(curlun, "file write %u @ %llu -> %d\n", amount,
- (unsigned long long) file_offset,
- (int) nwritten);
- if (signal_pending(current))
- return -EINTR; // Interrupted!
-
- if (nwritten < 0) {
- LDBG(curlun, "error in file write: %d\n",
- (int) nwritten);
- nwritten = 0;
- } else if (nwritten < amount) {
- LDBG(curlun, "partial file write: %d/%u\n",
- (int) nwritten, amount);
- nwritten = round_down(nwritten, curlun->blksize);
- }
- file_offset += nwritten;
- amount_left_to_write -= nwritten;
- fsg->residue -= nwritten;
-
- /* If an error occurred, report it and its position */
- if (nwritten < amount) {
- curlun->sense_data = SS_WRITE_ERROR;
- curlun->sense_data_info = file_offset >> curlun->blkbits;
- curlun->info_valid = 1;
- break;
- }
-
- empty_write:
- /* Did the host decide to stop early? */
- if (bh->outreq->actual < bh->bulk_out_intended_length) {
- fsg->short_packet_received = 1;
- break;
- }
- continue;
- }
-
- /* Wait for something to happen */
- rc = sleep_thread(fsg);
- if (rc)
- return rc;
- }
-
- return -EIO; // No default reply
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-static int do_synchronize_cache(struct fsg_dev *fsg)
-{
- struct fsg_lun *curlun = fsg->curlun;
- int rc;
-
- /* We ignore the requested LBA and write out all file's
- * dirty data buffers. */
- rc = fsg_lun_fsync_sub(curlun);
- if (rc)
- curlun->sense_data = SS_WRITE_ERROR;
- return 0;
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-static void invalidate_sub(struct fsg_lun *curlun)
-{
- struct file *filp = curlun->filp;
- struct inode *inode = filp->f_path.dentry->d_inode;
- unsigned long rc;
-
- rc = invalidate_mapping_pages(inode->i_mapping, 0, -1);
- VLDBG(curlun, "invalidate_mapping_pages -> %ld\n", rc);
-}
-
-static int do_verify(struct fsg_dev *fsg)
-{
- struct fsg_lun *curlun = fsg->curlun;
- u32 lba;
- u32 verification_length;
- struct fsg_buffhd *bh = fsg->next_buffhd_to_fill;
- loff_t file_offset, file_offset_tmp;
- u32 amount_left;
- unsigned int amount;
- ssize_t nread;
-
- /* Get the starting Logical Block Address and check that it's
- * not too big */
- lba = get_unaligned_be32(&fsg->cmnd[2]);
- if (lba >= curlun->num_sectors) {
- curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
- return -EINVAL;
- }
-
- /* We allow DPO (Disable Page Out = don't save data in the
- * cache) but we don't implement it. */
- if ((fsg->cmnd[1] & ~0x10) != 0) {
- curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
- return -EINVAL;
- }
-
- verification_length = get_unaligned_be16(&fsg->cmnd[7]);
- if (unlikely(verification_length == 0))
- return -EIO; // No default reply
-
- /* Prepare to carry out the file verify */
- amount_left = verification_length << curlun->blkbits;
- file_offset = ((loff_t) lba) << curlun->blkbits;
-
- /* Write out all the dirty buffers before invalidating them */
- fsg_lun_fsync_sub(curlun);
- if (signal_pending(current))
- return -EINTR;
-
- invalidate_sub(curlun);
- if (signal_pending(current))
- return -EINTR;
-
- /* Just try to read the requested blocks */
- while (amount_left > 0) {
-
- /* Figure out how much we need to read:
- * Try to read the remaining amount, but not more than
- * the buffer size.
- * And don't try to read past the end of the file.
- */
- amount = min((unsigned int) amount_left, mod_data.buflen);
- amount = min((loff_t) amount,
- curlun->file_length - file_offset);
- if (amount == 0) {
- curlun->sense_data =
- SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
- curlun->sense_data_info = file_offset >> curlun->blkbits;
- curlun->info_valid = 1;
- break;
- }
-
- /* Perform the read */
- file_offset_tmp = file_offset;
- nread = vfs_read(curlun->filp,
- (char __user *) bh->buf,
- amount, &file_offset_tmp);
- VLDBG(curlun, "file read %u @ %llu -> %d\n", amount,
- (unsigned long long) file_offset,
- (int) nread);
- if (signal_pending(current))
- return -EINTR;
-
- if (nread < 0) {
- LDBG(curlun, "error in file verify: %d\n",
- (int) nread);
- nread = 0;
- } else if (nread < amount) {
- LDBG(curlun, "partial file verify: %d/%u\n",
- (int) nread, amount);
- nread = round_down(nread, curlun->blksize);
- }
- if (nread == 0) {
- curlun->sense_data = SS_UNRECOVERED_READ_ERROR;
- curlun->sense_data_info = file_offset >> curlun->blkbits;
- curlun->info_valid = 1;
- break;
- }
- file_offset += nread;
- amount_left -= nread;
- }
- return 0;
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-static int do_inquiry(struct fsg_dev *fsg, struct fsg_buffhd *bh)
-{
- u8 *buf = (u8 *) bh->buf;
-
- static char vendor_id[] = "Linux ";
- static char product_disk_id[] = "File-Stor Gadget";
- static char product_cdrom_id[] = "File-CD Gadget ";
-
- if (!fsg->curlun) { // Unsupported LUNs are okay
- fsg->bad_lun_okay = 1;
- memset(buf, 0, 36);
- buf[0] = 0x7f; // Unsupported, no device-type
- buf[4] = 31; // Additional length
- return 36;
- }
-
- memset(buf, 0, 8);
- buf[0] = (mod_data.cdrom ? TYPE_ROM : TYPE_DISK);
- if (mod_data.removable)
- buf[1] = 0x80;
- buf[2] = 2; // ANSI SCSI level 2
- buf[3] = 2; // SCSI-2 INQUIRY data format
- buf[4] = 31; // Additional length
- // No special options
- sprintf(buf + 8, "%-8s%-16s%04x", vendor_id,
- (mod_data.cdrom ? product_cdrom_id :
- product_disk_id),
- mod_data.release);
- return 36;
-}
-
-
-static int do_request_sense(struct fsg_dev *fsg, struct fsg_buffhd *bh)
-{
- struct fsg_lun *curlun = fsg->curlun;
- u8 *buf = (u8 *) bh->buf;
- u32 sd, sdinfo;
- int valid;
-
- /*
- * From the SCSI-2 spec., section 7.9 (Unit attention condition):
- *
- * If a REQUEST SENSE command is received from an initiator
- * with a pending unit attention condition (before the target
- * generates the contingent allegiance condition), then the
- * target shall either:
- * a) report any pending sense data and preserve the unit
- * attention condition on the logical unit, or,
- * b) report the unit attention condition, may discard any
- * pending sense data, and clear the unit attention
- * condition on the logical unit for that initiator.
- *
- * FSG normally uses option a); enable this code to use option b).
- */
-#if 0
- if (curlun && curlun->unit_attention_data != SS_NO_SENSE) {
- curlun->sense_data = curlun->unit_attention_data;
- curlun->unit_attention_data = SS_NO_SENSE;
- }
-#endif
-
- if (!curlun) { // Unsupported LUNs are okay
- fsg->bad_lun_okay = 1;
- sd = SS_LOGICAL_UNIT_NOT_SUPPORTED;
- sdinfo = 0;
- valid = 0;
- } else {
- sd = curlun->sense_data;
- sdinfo = curlun->sense_data_info;
- valid = curlun->info_valid << 7;
- curlun->sense_data = SS_NO_SENSE;
- curlun->sense_data_info = 0;
- curlun->info_valid = 0;
- }
-
- memset(buf, 0, 18);
- buf[0] = valid | 0x70; // Valid, current error
- buf[2] = SK(sd);
- put_unaligned_be32(sdinfo, &buf[3]); /* Sense information */
- buf[7] = 18 - 8; // Additional sense length
- buf[12] = ASC(sd);
- buf[13] = ASCQ(sd);
- return 18;
-}
-
-
-static int do_read_capacity(struct fsg_dev *fsg, struct fsg_buffhd *bh)
-{
- struct fsg_lun *curlun = fsg->curlun;
- u32 lba = get_unaligned_be32(&fsg->cmnd[2]);
- int pmi = fsg->cmnd[8];
- u8 *buf = (u8 *) bh->buf;
-
- /* Check the PMI and LBA fields */
- if (pmi > 1 || (pmi == 0 && lba != 0)) {
- curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
- return -EINVAL;
- }
-
- put_unaligned_be32(curlun->num_sectors - 1, &buf[0]);
- /* Max logical block */
- put_unaligned_be32(curlun->blksize, &buf[4]); /* Block length */
- return 8;
-}
-
-
-static int do_read_header(struct fsg_dev *fsg, struct fsg_buffhd *bh)
-{
- struct fsg_lun *curlun = fsg->curlun;
- int msf = fsg->cmnd[1] & 0x02;
- u32 lba = get_unaligned_be32(&fsg->cmnd[2]);
- u8 *buf = (u8 *) bh->buf;
-
- if ((fsg->cmnd[1] & ~0x02) != 0) { /* Mask away MSF */
- curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
- return -EINVAL;
- }
- if (lba >= curlun->num_sectors) {
- curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
- return -EINVAL;
- }
-
- memset(buf, 0, 8);
- buf[0] = 0x01; /* 2048 bytes of user data, rest is EC */
- store_cdrom_address(&buf[4], msf, lba);
- return 8;
-}
-
-
-static int do_read_toc(struct fsg_dev *fsg, struct fsg_buffhd *bh)
-{
- struct fsg_lun *curlun = fsg->curlun;
- int msf = fsg->cmnd[1] & 0x02;
- int start_track = fsg->cmnd[6];
- u8 *buf = (u8 *) bh->buf;
-
- if ((fsg->cmnd[1] & ~0x02) != 0 || /* Mask away MSF */
- start_track > 1) {
- curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
- return -EINVAL;
- }
-
- memset(buf, 0, 20);
- buf[1] = (20-2); /* TOC data length */
- buf[2] = 1; /* First track number */
- buf[3] = 1; /* Last track number */
- buf[5] = 0x16; /* Data track, copying allowed */
- buf[6] = 0x01; /* Only track is number 1 */
- store_cdrom_address(&buf[8], msf, 0);
-
- buf[13] = 0x16; /* Lead-out track is data */
- buf[14] = 0xAA; /* Lead-out track number */
- store_cdrom_address(&buf[16], msf, curlun->num_sectors);
- return 20;
-}
-
-
-static int do_mode_sense(struct fsg_dev *fsg, struct fsg_buffhd *bh)
-{
- struct fsg_lun *curlun = fsg->curlun;
- int mscmnd = fsg->cmnd[0];
- u8 *buf = (u8 *) bh->buf;
- u8 *buf0 = buf;
- int pc, page_code;
- int changeable_values, all_pages;
- int valid_page = 0;
- int len, limit;
-
- if ((fsg->cmnd[1] & ~0x08) != 0) { // Mask away DBD
- curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
- return -EINVAL;
- }
- pc = fsg->cmnd[2] >> 6;
- page_code = fsg->cmnd[2] & 0x3f;
- if (pc == 3) {
- curlun->sense_data = SS_SAVING_PARAMETERS_NOT_SUPPORTED;
- return -EINVAL;
- }
- changeable_values = (pc == 1);
- all_pages = (page_code == 0x3f);
-
- /* Write the mode parameter header. Fixed values are: default
- * medium type, no cache control (DPOFUA), and no block descriptors.
- * The only variable value is the WriteProtect bit. We will fill in
- * the mode data length later. */
- memset(buf, 0, 8);
- if (mscmnd == MODE_SENSE) {
- buf[2] = (curlun->ro ? 0x80 : 0x00); // WP, DPOFUA
- buf += 4;
- limit = 255;
- } else { // MODE_SENSE_10
- buf[3] = (curlun->ro ? 0x80 : 0x00); // WP, DPOFUA
- buf += 8;
- limit = 65535; // Should really be mod_data.buflen
- }
-
- /* No block descriptors */
-
- /* The mode pages, in numerical order. The only page we support
- * is the Caching page. */
- if (page_code == 0x08 || all_pages) {
- valid_page = 1;
- buf[0] = 0x08; // Page code
- buf[1] = 10; // Page length
- memset(buf+2, 0, 10); // None of the fields are changeable
-
- if (!changeable_values) {
- buf[2] = 0x04; // Write cache enable,
- // Read cache not disabled
- // No cache retention priorities
- put_unaligned_be16(0xffff, &buf[4]);
- /* Don't disable prefetch */
- /* Minimum prefetch = 0 */
- put_unaligned_be16(0xffff, &buf[8]);
- /* Maximum prefetch */
- put_unaligned_be16(0xffff, &buf[10]);
- /* Maximum prefetch ceiling */
- }
- buf += 12;
- }
-
- /* Check that a valid page was requested and the mode data length
- * isn't too long. */
- len = buf - buf0;
- if (!valid_page || len > limit) {
- curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
- return -EINVAL;
- }
-
- /* Store the mode data length */
- if (mscmnd == MODE_SENSE)
- buf0[0] = len - 1;
- else
- put_unaligned_be16(len - 2, buf0);
- return len;
-}
-
-
-static int do_start_stop(struct fsg_dev *fsg)
-{
- struct fsg_lun *curlun = fsg->curlun;
- int loej, start;
-
- if (!mod_data.removable) {
- curlun->sense_data = SS_INVALID_COMMAND;
- return -EINVAL;
- }
-
- // int immed = fsg->cmnd[1] & 0x01;
- loej = fsg->cmnd[4] & 0x02;
- start = fsg->cmnd[4] & 0x01;
-
-#ifdef CONFIG_USB_FILE_STORAGE_TEST
- if ((fsg->cmnd[1] & ~0x01) != 0 || // Mask away Immed
- (fsg->cmnd[4] & ~0x03) != 0) { // Mask LoEj, Start
- curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
- return -EINVAL;
- }
-
- if (!start) {
-
- /* Are we allowed to unload the media? */
- if (curlun->prevent_medium_removal) {
- LDBG(curlun, "unload attempt prevented\n");
- curlun->sense_data = SS_MEDIUM_REMOVAL_PREVENTED;
- return -EINVAL;
- }
- if (loej) { // Simulate an unload/eject
- up_read(&fsg->filesem);
- down_write(&fsg->filesem);
- fsg_lun_close(curlun);
- up_write(&fsg->filesem);
- down_read(&fsg->filesem);
- }
- } else {
-
- /* Our emulation doesn't support mounting; the medium is
- * available for use as soon as it is loaded. */
- if (!fsg_lun_is_open(curlun)) {
- curlun->sense_data = SS_MEDIUM_NOT_PRESENT;
- return -EINVAL;
- }
- }
-#endif
- return 0;
-}
-
-
-static int do_prevent_allow(struct fsg_dev *fsg)
-{
- struct fsg_lun *curlun = fsg->curlun;
- int prevent;
-
- if (!mod_data.removable) {
- curlun->sense_data = SS_INVALID_COMMAND;
- return -EINVAL;
- }
-
- prevent = fsg->cmnd[4] & 0x01;
- if ((fsg->cmnd[4] & ~0x01) != 0) { // Mask away Prevent
- curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
- return -EINVAL;
- }
-
- if (curlun->prevent_medium_removal && !prevent)
- fsg_lun_fsync_sub(curlun);
- curlun->prevent_medium_removal = prevent;
- return 0;
-}
-
-
-static int do_read_format_capacities(struct fsg_dev *fsg,
- struct fsg_buffhd *bh)
-{
- struct fsg_lun *curlun = fsg->curlun;
- u8 *buf = (u8 *) bh->buf;
-
- buf[0] = buf[1] = buf[2] = 0;
- buf[3] = 8; // Only the Current/Maximum Capacity Descriptor
- buf += 4;
-
- put_unaligned_be32(curlun->num_sectors, &buf[0]);
- /* Number of blocks */
- put_unaligned_be32(curlun->blksize, &buf[4]); /* Block length */
- buf[4] = 0x02; /* Current capacity */
- return 12;
-}
-
-
-static int do_mode_select(struct fsg_dev *fsg, struct fsg_buffhd *bh)
-{
- struct fsg_lun *curlun = fsg->curlun;
-
- /* We don't support MODE SELECT */
- curlun->sense_data = SS_INVALID_COMMAND;
- return -EINVAL;
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-static int halt_bulk_in_endpoint(struct fsg_dev *fsg)
-{
- int rc;
-
- rc = fsg_set_halt(fsg, fsg->bulk_in);
- if (rc == -EAGAIN)
- VDBG(fsg, "delayed bulk-in endpoint halt\n");
- while (rc != 0) {
- if (rc != -EAGAIN) {
- WARNING(fsg, "usb_ep_set_halt -> %d\n", rc);
- rc = 0;
- break;
- }
-
- /* Wait for a short time and then try again */
- if (msleep_interruptible(100) != 0)
- return -EINTR;
- rc = usb_ep_set_halt(fsg->bulk_in);
- }
- return rc;
-}
-
-static int wedge_bulk_in_endpoint(struct fsg_dev *fsg)
-{
- int rc;
-
- DBG(fsg, "bulk-in set wedge\n");
- rc = usb_ep_set_wedge(fsg->bulk_in);
- if (rc == -EAGAIN)
- VDBG(fsg, "delayed bulk-in endpoint wedge\n");
- while (rc != 0) {
- if (rc != -EAGAIN) {
- WARNING(fsg, "usb_ep_set_wedge -> %d\n", rc);
- rc = 0;
- break;
- }
-
- /* Wait for a short time and then try again */
- if (msleep_interruptible(100) != 0)
- return -EINTR;
- rc = usb_ep_set_wedge(fsg->bulk_in);
- }
- return rc;
-}
-
-static int throw_away_data(struct fsg_dev *fsg)
-{
- struct fsg_buffhd *bh;
- u32 amount;
- int rc;
-
- while ((bh = fsg->next_buffhd_to_drain)->state != BUF_STATE_EMPTY ||
- fsg->usb_amount_left > 0) {
-
- /* Throw away the data in a filled buffer */
- if (bh->state == BUF_STATE_FULL) {
- smp_rmb();
- bh->state = BUF_STATE_EMPTY;
- fsg->next_buffhd_to_drain = bh->next;
-
- /* A short packet or an error ends everything */
- if (bh->outreq->actual < bh->bulk_out_intended_length ||
- bh->outreq->status != 0) {
- raise_exception(fsg, FSG_STATE_ABORT_BULK_OUT);
- return -EINTR;
- }
- continue;
- }
-
- /* Try to submit another request if we need one */
- bh = fsg->next_buffhd_to_fill;
- if (bh->state == BUF_STATE_EMPTY && fsg->usb_amount_left > 0) {
- amount = min(fsg->usb_amount_left,
- (u32) mod_data.buflen);
-
- /* Except at the end of the transfer, amount will be
- * equal to the buffer size, which is divisible by
- * the bulk-out maxpacket size.
- */
- set_bulk_out_req_length(fsg, bh, amount);
- start_transfer(fsg, fsg->bulk_out, bh->outreq,
- &bh->outreq_busy, &bh->state);
- fsg->next_buffhd_to_fill = bh->next;
- fsg->usb_amount_left -= amount;
- continue;
- }
-
- /* Otherwise wait for something to happen */
- rc = sleep_thread(fsg);
- if (rc)
- return rc;
- }
- return 0;
-}
-
-
-static int finish_reply(struct fsg_dev *fsg)
-{
- struct fsg_buffhd *bh = fsg->next_buffhd_to_fill;
- int rc = 0;
-
- switch (fsg->data_dir) {
- case DATA_DIR_NONE:
- break; // Nothing to send
-
- /* If we don't know whether the host wants to read or write,
- * this must be CB or CBI with an unknown command. We mustn't
- * try to send or receive any data. So stall both bulk pipes
- * if we can and wait for a reset. */
- case DATA_DIR_UNKNOWN:
- if (mod_data.can_stall) {
- fsg_set_halt(fsg, fsg->bulk_out);
- rc = halt_bulk_in_endpoint(fsg);
- }
- break;
-
- /* All but the last buffer of data must have already been sent */
- case DATA_DIR_TO_HOST:
- if (fsg->data_size == 0)
- ; // Nothing to send
-
- /* If there's no residue, simply send the last buffer */
- else if (fsg->residue == 0) {
- bh->inreq->zero = 0;
- start_transfer(fsg, fsg->bulk_in, bh->inreq,
- &bh->inreq_busy, &bh->state);
- fsg->next_buffhd_to_fill = bh->next;
- }
-
- /* There is a residue. For CB and CBI, simply mark the end
- * of the data with a short packet. However, if we are
- * allowed to stall, there was no data at all (residue ==
- * data_size), and the command failed (invalid LUN or
- * sense data is set), then halt the bulk-in endpoint
- * instead. */
- else if (!transport_is_bbb()) {
- if (mod_data.can_stall &&
- fsg->residue == fsg->data_size &&
- (!fsg->curlun || fsg->curlun->sense_data != SS_NO_SENSE)) {
- bh->state = BUF_STATE_EMPTY;
- rc = halt_bulk_in_endpoint(fsg);
- } else {
- bh->inreq->zero = 1;
- start_transfer(fsg, fsg->bulk_in, bh->inreq,
- &bh->inreq_busy, &bh->state);
- fsg->next_buffhd_to_fill = bh->next;
- }
- }
-
- /*
- * For Bulk-only, mark the end of the data with a short
- * packet. If we are allowed to stall, halt the bulk-in
- * endpoint. (Note: This violates the Bulk-Only Transport
- * specification, which requires us to pad the data if we
- * don't halt the endpoint. Presumably nobody will mind.)
- */
- else {
- bh->inreq->zero = 1;
- start_transfer(fsg, fsg->bulk_in, bh->inreq,
- &bh->inreq_busy, &bh->state);
- fsg->next_buffhd_to_fill = bh->next;
- if (mod_data.can_stall)
- rc = halt_bulk_in_endpoint(fsg);
- }
- break;
-
- /* We have processed all we want from the data the host has sent.
- * There may still be outstanding bulk-out requests. */
- case DATA_DIR_FROM_HOST:
- if (fsg->residue == 0)
- ; // Nothing to receive
-
- /* Did the host stop sending unexpectedly early? */
- else if (fsg->short_packet_received) {
- raise_exception(fsg, FSG_STATE_ABORT_BULK_OUT);
- rc = -EINTR;
- }
-
- /* We haven't processed all the incoming data. Even though
- * we may be allowed to stall, doing so would cause a race.
- * The controller may already have ACK'ed all the remaining
- * bulk-out packets, in which case the host wouldn't see a
- * STALL. Not realizing the endpoint was halted, it wouldn't
- * clear the halt -- leading to problems later on. */
-#if 0
- else if (mod_data.can_stall) {
- fsg_set_halt(fsg, fsg->bulk_out);
- raise_exception(fsg, FSG_STATE_ABORT_BULK_OUT);
- rc = -EINTR;
- }
-#endif
-
- /* We can't stall. Read in the excess data and throw it
- * all away. */
- else
- rc = throw_away_data(fsg);
- break;
- }
- return rc;
-}
-
-
-static int send_status(struct fsg_dev *fsg)
-{
- struct fsg_lun *curlun = fsg->curlun;
- struct fsg_buffhd *bh;
- int rc;
- u8 status = US_BULK_STAT_OK;
- u32 sd, sdinfo = 0;
-
- /* Wait for the next buffer to become available */
- bh = fsg->next_buffhd_to_fill;
- while (bh->state != BUF_STATE_EMPTY) {
- rc = sleep_thread(fsg);
- if (rc)
- return rc;
- }
-
- if (curlun) {
- sd = curlun->sense_data;
- sdinfo = curlun->sense_data_info;
- } else if (fsg->bad_lun_okay)
- sd = SS_NO_SENSE;
- else
- sd = SS_LOGICAL_UNIT_NOT_SUPPORTED;
-
- if (fsg->phase_error) {
- DBG(fsg, "sending phase-error status\n");
- status = US_BULK_STAT_PHASE;
- sd = SS_INVALID_COMMAND;
- } else if (sd != SS_NO_SENSE) {
- DBG(fsg, "sending command-failure status\n");
- status = US_BULK_STAT_FAIL;
- VDBG(fsg, " sense data: SK x%02x, ASC x%02x, ASCQ x%02x;"
- " info x%x\n",
- SK(sd), ASC(sd), ASCQ(sd), sdinfo);
- }
-
- if (transport_is_bbb()) {
- struct bulk_cs_wrap *csw = bh->buf;
-
- /* Store and send the Bulk-only CSW */
- csw->Signature = cpu_to_le32(US_BULK_CS_SIGN);
- csw->Tag = fsg->tag;
- csw->Residue = cpu_to_le32(fsg->residue);
- csw->Status = status;
-
- bh->inreq->length = US_BULK_CS_WRAP_LEN;
- bh->inreq->zero = 0;
- start_transfer(fsg, fsg->bulk_in, bh->inreq,
- &bh->inreq_busy, &bh->state);
-
- } else if (mod_data.transport_type == USB_PR_CB) {
-
- /* Control-Bulk transport has no status phase! */
- return 0;
-
- } else { // USB_PR_CBI
- struct interrupt_data *buf = bh->buf;
-
- /* Store and send the Interrupt data. UFI sends the ASC
- * and ASCQ bytes. Everything else sends a Type (which
- * is always 0) and the status Value. */
- if (mod_data.protocol_type == USB_SC_UFI) {
- buf->bType = ASC(sd);
- buf->bValue = ASCQ(sd);
- } else {
- buf->bType = 0;
- buf->bValue = status;
- }
- fsg->intreq->length = CBI_INTERRUPT_DATA_LEN;
-
- fsg->intr_buffhd = bh; // Point to the right buffhd
- fsg->intreq->buf = bh->inreq->buf;
- fsg->intreq->context = bh;
- start_transfer(fsg, fsg->intr_in, fsg->intreq,
- &fsg->intreq_busy, &bh->state);
- }
-
- fsg->next_buffhd_to_fill = bh->next;
- return 0;
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-/* Check whether the command is properly formed and whether its data size
- * and direction agree with the values we already have. */
-static int check_command(struct fsg_dev *fsg, int cmnd_size,
- enum data_direction data_dir, unsigned int mask,
- int needs_medium, const char *name)
-{
- int i;
- int lun = fsg->cmnd[1] >> 5;
- static const char dirletter[4] = {'u', 'o', 'i', 'n'};
- char hdlen[20];
- struct fsg_lun *curlun;
-
- /* Adjust the expected cmnd_size for protocol encapsulation padding.
- * Transparent SCSI doesn't pad. */
- if (protocol_is_scsi())
- ;
-
- /* There's some disagreement as to whether RBC pads commands or not.
- * We'll play it safe and accept either form. */
- else if (mod_data.protocol_type == USB_SC_RBC) {
- if (fsg->cmnd_size == 12)
- cmnd_size = 12;
-
- /* All the other protocols pad to 12 bytes */
- } else
- cmnd_size = 12;
-
- hdlen[0] = 0;
- if (fsg->data_dir != DATA_DIR_UNKNOWN)
- sprintf(hdlen, ", H%c=%u", dirletter[(int) fsg->data_dir],
- fsg->data_size);
- VDBG(fsg, "SCSI command: %s; Dc=%d, D%c=%u; Hc=%d%s\n",
- name, cmnd_size, dirletter[(int) data_dir],
- fsg->data_size_from_cmnd, fsg->cmnd_size, hdlen);
-
- /* We can't reply at all until we know the correct data direction
- * and size. */
- if (fsg->data_size_from_cmnd == 0)
- data_dir = DATA_DIR_NONE;
- if (fsg->data_dir == DATA_DIR_UNKNOWN) { // CB or CBI
- fsg->data_dir = data_dir;
- fsg->data_size = fsg->data_size_from_cmnd;
-
- } else { // Bulk-only
- if (fsg->data_size < fsg->data_size_from_cmnd) {
-
- /* Host data size < Device data size is a phase error.
- * Carry out the command, but only transfer as much
- * as we are allowed. */
- fsg->data_size_from_cmnd = fsg->data_size;
- fsg->phase_error = 1;
- }
- }
- fsg->residue = fsg->usb_amount_left = fsg->data_size;
-
- /* Conflicting data directions is a phase error */
- if (fsg->data_dir != data_dir && fsg->data_size_from_cmnd > 0) {
- fsg->phase_error = 1;
- return -EINVAL;
- }
-
- /* Verify the length of the command itself */
- if (cmnd_size != fsg->cmnd_size) {
-
- /* Special case workaround: There are plenty of buggy SCSI
- * implementations. Many have issues with cbw->Length
- * field passing a wrong command size. For those cases we
- * always try to work around the problem by using the length
- * sent by the host side provided it is at least as large
- * as the correct command length.
- * Examples of such cases would be MS-Windows, which issues
- * REQUEST SENSE with cbw->Length == 12 where it should
- * be 6, and xbox360 issuing INQUIRY, TEST UNIT READY and
- * REQUEST SENSE with cbw->Length == 10 where it should
- * be 6 as well.
- */
- if (cmnd_size <= fsg->cmnd_size) {
- DBG(fsg, "%s is buggy! Expected length %d "
- "but we got %d\n", name,
- cmnd_size, fsg->cmnd_size);
- cmnd_size = fsg->cmnd_size;
- } else {
- fsg->phase_error = 1;
- return -EINVAL;
- }
- }
-
- /* Check that the LUN values are consistent */
- if (transport_is_bbb()) {
- if (fsg->lun != lun)
- DBG(fsg, "using LUN %d from CBW, "
- "not LUN %d from CDB\n",
- fsg->lun, lun);
- }
-
- /* Check the LUN */
- curlun = fsg->curlun;
- if (curlun) {
- if (fsg->cmnd[0] != REQUEST_SENSE) {
- curlun->sense_data = SS_NO_SENSE;
- curlun->sense_data_info = 0;
- curlun->info_valid = 0;
- }
- } else {
- fsg->bad_lun_okay = 0;
-
- /* INQUIRY and REQUEST SENSE commands are explicitly allowed
- * to use unsupported LUNs; all others may not. */
- if (fsg->cmnd[0] != INQUIRY &&
- fsg->cmnd[0] != REQUEST_SENSE) {
- DBG(fsg, "unsupported LUN %d\n", fsg->lun);
- return -EINVAL;
- }
- }
-
- /* If a unit attention condition exists, only INQUIRY and
- * REQUEST SENSE commands are allowed; anything else must fail. */
- if (curlun && curlun->unit_attention_data != SS_NO_SENSE &&
- fsg->cmnd[0] != INQUIRY &&
- fsg->cmnd[0] != REQUEST_SENSE) {
- curlun->sense_data = curlun->unit_attention_data;
- curlun->unit_attention_data = SS_NO_SENSE;
- return -EINVAL;
- }
-
- /* Check that only command bytes listed in the mask are non-zero */
- fsg->cmnd[1] &= 0x1f; // Mask away the LUN
- for (i = 1; i < cmnd_size; ++i) {
- if (fsg->cmnd[i] && !(mask & (1 << i))) {
- if (curlun)
- curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
- return -EINVAL;
- }
- }
-
- /* If the medium isn't mounted and the command needs to access
- * it, return an error. */
- if (curlun && !fsg_lun_is_open(curlun) && needs_medium) {
- curlun->sense_data = SS_MEDIUM_NOT_PRESENT;
- return -EINVAL;
- }
-
- return 0;
-}
-
-/* wrapper of check_command for data size in blocks handling */
-static int check_command_size_in_blocks(struct fsg_dev *fsg, int cmnd_size,
- enum data_direction data_dir, unsigned int mask,
- int needs_medium, const char *name)
-{
- if (fsg->curlun)
- fsg->data_size_from_cmnd <<= fsg->curlun->blkbits;
- return check_command(fsg, cmnd_size, data_dir,
- mask, needs_medium, name);
-}
-
-static int do_scsi_command(struct fsg_dev *fsg)
-{
- struct fsg_buffhd *bh;
- int rc;
- int reply = -EINVAL;
- int i;
- static char unknown[16];
-
- dump_cdb(fsg);
-
- /* Wait for the next buffer to become available for data or status */
- bh = fsg->next_buffhd_to_drain = fsg->next_buffhd_to_fill;
- while (bh->state != BUF_STATE_EMPTY) {
- rc = sleep_thread(fsg);
- if (rc)
- return rc;
- }
- fsg->phase_error = 0;
- fsg->short_packet_received = 0;
-
- down_read(&fsg->filesem); // We're using the backing file
- switch (fsg->cmnd[0]) {
-
- case INQUIRY:
- fsg->data_size_from_cmnd = fsg->cmnd[4];
- if ((reply = check_command(fsg, 6, DATA_DIR_TO_HOST,
- (1<<4), 0,
- "INQUIRY")) == 0)
- reply = do_inquiry(fsg, bh);
- break;
-
- case MODE_SELECT:
- fsg->data_size_from_cmnd = fsg->cmnd[4];
- if ((reply = check_command(fsg, 6, DATA_DIR_FROM_HOST,
- (1<<1) | (1<<4), 0,
- "MODE SELECT(6)")) == 0)
- reply = do_mode_select(fsg, bh);
- break;
-
- case MODE_SELECT_10:
- fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]);
- if ((reply = check_command(fsg, 10, DATA_DIR_FROM_HOST,
- (1<<1) | (3<<7), 0,
- "MODE SELECT(10)")) == 0)
- reply = do_mode_select(fsg, bh);
- break;
-
- case MODE_SENSE:
- fsg->data_size_from_cmnd = fsg->cmnd[4];
- if ((reply = check_command(fsg, 6, DATA_DIR_TO_HOST,
- (1<<1) | (1<<2) | (1<<4), 0,
- "MODE SENSE(6)")) == 0)
- reply = do_mode_sense(fsg, bh);
- break;
-
- case MODE_SENSE_10:
- fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]);
- if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST,
- (1<<1) | (1<<2) | (3<<7), 0,
- "MODE SENSE(10)")) == 0)
- reply = do_mode_sense(fsg, bh);
- break;
-
- case ALLOW_MEDIUM_REMOVAL:
- fsg->data_size_from_cmnd = 0;
- if ((reply = check_command(fsg, 6, DATA_DIR_NONE,
- (1<<4), 0,
- "PREVENT-ALLOW MEDIUM REMOVAL")) == 0)
- reply = do_prevent_allow(fsg);
- break;
-
- case READ_6:
- i = fsg->cmnd[4];
- fsg->data_size_from_cmnd = (i == 0) ? 256 : i;
- if ((reply = check_command_size_in_blocks(fsg, 6,
- DATA_DIR_TO_HOST,
- (7<<1) | (1<<4), 1,
- "READ(6)")) == 0)
- reply = do_read(fsg);
- break;
-
- case READ_10:
- fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]);
- if ((reply = check_command_size_in_blocks(fsg, 10,
- DATA_DIR_TO_HOST,
- (1<<1) | (0xf<<2) | (3<<7), 1,
- "READ(10)")) == 0)
- reply = do_read(fsg);
- break;
-
- case READ_12:
- fsg->data_size_from_cmnd = get_unaligned_be32(&fsg->cmnd[6]);
- if ((reply = check_command_size_in_blocks(fsg, 12,
- DATA_DIR_TO_HOST,
- (1<<1) | (0xf<<2) | (0xf<<6), 1,
- "READ(12)")) == 0)
- reply = do_read(fsg);
- break;
-
- case READ_CAPACITY:
- fsg->data_size_from_cmnd = 8;
- if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST,
- (0xf<<2) | (1<<8), 1,
- "READ CAPACITY")) == 0)
- reply = do_read_capacity(fsg, bh);
- break;
-
- case READ_HEADER:
- if (!mod_data.cdrom)
- goto unknown_cmnd;
- fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]);
- if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST,
- (3<<7) | (0x1f<<1), 1,
- "READ HEADER")) == 0)
- reply = do_read_header(fsg, bh);
- break;
-
- case READ_TOC:
- if (!mod_data.cdrom)
- goto unknown_cmnd;
- fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]);
- if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST,
- (7<<6) | (1<<1), 1,
- "READ TOC")) == 0)
- reply = do_read_toc(fsg, bh);
- break;
-
- case READ_FORMAT_CAPACITIES:
- fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]);
- if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST,
- (3<<7), 1,
- "READ FORMAT CAPACITIES")) == 0)
- reply = do_read_format_capacities(fsg, bh);
- break;
-
- case REQUEST_SENSE:
- fsg->data_size_from_cmnd = fsg->cmnd[4];
- if ((reply = check_command(fsg, 6, DATA_DIR_TO_HOST,
- (1<<4), 0,
- "REQUEST SENSE")) == 0)
- reply = do_request_sense(fsg, bh);
- break;
-
- case START_STOP:
- fsg->data_size_from_cmnd = 0;
- if ((reply = check_command(fsg, 6, DATA_DIR_NONE,
- (1<<1) | (1<<4), 0,
- "START-STOP UNIT")) == 0)
- reply = do_start_stop(fsg);
- break;
-
- case SYNCHRONIZE_CACHE:
- fsg->data_size_from_cmnd = 0;
- if ((reply = check_command(fsg, 10, DATA_DIR_NONE,
- (0xf<<2) | (3<<7), 1,
- "SYNCHRONIZE CACHE")) == 0)
- reply = do_synchronize_cache(fsg);
- break;
-
- case TEST_UNIT_READY:
- fsg->data_size_from_cmnd = 0;
- reply = check_command(fsg, 6, DATA_DIR_NONE,
- 0, 1,
- "TEST UNIT READY");
- break;
-
- /* Although optional, this command is used by MS-Windows. We
- * support a minimal version: BytChk must be 0. */
- case VERIFY:
- fsg->data_size_from_cmnd = 0;
- if ((reply = check_command(fsg, 10, DATA_DIR_NONE,
- (1<<1) | (0xf<<2) | (3<<7), 1,
- "VERIFY")) == 0)
- reply = do_verify(fsg);
- break;
-
- case WRITE_6:
- i = fsg->cmnd[4];
- fsg->data_size_from_cmnd = (i == 0) ? 256 : i;
- if ((reply = check_command_size_in_blocks(fsg, 6,
- DATA_DIR_FROM_HOST,
- (7<<1) | (1<<4), 1,
- "WRITE(6)")) == 0)
- reply = do_write(fsg);
- break;
-
- case WRITE_10:
- fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]);
- if ((reply = check_command_size_in_blocks(fsg, 10,
- DATA_DIR_FROM_HOST,
- (1<<1) | (0xf<<2) | (3<<7), 1,
- "WRITE(10)")) == 0)
- reply = do_write(fsg);
- break;
-
- case WRITE_12:
- fsg->data_size_from_cmnd = get_unaligned_be32(&fsg->cmnd[6]);
- if ((reply = check_command_size_in_blocks(fsg, 12,
- DATA_DIR_FROM_HOST,
- (1<<1) | (0xf<<2) | (0xf<<6), 1,
- "WRITE(12)")) == 0)
- reply = do_write(fsg);
- break;
-
- /* Some mandatory commands that we recognize but don't implement.
- * They don't mean much in this setting. It's left as an exercise
- * for anyone interested to implement RESERVE and RELEASE in terms
- * of Posix locks. */
- case FORMAT_UNIT:
- case RELEASE:
- case RESERVE:
- case SEND_DIAGNOSTIC:
- // Fall through
-
- default:
- unknown_cmnd:
- fsg->data_size_from_cmnd = 0;
- sprintf(unknown, "Unknown x%02x", fsg->cmnd[0]);
- if ((reply = check_command(fsg, fsg->cmnd_size,
- DATA_DIR_UNKNOWN, ~0, 0, unknown)) == 0) {
- fsg->curlun->sense_data = SS_INVALID_COMMAND;
- reply = -EINVAL;
- }
- break;
- }
- up_read(&fsg->filesem);
-
- if (reply == -EINTR || signal_pending(current))
- return -EINTR;
-
- /* Set up the single reply buffer for finish_reply() */
- if (reply == -EINVAL)
- reply = 0; // Error reply length
- if (reply >= 0 && fsg->data_dir == DATA_DIR_TO_HOST) {
- reply = min((u32) reply, fsg->data_size_from_cmnd);
- bh->inreq->length = reply;
- bh->state = BUF_STATE_FULL;
- fsg->residue -= reply;
- } // Otherwise it's already set
-
- return 0;
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh)
-{
- struct usb_request *req = bh->outreq;
- struct bulk_cb_wrap *cbw = req->buf;
-
- /* Was this a real packet? Should it be ignored? */
- if (req->status || test_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags))
- return -EINVAL;
-
- /* Is the CBW valid? */
- if (req->actual != US_BULK_CB_WRAP_LEN ||
- cbw->Signature != cpu_to_le32(
- US_BULK_CB_SIGN)) {
- DBG(fsg, "invalid CBW: len %u sig 0x%x\n",
- req->actual,
- le32_to_cpu(cbw->Signature));
-
- /* The Bulk-only spec says we MUST stall the IN endpoint
- * (6.6.1), so it's unavoidable. It also says we must
- * retain this state until the next reset, but there's
- * no way to tell the controller driver it should ignore
- * Clear-Feature(HALT) requests.
- *
- * We aren't required to halt the OUT endpoint; instead
- * we can simply accept and discard any data received
- * until the next reset. */
- wedge_bulk_in_endpoint(fsg);
- set_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags);
- return -EINVAL;
- }
-
- /* Is the CBW meaningful? */
- if (cbw->Lun >= FSG_MAX_LUNS || cbw->Flags & ~US_BULK_FLAG_IN ||
- cbw->Length <= 0 || cbw->Length > MAX_COMMAND_SIZE) {
- DBG(fsg, "non-meaningful CBW: lun = %u, flags = 0x%x, "
- "cmdlen %u\n",
- cbw->Lun, cbw->Flags, cbw->Length);
-
- /* We can do anything we want here, so let's stall the
- * bulk pipes if we are allowed to. */
- if (mod_data.can_stall) {
- fsg_set_halt(fsg, fsg->bulk_out);
- halt_bulk_in_endpoint(fsg);
- }
- return -EINVAL;
- }
-
- /* Save the command for later */
- fsg->cmnd_size = cbw->Length;
- memcpy(fsg->cmnd, cbw->CDB, fsg->cmnd_size);
- if (cbw->Flags & US_BULK_FLAG_IN)
- fsg->data_dir = DATA_DIR_TO_HOST;
- else
- fsg->data_dir = DATA_DIR_FROM_HOST;
- fsg->data_size = le32_to_cpu(cbw->DataTransferLength);
- if (fsg->data_size == 0)
- fsg->data_dir = DATA_DIR_NONE;
- fsg->lun = cbw->Lun;
- fsg->tag = cbw->Tag;
- return 0;
-}
-
-
-static int get_next_command(struct fsg_dev *fsg)
-{
- struct fsg_buffhd *bh;
- int rc = 0;
-
- if (transport_is_bbb()) {
-
- /* Wait for the next buffer to become available */
- bh = fsg->next_buffhd_to_fill;
- while (bh->state != BUF_STATE_EMPTY) {
- rc = sleep_thread(fsg);
- if (rc)
- return rc;
- }
-
- /* Queue a request to read a Bulk-only CBW */
- set_bulk_out_req_length(fsg, bh, US_BULK_CB_WRAP_LEN);
- start_transfer(fsg, fsg->bulk_out, bh->outreq,
- &bh->outreq_busy, &bh->state);
-
- /* We will drain the buffer in software, which means we
- * can reuse it for the next filling. No need to advance
- * next_buffhd_to_fill. */
-
- /* Wait for the CBW to arrive */
- while (bh->state != BUF_STATE_FULL) {
- rc = sleep_thread(fsg);
- if (rc)
- return rc;
- }
- smp_rmb();
- rc = received_cbw(fsg, bh);
- bh->state = BUF_STATE_EMPTY;
-
- } else { // USB_PR_CB or USB_PR_CBI
-
- /* Wait for the next command to arrive */
- while (fsg->cbbuf_cmnd_size == 0) {
- rc = sleep_thread(fsg);
- if (rc)
- return rc;
- }
-
- /* Is the previous status interrupt request still busy?
- * The host is allowed to skip reading the status,
- * so we must cancel it. */
- if (fsg->intreq_busy)
- usb_ep_dequeue(fsg->intr_in, fsg->intreq);
-
- /* Copy the command and mark the buffer empty */
- fsg->data_dir = DATA_DIR_UNKNOWN;
- spin_lock_irq(&fsg->lock);
- fsg->cmnd_size = fsg->cbbuf_cmnd_size;
- memcpy(fsg->cmnd, fsg->cbbuf_cmnd, fsg->cmnd_size);
- fsg->cbbuf_cmnd_size = 0;
- spin_unlock_irq(&fsg->lock);
-
- /* Use LUN from the command */
- fsg->lun = fsg->cmnd[1] >> 5;
- }
-
- /* Update current lun */
- if (fsg->lun >= 0 && fsg->lun < fsg->nluns)
- fsg->curlun = &fsg->luns[fsg->lun];
- else
- fsg->curlun = NULL;
-
- return rc;
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-static int enable_endpoint(struct fsg_dev *fsg, struct usb_ep *ep,
- const struct usb_endpoint_descriptor *d)
-{
- int rc;
-
- ep->driver_data = fsg;
- ep->desc = d;
- rc = usb_ep_enable(ep);
- if (rc)
- ERROR(fsg, "can't enable %s, result %d\n", ep->name, rc);
- return rc;
-}
-
-static int alloc_request(struct fsg_dev *fsg, struct usb_ep *ep,
- struct usb_request **preq)
-{
- *preq = usb_ep_alloc_request(ep, GFP_ATOMIC);
- if (*preq)
- return 0;
- ERROR(fsg, "can't allocate request for %s\n", ep->name);
- return -ENOMEM;
-}
-
-/*
- * Reset interface setting and re-init endpoint state (toggle etc).
- * Call with altsetting < 0 to disable the interface. The only other
- * available altsetting is 0, which enables the interface.
- */
-static int do_set_interface(struct fsg_dev *fsg, int altsetting)
-{
- int rc = 0;
- int i;
- const struct usb_endpoint_descriptor *d;
-
- if (fsg->running)
- DBG(fsg, "reset interface\n");
-
-reset:
- /* Deallocate the requests */
- for (i = 0; i < fsg_num_buffers; ++i) {
- struct fsg_buffhd *bh = &fsg->buffhds[i];
-
- if (bh->inreq) {
- usb_ep_free_request(fsg->bulk_in, bh->inreq);
- bh->inreq = NULL;
- }
- if (bh->outreq) {
- usb_ep_free_request(fsg->bulk_out, bh->outreq);
- bh->outreq = NULL;
- }
- }
- if (fsg->intreq) {
- usb_ep_free_request(fsg->intr_in, fsg->intreq);
- fsg->intreq = NULL;
- }
-
- /* Disable the endpoints */
- if (fsg->bulk_in_enabled) {
- usb_ep_disable(fsg->bulk_in);
- fsg->bulk_in_enabled = 0;
- }
- if (fsg->bulk_out_enabled) {
- usb_ep_disable(fsg->bulk_out);
- fsg->bulk_out_enabled = 0;
- }
- if (fsg->intr_in_enabled) {
- usb_ep_disable(fsg->intr_in);
- fsg->intr_in_enabled = 0;
- }
-
- fsg->running = 0;
- if (altsetting < 0 || rc != 0)
- return rc;
-
- DBG(fsg, "set interface %d\n", altsetting);
-
- /* Enable the endpoints */
- d = fsg_ep_desc(fsg->gadget,
- &fsg_fs_bulk_in_desc, &fsg_hs_bulk_in_desc,
- &fsg_ss_bulk_in_desc);
- if ((rc = enable_endpoint(fsg, fsg->bulk_in, d)) != 0)
- goto reset;
- fsg->bulk_in_enabled = 1;
-
- d = fsg_ep_desc(fsg->gadget,
- &fsg_fs_bulk_out_desc, &fsg_hs_bulk_out_desc,
- &fsg_ss_bulk_out_desc);
- if ((rc = enable_endpoint(fsg, fsg->bulk_out, d)) != 0)
- goto reset;
- fsg->bulk_out_enabled = 1;
- fsg->bulk_out_maxpacket = usb_endpoint_maxp(d);
- clear_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags);
-
- if (transport_is_cbi()) {
- d = fsg_ep_desc(fsg->gadget,
- &fsg_fs_intr_in_desc, &fsg_hs_intr_in_desc,
- &fsg_ss_intr_in_desc);
- if ((rc = enable_endpoint(fsg, fsg->intr_in, d)) != 0)
- goto reset;
- fsg->intr_in_enabled = 1;
- }
-
- /* Allocate the requests */
- for (i = 0; i < fsg_num_buffers; ++i) {
- struct fsg_buffhd *bh = &fsg->buffhds[i];
-
- if ((rc = alloc_request(fsg, fsg->bulk_in, &bh->inreq)) != 0)
- goto reset;
- if ((rc = alloc_request(fsg, fsg->bulk_out, &bh->outreq)) != 0)
- goto reset;
- bh->inreq->buf = bh->outreq->buf = bh->buf;
- bh->inreq->context = bh->outreq->context = bh;
- bh->inreq->complete = bulk_in_complete;
- bh->outreq->complete = bulk_out_complete;
- }
- if (transport_is_cbi()) {
- if ((rc = alloc_request(fsg, fsg->intr_in, &fsg->intreq)) != 0)
- goto reset;
- fsg->intreq->complete = intr_in_complete;
- }
-
- fsg->running = 1;
- for (i = 0; i < fsg->nluns; ++i)
- fsg->luns[i].unit_attention_data = SS_RESET_OCCURRED;
- return rc;
-}
-
-
-/*
- * Change our operational configuration. This code must agree with the code
- * that returns config descriptors, and with interface altsetting code.
- *
- * It's also responsible for power management interactions. Some
- * configurations might not work with our current power sources.
- * For now we just assume the gadget is always self-powered.
- */
-static int do_set_config(struct fsg_dev *fsg, u8 new_config)
-{
- int rc = 0;
-
- /* Disable the single interface */
- if (fsg->config != 0) {
- DBG(fsg, "reset config\n");
- fsg->config = 0;
- rc = do_set_interface(fsg, -1);
- }
-
- /* Enable the interface */
- if (new_config != 0) {
- fsg->config = new_config;
- if ((rc = do_set_interface(fsg, 0)) != 0)
- fsg->config = 0; // Reset on errors
- else
- INFO(fsg, "%s config #%d\n",
- usb_speed_string(fsg->gadget->speed),
- fsg->config);
- }
- return rc;
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-static void handle_exception(struct fsg_dev *fsg)
-{
- siginfo_t info;
- int sig;
- int i;
- int num_active;
- struct fsg_buffhd *bh;
- enum fsg_state old_state;
- u8 new_config;
- struct fsg_lun *curlun;
- unsigned int exception_req_tag;
- int rc;
-
- /* Clear the existing signals. Anything but SIGUSR1 is converted
- * into a high-priority EXIT exception. */
- for (;;) {
- sig = dequeue_signal_lock(current, &current->blocked, &info);
- if (!sig)
- break;
- if (sig != SIGUSR1) {
- if (fsg->state < FSG_STATE_EXIT)
- DBG(fsg, "Main thread exiting on signal\n");
- raise_exception(fsg, FSG_STATE_EXIT);
- }
- }
-
- /* Cancel all the pending transfers */
- if (fsg->intreq_busy)
- usb_ep_dequeue(fsg->intr_in, fsg->intreq);
- for (i = 0; i < fsg_num_buffers; ++i) {
- bh = &fsg->buffhds[i];
- if (bh->inreq_busy)
- usb_ep_dequeue(fsg->bulk_in, bh->inreq);
- if (bh->outreq_busy)
- usb_ep_dequeue(fsg->bulk_out, bh->outreq);
- }
-
- /* Wait until everything is idle */
- for (;;) {
- num_active = fsg->intreq_busy;
- for (i = 0; i < fsg_num_buffers; ++i) {
- bh = &fsg->buffhds[i];
- num_active += bh->inreq_busy + bh->outreq_busy;
- }
- if (num_active == 0)
- break;
- if (sleep_thread(fsg))
- return;
- }
-
- /* Clear out the controller's fifos */
- if (fsg->bulk_in_enabled)
- usb_ep_fifo_flush(fsg->bulk_in);
- if (fsg->bulk_out_enabled)
- usb_ep_fifo_flush(fsg->bulk_out);
- if (fsg->intr_in_enabled)
- usb_ep_fifo_flush(fsg->intr_in);
-
- /* Reset the I/O buffer states and pointers, the SCSI
- * state, and the exception. Then invoke the handler. */
- spin_lock_irq(&fsg->lock);
-
- for (i = 0; i < fsg_num_buffers; ++i) {
- bh = &fsg->buffhds[i];
- bh->state = BUF_STATE_EMPTY;
- }
- fsg->next_buffhd_to_fill = fsg->next_buffhd_to_drain =
- &fsg->buffhds[0];
-
- exception_req_tag = fsg->exception_req_tag;
- new_config = fsg->new_config;
- old_state = fsg->state;
-
- if (old_state == FSG_STATE_ABORT_BULK_OUT)
- fsg->state = FSG_STATE_STATUS_PHASE;
- else {
- for (i = 0; i < fsg->nluns; ++i) {
- curlun = &fsg->luns[i];
- curlun->prevent_medium_removal = 0;
- curlun->sense_data = curlun->unit_attention_data =
- SS_NO_SENSE;
- curlun->sense_data_info = 0;
- curlun->info_valid = 0;
- }
- fsg->state = FSG_STATE_IDLE;
- }
- spin_unlock_irq(&fsg->lock);
-
- /* Carry out any extra actions required for the exception */
- switch (old_state) {
- default:
- break;
-
- case FSG_STATE_ABORT_BULK_OUT:
- send_status(fsg);
- spin_lock_irq(&fsg->lock);
- if (fsg->state == FSG_STATE_STATUS_PHASE)
- fsg->state = FSG_STATE_IDLE;
- spin_unlock_irq(&fsg->lock);
- break;
-
- case FSG_STATE_RESET:
- /* In case we were forced against our will to halt a
- * bulk endpoint, clear the halt now. (The SuperH UDC
- * requires this.) */
- if (test_and_clear_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags))
- usb_ep_clear_halt(fsg->bulk_in);
-
- if (transport_is_bbb()) {
- if (fsg->ep0_req_tag == exception_req_tag)
- ep0_queue(fsg); // Complete the status stage
-
- } else if (transport_is_cbi())
- send_status(fsg); // Status by interrupt pipe
-
- /* Technically this should go here, but it would only be
- * a waste of time. Ditto for the INTERFACE_CHANGE and
- * CONFIG_CHANGE cases. */
- // for (i = 0; i < fsg->nluns; ++i)
- // fsg->luns[i].unit_attention_data = SS_RESET_OCCURRED;
- break;
-
- case FSG_STATE_INTERFACE_CHANGE:
- rc = do_set_interface(fsg, 0);
- if (fsg->ep0_req_tag != exception_req_tag)
- break;
- if (rc != 0) // STALL on errors
- fsg_set_halt(fsg, fsg->ep0);
- else // Complete the status stage
- ep0_queue(fsg);
- break;
-
- case FSG_STATE_CONFIG_CHANGE:
- rc = do_set_config(fsg, new_config);
- if (fsg->ep0_req_tag != exception_req_tag)
- break;
- if (rc != 0) // STALL on errors
- fsg_set_halt(fsg, fsg->ep0);
- else // Complete the status stage
- ep0_queue(fsg);
- break;
-
- case FSG_STATE_DISCONNECT:
- for (i = 0; i < fsg->nluns; ++i)
- fsg_lun_fsync_sub(fsg->luns + i);
- do_set_config(fsg, 0); // Unconfigured state
- break;
-
- case FSG_STATE_EXIT:
- case FSG_STATE_TERMINATED:
- do_set_config(fsg, 0); // Free resources
- spin_lock_irq(&fsg->lock);
- fsg->state = FSG_STATE_TERMINATED; // Stop the thread
- spin_unlock_irq(&fsg->lock);
- break;
- }
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-static int fsg_main_thread(void *fsg_)
-{
- struct fsg_dev *fsg = fsg_;
-
- /* Allow the thread to be killed by a signal, but set the signal mask
- * to block everything but INT, TERM, KILL, and USR1. */
- allow_signal(SIGINT);
- allow_signal(SIGTERM);
- allow_signal(SIGKILL);
- allow_signal(SIGUSR1);
-
- /* Allow the thread to be frozen */
- set_freezable();
-
- /* Arrange for userspace references to be interpreted as kernel
- * pointers. That way we can pass a kernel pointer to a routine
- * that expects a __user pointer and it will work okay. */
- set_fs(get_ds());
-
- /* The main loop */
- while (fsg->state != FSG_STATE_TERMINATED) {
- if (exception_in_progress(fsg) || signal_pending(current)) {
- handle_exception(fsg);
- continue;
- }
-
- if (!fsg->running) {
- sleep_thread(fsg);
- continue;
- }
-
- if (get_next_command(fsg))
- continue;
-
- spin_lock_irq(&fsg->lock);
- if (!exception_in_progress(fsg))
- fsg->state = FSG_STATE_DATA_PHASE;
- spin_unlock_irq(&fsg->lock);
-
- if (do_scsi_command(fsg) || finish_reply(fsg))
- continue;
-
- spin_lock_irq(&fsg->lock);
- if (!exception_in_progress(fsg))
- fsg->state = FSG_STATE_STATUS_PHASE;
- spin_unlock_irq(&fsg->lock);
-
- if (send_status(fsg))
- continue;
-
- spin_lock_irq(&fsg->lock);
- if (!exception_in_progress(fsg))
- fsg->state = FSG_STATE_IDLE;
- spin_unlock_irq(&fsg->lock);
- }
-
- spin_lock_irq(&fsg->lock);
- fsg->thread_task = NULL;
- spin_unlock_irq(&fsg->lock);
-
- /* If we are exiting because of a signal, unregister the
- * gadget driver. */
- if (test_and_clear_bit(REGISTERED, &fsg->atomic_bitflags))
- usb_gadget_unregister_driver(&fsg_driver);
-
- /* Let the unbind and cleanup routines know the thread has exited */
- complete_and_exit(&fsg->thread_notifier, 0);
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-
-/* The write permissions and store_xxx pointers are set in fsg_bind() */
-static DEVICE_ATTR(ro, 0444, fsg_show_ro, NULL);
-static DEVICE_ATTR(nofua, 0644, fsg_show_nofua, NULL);
-static DEVICE_ATTR(file, 0444, fsg_show_file, NULL);
-
-
-/*-------------------------------------------------------------------------*/
-
-static void fsg_release(struct kref *ref)
-{
- struct fsg_dev *fsg = container_of(ref, struct fsg_dev, ref);
-
- kfree(fsg->luns);
- kfree(fsg);
-}
-
-static void lun_release(struct device *dev)
-{
- struct rw_semaphore *filesem = dev_get_drvdata(dev);
- struct fsg_dev *fsg =
- container_of(filesem, struct fsg_dev, filesem);
-
- kref_put(&fsg->ref, fsg_release);
-}
-
-static void /* __init_or_exit */ fsg_unbind(struct usb_gadget *gadget)
-{
- struct fsg_dev *fsg = get_gadget_data(gadget);
- int i;
- struct fsg_lun *curlun;
- struct usb_request *req = fsg->ep0req;
-
- DBG(fsg, "unbind\n");
- clear_bit(REGISTERED, &fsg->atomic_bitflags);
-
- /* If the thread isn't already dead, tell it to exit now */
- if (fsg->state != FSG_STATE_TERMINATED) {
- raise_exception(fsg, FSG_STATE_EXIT);
- wait_for_completion(&fsg->thread_notifier);
-
- /* The cleanup routine waits for this completion also */
- complete(&fsg->thread_notifier);
- }
-
- /* Unregister the sysfs attribute files and the LUNs */
- for (i = 0; i < fsg->nluns; ++i) {
- curlun = &fsg->luns[i];
- if (curlun->registered) {
- device_remove_file(&curlun->dev, &dev_attr_nofua);
- device_remove_file(&curlun->dev, &dev_attr_ro);
- device_remove_file(&curlun->dev, &dev_attr_file);
- fsg_lun_close(curlun);
- device_unregister(&curlun->dev);
- curlun->registered = 0;
- }
- }
-
- /* Free the data buffers */
- for (i = 0; i < fsg_num_buffers; ++i)
- kfree(fsg->buffhds[i].buf);
-
- /* Free the request and buffer for endpoint 0 */
- if (req) {
- kfree(req->buf);
- usb_ep_free_request(fsg->ep0, req);
- }
-
- set_gadget_data(gadget, NULL);
-}
-
-
-static int __init check_parameters(struct fsg_dev *fsg)
-{
- int prot;
-
- /* Store the default values */
- mod_data.transport_type = USB_PR_BULK;
- mod_data.transport_name = "Bulk-only";
- mod_data.protocol_type = USB_SC_SCSI;
- mod_data.protocol_name = "Transparent SCSI";
-
- /* Some peripheral controllers are known not to be able to
- * halt bulk endpoints correctly. If one of them is present,
- * disable stalls.
- */
- if (gadget_is_at91(fsg->gadget))
- mod_data.can_stall = 0;
-
- if (mod_data.release == 0xffff)
- mod_data.release = get_default_bcdDevice();
-
- prot = simple_strtol(mod_data.protocol_parm, NULL, 0);
-
-#ifdef CONFIG_USB_FILE_STORAGE_TEST
- if (strnicmp(mod_data.transport_parm, "BBB", 10) == 0) {
- ; // Use default setting
- } else if (strnicmp(mod_data.transport_parm, "CB", 10) == 0) {
- mod_data.transport_type = USB_PR_CB;
- mod_data.transport_name = "Control-Bulk";
- } else if (strnicmp(mod_data.transport_parm, "CBI", 10) == 0) {
- mod_data.transport_type = USB_PR_CBI;
- mod_data.transport_name = "Control-Bulk-Interrupt";
- } else {
- ERROR(fsg, "invalid transport: %s\n", mod_data.transport_parm);
- return -EINVAL;
- }
-
- if (strnicmp(mod_data.protocol_parm, "SCSI", 10) == 0 ||
- prot == USB_SC_SCSI) {
- ; // Use default setting
- } else if (strnicmp(mod_data.protocol_parm, "RBC", 10) == 0 ||
- prot == USB_SC_RBC) {
- mod_data.protocol_type = USB_SC_RBC;
- mod_data.protocol_name = "RBC";
- } else if (strnicmp(mod_data.protocol_parm, "8020", 4) == 0 ||
- strnicmp(mod_data.protocol_parm, "ATAPI", 10) == 0 ||
- prot == USB_SC_8020) {
- mod_data.protocol_type = USB_SC_8020;
- mod_data.protocol_name = "8020i (ATAPI)";
- } else if (strnicmp(mod_data.protocol_parm, "QIC", 3) == 0 ||
- prot == USB_SC_QIC) {
- mod_data.protocol_type = USB_SC_QIC;
- mod_data.protocol_name = "QIC-157";
- } else if (strnicmp(mod_data.protocol_parm, "UFI", 10) == 0 ||
- prot == USB_SC_UFI) {
- mod_data.protocol_type = USB_SC_UFI;
- mod_data.protocol_name = "UFI";
- } else if (strnicmp(mod_data.protocol_parm, "8070", 4) == 0 ||
- prot == USB_SC_8070) {
- mod_data.protocol_type = USB_SC_8070;
- mod_data.protocol_name = "8070i";
- } else {
- ERROR(fsg, "invalid protocol: %s\n", mod_data.protocol_parm);
- return -EINVAL;
- }
-
- mod_data.buflen &= PAGE_CACHE_MASK;
- if (mod_data.buflen <= 0) {
- ERROR(fsg, "invalid buflen\n");
- return -ETOOSMALL;
- }
-
-#endif /* CONFIG_USB_FILE_STORAGE_TEST */
-
- /* Serial string handling.
- * On a real device, the serial string would be loaded
- * from permanent storage. */
- if (mod_data.serial) {
- const char *ch;
- unsigned len = 0;
-
- /* Sanity check :
- * The CB[I] specification limits the serial string to
- * 12 uppercase hexadecimal characters.
- * BBB need at least 12 uppercase hexadecimal characters,
- * with a maximum of 126. */
- for (ch = mod_data.serial; *ch; ++ch) {
- ++len;
- if ((*ch < '0' || *ch > '9') &&
- (*ch < 'A' || *ch > 'F')) { /* not uppercase hex */
- WARNING(fsg,
- "Invalid serial string character: %c\n",
- *ch);
- goto no_serial;
- }
- }
- if (len > 126 ||
- (mod_data.transport_type == USB_PR_BULK && len < 12) ||
- (mod_data.transport_type != USB_PR_BULK && len > 12)) {
- WARNING(fsg, "Invalid serial string length!\n");
- goto no_serial;
- }
- fsg_strings[FSG_STRING_SERIAL - 1].s = mod_data.serial;
- } else {
- WARNING(fsg, "No serial-number string provided!\n");
- no_serial:
- device_desc.iSerialNumber = 0;
- }
-
- return 0;
-}
-
-
-static int __init fsg_bind(struct usb_gadget *gadget,
- struct usb_gadget_driver *driver)
-{
- struct fsg_dev *fsg = the_fsg;
- int rc;
- int i;
- struct fsg_lun *curlun;
- struct usb_ep *ep;
- struct usb_request *req;
- char *pathbuf, *p;
-
- fsg->gadget = gadget;
- set_gadget_data(gadget, fsg);
- fsg->ep0 = gadget->ep0;
- fsg->ep0->driver_data = fsg;
-
- if ((rc = check_parameters(fsg)) != 0)
- goto out;
-
- if (mod_data.removable) { // Enable the store_xxx attributes
- dev_attr_file.attr.mode = 0644;
- dev_attr_file.store = fsg_store_file;
- if (!mod_data.cdrom) {
- dev_attr_ro.attr.mode = 0644;
- dev_attr_ro.store = fsg_store_ro;
- }
- }
-
- /* Only for removable media? */
- dev_attr_nofua.attr.mode = 0644;
- dev_attr_nofua.store = fsg_store_nofua;
-
- /* Find out how many LUNs there should be */
- i = mod_data.nluns;
- if (i == 0)
- i = max(mod_data.num_filenames, 1u);
- if (i > FSG_MAX_LUNS) {
- ERROR(fsg, "invalid number of LUNs: %d\n", i);
- rc = -EINVAL;
- goto out;
- }
-
- /* Create the LUNs, open their backing files, and register the
- * LUN devices in sysfs. */
- fsg->luns = kzalloc(i * sizeof(struct fsg_lun), GFP_KERNEL);
- if (!fsg->luns) {
- rc = -ENOMEM;
- goto out;
- }
- fsg->nluns = i;
-
- for (i = 0; i < fsg->nluns; ++i) {
- curlun = &fsg->luns[i];
- curlun->cdrom = !!mod_data.cdrom;
- curlun->ro = mod_data.cdrom || mod_data.ro[i];
- curlun->initially_ro = curlun->ro;
- curlun->removable = mod_data.removable;
- curlun->nofua = mod_data.nofua[i];
- curlun->dev.release = lun_release;
- curlun->dev.parent = &gadget->dev;
- curlun->dev.driver = &fsg_driver.driver;
- dev_set_drvdata(&curlun->dev, &fsg->filesem);
- dev_set_name(&curlun->dev,"%s-lun%d",
- dev_name(&gadget->dev), i);
-
- kref_get(&fsg->ref);
- rc = device_register(&curlun->dev);
- if (rc) {
- INFO(fsg, "failed to register LUN%d: %d\n", i, rc);
- put_device(&curlun->dev);
- goto out;
- }
- curlun->registered = 1;
-
- rc = device_create_file(&curlun->dev, &dev_attr_ro);
- if (rc)
- goto out;
- rc = device_create_file(&curlun->dev, &dev_attr_nofua);
- if (rc)
- goto out;
- rc = device_create_file(&curlun->dev, &dev_attr_file);
- if (rc)
- goto out;
-
- if (mod_data.file[i] && *mod_data.file[i]) {
- rc = fsg_lun_open(curlun, mod_data.file[i]);
- if (rc)
- goto out;
- } else if (!mod_data.removable) {
- ERROR(fsg, "no file given for LUN%d\n", i);
- rc = -EINVAL;
- goto out;
- }
- }
-
- /* Find all the endpoints we will use */
- usb_ep_autoconfig_reset(gadget);
- ep = usb_ep_autoconfig(gadget, &fsg_fs_bulk_in_desc);
- if (!ep)
- goto autoconf_fail;
- ep->driver_data = fsg; // claim the endpoint
- fsg->bulk_in = ep;
-
- ep = usb_ep_autoconfig(gadget, &fsg_fs_bulk_out_desc);
- if (!ep)
- goto autoconf_fail;
- ep->driver_data = fsg; // claim the endpoint
- fsg->bulk_out = ep;
-
- if (transport_is_cbi()) {
- ep = usb_ep_autoconfig(gadget, &fsg_fs_intr_in_desc);
- if (!ep)
- goto autoconf_fail;
- ep->driver_data = fsg; // claim the endpoint
- fsg->intr_in = ep;
- }
-
- /* Fix up the descriptors */
- device_desc.idVendor = cpu_to_le16(mod_data.vendor);
- device_desc.idProduct = cpu_to_le16(mod_data.product);
- device_desc.bcdDevice = cpu_to_le16(mod_data.release);
-
- i = (transport_is_cbi() ? 3 : 2); // Number of endpoints
- fsg_intf_desc.bNumEndpoints = i;
- fsg_intf_desc.bInterfaceSubClass = mod_data.protocol_type;
- fsg_intf_desc.bInterfaceProtocol = mod_data.transport_type;
- fsg_fs_function[i + FSG_FS_FUNCTION_PRE_EP_ENTRIES] = NULL;
-
- if (gadget_is_dualspeed(gadget)) {
- fsg_hs_function[i + FSG_HS_FUNCTION_PRE_EP_ENTRIES] = NULL;
-
- /* Assume endpoint addresses are the same for both speeds */
- fsg_hs_bulk_in_desc.bEndpointAddress =
- fsg_fs_bulk_in_desc.bEndpointAddress;
- fsg_hs_bulk_out_desc.bEndpointAddress =
- fsg_fs_bulk_out_desc.bEndpointAddress;
- fsg_hs_intr_in_desc.bEndpointAddress =
- fsg_fs_intr_in_desc.bEndpointAddress;
- }
-
- if (gadget_is_superspeed(gadget)) {
- unsigned max_burst;
-
- fsg_ss_function[i + FSG_SS_FUNCTION_PRE_EP_ENTRIES] = NULL;
-
- /* Calculate bMaxBurst, we know packet size is 1024 */
- max_burst = min_t(unsigned, mod_data.buflen / 1024, 15);
-
- /* Assume endpoint addresses are the same for both speeds */
- fsg_ss_bulk_in_desc.bEndpointAddress =
- fsg_fs_bulk_in_desc.bEndpointAddress;
- fsg_ss_bulk_in_comp_desc.bMaxBurst = max_burst;
-
- fsg_ss_bulk_out_desc.bEndpointAddress =
- fsg_fs_bulk_out_desc.bEndpointAddress;
- fsg_ss_bulk_out_comp_desc.bMaxBurst = max_burst;
- }
-
- if (gadget_is_otg(gadget))
- fsg_otg_desc.bmAttributes |= USB_OTG_HNP;
-
- rc = -ENOMEM;
-
- /* Allocate the request and buffer for endpoint 0 */
- fsg->ep0req = req = usb_ep_alloc_request(fsg->ep0, GFP_KERNEL);
- if (!req)
- goto out;
- req->buf = kmalloc(EP0_BUFSIZE, GFP_KERNEL);
- if (!req->buf)
- goto out;
- req->complete = ep0_complete;
-
- /* Allocate the data buffers */
- for (i = 0; i < fsg_num_buffers; ++i) {
- struct fsg_buffhd *bh = &fsg->buffhds[i];
-
- /* Allocate for the bulk-in endpoint. We assume that
- * the buffer will also work with the bulk-out (and
- * interrupt-in) endpoint. */
- bh->buf = kmalloc(mod_data.buflen, GFP_KERNEL);
- if (!bh->buf)
- goto out;
- bh->next = bh + 1;
- }
- fsg->buffhds[fsg_num_buffers - 1].next = &fsg->buffhds[0];
-
- /* This should reflect the actual gadget power source */
- usb_gadget_set_selfpowered(gadget);
-
- snprintf(fsg_string_manufacturer, sizeof fsg_string_manufacturer,
- "%s %s with %s",
- init_utsname()->sysname, init_utsname()->release,
- gadget->name);
-
- fsg->thread_task = kthread_create(fsg_main_thread, fsg,
- "file-storage-gadget");
- if (IS_ERR(fsg->thread_task)) {
- rc = PTR_ERR(fsg->thread_task);
- goto out;
- }
-
- INFO(fsg, DRIVER_DESC ", version: " DRIVER_VERSION "\n");
- INFO(fsg, "NOTE: This driver is deprecated. "
- "Consider using g_mass_storage instead.\n");
- INFO(fsg, "Number of LUNs=%d\n", fsg->nluns);
-
- pathbuf = kmalloc(PATH_MAX, GFP_KERNEL);
- for (i = 0; i < fsg->nluns; ++i) {
- curlun = &fsg->luns[i];
- if (fsg_lun_is_open(curlun)) {
- p = NULL;
- if (pathbuf) {
- p = d_path(&curlun->filp->f_path,
- pathbuf, PATH_MAX);
- if (IS_ERR(p))
- p = NULL;
- }
- LINFO(curlun, "ro=%d, nofua=%d, file: %s\n",
- curlun->ro, curlun->nofua, (p ? p : "(error)"));
- }
- }
- kfree(pathbuf);
-
- DBG(fsg, "transport=%s (x%02x)\n",
- mod_data.transport_name, mod_data.transport_type);
- DBG(fsg, "protocol=%s (x%02x)\n",
- mod_data.protocol_name, mod_data.protocol_type);
- DBG(fsg, "VendorID=x%04x, ProductID=x%04x, Release=x%04x\n",
- mod_data.vendor, mod_data.product, mod_data.release);
- DBG(fsg, "removable=%d, stall=%d, cdrom=%d, buflen=%u\n",
- mod_data.removable, mod_data.can_stall,
- mod_data.cdrom, mod_data.buflen);
- DBG(fsg, "I/O thread pid: %d\n", task_pid_nr(fsg->thread_task));
-
- set_bit(REGISTERED, &fsg->atomic_bitflags);
-
- /* Tell the thread to start working */
- wake_up_process(fsg->thread_task);
- return 0;
-
-autoconf_fail:
- ERROR(fsg, "unable to autoconfigure all endpoints\n");
- rc = -ENOTSUPP;
-
-out:
- fsg->state = FSG_STATE_TERMINATED; // The thread is dead
- fsg_unbind(gadget);
- complete(&fsg->thread_notifier);
- return rc;
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-static void fsg_suspend(struct usb_gadget *gadget)
-{
- struct fsg_dev *fsg = get_gadget_data(gadget);
-
- DBG(fsg, "suspend\n");
- set_bit(SUSPENDED, &fsg->atomic_bitflags);
-}
-
-static void fsg_resume(struct usb_gadget *gadget)
-{
- struct fsg_dev *fsg = get_gadget_data(gadget);
-
- DBG(fsg, "resume\n");
- clear_bit(SUSPENDED, &fsg->atomic_bitflags);
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-static __refdata struct usb_gadget_driver fsg_driver = {
- .max_speed = USB_SPEED_SUPER,
- .function = (char *) fsg_string_product,
- .bind = fsg_bind,
- .unbind = fsg_unbind,
- .disconnect = fsg_disconnect,
- .setup = fsg_setup,
- .suspend = fsg_suspend,
- .resume = fsg_resume,
-
- .driver = {
- .name = DRIVER_NAME,
- .owner = THIS_MODULE,
- // .release = ...
- // .suspend = ...
- // .resume = ...
- },
-};
-
-
-static int __init fsg_alloc(void)
-{
- struct fsg_dev *fsg;
-
- fsg = kzalloc(sizeof *fsg +
- fsg_num_buffers * sizeof *(fsg->buffhds), GFP_KERNEL);
-
- if (!fsg)
- return -ENOMEM;
- spin_lock_init(&fsg->lock);
- init_rwsem(&fsg->filesem);
- kref_init(&fsg->ref);
- init_completion(&fsg->thread_notifier);
-
- the_fsg = fsg;
- return 0;
-}
-
-
-static int __init fsg_init(void)
-{
- int rc;
- struct fsg_dev *fsg;
-
- rc = fsg_num_buffers_validate();
- if (rc != 0)
- return rc;
-
- if ((rc = fsg_alloc()) != 0)
- return rc;
- fsg = the_fsg;
- rc = usb_gadget_probe_driver(&fsg_driver);
- if (rc != 0)
- kref_put(&fsg->ref, fsg_release);
- return rc;
-}
-module_init(fsg_init);
-
-
-static void __exit fsg_cleanup(void)
-{
- struct fsg_dev *fsg = the_fsg;
-
- /* Unregister the driver iff the thread hasn't already done so */
- if (test_and_clear_bit(REGISTERED, &fsg->atomic_bitflags))
- usb_gadget_unregister_driver(&fsg_driver);
-
- /* Wait for the thread to finish up */
- wait_for_completion(&fsg->thread_notifier);
-
- kref_put(&fsg->ref, fsg_release);
-}
-module_exit(fsg_cleanup);
diff --git a/drivers/usb/gadget/fsl_qe_udc.c b/drivers/usb/gadget/fsl_qe_udc.c
index b09452d6f33a..ec50f18c8890 100644
--- a/drivers/usb/gadget/fsl_qe_udc.c
+++ b/drivers/usb/gadget/fsl_qe_udc.c
@@ -2347,7 +2347,7 @@ static int fsl_qe_stop(struct usb_gadget *gadget,
}
/* udc structure's alloc and setup, include ep-param alloc */
-static struct qe_udc __devinit *qe_udc_config(struct platform_device *ofdev)
+static struct qe_udc *qe_udc_config(struct platform_device *ofdev)
{
struct qe_udc *udc;
struct device_node *np = ofdev->dev.of_node;
@@ -2402,7 +2402,7 @@ cleanup:
}
/* USB Controller register init */
-static int __devinit qe_udc_reg_init(struct qe_udc *udc)
+static int qe_udc_reg_init(struct qe_udc *udc)
{
struct usb_ctlr __iomem *qe_usbregs;
qe_usbregs = udc->usb_regs;
@@ -2420,7 +2420,7 @@ static int __devinit qe_udc_reg_init(struct qe_udc *udc)
return 0;
}
-static int __devinit qe_ep_config(struct qe_udc *udc, unsigned char pipe_num)
+static int qe_ep_config(struct qe_udc *udc, unsigned char pipe_num)
{
struct qe_ep *ep = &udc->eps[pipe_num];
@@ -2473,7 +2473,7 @@ static void qe_udc_release(struct device *dev)
/* Driver probe functions */
static const struct of_device_id qe_udc_match[];
-static int __devinit qe_udc_probe(struct platform_device *ofdev)
+static int qe_udc_probe(struct platform_device *ofdev)
{
struct qe_udc *udc;
const struct of_device_id *match;
@@ -2651,7 +2651,7 @@ static int qe_udc_resume(struct platform_device *dev)
}
#endif
-static int __devexit qe_udc_remove(struct platform_device *ofdev)
+static int qe_udc_remove(struct platform_device *ofdev)
{
struct qe_udc *udc = dev_get_drvdata(&ofdev->dev);
struct qe_ep *ep;
@@ -2710,7 +2710,7 @@ static int __devexit qe_udc_remove(struct platform_device *ofdev)
}
/*-------------------------------------------------------------------------*/
-static const struct of_device_id qe_udc_match[] __devinitconst = {
+static const struct of_device_id qe_udc_match[] = {
{
.compatible = "fsl,mpc8323-qe-usb",
.data = (void *)PORT_QE,
@@ -2735,7 +2735,7 @@ static struct platform_driver udc_driver = {
.of_match_table = qe_udc_match,
},
.probe = qe_udc_probe,
- .remove = __devexit_p(qe_udc_remove),
+ .remove = qe_udc_remove,
#ifdef CONFIG_PM
.suspend = qe_udc_suspend,
.resume = qe_udc_resume,
diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c
index 6ae70cba0c4a..c19f7f13790b 100644
--- a/drivers/usb/gadget/fsl_udc_core.c
+++ b/drivers/usb/gadget/fsl_udc_core.c
@@ -2126,7 +2126,7 @@ static int fsl_proc_read(char *page, char **start, off_t off, int count,
tmp_reg = fsl_readl(&dr_regs->usbintr);
t = scnprintf(next, size,
- "USB Intrrupt Enable Reg:\n"
+ "USB Interrupt Enable Reg:\n"
"Sleep Enable: %d SOF Received Enable: %d "
"Reset Enable: %d\n"
"System Error Enable: %d "
diff --git a/drivers/usb/gadget/hid.c b/drivers/usb/gadget/hid.c
index 74130f6c12c0..c36260ea8bf2 100644
--- a/drivers/usb/gadget/hid.c
+++ b/drivers/usb/gadget/hid.c
@@ -203,7 +203,7 @@ static int __init hidg_plat_driver_probe(struct platform_device *pdev)
return 0;
}
-static int __devexit hidg_plat_driver_remove(struct platform_device *pdev)
+static int hidg_plat_driver_remove(struct platform_device *pdev)
{
struct hidg_func_node *e, *n;
@@ -229,7 +229,7 @@ static __refdata struct usb_composite_driver hidg_driver = {
};
static struct platform_driver hidg_plat_driver = {
- .remove = __devexit_p(hidg_plat_driver_remove),
+ .remove = hidg_plat_driver_remove,
.driver = {
.owner = THIS_MODULE,
.name = "hidg",
diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c
index 76494cabf4e4..8ac840f25ba9 100644
--- a/drivers/usb/gadget/inode.c
+++ b/drivers/usb/gadget/inode.c
@@ -76,7 +76,6 @@ MODULE_LICENSE ("GPL");
/*----------------------------------------------------------------------*/
#define GADGETFS_MAGIC 0xaee71ee7
-#define DMA_ADDR_INVALID (~(dma_addr_t)0)
/* /dev/gadget/$CHIP represents ep0 and the whole device */
enum ep0_state {
@@ -918,7 +917,6 @@ static void clean_req (struct usb_ep *ep, struct usb_request *req)
if (req->buf != dev->rbuf) {
kfree(req->buf);
req->buf = dev->rbuf;
- req->dma = DMA_ADDR_INVALID;
}
req->complete = epio_complete;
dev->setup_out_ready = 0;
@@ -1408,7 +1406,6 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
dev->setup_abort = 1;
req->buf = dev->rbuf;
- req->dma = DMA_ADDR_INVALID;
req->context = NULL;
value = -EOPNOTSUPP;
switch (ctrl->bRequest) {
diff --git a/drivers/usb/gadget/lpc32xx_udc.c b/drivers/usb/gadget/lpc32xx_udc.c
index 21a9861dabf0..dd1c9b1fe528 100644
--- a/drivers/usb/gadget/lpc32xx_udc.c
+++ b/drivers/usb/gadget/lpc32xx_udc.c
@@ -2399,7 +2399,7 @@ static void udc_handle_ep0_setup(struct lpc32xx_udc *udc)
if (i < 0) {
/* setup processing failed, force stall */
- dev_err(udc->dev,
+ dev_dbg(udc->dev,
"req %02x.%02x protocol STALL; stat %d\n",
reqtype, req, i);
udc->ep0state = WAIT_FOR_SETUP;
@@ -3352,7 +3352,7 @@ phy_fail:
return retval;
}
-static int __devexit lpc32xx_udc_remove(struct platform_device *pdev)
+static int lpc32xx_udc_remove(struct platform_device *pdev)
{
struct lpc32xx_udc *udc = platform_get_drvdata(pdev);
@@ -3447,7 +3447,7 @@ MODULE_DEVICE_TABLE(of, lpc32xx_udc_of_match);
#endif
static struct platform_driver lpc32xx_udc_driver = {
- .remove = __devexit_p(lpc32xx_udc_remove),
+ .remove = lpc32xx_udc_remove,
.shutdown = lpc32xx_udc_shutdown,
.suspend = lpc32xx_udc_suspend,
.resume = lpc32xx_udc_resume,
diff --git a/drivers/usb/gadget/mv_u3d_core.c b/drivers/usb/gadget/mv_u3d_core.c
index 8cfd5b028dbd..b5cea273c957 100644
--- a/drivers/usb/gadget/mv_u3d_core.c
+++ b/drivers/usb/gadget/mv_u3d_core.c
@@ -1763,7 +1763,7 @@ static void mv_u3d_gadget_release(struct device *dev)
dev_dbg(dev, "%s\n", __func__);
}
-static __devexit int mv_u3d_remove(struct platform_device *dev)
+static int mv_u3d_remove(struct platform_device *dev)
{
struct mv_u3d *u3d = platform_get_drvdata(dev);
diff --git a/drivers/usb/gadget/mv_udc_core.c b/drivers/usb/gadget/mv_udc_core.c
index ea45224f78c8..379aac7b82fc 100644
--- a/drivers/usb/gadget/mv_udc_core.c
+++ b/drivers/usb/gadget/mv_udc_core.c
@@ -2128,7 +2128,7 @@ static void gadget_release(struct device *_dev)
complete(udc->done);
}
-static int __devexit mv_udc_remove(struct platform_device *dev)
+static int mv_udc_remove(struct platform_device *dev)
{
struct mv_udc *udc = the_controller;
int clk_i;
@@ -2188,7 +2188,7 @@ static int __devexit mv_udc_remove(struct platform_device *dev)
return 0;
}
-static int __devinit mv_udc_probe(struct platform_device *dev)
+static int mv_udc_probe(struct platform_device *dev)
{
struct mv_usb_platform_data *pdata = dev->dev.platform_data;
struct mv_udc *udc;
diff --git a/drivers/usb/gadget/net2272.c b/drivers/usb/gadget/net2272.c
index c009263a47e3..d226058e3b88 100644
--- a/drivers/usb/gadget/net2272.c
+++ b/drivers/usb/gadget/net2272.c
@@ -2193,7 +2193,7 @@ net2272_gadget_release(struct device *_dev)
/*---------------------------------------------------------------------------*/
-static void __devexit
+static void
net2272_remove(struct net2272 *dev)
{
usb_del_gadget_udc(&dev->gadget);
@@ -2215,8 +2215,7 @@ net2272_remove(struct net2272 *dev)
dev_info(dev->dev, "unbind\n");
}
-static struct net2272 * __devinit
-net2272_probe_init(struct device *dev, unsigned int irq)
+static struct net2272 *net2272_probe_init(struct device *dev, unsigned int irq)
{
struct net2272 *ret;
@@ -2246,7 +2245,7 @@ net2272_probe_init(struct device *dev, unsigned int irq)
return ret;
}
-static int __devinit
+static int
net2272_probe_fin(struct net2272 *dev, unsigned int irqflags)
{
int ret;
@@ -2306,7 +2305,7 @@ err_add_udc:
* don't respond over USB until a gadget driver binds to us
*/
-static int __devinit
+static int
net2272_rdk1_probe(struct pci_dev *pdev, struct net2272 *dev)
{
unsigned long resource, len, tmp;
@@ -2389,7 +2388,7 @@ net2272_rdk1_probe(struct pci_dev *pdev, struct net2272 *dev)
return ret;
}
-static int __devinit
+static int
net2272_rdk2_probe(struct pci_dev *pdev, struct net2272 *dev)
{
unsigned long resource, len;
@@ -2447,7 +2446,7 @@ net2272_rdk2_probe(struct pci_dev *pdev, struct net2272 *dev)
return ret;
}
-static int __devinit
+static int
net2272_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
struct net2272 *dev;
@@ -2489,7 +2488,7 @@ net2272_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
return ret;
}
-static void __devexit
+static void
net2272_rdk1_remove(struct pci_dev *pdev, struct net2272 *dev)
{
int i;
@@ -2511,7 +2510,7 @@ net2272_rdk1_remove(struct pci_dev *pdev, struct net2272 *dev)
}
}
-static void __devexit
+static void
net2272_rdk2_remove(struct pci_dev *pdev, struct net2272 *dev)
{
int i;
@@ -2530,7 +2529,7 @@ net2272_rdk2_remove(struct pci_dev *pdev, struct net2272 *dev)
pci_resource_len(pdev, i));
}
-static void __devexit
+static void
net2272_pci_remove(struct pci_dev *pdev)
{
struct net2272 *dev = pci_get_drvdata(pdev);
@@ -2549,7 +2548,7 @@ net2272_pci_remove(struct pci_dev *pdev)
}
/* Table of matching PCI IDs */
-static struct pci_device_id __devinitdata pci_ids[] = {
+static struct pci_device_id pci_ids[] = {
{ /* RDK 1 card */
.class = ((PCI_CLASS_BRIDGE_OTHER << 8) | 0xfe),
.class_mask = 0,
@@ -2575,7 +2574,7 @@ static struct pci_driver net2272_pci_driver = {
.id_table = pci_ids,
.probe = net2272_pci_probe,
- .remove = __devexit_p(net2272_pci_remove),
+ .remove = net2272_pci_remove,
};
static int net2272_pci_register(void)
@@ -2595,7 +2594,7 @@ static inline void net2272_pci_unregister(void) { }
/*---------------------------------------------------------------------------*/
-static int __devinit
+static int
net2272_plat_probe(struct platform_device *pdev)
{
struct net2272 *dev;
@@ -2661,7 +2660,7 @@ net2272_plat_probe(struct platform_device *pdev)
return ret;
}
-static int __devexit
+static int
net2272_plat_remove(struct platform_device *pdev)
{
struct net2272 *dev = platform_get_drvdata(pdev);
@@ -2678,7 +2677,7 @@ net2272_plat_remove(struct platform_device *pdev)
static struct platform_driver net2272_plat_driver = {
.probe = net2272_plat_probe,
- .remove = __devexit_p(net2272_plat_remove),
+ .remove = net2272_plat_remove,
.driver = {
.name = driver_name,
.owner = THIS_MODULE,
diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c
index ac335af154ba..708c0b55dcc8 100644
--- a/drivers/usb/gadget/net2280.c
+++ b/drivers/usb/gadget/net2280.c
@@ -9,7 +9,7 @@
* CODE STATUS HIGHLIGHTS
*
* This driver should work well with most "gadget" drivers, including
- * the File Storage, Serial, and Ethernet/RNDIS gadget drivers
+ * the Mass Storage, Serial, and Ethernet/RNDIS gadget drivers
* as well as Gadget Zero and Gadgetfs.
*
* DMA is enabled by default. Drivers using transfer queues might use
diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c
index 2a4749c3eb3f..9412bf53b864 100644
--- a/drivers/usb/gadget/omap_udc.c
+++ b/drivers/usb/gadget/omap_udc.c
@@ -2506,7 +2506,7 @@ static inline void remove_proc_file(void) {}
* UDC_SYSCON_1.CFG_LOCK is set can now work. We won't use that
* capability yet though.
*/
-static unsigned __devinit
+static unsigned
omap_ep_setup(char *name, u8 addr, u8 type,
unsigned buf, unsigned maxp, int dbuf)
{
@@ -2624,7 +2624,7 @@ static void omap_udc_release(struct device *dev)
udc = NULL;
}
-static int __devinit
+static int
omap_udc_setup(struct platform_device *odev, struct usb_phy *xceiv)
{
unsigned tmp, buf;
@@ -2761,7 +2761,7 @@ omap_udc_setup(struct platform_device *odev, struct usb_phy *xceiv)
return 0;
}
-static int __devinit omap_udc_probe(struct platform_device *pdev)
+static int omap_udc_probe(struct platform_device *pdev)
{
int status = -ENODEV;
int hmc;
@@ -2974,7 +2974,7 @@ cleanup0:
return status;
}
-static int __devexit omap_udc_remove(struct platform_device *pdev)
+static int omap_udc_remove(struct platform_device *pdev)
{
DECLARE_COMPLETION_ONSTACK(done);
@@ -3060,7 +3060,7 @@ static int omap_udc_resume(struct platform_device *dev)
static struct platform_driver udc_driver = {
.probe = omap_udc_probe,
- .remove = __devexit_p(omap_udc_remove),
+ .remove = omap_udc_remove,
.suspend = omap_udc_suspend,
.resume = omap_udc_resume,
.driver = {
diff --git a/drivers/usb/gadget/printer.c b/drivers/usb/gadget/printer.c
index e156e3f26727..35bcc83d1e04 100644
--- a/drivers/usb/gadget/printer.c
+++ b/drivers/usb/gadget/printer.c
@@ -983,8 +983,10 @@ static int __init printer_func_bind(struct usb_configuration *c,
{
struct printer_dev *dev = container_of(f, struct printer_dev, function);
struct usb_composite_dev *cdev = c->cdev;
- struct usb_ep *in_ep, *out_ep;
+ struct usb_ep *in_ep;
+ struct usb_ep *out_ep = NULL;
int id;
+ int ret;
id = usb_interface_id(c, f);
if (id < 0)
@@ -1010,6 +1012,11 @@ autoconf_fail:
hs_ep_in_desc.bEndpointAddress = fs_ep_in_desc.bEndpointAddress;
hs_ep_out_desc.bEndpointAddress = fs_ep_out_desc.bEndpointAddress;
+ ret = usb_assign_descriptors(f, fs_printer_function,
+ hs_printer_function, NULL);
+ if (ret)
+ return ret;
+
dev->in_ep = in_ep;
dev->out_ep = out_ep;
return 0;
@@ -1018,6 +1025,7 @@ autoconf_fail:
static void printer_func_unbind(struct usb_configuration *c,
struct usb_function *f)
{
+ usb_free_all_descriptors(f);
}
static int printer_func_set_alt(struct usb_function *f,
@@ -1110,8 +1118,6 @@ static int __init printer_bind_config(struct usb_configuration *c)
dev = &usb_printer_gadget;
dev->function.name = shortname;
- dev->function.descriptors = fs_printer_function;
- dev->function.hs_descriptors = hs_printer_function;
dev->function.bind = printer_func_bind;
dev->function.setup = printer_func_setup;
dev->function.unbind = printer_func_unbind;
diff --git a/drivers/usb/gadget/pxa27x_udc.h b/drivers/usb/gadget/pxa27x_udc.h
index a1d268c6f2cc..79d81a4b2344 100644
--- a/drivers/usb/gadget/pxa27x_udc.h
+++ b/drivers/usb/gadget/pxa27x_udc.h
@@ -418,7 +418,7 @@ struct udc_stats {
* @irq: udc irq
* @clk: udc clock
* @usb_gadget: udc gadget structure
- * @driver: bound gadget (zero, g_ether, g_file_storage, ...)
+ * @driver: bound gadget (zero, g_ether, g_mass_storage, ...)
* @dev: device
* @mach: machine info, used to activate specific GPIO
* @transceiver: external transceiver to handle vbus sense and D+ pullup
diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c
index 6f696ee8b817..141971d9051e 100644
--- a/drivers/usb/gadget/s3c-hsotg.c
+++ b/drivers/usb/gadget/s3c-hsotg.c
@@ -3072,7 +3072,7 @@ static struct usb_gadget_ops s3c_hsotg_gadget_ops = {
* creation) to give to the gadget driver. Setup the endpoint name, any
* direction information and other state that may be required.
*/
-static void __devinit s3c_hsotg_initep(struct s3c_hsotg *hsotg,
+static void s3c_hsotg_initep(struct s3c_hsotg *hsotg,
struct s3c_hsotg_ep *hs_ep,
int epnum)
{
@@ -3414,7 +3414,7 @@ static const struct file_operations ep_fops = {
* with the same name as the device itself, in case we end up
* with multiple blocks in future systems.
*/
-static void __devinit s3c_hsotg_create_debug(struct s3c_hsotg *hsotg)
+static void s3c_hsotg_create_debug(struct s3c_hsotg *hsotg)
{
struct dentry *root;
unsigned epidx;
@@ -3460,7 +3460,7 @@ static void __devinit s3c_hsotg_create_debug(struct s3c_hsotg *hsotg)
*
* Cleanup (remove) the debugfs files for use on module exit.
*/
-static void __devexit s3c_hsotg_delete_debug(struct s3c_hsotg *hsotg)
+static void s3c_hsotg_delete_debug(struct s3c_hsotg *hsotg)
{
unsigned epidx;
@@ -3490,7 +3490,7 @@ static void s3c_hsotg_release(struct device *dev)
* @pdev: The platform information for the driver
*/
-static int __devinit s3c_hsotg_probe(struct platform_device *pdev)
+static int s3c_hsotg_probe(struct platform_device *pdev)
{
struct s3c_hsotg_plat *plat = pdev->dev.platform_data;
struct device *dev = &pdev->dev;
@@ -3675,7 +3675,7 @@ err_clk:
* s3c_hsotg_remove - remove function for hsotg driver
* @pdev: The platform information for the driver
*/
-static int __devexit s3c_hsotg_remove(struct platform_device *pdev)
+static int s3c_hsotg_remove(struct platform_device *pdev)
{
struct s3c_hsotg *hsotg = platform_get_drvdata(pdev);
@@ -3708,7 +3708,7 @@ static struct platform_driver s3c_hsotg_driver = {
.owner = THIS_MODULE,
},
.probe = s3c_hsotg_probe,
- .remove = __devexit_p(s3c_hsotg_remove),
+ .remove = s3c_hsotg_remove,
.suspend = s3c_hsotg_suspend,
.resume = s3c_hsotg_resume,
};
diff --git a/drivers/usb/gadget/s3c-hsudc.c b/drivers/usb/gadget/s3c-hsudc.c
index d8e785d4ad59..52379b11f080 100644
--- a/drivers/usb/gadget/s3c-hsudc.c
+++ b/drivers/usb/gadget/s3c-hsudc.c
@@ -1261,7 +1261,7 @@ static struct usb_gadget_ops s3c_hsudc_gadget_ops = {
.vbus_draw = s3c_hsudc_vbus_draw,
};
-static int __devinit s3c_hsudc_probe(struct platform_device *pdev)
+static int s3c_hsudc_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct resource *res;
diff --git a/drivers/usb/gadget/storage_common.c b/drivers/usb/gadget/storage_common.c
index 8d9bcd8207c8..0e3ae43454a2 100644
--- a/drivers/usb/gadget/storage_common.c
+++ b/drivers/usb/gadget/storage_common.c
@@ -11,30 +11,10 @@
* (at your option) any later version.
*/
-
/*
* This file requires the following identifiers used in USB strings to
* be defined (each of type pointer to char):
- * - fsg_string_manufacturer -- name of the manufacturer
- * - fsg_string_product -- name of the product
- * - fsg_string_config -- name of the configuration
* - fsg_string_interface -- name of the interface
- * The first four are only needed when FSG_DESCRIPTORS_DEVICE_STRINGS
- * macro is defined prior to including this file.
- */
-
-/*
- * When FSG_NO_INTR_EP is defined fsg_fs_intr_in_desc and
- * fsg_hs_intr_in_desc objects as well as
- * FSG_FS_FUNCTION_PRE_EP_ENTRIES and FSG_HS_FUNCTION_PRE_EP_ENTRIES
- * macros are not defined.
- *
- * When FSG_NO_DEVICE_STRINGS is defined FSG_STRING_MANUFACTURER,
- * FSG_STRING_PRODUCT, FSG_STRING_SERIAL and FSG_STRING_CONFIG are not
- * defined (as well as corresponding entries in string tables are
- * missing) and FSG_STRING_INTERFACE has value of zero.
- *
- * When FSG_NO_OTG is defined fsg_otg_desc won't be defined.
*/
/*
@@ -78,34 +58,6 @@
#define LWARN(lun, fmt, args...) dev_warn(&(lun)->dev, fmt, ## args)
#define LINFO(lun, fmt, args...) dev_info(&(lun)->dev, fmt, ## args)
-/*
- * Keep those macros in sync with those in
- * include/linux/usb/composite.h or else GCC will complain. If they
- * are identical (the same names of arguments, white spaces in the
- * same places) GCC will allow redefinition otherwise (even if some
- * white space is removed or added) warning will be issued.
- *
- * Those macros are needed here because File Storage Gadget does not
- * include the composite.h header. For composite gadgets those macros
- * are redundant since composite.h is included any way.
- *
- * One could check whether those macros are already defined (which
- * would indicate composite.h had been included) or not (which would
- * indicate we were in FSG) but this is not done because a warning is
- * desired if definitions here differ from the ones in composite.h.
- *
- * We want the definitions to match and be the same in File Storage
- * Gadget as well as Mass Storage Function (and so composite gadgets
- * using MSF). If someone changes them in composite.h it will produce
- * a warning in this file when building MSF.
- */
-#define DBG(d, fmt, args...) dev_dbg(&(d)->gadget->dev , fmt , ## args)
-#define VDBG(d, fmt, args...) dev_vdbg(&(d)->gadget->dev , fmt , ## args)
-#define ERROR(d, fmt, args...) dev_err(&(d)->gadget->dev , fmt , ## args)
-#define WARNING(d, fmt, args...) dev_warn(&(d)->gadget->dev , fmt , ## args)
-#define INFO(d, fmt, args...) dev_info(&(d)->gadget->dev , fmt , ## args)
-
-
#ifdef DUMP_MSGS
@@ -203,9 +155,12 @@ struct fsg_lun {
struct device dev;
};
-#define fsg_lun_is_open(curlun) ((curlun)->filp != NULL)
+static inline bool fsg_lun_is_open(struct fsg_lun *curlun)
+{
+ return curlun->filp != NULL;
+}
-static struct fsg_lun *fsg_lun_from_dev(struct device *dev)
+static inline struct fsg_lun *fsg_lun_from_dev(struct device *dev)
{
return container_of(dev, struct fsg_lun, dev);
}
@@ -308,26 +263,10 @@ static inline u32 get_unaligned_be24(u8 *buf)
enum {
-#ifndef FSG_NO_DEVICE_STRINGS
- FSG_STRING_MANUFACTURER = 1,
- FSG_STRING_PRODUCT,
- FSG_STRING_SERIAL,
- FSG_STRING_CONFIG,
-#endif
FSG_STRING_INTERFACE
};
-#ifndef FSG_NO_OTG
-static struct usb_otg_descriptor
-fsg_otg_desc = {
- .bLength = sizeof fsg_otg_desc,
- .bDescriptorType = USB_DT_OTG,
-
- .bmAttributes = USB_OTG_SRP,
-};
-#endif
-
/* There is only one interface. */
static struct usb_interface_descriptor
@@ -367,37 +306,10 @@ fsg_fs_bulk_out_desc = {
/* wMaxPacketSize set by autoconfiguration */
};
-#ifndef FSG_NO_INTR_EP
-
-static struct usb_endpoint_descriptor
-fsg_fs_intr_in_desc = {
- .bLength = USB_DT_ENDPOINT_SIZE,
- .bDescriptorType = USB_DT_ENDPOINT,
-
- .bEndpointAddress = USB_DIR_IN,
- .bmAttributes = USB_ENDPOINT_XFER_INT,
- .wMaxPacketSize = cpu_to_le16(2),
- .bInterval = 32, /* frames -> 32 ms */
-};
-
-#ifndef FSG_NO_OTG
-# define FSG_FS_FUNCTION_PRE_EP_ENTRIES 2
-#else
-# define FSG_FS_FUNCTION_PRE_EP_ENTRIES 1
-#endif
-
-#endif
-
static struct usb_descriptor_header *fsg_fs_function[] = {
-#ifndef FSG_NO_OTG
- (struct usb_descriptor_header *) &fsg_otg_desc,
-#endif
(struct usb_descriptor_header *) &fsg_intf_desc,
(struct usb_descriptor_header *) &fsg_fs_bulk_in_desc,
(struct usb_descriptor_header *) &fsg_fs_bulk_out_desc,
-#ifndef FSG_NO_INTR_EP
- (struct usb_descriptor_header *) &fsg_fs_intr_in_desc,
-#endif
NULL,
};
@@ -431,37 +343,11 @@ fsg_hs_bulk_out_desc = {
.bInterval = 1, /* NAK every 1 uframe */
};
-#ifndef FSG_NO_INTR_EP
-
-static struct usb_endpoint_descriptor
-fsg_hs_intr_in_desc = {
- .bLength = USB_DT_ENDPOINT_SIZE,
- .bDescriptorType = USB_DT_ENDPOINT,
-
- /* bEndpointAddress copied from fs_intr_in_desc during fsg_bind() */
- .bmAttributes = USB_ENDPOINT_XFER_INT,
- .wMaxPacketSize = cpu_to_le16(2),
- .bInterval = 9, /* 2**(9-1) = 256 uframes -> 32 ms */
-};
-
-#ifndef FSG_NO_OTG
-# define FSG_HS_FUNCTION_PRE_EP_ENTRIES 2
-#else
-# define FSG_HS_FUNCTION_PRE_EP_ENTRIES 1
-#endif
-
-#endif
static struct usb_descriptor_header *fsg_hs_function[] = {
-#ifndef FSG_NO_OTG
- (struct usb_descriptor_header *) &fsg_otg_desc,
-#endif
(struct usb_descriptor_header *) &fsg_intf_desc,
(struct usb_descriptor_header *) &fsg_hs_bulk_in_desc,
(struct usb_descriptor_header *) &fsg_hs_bulk_out_desc,
-#ifndef FSG_NO_INTR_EP
- (struct usb_descriptor_header *) &fsg_hs_intr_in_desc,
-#endif
NULL,
};
@@ -499,34 +385,6 @@ static struct usb_ss_ep_comp_descriptor fsg_ss_bulk_out_comp_desc = {
/*.bMaxBurst = DYNAMIC, */
};
-#ifndef FSG_NO_INTR_EP
-
-static struct usb_endpoint_descriptor
-fsg_ss_intr_in_desc = {
- .bLength = USB_DT_ENDPOINT_SIZE,
- .bDescriptorType = USB_DT_ENDPOINT,
-
- /* bEndpointAddress copied from fs_intr_in_desc during fsg_bind() */
- .bmAttributes = USB_ENDPOINT_XFER_INT,
- .wMaxPacketSize = cpu_to_le16(2),
- .bInterval = 9, /* 2**(9-1) = 256 uframes -> 32 ms */
-};
-
-static struct usb_ss_ep_comp_descriptor fsg_ss_intr_in_comp_desc = {
- .bLength = sizeof(fsg_ss_bulk_in_comp_desc),
- .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
-
- .wBytesPerInterval = cpu_to_le16(2),
-};
-
-#ifndef FSG_NO_OTG
-# define FSG_SS_FUNCTION_PRE_EP_ENTRIES 2
-#else
-# define FSG_SS_FUNCTION_PRE_EP_ENTRIES 1
-#endif
-
-#endif
-
static __maybe_unused struct usb_ext_cap_descriptor fsg_ext_cap_desc = {
.bLength = USB_DT_USB_EXT_CAP_SIZE,
.bDescriptorType = USB_DT_DEVICE_CAPABILITY,
@@ -563,18 +421,11 @@ static __maybe_unused struct usb_bos_descriptor fsg_bos_desc = {
};
static struct usb_descriptor_header *fsg_ss_function[] = {
-#ifndef FSG_NO_OTG
- (struct usb_descriptor_header *) &fsg_otg_desc,
-#endif
(struct usb_descriptor_header *) &fsg_intf_desc,
(struct usb_descriptor_header *) &fsg_ss_bulk_in_desc,
(struct usb_descriptor_header *) &fsg_ss_bulk_in_comp_desc,
(struct usb_descriptor_header *) &fsg_ss_bulk_out_desc,
(struct usb_descriptor_header *) &fsg_ss_bulk_out_comp_desc,
-#ifndef FSG_NO_INTR_EP
- (struct usb_descriptor_header *) &fsg_ss_intr_in_desc,
- (struct usb_descriptor_header *) &fsg_ss_intr_in_comp_desc,
-#endif
NULL,
};
@@ -594,12 +445,6 @@ fsg_ep_desc(struct usb_gadget *g, struct usb_endpoint_descriptor *fs,
/* Static strings, in UTF-8 (for simplicity we use only ASCII characters) */
static struct usb_string fsg_strings[] = {
-#ifndef FSG_NO_DEVICE_STRINGS
- {FSG_STRING_MANUFACTURER, fsg_string_manufacturer},
- {FSG_STRING_PRODUCT, fsg_string_product},
- {FSG_STRING_SERIAL, ""},
- {FSG_STRING_CONFIG, fsg_string_config},
-#endif
{FSG_STRING_INTERFACE, fsg_string_interface},
{}
};
diff --git a/drivers/usb/gadget/tcm_usb_gadget.c b/drivers/usb/gadget/tcm_usb_gadget.c
index 97e68b38cfdf..4f7f76f00c74 100644
--- a/drivers/usb/gadget/tcm_usb_gadget.c
+++ b/drivers/usb/gadget/tcm_usb_gadget.c
@@ -1384,7 +1384,7 @@ static struct se_node_acl *usbg_alloc_fabric_acl(struct se_portal_group *se_tpg)
nacl = kzalloc(sizeof(struct usbg_nacl), GFP_KERNEL);
if (!nacl) {
- printk(KERN_ERR "Unable to alocate struct usbg_nacl\n");
+ printk(KERN_ERR "Unable to allocate struct usbg_nacl\n");
return NULL;
}
@@ -2139,6 +2139,7 @@ static struct usb_descriptor_header *uasp_fs_function_desc[] = {
(struct usb_descriptor_header *) &uasp_status_pipe_desc,
(struct usb_descriptor_header *) &uasp_fs_cmd_desc,
(struct usb_descriptor_header *) &uasp_cmd_pipe_desc,
+ NULL,
};
static struct usb_descriptor_header *uasp_hs_function_desc[] = {
@@ -2239,6 +2240,7 @@ static int usbg_bind(struct usb_configuration *c, struct usb_function *f)
struct usb_gadget *gadget = c->cdev->gadget;
struct usb_ep *ep;
int iface;
+ int ret;
iface = usb_interface_id(c, f);
if (iface < 0)
@@ -2289,6 +2291,11 @@ static int usbg_bind(struct usb_configuration *c, struct usb_function *f)
uasp_ss_status_desc.bEndpointAddress;
uasp_fs_cmd_desc.bEndpointAddress = uasp_ss_cmd_desc.bEndpointAddress;
+ ret = usb_assign_descriptors(f, uasp_fs_function_desc,
+ uasp_hs_function_desc, uasp_ss_function_desc);
+ if (ret)
+ goto ep_fail;
+
return 0;
ep_fail:
pr_err("Can't claim all required eps\n");
@@ -2304,6 +2311,7 @@ static void usbg_unbind(struct usb_configuration *c, struct usb_function *f)
{
struct f_uas *fu = to_f_uas(f);
+ usb_free_all_descriptors(f);
kfree(fu);
}
@@ -2384,9 +2392,6 @@ static int usbg_cfg_bind(struct usb_configuration *c)
if (!fu)
return -ENOMEM;
fu->function.name = "Target Function";
- fu->function.descriptors = uasp_fs_function_desc;
- fu->function.hs_descriptors = uasp_hs_function_desc;
- fu->function.ss_descriptors = uasp_ss_function_desc;
fu->function.bind = usbg_bind;
fu->function.unbind = usbg_unbind;
fu->function.set_alt = usbg_set_alt;
diff --git a/drivers/usb/gadget/u_ether.c b/drivers/usb/gadget/u_ether.c
index 6458764994ef..4ec3c0d7a18b 100644
--- a/drivers/usb/gadget/u_ether.c
+++ b/drivers/usb/gadget/u_ether.c
@@ -20,6 +20,7 @@
#include <linux/ctype.h>
#include <linux/etherdevice.h>
#include <linux/ethtool.h>
+#include <linux/if_vlan.h>
#include "u_ether.h"
@@ -295,7 +296,7 @@ static void rx_complete(struct usb_ep *ep, struct usb_request *req)
while (skb2) {
if (status < 0
|| ETH_HLEN > skb2->len
- || skb2->len > ETH_FRAME_LEN) {
+ || skb2->len > VLAN_ETH_FRAME_LEN) {
dev->net->stats.rx_errors++;
dev->net->stats.rx_length_errors++;
DBG(dev, "rx length %d\n", skb2->len);
diff --git a/drivers/usb/gadget/u_serial.c b/drivers/usb/gadget/u_serial.c
index f1739526820f..d0f95482f40e 100644
--- a/drivers/usb/gadget/u_serial.c
+++ b/drivers/usb/gadget/u_serial.c
@@ -1145,8 +1145,10 @@ int gserial_setup(struct usb_gadget *g, unsigned count)
return status;
fail:
- while (count--)
+ while (count--) {
+ tty_port_destroy(&ports[count].port->port);
kfree(ports[count].port);
+ }
put_tty_driver(gs_tty_driver);
gs_tty_driver = NULL;
return status;
@@ -1200,6 +1202,7 @@ void gserial_cleanup(void)
WARN_ON(port->port_usb != NULL);
+ tty_port_destroy(&port->port);
kfree(port);
}
n_ports = 0;
diff --git a/drivers/usb/gadget/udc-core.c b/drivers/usb/gadget/udc-core.c
index f3cd9690b101..4d90a800063c 100644
--- a/drivers/usb/gadget/udc-core.c
+++ b/drivers/usb/gadget/udc-core.c
@@ -439,16 +439,6 @@ static DEVICE_ATTR(name, S_IRUSR, usb_udc_##param##_show, NULL)
static USB_UDC_SPEED_ATTR(current_speed, speed);
static USB_UDC_SPEED_ATTR(maximum_speed, max_speed);
-/* TODO: Scheduled for removal in 3.8. */
-static ssize_t usb_udc_is_dualspeed_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct usb_udc *udc = container_of(dev, struct usb_udc, dev);
- return snprintf(buf, PAGE_SIZE, "%d\n",
- gadget_is_dualspeed(udc->gadget));
-}
-static DEVICE_ATTR(is_dualspeed, S_IRUSR, usb_udc_is_dualspeed_show, NULL);
-
#define USB_UDC_ATTR(name) \
ssize_t usb_udc_##name##_show(struct device *dev, \
struct device_attribute *attr, char *buf) \
@@ -472,7 +462,6 @@ static struct attribute *usb_udc_attrs[] = {
&dev_attr_current_speed.attr,
&dev_attr_maximum_speed.attr,
- &dev_attr_is_dualspeed.attr,
&dev_attr_is_otg.attr,
&dev_attr_is_a_peripheral.attr,
&dev_attr_b_hnp_enable.attr,
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 3f1431d37e1c..d6bb128ce21e 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -95,6 +95,11 @@ config USB_EHCI_TT_NEWSCHED
If unsure, say Y.
+config USB_EHCI_PCI
+ tristate
+ depends on USB_EHCI_HCD && PCI
+ default y
+
config USB_EHCI_HCD_PMC_MSP
tristate "EHCI support for on-chip PMC MSP71xx USB controller"
depends on USB_EHCI_HCD && MSP_HAS_USB
@@ -215,9 +220,13 @@ config USB_W90X900_EHCI
Enables support for the W90X900 USB controller
config USB_CNS3XXX_EHCI
- bool "Cavium CNS3XXX EHCI Module"
+ bool "Cavium CNS3XXX EHCI Module (DEPRECATED)"
depends on USB_EHCI_HCD && ARCH_CNS3XXX
+ select USB_EHCI_HCD_PLATFORM
---help---
+ This option is deprecated now and the driver was removed, use
+ USB_EHCI_HCD_PLATFORM instead.
+
Enable support for the CNS3XXX SOC's on-chip EHCI controller.
It is needed for high-speed (480Mbit/sec) USB 2.0 device
support.
@@ -333,16 +342,6 @@ config USB_OHCI_ATH79
Enables support for the built-in OHCI controller present on the
Atheros AR71XX/AR7240 SoCs.
-config USB_OHCI_HCD_PPC_SOC
- bool "OHCI support for on-chip PPC USB controller"
- depends on USB_OHCI_HCD && (STB03xxx || PPC_MPC52xx)
- default y
- select USB_OHCI_BIG_ENDIAN_DESC
- select USB_OHCI_BIG_ENDIAN_MMIO
- ---help---
- Enables support for the USB controller on the MPC52xx or
- STB03xxx processor chip. If unsure, say Y.
-
config USB_OHCI_HCD_PPC_OF_BE
bool "OHCI support for OF platform bus (big endian)"
depends on USB_OHCI_HCD && PPC_OF
@@ -393,9 +392,13 @@ config USB_OHCI_HCD_SSB
If unsure, say N.
config USB_OHCI_SH
- bool "OHCI support for SuperH USB controller"
+ bool "OHCI support for SuperH USB controller (DEPRECATED)"
depends on USB_OHCI_HCD && SUPERH
+ select USB_OHCI_HCD_PLATFORM
---help---
+ This option is deprecated now and the driver was removed, use
+ USB_OHCI_HCD_PLATFORM instead.
+
Enables support for the on-chip OHCI controller on the SuperH.
If you use the PCI OHCI controller, this option is not necessary.
@@ -406,9 +409,13 @@ config USB_OHCI_EXYNOS
Enable support for the Samsung Exynos SOC's on-chip OHCI controller.
config USB_CNS3XXX_OHCI
- bool "Cavium CNS3XXX OHCI Module"
+ bool "Cavium CNS3XXX OHCI Module (DEPRECATED)"
depends on USB_OHCI_HCD && ARCH_CNS3XXX
+ select USB_OHCI_HCD_PLATFORM
---help---
+ This option is deprecated now and the driver was removed, use
+ USB_OHCI_HCD_PLATFORM instead.
+
Enable support for the CNS3XXX SOC's on-chip OHCI controller.
It is needed for low-speed USB 1.0 device support.
@@ -423,7 +430,7 @@ config USB_OHCI_HCD_PLATFORM
If unsure, say N.
config USB_EHCI_HCD_PLATFORM
- bool "Generic EHCI driver for a platform device"
+ tristate "Generic EHCI driver for a platform device"
depends on USB_EHCI_HCD
default n
---help---
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index 9e0a89ced15c..1eb4c3006e9e 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -24,6 +24,9 @@ obj-$(CONFIG_USB_WHCI_HCD) += whci/
obj-$(CONFIG_PCI) += pci-quirks.o
obj-$(CONFIG_USB_EHCI_HCD) += ehci-hcd.o
+obj-$(CONFIG_USB_EHCI_PCI) += ehci-pci.o
+obj-$(CONFIG_USB_EHCI_HCD_PLATFORM) += ehci-platform.o
+
obj-$(CONFIG_USB_OXU210HP_HCD) += oxu210hp-hcd.o
obj-$(CONFIG_USB_ISP116X_HCD) += isp116x-hcd.o
obj-$(CONFIG_USB_ISP1362_HCD) += isp1362-hcd.o
@@ -40,6 +43,5 @@ obj-$(CONFIG_USB_HWA_HCD) += hwa-hc.o
obj-$(CONFIG_USB_IMX21_HCD) += imx21-hcd.o
obj-$(CONFIG_USB_FSL_MPH_DR_OF) += fsl-mph-dr-of.o
obj-$(CONFIG_USB_OCTEON2_COMMON) += octeon2-common.o
-obj-$(CONFIG_MIPS_ALCHEMY) += alchemy-common.o
obj-$(CONFIG_USB_HCD_BCMA) += bcma-hcd.o
obj-$(CONFIG_USB_HCD_SSB) += ssb-hcd.o
diff --git a/drivers/usb/host/alchemy-common.c b/drivers/usb/host/alchemy-common.c
deleted file mode 100644
index 936af8359fb2..000000000000
--- a/drivers/usb/host/alchemy-common.c
+++ /dev/null
@@ -1,614 +0,0 @@
-/*
- * USB block power/access management abstraction.
- *
- * Au1000+: The OHCI block control register is at the far end of the OHCI memory
- * area. Au1550 has OHCI on different base address. No need to handle
- * UDC here.
- * Au1200: one register to control access and clocks to O/EHCI, UDC and OTG
- * as well as the PHY for EHCI and UDC.
- *
- */
-
-#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/module.h>
-#include <linux/spinlock.h>
-#include <linux/syscore_ops.h>
-#include <asm/mach-au1x00/au1000.h>
-
-/* control register offsets */
-#define AU1000_OHCICFG 0x7fffc
-#define AU1550_OHCICFG 0x07ffc
-#define AU1200_USBCFG 0x04
-
-/* Au1000 USB block config bits */
-#define USBHEN_RD (1 << 4) /* OHCI reset-done indicator */
-#define USBHEN_CE (1 << 3) /* OHCI block clock enable */
-#define USBHEN_E (1 << 2) /* OHCI block enable */
-#define USBHEN_C (1 << 1) /* OHCI block coherency bit */
-#define USBHEN_BE (1 << 0) /* OHCI Big-Endian */
-
-/* Au1200 USB config bits */
-#define USBCFG_PFEN (1 << 31) /* prefetch enable (undoc) */
-#define USBCFG_RDCOMB (1 << 30) /* read combining (undoc) */
-#define USBCFG_UNKNOWN (5 << 20) /* unknown, leave this way */
-#define USBCFG_SSD (1 << 23) /* serial short detect en */
-#define USBCFG_PPE (1 << 19) /* HS PHY PLL */
-#define USBCFG_UCE (1 << 18) /* UDC clock enable */
-#define USBCFG_ECE (1 << 17) /* EHCI clock enable */
-#define USBCFG_OCE (1 << 16) /* OHCI clock enable */
-#define USBCFG_FLA(x) (((x) & 0x3f) << 8)
-#define USBCFG_UCAM (1 << 7) /* coherent access (undoc) */
-#define USBCFG_GME (1 << 6) /* OTG mem access */
-#define USBCFG_DBE (1 << 5) /* UDC busmaster enable */
-#define USBCFG_DME (1 << 4) /* UDC mem enable */
-#define USBCFG_EBE (1 << 3) /* EHCI busmaster enable */
-#define USBCFG_EME (1 << 2) /* EHCI mem enable */
-#define USBCFG_OBE (1 << 1) /* OHCI busmaster enable */
-#define USBCFG_OME (1 << 0) /* OHCI mem enable */
-#define USBCFG_INIT_AU1200 (USBCFG_PFEN | USBCFG_RDCOMB | USBCFG_UNKNOWN |\
- USBCFG_SSD | USBCFG_FLA(0x20) | USBCFG_UCAM | \
- USBCFG_GME | USBCFG_DBE | USBCFG_DME | \
- USBCFG_EBE | USBCFG_EME | USBCFG_OBE | \
- USBCFG_OME)
-
-/* Au1300 USB config registers */
-#define USB_DWC_CTRL1 0x00
-#define USB_DWC_CTRL2 0x04
-#define USB_VBUS_TIMER 0x10
-#define USB_SBUS_CTRL 0x14
-#define USB_MSR_ERR 0x18
-#define USB_DWC_CTRL3 0x1C
-#define USB_DWC_CTRL4 0x20
-#define USB_OTG_STATUS 0x28
-#define USB_DWC_CTRL5 0x2C
-#define USB_DWC_CTRL6 0x30
-#define USB_DWC_CTRL7 0x34
-#define USB_PHY_STATUS 0xC0
-#define USB_INT_STATUS 0xC4
-#define USB_INT_ENABLE 0xC8
-
-#define USB_DWC_CTRL1_OTGD 0x04 /* set to DISable OTG */
-#define USB_DWC_CTRL1_HSTRS 0x02 /* set to ENable EHCI */
-#define USB_DWC_CTRL1_DCRS 0x01 /* set to ENable UDC */
-
-#define USB_DWC_CTRL2_PHY1RS 0x04 /* set to enable PHY1 */
-#define USB_DWC_CTRL2_PHY0RS 0x02 /* set to enable PHY0 */
-#define USB_DWC_CTRL2_PHYRS 0x01 /* set to enable PHY */
-
-#define USB_DWC_CTRL3_OHCI1_CKEN (1 << 19)
-#define USB_DWC_CTRL3_OHCI0_CKEN (1 << 18)
-#define USB_DWC_CTRL3_EHCI0_CKEN (1 << 17)
-#define USB_DWC_CTRL3_OTG0_CKEN (1 << 16)
-
-#define USB_SBUS_CTRL_SBCA 0x04 /* coherent access */
-
-#define USB_INTEN_FORCE 0x20
-#define USB_INTEN_PHY 0x10
-#define USB_INTEN_UDC 0x08
-#define USB_INTEN_EHCI 0x04
-#define USB_INTEN_OHCI1 0x02
-#define USB_INTEN_OHCI0 0x01
-
-static DEFINE_SPINLOCK(alchemy_usb_lock);
-
-static inline void __au1300_usb_phyctl(void __iomem *base, int enable)
-{
- unsigned long r, s;
-
- r = __raw_readl(base + USB_DWC_CTRL2);
- s = __raw_readl(base + USB_DWC_CTRL3);
-
- s &= USB_DWC_CTRL3_OHCI1_CKEN | USB_DWC_CTRL3_OHCI0_CKEN |
- USB_DWC_CTRL3_EHCI0_CKEN | USB_DWC_CTRL3_OTG0_CKEN;
-
- if (enable) {
- /* simply enable all PHYs */
- r |= USB_DWC_CTRL2_PHY1RS | USB_DWC_CTRL2_PHY0RS |
- USB_DWC_CTRL2_PHYRS;
- __raw_writel(r, base + USB_DWC_CTRL2);
- wmb();
- } else if (!s) {
- /* no USB block active, do disable all PHYs */
- r &= ~(USB_DWC_CTRL2_PHY1RS | USB_DWC_CTRL2_PHY0RS |
- USB_DWC_CTRL2_PHYRS);
- __raw_writel(r, base + USB_DWC_CTRL2);
- wmb();
- }
-}
-
-static inline void __au1300_ohci_control(void __iomem *base, int enable, int id)
-{
- unsigned long r;
-
- if (enable) {
- __raw_writel(1, base + USB_DWC_CTRL7); /* start OHCI clock */
- wmb();
-
- r = __raw_readl(base + USB_DWC_CTRL3); /* enable OHCI block */
- r |= (id == 0) ? USB_DWC_CTRL3_OHCI0_CKEN
- : USB_DWC_CTRL3_OHCI1_CKEN;
- __raw_writel(r, base + USB_DWC_CTRL3);
- wmb();
-
- __au1300_usb_phyctl(base, enable); /* power up the PHYs */
-
- r = __raw_readl(base + USB_INT_ENABLE);
- r |= (id == 0) ? USB_INTEN_OHCI0 : USB_INTEN_OHCI1;
- __raw_writel(r, base + USB_INT_ENABLE);
- wmb();
-
- /* reset the OHCI start clock bit */
- __raw_writel(0, base + USB_DWC_CTRL7);
- wmb();
- } else {
- r = __raw_readl(base + USB_INT_ENABLE);
- r &= ~((id == 0) ? USB_INTEN_OHCI0 : USB_INTEN_OHCI1);
- __raw_writel(r, base + USB_INT_ENABLE);
- wmb();
-
- r = __raw_readl(base + USB_DWC_CTRL3);
- r &= ~((id == 0) ? USB_DWC_CTRL3_OHCI0_CKEN
- : USB_DWC_CTRL3_OHCI1_CKEN);
- __raw_writel(r, base + USB_DWC_CTRL3);
- wmb();
-
- __au1300_usb_phyctl(base, enable);
- }
-}
-
-static inline void __au1300_ehci_control(void __iomem *base, int enable)
-{
- unsigned long r;
-
- if (enable) {
- r = __raw_readl(base + USB_DWC_CTRL3);
- r |= USB_DWC_CTRL3_EHCI0_CKEN;
- __raw_writel(r, base + USB_DWC_CTRL3);
- wmb();
-
- r = __raw_readl(base + USB_DWC_CTRL1);
- r |= USB_DWC_CTRL1_HSTRS;
- __raw_writel(r, base + USB_DWC_CTRL1);
- wmb();
-
- __au1300_usb_phyctl(base, enable);
-
- r = __raw_readl(base + USB_INT_ENABLE);
- r |= USB_INTEN_EHCI;
- __raw_writel(r, base + USB_INT_ENABLE);
- wmb();
- } else {
- r = __raw_readl(base + USB_INT_ENABLE);
- r &= ~USB_INTEN_EHCI;
- __raw_writel(r, base + USB_INT_ENABLE);
- wmb();
-
- r = __raw_readl(base + USB_DWC_CTRL1);
- r &= ~USB_DWC_CTRL1_HSTRS;
- __raw_writel(r, base + USB_DWC_CTRL1);
- wmb();
-
- r = __raw_readl(base + USB_DWC_CTRL3);
- r &= ~USB_DWC_CTRL3_EHCI0_CKEN;
- __raw_writel(r, base + USB_DWC_CTRL3);
- wmb();
-
- __au1300_usb_phyctl(base, enable);
- }
-}
-
-static inline void __au1300_udc_control(void __iomem *base, int enable)
-{
- unsigned long r;
-
- if (enable) {
- r = __raw_readl(base + USB_DWC_CTRL1);
- r |= USB_DWC_CTRL1_DCRS;
- __raw_writel(r, base + USB_DWC_CTRL1);
- wmb();
-
- __au1300_usb_phyctl(base, enable);
-
- r = __raw_readl(base + USB_INT_ENABLE);
- r |= USB_INTEN_UDC;
- __raw_writel(r, base + USB_INT_ENABLE);
- wmb();
- } else {
- r = __raw_readl(base + USB_INT_ENABLE);
- r &= ~USB_INTEN_UDC;
- __raw_writel(r, base + USB_INT_ENABLE);
- wmb();
-
- r = __raw_readl(base + USB_DWC_CTRL1);
- r &= ~USB_DWC_CTRL1_DCRS;
- __raw_writel(r, base + USB_DWC_CTRL1);
- wmb();
-
- __au1300_usb_phyctl(base, enable);
- }
-}
-
-static inline void __au1300_otg_control(void __iomem *base, int enable)
-{
- unsigned long r;
- if (enable) {
- r = __raw_readl(base + USB_DWC_CTRL3);
- r |= USB_DWC_CTRL3_OTG0_CKEN;
- __raw_writel(r, base + USB_DWC_CTRL3);
- wmb();
-
- r = __raw_readl(base + USB_DWC_CTRL1);
- r &= ~USB_DWC_CTRL1_OTGD;
- __raw_writel(r, base + USB_DWC_CTRL1);
- wmb();
-
- __au1300_usb_phyctl(base, enable);
- } else {
- r = __raw_readl(base + USB_DWC_CTRL1);
- r |= USB_DWC_CTRL1_OTGD;
- __raw_writel(r, base + USB_DWC_CTRL1);
- wmb();
-
- r = __raw_readl(base + USB_DWC_CTRL3);
- r &= ~USB_DWC_CTRL3_OTG0_CKEN;
- __raw_writel(r, base + USB_DWC_CTRL3);
- wmb();
-
- __au1300_usb_phyctl(base, enable);
- }
-}
-
-static inline int au1300_usb_control(int block, int enable)
-{
- void __iomem *base =
- (void __iomem *)KSEG1ADDR(AU1300_USB_CTL_PHYS_ADDR);
- int ret = 0;
-
- switch (block) {
- case ALCHEMY_USB_OHCI0:
- __au1300_ohci_control(base, enable, 0);
- break;
- case ALCHEMY_USB_OHCI1:
- __au1300_ohci_control(base, enable, 1);
- break;
- case ALCHEMY_USB_EHCI0:
- __au1300_ehci_control(base, enable);
- break;
- case ALCHEMY_USB_UDC0:
- __au1300_udc_control(base, enable);
- break;
- case ALCHEMY_USB_OTG0:
- __au1300_otg_control(base, enable);
- break;
- default:
- ret = -ENODEV;
- }
- return ret;
-}
-
-static inline void au1300_usb_init(void)
-{
- void __iomem *base =
- (void __iomem *)KSEG1ADDR(AU1300_USB_CTL_PHYS_ADDR);
-
- /* set some sane defaults. Note: we don't fiddle with DWC_CTRL4
- * here at all: Port 2 routing (EHCI or UDC) must be set either
- * by boot firmware or platform init code; I can't autodetect
- * a sane setting.
- */
- __raw_writel(0, base + USB_INT_ENABLE); /* disable all USB irqs */
- wmb();
- __raw_writel(0, base + USB_DWC_CTRL3); /* disable all clocks */
- wmb();
- __raw_writel(~0, base + USB_MSR_ERR); /* clear all errors */
- wmb();
- __raw_writel(~0, base + USB_INT_STATUS); /* clear int status */
- wmb();
- /* set coherent access bit */
- __raw_writel(USB_SBUS_CTRL_SBCA, base + USB_SBUS_CTRL);
- wmb();
-}
-
-static inline void __au1200_ohci_control(void __iomem *base, int enable)
-{
- unsigned long r = __raw_readl(base + AU1200_USBCFG);
- if (enable) {
- __raw_writel(r | USBCFG_OCE, base + AU1200_USBCFG);
- wmb();
- udelay(2000);
- } else {
- __raw_writel(r & ~USBCFG_OCE, base + AU1200_USBCFG);
- wmb();
- udelay(1000);
- }
-}
-
-static inline void __au1200_ehci_control(void __iomem *base, int enable)
-{
- unsigned long r = __raw_readl(base + AU1200_USBCFG);
- if (enable) {
- __raw_writel(r | USBCFG_ECE | USBCFG_PPE, base + AU1200_USBCFG);
- wmb();
- udelay(1000);
- } else {
- if (!(r & USBCFG_UCE)) /* UDC also off? */
- r &= ~USBCFG_PPE; /* yes: disable HS PHY PLL */
- __raw_writel(r & ~USBCFG_ECE, base + AU1200_USBCFG);
- wmb();
- udelay(1000);
- }
-}
-
-static inline void __au1200_udc_control(void __iomem *base, int enable)
-{
- unsigned long r = __raw_readl(base + AU1200_USBCFG);
- if (enable) {
- __raw_writel(r | USBCFG_UCE | USBCFG_PPE, base + AU1200_USBCFG);
- wmb();
- } else {
- if (!(r & USBCFG_ECE)) /* EHCI also off? */
- r &= ~USBCFG_PPE; /* yes: disable HS PHY PLL */
- __raw_writel(r & ~USBCFG_UCE, base + AU1200_USBCFG);
- wmb();
- }
-}
-
-static inline int au1200_coherency_bug(void)
-{
-#if defined(CONFIG_DMA_COHERENT)
- /* Au1200 AB USB does not support coherent memory */
- if (!(read_c0_prid() & 0xff)) {
- printk(KERN_INFO "Au1200 USB: this is chip revision AB !!\n");
- printk(KERN_INFO "Au1200 USB: update your board or re-configure"
- " the kernel\n");
- return -ENODEV;
- }
-#endif
- return 0;
-}
-
-static inline int au1200_usb_control(int block, int enable)
-{
- void __iomem *base =
- (void __iomem *)KSEG1ADDR(AU1200_USB_CTL_PHYS_ADDR);
- int ret = 0;
-
- switch (block) {
- case ALCHEMY_USB_OHCI0:
- ret = au1200_coherency_bug();
- if (ret && enable)
- goto out;
- __au1200_ohci_control(base, enable);
- break;
- case ALCHEMY_USB_UDC0:
- __au1200_udc_control(base, enable);
- break;
- case ALCHEMY_USB_EHCI0:
- ret = au1200_coherency_bug();
- if (ret && enable)
- goto out;
- __au1200_ehci_control(base, enable);
- break;
- default:
- ret = -ENODEV;
- }
-out:
- return ret;
-}
-
-
-/* initialize USB block(s) to a known working state */
-static inline void au1200_usb_init(void)
-{
- void __iomem *base =
- (void __iomem *)KSEG1ADDR(AU1200_USB_CTL_PHYS_ADDR);
- __raw_writel(USBCFG_INIT_AU1200, base + AU1200_USBCFG);
- wmb();
- udelay(1000);
-}
-
-static inline void au1000_usb_init(unsigned long rb, int reg)
-{
- void __iomem *base = (void __iomem *)KSEG1ADDR(rb + reg);
- unsigned long r = __raw_readl(base);
-
-#if defined(__BIG_ENDIAN)
- r |= USBHEN_BE;
-#endif
- r |= USBHEN_C;
-
- __raw_writel(r, base);
- wmb();
- udelay(1000);
-}
-
-
-static inline void __au1xx0_ohci_control(int enable, unsigned long rb, int creg)
-{
- void __iomem *base = (void __iomem *)KSEG1ADDR(rb);
- unsigned long r = __raw_readl(base + creg);
-
- if (enable) {
- __raw_writel(r | USBHEN_CE, base + creg);
- wmb();
- udelay(1000);
- __raw_writel(r | USBHEN_CE | USBHEN_E, base + creg);
- wmb();
- udelay(1000);
-
- /* wait for reset complete (read reg twice: au1500 erratum) */
- while (__raw_readl(base + creg),
- !(__raw_readl(base + creg) & USBHEN_RD))
- udelay(1000);
- } else {
- __raw_writel(r & ~(USBHEN_CE | USBHEN_E), base + creg);
- wmb();
- }
-}
-
-static inline int au1000_usb_control(int block, int enable, unsigned long rb,
- int creg)
-{
- int ret = 0;
-
- switch (block) {
- case ALCHEMY_USB_OHCI0:
- __au1xx0_ohci_control(enable, rb, creg);
- break;
- default:
- ret = -ENODEV;
- }
- return ret;
-}
-
-/*
- * alchemy_usb_control - control Alchemy on-chip USB blocks
- * @block: USB block to target
- * @enable: set 1 to enable a block, 0 to disable
- */
-int alchemy_usb_control(int block, int enable)
-{
- unsigned long flags;
- int ret;
-
- spin_lock_irqsave(&alchemy_usb_lock, flags);
- switch (alchemy_get_cputype()) {
- case ALCHEMY_CPU_AU1000:
- case ALCHEMY_CPU_AU1500:
- case ALCHEMY_CPU_AU1100:
- ret = au1000_usb_control(block, enable,
- AU1000_USB_OHCI_PHYS_ADDR, AU1000_OHCICFG);
- break;
- case ALCHEMY_CPU_AU1550:
- ret = au1000_usb_control(block, enable,
- AU1550_USB_OHCI_PHYS_ADDR, AU1550_OHCICFG);
- break;
- case ALCHEMY_CPU_AU1200:
- ret = au1200_usb_control(block, enable);
- break;
- case ALCHEMY_CPU_AU1300:
- ret = au1300_usb_control(block, enable);
- break;
- default:
- ret = -ENODEV;
- }
- spin_unlock_irqrestore(&alchemy_usb_lock, flags);
- return ret;
-}
-EXPORT_SYMBOL_GPL(alchemy_usb_control);
-
-
-static unsigned long alchemy_usb_pmdata[2];
-
-static void au1000_usb_pm(unsigned long br, int creg, int susp)
-{
- void __iomem *base = (void __iomem *)KSEG1ADDR(br);
-
- if (susp) {
- alchemy_usb_pmdata[0] = __raw_readl(base + creg);
- /* There appears to be some undocumented reset register.... */
- __raw_writel(0, base + 0x04);
- wmb();
- __raw_writel(0, base + creg);
- wmb();
- } else {
- __raw_writel(alchemy_usb_pmdata[0], base + creg);
- wmb();
- }
-}
-
-static void au1200_usb_pm(int susp)
-{
- void __iomem *base =
- (void __iomem *)KSEG1ADDR(AU1200_USB_OTG_PHYS_ADDR);
- if (susp) {
- /* save OTG_CAP/MUX registers which indicate port routing */
- /* FIXME: write an OTG driver to do that */
- alchemy_usb_pmdata[0] = __raw_readl(base + 0x00);
- alchemy_usb_pmdata[1] = __raw_readl(base + 0x04);
- } else {
- /* restore access to all MMIO areas */
- au1200_usb_init();
-
- /* restore OTG_CAP/MUX registers */
- __raw_writel(alchemy_usb_pmdata[0], base + 0x00);
- __raw_writel(alchemy_usb_pmdata[1], base + 0x04);
- wmb();
- }
-}
-
-static void au1300_usb_pm(int susp)
-{
- void __iomem *base =
- (void __iomem *)KSEG1ADDR(AU1300_USB_CTL_PHYS_ADDR);
- /* remember Port2 routing */
- if (susp) {
- alchemy_usb_pmdata[0] = __raw_readl(base + USB_DWC_CTRL4);
- } else {
- au1300_usb_init();
- __raw_writel(alchemy_usb_pmdata[0], base + USB_DWC_CTRL4);
- wmb();
- }
-}
-
-static void alchemy_usb_pm(int susp)
-{
- switch (alchemy_get_cputype()) {
- case ALCHEMY_CPU_AU1000:
- case ALCHEMY_CPU_AU1500:
- case ALCHEMY_CPU_AU1100:
- au1000_usb_pm(AU1000_USB_OHCI_PHYS_ADDR, AU1000_OHCICFG, susp);
- break;
- case ALCHEMY_CPU_AU1550:
- au1000_usb_pm(AU1550_USB_OHCI_PHYS_ADDR, AU1550_OHCICFG, susp);
- break;
- case ALCHEMY_CPU_AU1200:
- au1200_usb_pm(susp);
- break;
- case ALCHEMY_CPU_AU1300:
- au1300_usb_pm(susp);
- break;
- }
-}
-
-static int alchemy_usb_suspend(void)
-{
- alchemy_usb_pm(1);
- return 0;
-}
-
-static void alchemy_usb_resume(void)
-{
- alchemy_usb_pm(0);
-}
-
-static struct syscore_ops alchemy_usb_pm_ops = {
- .suspend = alchemy_usb_suspend,
- .resume = alchemy_usb_resume,
-};
-
-static int __init alchemy_usb_init(void)
-{
- switch (alchemy_get_cputype()) {
- case ALCHEMY_CPU_AU1000:
- case ALCHEMY_CPU_AU1500:
- case ALCHEMY_CPU_AU1100:
- au1000_usb_init(AU1000_USB_OHCI_PHYS_ADDR, AU1000_OHCICFG);
- break;
- case ALCHEMY_CPU_AU1550:
- au1000_usb_init(AU1550_USB_OHCI_PHYS_ADDR, AU1550_OHCICFG);
- break;
- case ALCHEMY_CPU_AU1200:
- au1200_usb_init();
- break;
- case ALCHEMY_CPU_AU1300:
- au1300_usb_init();
- break;
- }
-
- register_syscore_ops(&alchemy_usb_pm_ops);
-
- return 0;
-}
-arch_initcall(alchemy_usb_init);
diff --git a/drivers/usb/host/bcma-hcd.c b/drivers/usb/host/bcma-hcd.c
index 443da21d73ca..df13d425e9c5 100644
--- a/drivers/usb/host/bcma-hcd.c
+++ b/drivers/usb/host/bcma-hcd.c
@@ -54,7 +54,7 @@ static int bcma_wait_bits(struct bcma_device *dev, u16 reg, u32 bitmask,
return -ETIMEDOUT;
}
-static void __devinit bcma_hcd_4716wa(struct bcma_device *dev)
+static void bcma_hcd_4716wa(struct bcma_device *dev)
{
#ifdef CONFIG_BCMA_DRIVER_MIPS
/* Work around for 4716 failures. */
@@ -88,7 +88,7 @@ static void __devinit bcma_hcd_4716wa(struct bcma_device *dev)
}
/* based on arch/mips/brcm-boards/bcm947xx/pcibios.c */
-static void __devinit bcma_hcd_init_chip(struct bcma_device *dev)
+static void bcma_hcd_init_chip(struct bcma_device *dev)
{
u32 tmp;
@@ -165,8 +165,7 @@ static const struct usb_ehci_pdata ehci_pdata = {
static const struct usb_ohci_pdata ohci_pdata = {
};
-static struct platform_device * __devinit
-bcma_hcd_create_pdev(struct bcma_device *dev, bool ohci, u32 addr)
+static struct platform_device *bcma_hcd_create_pdev(struct bcma_device *dev, bool ohci, u32 addr)
{
struct platform_device *hci_dev;
struct resource hci_res[2];
@@ -212,7 +211,7 @@ err_alloc:
return ERR_PTR(ret);
}
-static int __devinit bcma_hcd_probe(struct bcma_device *dev)
+static int bcma_hcd_probe(struct bcma_device *dev)
{
int err;
u16 chipid_top;
@@ -266,7 +265,7 @@ err_free_usb_dev:
return err;
}
-static void __devexit bcma_hcd_remove(struct bcma_device *dev)
+static void bcma_hcd_remove(struct bcma_device *dev)
{
struct bcma_hcd_device *usb_dev = bcma_get_drvdata(dev);
struct platform_device *ohci_dev = usb_dev->ohci_dev;
@@ -306,7 +305,7 @@ static int bcma_hcd_resume(struct bcma_device *dev)
#define bcma_hcd_resume NULL
#endif /* CONFIG_PM */
-static const struct bcma_device_id bcma_hcd_table[] __devinitconst = {
+static const struct bcma_device_id bcma_hcd_table[] = {
BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_USB20_HOST, BCMA_ANY_REV, BCMA_ANY_CLASS),
BCMA_CORETABLE_END
};
@@ -316,7 +315,7 @@ static struct bcma_driver bcma_hcd_driver = {
.name = KBUILD_MODNAME,
.id_table = bcma_hcd_table,
.probe = bcma_hcd_probe,
- .remove = __devexit_p(bcma_hcd_remove),
+ .remove = bcma_hcd_remove,
.shutdown = bcma_hcd_shutdown,
.suspend = bcma_hcd_suspend,
.resume = bcma_hcd_resume,
diff --git a/drivers/usb/host/ehci-atmel.c b/drivers/usb/host/ehci-atmel.c
index 411bb74152eb..27639487f7ac 100644
--- a/drivers/usb/host/ehci-atmel.c
+++ b/drivers/usb/host/ehci-atmel.c
@@ -53,18 +53,11 @@ static void atmel_stop_ehci(struct platform_device *pdev)
static int ehci_atmel_setup(struct usb_hcd *hcd)
{
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
- int retval;
/* registers start at offset 0x0 */
ehci->caps = hcd->regs;
- retval = ehci_setup(hcd);
- if (retval)
- return retval;
-
- ehci_port_power(ehci, 0);
-
- return retval;
+ return ehci_setup(hcd);
}
static const struct hc_driver ehci_atmel_hc_driver = {
@@ -104,7 +97,7 @@ static const struct hc_driver ehci_atmel_hc_driver = {
static u64 at91_ehci_dma_mask = DMA_BIT_MASK(32);
-static int __devinit ehci_atmel_drv_probe(struct platform_device *pdev)
+static int ehci_atmel_drv_probe(struct platform_device *pdev)
{
struct usb_hcd *hcd;
const struct hc_driver *driver = &ehci_atmel_hc_driver;
@@ -189,7 +182,7 @@ fail_create_hcd:
return retval;
}
-static int __devexit ehci_atmel_drv_remove(struct platform_device *pdev)
+static int ehci_atmel_drv_remove(struct platform_device *pdev)
{
struct usb_hcd *hcd = platform_get_drvdata(pdev);
@@ -214,7 +207,7 @@ MODULE_DEVICE_TABLE(of, atmel_ehci_dt_ids);
static struct platform_driver ehci_atmel_driver = {
.probe = ehci_atmel_drv_probe,
- .remove = __devexit_p(ehci_atmel_drv_remove),
+ .remove = ehci_atmel_drv_remove,
.shutdown = usb_hcd_platform_shutdown,
.driver = {
.name = "atmel-ehci",
diff --git a/drivers/usb/host/ehci-au1xxx.c b/drivers/usb/host/ehci-au1xxx.c
deleted file mode 100644
index 65c945eb4144..000000000000
--- a/drivers/usb/host/ehci-au1xxx.c
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * EHCI HCD (Host Controller Driver) for USB.
- *
- * Bus Glue for AMD Alchemy Au1xxx
- *
- * Based on "ohci-au1xxx.c" by Matt Porter <mporter@kernel.crashing.org>
- *
- * Modified for AMD Alchemy Au1200 EHC
- * by K.Boge <karsten.boge@amd.com>
- *
- * This file is licenced under the GPL.
- */
-
-#include <linux/platform_device.h>
-#include <asm/mach-au1x00/au1000.h>
-
-
-extern int usb_disabled(void);
-
-static int au1xxx_ehci_setup(struct usb_hcd *hcd)
-{
- struct ehci_hcd *ehci = hcd_to_ehci(hcd);
- int ret;
-
- ehci->caps = hcd->regs;
- ret = ehci_setup(hcd);
-
- ehci->need_io_watchdog = 0;
- return ret;
-}
-
-static const struct hc_driver ehci_au1xxx_hc_driver = {
- .description = hcd_name,
- .product_desc = "Au1xxx EHCI",
- .hcd_priv_size = sizeof(struct ehci_hcd),
-
- /*
- * generic hardware linkage
- */
- .irq = ehci_irq,
- .flags = HCD_MEMORY | HCD_USB2,
-
- /*
- * basic lifecycle operations
- *
- * FIXME -- ehci_init() doesn't do enough here.
- * See ehci-ppc-soc for a complete implementation.
- */
- .reset = au1xxx_ehci_setup,
- .start = ehci_run,
- .stop = ehci_stop,
- .shutdown = ehci_shutdown,
-
- /*
- * managing i/o requests and associated device resources
- */
- .urb_enqueue = ehci_urb_enqueue,
- .urb_dequeue = ehci_urb_dequeue,
- .endpoint_disable = ehci_endpoint_disable,
- .endpoint_reset = ehci_endpoint_reset,
-
- /*
- * scheduling support
- */
- .get_frame_number = ehci_get_frame,
-
- /*
- * root hub support
- */
- .hub_status_data = ehci_hub_status_data,
- .hub_control = ehci_hub_control,
- .bus_suspend = ehci_bus_suspend,
- .bus_resume = ehci_bus_resume,
- .relinquish_port = ehci_relinquish_port,
- .port_handed_over = ehci_port_handed_over,
-
- .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
-};
-
-static int ehci_hcd_au1xxx_drv_probe(struct platform_device *pdev)
-{
- struct usb_hcd *hcd;
- struct resource *res;
- int ret;
-
- if (usb_disabled())
- return -ENODEV;
-
- if (pdev->resource[1].flags != IORESOURCE_IRQ) {
- pr_debug("resource[1] is not IORESOURCE_IRQ");
- return -ENOMEM;
- }
- hcd = usb_create_hcd(&ehci_au1xxx_hc_driver, &pdev->dev, "Au1xxx");
- if (!hcd)
- return -ENOMEM;
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- hcd->rsrc_start = res->start;
- hcd->rsrc_len = resource_size(res);
-
- hcd->regs = devm_request_and_ioremap(&pdev->dev, res);
- if (!hcd->regs) {
- pr_debug("devm_request_and_ioremap failed");
- ret = -ENOMEM;
- goto err1;
- }
-
- if (alchemy_usb_control(ALCHEMY_USB_EHCI0, 1)) {
- printk(KERN_INFO "%s: controller init failed!\n", pdev->name);
- ret = -ENODEV;
- goto err1;
- }
-
- ret = usb_add_hcd(hcd, pdev->resource[1].start,
- IRQF_SHARED);
- if (ret == 0) {
- platform_set_drvdata(pdev, hcd);
- return ret;
- }
-
- alchemy_usb_control(ALCHEMY_USB_EHCI0, 0);
-err1:
- usb_put_hcd(hcd);
- return ret;
-}
-
-static int ehci_hcd_au1xxx_drv_remove(struct platform_device *pdev)
-{
- struct usb_hcd *hcd = platform_get_drvdata(pdev);
-
- usb_remove_hcd(hcd);
- alchemy_usb_control(ALCHEMY_USB_EHCI0, 0);
- usb_put_hcd(hcd);
- platform_set_drvdata(pdev, NULL);
-
- return 0;
-}
-
-#ifdef CONFIG_PM
-static int ehci_hcd_au1xxx_drv_suspend(struct device *dev)
-{
- struct usb_hcd *hcd = dev_get_drvdata(dev);
- bool do_wakeup = device_may_wakeup(dev);
- int rc;
-
- rc = ehci_suspend(hcd, do_wakeup);
- alchemy_usb_control(ALCHEMY_USB_EHCI0, 0);
-
- return rc;
-}
-
-static int ehci_hcd_au1xxx_drv_resume(struct device *dev)
-{
- struct usb_hcd *hcd = dev_get_drvdata(dev);
-
- alchemy_usb_control(ALCHEMY_USB_EHCI0, 1);
- ehci_resume(hcd, false);
-
- return 0;
-}
-
-static const struct dev_pm_ops au1xxx_ehci_pmops = {
- .suspend = ehci_hcd_au1xxx_drv_suspend,
- .resume = ehci_hcd_au1xxx_drv_resume,
-};
-
-#define AU1XXX_EHCI_PMOPS &au1xxx_ehci_pmops
-
-#else
-#define AU1XXX_EHCI_PMOPS NULL
-#endif
-
-static struct platform_driver ehci_hcd_au1xxx_driver = {
- .probe = ehci_hcd_au1xxx_drv_probe,
- .remove = ehci_hcd_au1xxx_drv_remove,
- .shutdown = usb_hcd_platform_shutdown,
- .driver = {
- .name = "au1xxx-ehci",
- .owner = THIS_MODULE,
- .pm = AU1XXX_EHCI_PMOPS,
- }
-};
-
-MODULE_ALIAS("platform:au1xxx-ehci");
diff --git a/drivers/usb/host/ehci-cns3xxx.c b/drivers/usb/host/ehci-cns3xxx.c
deleted file mode 100644
index d91708d2e729..000000000000
--- a/drivers/usb/host/ehci-cns3xxx.c
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * Copyright 2008 Cavium Networks
- *
- * This file is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License, Version 2, as
- * published by the Free Software Foundation.
- */
-
-#include <linux/platform_device.h>
-#include <linux/atomic.h>
-#include <mach/cns3xxx.h>
-#include <mach/pm.h>
-
-static int cns3xxx_ehci_init(struct usb_hcd *hcd)
-{
- struct ehci_hcd *ehci = hcd_to_ehci(hcd);
- int retval;
-
- /*
- * EHCI and OHCI share the same clock and power,
- * resetting twice would cause the 1st controller been reset.
- * Therefore only do power up at the first up device, and
- * power down at the last down device.
- *
- * Set USB AHB INCR length to 16
- */
- if (atomic_inc_return(&usb_pwr_ref) == 1) {
- cns3xxx_pwr_power_up(1 << PM_PLL_HM_PD_CTRL_REG_OFFSET_PLL_USB);
- cns3xxx_pwr_clk_en(1 << PM_CLK_GATE_REG_OFFSET_USB_HOST);
- cns3xxx_pwr_soft_rst(1 << PM_SOFT_RST_REG_OFFST_USB_HOST);
- __raw_writel((__raw_readl(MISC_CHIP_CONFIG_REG) | (0X2 << 24)),
- MISC_CHIP_CONFIG_REG);
- }
-
- ehci->caps = hcd->regs;
-
- hcd->has_tt = 0;
-
- retval = ehci_setup(hcd);
- if (retval)
- return retval;
-
- ehci_port_power(ehci, 0);
-
- return retval;
-}
-
-static const struct hc_driver cns3xxx_ehci_hc_driver = {
- .description = hcd_name,
- .product_desc = "CNS3XXX EHCI Host Controller",
- .hcd_priv_size = sizeof(struct ehci_hcd),
- .irq = ehci_irq,
- .flags = HCD_MEMORY | HCD_USB2,
- .reset = cns3xxx_ehci_init,
- .start = ehci_run,
- .stop = ehci_stop,
- .shutdown = ehci_shutdown,
- .urb_enqueue = ehci_urb_enqueue,
- .urb_dequeue = ehci_urb_dequeue,
- .endpoint_disable = ehci_endpoint_disable,
- .endpoint_reset = ehci_endpoint_reset,
- .get_frame_number = ehci_get_frame,
- .hub_status_data = ehci_hub_status_data,
- .hub_control = ehci_hub_control,
-#ifdef CONFIG_PM
- .bus_suspend = ehci_bus_suspend,
- .bus_resume = ehci_bus_resume,
-#endif
- .relinquish_port = ehci_relinquish_port,
- .port_handed_over = ehci_port_handed_over,
-
- .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
-};
-
-static int cns3xxx_ehci_probe(struct platform_device *pdev)
-{
- struct device *dev = &pdev->dev;
- struct usb_hcd *hcd;
- const struct hc_driver *driver = &cns3xxx_ehci_hc_driver;
- struct resource *res;
- int irq;
- int retval;
-
- if (usb_disabled())
- return -ENODEV;
-
- res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
- if (!res) {
- dev_err(dev, "Found HC with no IRQ.\n");
- return -ENODEV;
- }
- irq = res->start;
-
- hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev));
- if (!hcd)
- return -ENOMEM;
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res) {
- dev_err(dev, "Found HC with no register addr.\n");
- retval = -ENODEV;
- goto err1;
- }
-
- hcd->rsrc_start = res->start;
- hcd->rsrc_len = resource_size(res);
-
- hcd->regs = devm_request_and_ioremap(&pdev->dev, res);
- if (hcd->regs == NULL) {
- dev_dbg(dev, "error mapping memory\n");
- retval = -EFAULT;
- goto err1;
- }
-
- retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
- if (retval == 0)
- return retval;
-
-err1:
- usb_put_hcd(hcd);
-
- return retval;
-}
-
-static int cns3xxx_ehci_remove(struct platform_device *pdev)
-{
- struct usb_hcd *hcd = platform_get_drvdata(pdev);
-
- usb_remove_hcd(hcd);
-
- /*
- * EHCI and OHCI share the same clock and power,
- * resetting twice would cause the 1st controller been reset.
- * Therefore only do power up at the first up device, and
- * power down at the last down device.
- */
- if (atomic_dec_return(&usb_pwr_ref) == 0)
- cns3xxx_pwr_clk_dis(1 << PM_CLK_GATE_REG_OFFSET_USB_HOST);
-
- usb_put_hcd(hcd);
-
- platform_set_drvdata(pdev, NULL);
-
- return 0;
-}
-
-MODULE_ALIAS("platform:cns3xxx-ehci");
-
-static struct platform_driver cns3xxx_ehci_driver = {
- .probe = cns3xxx_ehci_probe,
- .remove = cns3xxx_ehci_remove,
- .driver = {
- .name = "cns3xxx-ehci",
- },
-};
diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c
index 1599806e3d47..70b496dc18a0 100644
--- a/drivers/usb/host/ehci-dbg.c
+++ b/drivers/usb/host/ehci-dbg.c
@@ -18,21 +18,6 @@
/* this file is part of ehci-hcd.c */
-#define ehci_dbg(ehci, fmt, args...) \
- dev_dbg (ehci_to_hcd(ehci)->self.controller , fmt , ## args )
-#define ehci_err(ehci, fmt, args...) \
- dev_err (ehci_to_hcd(ehci)->self.controller , fmt , ## args )
-#define ehci_info(ehci, fmt, args...) \
- dev_info (ehci_to_hcd(ehci)->self.controller , fmt , ## args )
-#define ehci_warn(ehci, fmt, args...) \
- dev_warn (ehci_to_hcd(ehci)->self.controller , fmt , ## args )
-
-#ifdef VERBOSE_DEBUG
-# define ehci_vdbg ehci_dbg
-#else
- static inline void ehci_vdbg(struct ehci_hcd *ehci, ...) {}
-#endif
-
#ifdef DEBUG
/* check the values in the HCSPARAMS register
@@ -352,11 +337,6 @@ static int debug_async_open(struct inode *, struct file *);
static int debug_periodic_open(struct inode *, struct file *);
static int debug_registers_open(struct inode *, struct file *);
static int debug_async_open(struct inode *, struct file *);
-static ssize_t debug_lpm_read(struct file *file, char __user *user_buf,
- size_t count, loff_t *ppos);
-static ssize_t debug_lpm_write(struct file *file, const char __user *buffer,
- size_t count, loff_t *ppos);
-static int debug_lpm_close(struct inode *inode, struct file *file);
static ssize_t debug_output(struct file*, char __user*, size_t, loff_t*);
static int debug_close(struct inode *, struct file *);
@@ -382,14 +362,6 @@ static const struct file_operations debug_registers_fops = {
.release = debug_close,
.llseek = default_llseek,
};
-static const struct file_operations debug_lpm_fops = {
- .owner = THIS_MODULE,
- .open = simple_open,
- .read = debug_lpm_read,
- .write = debug_lpm_write,
- .release = debug_lpm_close,
- .llseek = noop_llseek,
-};
static struct dentry *ehci_debug_root;
@@ -971,86 +943,6 @@ static int debug_registers_open(struct inode *inode, struct file *file)
return file->private_data ? 0 : -ENOMEM;
}
-static int debug_lpm_close(struct inode *inode, struct file *file)
-{
- return 0;
-}
-
-static ssize_t debug_lpm_read(struct file *file, char __user *user_buf,
- size_t count, loff_t *ppos)
-{
- /* TODO: show lpm stats */
- return 0;
-}
-
-static ssize_t debug_lpm_write(struct file *file, const char __user *user_buf,
- size_t count, loff_t *ppos)
-{
- struct usb_hcd *hcd;
- struct ehci_hcd *ehci;
- char buf[50];
- size_t len;
- u32 temp;
- unsigned long port;
- u32 __iomem *portsc ;
- u32 params;
-
- hcd = bus_to_hcd(file->private_data);
- ehci = hcd_to_ehci(hcd);
-
- len = min(count, sizeof(buf) - 1);
- if (copy_from_user(buf, user_buf, len))
- return -EFAULT;
- buf[len] = '\0';
- if (len > 0 && buf[len - 1] == '\n')
- buf[len - 1] = '\0';
-
- if (strncmp(buf, "enable", 5) == 0) {
- if (strict_strtoul(buf + 7, 10, &port))
- return -EINVAL;
- params = ehci_readl(ehci, &ehci->caps->hcs_params);
- if (port > HCS_N_PORTS(params)) {
- ehci_dbg(ehci, "ERR: LPM on bad port %lu\n", port);
- return -ENODEV;
- }
- portsc = &ehci->regs->port_status[port-1];
- temp = ehci_readl(ehci, portsc);
- if (!(temp & PORT_DEV_ADDR)) {
- ehci_dbg(ehci, "LPM: no device attached\n");
- return -ENODEV;
- }
- temp |= PORT_LPM;
- ehci_writel(ehci, temp, portsc);
- printk(KERN_INFO "force enable LPM for port %lu\n", port);
- } else if (strncmp(buf, "hird=", 5) == 0) {
- unsigned long hird;
- if (strict_strtoul(buf + 5, 16, &hird))
- return -EINVAL;
- printk(KERN_INFO "setting hird %s %lu\n", buf + 6, hird);
- ehci->command = (ehci->command & ~CMD_HIRD) | (hird << 24);
- ehci_writel(ehci, ehci->command, &ehci->regs->command);
- } else if (strncmp(buf, "disable", 7) == 0) {
- if (strict_strtoul(buf + 8, 10, &port))
- return -EINVAL;
- params = ehci_readl(ehci, &ehci->caps->hcs_params);
- if (port > HCS_N_PORTS(params)) {
- ehci_dbg(ehci, "ERR: LPM off bad port %lu\n", port);
- return -ENODEV;
- }
- portsc = &ehci->regs->port_status[port-1];
- temp = ehci_readl(ehci, portsc);
- if (!(temp & PORT_DEV_ADDR)) {
- ehci_dbg(ehci, "ERR: no device attached\n");
- return -ENODEV;
- }
- temp &= ~PORT_LPM;
- ehci_writel(ehci, temp, portsc);
- printk(KERN_INFO "disabled LPM for port %lu\n", port);
- } else
- return -EOPNOTSUPP;
- return count;
-}
-
static inline void create_debug_files (struct ehci_hcd *ehci)
{
struct usb_bus *bus = &ehci_to_hcd(ehci)->self;
@@ -1071,10 +963,6 @@ static inline void create_debug_files (struct ehci_hcd *ehci)
&debug_registers_fops))
goto file_error;
- if (!debugfs_create_file("lpm", S_IRUGO|S_IWUSR, ehci->debug_dir, bus,
- &debug_lpm_fops))
- goto file_error;
-
return;
file_error:
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
index 0d2f35ca93f1..fd9b5424b860 100644
--- a/drivers/usb/host/ehci-fsl.c
+++ b/drivers/usb/host/ehci-fsl.c
@@ -349,7 +349,6 @@ static int ehci_fsl_reinit(struct ehci_hcd *ehci)
{
if (ehci_fsl_usb_setup(ehci))
return -EINVAL;
- ehci_port_power(ehci, 0);
return 0;
}
diff --git a/drivers/usb/host/ehci-grlib.c b/drivers/usb/host/ehci-grlib.c
index 3180cb3624d9..1fc89292f5d6 100644
--- a/drivers/usb/host/ehci-grlib.c
+++ b/drivers/usb/host/ehci-grlib.c
@@ -34,22 +34,6 @@
#define GRUSBHC_HCIVERSION 0x0100 /* Known value of cap. reg. HCIVERSION */
-/* called during probe() after chip reset completes */
-static int ehci_grlib_setup(struct usb_hcd *hcd)
-{
- struct ehci_hcd *ehci = hcd_to_ehci(hcd);
- int retval;
-
- retval = ehci_setup(hcd);
- if (retval)
- return retval;
-
- ehci_port_power(ehci, 1);
-
- return retval;
-}
-
-
static const struct hc_driver ehci_grlib_hc_driver = {
.description = hcd_name,
.product_desc = "GRLIB GRUSBHC EHCI",
@@ -64,7 +48,7 @@ static const struct hc_driver ehci_grlib_hc_driver = {
/*
* basic lifecycle operations
*/
- .reset = ehci_grlib_setup,
+ .reset = ehci_setup,
.start = ehci_run,
.stop = ehci_stop,
.shutdown = ehci_shutdown,
@@ -98,7 +82,7 @@ static const struct hc_driver ehci_grlib_hc_driver = {
};
-static int __devinit ehci_hcd_grlib_probe(struct platform_device *op)
+static int ehci_hcd_grlib_probe(struct platform_device *op)
{
struct device_node *dn = op->dev.of_node;
struct usb_hcd *hcd;
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 6bf6c42481e8..c97503bb0b0e 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -39,7 +39,6 @@
#include <linux/dma-mapping.h>
#include <linux/debugfs.h>
#include <linux/slab.h>
-#include <linux/uaccess.h>
#include <asm/byteorder.h>
#include <asm/io.h>
@@ -108,19 +107,39 @@ static bool ignore_oc = 0;
module_param (ignore_oc, bool, S_IRUGO);
MODULE_PARM_DESC (ignore_oc, "ignore bogus hardware overcurrent indications");
-/* for link power management(LPM) feature */
-static unsigned int hird;
-module_param(hird, int, S_IRUGO);
-MODULE_PARM_DESC(hird, "host initiated resume duration, +1 for each 75us");
-
#define INTR_MASK (STS_IAA | STS_FATAL | STS_PCD | STS_ERR | STS_INT)
/*-------------------------------------------------------------------------*/
#include "ehci.h"
-#include "ehci-dbg.c"
#include "pci-quirks.h"
+/*
+ * The MosChip MCS9990 controller updates its microframe counter
+ * a little before the frame counter, and occasionally we will read
+ * the invalid intermediate value. Avoid problems by checking the
+ * microframe number (the low-order 3 bits); if they are 0 then
+ * re-read the register to get the correct value.
+ */
+static unsigned ehci_moschip_read_frame_index(struct ehci_hcd *ehci)
+{
+ unsigned uf;
+
+ uf = ehci_readl(ehci, &ehci->regs->frame_index);
+ if (unlikely((uf & 7) == 0))
+ uf = ehci_readl(ehci, &ehci->regs->frame_index);
+ return uf;
+}
+
+static inline unsigned ehci_read_frame_index(struct ehci_hcd *ehci)
+{
+ if (ehci->frame_index_bug)
+ return ehci_moschip_read_frame_index(ehci);
+ return ehci_readl(ehci, &ehci->regs->frame_index);
+}
+
+#include "ehci-dbg.c"
+
/*-------------------------------------------------------------------------*/
/*
@@ -293,7 +312,6 @@ static void end_unlink_intr(struct ehci_hcd *ehci, struct ehci_qh *qh);
#include "ehci-timer.c"
#include "ehci-hub.c"
-#include "ehci-lpm.c"
#include "ehci-mem.c"
#include "ehci-q.c"
#include "ehci-sched.c"
@@ -353,24 +371,6 @@ static void ehci_shutdown(struct usb_hcd *hcd)
hrtimer_cancel(&ehci->hrtimer);
}
-static void ehci_port_power (struct ehci_hcd *ehci, int is_on)
-{
- unsigned port;
-
- if (!HCS_PPC (ehci->hcs_params))
- return;
-
- ehci_dbg (ehci, "...power%s ports...\n", is_on ? "up" : "down");
- for (port = HCS_N_PORTS (ehci->hcs_params); port > 0; )
- (void) ehci_hub_control(ehci_to_hcd(ehci),
- is_on ? SetPortFeature : ClearPortFeature,
- USB_PORT_FEAT_POWER,
- port--, NULL, 0);
- /* Flush those writes */
- ehci_readl(ehci, &ehci->regs->command);
- msleep(20);
-}
-
/*-------------------------------------------------------------------------*/
/*
@@ -503,7 +503,7 @@ static int ehci_init(struct usb_hcd *hcd)
/* controllers may cache some of the periodic schedule ... */
if (HCC_ISOC_CACHE(hcc_params)) // full frame cache
- ehci->i_thresh = 2 + 8;
+ ehci->i_thresh = 0;
else // N microframes cached
ehci->i_thresh = 2 + HCC_ISOC_THRES(hcc_params);
@@ -555,17 +555,6 @@ static int ehci_init(struct usb_hcd *hcd)
temp &= ~(3 << 2);
temp |= (EHCI_TUNE_FLS << 2);
}
- if (HCC_LPM(hcc_params)) {
- /* support link power management EHCI 1.1 addendum */
- ehci_dbg(ehci, "support lpm\n");
- ehci->has_lpm = 1;
- if (hird > 0xf) {
- ehci_dbg(ehci, "hird %d invalid, use default 0",
- hird);
- hird = 0;
- }
- temp |= hird << 24;
- }
ehci->command = temp;
/* Accept arbitrarily long scatter-gather lists */
@@ -660,7 +649,7 @@ static int ehci_run (struct usb_hcd *hcd)
return 0;
}
-static int ehci_setup(struct usb_hcd *hcd)
+int ehci_setup(struct usb_hcd *hcd)
{
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
int retval;
@@ -691,6 +680,7 @@ static int ehci_setup(struct usb_hcd *hcd)
return 0;
}
+EXPORT_SYMBOL_GPL(ehci_setup);
/*-------------------------------------------------------------------------*/
@@ -1096,7 +1086,7 @@ static int ehci_get_frame (struct usb_hcd *hcd)
/* These routines handle the generic parts of controller suspend/resume */
-static int __maybe_unused ehci_suspend(struct usb_hcd *hcd, bool do_wakeup)
+int ehci_suspend(struct usb_hcd *hcd, bool do_wakeup)
{
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
@@ -1119,9 +1109,10 @@ static int __maybe_unused ehci_suspend(struct usb_hcd *hcd, bool do_wakeup)
return 0;
}
+EXPORT_SYMBOL_GPL(ehci_suspend);
/* Returns 0 if power was preserved, 1 if power was lost */
-static int __maybe_unused ehci_resume(struct usb_hcd *hcd, bool hibernated)
+int ehci_resume(struct usb_hcd *hcd, bool hibernated)
{
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
@@ -1177,33 +1168,83 @@ static int __maybe_unused ehci_resume(struct usb_hcd *hcd, bool hibernated)
ehci->rh_state = EHCI_RH_SUSPENDED;
spin_unlock_irq(&ehci->lock);
- /* here we "know" root ports should always stay powered */
- ehci_port_power(ehci, 1);
-
return 1;
}
+EXPORT_SYMBOL_GPL(ehci_resume);
#endif
/*-------------------------------------------------------------------------*/
/*
- * The EHCI in ChipIdea HDRC cannot be a separate module or device,
- * because its registers (and irq) are shared between host/gadget/otg
- * functions and in order to facilitate role switching we cannot
- * give the ehci driver exclusive access to those.
+ * Generic structure: This gets copied for platform drivers so that
+ * individual entries can be overridden as needed.
*/
-#ifndef CHIPIDEA_EHCI
+
+static const struct hc_driver ehci_hc_driver = {
+ .description = hcd_name,
+ .product_desc = "EHCI Host Controller",
+ .hcd_priv_size = sizeof(struct ehci_hcd),
+
+ /*
+ * generic hardware linkage
+ */
+ .irq = ehci_irq,
+ .flags = HCD_MEMORY | HCD_USB2,
+
+ /*
+ * basic lifecycle operations
+ */
+ .reset = ehci_setup,
+ .start = ehci_run,
+ .stop = ehci_stop,
+ .shutdown = ehci_shutdown,
+
+ /*
+ * managing i/o requests and associated device resources
+ */
+ .urb_enqueue = ehci_urb_enqueue,
+ .urb_dequeue = ehci_urb_dequeue,
+ .endpoint_disable = ehci_endpoint_disable,
+ .endpoint_reset = ehci_endpoint_reset,
+ .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
+
+ /*
+ * scheduling support
+ */
+ .get_frame_number = ehci_get_frame,
+
+ /*
+ * root hub support
+ */
+ .hub_status_data = ehci_hub_status_data,
+ .hub_control = ehci_hub_control,
+ .bus_suspend = ehci_bus_suspend,
+ .bus_resume = ehci_bus_resume,
+ .relinquish_port = ehci_relinquish_port,
+ .port_handed_over = ehci_port_handed_over,
+};
+
+void ehci_init_driver(struct hc_driver *drv,
+ const struct ehci_driver_overrides *over)
+{
+ /* Copy the generic table to drv and then apply the overrides */
+ *drv = ehci_hc_driver;
+
+ if (over) {
+ drv->hcd_priv_size += over->extra_priv_size;
+ if (over->reset)
+ drv->reset = over->reset;
+ }
+}
+EXPORT_SYMBOL_GPL(ehci_init_driver);
+
+/*-------------------------------------------------------------------------*/
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_AUTHOR (DRIVER_AUTHOR);
MODULE_LICENSE ("GPL");
-#ifdef CONFIG_PCI
-#include "ehci-pci.c"
-#define PCI_DRIVER ehci_pci_driver
-#endif
-
#ifdef CONFIG_USB_EHCI_FSL
#include "ehci-fsl.c"
#define PLATFORM_DRIVER ehci_fsl_driver
@@ -1219,11 +1260,6 @@ MODULE_LICENSE ("GPL");
#define PLATFORM_DRIVER ehci_hcd_sh_driver
#endif
-#ifdef CONFIG_MIPS_ALCHEMY
-#include "ehci-au1xxx.c"
-#define PLATFORM_DRIVER ehci_hcd_au1xxx_driver
-#endif
-
#ifdef CONFIG_USB_EHCI_HCD_OMAP
#include "ehci-omap.c"
#define PLATFORM_DRIVER ehci_hcd_omap_driver
@@ -1249,11 +1285,6 @@ MODULE_LICENSE ("GPL");
#define PLATFORM_DRIVER ehci_orion_driver
#endif
-#ifdef CONFIG_ARCH_IXP4XX
-#include "ehci-ixp4xx.c"
-#define PLATFORM_DRIVER ixp4xx_ehci_driver
-#endif
-
#ifdef CONFIG_USB_W90X900_EHCI
#include "ehci-w90x900.c"
#define PLATFORM_DRIVER ehci_hcd_w90x900_driver
@@ -1269,11 +1300,6 @@ MODULE_LICENSE ("GPL");
#define PLATFORM_DRIVER ehci_octeon_driver
#endif
-#ifdef CONFIG_USB_CNS3XXX_EHCI
-#include "ehci-cns3xxx.c"
-#define PLATFORM_DRIVER cns3xxx_ehci_driver
-#endif
-
#ifdef CONFIG_ARCH_VT8500
#include "ehci-vt8500.c"
#define PLATFORM_DRIVER vt8500_ehci_driver
@@ -1314,34 +1340,23 @@ MODULE_LICENSE ("GPL");
#define PLATFORM_DRIVER ehci_grlib_driver
#endif
-#ifdef CONFIG_CPU_XLR
-#include "ehci-xls.c"
-#define PLATFORM_DRIVER ehci_xls_driver
-#endif
-
#ifdef CONFIG_USB_EHCI_MV
#include "ehci-mv.c"
#define PLATFORM_DRIVER ehci_mv_driver
#endif
-#ifdef CONFIG_MACH_LOONGSON1
-#include "ehci-ls1x.c"
-#define PLATFORM_DRIVER ehci_ls1x_driver
-#endif
-
#ifdef CONFIG_MIPS_SEAD3
#include "ehci-sead3.c"
#define PLATFORM_DRIVER ehci_hcd_sead3_driver
#endif
-#ifdef CONFIG_USB_EHCI_HCD_PLATFORM
-#include "ehci-platform.c"
-#define PLATFORM_DRIVER ehci_platform_driver
-#endif
-
-#if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \
- !defined(PS3_SYSTEM_BUS_DRIVER) && !defined(OF_PLATFORM_DRIVER) && \
- !defined(XILINX_OF_PLATFORM_DRIVER)
+#if !IS_ENABLED(CONFIG_USB_EHCI_PCI) && \
+ !IS_ENABLED(CONFIG_USB_EHCI_HCD_PLATFORM) && \
+ !defined(CONFIG_USB_CHIPIDEA_HOST) && \
+ !defined(PLATFORM_DRIVER) && \
+ !defined(PS3_SYSTEM_BUS_DRIVER) && \
+ !defined(OF_PLATFORM_DRIVER) && \
+ !defined(XILINX_OF_PLATFORM_DRIVER)
#error "missing bus glue for ehci-hcd"
#endif
@@ -1378,12 +1393,6 @@ static int __init ehci_hcd_init(void)
goto clean0;
#endif
-#ifdef PCI_DRIVER
- retval = pci_register_driver(&PCI_DRIVER);
- if (retval < 0)
- goto clean1;
-#endif
-
#ifdef PS3_SYSTEM_BUS_DRIVER
retval = ps3_ehci_driver_register(&PS3_SYSTEM_BUS_DRIVER);
if (retval < 0)
@@ -1415,10 +1424,6 @@ clean3:
ps3_ehci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);
clean2:
#endif
-#ifdef PCI_DRIVER
- pci_unregister_driver(&PCI_DRIVER);
-clean1:
-#endif
#ifdef PLATFORM_DRIVER
platform_driver_unregister(&PLATFORM_DRIVER);
clean0:
@@ -1444,9 +1449,6 @@ static void __exit ehci_hcd_cleanup(void)
#ifdef PLATFORM_DRIVER
platform_driver_unregister(&PLATFORM_DRIVER);
#endif
-#ifdef PCI_DRIVER
- pci_unregister_driver(&PCI_DRIVER);
-#endif
#ifdef PS3_SYSTEM_BUS_DRIVER
ps3_ehci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);
#endif
@@ -1456,5 +1458,3 @@ static void __exit ehci_hcd_cleanup(void)
clear_bit(USB_EHCI_LOADED, &usb_hcds_loaded);
}
module_exit(ehci_hcd_cleanup);
-
-#endif /* CHIPIDEA_EHCI */
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index 914ce9370e70..4ccb97c0678f 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -56,6 +56,19 @@ static void ehci_handover_companion_ports(struct ehci_hcd *ehci)
if (!ehci->owned_ports)
return;
+ /* Make sure the ports are powered */
+ port = HCS_N_PORTS(ehci->hcs_params);
+ while (port--) {
+ if (test_bit(port, &ehci->owned_ports)) {
+ reg = &ehci->regs->port_status[port];
+ status = ehci_readl(ehci, reg) & ~PORT_RWC_BITS;
+ if (!(status & PORT_POWER)) {
+ status |= PORT_POWER;
+ ehci_writel(ehci, status, reg);
+ }
+ }
+ }
+
/* Give the connections some time to appear */
msleep(20);
@@ -384,11 +397,24 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
ehci_writel(ehci, ehci->command, &ehci->regs->command);
ehci->rh_state = EHCI_RH_RUNNING;
- /* Some controller/firmware combinations need a delay during which
- * they set up the port statuses. See Bugzilla #8190. */
- spin_unlock_irq(&ehci->lock);
- msleep(8);
- spin_lock_irq(&ehci->lock);
+ /*
+ * According to Bugzilla #8190, the port status for some controllers
+ * will be wrong without a delay. At their wrong status, the port
+ * is enabled, but not suspended neither resumed.
+ */
+ i = HCS_N_PORTS(ehci->hcs_params);
+ while (i--) {
+ temp = ehci_readl(ehci, &ehci->regs->port_status[i]);
+ if ((temp & PORT_PE) &&
+ !(temp & (PORT_SUSPEND | PORT_RESUME))) {
+ ehci_dbg(ehci, "Port status(0x%x) is wrong\n", temp);
+ spin_unlock_irq(&ehci->lock);
+ msleep(8);
+ spin_lock_irq(&ehci->lock);
+ break;
+ }
+ }
+
if (ehci->shutdown)
goto shutdown;
@@ -764,11 +790,6 @@ static int ehci_hub_control (
status_reg);
break;
case USB_PORT_FEAT_C_CONNECTION:
- if (ehci->has_lpm) {
- /* clear PORTSC bits on disconnect */
- temp &= ~PORT_LPM;
- temp &= ~PORT_DEV_ADDR;
- }
ehci_writel(ehci, temp | PORT_CSC, status_reg);
break;
case USB_PORT_FEAT_C_OVER_CURRENT:
@@ -1088,8 +1109,7 @@ error_exit:
return retval;
}
-static void __maybe_unused ehci_relinquish_port(struct usb_hcd *hcd,
- int portnum)
+static void ehci_relinquish_port(struct usb_hcd *hcd, int portnum)
{
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
@@ -1098,8 +1118,7 @@ static void __maybe_unused ehci_relinquish_port(struct usb_hcd *hcd,
set_owner(ehci, --portnum, PORT_OWNER);
}
-static int __maybe_unused ehci_port_handed_over(struct usb_hcd *hcd,
- int portnum)
+static int ehci_port_handed_over(struct usb_hcd *hcd, int portnum)
{
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
u32 __iomem *reg;
diff --git a/drivers/usb/host/ehci-ixp4xx.c b/drivers/usb/host/ehci-ixp4xx.c
deleted file mode 100644
index f224c0a48bed..000000000000
--- a/drivers/usb/host/ehci-ixp4xx.c
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * IXP4XX EHCI Host Controller Driver
- *
- * Author: Vladimir Barinov <vbarinov@embeddedalley.com>
- *
- * Based on "ehci-fsl.c" by Randy Vinson <rvinson@mvista.com>
- *
- * 2007 (c) MontaVista Software, Inc. This file is licensed under
- * the terms of the GNU General Public License version 2. This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- */
-
-#include <linux/platform_device.h>
-
-static int ixp4xx_ehci_init(struct usb_hcd *hcd)
-{
- struct ehci_hcd *ehci = hcd_to_ehci(hcd);
- int retval = 0;
-
- ehci->big_endian_desc = 1;
- ehci->big_endian_mmio = 1;
-
- ehci->caps = hcd->regs + 0x100;
-
- hcd->has_tt = 1;
-
- retval = ehci_setup(hcd);
- if (retval)
- return retval;
-
- ehci_port_power(ehci, 0);
-
- return retval;
-}
-
-static const struct hc_driver ixp4xx_ehci_hc_driver = {
- .description = hcd_name,
- .product_desc = "IXP4XX EHCI Host Controller",
- .hcd_priv_size = sizeof(struct ehci_hcd),
- .irq = ehci_irq,
- .flags = HCD_MEMORY | HCD_USB2,
- .reset = ixp4xx_ehci_init,
- .start = ehci_run,
- .stop = ehci_stop,
- .shutdown = ehci_shutdown,
- .urb_enqueue = ehci_urb_enqueue,
- .urb_dequeue = ehci_urb_dequeue,
- .endpoint_disable = ehci_endpoint_disable,
- .endpoint_reset = ehci_endpoint_reset,
- .get_frame_number = ehci_get_frame,
- .hub_status_data = ehci_hub_status_data,
- .hub_control = ehci_hub_control,
-#if defined(CONFIG_PM)
- .bus_suspend = ehci_bus_suspend,
- .bus_resume = ehci_bus_resume,
-#endif
- .relinquish_port = ehci_relinquish_port,
- .port_handed_over = ehci_port_handed_over,
-
- .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
-};
-
-static int ixp4xx_ehci_probe(struct platform_device *pdev)
-{
- struct usb_hcd *hcd;
- const struct hc_driver *driver = &ixp4xx_ehci_hc_driver;
- struct resource *res;
- int irq;
- int retval;
-
- if (usb_disabled())
- return -ENODEV;
-
- res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
- if (!res) {
- dev_err(&pdev->dev,
- "Found HC with no IRQ. Check %s setup!\n",
- dev_name(&pdev->dev));
- return -ENODEV;
- }
- irq = res->start;
-
- hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev));
- if (!hcd) {
- retval = -ENOMEM;
- goto fail_create_hcd;
- }
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res) {
- dev_err(&pdev->dev,
- "Found HC with no register addr. Check %s setup!\n",
- dev_name(&pdev->dev));
- retval = -ENODEV;
- goto fail_request_resource;
- }
- hcd->rsrc_start = res->start;
- hcd->rsrc_len = resource_size(res);
-
- hcd->regs = devm_request_and_ioremap(&pdev->dev, res);
- if (hcd->regs == NULL) {
- dev_dbg(&pdev->dev, "error mapping memory\n");
- retval = -EFAULT;
- goto fail_request_resource;
- }
-
- retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
- if (retval)
- goto fail_request_resource;
-
- return retval;
-
-fail_request_resource:
- usb_put_hcd(hcd);
-fail_create_hcd:
- dev_err(&pdev->dev, "init %s fail, %d\n", dev_name(&pdev->dev), retval);
- return retval;
-}
-
-static int ixp4xx_ehci_remove(struct platform_device *pdev)
-{
- struct usb_hcd *hcd = platform_get_drvdata(pdev);
-
- usb_remove_hcd(hcd);
- usb_put_hcd(hcd);
-
- return 0;
-}
-
-MODULE_ALIAS("platform:ixp4xx-ehci");
-
-static struct platform_driver ixp4xx_ehci_driver = {
- .probe = ixp4xx_ehci_probe,
- .remove = ixp4xx_ehci_remove,
- .driver = {
- .name = "ixp4xx-ehci",
- },
-};
diff --git a/drivers/usb/host/ehci-lpm.c b/drivers/usb/host/ehci-lpm.c
deleted file mode 100644
index 2111627a19de..000000000000
--- a/drivers/usb/host/ehci-lpm.c
+++ /dev/null
@@ -1,84 +0,0 @@
-/* ehci-lpm.c EHCI HCD LPM support code
- * Copyright (c) 2008 - 2010, Intel Corporation.
- * Author: Jacob Pan <jacob.jun.pan@intel.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-/* this file is part of ehci-hcd.c */
-static int __maybe_unused ehci_lpm_set_da(struct ehci_hcd *ehci,
- int dev_addr, int port_num)
-{
- u32 __iomem portsc;
-
- ehci_dbg(ehci, "set dev address %d for port %d\n", dev_addr, port_num);
- if (port_num > HCS_N_PORTS(ehci->hcs_params)) {
- ehci_dbg(ehci, "invalid port number %d\n", port_num);
- return -ENODEV;
- }
- portsc = ehci_readl(ehci, &ehci->regs->port_status[port_num-1]);
- portsc &= ~PORT_DEV_ADDR;
- portsc |= dev_addr<<25;
- ehci_writel(ehci, portsc, &ehci->regs->port_status[port_num-1]);
- return 0;
-}
-
-/*
- * this function is used to check if the device support LPM
- * if yes, mark the PORTSC register with PORT_LPM bit
- */
-static int __maybe_unused ehci_lpm_check(struct ehci_hcd *ehci, int port)
-{
- u32 __iomem *portsc ;
- u32 val32;
- int retval;
-
- portsc = &ehci->regs->port_status[port-1];
- val32 = ehci_readl(ehci, portsc);
- if (!(val32 & PORT_DEV_ADDR)) {
- ehci_dbg(ehci, "LPM: no device attached\n");
- return -ENODEV;
- }
- val32 |= PORT_LPM;
- ehci_writel(ehci, val32, portsc);
- msleep(5);
- val32 |= PORT_SUSPEND;
- ehci_dbg(ehci, "Sending LPM 0x%08x to port %d\n", val32, port);
- ehci_writel(ehci, val32, portsc);
- /* wait for ACK */
- msleep(10);
- retval = handshake(ehci, &ehci->regs->port_status[port-1], PORT_SSTS,
- PORTSC_SUSPEND_STS_ACK, 125);
- dbg_port(ehci, "LPM", port, val32);
- if (retval != -ETIMEDOUT) {
- ehci_dbg(ehci, "LPM: device ACK for LPM\n");
- val32 |= PORT_LPM;
- /*
- * now device should be in L1 sleep, let's wake up the device
- * so that we can complete enumeration.
- */
- ehci_writel(ehci, val32, portsc);
- msleep(10);
- val32 |= PORT_RESUME;
- ehci_writel(ehci, val32, portsc);
- } else {
- ehci_dbg(ehci, "LPM: device does not ACK, disable LPM %d\n",
- retval);
- val32 &= ~PORT_LPM;
- retval = -ETIMEDOUT;
- ehci_writel(ehci, val32, portsc);
- }
-
- return retval;
-}
diff --git a/drivers/usb/host/ehci-ls1x.c b/drivers/usb/host/ehci-ls1x.c
deleted file mode 100644
index ca759652626b..000000000000
--- a/drivers/usb/host/ehci-ls1x.c
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * Bus Glue for Loongson LS1X built-in EHCI controller.
- *
- * Copyright (c) 2012 Zhang, Keguang <keguang.zhang@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published
- * by the Free Software Foundation.
- */
-
-
-#include <linux/platform_device.h>
-
-static int ehci_ls1x_reset(struct usb_hcd *hcd)
-{
- struct ehci_hcd *ehci = hcd_to_ehci(hcd);
- int ret;
-
- ehci->caps = hcd->regs;
-
- ret = ehci_setup(hcd);
- if (ret)
- return ret;
-
- ehci_port_power(ehci, 0);
-
- return 0;
-}
-
-static const struct hc_driver ehci_ls1x_hc_driver = {
- .description = hcd_name,
- .product_desc = "LOONGSON1 EHCI",
- .hcd_priv_size = sizeof(struct ehci_hcd),
-
- /*
- * generic hardware linkage
- */
- .irq = ehci_irq,
- .flags = HCD_MEMORY | HCD_USB2,
-
- /*
- * basic lifecycle operations
- */
- .reset = ehci_ls1x_reset,
- .start = ehci_run,
- .stop = ehci_stop,
- .shutdown = ehci_shutdown,
-
- /*
- * managing i/o requests and associated device resources
- */
- .urb_enqueue = ehci_urb_enqueue,
- .urb_dequeue = ehci_urb_dequeue,
- .endpoint_disable = ehci_endpoint_disable,
- .endpoint_reset = ehci_endpoint_reset,
-
- /*
- * scheduling support
- */
- .get_frame_number = ehci_get_frame,
-
- /*
- * root hub support
- */
- .hub_status_data = ehci_hub_status_data,
- .hub_control = ehci_hub_control,
- .relinquish_port = ehci_relinquish_port,
- .port_handed_over = ehci_port_handed_over,
-
- .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
-};
-
-static int ehci_hcd_ls1x_probe(struct platform_device *pdev)
-{
- struct usb_hcd *hcd;
- struct resource *res;
- int irq;
- int ret;
-
- pr_debug("initializing loongson1 ehci USB Controller\n");
-
- if (usb_disabled())
- return -ENODEV;
-
- res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
- if (!res) {
- dev_err(&pdev->dev,
- "Found HC with no IRQ. Check %s setup!\n",
- dev_name(&pdev->dev));
- return -ENODEV;
- }
- irq = res->start;
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res) {
- dev_err(&pdev->dev,
- "Found HC with no register addr. Check %s setup!\n",
- dev_name(&pdev->dev));
- return -ENODEV;
- }
-
- hcd = usb_create_hcd(&ehci_ls1x_hc_driver, &pdev->dev,
- dev_name(&pdev->dev));
- if (!hcd)
- return -ENOMEM;
- hcd->rsrc_start = res->start;
- hcd->rsrc_len = resource_size(res);
-
- hcd->regs = devm_request_and_ioremap(&pdev->dev, res);
- if (hcd->regs == NULL) {
- dev_dbg(&pdev->dev, "error mapping memory\n");
- ret = -EFAULT;
- goto err_put_hcd;
- }
-
- ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
- if (ret)
- goto err_put_hcd;
-
- return ret;
-
-err_put_hcd:
- usb_put_hcd(hcd);
- return ret;
-}
-
-static int ehci_hcd_ls1x_remove(struct platform_device *pdev)
-{
- struct usb_hcd *hcd = platform_get_drvdata(pdev);
-
- usb_remove_hcd(hcd);
- usb_put_hcd(hcd);
-
- return 0;
-}
-
-static struct platform_driver ehci_ls1x_driver = {
- .probe = ehci_hcd_ls1x_probe,
- .remove = ehci_hcd_ls1x_remove,
- .shutdown = usb_hcd_platform_shutdown,
- .driver = {
- .name = "ls1x-ehci",
- .owner = THIS_MODULE,
- },
-};
-
-MODULE_ALIAS(PLATFORM_MODULE_PREFIX "ls1x-ehci");
diff --git a/drivers/usb/host/ehci-msm.c b/drivers/usb/host/ehci-msm.c
index 4af4dc5b618c..88a49c87e748 100644
--- a/drivers/usb/host/ehci-msm.c
+++ b/drivers/usb/host/ehci-msm.c
@@ -53,7 +53,6 @@ static int ehci_msm_reset(struct usb_hcd *hcd)
/* Disable streaming mode and select host mode */
writel(0x13, USB_USBMODE);
- ehci_port_power(ehci, 1);
return 0;
}
@@ -174,7 +173,7 @@ put_hcd:
return ret;
}
-static int __devexit ehci_msm_remove(struct platform_device *pdev)
+static int ehci_msm_remove(struct platform_device *pdev)
{
struct usb_hcd *hcd = platform_get_drvdata(pdev);
@@ -221,7 +220,7 @@ static const struct dev_pm_ops ehci_msm_dev_pm_ops = {
static struct platform_driver ehci_msm_driver = {
.probe = ehci_msm_probe,
- .remove = __devexit_p(ehci_msm_remove),
+ .remove = ehci_msm_remove,
.driver = {
.name = "msm_hsusb_host",
.pm = &ehci_msm_dev_pm_ops,
diff --git a/drivers/usb/host/ehci-mxc.c b/drivers/usb/host/ehci-mxc.c
index 4a08fc0b27c9..8804f74689d7 100644
--- a/drivers/usb/host/ehci-mxc.c
+++ b/drivers/usb/host/ehci-mxc.c
@@ -39,17 +39,9 @@ struct ehci_mxc_priv {
/* called during probe() after chip reset completes */
static int ehci_mxc_setup(struct usb_hcd *hcd)
{
- struct ehci_hcd *ehci = hcd_to_ehci(hcd);
- int retval;
-
hcd->has_tt = 1;
- retval = ehci_setup(hcd);
- if (retval)
- return retval;
-
- ehci_port_power(ehci, 0);
- return 0;
+ return ehci_setup(hcd);
}
static const struct hc_driver ehci_mxc_hc_driver = {
diff --git a/drivers/usb/host/ehci-octeon.c b/drivers/usb/host/ehci-octeon.c
index ba26957abf46..a89750fff4ff 100644
--- a/drivers/usb/host/ehci-octeon.c
+++ b/drivers/usb/host/ehci-octeon.c
@@ -159,9 +159,6 @@ static int ehci_octeon_drv_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, hcd);
- /* root ports should always stay powered */
- ehci_port_power(ehci, 1);
-
return 0;
err3:
ehci_octeon_stop();
diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c
index d7fe287d0678..44e7d0f638e8 100644
--- a/drivers/usb/host/ehci-omap.c
+++ b/drivers/usb/host/ehci-omap.c
@@ -146,9 +146,6 @@ static int omap_ehci_init(struct usb_hcd *hcd)
gpio_set_value_cansleep(pdata->reset_gpio_port[1], 1);
}
- /* root ports should always stay powered */
- ehci_port_power(ehci, 1);
-
return rc;
}
diff --git a/drivers/usb/host/ehci-orion.c b/drivers/usb/host/ehci-orion.c
index 9c2717d66730..f74794c93152 100644
--- a/drivers/usb/host/ehci-orion.c
+++ b/drivers/usb/host/ehci-orion.c
@@ -101,20 +101,6 @@ static void orion_usb_phy_v1_setup(struct usb_hcd *hcd)
wrl(USB_MODE, 0x13);
}
-static int ehci_orion_setup(struct usb_hcd *hcd)
-{
- struct ehci_hcd *ehci = hcd_to_ehci(hcd);
- int retval;
-
- retval = ehci_setup(hcd);
- if (retval)
- return retval;
-
- ehci_port_power(ehci, 0);
-
- return retval;
-}
-
static const struct hc_driver ehci_orion_hc_driver = {
.description = hcd_name,
.product_desc = "Marvell Orion EHCI",
@@ -129,7 +115,7 @@ static const struct hc_driver ehci_orion_hc_driver = {
/*
* basic lifecycle operations
*/
- .reset = ehci_orion_setup,
+ .reset = ehci_setup,
.start = ehci_run,
.stop = ehci_stop,
.shutdown = ehci_shutdown,
@@ -160,7 +146,7 @@ static const struct hc_driver ehci_orion_hc_driver = {
.clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
};
-static void __devinit
+static void
ehci_orion_conf_mbus_windows(struct usb_hcd *hcd,
const struct mbus_dram_target_info *dram)
{
@@ -181,7 +167,7 @@ ehci_orion_conf_mbus_windows(struct usb_hcd *hcd,
}
}
-static int __devinit ehci_orion_drv_probe(struct platform_device *pdev)
+static int ehci_orion_drv_probe(struct platform_device *pdev)
{
struct orion_ehci_data *pd = pdev->dev.platform_data;
const struct mbus_dram_target_info *dram;
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
index 2cb7d370c4ef..dabb20494826 100644
--- a/drivers/usb/host/ehci-pci.c
+++ b/drivers/usb/host/ehci-pci.c
@@ -18,9 +18,18 @@
* Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#ifndef CONFIG_PCI
-#error "This file is PCI bus glue. CONFIG_PCI must be defined."
-#endif
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/usb.h>
+#include <linux/usb/hcd.h>
+
+#include "ehci.h"
+#include "pci-quirks.h"
+
+#define DRIVER_DESC "EHCI PCI platform driver"
+
+static const char hcd_name[] = "ehci-pci";
/* defined here to avoid adding to pci_ids.h for single instance use */
#define PCI_DEVICE_ID_INTEL_CE4100_USB 0x2e70
@@ -103,7 +112,6 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
}
break;
case PCI_VENDOR_ID_INTEL:
- ehci->fs_i_thresh = 1;
if (pdev->device == PCI_DEVICE_ID_INTEL_CE4100_USB)
hcd->has_tt = 1;
break;
@@ -203,11 +211,6 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
break;
case PCI_VENDOR_ID_INTEL:
ehci->need_io_watchdog = 0;
- if (pdev->device == 0x0806 || pdev->device == 0x0811
- || pdev->device == 0x0829) {
- ehci_info(ehci, "disable lpm for langwell/penwell\n");
- ehci->has_lpm = 0;
- }
break;
case PCI_VENDOR_ID_NVIDIA:
switch (pdev->device) {
@@ -217,8 +220,7 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
* devices with PPCD enabled.
*/
case 0x0d9d:
- ehci_info(ehci, "disable lpm/ppcd for nvidia mcp89");
- ehci->has_lpm = 0;
+ ehci_info(ehci, "disable ppcd for nvidia mcp89\n");
ehci->has_ppcd = 0;
ehci->command &= ~CMD_PPCEE;
break;
@@ -304,7 +306,6 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
ehci_warn(ehci, "selective suspend/wakeup unavailable\n");
#endif
- ehci_port_power(ehci, 1);
retval = ehci_pci_reinit(ehci, pdev);
done:
return retval;
@@ -323,18 +324,14 @@ done:
* Also they depend on separate root hub suspend/resume.
*/
-static int ehci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup)
-{
- return ehci_suspend(hcd, do_wakeup);
-}
-
static bool usb_is_intel_switchable_ehci(struct pci_dev *pdev)
{
return pdev->class == PCI_CLASS_SERIAL_USB_EHCI &&
pdev->vendor == PCI_VENDOR_ID_INTEL &&
(pdev->device == 0x1E26 ||
pdev->device == 0x8C2D ||
- pdev->device == 0x8C26);
+ pdev->device == 0x8C26 ||
+ pdev->device == 0x9C26);
}
static void ehci_enable_xhci_companion(void)
@@ -378,76 +375,17 @@ static int ehci_pci_resume(struct usb_hcd *hcd, bool hibernated)
(void) ehci_pci_reinit(ehci, pdev);
return 0;
}
-#endif
-static int ehci_update_device(struct usb_hcd *hcd, struct usb_device *udev)
-{
- struct ehci_hcd *ehci = hcd_to_ehci(hcd);
- int rc = 0;
-
- if (!udev->parent) /* udev is root hub itself, impossible */
- rc = -1;
- /* we only support lpm device connected to root hub yet */
- if (ehci->has_lpm && !udev->parent->parent) {
- rc = ehci_lpm_set_da(ehci, udev->devnum, udev->portnum);
- if (!rc)
- rc = ehci_lpm_check(ehci, udev->portnum);
- }
- return rc;
-}
+#else
-static const struct hc_driver ehci_pci_hc_driver = {
- .description = hcd_name,
- .product_desc = "EHCI Host Controller",
- .hcd_priv_size = sizeof(struct ehci_hcd),
+#define ehci_suspend NULL
+#define ehci_pci_resume NULL
+#endif /* CONFIG_PM */
- /*
- * generic hardware linkage
- */
- .irq = ehci_irq,
- .flags = HCD_MEMORY | HCD_USB2,
+static struct hc_driver __read_mostly ehci_pci_hc_driver;
- /*
- * basic lifecycle operations
- */
+static const struct ehci_driver_overrides pci_overrides __initdata = {
.reset = ehci_pci_setup,
- .start = ehci_run,
-#ifdef CONFIG_PM
- .pci_suspend = ehci_pci_suspend,
- .pci_resume = ehci_pci_resume,
-#endif
- .stop = ehci_stop,
- .shutdown = ehci_shutdown,
-
- /*
- * managing i/o requests and associated device resources
- */
- .urb_enqueue = ehci_urb_enqueue,
- .urb_dequeue = ehci_urb_dequeue,
- .endpoint_disable = ehci_endpoint_disable,
- .endpoint_reset = ehci_endpoint_reset,
-
- /*
- * scheduling support
- */
- .get_frame_number = ehci_get_frame,
-
- /*
- * root hub support
- */
- .hub_status_data = ehci_hub_status_data,
- .hub_control = ehci_hub_control,
- .bus_suspend = ehci_bus_suspend,
- .bus_resume = ehci_bus_resume,
- .relinquish_port = ehci_relinquish_port,
- .port_handed_over = ehci_port_handed_over,
-
- /*
- * call back when device connected and addressed
- */
- .update_device = ehci_update_device,
-
- .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
};
/*-------------------------------------------------------------------------*/
@@ -480,3 +418,31 @@ static struct pci_driver ehci_pci_driver = {
},
#endif
};
+
+static int __init ehci_pci_init(void)
+{
+ if (usb_disabled())
+ return -ENODEV;
+
+ pr_info("%s: " DRIVER_DESC "\n", hcd_name);
+
+ ehci_init_driver(&ehci_pci_hc_driver, &pci_overrides);
+
+ /* Entries for the PCI suspend/resume callbacks are special */
+ ehci_pci_hc_driver.pci_suspend = ehci_suspend;
+ ehci_pci_hc_driver.pci_resume = ehci_pci_resume;
+
+ return pci_register_driver(&ehci_pci_driver);
+}
+module_init(ehci_pci_init);
+
+static void __exit ehci_pci_cleanup(void)
+{
+ pci_unregister_driver(&ehci_pci_driver);
+}
+module_exit(ehci_pci_cleanup);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_AUTHOR("David Brownell");
+MODULE_AUTHOR("Alan Stern");
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c
index 764e0100b6f4..58fa0c90c7c7 100644
--- a/drivers/usb/host/ehci-platform.c
+++ b/drivers/usb/host/ehci-platform.c
@@ -18,9 +18,21 @@
*
* Licensed under the GNU/GPL. See COPYING for details.
*/
+#include <linux/kernel.h>
+#include <linux/hrtimer.h>
+#include <linux/io.h>
+#include <linux/module.h>
#include <linux/platform_device.h>
+#include <linux/usb.h>
+#include <linux/usb/hcd.h>
#include <linux/usb/ehci_pdriver.h>
+#include "ehci.h"
+
+#define DRIVER_DESC "EHCI generic platform driver"
+
+static const char hcd_name[] = "ehci-platform";
+
static int ehci_platform_reset(struct usb_hcd *hcd)
{
struct platform_device *pdev = to_platform_device(hcd->self.controller);
@@ -38,47 +50,18 @@ static int ehci_platform_reset(struct usb_hcd *hcd)
if (retval)
return retval;
- if (pdata->port_power_on)
- ehci_port_power(ehci, 1);
- if (pdata->port_power_off)
- ehci_port_power(ehci, 0);
-
+ if (pdata->no_io_watchdog)
+ ehci->need_io_watchdog = 0;
return 0;
}
-static const struct hc_driver ehci_platform_hc_driver = {
- .description = hcd_name,
- .product_desc = "Generic Platform EHCI Controller",
- .hcd_priv_size = sizeof(struct ehci_hcd),
-
- .irq = ehci_irq,
- .flags = HCD_MEMORY | HCD_USB2,
-
- .reset = ehci_platform_reset,
- .start = ehci_run,
- .stop = ehci_stop,
- .shutdown = ehci_shutdown,
-
- .urb_enqueue = ehci_urb_enqueue,
- .urb_dequeue = ehci_urb_dequeue,
- .endpoint_disable = ehci_endpoint_disable,
- .endpoint_reset = ehci_endpoint_reset,
+static struct hc_driver __read_mostly ehci_platform_hc_driver;
- .get_frame_number = ehci_get_frame,
-
- .hub_status_data = ehci_hub_status_data,
- .hub_control = ehci_hub_control,
-#if defined(CONFIG_PM)
- .bus_suspend = ehci_bus_suspend,
- .bus_resume = ehci_bus_resume,
-#endif
- .relinquish_port = ehci_relinquish_port,
- .port_handed_over = ehci_port_handed_over,
-
- .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
+static const struct ehci_driver_overrides platform_overrides __initdata = {
+ .reset = ehci_platform_reset,
};
-static int __devinit ehci_platform_probe(struct platform_device *dev)
+static int ehci_platform_probe(struct platform_device *dev)
{
struct usb_hcd *hcd;
struct resource *res_mem;
@@ -96,12 +79,12 @@ static int __devinit ehci_platform_probe(struct platform_device *dev)
irq = platform_get_irq(dev, 0);
if (irq < 0) {
- pr_err("no irq provided");
+ dev_err(&dev->dev, "no irq provided");
return irq;
}
res_mem = platform_get_resource(dev, IORESOURCE_MEM, 0);
if (!res_mem) {
- pr_err("no memory recourse provided");
+ dev_err(&dev->dev, "no memory resource provided");
return -ENXIO;
}
@@ -121,29 +104,19 @@ static int __devinit ehci_platform_probe(struct platform_device *dev)
hcd->rsrc_start = res_mem->start;
hcd->rsrc_len = resource_size(res_mem);
- if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
- pr_err("controller already in use");
- err = -EBUSY;
- goto err_put_hcd;
- }
-
- hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len);
+ hcd->regs = devm_request_and_ioremap(&dev->dev, res_mem);
if (!hcd->regs) {
err = -ENOMEM;
- goto err_release_region;
+ goto err_put_hcd;
}
err = usb_add_hcd(hcd, irq, IRQF_SHARED);
if (err)
- goto err_iounmap;
+ goto err_put_hcd;
platform_set_drvdata(dev, hcd);
return err;
-err_iounmap:
- iounmap(hcd->regs);
-err_release_region:
- release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
err_put_hcd:
usb_put_hcd(hcd);
err_power:
@@ -153,14 +126,12 @@ err_power:
return err;
}
-static int __devexit ehci_platform_remove(struct platform_device *dev)
+static int ehci_platform_remove(struct platform_device *dev)
{
struct usb_hcd *hcd = platform_get_drvdata(dev);
struct usb_ehci_pdata *pdata = dev->dev.platform_data;
usb_remove_hcd(hcd);
- iounmap(hcd->regs);
- release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
usb_put_hcd(hcd);
platform_set_drvdata(dev, NULL);
@@ -225,7 +196,7 @@ static const struct dev_pm_ops ehci_platform_pm_ops = {
static struct platform_driver ehci_platform_driver = {
.id_table = ehci_platform_table,
.probe = ehci_platform_probe,
- .remove = __devexit_p(ehci_platform_remove),
+ .remove = ehci_platform_remove,
.shutdown = usb_hcd_platform_shutdown,
.driver = {
.owner = THIS_MODULE,
@@ -233,3 +204,26 @@ static struct platform_driver ehci_platform_driver = {
.pm = &ehci_platform_pm_ops,
}
};
+
+static int __init ehci_platform_init(void)
+{
+ if (usb_disabled())
+ return -ENODEV;
+
+ pr_info("%s: " DRIVER_DESC "\n", hcd_name);
+
+ ehci_init_driver(&ehci_platform_hc_driver, &platform_overrides);
+ return platform_driver_register(&ehci_platform_driver);
+}
+module_init(ehci_platform_init);
+
+static void __exit ehci_platform_cleanup(void)
+{
+ platform_driver_unregister(&ehci_platform_driver);
+}
+module_exit(ehci_platform_cleanup);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_AUTHOR("Hauke Mehrtens");
+MODULE_AUTHOR("Alan Stern");
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/host/ehci-pmcmsp.c b/drivers/usb/host/ehci-pmcmsp.c
index 087aee2a904f..363890ee41d2 100644
--- a/drivers/usb/host/ehci-pmcmsp.c
+++ b/drivers/usb/host/ehci-pmcmsp.c
@@ -90,7 +90,6 @@ static int ehci_msp_setup(struct usb_hcd *hcd)
return retval;
usb_hcd_tdi_set_mode(ehci);
- ehci_port_power(ehci, 0);
return retval;
}
diff --git a/drivers/usb/host/ehci-ppc-of.c b/drivers/usb/host/ehci-ppc-of.c
index fa937d05a02b..45aceefd0c2b 100644
--- a/drivers/usb/host/ehci-ppc-of.c
+++ b/drivers/usb/host/ehci-ppc-of.c
@@ -71,7 +71,7 @@ static const struct hc_driver ehci_ppc_of_hc_driver = {
* Fix: Enable Break Memory Transfer (BMT) in INSNREG3
*/
#define PPC440EPX_EHCI0_INSREG_BMT (0x1 << 0)
-static int __devinit
+static int
ppc44x_enable_bmt(struct device_node *dn)
{
__iomem u32 *insreg_virt;
@@ -87,7 +87,7 @@ ppc44x_enable_bmt(struct device_node *dn)
}
-static int __devinit ehci_hcd_ppc_of_probe(struct platform_device *op)
+static int ehci_hcd_ppc_of_probe(struct platform_device *op)
{
struct device_node *dn = op->dev.of_node;
struct usb_hcd *hcd;
diff --git a/drivers/usb/host/ehci-ps3.c b/drivers/usb/host/ehci-ps3.c
index 45a356e9f138..df5925a4f0db 100644
--- a/drivers/usb/host/ehci-ps3.c
+++ b/drivers/usb/host/ehci-ps3.c
@@ -93,7 +93,7 @@ static const struct hc_driver ps3_ehci_hc_driver = {
.clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
};
-static int __devinit ps3_ehci_probe(struct ps3_system_bus_device *dev)
+static int ps3_ehci_probe(struct ps3_system_bus_device *dev)
{
int result;
struct usb_hcd *hcd;
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
index 4b66374bdc8e..3d989028c836 100644
--- a/drivers/usb/host/ehci-q.c
+++ b/drivers/usb/host/ehci-q.c
@@ -264,15 +264,9 @@ ehci_urb_done(struct ehci_hcd *ehci, struct urb *urb, int status)
__releases(ehci->lock)
__acquires(ehci->lock)
{
- if (likely (urb->hcpriv != NULL)) {
- struct ehci_qh *qh = (struct ehci_qh *) urb->hcpriv;
-
- /* S-mask in a QH means it's an interrupt urb */
- if ((qh->hw->hw_info2 & cpu_to_hc32(ehci, QH_SMASK)) != 0) {
-
- /* ... update hc-wide periodic stats (for usbfs) */
- ehci_to_hcd(ehci)->self.bandwidth_int_reqs--;
- }
+ if (usb_pipetype(urb->pipe) == PIPE_INTERRUPT) {
+ /* ... update hc-wide periodic stats */
+ ehci_to_hcd(ehci)->self.bandwidth_int_reqs--;
}
if (unlikely(urb->unlinked)) {
diff --git a/drivers/usb/host/ehci-s5p.c b/drivers/usb/host/ehci-s5p.c
index 85b74be202eb..319dcfaa8735 100644
--- a/drivers/usb/host/ehci-s5p.c
+++ b/drivers/usb/host/ehci-s5p.c
@@ -85,7 +85,7 @@ static void s5p_setup_vbus_gpio(struct platform_device *pdev)
static u64 ehci_s5p_dma_mask = DMA_BIT_MASK(32);
-static int __devinit s5p_ehci_probe(struct platform_device *pdev)
+static int s5p_ehci_probe(struct platform_device *pdev)
{
struct s5p_ehci_platdata *pdata;
struct s5p_ehci_hcd *s5p_ehci;
@@ -136,7 +136,7 @@ static int __devinit s5p_ehci_probe(struct platform_device *pdev)
goto fail_clk;
}
- err = clk_enable(s5p_ehci->clk);
+ err = clk_prepare_enable(s5p_ehci->clk);
if (err)
goto fail_clk;
@@ -183,13 +183,13 @@ static int __devinit s5p_ehci_probe(struct platform_device *pdev)
return 0;
fail_io:
- clk_disable(s5p_ehci->clk);
+ clk_disable_unprepare(s5p_ehci->clk);
fail_clk:
usb_put_hcd(hcd);
return err;
}
-static int __devexit s5p_ehci_remove(struct platform_device *pdev)
+static int s5p_ehci_remove(struct platform_device *pdev)
{
struct s5p_ehci_platdata *pdata = pdev->dev.platform_data;
struct s5p_ehci_hcd *s5p_ehci = platform_get_drvdata(pdev);
@@ -200,7 +200,7 @@ static int __devexit s5p_ehci_remove(struct platform_device *pdev)
if (pdata && pdata->phy_exit)
pdata->phy_exit(pdev, S5P_USB_PHY_HOST);
- clk_disable(s5p_ehci->clk);
+ clk_disable_unprepare(s5p_ehci->clk);
usb_put_hcd(hcd);
@@ -231,7 +231,7 @@ static int s5p_ehci_suspend(struct device *dev)
if (pdata && pdata->phy_exit)
pdata->phy_exit(pdev, S5P_USB_PHY_HOST);
- clk_disable(s5p_ehci->clk);
+ clk_disable_unprepare(s5p_ehci->clk);
return rc;
}
@@ -243,7 +243,7 @@ static int s5p_ehci_resume(struct device *dev)
struct platform_device *pdev = to_platform_device(dev);
struct s5p_ehci_platdata *pdata = pdev->dev.platform_data;
- clk_enable(s5p_ehci->clk);
+ clk_prepare_enable(s5p_ehci->clk);
if (pdata && pdata->phy_init)
pdata->phy_init(pdev, S5P_USB_PHY_HOST);
@@ -274,7 +274,7 @@ MODULE_DEVICE_TABLE(of, exynos_ehci_match);
static struct platform_driver s5p_ehci_driver = {
.probe = s5p_ehci_probe,
- .remove = __devexit_p(s5p_ehci_remove),
+ .remove = s5p_ehci_remove,
.shutdown = s5p_ehci_shutdown,
.driver = {
.name = "s5p-ehci",
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
index 7cf3da7babf0..69ebee73c0c1 100644
--- a/drivers/usb/host/ehci-sched.c
+++ b/drivers/usb/host/ehci-sched.c
@@ -36,29 +36,6 @@
static int ehci_get_frame (struct usb_hcd *hcd);
-#ifdef CONFIG_PCI
-
-static unsigned ehci_read_frame_index(struct ehci_hcd *ehci)
-{
- unsigned uf;
-
- /*
- * The MosChip MCS9990 controller updates its microframe counter
- * a little before the frame counter, and occasionally we will read
- * the invalid intermediate value. Avoid problems by checking the
- * microframe number (the low-order 3 bits); if they are 0 then
- * re-read the register to get the correct value.
- */
- uf = ehci_readl(ehci, &ehci->regs->frame_index);
- if (unlikely(ehci->frame_index_bug && ((uf & 7) == 0)))
- uf = ehci_readl(ehci, &ehci->regs->frame_index);
- return uf;
-}
-
-#endif
-
-/*-------------------------------------------------------------------------*/
-
/*
* periodic_next_shadow - return "next" pointer on shadow list
* @periodic: host pointer to qh/itd/sitd
@@ -1361,7 +1338,7 @@ sitd_slot_ok (
* given EHCI_TUNE_FLS and the slop). Or, write a smarter scheduler!
*/
-#define SCHEDULE_SLOP 80 /* microframes */
+#define SCHEDULING_DELAY 40 /* microframes */
static int
iso_stream_schedule (
@@ -1370,7 +1347,7 @@ iso_stream_schedule (
struct ehci_iso_stream *stream
)
{
- u32 now, next, start, period, span;
+ u32 now, base, next, start, period, span;
int status;
unsigned mod = ehci->periodic_size << 3;
struct ehci_iso_sched *sched = urb->hcpriv;
@@ -1382,62 +1359,72 @@ iso_stream_schedule (
span <<= 3;
}
- if (span > mod - SCHEDULE_SLOP) {
- ehci_dbg (ehci, "iso request %p too long\n", urb);
- status = -EFBIG;
- goto fail;
- }
-
now = ehci_read_frame_index(ehci) & (mod - 1);
/* Typical case: reuse current schedule, stream is still active.
* Hopefully there are no gaps from the host falling behind
- * (irq delays etc), but if there are we'll take the next
- * slot in the schedule, implicitly assuming URB_ISO_ASAP.
+ * (irq delays etc). If there are, the behavior depends on
+ * whether URB_ISO_ASAP is set.
*/
if (likely (!list_empty (&stream->td_list))) {
- u32 excess;
- /* For high speed devices, allow scheduling within the
- * isochronous scheduling threshold. For full speed devices
- * and Intel PCI-based controllers, don't (work around for
- * Intel ICH9 bug).
- */
- if (!stream->highspeed && ehci->fs_i_thresh)
- next = now + ehci->i_thresh;
+ /* Take the isochronous scheduling threshold into account */
+ if (ehci->i_thresh)
+ next = now + ehci->i_thresh; /* uframe cache */
else
- next = now;
+ next = (now + 2 + 7) & ~0x07; /* full frame cache */
- /* Fell behind (by up to twice the slop amount)?
- * We decide based on the time of the last currently-scheduled
- * slot, not the time of the next available slot.
+ /*
+ * Use ehci->last_iso_frame as the base. There can't be any
+ * TDs scheduled for earlier than that.
*/
- excess = (stream->next_uframe - period - next) & (mod - 1);
- if (excess >= mod - 2 * SCHEDULE_SLOP)
- start = next + excess - mod + period *
- DIV_ROUND_UP(mod - excess, period);
- else
- start = next + excess + period;
- if (start - now >= mod) {
- ehci_dbg(ehci, "request %p would overflow (%d+%d >= %d)\n",
- urb, start - now - period, period,
- mod);
- status = -EFBIG;
+ base = ehci->last_iso_frame << 3;
+ next = (next - base) & (mod - 1);
+ start = (stream->next_uframe - base) & (mod - 1);
+
+ /* Is the schedule already full? */
+ if (unlikely(start < period)) {
+ ehci_dbg(ehci, "iso sched full %p (%u-%u < %u mod %u)\n",
+ urb, stream->next_uframe, base,
+ period, mod);
+ status = -ENOSPC;
goto fail;
}
+
+ /* Behind the scheduling threshold? */
+ if (unlikely(start < next)) {
+
+ /* USB_ISO_ASAP: Round up to the first available slot */
+ if (urb->transfer_flags & URB_ISO_ASAP)
+ start += (next - start + period - 1) & -period;
+
+ /*
+ * Not ASAP: Use the next slot in the stream. If
+ * the entire URB falls before the threshold, fail.
+ */
+ else if (start + span - period < next) {
+ ehci_dbg(ehci, "iso urb late %p (%u+%u < %u)\n",
+ urb, start + base,
+ span - period, next + base);
+ status = -EXDEV;
+ goto fail;
+ }
+ }
+
+ start += base;
}
/* need to schedule; when's the next (u)frame we could start?
* this is bigger than ehci->i_thresh allows; scheduling itself
- * isn't free, the slop should handle reasonably slow cpus. it
+ * isn't free, the delay should handle reasonably slow cpus. it
* can also help high bandwidth if the dma and irq loads don't
* jump until after the queue is primed.
*/
else {
int done = 0;
- start = SCHEDULE_SLOP + (now & ~0x07);
- /* NOTE: assumes URB_ISO_ASAP, to limit complexity/bugs */
+ base = now & ~0x07;
+ start = base + SCHEDULING_DELAY;
/* find a uframe slot with enough bandwidth.
* Early uframes are more precious because full-speed
@@ -1464,19 +1451,16 @@ iso_stream_schedule (
/* no room in the schedule */
if (!done) {
- ehci_dbg(ehci, "iso resched full %p (now %d max %d)\n",
- urb, now, now + mod);
+ ehci_dbg(ehci, "iso sched full %p", urb);
status = -ENOSPC;
goto fail;
}
}
/* Tried to schedule too far into the future? */
- if (unlikely(start - now + span - period
- >= mod - 2 * SCHEDULE_SLOP)) {
- ehci_dbg(ehci, "request %p would overflow (%d+%d >= %d)\n",
- urb, start - now, span - period,
- mod - 2 * SCHEDULE_SLOP);
+ if (unlikely(start - base + span - period >= mod)) {
+ ehci_dbg(ehci, "request %p would overflow (%u+%u >= %u)\n",
+ urb, start - base, span - period, mod);
status = -EFBIG;
goto fail;
}
@@ -1490,7 +1474,7 @@ iso_stream_schedule (
/* Make sure scan_isoc() sees these */
if (ehci->isoc_count == 0)
- ehci->next_frame = now >> 3;
+ ehci->last_iso_frame = now >> 3;
return 0;
fail:
@@ -1646,7 +1630,7 @@ static void itd_link_urb(
/* don't need that schedule data any more */
iso_sched_free (stream, iso_sched);
- urb->hcpriv = NULL;
+ urb->hcpriv = stream;
++ehci->isoc_count;
enable_periodic(ehci);
@@ -1708,7 +1692,7 @@ static bool itd_complete(struct ehci_hcd *ehci, struct ehci_itd *itd)
urb->actual_length += desc->actual_length;
} else {
/* URB was too late */
- desc->status = -EXDEV;
+ urb->error_count++;
}
}
@@ -2045,7 +2029,7 @@ static void sitd_link_urb(
/* don't need that schedule data any more */
iso_sched_free (stream, sched);
- urb->hcpriv = NULL;
+ urb->hcpriv = stream;
++ehci->isoc_count;
enable_periodic(ehci);
@@ -2081,7 +2065,7 @@ static bool sitd_complete(struct ehci_hcd *ehci, struct ehci_sitd *sitd)
t = hc32_to_cpup(ehci, &sitd->hw_results);
/* report transfer status */
- if (t & SITD_ERRS) {
+ if (unlikely(t & SITD_ERRS)) {
urb->error_count++;
if (t & SITD_STS_DBE)
desc->status = usb_pipein (urb->pipe)
@@ -2091,6 +2075,9 @@ static bool sitd_complete(struct ehci_hcd *ehci, struct ehci_sitd *sitd)
desc->status = -EOVERFLOW;
else /* XACT, MMF, etc */
desc->status = -EPROTO;
+ } else if (unlikely(t & SITD_STS_ACTIVE)) {
+ /* URB was too late */
+ urb->error_count++;
} else {
desc->status = 0;
desc->actual_length = desc->length - SITD_LENGTH(t);
@@ -2220,16 +2207,16 @@ static void scan_isoc(struct ehci_hcd *ehci)
now_frame = (uf >> 3) & fmask;
live = true;
} else {
- now_frame = (ehci->next_frame - 1) & fmask;
+ now_frame = (ehci->last_iso_frame - 1) & fmask;
live = false;
}
ehci->now_frame = now_frame;
- frame = ehci->next_frame;
for (;;) {
union ehci_shadow q, *q_p;
__hc32 type, *hw_p;
+ frame = ehci->last_iso_frame;
restart:
/* scan each element in frame's queue for completions */
q_p = &ehci->pshadow [frame];
@@ -2334,7 +2321,6 @@ restart:
/* Stop when we have reached the current frame */
if (frame == now_frame)
break;
- frame = (frame + 1) & fmask;
+ ehci->last_iso_frame = (frame + 1) & fmask;
}
- ehci->next_frame = now_frame;
}
diff --git a/drivers/usb/host/ehci-sh.c b/drivers/usb/host/ehci-sh.c
index 6081e1ed3ac9..0c90a24fa989 100644
--- a/drivers/usb/host/ehci-sh.c
+++ b/drivers/usb/host/ehci-sh.c
@@ -21,17 +21,10 @@ struct ehci_sh_priv {
static int ehci_sh_reset(struct usb_hcd *hcd)
{
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
- int ret;
ehci->caps = hcd->regs;
- ret = ehci_setup(hcd);
- if (unlikely(ret))
- return ret;
-
- ehci_port_power(ehci, 0);
-
- return ret;
+ return ehci_setup(hcd);
}
static const struct hc_driver ehci_sh_hc_driver = {
diff --git a/drivers/usb/host/ehci-spear.c b/drivers/usb/host/ehci-spear.c
index c718a065e154..466c1bb5b967 100644
--- a/drivers/usb/host/ehci-spear.c
+++ b/drivers/usb/host/ehci-spear.c
@@ -37,18 +37,11 @@ static void spear_stop_ehci(struct spear_ehci *ehci)
static int ehci_spear_setup(struct usb_hcd *hcd)
{
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
- int retval = 0;
/* registers start at offset 0x0 */
ehci->caps = hcd->regs;
- retval = ehci_setup(hcd);
- if (retval)
- return retval;
-
- ehci_port_power(ehci, 0);
-
- return retval;
+ return ehci_setup(hcd);
}
static const struct hc_driver ehci_spear_hc_driver = {
@@ -116,8 +109,6 @@ static int spear_ehci_hcd_drv_probe(struct platform_device *pdev)
struct clk *usbh_clk;
const struct hc_driver *driver = &ehci_spear_hc_driver;
int irq, retval;
- char clk_name[20] = "usbh_clk";
- static int instance = -1;
if (usb_disabled())
return -ENODEV;
@@ -125,7 +116,7 @@ static int spear_ehci_hcd_drv_probe(struct platform_device *pdev)
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
retval = irq;
- goto fail_irq_get;
+ goto fail;
}
/*
@@ -136,47 +127,38 @@ static int spear_ehci_hcd_drv_probe(struct platform_device *pdev)
if (!pdev->dev.dma_mask)
pdev->dev.dma_mask = &spear_ehci_dma_mask;
- /*
- * Increment the device instance, when probing via device-tree
- */
- if (pdev->id < 0)
- instance++;
- else
- instance = pdev->id;
- sprintf(clk_name, "usbh.%01d_clk", instance);
-
- usbh_clk = clk_get(NULL, clk_name);
+ usbh_clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(usbh_clk)) {
dev_err(&pdev->dev, "Error getting interface clock\n");
retval = PTR_ERR(usbh_clk);
- goto fail_get_usbh_clk;
+ goto fail;
}
hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev));
if (!hcd) {
retval = -ENOMEM;
- goto fail_create_hcd;
+ goto fail;
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
retval = -ENODEV;
- goto fail_request_resource;
+ goto err_put_hcd;
}
hcd->rsrc_start = res->start;
hcd->rsrc_len = resource_size(res);
- if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len,
+ if (!devm_request_mem_region(&pdev->dev, hcd->rsrc_start, hcd->rsrc_len,
driver->description)) {
retval = -EBUSY;
- goto fail_request_resource;
+ goto err_put_hcd;
}
- hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
+ hcd->regs = devm_ioremap(&pdev->dev, hcd->rsrc_start, hcd->rsrc_len);
if (hcd->regs == NULL) {
dev_dbg(&pdev->dev, "error mapping memory\n");
retval = -ENOMEM;
- goto fail_ioremap;
+ goto err_put_hcd;
}
ehci = (struct spear_ehci *)hcd_to_ehci(hcd);
@@ -185,21 +167,15 @@ static int spear_ehci_hcd_drv_probe(struct platform_device *pdev)
spear_start_ehci(ehci);
retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
if (retval)
- goto fail_add_hcd;
+ goto err_stop_ehci;
return retval;
-fail_add_hcd:
+err_stop_ehci:
spear_stop_ehci(ehci);
- iounmap(hcd->regs);
-fail_ioremap:
- release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
-fail_request_resource:
+err_put_hcd:
usb_put_hcd(hcd);
-fail_create_hcd:
- clk_put(usbh_clk);
-fail_get_usbh_clk:
-fail_irq_get:
+fail:
dev_err(&pdev->dev, "init fail, %d\n", retval);
return retval ;
@@ -218,17 +194,12 @@ static int spear_ehci_hcd_drv_remove(struct platform_device *pdev)
if (ehci_p->clk)
spear_stop_ehci(ehci_p);
- iounmap(hcd->regs);
- release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
usb_put_hcd(hcd);
- if (ehci_p->clk)
- clk_put(ehci_p->clk);
-
return 0;
}
-static struct of_device_id spear_ehci_id_table[] __devinitdata = {
+static struct of_device_id spear_ehci_id_table[] = {
{ .compatible = "st,spear600-ehci", },
{ },
};
diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c
index 6223d1757848..acf17556bd87 100644
--- a/drivers/usb/host/ehci-tegra.c
+++ b/drivers/usb/host/ehci-tegra.c
@@ -28,7 +28,10 @@
#include <linux/pm_runtime.h>
#include <linux/usb/tegra_usb_phy.h>
-#include <mach/iomap.h>
+
+#define TEGRA_USB_BASE 0xC5000000
+#define TEGRA_USB2_BASE 0xC5004000
+#define TEGRA_USB3_BASE 0xC5008000
#define TEGRA_USB_DMA_ALIGN 32
@@ -277,7 +280,6 @@ static void tegra_ehci_shutdown(struct usb_hcd *hcd)
static int tegra_ehci_setup(struct usb_hcd *hcd)
{
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
- int retval;
/* EHCI registers start at offset 0x100 */
ehci->caps = hcd->regs + 0x100;
@@ -285,12 +287,7 @@ static int tegra_ehci_setup(struct usb_hcd *hcd)
/* switch to host mode */
hcd->has_tt = 1;
- retval = ehci_setup(hcd);
- if (retval)
- return retval;
-
- ehci_port_power(ehci, 1);
- return retval;
+ return ehci_setup(hcd);
}
struct dma_aligned_buffer {
@@ -778,9 +775,6 @@ static int tegra_ehci_remove(struct platform_device *pdev)
struct tegra_ehci_hcd *tegra = platform_get_drvdata(pdev);
struct usb_hcd *hcd = ehci_to_hcd(tegra->ehci);
- if (tegra == NULL || hcd == NULL)
- return -EINVAL;
-
pm_runtime_get_sync(&pdev->dev);
pm_runtime_disable(&pdev->dev);
pm_runtime_put_noidle(&pdev->dev);
@@ -811,7 +805,7 @@ static void tegra_ehci_hcd_shutdown(struct platform_device *pdev)
hcd->driver->shutdown(hcd);
}
-static struct of_device_id tegra_ehci_of_match[] __devinitdata = {
+static struct of_device_id tegra_ehci_of_match[] = {
{ .compatible = "nvidia,tegra20-ehci", },
{ },
};
diff --git a/drivers/usb/host/ehci-vt8500.c b/drivers/usb/host/ehci-vt8500.c
index d3c9a3e397b9..11695d5b9d86 100644
--- a/drivers/usb/host/ehci-vt8500.c
+++ b/drivers/usb/host/ehci-vt8500.c
@@ -19,22 +19,6 @@
#include <linux/of.h>
#include <linux/platform_device.h>
-static int ehci_update_device(struct usb_hcd *hcd, struct usb_device *udev)
-{
- struct ehci_hcd *ehci = hcd_to_ehci(hcd);
- int rc = 0;
-
- if (!udev->parent) /* udev is root hub itself, impossible */
- rc = -1;
- /* we only support lpm device connected to root hub yet */
- if (ehci->has_lpm && !udev->parent->parent) {
- rc = ehci_lpm_set_da(ehci, udev->devnum, udev->portnum);
- if (!rc)
- rc = ehci_lpm_check(ehci, udev->portnum);
- }
- return rc;
-}
-
static const struct hc_driver vt8500_ehci_hc_driver = {
.description = hcd_name,
.product_desc = "VT8500 EHCI",
@@ -77,11 +61,6 @@ static const struct hc_driver vt8500_ehci_hc_driver = {
.relinquish_port = ehci_relinquish_port,
.port_handed_over = ehci_port_handed_over,
- /*
- * call back when device connected and addressed
- */
- .update_device = ehci_update_device,
-
.clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
};
diff --git a/drivers/usb/host/ehci-w90x900.c b/drivers/usb/host/ehci-w90x900.c
index ec598082c14b..59e0e24c753f 100644
--- a/drivers/usb/host/ehci-w90x900.c
+++ b/drivers/usb/host/ehci-w90x900.c
@@ -13,12 +13,12 @@
#include <linux/platform_device.h>
-/*ebable phy0 and phy1 for w90p910*/
+/* enable phy0 and phy1 for w90p910 */
#define ENPHY (0x01<<8)
#define PHY0_CTR (0xA4)
#define PHY1_CTR (0xA8)
-static int __devinit usb_w90x900_probe(const struct hc_driver *driver,
+static int usb_w90x900_probe(const struct hc_driver *driver,
struct platform_device *pdev)
{
struct usb_hcd *hcd;
@@ -147,7 +147,7 @@ static const struct hc_driver ehci_w90x900_hc_driver = {
.clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
};
-static int __devinit ehci_w90x900_probe(struct platform_device *pdev)
+static int ehci_w90x900_probe(struct platform_device *pdev)
{
if (usb_disabled())
return -ENODEV;
@@ -155,7 +155,7 @@ static int __devinit ehci_w90x900_probe(struct platform_device *pdev)
return usb_w90x900_probe(&ehci_w90x900_hc_driver, pdev);
}
-static int __devexit ehci_w90x900_remove(struct platform_device *pdev)
+static int ehci_w90x900_remove(struct platform_device *pdev)
{
struct usb_hcd *hcd = platform_get_drvdata(pdev);
@@ -166,7 +166,7 @@ static int __devexit ehci_w90x900_remove(struct platform_device *pdev)
static struct platform_driver ehci_hcd_w90x900_driver = {
.probe = ehci_w90x900_probe,
- .remove = __devexit_p(ehci_w90x900_remove),
+ .remove = ehci_w90x900_remove,
.driver = {
.name = "w90x900-ehci",
.owner = THIS_MODULE,
diff --git a/drivers/usb/host/ehci-xilinx-of.c b/drivers/usb/host/ehci-xilinx-of.c
index 6a3f921a5d76..4f285e8e404a 100644
--- a/drivers/usb/host/ehci-xilinx-of.c
+++ b/drivers/usb/host/ehci-xilinx-of.c
@@ -125,7 +125,7 @@ static const struct hc_driver ehci_xilinx_of_hc_driver = {
* as HS only or HS/FS only, it checks the configuration in the device tree
* entry, and sets an appropriate value for hcd->has_tt.
*/
-static int __devinit ehci_hcd_xilinx_of_probe(struct platform_device *op)
+static int ehci_hcd_xilinx_of_probe(struct platform_device *op)
{
struct device_node *dn = op->dev.of_node;
struct usb_hcd *hcd;
diff --git a/drivers/usb/host/ehci-xls.c b/drivers/usb/host/ehci-xls.c
deleted file mode 100644
index 8dc6a22d90b8..000000000000
--- a/drivers/usb/host/ehci-xls.c
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * EHCI HCD for Netlogic XLS processors.
- *
- * (C) Copyright 2011 Netlogic Microsystems Inc.
- *
- * Based on various ehci-*.c drivers
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file COPYING in the main directory of this archive for
- * more details.
- */
-
-#include <linux/platform_device.h>
-
-static int ehci_xls_setup(struct usb_hcd *hcd)
-{
- struct ehci_hcd *ehci = hcd_to_ehci(hcd);
-
- ehci->caps = hcd->regs;
-
- return ehci_setup(hcd);
-}
-
-int ehci_xls_probe_internal(const struct hc_driver *driver,
- struct platform_device *pdev)
-{
- struct usb_hcd *hcd;
- struct resource *res;
- int retval, irq;
-
- /* Get our IRQ from an earlier registered Platform Resource */
- irq = platform_get_irq(pdev, 0);
- if (irq < 0) {
- dev_err(&pdev->dev, "Found HC with no IRQ. Check %s setup!\n",
- dev_name(&pdev->dev));
- return -ENODEV;
- }
-
- /* Get our Memory Handle */
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res) {
- dev_err(&pdev->dev, "Error: MMIO Handle %s setup!\n",
- dev_name(&pdev->dev));
- return -ENODEV;
- }
- hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev));
- if (!hcd) {
- retval = -ENOMEM;
- goto err1;
- }
-
- hcd->rsrc_start = res->start;
- hcd->rsrc_len = resource_size(res);
-
- if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len,
- driver->description)) {
- dev_dbg(&pdev->dev, "controller already in use\n");
- retval = -EBUSY;
- goto err2;
- }
- hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len);
-
- if (hcd->regs == NULL) {
- dev_dbg(&pdev->dev, "error mapping memory\n");
- retval = -EFAULT;
- goto err3;
- }
-
- retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
- if (retval != 0)
- goto err4;
- return retval;
-
-err4:
- iounmap(hcd->regs);
-err3:
- release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
-err2:
- usb_put_hcd(hcd);
-err1:
- dev_err(&pdev->dev, "init %s fail, %d\n", dev_name(&pdev->dev),
- retval);
- return retval;
-}
-
-static struct hc_driver ehci_xls_hc_driver = {
- .description = hcd_name,
- .product_desc = "XLS EHCI Host Controller",
- .hcd_priv_size = sizeof(struct ehci_hcd),
- .irq = ehci_irq,
- .flags = HCD_USB2 | HCD_MEMORY,
- .reset = ehci_xls_setup,
- .start = ehci_run,
- .stop = ehci_stop,
- .shutdown = ehci_shutdown,
-
- .urb_enqueue = ehci_urb_enqueue,
- .urb_dequeue = ehci_urb_dequeue,
- .endpoint_disable = ehci_endpoint_disable,
- .endpoint_reset = ehci_endpoint_reset,
-
- .get_frame_number = ehci_get_frame,
-
- .hub_status_data = ehci_hub_status_data,
- .hub_control = ehci_hub_control,
- .bus_suspend = ehci_bus_suspend,
- .bus_resume = ehci_bus_resume,
- .relinquish_port = ehci_relinquish_port,
- .port_handed_over = ehci_port_handed_over,
-
- .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
-};
-
-static int ehci_xls_probe(struct platform_device *pdev)
-{
- if (usb_disabled())
- return -ENODEV;
-
- return ehci_xls_probe_internal(&ehci_xls_hc_driver, pdev);
-}
-
-static int ehci_xls_remove(struct platform_device *pdev)
-{
- struct usb_hcd *hcd = platform_get_drvdata(pdev);
-
- usb_remove_hcd(hcd);
- iounmap(hcd->regs);
- release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
- usb_put_hcd(hcd);
- return 0;
-}
-
-MODULE_ALIAS("ehci-xls");
-
-static struct platform_driver ehci_xls_driver = {
- .probe = ehci_xls_probe,
- .remove = ehci_xls_remove,
- .shutdown = usb_hcd_platform_shutdown,
- .driver = {
- .name = "ehci-xls",
- },
-};
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index da07d98f7d1d..9dadc7118d68 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -143,7 +143,7 @@ struct ehci_hcd { /* one per controller */
struct ehci_qh *intr_unlink_last;
unsigned intr_unlink_cycle;
unsigned now_frame; /* frame from HC hardware */
- unsigned next_frame; /* scan periodic, start here */
+ unsigned last_iso_frame; /* last frame scanned for iso */
unsigned intr_count; /* intr activity count */
unsigned isoc_count; /* isoc activity count */
unsigned periodic_count; /* periodic activity count */
@@ -193,7 +193,6 @@ struct ehci_hcd { /* one per controller */
unsigned has_amcc_usb23:1;
unsigned need_io_watchdog:1;
unsigned amd_pll_fix:1;
- unsigned fs_i_thresh:1; /* Intel iso scheduling */
unsigned use_dummy_qh:1; /* AMD Frame List table quirk*/
unsigned has_synopsys_hc_bug:1; /* Synopsys HC */
unsigned frame_index_bug:1; /* MosChip (AKA NetMos) */
@@ -207,7 +206,6 @@ struct ehci_hcd { /* one per controller */
#define OHCI_HCCTRL_LEN 0x4
__hc32 *ohci_hcctrl_reg;
unsigned has_hostpc:1;
- unsigned has_lpm:1; /* support link power management */
unsigned has_ppcd:1; /* support per-port change bits */
u8 sbrn; /* packed release number */
@@ -762,26 +760,41 @@ static inline u32 hc32_to_cpup (const struct ehci_hcd *ehci, const __hc32 *x)
/*-------------------------------------------------------------------------*/
-#ifdef CONFIG_PCI
-
-/* For working around the MosChip frame-index-register bug */
-static unsigned ehci_read_frame_index(struct ehci_hcd *ehci);
-
+#define ehci_dbg(ehci, fmt, args...) \
+ dev_dbg(ehci_to_hcd(ehci)->self.controller , fmt , ## args)
+#define ehci_err(ehci, fmt, args...) \
+ dev_err(ehci_to_hcd(ehci)->self.controller , fmt , ## args)
+#define ehci_info(ehci, fmt, args...) \
+ dev_info(ehci_to_hcd(ehci)->self.controller , fmt , ## args)
+#define ehci_warn(ehci, fmt, args...) \
+ dev_warn(ehci_to_hcd(ehci)->self.controller , fmt , ## args)
+
+#ifdef VERBOSE_DEBUG
+# define ehci_vdbg ehci_dbg
#else
-
-static inline unsigned ehci_read_frame_index(struct ehci_hcd *ehci)
-{
- return ehci_readl(ehci, &ehci->regs->frame_index);
-}
-
+ static inline void ehci_vdbg(struct ehci_hcd *ehci, ...) {}
#endif
-/*-------------------------------------------------------------------------*/
-
#ifndef DEBUG
#define STUB_DEBUG_FILES
#endif /* DEBUG */
/*-------------------------------------------------------------------------*/
+/* Declarations of things exported for use by ehci platform drivers */
+
+struct ehci_driver_overrides {
+ size_t extra_priv_size;
+ int (*reset)(struct usb_hcd *hcd);
+};
+
+extern void ehci_init_driver(struct hc_driver *drv,
+ const struct ehci_driver_overrides *over);
+extern int ehci_setup(struct usb_hcd *hcd);
+
+#ifdef CONFIG_PM
+extern int ehci_suspend(struct usb_hcd *hcd, bool do_wakeup);
+extern int ehci_resume(struct usb_hcd *hcd, bool hibernated);
+#endif /* CONFIG_PM */
+
#endif /* __LINUX_EHCI_HCD_H */
diff --git a/drivers/usb/host/fhci-hcd.c b/drivers/usb/host/fhci-hcd.c
index 7da1a26bed2e..0b46542591ff 100644
--- a/drivers/usb/host/fhci-hcd.c
+++ b/drivers/usb/host/fhci-hcd.c
@@ -561,7 +561,7 @@ static const struct hc_driver fhci_driver = {
.hub_control = fhci_hub_control,
};
-static int __devinit of_fhci_probe(struct platform_device *ofdev)
+static int of_fhci_probe(struct platform_device *ofdev)
{
struct device *dev = &ofdev->dev;
struct device_node *node = dev->of_node;
@@ -780,7 +780,7 @@ err_regs:
return ret;
}
-static int __devexit fhci_remove(struct device *dev)
+static int fhci_remove(struct device *dev)
{
struct usb_hcd *hcd = dev_get_drvdata(dev);
struct fhci_hcd *fhci = hcd_to_fhci(hcd);
@@ -803,7 +803,7 @@ static int __devexit fhci_remove(struct device *dev)
return 0;
}
-static int __devexit of_fhci_remove(struct platform_device *ofdev)
+static int of_fhci_remove(struct platform_device *ofdev)
{
return fhci_remove(&ofdev->dev);
}
@@ -821,7 +821,7 @@ static struct platform_driver of_fhci_driver = {
.of_match_table = of_fhci_match,
},
.probe = of_fhci_probe,
- .remove = __devexit_p(of_fhci_remove),
+ .remove = of_fhci_remove,
};
module_platform_driver(of_fhci_driver);
diff --git a/drivers/usb/host/fsl-mph-dr-of.c b/drivers/usb/host/fsl-mph-dr-of.c
index 1e771292383f..5105127c1d4b 100644
--- a/drivers/usb/host/fsl-mph-dr-of.c
+++ b/drivers/usb/host/fsl-mph-dr-of.c
@@ -24,7 +24,7 @@ struct fsl_usb2_dev_data {
enum fsl_usb2_operating_modes op_mode; /* operating mode */
};
-struct fsl_usb2_dev_data dr_mode_data[] __devinitdata = {
+struct fsl_usb2_dev_data dr_mode_data[] = {
{
.dr_mode = "host",
.drivers = { "fsl-ehci", NULL, NULL, },
@@ -42,7 +42,7 @@ struct fsl_usb2_dev_data dr_mode_data[] __devinitdata = {
},
};
-struct fsl_usb2_dev_data * __devinit get_dr_mode_data(struct device_node *np)
+struct fsl_usb2_dev_data *get_dr_mode_data(struct device_node *np)
{
const unsigned char *prop;
int i;
@@ -59,7 +59,7 @@ struct fsl_usb2_dev_data * __devinit get_dr_mode_data(struct device_node *np)
return &dr_mode_data[0]; /* mode not specified, use host */
}
-static enum fsl_usb2_phy_modes __devinit determine_usb_phy(const char *phy_type)
+static enum fsl_usb2_phy_modes determine_usb_phy(const char *phy_type)
{
if (!phy_type)
return FSL_USB2_PHY_NONE;
@@ -75,7 +75,7 @@ static enum fsl_usb2_phy_modes __devinit determine_usb_phy(const char *phy_type)
return FSL_USB2_PHY_NONE;
}
-struct platform_device * __devinit fsl_usb2_device_register(
+struct platform_device *fsl_usb2_device_register(
struct platform_device *ofdev,
struct fsl_usb2_platform_data *pdata,
const char *name, int id)
@@ -154,7 +154,7 @@ static int usb_get_ver_info(struct device_node *np)
return ver;
}
-static int __devinit fsl_usb2_mph_dr_of_probe(struct platform_device *ofdev)
+static int fsl_usb2_mph_dr_of_probe(struct platform_device *ofdev)
{
struct device_node *np = ofdev->dev.of_node;
struct platform_device *usb_dev;
@@ -224,13 +224,13 @@ static int __devinit fsl_usb2_mph_dr_of_probe(struct platform_device *ofdev)
return 0;
}
-static int __devexit __unregister_subdev(struct device *dev, void *d)
+static int __unregister_subdev(struct device *dev, void *d)
{
platform_device_unregister(to_platform_device(dev));
return 0;
}
-static int __devexit fsl_usb2_mph_dr_of_remove(struct platform_device *ofdev)
+static int fsl_usb2_mph_dr_of_remove(struct platform_device *ofdev)
{
device_for_each_child(&ofdev->dev, NULL, __unregister_subdev);
return 0;
@@ -336,7 +336,7 @@ static struct platform_driver fsl_usb2_mph_dr_driver = {
.of_match_table = fsl_usb2_mph_dr_of_match,
},
.probe = fsl_usb2_mph_dr_of_probe,
- .remove = __devexit_p(fsl_usb2_mph_dr_of_remove),
+ .remove = fsl_usb2_mph_dr_of_remove,
};
module_platform_driver(fsl_usb2_mph_dr_driver);
diff --git a/drivers/usb/host/imx21-hcd.c b/drivers/usb/host/imx21-hcd.c
index f19e2690c232..bd6a7447ccc9 100644
--- a/drivers/usb/host/imx21-hcd.c
+++ b/drivers/usb/host/imx21-hcd.c
@@ -1680,7 +1680,7 @@ static int imx21_hc_reset(struct usb_hcd *hcd)
return 0;
}
-static int __devinit imx21_hc_start(struct usb_hcd *hcd)
+static int imx21_hc_start(struct usb_hcd *hcd)
{
struct imx21 *imx21 = hcd_to_imx21(hcd);
unsigned long flags;
diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c
index 9e65e3091c8a..b64e661618bb 100644
--- a/drivers/usb/host/isp116x-hcd.c
+++ b/drivers/usb/host/isp116x-hcd.c
@@ -1557,7 +1557,7 @@ static int isp116x_remove(struct platform_device *pdev)
return 0;
}
-static int __devinit isp116x_probe(struct platform_device *pdev)
+static int isp116x_probe(struct platform_device *pdev)
{
struct usb_hcd *hcd;
struct isp116x *isp116x;
diff --git a/drivers/usb/host/isp1362-hcd.c b/drivers/usb/host/isp1362-hcd.c
index 256326322cfd..974480c516fa 100644
--- a/drivers/usb/host/isp1362-hcd.c
+++ b/drivers/usb/host/isp1362-hcd.c
@@ -2645,7 +2645,7 @@ static struct hc_driver isp1362_hc_driver = {
/*-------------------------------------------------------------------------*/
-static int __devexit isp1362_remove(struct platform_device *pdev)
+static int isp1362_remove(struct platform_device *pdev)
{
struct usb_hcd *hcd = platform_get_drvdata(pdev);
struct isp1362_hcd *isp1362_hcd = hcd_to_isp1362_hcd(hcd);
@@ -2680,7 +2680,7 @@ static int __devexit isp1362_remove(struct platform_device *pdev)
return 0;
}
-static int __devinit isp1362_probe(struct platform_device *pdev)
+static int isp1362_probe(struct platform_device *pdev)
{
struct usb_hcd *hcd;
struct isp1362_hcd *isp1362_hcd;
@@ -2856,7 +2856,7 @@ static int isp1362_resume(struct platform_device *pdev)
static struct platform_driver isp1362_driver = {
.probe = isp1362_probe,
- .remove = __devexit_p(isp1362_remove),
+ .remove = isp1362_remove,
.suspend = isp1362_suspend,
.resume = isp1362_resume,
diff --git a/drivers/usb/host/isp1760-if.c b/drivers/usb/host/isp1760-if.c
index fff114fd5461..bbb791bd7617 100644
--- a/drivers/usb/host/isp1760-if.c
+++ b/drivers/usb/host/isp1760-if.c
@@ -43,7 +43,6 @@ static int of_isp1760_probe(struct platform_device *dev)
struct device_node *dp = dev->dev.of_node;
struct resource *res;
struct resource memory;
- struct of_irq oirq;
int virq;
resource_size_t res_len;
int ret;
@@ -69,14 +68,12 @@ static int of_isp1760_probe(struct platform_device *dev)
goto free_data;
}
- if (of_irq_map_one(dp, 0, &oirq)) {
+ virq = irq_of_parse_and_map(dp, 0);
+ if (!virq) {
ret = -ENODEV;
goto release_reg;
}
- virq = irq_create_of_mapping(oirq.controller, oirq.specifier,
- oirq.size);
-
if (of_device_is_compatible(dp, "nxp,usb-isp1761"))
devflags |= ISP1760_FLAG_ISP1761;
@@ -175,7 +172,7 @@ static struct platform_driver isp1760_of_driver = {
#endif
#ifdef CONFIG_PCI
-static int __devinit isp1761_pci_probe(struct pci_dev *dev,
+static int isp1761_pci_probe(struct pci_dev *dev,
const struct pci_device_id *id)
{
u8 latency, limit;
@@ -349,7 +346,7 @@ static struct pci_driver isp1761_pci_driver = {
};
#endif
-static int __devinit isp1760_plat_probe(struct platform_device *pdev)
+static int isp1760_plat_probe(struct platform_device *pdev)
{
int ret = 0;
struct usb_hcd *hcd;
@@ -416,7 +413,7 @@ out:
return ret;
}
-static int __devexit isp1760_plat_remove(struct platform_device *pdev)
+static int isp1760_plat_remove(struct platform_device *pdev)
{
struct resource *mem_res;
resource_size_t mem_size;
@@ -435,7 +432,7 @@ static int __devexit isp1760_plat_remove(struct platform_device *pdev)
static struct platform_driver isp1760_plat_driver = {
.probe = isp1760_plat_probe,
- .remove = __devexit_p(isp1760_plat_remove),
+ .remove = isp1760_plat_remove,
.driver = {
.name = "isp1760",
},
diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c
index 0bf72f943b00..221850a8c25f 100644
--- a/drivers/usb/host/ohci-at91.c
+++ b/drivers/usb/host/ohci-at91.c
@@ -94,7 +94,7 @@ static void at91_stop_hc(struct platform_device *pdev)
/*-------------------------------------------------------------------------*/
-static void __devexit usb_hcd_at91_remove (struct usb_hcd *, struct platform_device *);
+static void usb_hcd_at91_remove (struct usb_hcd *, struct platform_device *);
/* configure so an HC device and id are always provided */
/* always called with process context; sleeping is OK */
@@ -108,7 +108,7 @@ static void __devexit usb_hcd_at91_remove (struct usb_hcd *, struct platform_dev
* then invokes the start() method for the HCD associated with it
* through the hotplug entry's driver_data.
*/
-static int __devinit usb_hcd_at91_probe(const struct hc_driver *driver,
+static int usb_hcd_at91_probe(const struct hc_driver *driver,
struct platform_device *pdev)
{
int retval;
@@ -203,7 +203,7 @@ static int __devinit usb_hcd_at91_probe(const struct hc_driver *driver,
* context, "rmmod" or something similar.
*
*/
-static void __devexit usb_hcd_at91_remove(struct usb_hcd *hcd,
+static void usb_hcd_at91_remove(struct usb_hcd *hcd,
struct platform_device *pdev)
{
usb_remove_hcd(hcd);
@@ -222,7 +222,7 @@ static void __devexit usb_hcd_at91_remove(struct usb_hcd *hcd,
/*-------------------------------------------------------------------------*/
-static int __devinit
+static int
ohci_at91_reset (struct usb_hcd *hcd)
{
struct at91_usbh_data *board = hcd->self.controller->platform_data;
@@ -236,7 +236,7 @@ ohci_at91_reset (struct usb_hcd *hcd)
return 0;
}
-static int __devinit
+static int
ohci_at91_start (struct usb_hcd *hcd)
{
struct ohci_hcd *ohci = hcd_to_ohci (hcd);
@@ -506,7 +506,7 @@ MODULE_DEVICE_TABLE(of, at91_ohci_dt_ids);
static u64 at91_ohci_dma_mask = DMA_BIT_MASK(32);
-static int __devinit ohci_at91_of_init(struct platform_device *pdev)
+static int ohci_at91_of_init(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
int i, gpio;
@@ -548,7 +548,7 @@ static int __devinit ohci_at91_of_init(struct platform_device *pdev)
return 0;
}
#else
-static int __devinit ohci_at91_of_init(struct platform_device *pdev)
+static int ohci_at91_of_init(struct platform_device *pdev)
{
return 0;
}
@@ -556,7 +556,7 @@ static int __devinit ohci_at91_of_init(struct platform_device *pdev)
/*-------------------------------------------------------------------------*/
-static int __devinit ohci_hcd_at91_drv_probe(struct platform_device *pdev)
+static int ohci_hcd_at91_drv_probe(struct platform_device *pdev)
{
struct at91_usbh_data *pdata;
int i;
@@ -641,7 +641,7 @@ static int __devinit ohci_hcd_at91_drv_probe(struct platform_device *pdev)
return usb_hcd_at91_probe(&ohci_at91_hc_driver, pdev);
}
-static int __devexit ohci_hcd_at91_drv_remove(struct platform_device *pdev)
+static int ohci_hcd_at91_drv_remove(struct platform_device *pdev)
{
struct at91_usbh_data *pdata = pdev->dev.platform_data;
int i;
@@ -705,7 +705,7 @@ static int ohci_hcd_at91_drv_resume(struct platform_device *pdev)
if (!clocked)
at91_start_clock();
- ohci_finish_controller_resume(hcd);
+ ohci_resume(hcd, false);
return 0;
}
#else
@@ -717,7 +717,7 @@ MODULE_ALIAS("platform:at91_ohci");
static struct platform_driver ohci_hcd_at91_driver = {
.probe = ohci_hcd_at91_drv_probe,
- .remove = __devexit_p(ohci_hcd_at91_drv_remove),
+ .remove = ohci_hcd_at91_drv_remove,
.shutdown = usb_hcd_platform_shutdown,
.suspend = ohci_hcd_at91_drv_suspend,
.resume = ohci_hcd_at91_drv_resume,
diff --git a/drivers/usb/host/ohci-au1xxx.c b/drivers/usb/host/ohci-au1xxx.c
deleted file mode 100644
index c611699b4aa6..000000000000
--- a/drivers/usb/host/ohci-au1xxx.c
+++ /dev/null
@@ -1,234 +0,0 @@
-/*
- * OHCI HCD (Host Controller Driver) for USB.
- *
- * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
- * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
- * (C) Copyright 2002 Hewlett-Packard Company
- *
- * Bus Glue for AMD Alchemy Au1xxx
- *
- * Written by Christopher Hoover <ch@hpl.hp.com>
- * Based on fragments of previous driver by Russell King et al.
- *
- * Modified for LH7A404 from ohci-sa1111.c
- * by Durgesh Pattamatta <pattamattad@sharpsec.com>
- * Modified for AMD Alchemy Au1xxx
- * by Matt Porter <mporter@kernel.crashing.org>
- *
- * This file is licenced under the GPL.
- */
-
-#include <linux/platform_device.h>
-#include <linux/signal.h>
-
-#include <asm/mach-au1x00/au1000.h>
-
-
-extern int usb_disabled(void);
-
-static int __devinit ohci_au1xxx_start(struct usb_hcd *hcd)
-{
- struct ohci_hcd *ohci = hcd_to_ohci(hcd);
- int ret;
-
- ohci_dbg(ohci, "ohci_au1xxx_start, ohci:%p", ohci);
-
- if ((ret = ohci_init(ohci)) < 0)
- return ret;
-
- if ((ret = ohci_run(ohci)) < 0) {
- dev_err(hcd->self.controller, "can't start %s",
- hcd->self.bus_name);
- ohci_stop(hcd);
- return ret;
- }
-
- return 0;
-}
-
-static const struct hc_driver ohci_au1xxx_hc_driver = {
- .description = hcd_name,
- .product_desc = "Au1xxx OHCI",
- .hcd_priv_size = sizeof(struct ohci_hcd),
-
- /*
- * generic hardware linkage
- */
- .irq = ohci_irq,
- .flags = HCD_USB11 | HCD_MEMORY,
-
- /*
- * basic lifecycle operations
- */
- .start = ohci_au1xxx_start,
- .stop = ohci_stop,
- .shutdown = ohci_shutdown,
-
- /*
- * managing i/o requests and associated device resources
- */
- .urb_enqueue = ohci_urb_enqueue,
- .urb_dequeue = ohci_urb_dequeue,
- .endpoint_disable = ohci_endpoint_disable,
-
- /*
- * scheduling support
- */
- .get_frame_number = ohci_get_frame,
-
- /*
- * root hub support
- */
- .hub_status_data = ohci_hub_status_data,
- .hub_control = ohci_hub_control,
-#ifdef CONFIG_PM
- .bus_suspend = ohci_bus_suspend,
- .bus_resume = ohci_bus_resume,
-#endif
- .start_port_reset = ohci_start_port_reset,
-};
-
-static int ohci_hcd_au1xxx_drv_probe(struct platform_device *pdev)
-{
- int ret, unit;
- struct usb_hcd *hcd;
-
- if (usb_disabled())
- return -ENODEV;
-
- if (pdev->resource[1].flags != IORESOURCE_IRQ) {
- pr_debug("resource[1] is not IORESOURCE_IRQ\n");
- return -ENOMEM;
- }
-
- hcd = usb_create_hcd(&ohci_au1xxx_hc_driver, &pdev->dev, "au1xxx");
- if (!hcd)
- return -ENOMEM;
-
- hcd->rsrc_start = pdev->resource[0].start;
- hcd->rsrc_len = pdev->resource[0].end - pdev->resource[0].start + 1;
-
- if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
- pr_debug("request_mem_region failed\n");
- ret = -EBUSY;
- goto err1;
- }
-
- hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
- if (!hcd->regs) {
- pr_debug("ioremap failed\n");
- ret = -ENOMEM;
- goto err2;
- }
-
- unit = (hcd->rsrc_start == AU1300_USB_OHCI1_PHYS_ADDR) ?
- ALCHEMY_USB_OHCI1 : ALCHEMY_USB_OHCI0;
- if (alchemy_usb_control(unit, 1)) {
- printk(KERN_INFO "%s: controller init failed!\n", pdev->name);
- ret = -ENODEV;
- goto err3;
- }
-
- ohci_hcd_init(hcd_to_ohci(hcd));
-
- ret = usb_add_hcd(hcd, pdev->resource[1].start,
- IRQF_SHARED);
- if (ret == 0) {
- platform_set_drvdata(pdev, hcd);
- return ret;
- }
-
- alchemy_usb_control(unit, 0);
-err3:
- iounmap(hcd->regs);
-err2:
- release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
-err1:
- usb_put_hcd(hcd);
- return ret;
-}
-
-static int ohci_hcd_au1xxx_drv_remove(struct platform_device *pdev)
-{
- struct usb_hcd *hcd = platform_get_drvdata(pdev);
- int unit;
-
- unit = (hcd->rsrc_start == AU1300_USB_OHCI1_PHYS_ADDR) ?
- ALCHEMY_USB_OHCI1 : ALCHEMY_USB_OHCI0;
- usb_remove_hcd(hcd);
- alchemy_usb_control(unit, 0);
- iounmap(hcd->regs);
- release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
- usb_put_hcd(hcd);
- platform_set_drvdata(pdev, NULL);
-
- return 0;
-}
-
-#ifdef CONFIG_PM
-static int ohci_hcd_au1xxx_drv_suspend(struct device *dev)
-{
- struct usb_hcd *hcd = dev_get_drvdata(dev);
- struct ohci_hcd *ohci = hcd_to_ohci(hcd);
- unsigned long flags;
- int rc;
-
- rc = 0;
-
- /* Root hub was already suspended. Disable irq emission and
- * mark HW unaccessible, bail out if RH has been resumed. Use
- * the spinlock to properly synchronize with possible pending
- * RH suspend or resume activity.
- */
- spin_lock_irqsave(&ohci->lock, flags);
- if (ohci->rh_state != OHCI_RH_SUSPENDED) {
- rc = -EINVAL;
- goto bail;
- }
- ohci_writel(ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable);
- (void)ohci_readl(ohci, &ohci->regs->intrdisable);
-
- clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
-
- alchemy_usb_control(ALCHEMY_USB_OHCI0, 0);
-bail:
- spin_unlock_irqrestore(&ohci->lock, flags);
-
- return rc;
-}
-
-static int ohci_hcd_au1xxx_drv_resume(struct device *dev)
-{
- struct usb_hcd *hcd = dev_get_drvdata(dev);
-
- alchemy_usb_control(ALCHEMY_USB_OHCI0, 1);
-
- set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
- ohci_finish_controller_resume(hcd);
-
- return 0;
-}
-
-static const struct dev_pm_ops au1xxx_ohci_pmops = {
- .suspend = ohci_hcd_au1xxx_drv_suspend,
- .resume = ohci_hcd_au1xxx_drv_resume,
-};
-
-#define AU1XXX_OHCI_PMOPS &au1xxx_ohci_pmops
-
-#else
-#define AU1XXX_OHCI_PMOPS NULL
-#endif
-
-static struct platform_driver ohci_hcd_au1xxx_driver = {
- .probe = ohci_hcd_au1xxx_drv_probe,
- .remove = ohci_hcd_au1xxx_drv_remove,
- .shutdown = usb_hcd_platform_shutdown,
- .driver = {
- .name = "au1xxx-ohci",
- .owner = THIS_MODULE,
- .pm = AU1XXX_OHCI_PMOPS,
- },
-};
-
-MODULE_ALIAS("platform:au1xxx-ohci");
diff --git a/drivers/usb/host/ohci-cns3xxx.c b/drivers/usb/host/ohci-cns3xxx.c
deleted file mode 100644
index 2c9f233047be..000000000000
--- a/drivers/usb/host/ohci-cns3xxx.c
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- * Copyright 2008 Cavium Networks
- *
- * This file is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License, Version 2, as
- * published by the Free Software Foundation.
- */
-
-#include <linux/platform_device.h>
-#include <linux/atomic.h>
-#include <mach/cns3xxx.h>
-#include <mach/pm.h>
-
-static int __devinit
-cns3xxx_ohci_start(struct usb_hcd *hcd)
-{
- struct ohci_hcd *ohci = hcd_to_ohci(hcd);
- int ret;
-
- /*
- * EHCI and OHCI share the same clock and power,
- * resetting twice would cause the 1st controller been reset.
- * Therefore only do power up at the first up device, and
- * power down at the last down device.
- *
- * Set USB AHB INCR length to 16
- */
- if (atomic_inc_return(&usb_pwr_ref) == 1) {
- cns3xxx_pwr_power_up(1 << PM_PLL_HM_PD_CTRL_REG_OFFSET_PLL_USB);
- cns3xxx_pwr_clk_en(1 << PM_CLK_GATE_REG_OFFSET_USB_HOST);
- cns3xxx_pwr_soft_rst(1 << PM_SOFT_RST_REG_OFFST_USB_HOST);
- __raw_writel((__raw_readl(MISC_CHIP_CONFIG_REG) | (0X2 << 24)),
- MISC_CHIP_CONFIG_REG);
- }
-
- ret = ohci_init(ohci);
- if (ret < 0)
- return ret;
-
- ohci->num_ports = 1;
-
- ret = ohci_run(ohci);
- if (ret < 0) {
- dev_err(hcd->self.controller, "can't start %s\n",
- hcd->self.bus_name);
- ohci_stop(hcd);
- return ret;
- }
- return 0;
-}
-
-static const struct hc_driver cns3xxx_ohci_hc_driver = {
- .description = hcd_name,
- .product_desc = "CNS3XXX OHCI Host controller",
- .hcd_priv_size = sizeof(struct ohci_hcd),
- .irq = ohci_irq,
- .flags = HCD_USB11 | HCD_MEMORY,
- .start = cns3xxx_ohci_start,
- .stop = ohci_stop,
- .shutdown = ohci_shutdown,
- .urb_enqueue = ohci_urb_enqueue,
- .urb_dequeue = ohci_urb_dequeue,
- .endpoint_disable = ohci_endpoint_disable,
- .get_frame_number = ohci_get_frame,
- .hub_status_data = ohci_hub_status_data,
- .hub_control = ohci_hub_control,
-#ifdef CONFIG_PM
- .bus_suspend = ohci_bus_suspend,
- .bus_resume = ohci_bus_resume,
-#endif
- .start_port_reset = ohci_start_port_reset,
-};
-
-static int cns3xxx_ohci_probe(struct platform_device *pdev)
-{
- struct device *dev = &pdev->dev;
- struct usb_hcd *hcd;
- const struct hc_driver *driver = &cns3xxx_ohci_hc_driver;
- struct resource *res;
- int irq;
- int retval;
-
- if (usb_disabled())
- return -ENODEV;
-
- res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
- if (!res) {
- dev_err(dev, "Found HC with no IRQ.\n");
- return -ENODEV;
- }
- irq = res->start;
-
- hcd = usb_create_hcd(driver, dev, dev_name(dev));
- if (!hcd)
- return -ENOMEM;
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res) {
- dev_err(dev, "Found HC with no register addr.\n");
- retval = -ENODEV;
- goto err1;
- }
- hcd->rsrc_start = res->start;
- hcd->rsrc_len = resource_size(res);
-
- if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len,
- driver->description)) {
- dev_dbg(dev, "controller already in use\n");
- retval = -EBUSY;
- goto err1;
- }
-
- hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
- if (!hcd->regs) {
- dev_dbg(dev, "error mapping memory\n");
- retval = -EFAULT;
- goto err2;
- }
-
- ohci_hcd_init(hcd_to_ohci(hcd));
-
- retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
- if (retval == 0)
- return retval;
-
- iounmap(hcd->regs);
-err2:
- release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
-err1:
- usb_put_hcd(hcd);
- return retval;
-}
-
-static int cns3xxx_ohci_remove(struct platform_device *pdev)
-{
- struct usb_hcd *hcd = platform_get_drvdata(pdev);
-
- usb_remove_hcd(hcd);
- iounmap(hcd->regs);
- release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
-
- /*
- * EHCI and OHCI share the same clock and power,
- * resetting twice would cause the 1st controller been reset.
- * Therefore only do power up at the first up device, and
- * power down at the last down device.
- */
- if (atomic_dec_return(&usb_pwr_ref) == 0)
- cns3xxx_pwr_clk_dis(1 << PM_CLK_GATE_REG_OFFSET_USB_HOST);
-
- usb_put_hcd(hcd);
-
- platform_set_drvdata(pdev, NULL);
-
- return 0;
-}
-
-MODULE_ALIAS("platform:cns3xxx-ohci");
-
-static struct platform_driver ohci_hcd_cns3xxx_driver = {
- .probe = cns3xxx_ohci_probe,
- .remove = cns3xxx_ohci_remove,
- .driver = {
- .name = "cns3xxx-ohci",
- },
-};
diff --git a/drivers/usb/host/ohci-ep93xx.c b/drivers/usb/host/ohci-ep93xx.c
index dbfbd1dfd2e2..8704e9fa5a80 100644
--- a/drivers/usb/host/ohci-ep93xx.c
+++ b/drivers/usb/host/ohci-ep93xx.c
@@ -107,7 +107,7 @@ static void usb_hcd_ep93xx_remove(struct usb_hcd *hcd,
usb_put_hcd(hcd);
}
-static int __devinit ohci_ep93xx_start(struct usb_hcd *hcd)
+static int ohci_ep93xx_start(struct usb_hcd *hcd)
{
struct ohci_hcd *ohci = hcd_to_ohci(hcd);
int ret;
@@ -194,7 +194,7 @@ static int ohci_hcd_ep93xx_drv_resume(struct platform_device *pdev)
ep93xx_start_hc(&pdev->dev);
- ohci_finish_controller_resume(hcd);
+ ohci_resume(hcd, false);
return 0;
}
#endif
diff --git a/drivers/usb/host/ohci-exynos.c b/drivers/usb/host/ohci-exynos.c
index 20a50081f922..aa3b8844bb9f 100644
--- a/drivers/usb/host/ohci-exynos.c
+++ b/drivers/usb/host/ohci-exynos.c
@@ -23,6 +23,11 @@ struct exynos_ohci_hcd {
struct clk *clk;
};
+static int ohci_exynos_reset(struct usb_hcd *hcd)
+{
+ return ohci_init(hcd_to_ohci(hcd));
+}
+
static int ohci_exynos_start(struct usb_hcd *hcd)
{
struct ohci_hcd *ohci = hcd_to_ohci(hcd);
@@ -30,10 +35,6 @@ static int ohci_exynos_start(struct usb_hcd *hcd)
ohci_dbg(ohci, "ohci_exynos_start, ohci:%p", ohci);
- ret = ohci_init(ohci);
- if (ret < 0)
- return ret;
-
ret = ohci_run(ohci);
if (ret < 0) {
dev_err(hcd->self.controller, "can't start %s\n",
@@ -53,6 +54,7 @@ static const struct hc_driver exynos_ohci_hc_driver = {
.irq = ohci_irq,
.flags = HCD_MEMORY|HCD_USB11,
+ .reset = ohci_exynos_reset,
.start = ohci_exynos_start,
.stop = ohci_stop,
.shutdown = ohci_shutdown,
@@ -74,7 +76,7 @@ static const struct hc_driver exynos_ohci_hc_driver = {
static u64 ohci_exynos_dma_mask = DMA_BIT_MASK(32);
-static int __devinit exynos_ohci_probe(struct platform_device *pdev)
+static int exynos_ohci_probe(struct platform_device *pdev)
{
struct exynos4_ohci_platdata *pdata;
struct exynos_ohci_hcd *exynos_ohci;
@@ -115,7 +117,7 @@ static int __devinit exynos_ohci_probe(struct platform_device *pdev)
}
exynos_ohci->hcd = hcd;
- exynos_ohci->clk = clk_get(&pdev->dev, "usbhost");
+ exynos_ohci->clk = devm_clk_get(&pdev->dev, "usbhost");
if (IS_ERR(exynos_ohci->clk)) {
dev_err(&pdev->dev, "Failed to get usbhost clock\n");
@@ -123,9 +125,9 @@ static int __devinit exynos_ohci_probe(struct platform_device *pdev)
goto fail_clk;
}
- err = clk_enable(exynos_ohci->clk);
+ err = clk_prepare_enable(exynos_ohci->clk);
if (err)
- goto fail_clken;
+ goto fail_clk;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
@@ -167,15 +169,13 @@ static int __devinit exynos_ohci_probe(struct platform_device *pdev)
return 0;
fail_io:
- clk_disable(exynos_ohci->clk);
-fail_clken:
- clk_put(exynos_ohci->clk);
+ clk_disable_unprepare(exynos_ohci->clk);
fail_clk:
usb_put_hcd(hcd);
return err;
}
-static int __devexit exynos_ohci_remove(struct platform_device *pdev)
+static int exynos_ohci_remove(struct platform_device *pdev)
{
struct exynos4_ohci_platdata *pdata = pdev->dev.platform_data;
struct exynos_ohci_hcd *exynos_ohci = platform_get_drvdata(pdev);
@@ -186,8 +186,7 @@ static int __devexit exynos_ohci_remove(struct platform_device *pdev)
if (pdata && pdata->phy_exit)
pdata->phy_exit(pdev, S5P_USB_PHY_HOST);
- clk_disable(exynos_ohci->clk);
- clk_put(exynos_ohci->clk);
+ clk_disable_unprepare(exynos_ohci->clk);
usb_put_hcd(hcd);
@@ -232,7 +231,7 @@ static int exynos_ohci_suspend(struct device *dev)
if (pdata && pdata->phy_exit)
pdata->phy_exit(pdev, S5P_USB_PHY_HOST);
- clk_disable(exynos_ohci->clk);
+ clk_disable_unprepare(exynos_ohci->clk);
fail:
spin_unlock_irqrestore(&ohci->lock, flags);
@@ -247,15 +246,12 @@ static int exynos_ohci_resume(struct device *dev)
struct platform_device *pdev = to_platform_device(dev);
struct exynos4_ohci_platdata *pdata = pdev->dev.platform_data;
- clk_enable(exynos_ohci->clk);
+ clk_prepare_enable(exynos_ohci->clk);
if (pdata && pdata->phy_init)
pdata->phy_init(pdev, S5P_USB_PHY_HOST);
- /* Mark hardware accessible again as we are out of D3 state by now */
- set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
-
- ohci_finish_controller_resume(hcd);
+ ohci_resume(hcd, false);
return 0;
}
@@ -279,7 +275,7 @@ MODULE_DEVICE_TABLE(of, exynos_ohci_match);
static struct platform_driver exynos_ohci_driver = {
.probe = exynos_ohci_probe,
- .remove = __devexit_p(exynos_ohci_remove),
+ .remove = exynos_ohci_remove,
.shutdown = exynos_ohci_shutdown,
.driver = {
.name = "exynos-ohci",
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index 4a1d64d92338..180a2b01db56 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -231,13 +231,41 @@ static int ohci_urb_enqueue (
frame &= ~(ed->interval - 1);
frame |= ed->branch;
urb->start_frame = frame;
+ }
+ } else if (ed->type == PIPE_ISOCHRONOUS) {
+ u16 next = ohci_frame_no(ohci) + 2;
+ u16 frame = ed->last_iso + ed->interval;
+
+ /* Behind the scheduling threshold? */
+ if (unlikely(tick_before(frame, next))) {
- /* yes, only URB_ISO_ASAP is supported, and
- * urb->start_frame is never used as input.
+ /* USB_ISO_ASAP: Round up to the first available slot */
+ if (urb->transfer_flags & URB_ISO_ASAP)
+ frame += (next - frame + ed->interval - 1) &
+ -ed->interval;
+
+ /*
+ * Not ASAP: Use the next slot in the stream. If
+ * the entire URB falls before the threshold, fail.
*/
+ else if (tick_before(frame + ed->interval *
+ (urb->number_of_packets - 1), next)) {
+ retval = -EXDEV;
+ usb_hcd_unlink_urb_from_ep(hcd, urb);
+ goto fail;
+ }
+
+ /*
+ * Some OHCI hardware doesn't handle late TDs
+ * correctly. After retiring them it proceeds to
+ * the next ED instead of the next TD. Therefore
+ * we have to omit the late TDs entirely.
+ */
+ urb_priv->td_cnt = DIV_ROUND_UP(next - frame,
+ ed->interval);
}
- } else if (ed->type == PIPE_ISOCHRONOUS)
- urb->start_frame = ed->last_iso + ed->interval;
+ urb->start_frame = frame;
+ }
/* fill the TDs and link them to the ed; and
* enable that part of the schedule, if needed
@@ -983,6 +1011,79 @@ static int ohci_restart (struct ohci_hcd *ohci)
#endif
+#ifdef CONFIG_PM
+
+static int __maybe_unused ohci_suspend(struct usb_hcd *hcd, bool do_wakeup)
+{
+ struct ohci_hcd *ohci = hcd_to_ohci (hcd);
+ unsigned long flags;
+
+ /* Disable irq emission and mark HW unaccessible. Use
+ * the spinlock to properly synchronize with possible pending
+ * RH suspend or resume activity.
+ */
+ spin_lock_irqsave (&ohci->lock, flags);
+ ohci_writel(ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable);
+ (void)ohci_readl(ohci, &ohci->regs->intrdisable);
+
+ clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+ spin_unlock_irqrestore (&ohci->lock, flags);
+
+ return 0;
+}
+
+
+static int __maybe_unused ohci_resume(struct usb_hcd *hcd, bool hibernated)
+{
+ struct ohci_hcd *ohci = hcd_to_ohci(hcd);
+ int port;
+ bool need_reinit = false;
+
+ set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+
+ /* Make sure resume from hibernation re-enumerates everything */
+ if (hibernated)
+ ohci_usb_reset(ohci);
+
+ /* See if the controller is already running or has been reset */
+ ohci->hc_control = ohci_readl(ohci, &ohci->regs->control);
+ if (ohci->hc_control & (OHCI_CTRL_IR | OHCI_SCHED_ENABLES)) {
+ need_reinit = true;
+ } else {
+ switch (ohci->hc_control & OHCI_CTRL_HCFS) {
+ case OHCI_USB_OPER:
+ case OHCI_USB_RESET:
+ need_reinit = true;
+ }
+ }
+
+ /* If needed, reinitialize and suspend the root hub */
+ if (need_reinit) {
+ spin_lock_irq(&ohci->lock);
+ ohci_rh_resume(ohci);
+ ohci_rh_suspend(ohci, 0);
+ spin_unlock_irq(&ohci->lock);
+ }
+
+ /* Normally just turn on port power and enable interrupts */
+ else {
+ ohci_dbg(ohci, "powerup ports\n");
+ for (port = 0; port < ohci->num_ports; port++)
+ ohci_writel(ohci, RH_PS_PPS,
+ &ohci->regs->roothub.portstatus[port]);
+
+ ohci_writel(ohci, OHCI_INTR_MIE, &ohci->regs->intrenable);
+ ohci_readl(ohci, &ohci->regs->intrenable);
+ msleep(20);
+ }
+
+ usb_hcd_resume_root_hub(hcd);
+
+ return 0;
+}
+
+#endif
+
/*-------------------------------------------------------------------------*/
MODULE_AUTHOR (DRIVER_AUTHOR);
@@ -1029,21 +1130,6 @@ MODULE_LICENSE ("GPL");
#define PLATFORM_DRIVER ohci_hcd_ep93xx_driver
#endif
-#ifdef CONFIG_MIPS_ALCHEMY
-#include "ohci-au1xxx.c"
-#define PLATFORM_DRIVER ohci_hcd_au1xxx_driver
-#endif
-
-#ifdef CONFIG_PNX8550
-#include "ohci-pnx8550.c"
-#define PLATFORM_DRIVER ohci_hcd_pnx8550_driver
-#endif
-
-#ifdef CONFIG_USB_OHCI_HCD_PPC_SOC
-#include "ohci-ppc-soc.c"
-#define PLATFORM_DRIVER ohci_hcd_ppc_soc_driver
-#endif
-
#ifdef CONFIG_ARCH_AT91
#include "ohci-at91.c"
#define PLATFORM_DRIVER ohci_hcd_at91_driver
@@ -1059,11 +1145,6 @@ MODULE_LICENSE ("GPL");
#define PLATFORM_DRIVER ohci_hcd_da8xx_driver
#endif
-#ifdef CONFIG_USB_OHCI_SH
-#include "ohci-sh.c"
-#define PLATFORM_DRIVER ohci_hcd_sh_driver
-#endif
-
#ifdef CONFIG_USB_OHCI_HCD_PPC_OF
#include "ohci-ppc-of.c"
@@ -1105,16 +1186,6 @@ MODULE_LICENSE ("GPL");
#define PLATFORM_DRIVER ohci_hcd_tilegx_driver
#endif
-#ifdef CONFIG_USB_CNS3XXX_OHCI
-#include "ohci-cns3xxx.c"
-#define PLATFORM_DRIVER ohci_hcd_cns3xxx_driver
-#endif
-
-#ifdef CONFIG_CPU_XLR
-#include "ohci-xls.c"
-#define PLATFORM_DRIVER ohci_xls_driver
-#endif
-
#ifdef CONFIG_USB_OHCI_HCD_PLATFORM
#include "ohci-platform.c"
#define PLATFORM_DRIVER ohci_platform_driver
diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
index 2f3619eefefa..db09dae7b557 100644
--- a/drivers/usb/host/ohci-hub.c
+++ b/drivers/usb/host/ohci-hub.c
@@ -316,48 +316,6 @@ static int ohci_bus_resume (struct usb_hcd *hcd)
return rc;
}
-/* Carry out the final steps of resuming the controller device */
-static void __maybe_unused ohci_finish_controller_resume(struct usb_hcd *hcd)
-{
- struct ohci_hcd *ohci = hcd_to_ohci(hcd);
- int port;
- bool need_reinit = false;
-
- /* See if the controller is already running or has been reset */
- ohci->hc_control = ohci_readl(ohci, &ohci->regs->control);
- if (ohci->hc_control & (OHCI_CTRL_IR | OHCI_SCHED_ENABLES)) {
- need_reinit = true;
- } else {
- switch (ohci->hc_control & OHCI_CTRL_HCFS) {
- case OHCI_USB_OPER:
- case OHCI_USB_RESET:
- need_reinit = true;
- }
- }
-
- /* If needed, reinitialize and suspend the root hub */
- if (need_reinit) {
- spin_lock_irq(&ohci->lock);
- ohci_rh_resume(ohci);
- ohci_rh_suspend(ohci, 0);
- spin_unlock_irq(&ohci->lock);
- }
-
- /* Normally just turn on port power and enable interrupts */
- else {
- ohci_dbg(ohci, "powerup ports\n");
- for (port = 0; port < ohci->num_ports; port++)
- ohci_writel(ohci, RH_PS_PPS,
- &ohci->regs->roothub.portstatus[port]);
-
- ohci_writel(ohci, OHCI_INTR_MIE, &ohci->regs->intrenable);
- ohci_readl(ohci, &ohci->regs->intrenable);
- msleep(20);
- }
-
- usb_hcd_resume_root_hub(hcd);
-}
-
/* Carry out polling-, autostop-, and autoresume-related state changes */
static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed,
int any_connected, int rhsc_status)
diff --git a/drivers/usb/host/ohci-jz4740.c b/drivers/usb/host/ohci-jz4740.c
index 931d588c3fb5..8062bb9dea16 100644
--- a/drivers/usb/host/ohci-jz4740.c
+++ b/drivers/usb/host/ohci-jz4740.c
@@ -145,7 +145,7 @@ static const struct hc_driver ohci_jz4740_hc_driver = {
};
-static __devinit int jz4740_ohci_probe(struct platform_device *pdev)
+static int jz4740_ohci_probe(struct platform_device *pdev)
{
int ret;
struct usb_hcd *hcd;
@@ -239,7 +239,7 @@ err_free:
return ret;
}
-static __devexit int jz4740_ohci_remove(struct platform_device *pdev)
+static int jz4740_ohci_remove(struct platform_device *pdev)
{
struct usb_hcd *hcd = platform_get_drvdata(pdev);
struct jz4740_ohci_hcd *jz4740_ohci = hcd_to_jz4740_hcd(hcd);
@@ -266,7 +266,7 @@ static __devexit int jz4740_ohci_remove(struct platform_device *pdev)
static struct platform_driver ohci_hcd_jz4740_driver = {
.probe = jz4740_ohci_probe,
- .remove = __devexit_p(jz4740_ohci_remove),
+ .remove = jz4740_ohci_remove,
.driver = {
.name = "jz4740-ohci",
.owner = THIS_MODULE,
diff --git a/drivers/usb/host/ohci-nxp.c b/drivers/usb/host/ohci-nxp.c
index e068f034cb9b..2344040c16d2 100644
--- a/drivers/usb/host/ohci-nxp.c
+++ b/drivers/usb/host/ohci-nxp.c
@@ -147,7 +147,7 @@ static void nxp_stop_hc(void)
__raw_writel(tmp, USB_OTG_STAT_CONTROL);
}
-static int __devinit ohci_nxp_start(struct usb_hcd *hcd)
+static int ohci_nxp_start(struct usb_hcd *hcd)
{
struct ohci_hcd *ohci = hcd_to_ohci(hcd);
int ret;
@@ -205,7 +205,7 @@ static const struct hc_driver ohci_nxp_hc_driver = {
.start_port_reset = ohci_start_port_reset,
};
-static int __devinit usb_hcd_nxp_probe(struct platform_device *pdev)
+static int usb_hcd_nxp_probe(struct platform_device *pdev)
{
struct usb_hcd *hcd = 0;
struct ohci_hcd *ohci;
diff --git a/drivers/usb/host/ohci-octeon.c b/drivers/usb/host/ohci-octeon.c
index d469bf9b9e54..d44430d009f8 100644
--- a/drivers/usb/host/ohci-octeon.c
+++ b/drivers/usb/host/ohci-octeon.c
@@ -42,7 +42,7 @@ static void ohci_octeon_hw_stop(void)
octeon2_usb_clocks_stop();
}
-static int __devinit ohci_octeon_start(struct usb_hcd *hcd)
+static int ohci_octeon_start(struct usb_hcd *hcd)
{
struct ohci_hcd *ohci = hcd_to_ohci(hcd);
int ret;
diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c
index 4531d03503c3..733c77c36355 100644
--- a/drivers/usb/host/ohci-omap.c
+++ b/drivers/usb/host/ohci-omap.c
@@ -530,7 +530,7 @@ static int ohci_omap_resume(struct platform_device *dev)
ohci->next_statechange = jiffies;
omap_ohci_clock_power(1);
- ohci_finish_controller_resume(hcd);
+ ohci_resume(hcd, false);
return 0;
}
diff --git a/drivers/usb/host/ohci-omap3.c b/drivers/usb/host/ohci-omap3.c
index 1b8133b6e451..4382af3a45f9 100644
--- a/drivers/usb/host/ohci-omap3.c
+++ b/drivers/usb/host/ohci-omap3.c
@@ -125,7 +125,7 @@ static const struct hc_driver ohci_omap3_hc_driver = {
* then invokes the start() method for the HCD associated with it
* through the hotplug entry's driver_data.
*/
-static int __devinit ohci_hcd_omap3_probe(struct platform_device *pdev)
+static int ohci_hcd_omap3_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct usb_hcd *hcd = NULL;
@@ -209,7 +209,7 @@ err_io:
* the HCD's stop() method. It is always called from a thread
* context, normally "rmmod", "apmd", or something similar.
*/
-static int __devexit ohci_hcd_omap3_remove(struct platform_device *pdev)
+static int ohci_hcd_omap3_remove(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct usb_hcd *hcd = dev_get_drvdata(dev);
@@ -232,7 +232,7 @@ static void ohci_hcd_omap3_shutdown(struct platform_device *pdev)
static struct platform_driver ohci_hcd_omap3_driver = {
.probe = ohci_hcd_omap3_probe,
- .remove = __devexit_p(ohci_hcd_omap3_remove),
+ .remove = ohci_hcd_omap3_remove,
.shutdown = ohci_hcd_omap3_shutdown,
.driver = {
.name = "ohci-omap3",
diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c
index 1843bb68ac7c..951514ef446d 100644
--- a/drivers/usb/host/ohci-pci.c
+++ b/drivers/usb/host/ohci-pci.c
@@ -270,7 +270,7 @@ static int ohci_pci_reset (struct usb_hcd *hcd)
}
-static int __devinit ohci_pci_start (struct usb_hcd *hcd)
+static int ohci_pci_start (struct usb_hcd *hcd)
{
struct ohci_hcd *ohci = hcd_to_ohci (hcd);
int ret;
@@ -296,49 +296,6 @@ static int __devinit ohci_pci_start (struct usb_hcd *hcd)
return ret;
}
-#ifdef CONFIG_PM
-
-static int ohci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup)
-{
- struct ohci_hcd *ohci = hcd_to_ohci (hcd);
- unsigned long flags;
- int rc = 0;
-
- /* Root hub was already suspended. Disable irq emission and
- * mark HW unaccessible, bail out if RH has been resumed. Use
- * the spinlock to properly synchronize with possible pending
- * RH suspend or resume activity.
- */
- spin_lock_irqsave (&ohci->lock, flags);
- if (ohci->rh_state != OHCI_RH_SUSPENDED) {
- rc = -EINVAL;
- goto bail;
- }
- ohci_writel(ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable);
- (void)ohci_readl(ohci, &ohci->regs->intrdisable);
-
- clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
- bail:
- spin_unlock_irqrestore (&ohci->lock, flags);
-
- return rc;
-}
-
-
-static int ohci_pci_resume(struct usb_hcd *hcd, bool hibernated)
-{
- set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
-
- /* Make sure resume from hibernation re-enumerates everything */
- if (hibernated)
- ohci_usb_reset(hcd_to_ohci(hcd));
-
- ohci_finish_controller_resume(hcd);
- return 0;
-}
-
-#endif /* CONFIG_PM */
-
/*-------------------------------------------------------------------------*/
@@ -362,8 +319,8 @@ static const struct hc_driver ohci_pci_hc_driver = {
.shutdown = ohci_shutdown,
#ifdef CONFIG_PM
- .pci_suspend = ohci_pci_suspend,
- .pci_resume = ohci_pci_resume,
+ .pci_suspend = ohci_suspend,
+ .pci_resume = ohci_resume,
#endif
/*
diff --git a/drivers/usb/host/ohci-platform.c b/drivers/usb/host/ohci-platform.c
index e24ec9f79164..084503b03fcf 100644
--- a/drivers/usb/host/ohci-platform.c
+++ b/drivers/usb/host/ohci-platform.c
@@ -31,6 +31,10 @@ static int ohci_platform_reset(struct usb_hcd *hcd)
ohci->flags |= OHCI_QUIRK_FRAME_NO;
ohci_hcd_init(ohci);
+
+ if (pdata->num_ports)
+ ohci->num_ports = pdata->num_ports;
+
err = ohci_init(ohci);
return err;
@@ -79,7 +83,7 @@ static const struct hc_driver ohci_platform_hc_driver = {
.start_port_reset = ohci_start_port_reset,
};
-static int __devinit ohci_platform_probe(struct platform_device *dev)
+static int ohci_platform_probe(struct platform_device *dev)
{
struct usb_hcd *hcd;
struct resource *res_mem;
@@ -97,13 +101,13 @@ static int __devinit ohci_platform_probe(struct platform_device *dev)
irq = platform_get_irq(dev, 0);
if (irq < 0) {
- pr_err("no irq provided");
+ dev_err(&dev->dev, "no irq provided");
return irq;
}
res_mem = platform_get_resource(dev, IORESOURCE_MEM, 0);
if (!res_mem) {
- pr_err("no memory recourse provided");
+ dev_err(&dev->dev, "no memory resource provided");
return -ENXIO;
}
@@ -123,29 +127,19 @@ static int __devinit ohci_platform_probe(struct platform_device *dev)
hcd->rsrc_start = res_mem->start;
hcd->rsrc_len = resource_size(res_mem);
- if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
- pr_err("controller already in use");
- err = -EBUSY;
- goto err_put_hcd;
- }
-
- hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len);
+ hcd->regs = devm_request_and_ioremap(&dev->dev, res_mem);
if (!hcd->regs) {
err = -ENOMEM;
- goto err_release_region;
+ goto err_put_hcd;
}
err = usb_add_hcd(hcd, irq, IRQF_SHARED);
if (err)
- goto err_iounmap;
+ goto err_put_hcd;
platform_set_drvdata(dev, hcd);
return err;
-err_iounmap:
- iounmap(hcd->regs);
-err_release_region:
- release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
err_put_hcd:
usb_put_hcd(hcd);
err_power:
@@ -155,14 +149,12 @@ err_power:
return err;
}
-static int __devexit ohci_platform_remove(struct platform_device *dev)
+static int ohci_platform_remove(struct platform_device *dev)
{
struct usb_hcd *hcd = platform_get_drvdata(dev);
struct usb_ohci_pdata *pdata = dev->dev.platform_data;
usb_remove_hcd(hcd);
- iounmap(hcd->regs);
- release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
usb_put_hcd(hcd);
platform_set_drvdata(dev, NULL);
@@ -199,7 +191,7 @@ static int ohci_platform_resume(struct device *dev)
return err;
}
- ohci_finish_controller_resume(hcd);
+ ohci_resume(hcd, false);
return 0;
}
@@ -222,7 +214,7 @@ static const struct dev_pm_ops ohci_platform_pm_ops = {
static struct platform_driver ohci_platform_driver = {
.id_table = ohci_platform_table,
.probe = ohci_platform_probe,
- .remove = __devexit_p(ohci_platform_remove),
+ .remove = ohci_platform_remove,
.shutdown = usb_hcd_platform_shutdown,
.driver = {
.owner = THIS_MODULE,
diff --git a/drivers/usb/host/ohci-pnx8550.c b/drivers/usb/host/ohci-pnx8550.c
deleted file mode 100644
index 148d27d6a67c..000000000000
--- a/drivers/usb/host/ohci-pnx8550.c
+++ /dev/null
@@ -1,243 +0,0 @@
-/*
- * OHCI HCD (Host Controller Driver) for USB.
- *
- * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
- * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
- * (C) Copyright 2002 Hewlett-Packard Company
- * (C) Copyright 2005 Embedded Alley Solutions, Inc.
- *
- * Bus Glue for PNX8550
- *
- * Written by Christopher Hoover <ch@hpl.hp.com>
- * Based on fragments of previous driver by Russell King et al.
- *
- * Modified for LH7A404 from ohci-sa1111.c
- * by Durgesh Pattamatta <pattamattad@sharpsec.com>
- *
- * Modified for PNX8550 from ohci-sa1111.c and sa-omap.c
- * by Vitaly Wool <vitalywool@gmail.com>
- *
- * This file is licenced under the GPL.
- */
-
-#include <linux/device.h>
-#include <linux/platform_device.h>
-#include <asm/mach-pnx8550/usb.h>
-#include <asm/mach-pnx8550/int.h>
-#include <asm/mach-pnx8550/pci.h>
-
-#ifndef CONFIG_PNX8550
-#error "This file is PNX8550 bus glue. CONFIG_PNX8550 must be defined."
-#endif
-
-extern int usb_disabled(void);
-
-/*-------------------------------------------------------------------------*/
-
-static void pnx8550_start_hc(struct platform_device *dev)
-{
- /*
- * Set register CLK48CTL to enable and 48MHz
- */
- outl(0x00000003, PCI_BASE | 0x0004770c);
-
- /*
- * Set register CLK12CTL to enable and 48MHz
- */
- outl(0x00000003, PCI_BASE | 0x00047710);
-
- udelay(100);
-}
-
-static void pnx8550_stop_hc(struct platform_device *dev)
-{
- udelay(10);
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-/* configure so an HC device and id are always provided */
-/* always called with process context; sleeping is OK */
-
-
-/**
- * usb_hcd_pnx8550_probe - initialize pnx8550-based HCDs
- * Context: !in_interrupt()
- *
- * Allocates basic resources for this USB host controller, and
- * then invokes the start() method for the HCD associated with it
- * through the hotplug entry's driver_data.
- *
- */
-int usb_hcd_pnx8550_probe (const struct hc_driver *driver,
- struct platform_device *dev)
-{
- int retval;
- struct usb_hcd *hcd;
-
- if (dev->resource[0].flags != IORESOURCE_MEM ||
- dev->resource[1].flags != IORESOURCE_IRQ) {
- dev_err (&dev->dev,"invalid resource type\n");
- return -ENOMEM;
- }
-
- hcd = usb_create_hcd (driver, &dev->dev, "pnx8550");
- if (!hcd)
- return -ENOMEM;
- hcd->rsrc_start = dev->resource[0].start;
- hcd->rsrc_len = dev->resource[0].end - dev->resource[0].start + 1;
-
- if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
- dev_err(&dev->dev, "request_mem_region [0x%08llx, 0x%08llx] "
- "failed\n", hcd->rsrc_start, hcd->rsrc_len);
- retval = -EBUSY;
- goto err1;
- }
-
- hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
- if (!hcd->regs) {
- dev_err(&dev->dev, "ioremap [[0x%08llx, 0x%08llx] failed\n",
- hcd->rsrc_start, hcd->rsrc_len);
- retval = -ENOMEM;
- goto err2;
- }
-
- pnx8550_start_hc(dev);
-
- ohci_hcd_init(hcd_to_ohci(hcd));
-
- retval = usb_add_hcd(hcd, dev->resource[1].start, 0);
- if (retval == 0)
- return retval;
-
- pnx8550_stop_hc(dev);
- iounmap(hcd->regs);
- err2:
- release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
- err1:
- usb_put_hcd(hcd);
- return retval;
-}
-
-
-/* may be called without controller electrically present */
-/* may be called with controller, bus, and devices active */
-
-/**
- * usb_hcd_pnx8550_remove - shutdown processing for pnx8550-based HCDs
- * @dev: USB Host Controller being removed
- * Context: !in_interrupt()
- *
- * Reverses the effect of usb_hcd_pnx8550_probe(), first invoking
- * the HCD's stop() method. It is always called from a thread
- * context, normally "rmmod", "apmd", or something similar.
- *
- */
-void usb_hcd_pnx8550_remove (struct usb_hcd *hcd, struct platform_device *dev)
-{
- usb_remove_hcd(hcd);
- pnx8550_stop_hc(dev);
- iounmap(hcd->regs);
- release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
- usb_put_hcd(hcd);
-}
-
-/*-------------------------------------------------------------------------*/
-
-static int __devinit
-ohci_pnx8550_start (struct usb_hcd *hcd)
-{
- struct ohci_hcd *ohci = hcd_to_ohci (hcd);
- int ret;
-
- ohci_dbg (ohci, "ohci_pnx8550_start, ohci:%p", ohci);
-
- if ((ret = ohci_init(ohci)) < 0)
- return ret;
-
- if ((ret = ohci_run (ohci)) < 0) {
- dev_err(hcd->self.controller, "can't start %s",
- hcd->self.bus_name);
- ohci_stop (hcd);
- return ret;
- }
-
- return 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static const struct hc_driver ohci_pnx8550_hc_driver = {
- .description = hcd_name,
- .product_desc = "PNX8550 OHCI",
- .hcd_priv_size = sizeof(struct ohci_hcd),
-
- /*
- * generic hardware linkage
- */
- .irq = ohci_irq,
- .flags = HCD_USB11 | HCD_MEMORY,
-
- /*
- * basic lifecycle operations
- */
- .start = ohci_pnx8550_start,
- .stop = ohci_stop,
-
- /*
- * managing i/o requests and associated device resources
- */
- .urb_enqueue = ohci_urb_enqueue,
- .urb_dequeue = ohci_urb_dequeue,
- .endpoint_disable = ohci_endpoint_disable,
-
- /*
- * scheduling support
- */
- .get_frame_number = ohci_get_frame,
-
- /*
- * root hub support
- */
- .hub_status_data = ohci_hub_status_data,
- .hub_control = ohci_hub_control,
-#ifdef CONFIG_PM
- .bus_suspend = ohci_bus_suspend,
- .bus_resume = ohci_bus_resume,
-#endif
- .start_port_reset = ohci_start_port_reset,
-};
-
-/*-------------------------------------------------------------------------*/
-
-static int ohci_hcd_pnx8550_drv_probe(struct platform_device *pdev)
-{
- int ret;
-
- if (usb_disabled())
- return -ENODEV;
-
- ret = usb_hcd_pnx8550_probe(&ohci_pnx8550_hc_driver, pdev);
- return ret;
-}
-
-static int ohci_hcd_pnx8550_drv_remove(struct platform_device *pdev)
-{
- struct usb_hcd *hcd = platform_get_drvdata(pdev);
-
- usb_hcd_pnx8550_remove(hcd, pdev);
- return 0;
-}
-
-MODULE_ALIAS("platform:pnx8550-ohci");
-
-static struct platform_driver ohci_hcd_pnx8550_driver = {
- .driver = {
- .name = "pnx8550-ohci",
- .owner = THIS_MODULE,
- },
- .probe = ohci_hcd_pnx8550_drv_probe,
- .remove = ohci_hcd_pnx8550_drv_remove,
-};
-
diff --git a/drivers/usb/host/ohci-ppc-of.c b/drivers/usb/host/ohci-ppc-of.c
index e27d5ae2b9eb..64c2ed9ff95e 100644
--- a/drivers/usb/host/ohci-ppc-of.c
+++ b/drivers/usb/host/ohci-ppc-of.c
@@ -19,7 +19,7 @@
#include <asm/prom.h>
-static int __devinit
+static int
ohci_ppc_of_start(struct usb_hcd *hcd)
{
struct ohci_hcd *ohci = hcd_to_ohci(hcd);
@@ -81,7 +81,7 @@ static const struct hc_driver ohci_ppc_of_hc_driver = {
};
-static int __devinit ohci_hcd_ppc_of_probe(struct platform_device *op)
+static int ohci_hcd_ppc_of_probe(struct platform_device *op)
{
struct device_node *dn = op->dev.of_node;
struct usb_hcd *hcd;
diff --git a/drivers/usb/host/ohci-ppc-soc.c b/drivers/usb/host/ohci-ppc-soc.c
deleted file mode 100644
index 185c39ed81b7..000000000000
--- a/drivers/usb/host/ohci-ppc-soc.c
+++ /dev/null
@@ -1,216 +0,0 @@
-/*
- * OHCI HCD (Host Controller Driver) for USB.
- *
- * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
- * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
- * (C) Copyright 2002 Hewlett-Packard Company
- * (C) Copyright 2003-2005 MontaVista Software Inc.
- *
- * Bus Glue for PPC On-Chip OHCI driver
- * Tested on Freescale MPC5200 and IBM STB04xxx
- *
- * Modified by Dale Farnsworth <dale@farnsworth.org> from ohci-sa1111.c
- *
- * This file is licenced under the GPL.
- */
-
-#include <linux/platform_device.h>
-#include <linux/signal.h>
-
-/* configure so an HC device and id are always provided */
-/* always called with process context; sleeping is OK */
-
-/**
- * usb_hcd_ppc_soc_probe - initialize On-Chip HCDs
- * Context: !in_interrupt()
- *
- * Allocates basic resources for this USB host controller.
- *
- * Store this function in the HCD's struct pci_driver as probe().
- */
-static int usb_hcd_ppc_soc_probe(const struct hc_driver *driver,
- struct platform_device *pdev)
-{
- int retval;
- struct usb_hcd *hcd;
- struct ohci_hcd *ohci;
- struct resource *res;
- int irq;
-
- pr_debug("initializing PPC-SOC USB Controller\n");
-
- res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
- if (!res) {
- pr_debug("%s: no irq\n", __FILE__);
- return -ENODEV;
- }
- irq = res->start;
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res) {
- pr_debug("%s: no reg addr\n", __FILE__);
- return -ENODEV;
- }
-
- hcd = usb_create_hcd(driver, &pdev->dev, "PPC-SOC USB");
- if (!hcd)
- return -ENOMEM;
- hcd->rsrc_start = res->start;
- hcd->rsrc_len = resource_size(res);
-
- if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
- pr_debug("%s: request_mem_region failed\n", __FILE__);
- retval = -EBUSY;
- goto err1;
- }
-
- hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
- if (!hcd->regs) {
- pr_debug("%s: ioremap failed\n", __FILE__);
- retval = -ENOMEM;
- goto err2;
- }
-
- ohci = hcd_to_ohci(hcd);
- ohci->flags |= OHCI_QUIRK_BE_MMIO | OHCI_QUIRK_BE_DESC;
-
-#ifdef CONFIG_PPC_MPC52xx
- /* MPC52xx doesn't need frame_no shift */
- ohci->flags |= OHCI_QUIRK_FRAME_NO;
-#endif
- ohci_hcd_init(ohci);
-
- retval = usb_add_hcd(hcd, irq, 0);
- if (retval == 0)
- return retval;
-
- pr_debug("Removing PPC-SOC USB Controller\n");
-
- iounmap(hcd->regs);
- err2:
- release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
- err1:
- usb_put_hcd(hcd);
- return retval;
-}
-
-
-/* may be called without controller electrically present */
-/* may be called with controller, bus, and devices active */
-
-/**
- * usb_hcd_ppc_soc_remove - shutdown processing for On-Chip HCDs
- * @pdev: USB Host Controller being removed
- * Context: !in_interrupt()
- *
- * Reverses the effect of usb_hcd_ppc_soc_probe().
- * It is always called from a thread
- * context, normally "rmmod", "apmd", or something similar.
- *
- */
-static void usb_hcd_ppc_soc_remove(struct usb_hcd *hcd,
- struct platform_device *pdev)
-{
- usb_remove_hcd(hcd);
-
- pr_debug("stopping PPC-SOC USB Controller\n");
-
- iounmap(hcd->regs);
- release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
- usb_put_hcd(hcd);
-}
-
-static int __devinit
-ohci_ppc_soc_start(struct usb_hcd *hcd)
-{
- struct ohci_hcd *ohci = hcd_to_ohci(hcd);
- int ret;
-
- if ((ret = ohci_init(ohci)) < 0)
- return ret;
-
- if ((ret = ohci_run(ohci)) < 0) {
- dev_err(hcd->self.controller, "can't start %s\n",
- hcd->self.bus_name);
- ohci_stop(hcd);
- return ret;
- }
-
- return 0;
-}
-
-static const struct hc_driver ohci_ppc_soc_hc_driver = {
- .description = hcd_name,
- .hcd_priv_size = sizeof(struct ohci_hcd),
-
- /*
- * generic hardware linkage
- */
- .irq = ohci_irq,
- .flags = HCD_USB11 | HCD_MEMORY,
-
- /*
- * basic lifecycle operations
- */
- .start = ohci_ppc_soc_start,
- .stop = ohci_stop,
- .shutdown = ohci_shutdown,
-
- /*
- * managing i/o requests and associated device resources
- */
- .urb_enqueue = ohci_urb_enqueue,
- .urb_dequeue = ohci_urb_dequeue,
- .endpoint_disable = ohci_endpoint_disable,
-
- /*
- * scheduling support
- */
- .get_frame_number = ohci_get_frame,
-
- /*
- * root hub support
- */
- .hub_status_data = ohci_hub_status_data,
- .hub_control = ohci_hub_control,
-#ifdef CONFIG_PM
- .bus_suspend = ohci_bus_suspend,
- .bus_resume = ohci_bus_resume,
-#endif
- .start_port_reset = ohci_start_port_reset,
-};
-
-static int ohci_hcd_ppc_soc_drv_probe(struct platform_device *pdev)
-{
- int ret;
-
- if (usb_disabled())
- return -ENODEV;
-
- ret = usb_hcd_ppc_soc_probe(&ohci_ppc_soc_hc_driver, pdev);
- return ret;
-}
-
-static int ohci_hcd_ppc_soc_drv_remove(struct platform_device *pdev)
-{
- struct usb_hcd *hcd = platform_get_drvdata(pdev);
-
- usb_hcd_ppc_soc_remove(hcd, pdev);
- return 0;
-}
-
-static struct platform_driver ohci_hcd_ppc_soc_driver = {
- .probe = ohci_hcd_ppc_soc_drv_probe,
- .remove = ohci_hcd_ppc_soc_drv_remove,
- .shutdown = usb_hcd_platform_shutdown,
-#ifdef CONFIG_PM
- /*.suspend = ohci_hcd_ppc_soc_drv_suspend,*/
- /*.resume = ohci_hcd_ppc_soc_drv_resume,*/
-#endif
- .driver = {
- .name = "ppc-soc-ohci",
- .owner = THIS_MODULE,
- },
-};
-
-MODULE_ALIAS("platform:ppc-soc-ohci");
diff --git a/drivers/usb/host/ohci-ps3.c b/drivers/usb/host/ohci-ps3.c
index 2ee1d8d713d2..7d35cd9e2862 100644
--- a/drivers/usb/host/ohci-ps3.c
+++ b/drivers/usb/host/ohci-ps3.c
@@ -30,7 +30,7 @@ static int ps3_ohci_hc_reset(struct usb_hcd *hcd)
return ohci_init(ohci);
}
-static int __devinit ps3_ohci_hc_start(struct usb_hcd *hcd)
+static int ps3_ohci_hc_start(struct usb_hcd *hcd)
{
int result;
struct ohci_hcd *ohci = hcd_to_ohci(hcd);
@@ -76,7 +76,7 @@ static const struct hc_driver ps3_ohci_hc_driver = {
#endif
};
-static int __devinit ps3_ohci_probe(struct ps3_system_bus_device *dev)
+static int ps3_ohci_probe(struct ps3_system_bus_device *dev)
{
int result;
struct usb_hcd *hcd;
diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c
index 2bf11440b010..efe71f3ca477 100644
--- a/drivers/usb/host/ohci-pxa27x.c
+++ b/drivers/usb/host/ohci-pxa27x.c
@@ -284,7 +284,7 @@ MODULE_DEVICE_TABLE(of, pxa_ohci_dt_ids);
static u64 pxa_ohci_dma_mask = DMA_BIT_MASK(32);
-static int __devinit ohci_pxa_of_init(struct platform_device *pdev)
+static int ohci_pxa_of_init(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
struct pxaohci_platform_data *pdata;
@@ -330,7 +330,7 @@ static int __devinit ohci_pxa_of_init(struct platform_device *pdev)
return 0;
}
#else
-static int __devinit ohci_pxa_of_init(struct platform_device *pdev)
+static int ohci_pxa_of_init(struct platform_device *pdev)
{
return 0;
}
@@ -471,7 +471,7 @@ void usb_hcd_pxa27x_remove (struct usb_hcd *hcd, struct platform_device *pdev)
/*-------------------------------------------------------------------------*/
-static int __devinit
+static int
ohci_pxa27x_start (struct usb_hcd *hcd)
{
struct ohci_hcd *ohci = hcd_to_ohci (hcd);
@@ -591,7 +591,7 @@ static int ohci_hcd_pxa27x_drv_resume(struct device *dev)
/* Select Power Management Mode */
pxa27x_ohci_select_pmm(ohci, inf->port_mode);
- ohci_finish_controller_resume(hcd);
+ ohci_resume(hcd, false);
return 0;
}
diff --git a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c
index c5a1ea9145fa..7482cfbe8c5e 100644
--- a/drivers/usb/host/ohci-q.c
+++ b/drivers/usb/host/ohci-q.c
@@ -596,7 +596,6 @@ static void td_submit_urb (
urb_priv->ed->hwHeadP &= ~cpu_to_hc32 (ohci, ED_C);
}
- urb_priv->td_cnt = 0;
list_add (&urb_priv->pending, &ohci->pending);
if (data_len)
@@ -672,7 +671,8 @@ static void td_submit_urb (
* we could often reduce the number of TDs here.
*/
case PIPE_ISOCHRONOUS:
- for (cnt = 0; cnt < urb->number_of_packets; cnt++) {
+ for (cnt = urb_priv->td_cnt; cnt < urb->number_of_packets;
+ cnt++) {
int frame = urb->start_frame;
// FIXME scheduling should handle frame counter
@@ -1128,6 +1128,25 @@ dl_done_list (struct ohci_hcd *ohci)
while (td) {
struct td *td_next = td->next_dl_td;
+ struct ed *ed = td->ed;
+
+ /*
+ * Some OHCI controllers (NVIDIA for sure, maybe others)
+ * occasionally forget to add TDs to the done queue. Since
+ * TDs for a given endpoint are always processed in order,
+ * if we find a TD on the donelist then all of its
+ * predecessors must be finished as well.
+ */
+ for (;;) {
+ struct td *td2;
+
+ td2 = list_first_entry(&ed->td_list, struct td,
+ td_list);
+ if (td2 == td)
+ break;
+ takeback_td(ohci, td2);
+ }
+
takeback_td(ohci, td);
td = td_next;
}
diff --git a/drivers/usb/host/ohci-s3c2410.c b/drivers/usb/host/ohci-s3c2410.c
index 0d2309ca471e..ad0f55269603 100644
--- a/drivers/usb/host/ohci-s3c2410.c
+++ b/drivers/usb/host/ohci-s3c2410.c
@@ -323,8 +323,6 @@ usb_hcd_s3c2410_remove(struct usb_hcd *hcd, struct platform_device *dev)
{
usb_remove_hcd(hcd);
s3c2410_stop_hc(dev);
- iounmap(hcd->regs);
- release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
usb_put_hcd(hcd);
}
@@ -353,35 +351,29 @@ static int usb_hcd_s3c2410_probe(const struct hc_driver *driver,
hcd->rsrc_start = dev->resource[0].start;
hcd->rsrc_len = resource_size(&dev->resource[0]);
- if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
- dev_err(&dev->dev, "request_mem_region failed\n");
- retval = -EBUSY;
+ hcd->regs = devm_request_and_ioremap(&dev->dev, &dev->resource[0]);
+ if (!hcd->regs) {
+ dev_err(&dev->dev, "devm_request_and_ioremap failed\n");
+ retval = -ENOMEM;
goto err_put;
}
- clk = clk_get(&dev->dev, "usb-host");
+ clk = devm_clk_get(&dev->dev, "usb-host");
if (IS_ERR(clk)) {
dev_err(&dev->dev, "cannot get usb-host clock\n");
retval = PTR_ERR(clk);
- goto err_mem;
+ goto err_put;
}
- usb_clk = clk_get(&dev->dev, "usb-bus-host");
+ usb_clk = devm_clk_get(&dev->dev, "usb-bus-host");
if (IS_ERR(usb_clk)) {
dev_err(&dev->dev, "cannot get usb-bus-host clock\n");
retval = PTR_ERR(usb_clk);
- goto err_clk;
+ goto err_put;
}
s3c2410_start_hc(dev, hcd);
- hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
- if (!hcd->regs) {
- dev_err(&dev->dev, "ioremap failed\n");
- retval = -ENOMEM;
- goto err_ioremap;
- }
-
ohci_hcd_init(hcd_to_ohci(hcd));
retval = usb_add_hcd(hcd, dev->resource[1].start, 0);
@@ -392,14 +384,6 @@ static int usb_hcd_s3c2410_probe(const struct hc_driver *driver,
err_ioremap:
s3c2410_stop_hc(dev);
- iounmap(hcd->regs);
- clk_put(usb_clk);
-
- err_clk:
- clk_put(clk);
-
- err_mem:
- release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
err_put:
usb_put_hcd(hcd);
@@ -474,12 +458,12 @@ static const struct hc_driver ohci_s3c2410_hc_driver = {
/* device driver */
-static int __devinit ohci_hcd_s3c2410_drv_probe(struct platform_device *pdev)
+static int ohci_hcd_s3c2410_drv_probe(struct platform_device *pdev)
{
return usb_hcd_s3c2410_probe(&ohci_s3c2410_hc_driver, pdev);
}
-static int __devexit ohci_hcd_s3c2410_drv_remove(struct platform_device *pdev)
+static int ohci_hcd_s3c2410_drv_remove(struct platform_device *pdev)
{
struct usb_hcd *hcd = platform_get_drvdata(pdev);
@@ -524,8 +508,7 @@ static int ohci_hcd_s3c2410_drv_resume(struct device *dev)
s3c2410_start_hc(pdev, hcd);
- set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
- ohci_finish_controller_resume(hcd);
+ ohci_resume(hcd, false);
return 0;
}
@@ -541,7 +524,7 @@ static const struct dev_pm_ops ohci_hcd_s3c2410_pm_ops = {
static struct platform_driver ohci_hcd_s3c2410_driver = {
.probe = ohci_hcd_s3c2410_drv_probe,
- .remove = __devexit_p(ohci_hcd_s3c2410_drv_remove),
+ .remove = ohci_hcd_s3c2410_drv_remove,
.shutdown = usb_hcd_platform_shutdown,
.driver = {
.owner = THIS_MODULE,
diff --git a/drivers/usb/host/ohci-sa1111.c b/drivers/usb/host/ohci-sa1111.c
index b6cc92520924..17b2a7dad77b 100644
--- a/drivers/usb/host/ohci-sa1111.c
+++ b/drivers/usb/host/ohci-sa1111.c
@@ -63,7 +63,7 @@ static int ohci_sa1111_reset(struct usb_hcd *hcd)
return ohci_init(ohci);
}
-static int __devinit ohci_sa1111_start(struct usb_hcd *hcd)
+static int ohci_sa1111_start(struct usb_hcd *hcd)
{
struct ohci_hcd *ohci = hcd_to_ohci(hcd);
int ret;
diff --git a/drivers/usb/host/ohci-sh.c b/drivers/usb/host/ohci-sh.c
deleted file mode 100644
index 76a20c278362..000000000000
--- a/drivers/usb/host/ohci-sh.c
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * OHCI HCD (Host Controller Driver) for USB.
- *
- * Copyright (C) 2008 Renesas Solutions Corp.
- *
- * Author : Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#include <linux/platform_device.h>
-
-static int ohci_sh_start(struct usb_hcd *hcd)
-{
- struct ohci_hcd *ohci = hcd_to_ohci(hcd);
-
- ohci_hcd_init(ohci);
- ohci_init(ohci);
- ohci_run(ohci);
- return 0;
-}
-
-static const struct hc_driver ohci_sh_hc_driver = {
- .description = hcd_name,
- .product_desc = "SuperH OHCI",
- .hcd_priv_size = sizeof(struct ohci_hcd),
-
- /*
- * generic hardware linkage
- */
- .irq = ohci_irq,
- .flags = HCD_USB11 | HCD_MEMORY,
-
- /*
- * basic lifecycle operations
- */
- .start = ohci_sh_start,
- .stop = ohci_stop,
- .shutdown = ohci_shutdown,
-
- /*
- * managing i/o requests and associated device resources
- */
- .urb_enqueue = ohci_urb_enqueue,
- .urb_dequeue = ohci_urb_dequeue,
- .endpoint_disable = ohci_endpoint_disable,
-
- /*
- * scheduling support
- */
- .get_frame_number = ohci_get_frame,
-
- /*
- * root hub support
- */
- .hub_status_data = ohci_hub_status_data,
- .hub_control = ohci_hub_control,
-#ifdef CONFIG_PM
- .bus_suspend = ohci_bus_suspend,
- .bus_resume = ohci_bus_resume,
-#endif
- .start_port_reset = ohci_start_port_reset,
-};
-
-/*-------------------------------------------------------------------------*/
-
-static int ohci_hcd_sh_probe(struct platform_device *pdev)
-{
- struct resource *res = NULL;
- struct usb_hcd *hcd = NULL;
- int irq = -1;
- int ret;
-
- if (usb_disabled())
- return -ENODEV;
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res) {
- dev_err(&pdev->dev, "platform_get_resource error.\n");
- return -ENODEV;
- }
-
- irq = platform_get_irq(pdev, 0);
- if (irq < 0) {
- dev_err(&pdev->dev, "platform_get_irq error.\n");
- return -ENODEV;
- }
-
- /* initialize hcd */
- hcd = usb_create_hcd(&ohci_sh_hc_driver, &pdev->dev, (char *)hcd_name);
- if (!hcd) {
- dev_err(&pdev->dev, "Failed to create hcd\n");
- return -ENOMEM;
- }
-
- hcd->regs = (void __iomem *)res->start;
- hcd->rsrc_start = res->start;
- hcd->rsrc_len = resource_size(res);
- ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
- if (ret != 0) {
- dev_err(&pdev->dev, "Failed to add hcd\n");
- usb_put_hcd(hcd);
- return ret;
- }
-
- return ret;
-}
-
-static int ohci_hcd_sh_remove(struct platform_device *pdev)
-{
- struct usb_hcd *hcd = platform_get_drvdata(pdev);
-
- usb_remove_hcd(hcd);
- usb_put_hcd(hcd);
-
- return 0;
-}
-
-static struct platform_driver ohci_hcd_sh_driver = {
- .probe = ohci_hcd_sh_probe,
- .remove = ohci_hcd_sh_remove,
- .shutdown = usb_hcd_platform_shutdown,
- .driver = {
- .name = "sh_ohci",
- .owner = THIS_MODULE,
- },
-};
-
-MODULE_ALIAS("platform:sh_ohci");
diff --git a/drivers/usb/host/ohci-sm501.c b/drivers/usb/host/ohci-sm501.c
index 5596ac2ba1ca..3b5b908fd47b 100644
--- a/drivers/usb/host/ohci-sm501.c
+++ b/drivers/usb/host/ohci-sm501.c
@@ -238,7 +238,7 @@ static int ohci_sm501_resume(struct platform_device *pdev)
ohci->next_statechange = jiffies;
sm501_unit_power(dev->parent, SM501_GATE_USB_HOST, 1);
- ohci_finish_controller_resume(hcd);
+ ohci_resume(hcd, false);
return 0;
}
#else
diff --git a/drivers/usb/host/ohci-spear.c b/drivers/usb/host/ohci-spear.c
index fc7305ee3c9c..9020bf0e2eca 100644
--- a/drivers/usb/host/ohci-spear.c
+++ b/drivers/usb/host/ohci-spear.c
@@ -33,7 +33,7 @@ static void spear_stop_ohci(struct spear_ohci *ohci)
clk_disable_unprepare(ohci->clk);
}
-static int __devinit ohci_spear_start(struct usb_hcd *hcd)
+static int ohci_spear_start(struct usb_hcd *hcd)
{
struct ohci_hcd *ohci = hcd_to_ohci(hcd);
int ret;
@@ -101,13 +101,11 @@ static int spear_ohci_hcd_drv_probe(struct platform_device *pdev)
struct spear_ohci *ohci_p;
struct resource *res;
int retval, irq;
- char clk_name[20] = "usbh_clk";
- static int instance = -1;
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
retval = irq;
- goto fail_irq_get;
+ goto fail;
}
/*
@@ -118,47 +116,39 @@ static int spear_ohci_hcd_drv_probe(struct platform_device *pdev)
if (!pdev->dev.dma_mask)
pdev->dev.dma_mask = &spear_ohci_dma_mask;
- /*
- * Increment the device instance, when probing via device-tree
- */
- if (pdev->id < 0)
- instance++;
- else
- instance = pdev->id;
- sprintf(clk_name, "usbh.%01d_clk", instance);
-
- usbh_clk = clk_get(NULL, clk_name);
+ usbh_clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(usbh_clk)) {
dev_err(&pdev->dev, "Error getting interface clock\n");
retval = PTR_ERR(usbh_clk);
- goto fail_get_usbh_clk;
+ goto fail;
}
hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev));
if (!hcd) {
retval = -ENOMEM;
- goto fail_create_hcd;
+ goto fail;
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
retval = -ENODEV;
- goto fail_request_resource;
+ goto err_put_hcd;
}
hcd->rsrc_start = pdev->resource[0].start;
hcd->rsrc_len = resource_size(res);
- if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
+ if (!devm_request_mem_region(&pdev->dev, hcd->rsrc_start, hcd->rsrc_len,
+ hcd_name)) {
dev_dbg(&pdev->dev, "request_mem_region failed\n");
retval = -EBUSY;
- goto fail_request_resource;
+ goto err_put_hcd;
}
- hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
+ hcd->regs = devm_ioremap(&pdev->dev, hcd->rsrc_start, hcd->rsrc_len);
if (!hcd->regs) {
dev_dbg(&pdev->dev, "ioremap failed\n");
retval = -ENOMEM;
- goto fail_ioremap;
+ goto err_put_hcd;
}
ohci_p = (struct spear_ohci *)hcd_to_ohci(hcd);
@@ -171,15 +161,9 @@ static int spear_ohci_hcd_drv_probe(struct platform_device *pdev)
return retval;
spear_stop_ohci(ohci_p);
- iounmap(hcd->regs);
-fail_ioremap:
- release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
-fail_request_resource:
+err_put_hcd:
usb_put_hcd(hcd);
-fail_create_hcd:
- clk_put(usbh_clk);
-fail_get_usbh_clk:
-fail_irq_get:
+fail:
dev_err(&pdev->dev, "init fail, %d\n", retval);
return retval;
@@ -194,12 +178,8 @@ static int spear_ohci_hcd_drv_remove(struct platform_device *pdev)
if (ohci_p->clk)
spear_stop_ohci(ohci_p);
- iounmap(hcd->regs);
- release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
usb_put_hcd(hcd);
- if (ohci_p->clk)
- clk_put(ohci_p->clk);
platform_set_drvdata(pdev, NULL);
return 0;
}
@@ -231,12 +211,12 @@ static int spear_ohci_hcd_drv_resume(struct platform_device *dev)
ohci->next_statechange = jiffies;
spear_start_ohci(ohci_p);
- ohci_finish_controller_resume(hcd);
+ ohci_resume(hcd, false);
return 0;
}
#endif
-static struct of_device_id spear_ohci_id_table[] __devinitdata = {
+static struct of_device_id spear_ohci_id_table[] = {
{ .compatible = "st,spear600-ohci", },
{ },
};
diff --git a/drivers/usb/host/ohci-tmio.c b/drivers/usb/host/ohci-tmio.c
index 60c2b0722f2e..d370245a4ee2 100644
--- a/drivers/usb/host/ohci-tmio.c
+++ b/drivers/usb/host/ohci-tmio.c
@@ -184,7 +184,7 @@ static const struct hc_driver ohci_tmio_hc_driver = {
/*-------------------------------------------------------------------------*/
static struct platform_driver ohci_hcd_tmio_driver;
-static int __devinit ohci_hcd_tmio_drv_probe(struct platform_device *dev)
+static int ohci_hcd_tmio_drv_probe(struct platform_device *dev)
{
const struct mfd_cell *cell = mfd_get_cell(dev);
struct resource *regs = platform_get_resource(dev, IORESOURCE_MEM, 0);
@@ -271,7 +271,7 @@ err_usb_create_hcd:
return ret;
}
-static int __devexit ohci_hcd_tmio_drv_remove(struct platform_device *dev)
+static int ohci_hcd_tmio_drv_remove(struct platform_device *dev)
{
struct usb_hcd *hcd = platform_get_drvdata(dev);
struct tmio_hcd *tmio = hcd_to_tmio(hcd);
@@ -352,7 +352,7 @@ static int ohci_hcd_tmio_drv_resume(struct platform_device *dev)
spin_unlock_irqrestore(&tmio->lock, flags);
- ohci_finish_controller_resume(hcd);
+ ohci_resume(hcd, false);
return 0;
}
@@ -363,7 +363,7 @@ static int ohci_hcd_tmio_drv_resume(struct platform_device *dev)
static struct platform_driver ohci_hcd_tmio_driver = {
.probe = ohci_hcd_tmio_drv_probe,
- .remove = __devexit_p(ohci_hcd_tmio_drv_remove),
+ .remove = ohci_hcd_tmio_drv_remove,
.shutdown = usb_hcd_platform_shutdown,
.suspend = ohci_hcd_tmio_drv_suspend,
.resume = ohci_hcd_tmio_drv_resume,
diff --git a/drivers/usb/host/ohci-xls.c b/drivers/usb/host/ohci-xls.c
deleted file mode 100644
index 84201cd1a472..000000000000
--- a/drivers/usb/host/ohci-xls.c
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * OHCI HCD for Netlogic XLS processors.
- *
- * (C) Copyright 2011 Netlogic Microsystems Inc.
- *
- * Based on ohci-au1xxx.c, and other Linux OHCI drivers.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file COPYING in the main directory of this archive for
- * more details.
- */
-
-#include <linux/platform_device.h>
-#include <linux/signal.h>
-
-static int ohci_xls_probe_internal(const struct hc_driver *driver,
- struct platform_device *dev)
-{
- struct resource *res;
- struct usb_hcd *hcd;
- int retval, irq;
-
- /* Get our IRQ from an earlier registered Platform Resource */
- irq = platform_get_irq(dev, 0);
- if (irq < 0) {
- dev_err(&dev->dev, "Found HC with no IRQ\n");
- return -ENODEV;
- }
-
- /* Get our Memory Handle */
- res = platform_get_resource(dev, IORESOURCE_MEM, 0);
- if (!res) {
- dev_err(&dev->dev, "MMIO Handle incorrect!\n");
- return -ENODEV;
- }
-
- hcd = usb_create_hcd(driver, &dev->dev, "XLS");
- if (!hcd) {
- retval = -ENOMEM;
- goto err1;
- }
- hcd->rsrc_start = res->start;
- hcd->rsrc_len = resource_size(res);
-
- if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len,
- driver->description)) {
- dev_dbg(&dev->dev, "Controller already in use\n");
- retval = -EBUSY;
- goto err2;
- }
-
- hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len);
- if (hcd->regs == NULL) {
- dev_dbg(&dev->dev, "error mapping memory\n");
- retval = -EFAULT;
- goto err3;
- }
-
- retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
- if (retval != 0)
- goto err4;
- return retval;
-
-err4:
- iounmap(hcd->regs);
-err3:
- release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
-err2:
- usb_put_hcd(hcd);
-err1:
- dev_err(&dev->dev, "init fail, %d\n", retval);
- return retval;
-}
-
-static int ohci_xls_reset(struct usb_hcd *hcd)
-{
- struct ohci_hcd *ohci = hcd_to_ohci(hcd);
-
- ohci_hcd_init(ohci);
- return ohci_init(ohci);
-}
-
-static int __devinit ohci_xls_start(struct usb_hcd *hcd)
-{
- struct ohci_hcd *ohci;
- int ret;
-
- ohci = hcd_to_ohci(hcd);
- ret = ohci_run(ohci);
- if (ret < 0) {
- dev_err(hcd->self.controller, "can't start %s\n",
- hcd->self.bus_name);
- ohci_stop(hcd);
- return ret;
- }
- return 0;
-}
-
-static struct hc_driver ohci_xls_hc_driver = {
- .description = hcd_name,
- .product_desc = "XLS OHCI Host Controller",
- .hcd_priv_size = sizeof(struct ohci_hcd),
- .irq = ohci_irq,
- .flags = HCD_MEMORY | HCD_USB11,
- .reset = ohci_xls_reset,
- .start = ohci_xls_start,
- .stop = ohci_stop,
- .shutdown = ohci_shutdown,
- .urb_enqueue = ohci_urb_enqueue,
- .urb_dequeue = ohci_urb_dequeue,
- .endpoint_disable = ohci_endpoint_disable,
- .get_frame_number = ohci_get_frame,
- .hub_status_data = ohci_hub_status_data,
- .hub_control = ohci_hub_control,
-#ifdef CONFIG_PM
- .bus_suspend = ohci_bus_suspend,
- .bus_resume = ohci_bus_resume,
-#endif
- .start_port_reset = ohci_start_port_reset,
-};
-
-static int ohci_xls_probe(struct platform_device *dev)
-{
- int ret;
-
- pr_debug("In ohci_xls_probe");
- if (usb_disabled())
- return -ENODEV;
- ret = ohci_xls_probe_internal(&ohci_xls_hc_driver, dev);
- return ret;
-}
-
-static int ohci_xls_remove(struct platform_device *dev)
-{
- struct usb_hcd *hcd = platform_get_drvdata(dev);
-
- usb_remove_hcd(hcd);
- iounmap(hcd->regs);
- release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
- usb_put_hcd(hcd);
- return 0;
-}
-
-static struct platform_driver ohci_xls_driver = {
- .probe = ohci_xls_probe,
- .remove = ohci_xls_remove,
- .shutdown = usb_hcd_platform_shutdown,
- .driver = {
- .name = "ohci-xls-0",
- .owner = THIS_MODULE,
- },
-};
diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c
index 39f9e4a9a2d3..a3b6d7104ae2 100644
--- a/drivers/usb/host/pci-quirks.c
+++ b/drivers/usb/host/pci-quirks.c
@@ -443,7 +443,7 @@ static inline int io_type_enabled(struct pci_dev *pdev, unsigned int mask)
#define pio_enabled(dev) io_type_enabled(dev, PCI_COMMAND_IO)
#define mmio_enabled(dev) io_type_enabled(dev, PCI_COMMAND_MEMORY)
-static void __devinit quirk_usb_handoff_uhci(struct pci_dev *pdev)
+static void quirk_usb_handoff_uhci(struct pci_dev *pdev)
{
unsigned long base = 0;
int i;
@@ -461,12 +461,12 @@ static void __devinit quirk_usb_handoff_uhci(struct pci_dev *pdev)
uhci_check_and_reset_hc(pdev, base);
}
-static int __devinit mmio_resource_enabled(struct pci_dev *pdev, int idx)
+static int mmio_resource_enabled(struct pci_dev *pdev, int idx)
{
return pci_resource_start(pdev, idx) && mmio_enabled(pdev);
}
-static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev)
+static void quirk_usb_handoff_ohci(struct pci_dev *pdev)
{
void __iomem *base;
u32 control;
@@ -533,7 +533,7 @@ static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev)
iounmap(base);
}
-static const struct dmi_system_id __devinitconst ehci_dmi_nohandoff_table[] = {
+static const struct dmi_system_id ehci_dmi_nohandoff_table[] = {
{
/* Pegatron Lucid (ExoPC) */
.matches = {
@@ -558,7 +558,7 @@ static const struct dmi_system_id __devinitconst ehci_dmi_nohandoff_table[] = {
{ }
};
-static void __devinit ehci_bios_handoff(struct pci_dev *pdev,
+static void ehci_bios_handoff(struct pci_dev *pdev,
void __iomem *op_reg_base,
u32 cap, u8 offset)
{
@@ -626,7 +626,7 @@ static void __devinit ehci_bios_handoff(struct pci_dev *pdev,
writel(0, op_reg_base + EHCI_CONFIGFLAG);
}
-static void __devinit quirk_usb_disable_ehci(struct pci_dev *pdev)
+static void quirk_usb_disable_ehci(struct pci_dev *pdev)
{
void __iomem *base, *op_reg_base;
u32 hcc_params, cap, val;
@@ -723,6 +723,7 @@ static int handshake(void __iomem *ptr, u32 mask, u32 done,
}
#define PCI_DEVICE_ID_INTEL_LYNX_POINT_XHCI 0x8C31
+#define PCI_DEVICE_ID_INTEL_LYNX_POINT_LP_XHCI 0x9C31
bool usb_is_intel_ppt_switchable_xhci(struct pci_dev *pdev)
{
@@ -736,7 +737,8 @@ bool usb_is_intel_lpt_switchable_xhci(struct pci_dev *pdev)
{
return pdev->class == PCI_CLASS_SERIAL_USB_XHCI &&
pdev->vendor == PCI_VENDOR_ID_INTEL &&
- pdev->device == PCI_DEVICE_ID_INTEL_LYNX_POINT_XHCI;
+ (pdev->device == PCI_DEVICE_ID_INTEL_LYNX_POINT_XHCI ||
+ pdev->device == PCI_DEVICE_ID_INTEL_LYNX_POINT_LP_XHCI);
}
bool usb_is_intel_switchable_xhci(struct pci_dev *pdev)
@@ -841,7 +843,7 @@ EXPORT_SYMBOL_GPL(usb_disable_xhci_ports);
* and then waits 5 seconds for the BIOS to hand over control.
* If we timeout, assume the BIOS is broken and take control anyway.
*/
-static void __devinit quirk_usb_handoff_xhci(struct pci_dev *pdev)
+static void quirk_usb_handoff_xhci(struct pci_dev *pdev)
{
void __iomem *base;
int ext_cap_offset;
@@ -941,7 +943,7 @@ hc_init:
iounmap(base);
}
-static void __devinit quirk_usb_early_handoff(struct pci_dev *pdev)
+static void quirk_usb_early_handoff(struct pci_dev *pdev)
{
/* Skip Netlogic mips SoC's internal PCI USB controller.
* This device does not need/support EHCI/OHCI handoff
diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c
index fcc09e5ec0ad..a6fd8f5371df 100644
--- a/drivers/usb/host/r8a66597-hcd.c
+++ b/drivers/usb/host/r8a66597-hcd.c
@@ -2036,10 +2036,8 @@ static void collect_usb_address_map(struct usb_device *udev, unsigned long *map)
udev->parent->descriptor.bDeviceClass == USB_CLASS_HUB)
map[udev->devnum/32] |= (1 << (udev->devnum % 32));
- usb_hub_for_each_child(udev, chix, childdev) {
- if (childdev)
- collect_usb_address_map(childdev, map);
- }
+ usb_hub_for_each_child(udev, chix, childdev)
+ collect_usb_address_map(childdev, map);
}
/* this function must be called with interrupt disabled */
@@ -2393,7 +2391,7 @@ static const struct dev_pm_ops r8a66597_dev_pm_ops = {
#define R8A66597_DEV_PM_OPS NULL
#endif
-static int __devexit r8a66597_remove(struct platform_device *pdev)
+static int r8a66597_remove(struct platform_device *pdev)
{
struct r8a66597 *r8a66597 = dev_get_drvdata(&pdev->dev);
struct usb_hcd *hcd = r8a66597_to_hcd(r8a66597);
@@ -2407,7 +2405,7 @@ static int __devexit r8a66597_remove(struct platform_device *pdev)
return 0;
}
-static int __devinit r8a66597_probe(struct platform_device *pdev)
+static int r8a66597_probe(struct platform_device *pdev)
{
char clk_name[8];
struct resource *res = NULL, *ires;
@@ -2534,7 +2532,7 @@ clean_up:
static struct platform_driver r8a66597_driver = {
.probe = r8a66597_probe,
- .remove = __devexit_p(r8a66597_remove),
+ .remove = r8a66597_remove,
.driver = {
.name = (char *) hcd_name,
.owner = THIS_MODULE,
diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c
index 619b05f42d4f..d62f0404baaa 100644
--- a/drivers/usb/host/sl811-hcd.c
+++ b/drivers/usb/host/sl811-hcd.c
@@ -1595,7 +1595,7 @@ static struct hc_driver sl811h_hc_driver = {
/*-------------------------------------------------------------------------*/
-static int __devexit
+static int
sl811h_remove(struct platform_device *dev)
{
struct usb_hcd *hcd = platform_get_drvdata(dev);
@@ -1618,7 +1618,7 @@ sl811h_remove(struct platform_device *dev)
return 0;
}
-static int __devinit
+static int
sl811h_probe(struct platform_device *dev)
{
struct usb_hcd *hcd;
@@ -1808,7 +1808,7 @@ sl811h_resume(struct platform_device *dev)
/* this driver is exported so sl811_cs can depend on it */
struct platform_driver sl811h_driver = {
.probe = sl811h_probe,
- .remove = __devexit_p(sl811h_remove),
+ .remove = sl811h_remove,
.suspend = sl811h_suspend,
.resume = sl811h_resume,
diff --git a/drivers/usb/host/ssb-hcd.c b/drivers/usb/host/ssb-hcd.c
index c2a29faba076..74af2c6287d2 100644
--- a/drivers/usb/host/ssb-hcd.c
+++ b/drivers/usb/host/ssb-hcd.c
@@ -39,7 +39,7 @@ struct ssb_hcd_device {
u32 enable_flags;
};
-static void __devinit ssb_hcd_5354wa(struct ssb_device *dev)
+static void ssb_hcd_5354wa(struct ssb_device *dev)
{
#ifdef CONFIG_SSB_DRIVER_MIPS
/* Work around for 5354 failures */
@@ -53,7 +53,7 @@ static void __devinit ssb_hcd_5354wa(struct ssb_device *dev)
#endif
}
-static void __devinit ssb_hcd_usb20wa(struct ssb_device *dev)
+static void ssb_hcd_usb20wa(struct ssb_device *dev)
{
if (dev->id.coreid == SSB_DEV_USB20_HOST) {
/*
@@ -80,7 +80,7 @@ static void __devinit ssb_hcd_usb20wa(struct ssb_device *dev)
}
/* based on arch/mips/brcm-boards/bcm947xx/pcibios.c */
-static u32 __devinit ssb_hcd_init_chip(struct ssb_device *dev)
+static u32 ssb_hcd_init_chip(struct ssb_device *dev)
{
u32 flags = 0;
@@ -101,8 +101,7 @@ static const struct usb_ehci_pdata ehci_pdata = {
static const struct usb_ohci_pdata ohci_pdata = {
};
-static struct platform_device * __devinit
-ssb_hcd_create_pdev(struct ssb_device *dev, bool ohci, u32 addr, u32 len)
+static struct platform_device *ssb_hcd_create_pdev(struct ssb_device *dev, bool ohci, u32 addr, u32 len)
{
struct platform_device *hci_dev;
struct resource hci_res[2];
@@ -148,7 +147,7 @@ err_alloc:
return ERR_PTR(ret);
}
-static int __devinit ssb_hcd_probe(struct ssb_device *dev,
+static int ssb_hcd_probe(struct ssb_device *dev,
const struct ssb_device_id *id)
{
int err, tmp;
@@ -207,7 +206,7 @@ err_free_usb_dev:
return err;
}
-static void __devexit ssb_hcd_remove(struct ssb_device *dev)
+static void ssb_hcd_remove(struct ssb_device *dev)
{
struct ssb_hcd_device *usb_dev = ssb_get_drvdata(dev);
struct platform_device *ohci_dev = usb_dev->ohci_dev;
@@ -221,7 +220,7 @@ static void __devexit ssb_hcd_remove(struct ssb_device *dev)
ssb_device_disable(dev, 0);
}
-static void __devexit ssb_hcd_shutdown(struct ssb_device *dev)
+static void ssb_hcd_shutdown(struct ssb_device *dev)
{
ssb_device_disable(dev, 0);
}
@@ -249,7 +248,7 @@ static int ssb_hcd_resume(struct ssb_device *dev)
#define ssb_hcd_resume NULL
#endif /* CONFIG_PM */
-static const struct ssb_device_id ssb_hcd_table[] __devinitconst = {
+static const struct ssb_device_id ssb_hcd_table[] = {
SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB11_HOSTDEV, SSB_ANY_REV),
SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB11_HOST, SSB_ANY_REV),
SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB20_HOST, SSB_ANY_REV),
@@ -261,7 +260,7 @@ static struct ssb_driver ssb_hcd_driver = {
.name = KBUILD_MODNAME,
.id_table = ssb_hcd_table,
.probe = ssb_hcd_probe,
- .remove = __devexit_p(ssb_hcd_remove),
+ .remove = ssb_hcd_remove,
.shutdown = ssb_hcd_shutdown,
.suspend = ssb_hcd_suspend,
.resume = ssb_hcd_resume,
diff --git a/drivers/usb/host/u132-hcd.c b/drivers/usb/host/u132-hcd.c
index dbbd1ba25224..5efdffe32365 100644
--- a/drivers/usb/host/u132-hcd.c
+++ b/drivers/usb/host/u132-hcd.c
@@ -2990,7 +2990,7 @@ static struct hc_driver u132_hc_driver = {
* synchronously - but instead should immediately stop activity to the
* device and asynchronously call usb_remove_hcd()
*/
-static int __devexit u132_remove(struct platform_device *pdev)
+static int u132_remove(struct platform_device *pdev)
{
struct usb_hcd *hcd = platform_get_drvdata(pdev);
if (hcd) {
@@ -3084,7 +3084,7 @@ static void u132_initialise(struct u132 *u132, struct platform_device *pdev)
mutex_unlock(&u132->sw_lock);
}
-static int __devinit u132_probe(struct platform_device *pdev)
+static int u132_probe(struct platform_device *pdev)
{
struct usb_hcd *hcd;
int retval;
@@ -3212,7 +3212,7 @@ static int u132_resume(struct platform_device *pdev)
*/
static struct platform_driver u132_platform_driver = {
.probe = u132_probe,
- .remove = __devexit_p(u132_remove),
+ .remove = u132_remove,
.suspend = u132_suspend,
.resume = u132_resume,
.driver = {
diff --git a/drivers/usb/host/uhci-grlib.c b/drivers/usb/host/uhci-grlib.c
index f7a62138e3e0..511bfc46dd78 100644
--- a/drivers/usb/host/uhci-grlib.c
+++ b/drivers/usb/host/uhci-grlib.c
@@ -85,7 +85,7 @@ static const struct hc_driver uhci_grlib_hc_driver = {
};
-static int __devinit uhci_hcd_grlib_probe(struct platform_device *op)
+static int uhci_hcd_grlib_probe(struct platform_device *op)
{
struct device_node *dn = op->dev.of_node;
struct usb_hcd *hcd;
diff --git a/drivers/usb/host/uhci-platform.c b/drivers/usb/host/uhci-platform.c
index 68ebf20e1519..8c4dace4b14a 100644
--- a/drivers/usb/host/uhci-platform.c
+++ b/drivers/usb/host/uhci-platform.c
@@ -62,7 +62,7 @@ static const struct hc_driver uhci_platform_hc_driver = {
static u64 platform_uhci_dma_mask = DMA_BIT_MASK(32);
-static int __devinit uhci_hcd_platform_probe(struct platform_device *pdev)
+static int uhci_hcd_platform_probe(struct platform_device *pdev)
{
struct usb_hcd *hcd;
struct uhci_hcd *uhci;
diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
index d2c6f5ac4626..15921fd55048 100644
--- a/drivers/usb/host/uhci-q.c
+++ b/drivers/usb/host/uhci-q.c
@@ -1256,7 +1256,8 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb,
struct uhci_qh *qh)
{
struct uhci_td *td = NULL; /* Since urb->number_of_packets > 0 */
- int i, frame;
+ int i;
+ unsigned frame, next;
unsigned long destination, status;
struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv;
@@ -1265,37 +1266,29 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb,
urb->number_of_packets >= UHCI_NUMFRAMES)
return -EFBIG;
+ uhci_get_current_frame_number(uhci);
+
/* Check the period and figure out the starting frame number */
if (!qh->bandwidth_reserved) {
qh->period = urb->interval;
- if (urb->transfer_flags & URB_ISO_ASAP) {
- qh->phase = -1; /* Find the best phase */
- i = uhci_check_bandwidth(uhci, qh);
- if (i)
- return i;
-
- /* Allow a little time to allocate the TDs */
- uhci_get_current_frame_number(uhci);
- frame = uhci->frame_number + 10;
-
- /* Move forward to the first frame having the
- * correct phase */
- urb->start_frame = frame + ((qh->phase - frame) &
- (qh->period - 1));
- } else {
- i = urb->start_frame - uhci->last_iso_frame;
- if (i <= 0 || i >= UHCI_NUMFRAMES)
- return -EINVAL;
- qh->phase = urb->start_frame & (qh->period - 1);
- i = uhci_check_bandwidth(uhci, qh);
- if (i)
- return i;
- }
+ qh->phase = -1; /* Find the best phase */
+ i = uhci_check_bandwidth(uhci, qh);
+ if (i)
+ return i;
+
+ /* Allow a little time to allocate the TDs */
+ next = uhci->frame_number + 10;
+ frame = qh->phase;
+
+ /* Round up to the first available slot */
+ frame += (next - frame + qh->period - 1) & -qh->period;
} else if (qh->period != urb->interval) {
return -EINVAL; /* Can't change the period */
} else {
+ next = uhci->frame_number + 2;
+
/* Find the next unused frame */
if (list_empty(&qh->queue)) {
frame = qh->iso_frame;
@@ -1308,25 +1301,31 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb,
lurb->number_of_packets *
lurb->interval;
}
- if (urb->transfer_flags & URB_ISO_ASAP) {
- /* Skip some frames if necessary to insure
- * the start frame is in the future.
+
+ /* Fell behind? */
+ if (uhci_frame_before_eq(frame, next)) {
+
+ /* USB_ISO_ASAP: Round up to the first available slot */
+ if (urb->transfer_flags & URB_ISO_ASAP)
+ frame += (next - frame + qh->period - 1) &
+ -qh->period;
+
+ /*
+ * Not ASAP: Use the next slot in the stream. If
+ * the entire URB falls before the threshold, fail.
*/
- uhci_get_current_frame_number(uhci);
- if (uhci_frame_before_eq(frame, uhci->frame_number)) {
- frame = uhci->frame_number + 1;
- frame += ((qh->phase - frame) &
- (qh->period - 1));
- }
- } /* Otherwise pick up where the last URB leaves off */
- urb->start_frame = frame;
+ else if (!uhci_frame_before_eq(next,
+ frame + (urb->number_of_packets - 1) *
+ qh->period))
+ return -EXDEV;
+ }
}
/* Make sure we won't have to go too far into the future */
if (uhci_frame_before_eq(uhci->last_iso_frame + UHCI_NUMFRAMES,
- urb->start_frame + urb->number_of_packets *
- urb->interval))
+ frame + urb->number_of_packets * urb->interval))
return -EFBIG;
+ urb->start_frame = frame;
status = TD_CTRL_ACTIVE | TD_CTRL_IOS;
destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid(urb->pipe);
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index 487bc083dead..fb51c7085ad0 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -205,7 +205,12 @@ static int xhci_alloc_segments_for_ring(struct xhci_hcd *xhci,
next = xhci_segment_alloc(xhci, cycle_state, flags);
if (!next) {
- xhci_free_segments_for_ring(xhci, *first);
+ prev = *first;
+ while (prev) {
+ next = prev->next;
+ xhci_segment_free(xhci, prev);
+ prev = next;
+ }
return -ENOMEM;
}
xhci_link_segments(xhci, prev, next, type);
@@ -258,7 +263,7 @@ static struct xhci_ring *xhci_ring_alloc(struct xhci_hcd *xhci,
return ring;
fail:
- xhci_ring_free(xhci, ring);
+ kfree(ring);
return NULL;
}
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index 8345d7c23061..af259e0ec172 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -29,6 +29,7 @@
/* Device for a quirk */
#define PCI_VENDOR_ID_FRESCO_LOGIC 0x1b73
#define PCI_DEVICE_ID_FRESCO_LOGIC_PDK 0x1000
+#define PCI_DEVICE_ID_FRESCO_LOGIC_FL1400 0x1400
#define PCI_VENDOR_ID_ETRON 0x1b6f
#define PCI_DEVICE_ID_ASROCK_P67 0x7023
@@ -58,8 +59,10 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
/* Look for vendor-specific quirks */
if (pdev->vendor == PCI_VENDOR_ID_FRESCO_LOGIC &&
- pdev->device == PCI_DEVICE_ID_FRESCO_LOGIC_PDK) {
- if (pdev->revision == 0x0) {
+ (pdev->device == PCI_DEVICE_ID_FRESCO_LOGIC_PDK ||
+ pdev->device == PCI_DEVICE_ID_FRESCO_LOGIC_FL1400)) {
+ if (pdev->device == PCI_DEVICE_ID_FRESCO_LOGIC_PDK &&
+ pdev->revision == 0x0) {
xhci->quirks |= XHCI_RESET_EP_QUIRK;
xhci_dbg(xhci, "QUIRK: Fresco Logic xHC needs configure"
" endpoint cmd after reset endpoint\n");
@@ -218,15 +221,8 @@ static void xhci_pci_remove(struct pci_dev *dev)
static int xhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup)
{
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
- int retval = 0;
- if (hcd->state != HC_STATE_SUSPENDED ||
- xhci->shared_hcd->state != HC_STATE_SUSPENDED)
- return -EINVAL;
-
- retval = xhci_suspend(xhci);
-
- return retval;
+ return xhci_suspend(xhci);
}
static int xhci_pci_resume(struct usb_hcd *hcd, bool hibernated)
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 4e1a8946b8d1..cbb44b7b9d65 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -318,7 +318,7 @@ static int xhci_abort_cmd_ring(struct xhci_hcd *xhci)
* seconds), then it should assume that the there are
* larger problems with the xHC and assert HCRST.
*/
- ret = handshake(xhci, &xhci->op_regs->cmd_ring,
+ ret = xhci_handshake(xhci, &xhci->op_regs->cmd_ring,
CMD_RING_RUNNING, 0, 5 * 1000 * 1000);
if (ret < 0) {
xhci_err(xhci, "Stopped the command ring failed, "
@@ -3071,11 +3071,11 @@ static u32 xhci_td_remainder(unsigned int remainder)
}
/*
- * For xHCI 1.0 host controllers, TD size is the number of packets remaining in
- * the TD (*not* including this TRB).
+ * For xHCI 1.0 host controllers, TD size is the number of max packet sized
+ * packets remaining in the TD (*not* including this TRB).
*
* Total TD packet count = total_packet_count =
- * roundup(TD size in bytes / wMaxPacketSize)
+ * DIV_ROUND_UP(TD size in bytes / wMaxPacketSize)
*
* Packets transferred up to and including this TRB = packets_transferred =
* rounddown(total bytes transferred including this TRB / wMaxPacketSize)
@@ -3083,15 +3083,16 @@ static u32 xhci_td_remainder(unsigned int remainder)
* TD size = total_packet_count - packets_transferred
*
* It must fit in bits 21:17, so it can't be bigger than 31.
+ * The last TRB in a TD must have the TD size set to zero.
*/
-
static u32 xhci_v1_0_td_remainder(int running_total, int trb_buff_len,
- unsigned int total_packet_count, struct urb *urb)
+ unsigned int total_packet_count, struct urb *urb,
+ unsigned int num_trbs_left)
{
int packets_transferred;
/* One TRB with a zero-length data packet. */
- if (running_total == 0 && trb_buff_len == 0)
+ if (num_trbs_left == 0 || (running_total == 0 && trb_buff_len == 0))
return 0;
/* All the TRB queueing functions don't count the current TRB in
@@ -3100,7 +3101,9 @@ static u32 xhci_v1_0_td_remainder(int running_total, int trb_buff_len,
packets_transferred = (running_total + trb_buff_len) /
usb_endpoint_maxp(&urb->ep->desc);
- return xhci_td_remainder(total_packet_count - packets_transferred);
+ if ((total_packet_count - packets_transferred) > 31)
+ return 31 << 17;
+ return (total_packet_count - packets_transferred) << 17;
}
static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
@@ -3127,7 +3130,7 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
num_trbs = count_sg_trbs_needed(xhci, urb);
num_sgs = urb->num_mapped_sgs;
- total_packet_count = roundup(urb->transfer_buffer_length,
+ total_packet_count = DIV_ROUND_UP(urb->transfer_buffer_length,
usb_endpoint_maxp(&urb->ep->desc));
trb_buff_len = prepare_transfer(xhci, xhci->devs[slot_id],
@@ -3210,7 +3213,8 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
running_total);
} else {
remainder = xhci_v1_0_td_remainder(running_total,
- trb_buff_len, total_packet_count, urb);
+ trb_buff_len, total_packet_count, urb,
+ num_trbs - 1);
}
length_field = TRB_LEN(trb_buff_len) |
remainder |
@@ -3318,7 +3322,7 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
start_cycle = ep_ring->cycle_state;
running_total = 0;
- total_packet_count = roundup(urb->transfer_buffer_length,
+ total_packet_count = DIV_ROUND_UP(urb->transfer_buffer_length,
usb_endpoint_maxp(&urb->ep->desc));
/* How much data is in the first TRB? */
addr = (u64) urb->transfer_dma;
@@ -3364,7 +3368,8 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
running_total);
} else {
remainder = xhci_v1_0_td_remainder(running_total,
- trb_buff_len, total_packet_count, urb);
+ trb_buff_len, total_packet_count, urb,
+ num_trbs - 1);
}
length_field = TRB_LEN(trb_buff_len) |
remainder |
@@ -3627,7 +3632,7 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
addr = start_addr + urb->iso_frame_desc[i].offset;
td_len = urb->iso_frame_desc[i].length;
td_remain_len = td_len;
- total_packet_count = roundup(td_len,
+ total_packet_count = DIV_ROUND_UP(td_len,
usb_endpoint_maxp(&urb->ep->desc));
/* A zero-length transfer still involves at least one packet. */
if (total_packet_count == 0)
@@ -3706,7 +3711,8 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
} else {
remainder = xhci_v1_0_td_remainder(
running_total, trb_buff_len,
- total_packet_count, urb);
+ total_packet_count, urb,
+ (trbs_per_td - j - 1));
}
length_field = TRB_LEN(trb_buff_len) |
remainder |
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index c9e419f29b74..5c72c431bab1 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -40,7 +40,7 @@ MODULE_PARM_DESC(link_quirk, "Don't clear the chain bit on a link TRB");
/* TODO: copied from ehci-hcd.c - can this be refactored? */
/*
- * handshake - spin reading hc until handshake completes or fails
+ * xhci_handshake - spin reading hc until handshake completes or fails
* @ptr: address of hc register to be read
* @mask: bits to look at in result of read
* @done: value of those bits when handshake succeeds
@@ -52,7 +52,7 @@ MODULE_PARM_DESC(link_quirk, "Don't clear the chain bit on a link TRB");
* handshake done). There are two failure modes: "usec" have passed (major
* hardware flakeout), or the register reads as all-ones (hardware removed).
*/
-int handshake(struct xhci_hcd *xhci, void __iomem *ptr,
+int xhci_handshake(struct xhci_hcd *xhci, void __iomem *ptr,
u32 mask, u32 done, int usec)
{
u32 result;
@@ -103,7 +103,7 @@ int xhci_halt(struct xhci_hcd *xhci)
xhci_dbg(xhci, "// Halt the HC\n");
xhci_quiesce(xhci);
- ret = handshake(xhci, &xhci->op_regs->status,
+ ret = xhci_handshake(xhci, &xhci->op_regs->status,
STS_HALT, STS_HALT, XHCI_MAX_HALT_USEC);
if (!ret) {
xhci->xhc_state |= XHCI_STATE_HALTED;
@@ -132,7 +132,7 @@ static int xhci_start(struct xhci_hcd *xhci)
* Wait for the HCHalted Status bit to be 0 to indicate the host is
* running.
*/
- ret = handshake(xhci, &xhci->op_regs->status,
+ ret = xhci_handshake(xhci, &xhci->op_regs->status,
STS_HALT, 0, XHCI_MAX_HALT_USEC);
if (ret == -ETIMEDOUT)
xhci_err(xhci, "Host took too long to start, "
@@ -167,7 +167,7 @@ int xhci_reset(struct xhci_hcd *xhci)
command |= CMD_RESET;
xhci_writel(xhci, command, &xhci->op_regs->command);
- ret = handshake(xhci, &xhci->op_regs->command,
+ ret = xhci_handshake(xhci, &xhci->op_regs->command,
CMD_RESET, 0, 10 * 1000 * 1000);
if (ret)
return ret;
@@ -177,7 +177,7 @@ int xhci_reset(struct xhci_hcd *xhci)
* xHCI cannot write to any doorbells or operational registers other
* than status until the "Controller Not Ready" flag is cleared.
*/
- ret = handshake(xhci, &xhci->op_regs->status,
+ ret = xhci_handshake(xhci, &xhci->op_regs->status,
STS_CNR, 0, 10 * 1000 * 1000);
for (i = 0; i < 2; ++i) {
@@ -480,7 +480,7 @@ static bool compliance_mode_recovery_timer_quirk_check(void)
if (strstr(dmi_product_name, "Z420") ||
strstr(dmi_product_name, "Z620") ||
strstr(dmi_product_name, "Z820") ||
- strstr(dmi_product_name, "Z1"))
+ strstr(dmi_product_name, "Z1 Workstation"))
return true;
return false;
@@ -880,6 +880,10 @@ int xhci_suspend(struct xhci_hcd *xhci)
struct usb_hcd *hcd = xhci_to_hcd(xhci);
u32 command;
+ if (hcd->state != HC_STATE_SUSPENDED ||
+ xhci->shared_hcd->state != HC_STATE_SUSPENDED)
+ return -EINVAL;
+
spin_lock_irq(&xhci->lock);
clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
clear_bit(HCD_FLAG_HW_ACCESSIBLE, &xhci->shared_hcd->flags);
@@ -890,7 +894,7 @@ int xhci_suspend(struct xhci_hcd *xhci)
command = xhci_readl(xhci, &xhci->op_regs->command);
command &= ~CMD_RUN;
xhci_writel(xhci, command, &xhci->op_regs->command);
- if (handshake(xhci, &xhci->op_regs->status,
+ if (xhci_handshake(xhci, &xhci->op_regs->status,
STS_HALT, STS_HALT, XHCI_MAX_HALT_USEC)) {
xhci_warn(xhci, "WARN: xHC CMD_RUN timeout\n");
spin_unlock_irq(&xhci->lock);
@@ -905,7 +909,8 @@ int xhci_suspend(struct xhci_hcd *xhci)
command = xhci_readl(xhci, &xhci->op_regs->command);
command |= CMD_CSS;
xhci_writel(xhci, command, &xhci->op_regs->command);
- if (handshake(xhci, &xhci->op_regs->status, STS_SAVE, 0, 10 * 1000)) {
+ if (xhci_handshake(xhci, &xhci->op_regs->status,
+ STS_SAVE, 0, 10 * 1000)) {
xhci_warn(xhci, "WARN: xHC save state timeout\n");
spin_unlock_irq(&xhci->lock);
return -ETIMEDOUT;
@@ -967,7 +972,7 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
command = xhci_readl(xhci, &xhci->op_regs->command);
command |= CMD_CRS;
xhci_writel(xhci, command, &xhci->op_regs->command);
- if (handshake(xhci, &xhci->op_regs->status,
+ if (xhci_handshake(xhci, &xhci->op_regs->status,
STS_RESTORE, 0, 10 * 1000)) {
xhci_warn(xhci, "WARN: xHC restore state timeout\n");
spin_unlock_irq(&xhci->lock);
@@ -1035,7 +1040,7 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
command = xhci_readl(xhci, &xhci->op_regs->command);
command |= CMD_RUN;
xhci_writel(xhci, command, &xhci->op_regs->command);
- handshake(xhci, &xhci->op_regs->status, STS_HALT,
+ xhci_handshake(xhci, &xhci->op_regs->status, STS_HALT,
0, 250 * 1000);
/* step 5: walk topology and initialize portsc,
@@ -2254,7 +2259,7 @@ static bool xhci_is_async_ep(unsigned int ep_type)
static bool xhci_is_sync_in_ep(unsigned int ep_type)
{
- return (ep_type == ISOC_IN_EP || ep_type != INT_IN_EP);
+ return (ep_type == ISOC_IN_EP || ep_type == INT_IN_EP);
}
static unsigned int xhci_get_ss_bw_consumed(struct xhci_bw_info *ep_bw)
@@ -3874,7 +3879,8 @@ static int xhci_usb2_software_lpm_test(struct usb_hcd *hcd,
spin_lock_irqsave(&xhci->lock, flags);
/* Check L1 Status */
- ret = handshake(xhci, pm_addr, PORT_L1S_MASK, PORT_L1S_SUCCESS, 125);
+ ret = xhci_handshake(xhci, pm_addr,
+ PORT_L1S_MASK, PORT_L1S_SUCCESS, 125);
if (ret != -ETIMEDOUT) {
/* enter L1 successfully */
temp = xhci_readl(xhci, addr);
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 53df4e70ca07..f791bd0aee6c 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -1720,7 +1720,7 @@ static inline void xhci_unregister_plat(void)
/* xHCI host controller glue */
typedef void (*xhci_get_quirks_t)(struct device *, struct xhci_hcd *);
-int handshake(struct xhci_hcd *xhci, void __iomem *ptr,
+int xhci_handshake(struct xhci_hcd *xhci, void __iomem *ptr,
u32 mask, u32 done, int usec);
void xhci_quiesce(struct xhci_hcd *xhci);
int xhci_halt(struct xhci_hcd *xhci);
diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig
index a8f05239350e..fecde69bfa7d 100644
--- a/drivers/usb/misc/Kconfig
+++ b/drivers/usb/misc/Kconfig
@@ -246,6 +246,7 @@ 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/ezusb.c b/drivers/usb/misc/ezusb.c
index 6589268a6515..e712afed947c 100644
--- a/drivers/usb/misc/ezusb.c
+++ b/drivers/usb/misc/ezusb.c
@@ -15,6 +15,7 @@
#include <linux/usb.h>
#include <linux/firmware.h>
#include <linux/ihex.h>
+#include <linux/usb/ezusb.h>
struct ezusb_fx_type {
/* EZ-USB Control and Status Register. Bit 0 controls 8051 reset */
@@ -22,21 +23,16 @@ struct ezusb_fx_type {
unsigned short max_internal_adress;
};
-struct ezusb_fx_type ezusb_fx1 = {
+static struct ezusb_fx_type ezusb_fx1 = {
.cpucs_reg = 0x7F92,
.max_internal_adress = 0x1B3F,
};
-struct ezusb_fx_type ezusb_fx2 = {
- .cpucs_reg = 0xE600,
- .max_internal_adress = 0x3FFF,
-};
-
/* Commands for writing to memory */
#define WRITE_INT_RAM 0xA0
#define WRITE_EXT_RAM 0xA3
-int ezusb_writememory(struct usb_device *dev, int address,
+static int ezusb_writememory(struct usb_device *dev, int address,
unsigned char *data, int length, __u8 request)
{
int result;
@@ -58,10 +54,9 @@ int ezusb_writememory(struct usb_device *dev, int address,
kfree(transfer_buffer);
return result;
}
-EXPORT_SYMBOL_GPL(ezusb_writememory);
-int ezusb_set_reset(struct usb_device *dev, unsigned short cpucs_reg,
- unsigned char reset_bit)
+static int ezusb_set_reset(struct usb_device *dev, unsigned short cpucs_reg,
+ unsigned char reset_bit)
{
int response = ezusb_writememory(dev, cpucs_reg, &reset_bit, 1, WRITE_INT_RAM);
if (response < 0)
@@ -76,12 +71,6 @@ int ezusb_fx1_set_reset(struct usb_device *dev, unsigned char reset_bit)
}
EXPORT_SYMBOL_GPL(ezusb_fx1_set_reset);
-int ezusb_fx2_set_reset(struct usb_device *dev, unsigned char reset_bit)
-{
- return ezusb_set_reset(dev, ezusb_fx2.cpucs_reg, reset_bit);
-}
-EXPORT_SYMBOL_GPL(ezusb_fx2_set_reset);
-
static int ezusb_ihex_firmware_download(struct usb_device *dev,
struct ezusb_fx_type fx,
const char *firmware_path)
@@ -151,11 +140,28 @@ int ezusb_fx1_ihex_firmware_download(struct usb_device *dev,
}
EXPORT_SYMBOL_GPL(ezusb_fx1_ihex_firmware_download);
+#if 0
+/*
+ * Once someone one needs these fx2 functions, uncomment them
+ * and add them to ezusb.h and all should be good.
+ */
+static struct ezusb_fx_type ezusb_fx2 = {
+ .cpucs_reg = 0xE600,
+ .max_internal_adress = 0x3FFF,
+};
+
+int ezusb_fx2_set_reset(struct usb_device *dev, unsigned char reset_bit)
+{
+ return ezusb_set_reset(dev, ezusb_fx2.cpucs_reg, reset_bit);
+}
+EXPORT_SYMBOL_GPL(ezusb_fx2_set_reset);
+
int ezusb_fx2_ihex_firmware_download(struct usb_device *dev,
const char *firmware_path)
{
return ezusb_ihex_firmware_download(dev, ezusb_fx2, firmware_path);
}
EXPORT_SYMBOL_GPL(ezusb_fx2_ihex_firmware_download);
+#endif
MODULE_LICENSE("GPL");
diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c
index 055b84adedac..7667b12f2ff5 100644
--- a/drivers/usb/misc/usbtest.c
+++ b/drivers/usb/misc/usbtest.c
@@ -423,6 +423,9 @@ alloc_sglist(int nents, int max, int vary)
unsigned i;
unsigned size = max;
+ if (max == 0)
+ return NULL;
+
sg = kmalloc_array(nents, sizeof *sg, GFP_KERNEL);
if (!sg)
return NULL;
@@ -2386,6 +2389,7 @@ static struct usbtest_info gz_info = {
.name = "Linux gadget zero",
.autoconf = 1,
.ctrl_out = 1,
+ .iso = 1,
.alt = 0,
};
diff --git a/drivers/usb/musb/am35x.c b/drivers/usb/musb/am35x.c
index c964d6af178b..3d1c71b50f76 100644
--- a/drivers/usb/musb/am35x.c
+++ b/drivers/usb/musb/am35x.c
@@ -455,7 +455,7 @@ static const struct musb_platform_ops am35x_ops = {
static u64 am35x_dmamask = DMA_BIT_MASK(32);
-static int __devinit am35x_probe(struct platform_device *pdev)
+static int am35x_probe(struct platform_device *pdev)
{
struct musb_hdrc_platform_data *pdata = pdev->dev.platform_data;
struct platform_device *musb;
@@ -465,7 +465,6 @@ static int __devinit am35x_probe(struct platform_device *pdev)
struct clk *clk;
int ret = -ENOMEM;
- int musbid;
glue = kzalloc(sizeof(*glue), GFP_KERNEL);
if (!glue) {
@@ -473,18 +472,10 @@ static int __devinit am35x_probe(struct platform_device *pdev)
goto err0;
}
- /* get the musb id */
- musbid = musb_get_id(&pdev->dev, GFP_KERNEL);
- if (musbid < 0) {
- dev_err(&pdev->dev, "failed to allocate musb id\n");
- ret = -ENOMEM;
- goto err1;
- }
-
- musb = platform_device_alloc("musb-hdrc", musbid);
+ musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO);
if (!musb) {
dev_err(&pdev->dev, "failed to allocate musb device\n");
- goto err2;
+ goto err1;
}
phy_clk = clk_get(&pdev->dev, "fck");
@@ -513,7 +504,6 @@ static int __devinit am35x_probe(struct platform_device *pdev)
goto err6;
}
- musb->id = musbid;
musb->dev.parent = &pdev->dev;
musb->dev.dma_mask = &am35x_dmamask;
musb->dev.coherent_dma_mask = am35x_dmamask;
@@ -563,9 +553,6 @@ err4:
err3:
platform_device_put(musb);
-err2:
- musb_put_id(&pdev->dev, musbid);
-
err1:
kfree(glue);
@@ -573,13 +560,11 @@ err0:
return ret;
}
-static int __devexit am35x_remove(struct platform_device *pdev)
+static int am35x_remove(struct platform_device *pdev)
{
struct am35x_glue *glue = platform_get_drvdata(pdev);
- musb_put_id(&pdev->dev, glue->musb->id);
- platform_device_del(glue->musb);
- platform_device_put(glue->musb);
+ platform_device_unregister(glue->musb);
clk_disable(glue->clk);
clk_disable(glue->phy_clk);
clk_put(glue->clk);
@@ -644,7 +629,7 @@ static struct dev_pm_ops am35x_pm_ops = {
static struct platform_driver am35x_driver = {
.probe = am35x_probe,
- .remove = __devexit_p(am35x_remove),
+ .remove = am35x_remove,
.driver = {
.name = "musb-am35x",
.pm = DEV_PM_OPS,
@@ -654,15 +639,4 @@ static struct platform_driver am35x_driver = {
MODULE_DESCRIPTION("AM35x MUSB Glue Layer");
MODULE_AUTHOR("Ajay Kumar Gupta <ajay.gupta@ti.com>");
MODULE_LICENSE("GPL v2");
-
-static int __init am35x_init(void)
-{
- return platform_driver_register(&am35x_driver);
-}
-module_init(am35x_init);
-
-static void __exit am35x_exit(void)
-{
- platform_driver_unregister(&am35x_driver);
-}
-module_exit(am35x_exit);
+module_platform_driver(am35x_driver);
diff --git a/drivers/usb/musb/blackfin.c b/drivers/usb/musb/blackfin.c
index e8cff9bb9d23..14dab9f9b3d0 100644
--- a/drivers/usb/musb/blackfin.c
+++ b/drivers/usb/musb/blackfin.c
@@ -448,14 +448,13 @@ static const struct musb_platform_ops bfin_ops = {
static u64 bfin_dmamask = DMA_BIT_MASK(32);
-static int __devinit bfin_probe(struct platform_device *pdev)
+static int bfin_probe(struct platform_device *pdev)
{
struct musb_hdrc_platform_data *pdata = pdev->dev.platform_data;
struct platform_device *musb;
struct bfin_glue *glue;
int ret = -ENOMEM;
- int musbid;
glue = kzalloc(sizeof(*glue), GFP_KERNEL);
if (!glue) {
@@ -463,21 +462,12 @@ static int __devinit bfin_probe(struct platform_device *pdev)
goto err0;
}
- /* get the musb id */
- musbid = musb_get_id(&pdev->dev, GFP_KERNEL);
- if (musbid < 0) {
- dev_err(&pdev->dev, "failed to allocate musb id\n");
- ret = -ENOMEM;
- goto err1;
- }
-
- musb = platform_device_alloc("musb-hdrc", musbid);
+ musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO);
if (!musb) {
dev_err(&pdev->dev, "failed to allocate musb device\n");
- goto err2;
+ goto err1;
}
- musb->id = musbid;
musb->dev.parent = &pdev->dev;
musb->dev.dma_mask = &bfin_dmamask;
musb->dev.coherent_dma_mask = bfin_dmamask;
@@ -513,9 +503,6 @@ static int __devinit bfin_probe(struct platform_device *pdev)
err3:
platform_device_put(musb);
-err2:
- musb_put_id(&pdev->dev, musbid);
-
err1:
kfree(glue);
@@ -523,13 +510,11 @@ err0:
return ret;
}
-static int __devexit bfin_remove(struct platform_device *pdev)
+static int bfin_remove(struct platform_device *pdev)
{
struct bfin_glue *glue = platform_get_drvdata(pdev);
- musb_put_id(&pdev->dev, glue->musb->id);
- platform_device_del(glue->musb);
- platform_device_put(glue->musb);
+ platform_device_unregister(glue->musb);
kfree(glue);
return 0;
@@ -585,15 +570,4 @@ static struct platform_driver bfin_driver = {
MODULE_DESCRIPTION("Blackfin MUSB Glue Layer");
MODULE_AUTHOR("Bryan Wy <cooloney@kernel.org>");
MODULE_LICENSE("GPL v2");
-
-static int __init bfin_init(void)
-{
- return platform_driver_register(&bfin_driver);
-}
-module_init(bfin_init);
-
-static void __exit bfin_exit(void)
-{
- platform_driver_unregister(&bfin_driver);
-}
-module_exit(bfin_exit);
+module_platform_driver(bfin_driver);
diff --git a/drivers/usb/musb/cppi_dma.c b/drivers/usb/musb/cppi_dma.c
index e19da82b4782..0968dd7a859d 100644
--- a/drivers/usb/musb/cppi_dma.c
+++ b/drivers/usb/musb/cppi_dma.c
@@ -1314,10 +1314,10 @@ irqreturn_t cppi_interrupt(int irq, void *dev_id)
return IRQ_HANDLED;
}
+EXPORT_SYMBOL_GPL(cppi_interrupt);
/* Instantiate a software object representing a DMA controller. */
-struct dma_controller *__devinit
-dma_controller_create(struct musb *musb, void __iomem *mregs)
+struct dma_controller *dma_controller_create(struct musb *musb, void __iomem *mregs)
{
struct cppi *controller;
struct device *dev = musb->controller;
diff --git a/drivers/usb/musb/da8xx.c b/drivers/usb/musb/da8xx.c
index 8bc44b76eec2..97996af2646e 100644
--- a/drivers/usb/musb/da8xx.c
+++ b/drivers/usb/musb/da8xx.c
@@ -471,7 +471,7 @@ static const struct musb_platform_ops da8xx_ops = {
static u64 da8xx_dmamask = DMA_BIT_MASK(32);
-static int __devinit da8xx_probe(struct platform_device *pdev)
+static int da8xx_probe(struct platform_device *pdev)
{
struct musb_hdrc_platform_data *pdata = pdev->dev.platform_data;
struct platform_device *musb;
@@ -480,7 +480,6 @@ static int __devinit da8xx_probe(struct platform_device *pdev)
struct clk *clk;
int ret = -ENOMEM;
- int musbid;
glue = kzalloc(sizeof(*glue), GFP_KERNEL);
if (!glue) {
@@ -488,18 +487,10 @@ static int __devinit da8xx_probe(struct platform_device *pdev)
goto err0;
}
- /* get the musb id */
- musbid = musb_get_id(&pdev->dev, GFP_KERNEL);
- if (musbid < 0) {
- dev_err(&pdev->dev, "failed to allocate musb id\n");
- ret = -ENOMEM;
- goto err1;
- }
-
- musb = platform_device_alloc("musb-hdrc", musbid);
+ musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO);
if (!musb) {
dev_err(&pdev->dev, "failed to allocate musb device\n");
- goto err2;
+ goto err1;
}
clk = clk_get(&pdev->dev, "usb20");
@@ -515,7 +506,6 @@ static int __devinit da8xx_probe(struct platform_device *pdev)
goto err4;
}
- musb->id = musbid;
musb->dev.parent = &pdev->dev;
musb->dev.dma_mask = &da8xx_dmamask;
musb->dev.coherent_dma_mask = da8xx_dmamask;
@@ -558,9 +548,6 @@ err4:
err3:
platform_device_put(musb);
-err2:
- musb_put_id(&pdev->dev, musbid);
-
err1:
kfree(glue);
@@ -568,13 +555,11 @@ err0:
return ret;
}
-static int __devexit da8xx_remove(struct platform_device *pdev)
+static int da8xx_remove(struct platform_device *pdev)
{
struct da8xx_glue *glue = platform_get_drvdata(pdev);
- musb_put_id(&pdev->dev, glue->musb->id);
- platform_device_del(glue->musb);
- platform_device_put(glue->musb);
+ platform_device_unregister(glue->musb);
clk_disable(glue->clk);
clk_put(glue->clk);
kfree(glue);
@@ -584,7 +569,7 @@ static int __devexit da8xx_remove(struct platform_device *pdev)
static struct platform_driver da8xx_driver = {
.probe = da8xx_probe,
- .remove = __devexit_p(da8xx_remove),
+ .remove = da8xx_remove,
.driver = {
.name = "musb-da8xx",
},
@@ -593,15 +578,4 @@ static struct platform_driver da8xx_driver = {
MODULE_DESCRIPTION("DA8xx/OMAP-L1x MUSB Glue Layer");
MODULE_AUTHOR("Sergei Shtylyov <sshtylyov@ru.mvista.com>");
MODULE_LICENSE("GPL v2");
-
-static int __init da8xx_init(void)
-{
- return platform_driver_register(&da8xx_driver);
-}
-module_init(da8xx_init);
-
-static void __exit da8xx_exit(void)
-{
- platform_driver_unregister(&da8xx_driver);
-}
-module_exit(da8xx_exit);
+module_platform_driver(da8xx_driver);
diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c
index 606bfd00cde6..b1c01cad28b2 100644
--- a/drivers/usb/musb/davinci.c
+++ b/drivers/usb/musb/davinci.c
@@ -504,7 +504,7 @@ static const struct musb_platform_ops davinci_ops = {
static u64 davinci_dmamask = DMA_BIT_MASK(32);
-static int __devinit davinci_probe(struct platform_device *pdev)
+static int davinci_probe(struct platform_device *pdev)
{
struct musb_hdrc_platform_data *pdata = pdev->dev.platform_data;
struct platform_device *musb;
@@ -512,7 +512,6 @@ static int __devinit davinci_probe(struct platform_device *pdev)
struct clk *clk;
int ret = -ENOMEM;
- int musbid;
glue = kzalloc(sizeof(*glue), GFP_KERNEL);
if (!glue) {
@@ -520,18 +519,10 @@ static int __devinit davinci_probe(struct platform_device *pdev)
goto err0;
}
- /* get the musb id */
- musbid = musb_get_id(&pdev->dev, GFP_KERNEL);
- if (musbid < 0) {
- dev_err(&pdev->dev, "failed to allocate musb id\n");
- ret = -ENOMEM;
- goto err1;
- }
-
- musb = platform_device_alloc("musb-hdrc", musbid);
+ musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO);
if (!musb) {
dev_err(&pdev->dev, "failed to allocate musb device\n");
- goto err2;
+ goto err1;
}
clk = clk_get(&pdev->dev, "usb");
@@ -547,7 +538,6 @@ static int __devinit davinci_probe(struct platform_device *pdev)
goto err4;
}
- musb->id = musbid;
musb->dev.parent = &pdev->dev;
musb->dev.dma_mask = &davinci_dmamask;
musb->dev.coherent_dma_mask = davinci_dmamask;
@@ -590,9 +580,6 @@ err4:
err3:
platform_device_put(musb);
-err2:
- musb_put_id(&pdev->dev, musbid);
-
err1:
kfree(glue);
@@ -600,13 +587,11 @@ err0:
return ret;
}
-static int __devexit davinci_remove(struct platform_device *pdev)
+static int davinci_remove(struct platform_device *pdev)
{
struct davinci_glue *glue = platform_get_drvdata(pdev);
- musb_put_id(&pdev->dev, glue->musb->id);
- platform_device_del(glue->musb);
- platform_device_put(glue->musb);
+ platform_device_unregister(glue->musb);
clk_disable(glue->clk);
clk_put(glue->clk);
kfree(glue);
@@ -616,7 +601,7 @@ static int __devexit davinci_remove(struct platform_device *pdev)
static struct platform_driver davinci_driver = {
.probe = davinci_probe,
- .remove = __devexit_p(davinci_remove),
+ .remove = davinci_remove,
.driver = {
.name = "musb-davinci",
},
@@ -625,15 +610,4 @@ static struct platform_driver davinci_driver = {
MODULE_DESCRIPTION("DaVinci MUSB Glue Layer");
MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>");
MODULE_LICENSE("GPL v2");
-
-static int __init davinci_init(void)
-{
- return platform_driver_register(&davinci_driver);
-}
-module_init(davinci_init);
-
-static void __exit davinci_exit(void)
-{
- platform_driver_unregister(&davinci_driver);
-}
-module_exit(davinci_exit);
+module_platform_driver(davinci_driver);
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index bb56a0e8b23b..57cc9c6eaa9f 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -116,7 +116,6 @@
#define MUSB_DRIVER_NAME "musb-hdrc"
const char musb_driver_name[] = MUSB_DRIVER_NAME;
-static DEFINE_IDA(musb_ida);
MODULE_DESCRIPTION(DRIVER_INFO);
MODULE_AUTHOR(DRIVER_AUTHOR);
@@ -133,35 +132,6 @@ static inline struct musb *dev_to_musb(struct device *dev)
/*-------------------------------------------------------------------------*/
-int musb_get_id(struct device *dev, gfp_t gfp_mask)
-{
- int ret;
- int id;
-
- ret = ida_pre_get(&musb_ida, gfp_mask);
- if (!ret) {
- dev_err(dev, "failed to reserve resource for id\n");
- return -ENOMEM;
- }
-
- ret = ida_get_new(&musb_ida, &id);
- if (ret < 0) {
- dev_err(dev, "failed to allocate a new id\n");
- return ret;
- }
-
- return id;
-}
-EXPORT_SYMBOL_GPL(musb_get_id);
-
-void musb_put_id(struct device *dev, int id)
-{
-
- dev_dbg(dev, "removing id %d\n", id);
- ida_remove(&musb_ida, id);
-}
-EXPORT_SYMBOL_GPL(musb_put_id);
-
#ifndef CONFIG_BLACKFIN
static int musb_ulpi_read(struct usb_phy *phy, u32 offset)
{
@@ -467,12 +437,12 @@ void musb_hnp_stop(struct musb *musb)
*/
static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
- u8 devctl, u8 power)
+ u8 devctl)
{
struct usb_otg *otg = musb->xceiv->otg;
irqreturn_t handled = IRQ_NONE;
- dev_dbg(musb->controller, "<== Power=%02x, DevCtl=%02x, int_usb=0x%x\n", power, devctl,
+ dev_dbg(musb->controller, "<== DevCtl=%02x, int_usb=0x%x\n", devctl,
int_usb);
/* in host mode, the peripheral may issue remote wakeup.
@@ -485,6 +455,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
if (devctl & MUSB_DEVCTL_HM) {
void __iomem *mbase = musb->mregs;
+ u8 power;
switch (musb->xceiv->state) {
case OTG_STATE_A_SUSPEND:
@@ -492,6 +463,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
* will stop RESUME signaling
*/
+ power = musb_readb(musb->mregs, MUSB_POWER);
if (power & MUSB_POWER_SUSPENDM) {
/* spurious */
musb->int_usb &= ~MUSB_INTR_SUSPEND;
@@ -655,8 +627,8 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
}
if (int_usb & MUSB_INTR_SUSPEND) {
- dev_dbg(musb->controller, "SUSPEND (%s) devctl %02x power %02x\n",
- otg_state_string(musb->xceiv->state), devctl, power);
+ dev_dbg(musb->controller, "SUSPEND (%s) devctl %02x\n",
+ otg_state_string(musb->xceiv->state), devctl);
handled = IRQ_HANDLED;
switch (musb->xceiv->state) {
@@ -722,8 +694,10 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
if (is_peripheral_active(musb)) {
/* REVISIT HNP; just force disconnect */
}
- musb_writew(musb->mregs, MUSB_INTRTXE, musb->epmask);
- musb_writew(musb->mregs, MUSB_INTRRXE, musb->epmask & 0xfffe);
+ musb->intrtxe = musb->epmask;
+ musb_writew(musb->mregs, MUSB_INTRTXE, musb->intrtxe);
+ musb->intrrxe = musb->epmask & 0xfffe;
+ musb_writew(musb->mregs, MUSB_INTRRXE, musb->intrrxe);
musb_writeb(musb->mregs, MUSB_INTRUSBE, 0xf7);
musb->port1_status &= ~(USB_PORT_STAT_LOW_SPEED
|USB_PORT_STAT_HIGH_SPEED
@@ -944,8 +918,10 @@ void musb_start(struct musb *musb)
dev_dbg(musb->controller, "<== devctl %02x\n", devctl);
/* Set INT enable registers, enable interrupts */
- musb_writew(regs, MUSB_INTRTXE, musb->epmask);
- musb_writew(regs, MUSB_INTRRXE, musb->epmask & 0xfffe);
+ musb->intrtxe = musb->epmask;
+ musb_writew(regs, MUSB_INTRTXE, musb->intrtxe);
+ musb->intrrxe = musb->epmask & 0xfffe;
+ musb_writew(regs, MUSB_INTRRXE, musb->intrrxe);
musb_writeb(regs, MUSB_INTRUSBE, 0xf7);
musb_writeb(regs, MUSB_TESTMODE, 0);
@@ -983,7 +959,9 @@ static void musb_generic_disable(struct musb *musb)
/* disable interrupts */
musb_writeb(mbase, MUSB_INTRUSBE, 0);
+ musb->intrtxe = 0;
musb_writew(mbase, MUSB_INTRTXE, 0);
+ musb->intrrxe = 0;
musb_writew(mbase, MUSB_INTRRXE, 0);
/* off */
@@ -1062,12 +1040,12 @@ static void musb_shutdown(struct platform_device *pdev)
|| defined(CONFIG_USB_MUSB_AM35X_MODULE) \
|| defined(CONFIG_USB_MUSB_DSPS) \
|| defined(CONFIG_USB_MUSB_DSPS_MODULE)
-static ushort __devinitdata fifo_mode = 4;
+static ushort fifo_mode = 4;
#elif defined(CONFIG_USB_MUSB_UX500) \
|| defined(CONFIG_USB_MUSB_UX500_MODULE)
-static ushort __devinitdata fifo_mode = 5;
+static ushort fifo_mode = 5;
#else
-static ushort __devinitdata fifo_mode = 2;
+static ushort fifo_mode = 2;
#endif
/* "modprobe ... fifo_mode=1" etc */
@@ -1080,7 +1058,7 @@ MODULE_PARM_DESC(fifo_mode, "initial endpoint configuration");
*/
/* mode 0 - fits in 2KB */
-static struct musb_fifo_cfg __devinitdata mode_0_cfg[] = {
+static struct musb_fifo_cfg mode_0_cfg[] = {
{ .hw_ep_num = 1, .style = FIFO_TX, .maxpacket = 512, },
{ .hw_ep_num = 1, .style = FIFO_RX, .maxpacket = 512, },
{ .hw_ep_num = 2, .style = FIFO_RXTX, .maxpacket = 512, },
@@ -1089,7 +1067,7 @@ static struct musb_fifo_cfg __devinitdata mode_0_cfg[] = {
};
/* mode 1 - fits in 4KB */
-static struct musb_fifo_cfg __devinitdata mode_1_cfg[] = {
+static struct musb_fifo_cfg mode_1_cfg[] = {
{ .hw_ep_num = 1, .style = FIFO_TX, .maxpacket = 512, .mode = BUF_DOUBLE, },
{ .hw_ep_num = 1, .style = FIFO_RX, .maxpacket = 512, .mode = BUF_DOUBLE, },
{ .hw_ep_num = 2, .style = FIFO_RXTX, .maxpacket = 512, .mode = BUF_DOUBLE, },
@@ -1098,7 +1076,7 @@ static struct musb_fifo_cfg __devinitdata mode_1_cfg[] = {
};
/* mode 2 - fits in 4KB */
-static struct musb_fifo_cfg __devinitdata mode_2_cfg[] = {
+static struct musb_fifo_cfg mode_2_cfg[] = {
{ .hw_ep_num = 1, .style = FIFO_TX, .maxpacket = 512, },
{ .hw_ep_num = 1, .style = FIFO_RX, .maxpacket = 512, },
{ .hw_ep_num = 2, .style = FIFO_TX, .maxpacket = 512, },
@@ -1108,7 +1086,7 @@ static struct musb_fifo_cfg __devinitdata mode_2_cfg[] = {
};
/* mode 3 - fits in 4KB */
-static struct musb_fifo_cfg __devinitdata mode_3_cfg[] = {
+static struct musb_fifo_cfg mode_3_cfg[] = {
{ .hw_ep_num = 1, .style = FIFO_TX, .maxpacket = 512, .mode = BUF_DOUBLE, },
{ .hw_ep_num = 1, .style = FIFO_RX, .maxpacket = 512, .mode = BUF_DOUBLE, },
{ .hw_ep_num = 2, .style = FIFO_TX, .maxpacket = 512, },
@@ -1118,7 +1096,7 @@ static struct musb_fifo_cfg __devinitdata mode_3_cfg[] = {
};
/* mode 4 - fits in 16KB */
-static struct musb_fifo_cfg __devinitdata mode_4_cfg[] = {
+static struct musb_fifo_cfg mode_4_cfg[] = {
{ .hw_ep_num = 1, .style = FIFO_TX, .maxpacket = 512, },
{ .hw_ep_num = 1, .style = FIFO_RX, .maxpacket = 512, },
{ .hw_ep_num = 2, .style = FIFO_TX, .maxpacket = 512, },
@@ -1149,7 +1127,7 @@ static struct musb_fifo_cfg __devinitdata mode_4_cfg[] = {
};
/* mode 5 - fits in 8KB */
-static struct musb_fifo_cfg __devinitdata mode_5_cfg[] = {
+static struct musb_fifo_cfg mode_5_cfg[] = {
{ .hw_ep_num = 1, .style = FIFO_TX, .maxpacket = 512, },
{ .hw_ep_num = 1, .style = FIFO_RX, .maxpacket = 512, },
{ .hw_ep_num = 2, .style = FIFO_TX, .maxpacket = 512, },
@@ -1185,7 +1163,7 @@ static struct musb_fifo_cfg __devinitdata mode_5_cfg[] = {
*
* returns negative errno or offset for next fifo.
*/
-static int __devinit
+static int
fifo_setup(struct musb *musb, struct musb_hw_ep *hw_ep,
const struct musb_fifo_cfg *cfg, u16 offset)
{
@@ -1256,11 +1234,11 @@ fifo_setup(struct musb *musb, struct musb_hw_ep *hw_ep,
return offset + (maxpacket << ((c_size & MUSB_FIFOSZ_DPB) ? 1 : 0));
}
-static struct musb_fifo_cfg __devinitdata ep0_cfg = {
+static struct musb_fifo_cfg ep0_cfg = {
.style = FIFO_RXTX, .maxpacket = 64,
};
-static int __devinit ep_config_from_table(struct musb *musb)
+static int ep_config_from_table(struct musb *musb)
{
const struct musb_fifo_cfg *cfg;
unsigned i, n;
@@ -1351,7 +1329,7 @@ done:
* ep_config_from_hw - when MUSB_C_DYNFIFO_DEF is false
* @param musb the controller
*/
-static int __devinit ep_config_from_hw(struct musb *musb)
+static int ep_config_from_hw(struct musb *musb)
{
u8 epnum = 0;
struct musb_hw_ep *hw_ep;
@@ -1398,7 +1376,7 @@ enum { MUSB_CONTROLLER_MHDRC, MUSB_CONTROLLER_HDRC, };
/* Initialize MUSB (M)HDRC part of the USB hardware subsystem;
* configure endpoints, or take their config from silicon
*/
-static int __devinit musb_core_init(u16 musb_type, struct musb *musb)
+static int musb_core_init(u16 musb_type, struct musb *musb)
{
u8 reg;
char *type;
@@ -1523,33 +1501,6 @@ static int __devinit musb_core_init(u16 musb_type, struct musb *musb)
/*-------------------------------------------------------------------------*/
-#if defined(CONFIG_SOC_OMAP2430) || defined(CONFIG_SOC_OMAP3430) || \
- defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_ARCH_U8500)
-
-static irqreturn_t generic_interrupt(int irq, void *__hci)
-{
- unsigned long flags;
- irqreturn_t retval = IRQ_NONE;
- struct musb *musb = __hci;
-
- spin_lock_irqsave(&musb->lock, flags);
-
- musb->int_usb = musb_readb(musb->mregs, MUSB_INTRUSB);
- musb->int_tx = musb_readw(musb->mregs, MUSB_INTRTX);
- musb->int_rx = musb_readw(musb->mregs, MUSB_INTRRX);
-
- if (musb->int_usb || musb->int_tx || musb->int_rx)
- retval = musb_interrupt(musb);
-
- spin_unlock_irqrestore(&musb->lock, flags);
-
- return retval;
-}
-
-#else
-#define generic_interrupt NULL
-#endif
-
/*
* handle all the irqs defined by the HDRC core. for now we expect: other
* irq sources (phy, dma, etc) will be handled first, musb->int_* values
@@ -1560,12 +1511,11 @@ static irqreturn_t generic_interrupt(int irq, void *__hci)
irqreturn_t musb_interrupt(struct musb *musb)
{
irqreturn_t retval = IRQ_NONE;
- u8 devctl, power;
+ u8 devctl;
int ep_num;
u32 reg;
devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
- power = musb_readb(musb->mregs, MUSB_POWER);
dev_dbg(musb->controller, "** IRQ %s usb%04x tx%04x rx%04x\n",
(devctl & MUSB_DEVCTL_HM) ? "host" : "peripheral",
@@ -1576,7 +1526,7 @@ irqreturn_t musb_interrupt(struct musb *musb)
*/
if (musb->int_usb)
retval |= musb_stage0_irq(musb, musb->int_usb,
- devctl, power);
+ devctl);
/* "stage 1" is handling endpoint irqs */
@@ -1628,7 +1578,7 @@ irqreturn_t musb_interrupt(struct musb *musb)
EXPORT_SYMBOL_GPL(musb_interrupt);
#ifndef CONFIG_MUSB_PIO_ONLY
-static bool __devinitdata use_dma = 1;
+static bool use_dma = 1;
/* "modprobe ... use_dma=0" etc */
module_param(use_dma, bool, 0);
@@ -1809,8 +1759,7 @@ static void musb_irq_work(struct work_struct *data)
* Init support
*/
-static struct musb *__devinit
-allocate_instance(struct device *dev,
+static struct musb *allocate_instance(struct device *dev,
struct musb_hdrc_config *config, void __iomem *mbase)
{
struct musb *musb;
@@ -1885,7 +1834,7 @@ static void musb_free(struct musb *musb)
* @ctrl: virtual address of controller registers,
* not yet corrected for platform-specific offsets
*/
-static int __devinit
+static int
musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
{
int status;
@@ -1919,7 +1868,8 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
musb->ops = plat->platform_ops;
/* The musb_platform_init() call:
- * - adjusts musb->mregs and musb->isr if needed,
+ * - adjusts musb->mregs
+ * - sets the musb->isr
* - may initialize an integrated tranceiver
* - initializes musb->xceiv, usually by otg_get_phy()
* - stops powering VBUS
@@ -1929,7 +1879,6 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
* external/discrete ones in various flavors (twl4030 family,
* isp1504, non-OTG, etc) mostly hooking up through ULPI.
*/
- musb->isr = generic_interrupt;
status = musb_platform_init(musb);
if (status < 0)
goto fail1;
@@ -2060,7 +2009,7 @@ fail0:
/* all implementations (PCI bridge to FPGA, VLYNQ, etc) should just
* bridge to a platform device; this driver then suffices.
*/
-static int __devinit musb_probe(struct platform_device *pdev)
+static int musb_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
int irq = platform_get_irq_byname(pdev, "mc");
@@ -2085,7 +2034,7 @@ static int __devinit musb_probe(struct platform_device *pdev)
return status;
}
-static int __devexit musb_remove(struct platform_device *pdev)
+static int musb_remove(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct musb *musb = dev_to_musb(dev);
@@ -2120,8 +2069,6 @@ static void musb_save_context(struct musb *musb)
musb->context.testmode = musb_readb(musb_base, MUSB_TESTMODE);
musb->context.busctl = musb_read_ulpi_buscontrol(musb->mregs);
musb->context.power = musb_readb(musb_base, MUSB_POWER);
- musb->context.intrtxe = musb_readw(musb_base, MUSB_INTRTXE);
- musb->context.intrrxe = musb_readw(musb_base, MUSB_INTRRXE);
musb->context.intrusbe = musb_readb(musb_base, MUSB_INTRUSBE);
musb->context.index = musb_readb(musb_base, MUSB_INDEX);
musb->context.devctl = musb_readb(musb_base, MUSB_DEVCTL);
@@ -2194,8 +2141,8 @@ static void musb_restore_context(struct musb *musb)
musb_writeb(musb_base, MUSB_TESTMODE, musb->context.testmode);
musb_write_ulpi_buscontrol(musb->mregs, musb->context.busctl);
musb_writeb(musb_base, MUSB_POWER, musb->context.power);
- musb_writew(musb_base, MUSB_INTRTXE, musb->context.intrtxe);
- musb_writew(musb_base, MUSB_INTRRXE, musb->context.intrrxe);
+ musb_writew(musb_base, MUSB_INTRTXE, musb->intrtxe);
+ musb_writew(musb_base, MUSB_INTRRXE, musb->intrrxe);
musb_writeb(musb_base, MUSB_INTRUSBE, musb->context.intrusbe);
musb_writeb(musb_base, MUSB_DEVCTL, musb->context.devctl);
@@ -2340,7 +2287,7 @@ static struct platform_driver musb_driver = {
.pm = MUSB_DEV_PM_OPS,
},
.probe = musb_probe,
- .remove = __devexit_p(musb_remove),
+ .remove = musb_remove,
.shutdown = musb_shutdown,
};
diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h
index c158aacd6de8..7fb4819a6f11 100644
--- a/drivers/usb/musb/musb_core.h
+++ b/drivers/usb/musb/musb_core.h
@@ -288,7 +288,6 @@ struct musb_csr_regs {
struct musb_context_registers {
u8 power;
- u16 intrtxe, intrrxe;
u8 intrusbe;
u16 frame;
u8 index, testmode;
@@ -313,6 +312,8 @@ struct musb {
struct work_struct irq_work;
u16 hwvers;
+ u16 intrrxe;
+ u16 intrtxe;
/* this hub status bit is reserved by USB 2.0 and not seen by usbcore */
#define MUSB_PORT_STAT_RESUME (1 << 31)
@@ -521,8 +522,6 @@ extern const char musb_driver_name[];
extern void musb_start(struct musb *musb);
extern void musb_stop(struct musb *musb);
-extern int musb_get_id(struct device *dev, gfp_t gfp_mask);
-extern void musb_put_id(struct device *dev, int id);
extern void musb_write_fifo(struct musb_hw_ep *ep, u16 len, const u8 *src);
extern void musb_read_fifo(struct musb_hw_ep *ep, u16 len, u8 *dst);
diff --git a/drivers/usb/musb/musb_debugfs.c b/drivers/usb/musb/musb_debugfs.c
index 1d6e8af94c06..4c216790e86b 100644
--- a/drivers/usb/musb/musb_debugfs.c
+++ b/drivers/usb/musb/musb_debugfs.c
@@ -233,7 +233,7 @@ static const struct file_operations musb_test_mode_fops = {
.release = single_release,
};
-int __devinit musb_init_debugfs(struct musb *musb)
+int musb_init_debugfs(struct musb *musb)
{
struct dentry *root;
struct dentry *file;
diff --git a/drivers/usb/musb/musb_dma.h b/drivers/usb/musb/musb_dma.h
index 24d39210d4ab..1b6b827b769f 100644
--- a/drivers/usb/musb/musb_dma.h
+++ b/drivers/usb/musb/musb_dma.h
@@ -178,8 +178,7 @@ struct dma_controller {
extern void musb_dma_completion(struct musb *musb, u8 epnum, u8 transmit);
-extern struct dma_controller *__devinit
-dma_controller_create(struct musb *, void __iomem *);
+extern struct dma_controller *dma_controller_create(struct musb *, void __iomem *);
extern void dma_controller_destroy(struct dma_controller *);
diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c
index ff5f112053d2..9a975aa0dee2 100644
--- a/drivers/usb/musb/musb_dsps.c
+++ b/drivers/usb/musb/musb_dsps.c
@@ -124,8 +124,44 @@ struct dsps_glue {
const struct dsps_musb_wrapper *wrp; /* wrapper register offsets */
struct timer_list timer[2]; /* otg_workaround timer */
unsigned long last_timer[2]; /* last timer data for each instance */
+ u32 __iomem *usb_ctrl[2];
};
+#define DSPS_AM33XX_CONTROL_MODULE_PHYS_0 0x44e10620
+#define DSPS_AM33XX_CONTROL_MODULE_PHYS_1 0x44e10628
+
+static const resource_size_t dsps_control_module_phys[] = {
+ DSPS_AM33XX_CONTROL_MODULE_PHYS_0,
+ DSPS_AM33XX_CONTROL_MODULE_PHYS_1,
+};
+
+/**
+ * musb_dsps_phy_control - phy on/off
+ * @glue: struct dsps_glue *
+ * @id: musb instance
+ * @on: flag for phy to be switched on or off
+ *
+ * This is to enable the PHY using usb_ctrl register in system control
+ * module space.
+ *
+ * XXX: This function will be removed once we have a seperate driver for
+ * control module
+ */
+static void musb_dsps_phy_control(struct dsps_glue *glue, u8 id, u8 on)
+{
+ u32 usbphycfg;
+
+ usbphycfg = readl(glue->usb_ctrl[id]);
+
+ if (on) {
+ usbphycfg &= ~(USBPHY_CM_PWRDN | USBPHY_OTG_PWRDN);
+ usbphycfg |= USBPHY_OTGVDET_EN | USBPHY_OTGSESSEND_EN;
+ } else {
+ usbphycfg |= USBPHY_CM_PWRDN | USBPHY_OTG_PWRDN;
+ }
+
+ writel(usbphycfg, glue->usb_ctrl[id]);
+}
/**
* dsps_musb_enable - enable interrupts
*/
@@ -296,7 +332,7 @@ static irqreturn_t dsps_interrupt(int irq, void *hci)
* Also, DRVVBUS pulses for SRP (but not at 5V) ...
*/
if (usbintr & MUSB_INTR_BABBLE)
- pr_info("CAUTION: musb: Babble Interrupt Occured\n");
+ pr_info("CAUTION: musb: Babble Interrupt Occurred\n");
if (usbintr & ((1 << wrp->drvvbus) << wrp->usb_shift)) {
int drvvbus = dsps_readl(reg_base, wrp->status);
@@ -365,11 +401,9 @@ static irqreturn_t dsps_interrupt(int irq, void *hci)
static int dsps_musb_init(struct musb *musb)
{
struct device *dev = musb->controller;
- struct musb_hdrc_platform_data *plat = dev->platform_data;
struct platform_device *pdev = to_platform_device(dev);
struct dsps_glue *glue = dev_get_drvdata(dev->parent);
const struct dsps_musb_wrapper *wrp = glue->wrp;
- struct omap_musb_board_data *data = plat->board_data;
void __iomem *reg_base = musb->ctrl_base;
u32 rev, val;
int status;
@@ -377,7 +411,8 @@ static int dsps_musb_init(struct musb *musb)
/* mentor core register starts at offset of 0x400 from musb base */
musb->mregs += wrp->musb_core_offset;
- /* Get the NOP PHY */
+ /* NOP driver needs change if supporting dual instance */
+ usb_nop_xceiv_register();
musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
if (IS_ERR_OR_NULL(musb->xceiv))
return -ENODEV;
@@ -395,8 +430,7 @@ static int dsps_musb_init(struct musb *musb)
dsps_writel(reg_base, wrp->control, (1 << wrp->reset));
/* Start the on-chip PHY and its PLL. */
- if (data->set_phy_power)
- data->set_phy_power(1);
+ musb_dsps_phy_control(glue, pdev->id, 1);
musb->isr = dsps_interrupt;
@@ -418,16 +452,13 @@ err0:
static int dsps_musb_exit(struct musb *musb)
{
struct device *dev = musb->controller;
- struct musb_hdrc_platform_data *plat = dev->platform_data;
- struct omap_musb_board_data *data = plat->board_data;
struct platform_device *pdev = to_platform_device(dev);
struct dsps_glue *glue = dev_get_drvdata(dev->parent);
del_timer_sync(&glue->timer[pdev->id]);
/* Shutdown the on-chip PHY and its PLL. */
- if (data->set_phy_power)
- data->set_phy_power(0);
+ musb_dsps_phy_control(glue, pdev->id, 0);
/* NOP driver needs change if supporting dual instance */
usb_put_phy(musb->xceiv);
@@ -448,7 +479,7 @@ static struct musb_platform_ops dsps_ops = {
static u64 musb_dmamask = DMA_BIT_MASK(32);
-static int __devinit dsps_create_musb_pdev(struct dsps_glue *glue, u8 id)
+static int dsps_create_musb_pdev(struct dsps_glue *glue, u8 id)
{
struct device *dev = glue->dev;
struct platform_device *pdev = to_platform_device(dev);
@@ -459,24 +490,33 @@ static int __devinit dsps_create_musb_pdev(struct dsps_glue *glue, u8 id)
struct resource *res;
struct resource resources[2];
char res_name[11];
- int ret, musbid;
+ int ret;
- /* get memory resource */
- snprintf(res_name, sizeof(res_name), "musb%d", id);
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, res_name);
+ resources[0].start = dsps_control_module_phys[id];
+ resources[0].end = resources[0].start + SZ_4 - 1;
+ resources[0].flags = IORESOURCE_MEM;
+
+ glue->usb_ctrl[id] = devm_request_and_ioremap(&pdev->dev, resources);
+ if (glue->usb_ctrl[id] == NULL) {
+ dev_err(dev, "Failed to obtain usb_ctrl%d memory\n", id);
+ ret = -ENODEV;
+ goto err0;
+ }
+
+ /* first resource is for usbss, so start index from 1 */
+ res = platform_get_resource(pdev, IORESOURCE_MEM, id + 1);
if (!res) {
- dev_err(dev, "%s get mem resource failed\n", res_name);
+ dev_err(dev, "failed to get memory for instance %d\n", id);
ret = -ENODEV;
goto err0;
}
res->parent = NULL;
resources[0] = *res;
- /* get irq resource */
- snprintf(res_name, sizeof(res_name), "musb%d-irq", id);
- res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, res_name);
+ /* first resource is for usbss, so start index from 1 */
+ res = platform_get_resource(pdev, IORESOURCE_IRQ, id + 1);
if (!res) {
- dev_err(dev, "%s get irq resource failed\n", res_name);
+ dev_err(dev, "failed to get irq for instance %d\n", id);
ret = -ENODEV;
goto err0;
}
@@ -484,22 +524,14 @@ static int __devinit dsps_create_musb_pdev(struct dsps_glue *glue, u8 id)
resources[1] = *res;
resources[1].name = "mc";
- /* get the musb id */
- musbid = musb_get_id(dev, GFP_KERNEL);
- if (musbid < 0) {
- dev_err(dev, "failed to allocate musb id\n");
- ret = -ENOMEM;
- goto err0;
- }
/* allocate the child platform device */
- musb = platform_device_alloc("musb-hdrc", musbid);
+ musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO);
if (!musb) {
dev_err(dev, "failed to allocate musb device\n");
ret = -ENOMEM;
- goto err1;
+ goto err0;
}
- musb->id = musbid;
musb->dev.parent = dev;
musb->dev.dma_mask = &musb_dmamask;
musb->dev.coherent_dma_mask = musb_dmamask;
@@ -556,20 +588,11 @@ static int __devinit dsps_create_musb_pdev(struct dsps_glue *glue, u8 id)
err2:
platform_device_put(musb);
-err1:
- musb_put_id(dev, musbid);
err0:
return ret;
}
-static void dsps_delete_musb_pdev(struct dsps_glue *glue, u8 id)
-{
- musb_put_id(glue->dev, glue->musb[id]->id);
- platform_device_del(glue->musb[id]);
- platform_device_put(glue->musb[id]);
-}
-
-static int __devinit dsps_probe(struct platform_device *pdev)
+static int dsps_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
const struct of_device_id *match;
@@ -628,7 +651,7 @@ static int __devinit dsps_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "failed to create child pdev\n");
/* release resources of previously created instances */
for (i--; i >= 0 ; i--)
- dsps_delete_musb_pdev(glue, i);
+ platform_device_unregister(glue->musb[i]);
goto err3;
}
}
@@ -645,7 +668,7 @@ err1:
err0:
return ret;
}
-static int __devexit dsps_remove(struct platform_device *pdev)
+static int dsps_remove(struct platform_device *pdev)
{
struct dsps_glue *glue = platform_get_drvdata(pdev);
const struct dsps_musb_wrapper *wrp = glue->wrp;
@@ -653,7 +676,7 @@ static int __devexit dsps_remove(struct platform_device *pdev)
/* delete the child platform device */
for (i = 0; i < wrp->instances ; i++)
- dsps_delete_musb_pdev(glue, i);
+ platform_device_unregister(glue->musb[i]);
/* disable usbss clocks */
pm_runtime_put(&pdev->dev);
@@ -666,24 +689,26 @@ static int __devexit dsps_remove(struct platform_device *pdev)
#ifdef CONFIG_PM_SLEEP
static int dsps_suspend(struct device *dev)
{
- struct musb_hdrc_platform_data *plat = dev->platform_data;
- struct omap_musb_board_data *data = plat->board_data;
+ struct platform_device *pdev = to_platform_device(dev->parent);
+ struct dsps_glue *glue = platform_get_drvdata(pdev);
+ const struct dsps_musb_wrapper *wrp = glue->wrp;
+ int i;
- /* Shutdown the on-chip PHY and its PLL. */
- if (data->set_phy_power)
- data->set_phy_power(0);
+ for (i = 0; i < wrp->instances; i++)
+ musb_dsps_phy_control(glue, i, 0);
return 0;
}
static int dsps_resume(struct device *dev)
{
- struct musb_hdrc_platform_data *plat = dev->platform_data;
- struct omap_musb_board_data *data = plat->board_data;
+ struct platform_device *pdev = to_platform_device(dev->parent);
+ struct dsps_glue *glue = platform_get_drvdata(pdev);
+ const struct dsps_musb_wrapper *wrp = glue->wrp;
+ int i;
- /* Start the on-chip PHY and its PLL. */
- if (data->set_phy_power)
- data->set_phy_power(1);
+ for (i = 0; i < wrp->instances; i++)
+ musb_dsps_phy_control(glue, i, 1);
return 0;
}
@@ -691,7 +716,7 @@ static int dsps_resume(struct device *dev)
static SIMPLE_DEV_PM_OPS(dsps_pm_ops, dsps_suspend, dsps_resume);
-static const struct dsps_musb_wrapper ti81xx_driver_data __devinitconst = {
+static const struct dsps_musb_wrapper ti81xx_driver_data = {
.revision = 0x00,
.control = 0x14,
.status = 0x18,
@@ -719,10 +744,10 @@ static const struct dsps_musb_wrapper ti81xx_driver_data __devinitconst = {
.rxep_bitmap = (0xfffe << 16),
.musb_core_offset = 0x400,
.poll_seconds = 2,
- .instances = 2,
+ .instances = 1,
};
-static const struct platform_device_id musb_dsps_id_table[] __devinitconst = {
+static const struct platform_device_id musb_dsps_id_table[] = {
{
.name = "musb-ti81xx",
.driver_data = (kernel_ulong_t) &ti81xx_driver_data,
@@ -732,7 +757,7 @@ static const struct platform_device_id musb_dsps_id_table[] __devinitconst = {
MODULE_DEVICE_TABLE(platform, musb_dsps_id_table);
#ifdef CONFIG_OF
-static const struct of_device_id musb_dsps_of_match[] __devinitconst = {
+static const struct of_device_id musb_dsps_of_match[] = {
{ .compatible = "ti,musb-am33xx",
.data = (void *) &ti81xx_driver_data, },
{ },
@@ -742,7 +767,7 @@ MODULE_DEVICE_TABLE(of, musb_dsps_of_match);
static struct platform_driver dsps_usbss_driver = {
.probe = dsps_probe,
- .remove = __devexit_p(dsps_remove),
+ .remove = dsps_remove,
.driver = {
.name = "musb-dsps",
.pm = &dsps_pm_ops,
diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c
index d0b87e7b4abf..876787438c2f 100644
--- a/drivers/usb/musb/musb_gadget.c
+++ b/drivers/usb/musb/musb_gadget.c
@@ -707,11 +707,12 @@ static void rxstate(struct musb *musb, struct musb_request *req)
fifo_count = musb_readw(epio, MUSB_RXCOUNT);
/*
- * use mode 1 only if we expect data of at least ep packet_sz
- * and have not yet received a short packet
+ * Enable Mode 1 on RX transfers only when short_not_ok flag
+ * is set. Currently short_not_ok flag is set only from
+ * file_storage and f_mass_storage drivers
*/
- if ((request->length - request->actual >= musb_ep->packet_sz) &&
- (fifo_count >= musb_ep->packet_sz))
+
+ if (request->short_not_ok && fifo_count == musb_ep->packet_sz)
use_mode_1 = 1;
else
use_mode_1 = 0;
@@ -727,6 +728,27 @@ static void rxstate(struct musb *musb, struct musb_request *req)
c = musb->dma_controller;
channel = musb_ep->dma;
+ /* We use DMA Req mode 0 in rx_csr, and DMA controller operates in
+ * mode 0 only. So we do not get endpoint interrupts due to DMA
+ * completion. We only get interrupts from DMA controller.
+ *
+ * We could operate in DMA mode 1 if we knew the size of the tranfer
+ * in advance. For mass storage class, request->length = what the host
+ * sends, so that'd work. But for pretty much everything else,
+ * request->length is routinely more than what the host sends. For
+ * most these gadgets, end of is signified either by a short packet,
+ * or filling the last byte of the buffer. (Sending extra data in
+ * that last pckate should trigger an overflow fault.) But in mode 1,
+ * we don't get DMA completion interrupt for short packets.
+ *
+ * Theoretically, we could enable DMAReq irq (MUSB_RXCSR_DMAMODE = 1),
+ * to get endpoint interrupt on every DMA req, but that didn't seem
+ * to work reliably.
+ *
+ * REVISIT an updated g_file_storage can set req->short_not_ok, which
+ * then becomes usable as a runtime "use mode 1" hint...
+ */
+
/* Experimental: Mode1 works with mass storage use cases */
if (use_mode_1) {
csr |= MUSB_RXCSR_AUTOCLEAR;
@@ -1068,7 +1090,6 @@ static int musb_gadget_enable(struct usb_ep *ep,
*/
musb_ep_select(mbase, epnum);
if (usb_endpoint_dir_in(desc)) {
- u16 int_txe = musb_readw(mbase, MUSB_INTRTXE);
if (hw_ep->is_shared_fifo)
musb_ep->is_in = 1;
@@ -1080,8 +1101,8 @@ static int musb_gadget_enable(struct usb_ep *ep,
goto fail;
}
- int_txe |= (1 << epnum);
- musb_writew(mbase, MUSB_INTRTXE, int_txe);
+ musb->intrtxe |= (1 << epnum);
+ musb_writew(mbase, MUSB_INTRTXE, musb->intrtxe);
/* REVISIT if can_bulk_split(), use by updating "tmp";
* likewise high bandwidth periodic tx
@@ -1108,7 +1129,6 @@ static int musb_gadget_enable(struct usb_ep *ep,
musb_writew(regs, MUSB_TXCSR, csr);
} else {
- u16 int_rxe = musb_readw(mbase, MUSB_INTRRXE);
if (hw_ep->is_shared_fifo)
musb_ep->is_in = 0;
@@ -1120,8 +1140,8 @@ static int musb_gadget_enable(struct usb_ep *ep,
goto fail;
}
- int_rxe |= (1 << epnum);
- musb_writew(mbase, MUSB_INTRRXE, int_rxe);
+ musb->intrrxe |= (1 << epnum);
+ musb_writew(mbase, MUSB_INTRRXE, musb->intrrxe);
/* REVISIT if can_bulk_combine() use by updating "tmp"
* likewise high bandwidth periodic rx
@@ -1209,14 +1229,12 @@ static int musb_gadget_disable(struct usb_ep *ep)
/* zero the endpoint sizes */
if (musb_ep->is_in) {
- u16 int_txe = musb_readw(musb->mregs, MUSB_INTRTXE);
- int_txe &= ~(1 << epnum);
- musb_writew(musb->mregs, MUSB_INTRTXE, int_txe);
+ musb->intrtxe &= ~(1 << epnum);
+ musb_writew(musb->mregs, MUSB_INTRTXE, musb->intrtxe);
musb_writew(epio, MUSB_TXMAXP, 0);
} else {
- u16 int_rxe = musb_readw(musb->mregs, MUSB_INTRRXE);
- int_rxe &= ~(1 << epnum);
- musb_writew(musb->mregs, MUSB_INTRRXE, int_rxe);
+ musb->intrrxe &= ~(1 << epnum);
+ musb_writew(musb->mregs, MUSB_INTRRXE, musb->intrrxe);
musb_writew(epio, MUSB_RXMAXP, 0);
}
@@ -1532,7 +1550,7 @@ static void musb_gadget_fifo_flush(struct usb_ep *ep)
void __iomem *epio = musb->endpoints[epnum].regs;
void __iomem *mbase;
unsigned long flags;
- u16 csr, int_txe;
+ u16 csr;
mbase = musb->mregs;
@@ -1540,8 +1558,7 @@ static void musb_gadget_fifo_flush(struct usb_ep *ep)
musb_ep_select(mbase, (u8) epnum);
/* disable interrupts */
- int_txe = musb_readw(mbase, MUSB_INTRTXE);
- musb_writew(mbase, MUSB_INTRTXE, int_txe & ~(1 << epnum));
+ musb_writew(mbase, MUSB_INTRTXE, musb->intrtxe & ~(1 << epnum));
if (musb_ep->is_in) {
csr = musb_readw(epio, MUSB_TXCSR);
@@ -1565,7 +1582,7 @@ static void musb_gadget_fifo_flush(struct usb_ep *ep)
}
/* re-enable interrupt */
- musb_writew(mbase, MUSB_INTRTXE, int_txe);
+ musb_writew(mbase, MUSB_INTRTXE, musb->intrtxe);
spin_unlock_irqrestore(&musb->lock, flags);
}
@@ -1770,7 +1787,7 @@ static void musb_gadget_release(struct device *dev)
}
-static void __devinit
+static void
init_peripheral_ep(struct musb *musb, struct musb_ep *ep, u8 epnum, int is_in)
{
struct musb_hw_ep *hw_ep = musb->endpoints + epnum;
@@ -1807,7 +1824,7 @@ init_peripheral_ep(struct musb *musb, struct musb_ep *ep, u8 epnum, int is_in)
* Initialize the endpoints exposed to peripheral drivers, with backlinks
* to the rest of the driver state.
*/
-static inline void __devinit musb_g_init_endpoints(struct musb *musb)
+static inline void musb_g_init_endpoints(struct musb *musb)
{
u8 epnum;
struct musb_hw_ep *hw_ep;
@@ -1840,7 +1857,7 @@ static inline void __devinit musb_g_init_endpoints(struct musb *musb)
/* called once during driver setup to initialize and link into
* the driver model; memory is zeroed.
*/
-int __devinit musb_gadget_setup(struct musb *musb)
+int musb_gadget_setup(struct musb *musb)
{
int status;
@@ -2154,10 +2171,9 @@ __acquires(musb->lock)
u8 devctl = musb_readb(mbase, MUSB_DEVCTL);
u8 power;
- dev_dbg(musb->controller, "<== %s addr=%x driver '%s'\n",
+ dev_dbg(musb->controller, "<== %s driver '%s'\n",
(devctl & MUSB_DEVCTL_BDEVICE)
? "B-Device" : "A-Device",
- musb_readb(mbase, MUSB_FADDR),
musb->gadget_driver
? musb->gadget_driver->driver.name
: NULL
diff --git a/drivers/usb/musb/musb_gadget_ep0.c b/drivers/usb/musb/musb_gadget_ep0.c
index e40d7647caf1..c9c1ac4e075f 100644
--- a/drivers/usb/musb/musb_gadget_ep0.c
+++ b/drivers/usb/musb/musb_gadget_ep0.c
@@ -673,10 +673,8 @@ irqreturn_t musb_g_ep0_irq(struct musb *musb)
csr = musb_readw(regs, MUSB_CSR0);
len = musb_readb(regs, MUSB_COUNT0);
- dev_dbg(musb->controller, "csr %04x, count %d, myaddr %d, ep0stage %s\n",
- csr, len,
- musb_readb(mbase, MUSB_FADDR),
- decode_ep0stage(musb->ep0_state));
+ dev_dbg(musb->controller, "csr %04x, count %d, ep0stage %s\n",
+ csr, len, decode_ep0stage(musb->ep0_state));
if (csr & MUSB_CSR0_P_DATAEND) {
/*
diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c
index 3df6a76b851d..e9f0fd9ddd2d 100644
--- a/drivers/usb/musb/musb_host.c
+++ b/drivers/usb/musb/musb_host.c
@@ -740,7 +740,7 @@ static void musb_ep_program(struct musb *musb, u8 epnum,
csr = musb_readw(epio, MUSB_TXCSR);
/* disable interrupt in case we flush */
- int_txe = musb_readw(mbase, MUSB_INTRTXE);
+ int_txe = musb->intrtxe;
musb_writew(mbase, MUSB_INTRTXE, int_txe & ~(1 << epnum));
/* general endpoint setup */
diff --git a/drivers/usb/musb/musbhsdma.c b/drivers/usb/musb/musbhsdma.c
index 0fc6ca6bc60a..3d1fd52a15a9 100644
--- a/drivers/usb/musb/musbhsdma.c
+++ b/drivers/usb/musb/musbhsdma.c
@@ -380,8 +380,7 @@ void dma_controller_destroy(struct dma_controller *c)
kfree(controller);
}
-struct dma_controller *__devinit
-dma_controller_create(struct musb *musb, void __iomem *base)
+struct dma_controller *dma_controller_create(struct musb *musb, void __iomem *base)
{
struct musb_dma_controller *controller;
struct device *dev = musb->controller;
diff --git a/drivers/usb/musb/musbhsdma.h b/drivers/usb/musb/musbhsdma.h
index 320fd4afb93f..f7b13fd25257 100644
--- a/drivers/usb/musb/musbhsdma.h
+++ b/drivers/usb/musb/musbhsdma.h
@@ -31,10 +31,6 @@
*
*/
-#if defined(CONFIG_SOC_OMAP2430) || defined(CONFIG_SOC_OMAP3430)
-#include "omap2430.h"
-#endif
-
#ifndef CONFIG_BLACKFIN
#define MUSB_HSDMA_BASE 0x200
diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c
index a538fe17a966..da00af460794 100644
--- a/drivers/usb/musb/omap2430.c
+++ b/drivers/usb/musb/omap2430.c
@@ -333,6 +333,26 @@ static void omap_musb_mailbox_work(struct work_struct *mailbox_work)
omap_musb_set_mailbox(glue);
}
+static irqreturn_t omap2430_musb_interrupt(int irq, void *__hci)
+{
+ unsigned long flags;
+ irqreturn_t retval = IRQ_NONE;
+ struct musb *musb = __hci;
+
+ spin_lock_irqsave(&musb->lock, flags);
+
+ musb->int_usb = musb_readb(musb->mregs, MUSB_INTRUSB);
+ musb->int_tx = musb_readw(musb->mregs, MUSB_INTRTX);
+ musb->int_rx = musb_readw(musb->mregs, MUSB_INTRRX);
+
+ if (musb->int_usb || musb->int_tx || musb->int_rx)
+ retval = musb_interrupt(musb);
+
+ spin_unlock_irqrestore(&musb->lock, flags);
+
+ return retval;
+}
+
static int omap2430_musb_init(struct musb *musb)
{
u32 l;
@@ -352,6 +372,8 @@ static int omap2430_musb_init(struct musb *musb)
return -ENODEV;
}
+ musb->isr = omap2430_musb_interrupt;
+
status = pm_runtime_get_sync(dev);
if (status < 0) {
dev_err(dev, "pm_runtime_get_sync FAILED %d\n", status);
@@ -468,7 +490,7 @@ static const struct musb_platform_ops omap2430_ops = {
static u64 omap2430_dmamask = DMA_BIT_MASK(32);
-static int __devinit omap2430_probe(struct platform_device *pdev)
+static int omap2430_probe(struct platform_device *pdev)
{
struct musb_hdrc_platform_data *pdata = pdev->dev.platform_data;
struct omap_musb_board_data *data;
@@ -478,7 +500,6 @@ static int __devinit omap2430_probe(struct platform_device *pdev)
struct musb_hdrc_config *config;
struct resource *res;
int ret = -ENOMEM;
- int musbid;
glue = devm_kzalloc(&pdev->dev, sizeof(*glue), GFP_KERNEL);
if (!glue) {
@@ -486,21 +507,12 @@ static int __devinit omap2430_probe(struct platform_device *pdev)
goto err0;
}
- /* get the musb id */
- musbid = musb_get_id(&pdev->dev, GFP_KERNEL);
- if (musbid < 0) {
- dev_err(&pdev->dev, "failed to allocate musb id\n");
- ret = -ENOMEM;
- goto err0;
- }
-
- musb = platform_device_alloc("musb-hdrc", musbid);
+ musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO);
if (!musb) {
dev_err(&pdev->dev, "failed to allocate musb device\n");
- goto err1;
+ goto err0;
}
- musb->id = musbid;
musb->dev.parent = &pdev->dev;
musb->dev.dma_mask = &omap2430_dmamask;
musb->dev.coherent_dma_mask = omap2430_dmamask;
@@ -521,7 +533,7 @@ static int __devinit omap2430_probe(struct platform_device *pdev)
dev_err(&pdev->dev,
"failed to allocate musb platfrom data\n");
ret = -ENOMEM;
- goto err1;
+ goto err2;
}
data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
@@ -529,14 +541,14 @@ static int __devinit omap2430_probe(struct platform_device *pdev)
dev_err(&pdev->dev,
"failed to allocate musb board data\n");
ret = -ENOMEM;
- goto err1;
+ goto err2;
}
config = devm_kzalloc(&pdev->dev, sizeof(*config), GFP_KERNEL);
if (!data) {
dev_err(&pdev->dev,
"failed to allocate musb hdrc config\n");
- goto err1;
+ goto err2;
}
of_property_read_u32(np, "mode", (u32 *)&pdata->mode);
@@ -589,19 +601,15 @@ static int __devinit omap2430_probe(struct platform_device *pdev)
err2:
platform_device_put(musb);
-err1:
- musb_put_id(&pdev->dev, musbid);
-
err0:
return ret;
}
-static int __devexit omap2430_remove(struct platform_device *pdev)
+static int omap2430_remove(struct platform_device *pdev)
{
struct omap2430_glue *glue = platform_get_drvdata(pdev);
cancel_work_sync(&glue->omap_musb_mailbox_work);
- musb_put_id(&pdev->dev, glue->musb->id);
platform_device_unregister(glue->musb);
return 0;
@@ -666,7 +674,7 @@ MODULE_DEVICE_TABLE(of, omap2430_id_table);
static struct platform_driver omap2430_driver = {
.probe = omap2430_probe,
- .remove = __devexit_p(omap2430_remove),
+ .remove = omap2430_remove,
.driver = {
.name = "musb-omap2430",
.pm = DEV_PM_OPS,
diff --git a/drivers/usb/musb/tusb6010.c b/drivers/usb/musb/tusb6010.c
index dc4d75ea13ad..8bde6fc5eb75 100644
--- a/drivers/usb/musb/tusb6010.c
+++ b/drivers/usb/musb/tusb6010.c
@@ -1153,14 +1153,13 @@ static const struct musb_platform_ops tusb_ops = {
static u64 tusb_dmamask = DMA_BIT_MASK(32);
-static int __devinit tusb_probe(struct platform_device *pdev)
+static int tusb_probe(struct platform_device *pdev)
{
struct musb_hdrc_platform_data *pdata = pdev->dev.platform_data;
struct platform_device *musb;
struct tusb6010_glue *glue;
int ret = -ENOMEM;
- int musbid;
glue = kzalloc(sizeof(*glue), GFP_KERNEL);
if (!glue) {
@@ -1168,21 +1167,12 @@ static int __devinit tusb_probe(struct platform_device *pdev)
goto err0;
}
- /* get the musb id */
- musbid = musb_get_id(&pdev->dev, GFP_KERNEL);
- if (musbid < 0) {
- dev_err(&pdev->dev, "failed to allocate musb id\n");
- ret = -ENOMEM;
- goto err1;
- }
-
- musb = platform_device_alloc("musb-hdrc", musbid);
+ musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO);
if (!musb) {
dev_err(&pdev->dev, "failed to allocate musb device\n");
- goto err2;
+ goto err1;
}
- musb->id = musbid;
musb->dev.parent = &pdev->dev;
musb->dev.dma_mask = &tusb_dmamask;
musb->dev.coherent_dma_mask = tusb_dmamask;
@@ -1218,9 +1208,6 @@ static int __devinit tusb_probe(struct platform_device *pdev)
err3:
platform_device_put(musb);
-err2:
- musb_put_id(&pdev->dev, musbid);
-
err1:
kfree(glue);
@@ -1228,13 +1215,11 @@ err0:
return ret;
}
-static int __devexit tusb_remove(struct platform_device *pdev)
+static int tusb_remove(struct platform_device *pdev)
{
struct tusb6010_glue *glue = platform_get_drvdata(pdev);
- musb_put_id(&pdev->dev, glue->musb->id);
- platform_device_del(glue->musb);
- platform_device_put(glue->musb);
+ platform_device_unregister(glue->musb);
kfree(glue);
return 0;
@@ -1242,7 +1227,7 @@ static int __devexit tusb_remove(struct platform_device *pdev)
static struct platform_driver tusb_driver = {
.probe = tusb_probe,
- .remove = __devexit_p(tusb_remove),
+ .remove = tusb_remove,
.driver = {
.name = "musb-tusb",
},
@@ -1251,15 +1236,4 @@ static struct platform_driver tusb_driver = {
MODULE_DESCRIPTION("TUSB6010 MUSB Glue Layer");
MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>");
MODULE_LICENSE("GPL v2");
-
-static int __init tusb_init(void)
-{
- return platform_driver_register(&tusb_driver);
-}
-module_init(tusb_init);
-
-static void __exit tusb_exit(void)
-{
- platform_driver_unregister(&tusb_driver);
-}
-module_exit(tusb_exit);
+module_platform_driver(tusb_driver);
diff --git a/drivers/usb/musb/tusb6010_omap.c b/drivers/usb/musb/tusb6010_omap.c
index 7a62b95dac24..2c46d42e6618 100644
--- a/drivers/usb/musb/tusb6010_omap.c
+++ b/drivers/usb/musb/tusb6010_omap.c
@@ -661,8 +661,7 @@ void dma_controller_destroy(struct dma_controller *c)
kfree(tusb_dma);
}
-struct dma_controller *__devinit
-dma_controller_create(struct musb *musb, void __iomem *base)
+struct dma_controller *dma_controller_create(struct musb *musb, void __iomem *base)
{
void __iomem *tbase = musb->ctrl_base;
struct tusb_omap_dma *tusb_dma;
diff --git a/drivers/usb/musb/ux500.c b/drivers/usb/musb/ux500.c
index d62a91fedc22..a27ca1a9c994 100644
--- a/drivers/usb/musb/ux500.c
+++ b/drivers/usb/musb/ux500.c
@@ -36,6 +36,26 @@ struct ux500_glue {
};
#define glue_to_musb(g) platform_get_drvdata(g->musb)
+static irqreturn_t ux500_musb_interrupt(int irq, void *__hci)
+{
+ unsigned long flags;
+ irqreturn_t retval = IRQ_NONE;
+ struct musb *musb = __hci;
+
+ spin_lock_irqsave(&musb->lock, flags);
+
+ musb->int_usb = musb_readb(musb->mregs, MUSB_INTRUSB);
+ musb->int_tx = musb_readw(musb->mregs, MUSB_INTRTX);
+ musb->int_rx = musb_readw(musb->mregs, MUSB_INTRRX);
+
+ if (musb->int_usb || musb->int_tx || musb->int_rx)
+ retval = musb_interrupt(musb);
+
+ spin_unlock_irqrestore(&musb->lock, flags);
+
+ return retval;
+}
+
static int ux500_musb_init(struct musb *musb)
{
musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
@@ -44,6 +64,8 @@ static int ux500_musb_init(struct musb *musb)
return -ENODEV;
}
+ musb->isr = ux500_musb_interrupt;
+
return 0;
}
@@ -59,13 +81,12 @@ static const struct musb_platform_ops ux500_ops = {
.exit = ux500_musb_exit,
};
-static int __devinit ux500_probe(struct platform_device *pdev)
+static int ux500_probe(struct platform_device *pdev)
{
struct musb_hdrc_platform_data *pdata = pdev->dev.platform_data;
struct platform_device *musb;
struct ux500_glue *glue;
struct clk *clk;
-
int ret = -ENOMEM;
glue = kzalloc(sizeof(*glue), GFP_KERNEL);
@@ -74,18 +95,10 @@ static int __devinit ux500_probe(struct platform_device *pdev)
goto err0;
}
- /* get the musb id */
- musbid = musb_get_id(&pdev->dev, GFP_KERNEL);
- if (musbid < 0) {
- dev_err(&pdev->dev, "failed to allocate musb id\n");
- ret = -ENOMEM;
- goto err1;
- }
-
- musb = platform_device_alloc("musb-hdrc", musbid);
+ musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO);
if (!musb) {
dev_err(&pdev->dev, "failed to allocate musb device\n");
- goto err2;
+ goto err1;
}
clk = clk_get(&pdev->dev, "usb");
@@ -101,7 +114,6 @@ static int __devinit ux500_probe(struct platform_device *pdev)
goto err4;
}
- musb->id = musbid;
musb->dev.parent = &pdev->dev;
musb->dev.dma_mask = pdev->dev.dma_mask;
musb->dev.coherent_dma_mask = pdev->dev.coherent_dma_mask;
@@ -144,9 +156,6 @@ err4:
err3:
platform_device_put(musb);
-err2:
- musb_put_id(&pdev->dev, musbid);
-
err1:
kfree(glue);
@@ -154,13 +163,11 @@ err0:
return ret;
}
-static int __devexit ux500_remove(struct platform_device *pdev)
+static int ux500_remove(struct platform_device *pdev)
{
struct ux500_glue *glue = platform_get_drvdata(pdev);
- musb_put_id(&pdev->dev, glue->musb->id);
- platform_device_del(glue->musb);
- platform_device_put(glue->musb);
+ platform_device_unregister(glue->musb);
clk_disable(glue->clk);
clk_put(glue->clk);
kfree(glue);
@@ -209,7 +216,7 @@ static const struct dev_pm_ops ux500_pm_ops = {
static struct platform_driver ux500_driver = {
.probe = ux500_probe,
- .remove = __devexit_p(ux500_remove),
+ .remove = ux500_remove,
.driver = {
.name = "musb-ux500",
.pm = DEV_PM_OPS,
@@ -219,15 +226,4 @@ static struct platform_driver ux500_driver = {
MODULE_DESCRIPTION("UX500 MUSB Glue Layer");
MODULE_AUTHOR("Mian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.com>");
MODULE_LICENSE("GPL v2");
-
-static int __init ux500_init(void)
-{
- return platform_driver_register(&ux500_driver);
-}
-module_init(ux500_init);
-
-static void __exit ux500_exit(void)
-{
- platform_driver_unregister(&ux500_driver);
-}
-module_exit(ux500_exit);
+module_platform_driver(ux500_driver);
diff --git a/drivers/usb/musb/ux500_dma.c b/drivers/usb/musb/ux500_dma.c
index f1059e725ea8..039e567dd3b6 100644
--- a/drivers/usb/musb/ux500_dma.c
+++ b/drivers/usb/musb/ux500_dma.c
@@ -364,8 +364,7 @@ void dma_controller_destroy(struct dma_controller *c)
kfree(controller);
}
-struct dma_controller *__devinit
-dma_controller_create(struct musb *musb, void __iomem *base)
+struct dma_controller *dma_controller_create(struct musb *musb, void __iomem *base)
{
struct ux500_dma_controller *controller;
struct platform_device *pdev = to_platform_device(musb->controller);
diff --git a/drivers/usb/otg/Kconfig b/drivers/usb/otg/Kconfig
index d8c8a42bff3e..6223062d5d1b 100644
--- a/drivers/usb/otg/Kconfig
+++ b/drivers/usb/otg/Kconfig
@@ -58,7 +58,7 @@ config USB_ULPI_VIEWPORT
config TWL4030_USB
tristate "TWL4030 USB Transceiver Driver"
- depends on TWL4030_CORE && REGULATOR_TWL4030
+ depends on TWL4030_CORE && REGULATOR_TWL4030 && USB_MUSB_OMAP2PLUS
select USB_OTG_UTILS
help
Enable this to support the USB OTG transceiver on TWL4030
@@ -68,7 +68,7 @@ config TWL4030_USB
config TWL6030_USB
tristate "TWL6030 USB Transceiver Driver"
- depends on TWL4030_CORE && OMAP_USB2
+ depends on TWL4030_CORE && OMAP_USB2 && USB_MUSB_OMAP2PLUS
select USB_OTG_UTILS
help
Enable this to support the USB OTG transceiver on TWL6030
diff --git a/drivers/usb/otg/ab8500-usb.c b/drivers/usb/otg/ab8500-usb.c
index ae8ad561f083..2d86f26a0183 100644
--- a/drivers/usb/otg/ab8500-usb.c
+++ b/drivers/usb/otg/ab8500-usb.c
@@ -468,7 +468,7 @@ static int ab8500_usb_v2_res_setup(struct platform_device *pdev,
return 0;
}
-static int __devinit ab8500_usb_probe(struct platform_device *pdev)
+static int ab8500_usb_probe(struct platform_device *pdev)
{
struct ab8500_usb *ab;
struct usb_otg *otg;
@@ -546,7 +546,7 @@ fail0:
return err;
}
-static int __devexit ab8500_usb_remove(struct platform_device *pdev)
+static int ab8500_usb_remove(struct platform_device *pdev)
{
struct ab8500_usb *ab = platform_get_drvdata(pdev);
@@ -571,7 +571,7 @@ static int __devexit ab8500_usb_remove(struct platform_device *pdev)
static struct platform_driver ab8500_usb_driver = {
.probe = ab8500_usb_probe,
- .remove = __devexit_p(ab8500_usb_remove),
+ .remove = ab8500_usb_remove,
.driver = {
.name = "ab8500-usb",
.owner = THIS_MODULE,
diff --git a/drivers/usb/otg/fsl_otg.c b/drivers/usb/otg/fsl_otg.c
index c19d1d7173a9..d16adb41eb21 100644
--- a/drivers/usb/otg/fsl_otg.c
+++ b/drivers/usb/otg/fsl_otg.c
@@ -1110,7 +1110,7 @@ static const struct file_operations otg_fops = {
.release = fsl_otg_release,
};
-static int __devinit fsl_otg_probe(struct platform_device *pdev)
+static int fsl_otg_probe(struct platform_device *pdev)
{
int ret;
@@ -1144,7 +1144,7 @@ static int __devinit fsl_otg_probe(struct platform_device *pdev)
return ret;
}
-static int __devexit fsl_otg_remove(struct platform_device *pdev)
+static int fsl_otg_remove(struct platform_device *pdev)
{
struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
@@ -1169,7 +1169,7 @@ static int __devexit fsl_otg_remove(struct platform_device *pdev)
struct platform_driver fsl_otg_driver = {
.probe = fsl_otg_probe,
- .remove = __devexit_p(fsl_otg_remove),
+ .remove = fsl_otg_remove,
.driver = {
.name = driver_name,
.owner = THIS_MODULE,
diff --git a/drivers/usb/otg/isp1301_omap.c b/drivers/usb/otg/isp1301_omap.c
index ceee2119bffa..af9cb11626b2 100644
--- a/drivers/usb/otg/isp1301_omap.c
+++ b/drivers/usb/otg/isp1301_omap.c
@@ -1493,7 +1493,7 @@ isp1301_start_hnp(struct usb_otg *otg)
/*-------------------------------------------------------------------------*/
-static int __devinit
+static int
isp1301_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
{
int status;
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index 9f5fc906041a..3b9f0d951132 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -1606,7 +1606,7 @@ free_motg:
return ret;
}
-static int __devexit msm_otg_remove(struct platform_device *pdev)
+static int msm_otg_remove(struct platform_device *pdev)
{
struct msm_otg *motg = platform_get_drvdata(pdev);
struct usb_phy *phy = &motg->phy;
@@ -1746,7 +1746,7 @@ static const struct dev_pm_ops msm_otg_dev_pm_ops = {
#endif
static struct platform_driver msm_otg_driver = {
- .remove = __devexit_p(msm_otg_remove),
+ .remove = msm_otg_remove,
.driver = {
.name = DRIVER_NAME,
.owner = THIS_MODULE,
diff --git a/drivers/usb/otg/mv_otg.c b/drivers/usb/otg/mv_otg.c
index 3f124e8f5792..1dd57504186d 100644
--- a/drivers/usb/otg/mv_otg.c
+++ b/drivers/usb/otg/mv_otg.c
@@ -958,16 +958,4 @@ static struct platform_driver mv_otg_driver = {
.resume = mv_otg_resume,
#endif
};
-
-static int __init mv_otg_init(void)
-{
- return platform_driver_register(&mv_otg_driver);
-}
-
-static void __exit mv_otg_exit(void)
-{
- platform_driver_unregister(&mv_otg_driver);
-}
-
-module_init(mv_otg_init);
-module_exit(mv_otg_exit);
+module_platform_driver(mv_otg_driver);
diff --git a/drivers/usb/otg/mxs-phy.c b/drivers/usb/otg/mxs-phy.c
index 88db976647cf..76302720055a 100644
--- a/drivers/usb/otg/mxs-phy.c
+++ b/drivers/usb/otg/mxs-phy.c
@@ -20,7 +20,6 @@
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/io.h>
-#include <linux/workqueue.h>
#define DRIVER_NAME "mxs_phy"
@@ -35,16 +34,9 @@
#define BM_USBPHY_CTRL_ENUTMILEVEL2 BIT(14)
#define BM_USBPHY_CTRL_ENHOSTDISCONDETECT BIT(1)
-/*
- * Amount of delay in miliseconds to safely enable ENHOSTDISCONDETECT bit
- * so that connection and reset processing can be completed for the root hub.
- */
-#define MXY_PHY_ENHOSTDISCONDETECT_DELAY 250
-
struct mxs_phy {
struct usb_phy phy;
struct clk *clk;
- struct delayed_work enhostdiscondetect_work;
};
#define to_mxs_phy(p) container_of((p), struct mxs_phy, phy)
@@ -70,7 +62,6 @@ static int mxs_phy_init(struct usb_phy *phy)
clk_prepare_enable(mxs_phy->clk);
mxs_phy_hw_init(mxs_phy);
- INIT_DELAYED_WORK(&mxs_phy->enhostdiscondetect_work, NULL);
return 0;
}
@@ -85,46 +76,28 @@ static void mxs_phy_shutdown(struct usb_phy *phy)
clk_disable_unprepare(mxs_phy->clk);
}
-static void mxs_phy_enhostdiscondetect_delay(struct work_struct *ws)
+static int mxs_phy_on_connect(struct usb_phy *phy,
+ enum usb_device_speed speed)
{
- struct mxs_phy *mxs_phy = container_of(ws, struct mxs_phy,
- enhostdiscondetect_work.work);
-
- /* Enable HOSTDISCONDETECT after delay. */
- dev_dbg(mxs_phy->phy.dev, "Setting ENHOSTDISCONDETECT\n");
- writel_relaxed(BM_USBPHY_CTRL_ENHOSTDISCONDETECT,
- mxs_phy->phy.io_priv + HW_USBPHY_CTRL_SET);
-}
-
-static int mxs_phy_on_connect(struct usb_phy *phy, int port)
-{
- struct mxs_phy *mxs_phy = to_mxs_phy(phy);
-
- dev_dbg(phy->dev, "Connect on port %d\n", port);
-
- mxs_phy_hw_init(mxs_phy);
+ dev_dbg(phy->dev, "%s speed device has connected\n",
+ (speed == USB_SPEED_HIGH) ? "high" : "non-high");
- /*
- * Delay enabling ENHOSTDISCONDETECT so that connection and
- * reset processing can be completed for the root hub.
- */
- dev_dbg(phy->dev, "Delaying setting ENHOSTDISCONDETECT\n");
- PREPARE_DELAYED_WORK(&mxs_phy->enhostdiscondetect_work,
- mxs_phy_enhostdiscondetect_delay);
- schedule_delayed_work(&mxs_phy->enhostdiscondetect_work,
- msecs_to_jiffies(MXY_PHY_ENHOSTDISCONDETECT_DELAY));
+ if (speed == USB_SPEED_HIGH)
+ writel_relaxed(BM_USBPHY_CTRL_ENHOSTDISCONDETECT,
+ phy->io_priv + HW_USBPHY_CTRL_SET);
return 0;
}
-static int mxs_phy_on_disconnect(struct usb_phy *phy, int port)
+static int mxs_phy_on_disconnect(struct usb_phy *phy,
+ enum usb_device_speed speed)
{
- dev_dbg(phy->dev, "Disconnect on port %d\n", port);
+ dev_dbg(phy->dev, "%s speed device has disconnected\n",
+ (speed == USB_SPEED_HIGH) ? "high" : "non-high");
- /* No need to delay before clearing ENHOSTDISCONDETECT. */
- dev_dbg(phy->dev, "Clearing ENHOSTDISCONDETECT\n");
- writel_relaxed(BM_USBPHY_CTRL_ENHOSTDISCONDETECT,
- phy->io_priv + HW_USBPHY_CTRL_CLR);
+ if (speed == USB_SPEED_HIGH)
+ writel_relaxed(BM_USBPHY_CTRL_ENHOSTDISCONDETECT,
+ phy->io_priv + HW_USBPHY_CTRL_CLR);
return 0;
}
@@ -176,7 +149,7 @@ static int mxs_phy_probe(struct platform_device *pdev)
return 0;
}
-static int __devexit mxs_phy_remove(struct platform_device *pdev)
+static int mxs_phy_remove(struct platform_device *pdev)
{
platform_set_drvdata(pdev, NULL);
@@ -191,7 +164,7 @@ MODULE_DEVICE_TABLE(of, mxs_phy_dt_ids);
static struct platform_driver mxs_phy_driver = {
.probe = mxs_phy_probe,
- .remove = __devexit_p(mxs_phy_remove),
+ .remove = mxs_phy_remove,
.driver = {
.name = DRIVER_NAME,
.owner = THIS_MODULE,
diff --git a/drivers/usb/otg/nop-usb-xceiv.c b/drivers/usb/otg/nop-usb-xceiv.c
index e52e35e7adaf..a3ce24b94a73 100644
--- a/drivers/usb/otg/nop-usb-xceiv.c
+++ b/drivers/usb/otg/nop-usb-xceiv.c
@@ -93,7 +93,7 @@ static int nop_set_host(struct usb_otg *otg, struct usb_bus *host)
return 0;
}
-static int __devinit nop_usb_xceiv_probe(struct platform_device *pdev)
+static int nop_usb_xceiv_probe(struct platform_device *pdev)
{
struct nop_usb_xceiv_platform_data *pdata = pdev->dev.platform_data;
struct nop_usb_xceiv *nop;
@@ -141,7 +141,7 @@ exit:
return err;
}
-static int __devexit nop_usb_xceiv_remove(struct platform_device *pdev)
+static int nop_usb_xceiv_remove(struct platform_device *pdev)
{
struct nop_usb_xceiv *nop = platform_get_drvdata(pdev);
@@ -156,7 +156,7 @@ static int __devexit nop_usb_xceiv_remove(struct platform_device *pdev)
static struct platform_driver nop_usb_xceiv_driver = {
.probe = nop_usb_xceiv_probe,
- .remove = __devexit_p(nop_usb_xceiv_remove),
+ .remove = nop_usb_xceiv_remove,
.driver = {
.name = "nop_usb_xceiv",
.owner = THIS_MODULE,
diff --git a/drivers/usb/otg/twl4030-usb.c b/drivers/usb/otg/twl4030-usb.c
index f0d2e7530cfe..0a701938ab53 100644
--- a/drivers/usb/otg/twl4030-usb.c
+++ b/drivers/usb/otg/twl4030-usb.c
@@ -123,10 +123,10 @@
#define PHY_CLK_CTRL_STS 0xFF
#define PHY_DPLL_CLK (1 << 0)
-/* In module TWL4030_MODULE_PM_MASTER */
+/* In module TWL_MODULE_PM_MASTER */
#define STS_HW_CONDITIONS 0x0F
-/* In module TWL4030_MODULE_PM_RECEIVER */
+/* In module TWL_MODULE_PM_RECEIVER */
#define VUSB_DEDICATED1 0x7D
#define VUSB_DEDICATED2 0x7E
#define VUSB1V5_DEV_GRP 0x71
@@ -195,14 +195,14 @@ static int twl4030_i2c_write_u8_verify(struct twl4030_usb *twl,
}
#define twl4030_usb_write_verify(twl, address, data) \
- twl4030_i2c_write_u8_verify(twl, TWL4030_MODULE_USB, (data), (address))
+ twl4030_i2c_write_u8_verify(twl, TWL_MODULE_USB, (data), (address))
static inline int twl4030_usb_write(struct twl4030_usb *twl,
u8 address, u8 data)
{
int ret = 0;
- ret = twl_i2c_write_u8(TWL4030_MODULE_USB, data, address);
+ ret = twl_i2c_write_u8(TWL_MODULE_USB, data, address);
if (ret < 0)
dev_dbg(twl->dev,
"TWL4030:USB:Write[0x%x] Error %d\n", address, ret);
@@ -227,7 +227,7 @@ static inline int twl4030_readb(struct twl4030_usb *twl, u8 module, u8 address)
static inline int twl4030_usb_read(struct twl4030_usb *twl, u8 address)
{
- return twl4030_readb(twl, TWL4030_MODULE_USB, address);
+ return twl4030_readb(twl, TWL_MODULE_USB, address);
}
/*-------------------------------------------------------------------------*/
@@ -264,8 +264,7 @@ static enum omap_musb_vbus_id_status
* signal is active, the OTG module is activated, and
* its interrupt may be raised (may wake the system).
*/
- status = twl4030_readb(twl, TWL4030_MODULE_PM_MASTER,
- STS_HW_CONDITIONS);
+ status = twl4030_readb(twl, TWL_MODULE_PM_MASTER, STS_HW_CONDITIONS);
if (status < 0)
dev_err(twl->dev, "USB link status err %d\n", status);
else if (status & (BIT(7) | BIT(2))) {
@@ -372,8 +371,7 @@ static void twl4030_phy_power(struct twl4030_usb *twl, int on)
* SLEEP. We work around this by clearing the bit after usv3v1
* is re-activated. This ensures that VUSB3V1 is really active.
*/
- twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0,
- VUSB_DEDICATED2);
+ twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB_DEDICATED2);
regulator_enable(twl->usb1v5);
__twl4030_phy_power(twl, 1);
twl4030_usb_write(twl, PHY_CLK_CTRL,
@@ -419,50 +417,48 @@ static void twl4030_phy_resume(struct twl4030_usb *twl)
static int twl4030_usb_ldo_init(struct twl4030_usb *twl)
{
/* Enable writing to power configuration registers */
- twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER,
- TWL4030_PM_MASTER_KEY_CFG1,
- TWL4030_PM_MASTER_PROTECT_KEY);
+ twl_i2c_write_u8(TWL_MODULE_PM_MASTER, TWL4030_PM_MASTER_KEY_CFG1,
+ TWL4030_PM_MASTER_PROTECT_KEY);
- twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER,
- TWL4030_PM_MASTER_KEY_CFG2,
- TWL4030_PM_MASTER_PROTECT_KEY);
+ twl_i2c_write_u8(TWL_MODULE_PM_MASTER, TWL4030_PM_MASTER_KEY_CFG2,
+ TWL4030_PM_MASTER_PROTECT_KEY);
/* Keep VUSB3V1 LDO in sleep state until VBUS/ID change detected*/
- /*twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB_DEDICATED2);*/
+ /*twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB_DEDICATED2);*/
/* input to VUSB3V1 LDO is from VBAT, not VBUS */
- twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x14, VUSB_DEDICATED1);
+ twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0x14, VUSB_DEDICATED1);
/* Initialize 3.1V regulator */
- twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB3V1_DEV_GRP);
+ twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB3V1_DEV_GRP);
twl->usb3v1 = regulator_get(twl->dev, "usb3v1");
if (IS_ERR(twl->usb3v1))
return -ENODEV;
- twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB3V1_TYPE);
+ twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB3V1_TYPE);
/* Initialize 1.5V regulator */
- twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V5_DEV_GRP);
+ twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB1V5_DEV_GRP);
twl->usb1v5 = regulator_get(twl->dev, "usb1v5");
if (IS_ERR(twl->usb1v5))
goto fail1;
- twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V5_TYPE);
+ twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB1V5_TYPE);
/* Initialize 1.8V regulator */
- twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V8_DEV_GRP);
+ twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB1V8_DEV_GRP);
twl->usb1v8 = regulator_get(twl->dev, "usb1v8");
if (IS_ERR(twl->usb1v8))
goto fail2;
- twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V8_TYPE);
+ twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB1V8_TYPE);
/* disable access to power configuration registers */
- twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0,
- TWL4030_PM_MASTER_PROTECT_KEY);
+ twl_i2c_write_u8(TWL_MODULE_PM_MASTER, 0,
+ TWL4030_PM_MASTER_PROTECT_KEY);
return 0;
@@ -579,7 +575,7 @@ static int twl4030_set_host(struct usb_otg *otg, struct usb_bus *host)
return 0;
}
-static int __devinit twl4030_usb_probe(struct platform_device *pdev)
+static int twl4030_usb_probe(struct platform_device *pdev)
{
struct twl4030_usb_data *pdata = pdev->dev.platform_data;
struct twl4030_usb *twl;
diff --git a/drivers/usb/otg/twl6030-usb.c b/drivers/usb/otg/twl6030-usb.c
index fcadef7864f1..8cd6cf49bdbd 100644
--- a/drivers/usb/otg/twl6030-usb.c
+++ b/drivers/usb/otg/twl6030-usb.c
@@ -310,7 +310,7 @@ static int twl6030_set_vbus(struct phy_companion *comparator, bool enabled)
return 0;
}
-static int __devinit twl6030_usb_probe(struct platform_device *pdev)
+static int twl6030_usb_probe(struct platform_device *pdev)
{
u32 ret;
struct twl6030_usb *twl;
diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig
index 63c339b3e676..7eb73c561bd2 100644
--- a/drivers/usb/phy/Kconfig
+++ b/drivers/usb/phy/Kconfig
@@ -32,3 +32,15 @@ config MV_U3D_PHY
help
Enable this to support Marvell USB 3.0 phy controller for Marvell
SoC.
+
+config USB_RCAR_PHY
+ tristate "Renesas R-Car USB phy support"
+ depends on USB || USB_GADGET
+ select USB_OTG_UTILS
+ help
+ Say Y here to add support for the Renesas R-Car USB phy driver.
+ This chip is typically used as USB phy for USB host, gadget.
+ This driver supports: R8A7779
+
+ To compile this driver as a module, choose M here: the
+ module will be called rcar-phy.
diff --git a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile
index b069f29f1225..1a579a860a03 100644
--- a/drivers/usb/phy/Makefile
+++ b/drivers/usb/phy/Makefile
@@ -8,3 +8,4 @@ obj-$(CONFIG_OMAP_USB2) += omap-usb2.o
obj-$(CONFIG_USB_ISP1301) += isp1301.o
obj-$(CONFIG_MV_U3D_PHY) += mv_u3d_phy.o
obj-$(CONFIG_USB_EHCI_TEGRA) += tegra_usb_phy.o
+obj-$(CONFIG_USB_RCAR_PHY) += rcar-phy.o
diff --git a/drivers/usb/phy/mv_u3d_phy.c b/drivers/usb/phy/mv_u3d_phy.c
index 9f1c5d3c60ec..eaddbe3d4304 100644
--- a/drivers/usb/phy/mv_u3d_phy.c
+++ b/drivers/usb/phy/mv_u3d_phy.c
@@ -262,7 +262,7 @@ calstart:
return 0;
}
-static int __devinit mv_u3d_phy_probe(struct platform_device *pdev)
+static int mv_u3d_phy_probe(struct platform_device *pdev)
{
struct mv_u3d_phy *mv_u3d_phy;
struct mv_usb_platform_data *pdata;
@@ -331,7 +331,7 @@ static int __exit mv_u3d_phy_remove(struct platform_device *pdev)
static struct platform_driver mv_u3d_phy_driver = {
.probe = mv_u3d_phy_probe,
- .remove = __devexit_p(mv_u3d_phy_remove),
+ .remove = mv_u3d_phy_remove,
.driver = {
.name = "mv-u3d-phy",
.owner = THIS_MODULE,
diff --git a/drivers/usb/phy/omap-usb2.c b/drivers/usb/phy/omap-usb2.c
index 15ab3d6f2e8c..26ae8f49225c 100644
--- a/drivers/usb/phy/omap-usb2.c
+++ b/drivers/usb/phy/omap-usb2.c
@@ -141,7 +141,7 @@ static int omap_usb2_suspend(struct usb_phy *x, int suspend)
return 0;
}
-static int __devinit omap_usb2_probe(struct platform_device *pdev)
+static int omap_usb2_probe(struct platform_device *pdev)
{
struct omap_usb *phy;
struct usb_otg *otg;
@@ -199,7 +199,7 @@ static int __devinit omap_usb2_probe(struct platform_device *pdev)
return 0;
}
-static int __devexit omap_usb2_remove(struct platform_device *pdev)
+static int omap_usb2_remove(struct platform_device *pdev)
{
struct omap_usb *phy = platform_get_drvdata(pdev);
@@ -254,7 +254,7 @@ MODULE_DEVICE_TABLE(of, omap_usb2_id_table);
static struct platform_driver omap_usb2_driver = {
.probe = omap_usb2_probe,
- .remove = __devexit_p(omap_usb2_remove),
+ .remove = omap_usb2_remove,
.driver = {
.name = "omap-usb2",
.owner = THIS_MODULE,
diff --git a/drivers/usb/phy/rcar-phy.c b/drivers/usb/phy/rcar-phy.c
new file mode 100644
index 000000000000..a35681b0c501
--- /dev/null
+++ b/drivers/usb/phy/rcar-phy.c
@@ -0,0 +1,220 @@
+/*
+ * Renesas R-Car USB phy driver
+ *
+ * Copyright (C) 2012 Renesas Solutions Corp.
+ * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/usb/otg.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+#include <linux/module.h>
+
+/* USBH common register */
+#define USBPCTRL0 0x0800
+#define USBPCTRL1 0x0804
+#define USBST 0x0808
+#define USBEH0 0x080C
+#define USBOH0 0x081C
+#define USBCTL0 0x0858
+#define EIIBC1 0x0094
+#define EIIBC2 0x009C
+
+/* USBPCTRL1 */
+#define PHY_RST (1 << 2)
+#define PLL_ENB (1 << 1)
+#define PHY_ENB (1 << 0)
+
+/* USBST */
+#define ST_ACT (1 << 31)
+#define ST_PLL (1 << 30)
+
+struct rcar_usb_phy_priv {
+ struct usb_phy phy;
+ spinlock_t lock;
+
+ void __iomem *reg0;
+ void __iomem *reg1;
+ int counter;
+};
+
+#define usb_phy_to_priv(p) container_of(p, struct rcar_usb_phy_priv, phy)
+
+
+/*
+ * USB initial/install operation.
+ *
+ * This function setup USB phy.
+ * The used value and setting order came from
+ * [USB :: Initial setting] on datasheet.
+ */
+static int rcar_usb_phy_init(struct usb_phy *phy)
+{
+ struct rcar_usb_phy_priv *priv = usb_phy_to_priv(phy);
+ struct device *dev = phy->dev;
+ void __iomem *reg0 = priv->reg0;
+ void __iomem *reg1 = priv->reg1;
+ int i;
+ u32 val;
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->lock, flags);
+ if (priv->counter++ == 0) {
+
+ /*
+ * USB phy start-up
+ */
+
+ /* (1) USB-PHY standby release */
+ iowrite32(PHY_ENB, (reg0 + USBPCTRL1));
+
+ /* (2) start USB-PHY internal PLL */
+ iowrite32(PHY_ENB | PLL_ENB, (reg0 + USBPCTRL1));
+
+ /* (3) USB module status check */
+ for (i = 0; i < 1024; i++) {
+ udelay(10);
+ val = ioread32(reg0 + USBST);
+ if (val == (ST_ACT | ST_PLL))
+ break;
+ }
+
+ if (val != (ST_ACT | ST_PLL)) {
+ dev_err(dev, "USB phy not ready\n");
+ goto phy_init_end;
+ }
+
+ /* (4) USB-PHY reset clear */
+ iowrite32(PHY_ENB | PLL_ENB | PHY_RST, (reg0 + USBPCTRL1));
+
+ /* set platform specific port settings */
+ iowrite32(0x00000000, (reg0 + USBPCTRL0));
+
+ /*
+ * EHCI IP internal buffer setting
+ * EHCI IP internal buffer enable
+ *
+ * These are recommended value of a datasheet
+ * see [USB :: EHCI internal buffer setting]
+ */
+ iowrite32(0x00ff0040, (reg0 + EIIBC1));
+ iowrite32(0x00ff0040, (reg1 + EIIBC1));
+
+ iowrite32(0x00000001, (reg0 + EIIBC2));
+ iowrite32(0x00000001, (reg1 + EIIBC2));
+
+ /*
+ * Bus alignment settings
+ */
+
+ /* (1) EHCI bus alignment (little endian) */
+ iowrite32(0x00000000, (reg0 + USBEH0));
+
+ /* (1) OHCI bus alignment (little endian) */
+ iowrite32(0x00000000, (reg0 + USBOH0));
+ }
+
+phy_init_end:
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ return 0;
+}
+
+static void rcar_usb_phy_shutdown(struct usb_phy *phy)
+{
+ struct rcar_usb_phy_priv *priv = usb_phy_to_priv(phy);
+ void __iomem *reg0 = priv->reg0;
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->lock, flags);
+
+ if (priv->counter-- == 1) { /* last user */
+ iowrite32(0x00000000, (reg0 + USBPCTRL0));
+ iowrite32(0x00000000, (reg0 + USBPCTRL1));
+ }
+
+ spin_unlock_irqrestore(&priv->lock, flags);
+}
+
+static int rcar_usb_phy_probe(struct platform_device *pdev)
+{
+ struct rcar_usb_phy_priv *priv;
+ struct resource *res0, *res1;
+ struct device *dev = &pdev->dev;
+ void __iomem *reg0, *reg1;
+ int ret;
+
+ res0 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ res1 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ if (!res0 || !res1) {
+ dev_err(dev, "Not enough platform resources\n");
+ return -EINVAL;
+ }
+
+ /*
+ * CAUTION
+ *
+ * Because this phy address is also mapped under OHCI/EHCI address area,
+ * this driver can't use devm_request_and_ioremap(dev, res) here
+ */
+ reg0 = devm_ioremap_nocache(dev, res0->start, resource_size(res0));
+ reg1 = devm_ioremap_nocache(dev, res1->start, resource_size(res1));
+ if (!reg0 || !reg1) {
+ dev_err(dev, "ioremap error\n");
+ return -ENOMEM;
+ }
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv) {
+ dev_err(dev, "priv data allocation error\n");
+ return -ENOMEM;
+ }
+
+ priv->reg0 = reg0;
+ priv->reg1 = reg1;
+ priv->counter = 0;
+ priv->phy.dev = dev;
+ priv->phy.label = dev_name(dev);
+ priv->phy.init = rcar_usb_phy_init;
+ priv->phy.shutdown = rcar_usb_phy_shutdown;
+ spin_lock_init(&priv->lock);
+
+ ret = usb_add_phy(&priv->phy, USB_PHY_TYPE_USB2);
+ if (ret < 0) {
+ dev_err(dev, "usb phy addition error\n");
+ return ret;
+ }
+
+ platform_set_drvdata(pdev, priv);
+
+ return ret;
+}
+
+static int rcar_usb_phy_remove(struct platform_device *pdev)
+{
+ struct rcar_usb_phy_priv *priv = platform_get_drvdata(pdev);
+
+ usb_remove_phy(&priv->phy);
+
+ return 0;
+}
+
+static struct platform_driver rcar_usb_phy_driver = {
+ .driver = {
+ .name = "rcar_usb_phy",
+ },
+ .probe = rcar_usb_phy_probe,
+ .remove = rcar_usb_phy_remove,
+};
+
+module_platform_driver(rcar_usb_phy_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Renesas R-Car USB phy");
+MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");
diff --git a/drivers/usb/phy/tegra_usb_phy.c b/drivers/usb/phy/tegra_usb_phy.c
index 987116f9efcd..9d13c81754e0 100644
--- a/drivers/usb/phy/tegra_usb_phy.c
+++ b/drivers/usb/phy/tegra_usb_phy.c
@@ -29,7 +29,9 @@
#include <linux/usb/ulpi.h>
#include <asm/mach-types.h>
#include <linux/usb/tegra_usb_phy.h>
-#include <mach/iomap.h>
+
+#define TEGRA_USB_BASE 0xC5000000
+#define TEGRA_USB_SIZE SZ_16K
#define ULPI_VIEWPORT 0x170
diff --git a/drivers/usb/renesas_usbhs/common.c b/drivers/usb/renesas_usbhs/common.c
index 072edc1cc55f..38bce046f4d0 100644
--- a/drivers/usb/renesas_usbhs/common.c
+++ b/drivers/usb/renesas_usbhs/common.c
@@ -132,6 +132,11 @@ void usbhs_sys_function_ctrl(struct usbhs_priv *priv, int enable)
usbhs_bset(priv, SYSCFG, mask, enable ? val : 0);
}
+void usbhs_sys_function_pullup(struct usbhs_priv *priv, int enable)
+{
+ usbhs_bset(priv, SYSCFG, DPRPU, enable ? DPRPU : 0);
+}
+
void usbhs_sys_set_test_mode(struct usbhs_priv *priv, u16 mode)
{
usbhs_write(priv, TESTMODE, mode);
@@ -551,7 +556,7 @@ probe_end_pipe_exit:
return ret;
}
-static int __devexit usbhs_remove(struct platform_device *pdev)
+static int usbhs_remove(struct platform_device *pdev)
{
struct usbhs_priv *priv = usbhs_pdev_to_priv(pdev);
struct renesas_usbhs_platform_info *info = pdev->dev.platform_data;
@@ -631,7 +636,7 @@ static struct platform_driver renesas_usbhs_driver = {
.pm = &usbhsc_pm_ops,
},
.probe = usbhs_probe,
- .remove = __devexit_p(usbhs_remove),
+ .remove = usbhs_remove,
};
module_platform_driver(renesas_usbhs_driver);
diff --git a/drivers/usb/renesas_usbhs/common.h b/drivers/usb/renesas_usbhs/common.h
index dddf40a59ded..c69dd2fba360 100644
--- a/drivers/usb/renesas_usbhs/common.h
+++ b/drivers/usb/renesas_usbhs/common.h
@@ -285,6 +285,7 @@ void usbhs_bset(struct usbhs_priv *priv, u32 reg, u16 mask, u16 data);
*/
void usbhs_sys_host_ctrl(struct usbhs_priv *priv, int enable);
void usbhs_sys_function_ctrl(struct usbhs_priv *priv, int enable);
+void usbhs_sys_function_pullup(struct usbhs_priv *priv, int enable);
void usbhs_sys_set_test_mode(struct usbhs_priv *priv, u16 mode);
/*
diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c
index c021b202c0f3..9538f0feafe2 100644
--- a/drivers/usb/renesas_usbhs/fifo.c
+++ b/drivers/usb/renesas_usbhs/fifo.c
@@ -163,7 +163,7 @@ static int usbhsf_pkt_handler(struct usbhs_pipe *pipe, int type)
func = pkt->handler->dma_done;
break;
default:
- dev_err(dev, "unknown pkt hander\n");
+ dev_err(dev, "unknown pkt handler\n");
goto __usbhs_pkt_handler_end;
}
@@ -192,8 +192,8 @@ void usbhs_pkt_start(struct usbhs_pipe *pipe)
/*
* irq enable/disable function
*/
-#define usbhsf_irq_empty_ctrl(p, e) usbhsf_irq_callback_ctrl(p, bempsts, e)
-#define usbhsf_irq_ready_ctrl(p, e) usbhsf_irq_callback_ctrl(p, brdysts, e)
+#define usbhsf_irq_empty_ctrl(p, e) usbhsf_irq_callback_ctrl(p, irq_bempsts, e)
+#define usbhsf_irq_ready_ctrl(p, e) usbhsf_irq_callback_ctrl(p, irq_brdysts, e)
#define usbhsf_irq_callback_ctrl(pipe, status, enable) \
({ \
struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); \
@@ -202,9 +202,9 @@ void usbhs_pkt_start(struct usbhs_pipe *pipe)
if (!mod) \
return; \
if (enable) \
- mod->irq_##status |= status; \
+ mod->status |= status; \
else \
- mod->irq_##status &= ~status; \
+ mod->status &= ~status; \
usbhs_irq_callback_update(priv, mod); \
})
@@ -488,6 +488,8 @@ static int usbhsf_pio_try_push(struct usbhs_pkt *pkt, int *is_done)
usbhs_pipe_data_sequence(pipe, pkt->sequence);
pkt->sequence = -1; /* -1 sequence will be ignored */
+ usbhs_pipe_set_trans_count_if_bulk(pipe, pkt->length);
+
ret = usbhsf_fifo_select(pipe, fifo, 1);
if (ret < 0)
return 0;
@@ -594,6 +596,7 @@ static int usbhsf_prepare_pop(struct usbhs_pkt *pkt, int *is_done)
usbhs_pipe_data_sequence(pipe, pkt->sequence);
pkt->sequence = -1; /* -1 sequence will be ignored */
+ usbhs_pipe_set_trans_count_if_bulk(pipe, pkt->length);
usbhs_pipe_enable(pipe);
usbhsf_rx_irq_ctrl(pipe, 1);
@@ -795,6 +798,7 @@ static void xfer_work(struct work_struct *work)
dev_dbg(dev, " %s %d (%d/ %d)\n",
fifo->name, usbhs_pipe_number(pipe), pkt->length, pkt->zero);
+ usbhs_pipe_set_trans_count_if_bulk(pipe, pkt->trans);
usbhs_pipe_enable(pipe);
usbhsf_dma_start(pipe, fifo);
dma_async_issue_pending(chan);
diff --git a/drivers/usb/renesas_usbhs/mod.c b/drivers/usb/renesas_usbhs/mod.c
index 61933a90e5bf..6a030b931a3b 100644
--- a/drivers/usb/renesas_usbhs/mod.c
+++ b/drivers/usb/renesas_usbhs/mod.c
@@ -151,7 +151,7 @@ int usbhs_mod_probe(struct usbhs_priv *priv)
goto mod_init_host_err;
/* irq settings */
- ret = request_irq(priv->irq, usbhs_interrupt,
+ ret = devm_request_irq(dev, priv->irq, usbhs_interrupt,
priv->irqflags, dev_name(dev), priv);
if (ret) {
dev_err(dev, "irq request err\n");
@@ -172,7 +172,6 @@ void usbhs_mod_remove(struct usbhs_priv *priv)
{
usbhs_mod_host_remove(priv);
usbhs_mod_gadget_remove(priv);
- free_irq(priv->irq, priv);
}
/*
diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c b/drivers/usb/renesas_usbhs/mod_gadget.c
index 28478ce26c34..dd41f61893ef 100644
--- a/drivers/usb/renesas_usbhs/mod_gadget.c
+++ b/drivers/usb/renesas_usbhs/mod_gadget.c
@@ -883,6 +883,16 @@ static int usbhsg_get_frame(struct usb_gadget *gadget)
return usbhs_frame_get_num(priv);
}
+static int usbhsg_pullup(struct usb_gadget *gadget, int is_on)
+{
+ struct usbhsg_gpriv *gpriv = usbhsg_gadget_to_gpriv(gadget);
+ struct usbhs_priv *priv = usbhsg_gpriv_to_priv(gpriv);
+
+ usbhs_sys_function_pullup(priv, is_on);
+
+ return 0;
+}
+
static int usbhsg_set_selfpowered(struct usb_gadget *gadget, int is_self)
{
struct usbhsg_gpriv *gpriv = usbhsg_gadget_to_gpriv(gadget);
@@ -900,6 +910,7 @@ static struct usb_gadget_ops usbhsg_gadget_ops = {
.set_selfpowered = usbhsg_set_selfpowered,
.udc_start = usbhsg_gadget_start,
.udc_stop = usbhsg_gadget_stop,
+ .pullup = usbhsg_pullup,
};
static int usbhsg_start(struct usbhs_priv *priv)
diff --git a/drivers/usb/renesas_usbhs/mod_host.c b/drivers/usb/renesas_usbhs/mod_host.c
index 069cd765400c..3d3cd6ca2689 100644
--- a/drivers/usb/renesas_usbhs/mod_host.c
+++ b/drivers/usb/renesas_usbhs/mod_host.c
@@ -85,6 +85,7 @@ struct usbhsh_ep {
struct usbhsh_device *udev; /* attached udev */
struct usb_host_endpoint *ep;
struct list_head ep_list; /* list to usbhsh_device */
+ unsigned int counter; /* pipe attach counter */
};
#define USBHSH_DEVICE_MAX 10 /* see DEVADDn / DCPMAXP / PIPEMAXP */
@@ -271,8 +272,12 @@ static int usbhsh_pipe_attach(struct usbhsh_hpriv *hpriv,
/******************** spin lock ********************/
usbhs_lock(priv, flags);
- if (unlikely(usbhsh_uep_to_pipe(uep))) {
- dev_err(dev, "uep already has pipe\n");
+ /*
+ * if uep has been attached to pipe,
+ * reuse it
+ */
+ if (usbhsh_uep_to_pipe(uep)) {
+ ret = 0;
goto usbhsh_pipe_attach_done;
}
@@ -320,6 +325,9 @@ static int usbhsh_pipe_attach(struct usbhsh_hpriv *hpriv,
}
usbhsh_pipe_attach_done:
+ if (0 == ret)
+ uep->counter++;
+
usbhs_unlock(priv, flags);
/******************** spin unlock ******************/
@@ -346,7 +354,7 @@ static void usbhsh_pipe_detach(struct usbhsh_hpriv *hpriv,
if (unlikely(!pipe)) {
dev_err(dev, "uep doens't have pipe\n");
- } else {
+ } else if (1 == uep->counter--) { /* last user */
struct usb_host_endpoint *ep = usbhsh_uep_to_ep(uep);
struct usbhsh_device *udev = usbhsh_uep_to_udev(uep);
@@ -391,6 +399,7 @@ static int usbhsh_endpoint_attach(struct usbhsh_hpriv *hpriv,
/*
* init endpoint
*/
+ uep->counter = 0;
INIT_LIST_HEAD(&uep->ep_list);
list_add_tail(&uep->ep_list, &udev->ep_list_head);
@@ -686,9 +695,9 @@ static int usbhsh_queue_push(struct usb_hcd *hcd,
}
if (usb_pipein(urb->pipe))
- pipe->handler = &usbhs_fifo_pio_pop_handler;
+ pipe->handler = &usbhs_fifo_dma_pop_handler;
else
- pipe->handler = &usbhs_fifo_pio_push_handler;
+ pipe->handler = &usbhs_fifo_dma_push_handler;
buf = (void *)(urb->transfer_buffer + urb->actual_length);
len = urb->transfer_buffer_length - urb->actual_length;
@@ -921,6 +930,19 @@ static int usbhsh_dcp_queue_push(struct usb_hcd *hcd,
*/
static int usbhsh_dma_map_ctrl(struct usbhs_pkt *pkt, int map)
{
+ if (map) {
+ struct usbhsh_request *ureq = usbhsh_pkt_to_ureq(pkt);
+ struct urb *urb = ureq->urb;
+
+ /* it can not use scatter/gather */
+ if (urb->num_sgs)
+ return -EINVAL;
+
+ pkt->dma = urb->transfer_dma;
+ if (!pkt->dma)
+ return -EINVAL;
+ }
+
return 0;
}
@@ -946,7 +968,6 @@ static int usbhsh_urb_enqueue(struct usb_hcd *hcd,
struct usb_host_endpoint *ep = urb->ep;
struct usbhsh_device *new_udev = NULL;
int is_dir_in = usb_pipein(urb->pipe);
- int i;
int ret;
dev_dbg(dev, "%s (%s)\n", __func__, is_dir_in ? "in" : "out");
@@ -992,13 +1013,7 @@ static int usbhsh_urb_enqueue(struct usb_hcd *hcd,
* attach pipe to endpoint
* see [image of mod_host]
*/
- for (i = 0; i < 1024; i++) {
- ret = usbhsh_pipe_attach(hpriv, urb);
- if (ret < 0)
- msleep(100);
- else
- break;
- }
+ ret = usbhsh_pipe_attach(hpriv, urb);
if (ret < 0) {
dev_err(dev, "pipe attach failed\n");
goto usbhsh_urb_enqueue_error_free_endpoint;
@@ -1072,8 +1087,6 @@ static void usbhsh_endpoint_disable(struct usb_hcd *hcd,
static int usbhsh_hub_status_data(struct usb_hcd *hcd, char *buf)
{
struct usbhsh_hpriv *hpriv = usbhsh_hcd_to_hpriv(hcd);
- struct usbhs_priv *priv = usbhsh_hpriv_to_priv(hpriv);
- struct device *dev = usbhs_priv_to_dev(priv);
int roothub_id = 1; /* only 1 root hub */
/*
@@ -1085,8 +1098,6 @@ static int usbhsh_hub_status_data(struct usb_hcd *hcd, char *buf)
else
*buf = 0;
- dev_dbg(dev, "%s (%02x)\n", __func__, *buf);
-
return !!(*buf);
}
diff --git a/drivers/usb/renesas_usbhs/pipe.c b/drivers/usb/renesas_usbhs/pipe.c
index 122526cfd32b..7926e1c700f1 100644
--- a/drivers/usb/renesas_usbhs/pipe.c
+++ b/drivers/usb/renesas_usbhs/pipe.c
@@ -93,6 +93,82 @@ static void usbhsp_pipe_cfg_set(struct usbhs_pipe *pipe, u16 mask, u16 val)
}
/*
+ * PIPEnTRN/PIPEnTRE functions
+ */
+static void usbhsp_pipe_trn_set(struct usbhs_pipe *pipe, u16 mask, u16 val)
+{
+ struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
+ struct device *dev = usbhs_priv_to_dev(priv);
+ int num = usbhs_pipe_number(pipe);
+ u16 reg;
+
+ /*
+ * It is impossible to calculate address,
+ * since PIPEnTRN addresses were mapped randomly.
+ */
+#define CASE_PIPExTRN(a) \
+ case 0x ## a: \
+ reg = PIPE ## a ## TRN; \
+ break;
+
+ switch (num) {
+ CASE_PIPExTRN(1);
+ CASE_PIPExTRN(2);
+ CASE_PIPExTRN(3);
+ CASE_PIPExTRN(4);
+ CASE_PIPExTRN(5);
+ CASE_PIPExTRN(B);
+ CASE_PIPExTRN(C);
+ CASE_PIPExTRN(D);
+ CASE_PIPExTRN(E);
+ CASE_PIPExTRN(F);
+ CASE_PIPExTRN(9);
+ CASE_PIPExTRN(A);
+ default:
+ dev_err(dev, "unknown pipe (%d)\n", num);
+ return;
+ }
+ __usbhsp_pipe_xxx_set(pipe, 0, reg, mask, val);
+}
+
+static void usbhsp_pipe_tre_set(struct usbhs_pipe *pipe, u16 mask, u16 val)
+{
+ struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
+ struct device *dev = usbhs_priv_to_dev(priv);
+ int num = usbhs_pipe_number(pipe);
+ u16 reg;
+
+ /*
+ * It is impossible to calculate address,
+ * since PIPEnTRE addresses were mapped randomly.
+ */
+#define CASE_PIPExTRE(a) \
+ case 0x ## a: \
+ reg = PIPE ## a ## TRE; \
+ break;
+
+ switch (num) {
+ CASE_PIPExTRE(1);
+ CASE_PIPExTRE(2);
+ CASE_PIPExTRE(3);
+ CASE_PIPExTRE(4);
+ CASE_PIPExTRE(5);
+ CASE_PIPExTRE(B);
+ CASE_PIPExTRE(C);
+ CASE_PIPExTRE(D);
+ CASE_PIPExTRE(E);
+ CASE_PIPExTRE(F);
+ CASE_PIPExTRE(9);
+ CASE_PIPExTRE(A);
+ default:
+ dev_err(dev, "unknown pipe (%d)\n", num);
+ return;
+ }
+
+ __usbhsp_pipe_xxx_set(pipe, 0, reg, mask, val);
+}
+
+/*
* PIPEBUF
*/
static void usbhsp_pipe_buf_set(struct usbhs_pipe *pipe, u16 mask, u16 val)
@@ -264,6 +340,31 @@ int usbhs_pipe_is_stall(struct usbhs_pipe *pipe)
return (int)(pid == PID_STALL10 || pid == PID_STALL11);
}
+void usbhs_pipe_set_trans_count_if_bulk(struct usbhs_pipe *pipe, int len)
+{
+ if (!usbhs_pipe_type_is(pipe, USB_ENDPOINT_XFER_BULK))
+ return;
+
+ /*
+ * clear and disable transfer counter for IN/OUT pipe
+ */
+ usbhsp_pipe_tre_set(pipe, TRCLR | TRENB, TRCLR);
+
+ /*
+ * Only IN direction bulk pipe can use transfer count.
+ * Without using this function,
+ * received data will break if it was large data size.
+ * see PIPEnTRN/PIPEnTRE for detail
+ */
+ if (usbhs_pipe_is_dir_in(pipe)) {
+ int maxp = usbhs_pipe_get_maxpacket(pipe);
+
+ usbhsp_pipe_trn_set(pipe, 0xffff, DIV_ROUND_UP(len, maxp));
+ usbhsp_pipe_tre_set(pipe, TRENB, TRENB); /* enable */
+ }
+}
+
+
/*
* pipe setup
*/
diff --git a/drivers/usb/renesas_usbhs/pipe.h b/drivers/usb/renesas_usbhs/pipe.h
index 3d80c7b1fd1b..b476fde955bf 100644
--- a/drivers/usb/renesas_usbhs/pipe.h
+++ b/drivers/usb/renesas_usbhs/pipe.h
@@ -88,6 +88,7 @@ void usbhs_pipe_enable(struct usbhs_pipe *pipe);
void usbhs_pipe_disable(struct usbhs_pipe *pipe);
void usbhs_pipe_stall(struct usbhs_pipe *pipe);
int usbhs_pipe_is_stall(struct usbhs_pipe *pipe);
+void usbhs_pipe_set_trans_count_if_bulk(struct usbhs_pipe *pipe, int len);
void usbhs_pipe_select_fifo(struct usbhs_pipe *pipe, struct usbhs_fifo *fifo);
void usbhs_pipe_config_update(struct usbhs_pipe *pipe, u16 devsel,
u16 epnum, u16 maxp);
diff --git a/drivers/usb/serial/aircable.c b/drivers/usb/serial/aircable.c
index 54e1bb6372e7..6d110a3bc7e7 100644
--- a/drivers/usb/serial/aircable.c
+++ b/drivers/usb/serial/aircable.c
@@ -68,10 +68,6 @@
#define THROTTLED 0x01
#define ACTUALLY_THROTTLED 0x02
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v2.0"
#define DRIVER_AUTHOR "Naranjo, Manuel Francisco <naranjo.manuel@gmail.com>, Johan Hovold <jhovold@gmail.com>"
#define DRIVER_DESC "AIRcable USB Driver"
@@ -192,5 +188,4 @@ module_usb_serial_driver(serial_drivers, id_table);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_VERSION(DRIVER_VERSION);
MODULE_LICENSE("GPL");
diff --git a/drivers/usb/serial/ark3116.c b/drivers/usb/serial/ark3116.c
index bd50a8a41a0f..a88882c0e237 100644
--- a/drivers/usb/serial/ark3116.c
+++ b/drivers/usb/serial/ark3116.c
@@ -37,11 +37,6 @@
#include <linux/mutex.h>
#include <linux/spinlock.h>
-/*
- * Version information
- */
-
-#define DRIVER_VERSION "v0.7"
#define DRIVER_AUTHOR "Bart Hartgers <bart.hartgers+ark3116@gmail.com>"
#define DRIVER_DESC "USB ARK3116 serial/IrDA driver"
#define DRIVER_DEV_DESC "ARK3116 RS232/IrDA"
diff --git a/drivers/usb/serial/belkin_sa.c b/drivers/usb/serial/belkin_sa.c
index ea29556f0d72..b72a4c166705 100644
--- a/drivers/usb/serial/belkin_sa.c
+++ b/drivers/usb/serial/belkin_sa.c
@@ -37,10 +37,6 @@
#include <linux/usb/serial.h>
#include "belkin_sa.h"
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v1.3"
#define DRIVER_AUTHOR "William Greathouse <wgreathouse@smva.com>"
#define DRIVER_DESC "USB Belkin Serial converter driver"
@@ -509,5 +505,4 @@ module_usb_serial_driver(serial_drivers, id_table);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_VERSION(DRIVER_VERSION);
MODULE_LICENSE("GPL");
diff --git a/drivers/usb/serial/bus.c b/drivers/usb/serial/bus.c
index c15f2e7cefc7..37decb13d7eb 100644
--- a/drivers/usb/serial/bus.c
+++ b/drivers/usb/serial/bus.c
@@ -121,7 +121,6 @@ static int usb_serial_device_remove(struct device *dev)
return retval;
}
-#ifdef CONFIG_HOTPLUG
static ssize_t store_new_id(struct device_driver *driver,
const char *buf, size_t count)
{
@@ -159,15 +158,6 @@ static void free_dynids(struct usb_serial_driver *drv)
spin_unlock(&drv->dynids.lock);
}
-#else
-static struct driver_attribute drv_attrs[] = {
- __ATTR_NULL,
-};
-static inline void free_dynids(struct usb_serial_driver *drv)
-{
-}
-#endif
-
struct bus_type usb_serial_bus_type = {
.name = "usb-serial",
.match = usb_serial_device_match,
diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c
index eb033fc92a15..f14736f647ff 100644
--- a/drivers/usb/serial/cp210x.c
+++ b/drivers/usb/serial/cp210x.c
@@ -24,10 +24,6 @@
#include <linux/uaccess.h>
#include <linux/usb/serial.h>
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v0.09"
#define DRIVER_DESC "Silicon Labs CP210x RS232 serial adaptor driver"
/*
@@ -35,8 +31,7 @@
*/
static int cp210x_open(struct tty_struct *tty, struct usb_serial_port *);
static void cp210x_close(struct usb_serial_port *);
-static void cp210x_get_termios(struct tty_struct *,
- struct usb_serial_port *port);
+static void cp210x_get_termios(struct tty_struct *, struct usb_serial_port *);
static void cp210x_get_termios_port(struct usb_serial_port *port,
unsigned int *cflagp, unsigned int *baudp);
static void cp210x_change_speed(struct tty_struct *, struct usb_serial_port *,
@@ -118,6 +113,7 @@ static const struct usb_device_id id_table[] = {
{ USB_DEVICE(0x10C4, 0x8477) }, /* Balluff RFID */
{ USB_DEVICE(0x10C4, 0x85EA) }, /* AC-Services IBUS-IF */
{ USB_DEVICE(0x10C4, 0x85EB) }, /* AC-Services CIS-IBUS */
+ { USB_DEVICE(0x10C4, 0x85F8) }, /* Virtenio Preon32 */
{ USB_DEVICE(0x10C4, 0x8664) }, /* AC-Services CAN-IF */
{ USB_DEVICE(0x10C4, 0x8665) }, /* AC-Services OBD-IF */
{ USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */
@@ -169,7 +165,7 @@ struct cp210x_serial_private {
static struct usb_serial_driver cp210x_device = {
.driver = {
.owner = THIS_MODULE,
- .name = "cp210x",
+ .name = "cp210x",
},
.id_table = id_table,
.num_ports = 1,
@@ -179,7 +175,7 @@ static struct usb_serial_driver cp210x_device = {
.close = cp210x_close,
.break_ctl = cp210x_break_ctl,
.set_termios = cp210x_set_termios,
- .tiocmget = cp210x_tiocmget,
+ .tiocmget = cp210x_tiocmget,
.tiocmset = cp210x_tiocmset,
.attach = cp210x_startup,
.release = cp210x_release,
@@ -281,7 +277,7 @@ static int cp210x_get_config(struct usb_serial_port *port, u8 request,
int result, i, length;
/* Number of integers required to contain the array */
- length = (((size - 1) | 3) + 1)/4;
+ length = (((size - 1) | 3) + 1) / 4;
buf = kcalloc(length, sizeof(__le32), GFP_KERNEL);
if (!buf) {
@@ -328,12 +324,11 @@ static int cp210x_set_config(struct usb_serial_port *port, u8 request,
int result, i, length;
/* Number of integers required to contain the array */
- length = (((size - 1) | 3) + 1)/4;
+ length = (((size - 1) | 3) + 1) / 4;
buf = kmalloc(length * sizeof(__le32), GFP_KERNEL);
if (!buf) {
- dev_err(&port->dev, "%s - out of memory.\n",
- __func__);
+ dev_err(&port->dev, "%s - out of memory.\n", __func__);
return -ENOMEM;
}
@@ -384,7 +379,8 @@ static inline int cp210x_set_config_single(struct usb_serial_port *port,
* cp210x_quantise_baudrate
* Quantises the baud rate as per AN205 Table 1
*/
-static unsigned int cp210x_quantise_baudrate(unsigned int baud) {
+static unsigned int cp210x_quantise_baudrate(unsigned int baud)
+{
if (baud <= 300)
baud = 300;
else if (baud <= 600) baud = 600;
@@ -467,9 +463,7 @@ static void cp210x_get_termios(struct tty_struct *tty,
cp210x_get_termios_port(tty->driver_data,
&tty->termios.c_cflag, &baud);
tty_encode_baud_rate(tty, baud, baud);
- }
-
- else {
+ } else {
unsigned int cflag;
cflag = 0;
cp210x_get_termios_port(port, &cflag, &baud);
@@ -693,8 +687,8 @@ static void cp210x_set_termios(struct tty_struct *tty,
break;*/
default:
dev_dbg(dev, "cp210x driver does not support the number of bits requested, using 8 bit mode\n");
- bits |= BITS_DATA_8;
- break;
+ bits |= BITS_DATA_8;
+ break;
}
if (cp210x_set_config(port, CP210X_SET_LINE_CTL, &bits, 2))
dev_dbg(dev, "Number of data bits requested not supported by device\n");
@@ -767,7 +761,7 @@ static void cp210x_set_termios(struct tty_struct *tty,
}
-static int cp210x_tiocmset (struct tty_struct *tty,
+static int cp210x_tiocmset(struct tty_struct *tty,
unsigned int set, unsigned int clear)
{
struct usb_serial_port *port = tty->driver_data;
@@ -809,7 +803,7 @@ static void cp210x_dtr_rts(struct usb_serial_port *p, int on)
cp210x_tiocmset_port(p, 0, TIOCM_DTR|TIOCM_RTS);
}
-static int cp210x_tiocmget (struct tty_struct *tty)
+static int cp210x_tiocmget(struct tty_struct *tty)
{
struct usb_serial_port *port = tty->driver_data;
unsigned int control;
@@ -829,7 +823,7 @@ static int cp210x_tiocmget (struct tty_struct *tty)
return result;
}
-static void cp210x_break_ctl (struct tty_struct *tty, int break_state)
+static void cp210x_break_ctl(struct tty_struct *tty, int break_state)
{
struct usb_serial_port *port = tty->driver_data;
unsigned int state;
@@ -874,5 +868,4 @@ static void cp210x_release(struct usb_serial *serial)
module_usb_serial_driver(serial_drivers, id_table);
MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_VERSION(DRIVER_VERSION);
MODULE_LICENSE("GPL");
diff --git a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c
index 4ee77dcbe690..69a4fa1cee25 100644
--- a/drivers/usb/serial/cyberjack.c
+++ b/drivers/usb/serial/cyberjack.c
@@ -43,10 +43,6 @@
#define CYBERJACK_LOCAL_BUF_SIZE 32
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v1.01"
#define DRIVER_AUTHOR "Matthias Bruestle"
#define DRIVER_DESC "REINER SCT cyberJack pinpad/e-com USB Chipcard Reader Driver"
@@ -441,5 +437,4 @@ module_usb_serial_driver(serial_drivers, id_table);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_VERSION(DRIVER_VERSION);
MODULE_LICENSE("GPL");
diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c
index f0da1279c114..fd8c35fd452e 100644
--- a/drivers/usb/serial/cypress_m8.c
+++ b/drivers/usb/serial/cypress_m8.c
@@ -50,10 +50,6 @@ static bool stats;
static int interval;
static bool unstable_bauds;
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v1.10"
#define DRIVER_AUTHOR "Lonnie Mendez <dignome@gmail.com>, Neil Whelchel <koyama@firstlight.net>"
#define DRIVER_DESC "Cypress USB to Serial Driver"
@@ -1303,7 +1299,6 @@ module_usb_serial_driver(serial_drivers, id_table_combined);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_VERSION(DRIVER_VERSION);
MODULE_LICENSE("GPL");
module_param(stats, bool, S_IRUGO | S_IWUSR);
diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c
index b50fa1c6d885..45d4af62967f 100644
--- a/drivers/usb/serial/digi_acceleport.c
+++ b/drivers/usb/serial/digi_acceleport.c
@@ -32,10 +32,6 @@
/* Defines */
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v1.80.1.2"
#define DRIVER_AUTHOR "Peter Berger <pberger@brimson.com>, Al Borchers <borchers@steinerpoint.com>"
#define DRIVER_DESC "Digi AccelePort USB-2/USB-4 Serial Converter driver"
diff --git a/drivers/usb/serial/empeg.c b/drivers/usb/serial/empeg.c
index 43ede4a1e12c..0f658618db13 100644
--- a/drivers/usb/serial/empeg.c
+++ b/drivers/usb/serial/empeg.c
@@ -28,10 +28,6 @@
#include <linux/usb.h>
#include <linux/usb/serial.h>
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v1.3"
#define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>, Gary Brubaker <xavyer@ix.netcom.com>"
#define DRIVER_DESC "USB Empeg Mark I/II Driver"
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index be845873e23d..0a373b3ae96a 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -73,7 +73,6 @@ struct ftdi_private {
char prev_status; /* Used for TIOCMIWAIT */
bool dev_gone; /* Used to abort TIOCMIWAIT */
char transmit_empty; /* If transmitter is empty or not */
- struct usb_serial_port *port;
__u16 interface; /* FT2232C, FT2232H or FT4232H port interface
(0 for FT232/245) */
@@ -192,6 +191,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(NEWPORT_VID, NEWPORT_AGILIS_PID) },
{ USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_IOBOARD_PID) },
{ USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_MINI_IOBOARD_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_SPROG_II) },
@@ -923,6 +923,9 @@ static int ftdi_get_icount(struct tty_struct *tty,
static int ftdi_ioctl(struct tty_struct *tty,
unsigned int cmd, unsigned long arg);
static void ftdi_break_ctl(struct tty_struct *tty, int break_state);
+static int ftdi_chars_in_buffer(struct tty_struct *tty);
+static int ftdi_get_modem_status(struct tty_struct *tty,
+ unsigned char status[2]);
static unsigned short int ftdi_232am_baud_base_to_divisor(int baud, int base);
static unsigned short int ftdi_232am_baud_to_divisor(int baud);
@@ -957,6 +960,7 @@ static struct usb_serial_driver ftdi_sio_device = {
.ioctl = ftdi_ioctl,
.set_termios = ftdi_set_termios,
.break_ctl = ftdi_break_ctl,
+ .chars_in_buffer = ftdi_chars_in_buffer,
};
static struct usb_serial_driver * const serial_drivers[] = {
@@ -1090,6 +1094,7 @@ static int update_mctrl(struct usb_serial_port *port, unsigned int set,
__func__,
(set & TIOCM_DTR) ? "HIGH" : (clear & TIOCM_DTR) ? "LOW" : "unchanged",
(set & TIOCM_RTS) ? "HIGH" : (clear & TIOCM_RTS) ? "LOW" : "unchanged");
+ rv = usb_translate_errors(rv);
} else {
dev_dbg(dev, "%s - DTR %s, RTS %s\n", __func__,
(set & TIOCM_DTR) ? "HIGH" : (clear & TIOCM_DTR) ? "LOW" : "unchanged",
@@ -1682,7 +1687,6 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port)
kref_init(&priv->kref);
mutex_init(&priv->cfg_lock);
- memset(&priv->icount, 0x00, sizeof(priv->icount));
init_waitqueue_head(&priv->delta_msr_wait);
priv->flags = ASYNC_LOW_LATENCY;
@@ -1691,7 +1695,6 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port)
if (quirk && quirk->port_probe)
quirk->port_probe(priv);
- priv->port = port;
usb_set_serial_port_data(port, priv);
ftdi_determine_type(port);
@@ -1781,7 +1784,7 @@ static int ftdi_8u2232c_probe(struct usb_serial *serial)
struct usb_device *udev = serial->dev;
if ((udev->manufacturer && !strcmp(udev->manufacturer, "CALAO Systems")) ||
- (udev->product && !strcmp(udev->product, "BeagleBone/XDS100")))
+ (udev->product && !strcmp(udev->product, "BeagleBone/XDS100V2")))
return ftdi_jtag_probe(serial);
return 0;
@@ -2089,6 +2092,29 @@ static void ftdi_break_ctl(struct tty_struct *tty, int break_state)
}
+static int ftdi_chars_in_buffer(struct tty_struct *tty)
+{
+ struct usb_serial_port *port = tty->driver_data;
+ int chars;
+ unsigned char buf[2];
+ int ret;
+
+ chars = usb_serial_generic_chars_in_buffer(tty);
+ if (chars)
+ goto out;
+
+ /* Check if hardware buffer is empty. */
+ ret = ftdi_get_modem_status(tty, buf);
+ if (ret == 2) {
+ if (!(buf[1] & FTDI_RS_TEMT))
+ chars = 1;
+ }
+out:
+ dev_dbg(&port->dev, "%s - %d\n", __func__, chars);
+
+ return chars;
+}
+
/* old_termios contains the original termios settings and tty->termios contains
* the new setting to be used
* WARNING: set_termios calls this with old_termios in kernel space
@@ -2272,7 +2298,14 @@ no_c_cflag_changes:
}
}
-static int ftdi_tiocmget(struct tty_struct *tty)
+/*
+ * Get modem-control status.
+ *
+ * Returns the number of status bytes retrieved (device dependant), or
+ * negative error code.
+ */
+static int ftdi_get_modem_status(struct tty_struct *tty,
+ unsigned char status[2])
{
struct usb_serial_port *port = tty->driver_data;
struct ftdi_private *priv = usb_get_serial_port_data(port);
@@ -2312,16 +2345,43 @@ static int ftdi_tiocmget(struct tty_struct *tty)
FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE,
0, priv->interface,
buf, len, WDR_TIMEOUT);
- if (ret < 0)
+ if (ret < 0) {
+ dev_err(&port->dev, "failed to get modem status: %d\n", ret);
+ ret = usb_translate_errors(ret);
goto out;
+ }
- ret = (buf[0] & FTDI_SIO_DSR_MASK ? TIOCM_DSR : 0) |
- (buf[0] & FTDI_SIO_CTS_MASK ? TIOCM_CTS : 0) |
- (buf[0] & FTDI_SIO_RI_MASK ? TIOCM_RI : 0) |
- (buf[0] & FTDI_SIO_RLSD_MASK ? TIOCM_CD : 0) |
- priv->last_dtr_rts;
+ status[0] = buf[0];
+ if (ret > 1)
+ status[1] = buf[1];
+ else
+ status[1] = 0;
+
+ dev_dbg(&port->dev, "%s - 0x%02x%02x\n", __func__, status[0],
+ status[1]);
out:
kfree(buf);
+
+ return ret;
+}
+
+static int ftdi_tiocmget(struct tty_struct *tty)
+{
+ struct usb_serial_port *port = tty->driver_data;
+ struct ftdi_private *priv = usb_get_serial_port_data(port);
+ unsigned char buf[2];
+ int ret;
+
+ ret = ftdi_get_modem_status(tty, buf);
+ if (ret < 0)
+ return ret;
+
+ ret = (buf[0] & FTDI_SIO_DSR_MASK ? TIOCM_DSR : 0) |
+ (buf[0] & FTDI_SIO_CTS_MASK ? TIOCM_CTS : 0) |
+ (buf[0] & FTDI_SIO_RI_MASK ? TIOCM_RI : 0) |
+ (buf[0] & FTDI_SIO_RLSD_MASK ? TIOCM_CD : 0) |
+ priv->last_dtr_rts;
+
return ret;
}
diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h
index 57c12ef6625e..049b6e715fa4 100644
--- a/drivers/usb/serial/ftdi_sio_ids.h
+++ b/drivers/usb/serial/ftdi_sio_ids.h
@@ -752,6 +752,12 @@
#define TTI_VID 0x103E /* Vendor Id */
#define TTI_QL355P_PID 0x03E8 /* TTi QL355P power supply */
+/*
+ * Newport Cooperation (www.newport.com)
+ */
+#define NEWPORT_VID 0x104D
+#define NEWPORT_AGILIS_PID 0x3000
+
/* Interbiometrics USB I/O Board */
/* Developed for Interbiometrics by Rudolf Gugler */
#define INTERBIOMETRICS_VID 0x1209
diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c
index 296612153ea2..2ea70a631996 100644
--- a/drivers/usb/serial/generic.c
+++ b/drivers/usb/serial/generic.c
@@ -262,6 +262,7 @@ int usb_serial_generic_chars_in_buffer(struct tty_struct *tty)
dev_dbg(&port->dev, "%s - returns %d\n", __func__, chars);
return chars;
}
+EXPORT_SYMBOL_GPL(usb_serial_generic_chars_in_buffer);
static int usb_serial_generic_submit_read_urb(struct usb_serial_port *port,
int index, gfp_t mem_flags)
diff --git a/drivers/usb/serial/hp4x.c b/drivers/usb/serial/hp4x.c
index 0bbaf21a9d1e..2cba60d90c79 100644
--- a/drivers/usb/serial/hp4x.c
+++ b/drivers/usb/serial/hp4x.c
@@ -20,10 +20,6 @@
#include <linux/usb.h>
#include <linux/usb/serial.h>
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v1.00"
#define DRIVER_DESC "HP4x (48/49) Generic Serial driver"
#define HP_VENDOR_ID 0x03f0
@@ -52,5 +48,4 @@ static struct usb_serial_driver * const serial_drivers[] = {
module_usb_serial_driver(serial_drivers, id_table);
MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_VERSION(DRIVER_VERSION);
MODULE_LICENSE("GPL");
diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c
index 5acc0d13864a..7b770c7f8b11 100644
--- a/drivers/usb/serial/io_edgeport.c
+++ b/drivers/usb/serial/io_edgeport.c
@@ -51,10 +51,6 @@
#include "io_ionsp.h" /* info for the iosp messages */
#include "io_16654.h" /* 16654 UART defines */
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v2.7"
#define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com> and David Iacovelli"
#define DRIVER_DESC "Edgeport USB Serial Driver"
diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c
index 60023c2d2a31..58184f3de686 100644
--- a/drivers/usb/serial/io_ti.c
+++ b/drivers/usb/serial/io_ti.c
@@ -40,10 +40,6 @@
#include "io_usbvend.h"
#include "io_ti.h"
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v0.7mode043006"
#define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com> and David Iacovelli"
#define DRIVER_DESC "Edgeport USB Serial Driver"
diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c
index 1068bf22e27e..76c9a847da5d 100644
--- a/drivers/usb/serial/ipaq.c
+++ b/drivers/usb/serial/ipaq.c
@@ -25,11 +25,6 @@
#define KP_RETRIES 100
-/*
- * Version Information
- */
-
-#define DRIVER_VERSION "v1.0"
#define DRIVER_AUTHOR "Ganesh Varadarajan <ganesh@veritas.com>"
#define DRIVER_DESC "USB PocketPC PDA driver"
diff --git a/drivers/usb/serial/ipw.c b/drivers/usb/serial/ipw.c
index 4264821a3b34..155eab14b30e 100644
--- a/drivers/usb/serial/ipw.c
+++ b/drivers/usb/serial/ipw.c
@@ -49,10 +49,6 @@
#include <linux/uaccess.h>
#include "usb-wwan.h"
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v0.4"
#define DRIVER_AUTHOR "Roelf Diedericks"
#define DRIVER_DESC "IPWireless tty driver"
diff --git a/drivers/usb/serial/iuu_phoenix.c b/drivers/usb/serial/iuu_phoenix.c
index cd5533e81de7..1e1fbed65ef2 100644
--- a/drivers/usb/serial/iuu_phoenix.c
+++ b/drivers/usb/serial/iuu_phoenix.c
@@ -32,10 +32,6 @@
#include "iuu_phoenix.h"
#include <linux/random.h>
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v0.12"
#define DRIVER_DESC "Infinity USB Unlimited Phoenix driver"
static const struct usb_device_id id_table[] = {
@@ -1164,7 +1160,7 @@ static ssize_t store_vcc_mode(struct device *dev,
struct iuu_private *priv = usb_get_serial_port_data(port);
unsigned long v;
- if (strict_strtoul(buf, 10, &v)) {
+ if (kstrtoul(buf, 10, &v)) {
dev_err(dev, "%s - vcc_mode: %s is not a unsigned long\n",
__func__, buf);
goto fail_store_vcc_mode;
@@ -1232,8 +1228,6 @@ MODULE_AUTHOR("Alain Degreffe eczema@ecze.com");
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
-MODULE_VERSION(DRIVER_VERSION);
-
module_param(xmas, bool, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(xmas, "Xmas colors enabled or not");
diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c
index 7179b0c5f814..97bc49f68efd 100644
--- a/drivers/usb/serial/keyspan.c
+++ b/drivers/usb/serial/keyspan.c
@@ -44,10 +44,6 @@
#include <linux/usb/ezusb.h>
#include "keyspan.h"
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v1.1.5"
#define DRIVER_AUTHOR "Hugh Blemings <hugh@misc.nu"
#define DRIVER_DESC "Keyspan USB to Serial Converter Driver"
@@ -2430,7 +2426,7 @@ static void keyspan_release(struct usb_serial *serial)
static int keyspan_port_probe(struct usb_serial_port *port)
{
struct usb_serial *serial = port->serial;
- struct keyspan_port_private *s_priv;
+ struct keyspan_serial_private *s_priv;
struct keyspan_port_private *p_priv;
const struct keyspan_device_details *d_details;
struct callbacks *cback;
@@ -2445,7 +2441,6 @@ static int keyspan_port_probe(struct usb_serial_port *port)
if (!p_priv)
return -ENOMEM;
- s_priv = usb_get_serial_data(port->serial);
p_priv->device_details = d_details;
/* Setup values for the various callback routines */
diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c
index bb87e29c4ac2..41b01092af07 100644
--- a/drivers/usb/serial/keyspan_pda.c
+++ b/drivers/usb/serial/keyspan_pda.c
@@ -42,10 +42,6 @@
#undef XIRCOM
#endif
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v1.1"
#define DRIVER_AUTHOR "Brian Warner <warner@lothar.com>"
#define DRIVER_DESC "USB Keyspan PDA Converter driver"
diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c
index 1f4517864cd2..fc9e14a1e9b3 100644
--- a/drivers/usb/serial/kl5kusb105.c
+++ b/drivers/usb/serial/kl5kusb105.c
@@ -49,10 +49,6 @@
#include <linux/usb/serial.h>
#include "kl5kusb105.h"
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v0.4"
#define DRIVER_AUTHOR "Utz-Uwe Haus <haus@uuhaus.de>, Johan Hovold <jhovold@gmail.com>"
#define DRIVER_DESC "KLSI KL5KUSB105 chipset USB->Serial Converter driver"
diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c
index c9ca7a5b12e0..b747ba615d0b 100644
--- a/drivers/usb/serial/kobil_sct.c
+++ b/drivers/usb/serial/kobil_sct.c
@@ -38,8 +38,6 @@
#include <linux/ioctl.h>
#include "kobil_sct.h"
-/* Version Information */
-#define DRIVER_VERSION "21/05/2004"
#define DRIVER_AUTHOR "KOBIL Systems GmbH - http://www.kobil.com"
#define DRIVER_DESC "KOBIL USB Smart Card Terminal Driver (experimental)"
diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c
index 8a2081004107..b6911757c855 100644
--- a/drivers/usb/serial/mct_u232.c
+++ b/drivers/usb/serial/mct_u232.c
@@ -38,10 +38,6 @@
#include <linux/ioctl.h>
#include "mct_u232.h"
-/*
- * Version Information
- */
-#define DRIVER_VERSION "z2.1" /* Linux in-kernel version */
#define DRIVER_AUTHOR "Wolfgang Grandegger <wolfgang@ces.ch>"
#define DRIVER_DESC "Magic Control Technology USB-RS232 converter driver"
diff --git a/drivers/usb/serial/metro-usb.c b/drivers/usb/serial/metro-usb.c
index 6f29c74eb769..3d258448c29a 100644
--- a/drivers/usb/serial/metro-usb.c
+++ b/drivers/usb/serial/metro-usb.c
@@ -20,8 +20,6 @@
#include <linux/uaccess.h>
#include <linux/usb/serial.h>
-/* Version Information */
-#define DRIVER_VERSION "v1.2.0.0"
#define DRIVER_DESC "Metrologic Instruments Inc. - USB-POS driver"
/* Product information. */
diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c
index 75267421aad8..f57a6b1fe787 100644
--- a/drivers/usb/serial/mos7720.c
+++ b/drivers/usb/serial/mos7720.c
@@ -36,10 +36,6 @@
#include <linux/uaccess.h>
#include <linux/parport.h>
-/*
- * Version Information
- */
-#define DRIVER_VERSION "2.1"
#define DRIVER_AUTHOR "Aspire Communications pvt Ltd."
#define DRIVER_DESC "Moschip USB Serial Driver"
diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c
index 1cf3375ec1af..66d9e088d9d9 100644
--- a/drivers/usb/serial/mos7840.c
+++ b/drivers/usb/serial/mos7840.c
@@ -35,10 +35,6 @@
#include <linux/usb/serial.h>
#include <linux/uaccess.h>
-/*
- * Version Information
- */
-#define DRIVER_VERSION "1.3.2"
#define DRIVER_DESC "Moschip 7840/7820 USB Serial Driver"
/*
diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c
index 9ab73d295774..7818af931a48 100644
--- a/drivers/usb/serial/omninet.c
+++ b/drivers/usb/serial/omninet.c
@@ -23,10 +23,6 @@
#include <linux/usb.h>
#include <linux/usb/serial.h>
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v1.1"
#define DRIVER_AUTHOR "Alessandro Zummo"
#define DRIVER_DESC "USB ZyXEL omni.net LCD PLUS Driver"
diff --git a/drivers/usb/serial/opticon.c b/drivers/usb/serial/opticon.c
index 6aba731d4864..c6bfb83efb1e 100644
--- a/drivers/usb/serial/opticon.c
+++ b/drivers/usb/serial/opticon.c
@@ -1,6 +1,7 @@
/*
* Opticon USB barcode to serial driver
*
+ * Copyright (C) 2011 - 2012 Johan Hovold <jhovold@gmail.com>
* Copyright (C) 2011 Martin Jansen <martin.jansen@opticon.com>
* Copyright (C) 2008 - 2009 Greg Kroah-Hartman <gregkh@suse.de>
* Copyright (C) 2008 - 2009 Novell Inc.
@@ -40,114 +41,70 @@ MODULE_DEVICE_TABLE(usb, id_table);
/* This structure holds all of the individual device information */
struct opticon_private {
- struct usb_device *udev;
- struct usb_serial *serial;
- struct usb_serial_port *port;
- unsigned char *bulk_in_buffer;
- struct urb *bulk_read_urb;
- int buffer_size;
- u8 bulk_address;
spinlock_t lock; /* protects the following flags */
- bool throttled;
- bool actually_throttled;
bool rts;
bool cts;
int outstanding_urbs;
};
-
-static void opticon_read_bulk_callback(struct urb *urb)
+static void opticon_process_data_packet(struct usb_serial_port *port,
+ const unsigned char *buf, size_t len)
{
- struct opticon_private *priv = urb->context;
- unsigned char *data = urb->transfer_buffer;
- struct usb_serial_port *port = priv->port;
- int status = urb->status;
struct tty_struct *tty;
- int result;
- int data_length;
+
+ tty = tty_port_tty_get(&port->port);
+ if (!tty)
+ return;
+
+ tty_insert_flip_string(tty, buf, len);
+ tty_flip_buffer_push(tty);
+ tty_kref_put(tty);
+}
+
+static void opticon_process_status_packet(struct usb_serial_port *port,
+ const unsigned char *buf, size_t len)
+{
+ struct opticon_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
- switch (status) {
- case 0:
- /* success */
- break;
- case -ECONNRESET:
- case -ENOENT:
- case -ESHUTDOWN:
- /* this urb is terminated, clean up */
- dev_dbg(&priv->udev->dev, "%s - urb shutting down with status: %d\n",
- __func__, status);
+ spin_lock_irqsave(&priv->lock, flags);
+ if (buf[0] == 0x00)
+ priv->cts = false;
+ else
+ priv->cts = true;
+ spin_unlock_irqrestore(&priv->lock, flags);
+}
+
+static void opticon_process_read_urb(struct urb *urb)
+{
+ struct usb_serial_port *port = urb->context;
+ const unsigned char *hdr = urb->transfer_buffer;
+ const unsigned char *data = hdr + 2;
+ size_t data_len = urb->actual_length - 2;
+
+ if (urb->actual_length <= 2) {
+ dev_dbg(&port->dev, "malformed packet received: %d bytes\n",
+ urb->actual_length);
return;
- default:
- dev_dbg(&priv->udev->dev, "%s - nonzero urb status received: %d\n",
- __func__, status);
- goto exit;
}
-
- usb_serial_debug_data(&port->dev, __func__, urb->actual_length, data);
-
- if (urb->actual_length > 2) {
- data_length = urb->actual_length - 2;
-
- /*
- * Data from the device comes with a 2 byte header:
- *
- * <0x00><0x00>data...
- * This is real data to be sent to the tty layer
- * <0x00><0x01)level
- * This is a CTS level change, the third byte is the CTS
- * value (0 for low, 1 for high).
- */
- if ((data[0] == 0x00) && (data[1] == 0x00)) {
- /* real data, send it to the tty layer */
- tty = tty_port_tty_get(&port->port);
- if (tty) {
- tty_insert_flip_string(tty, data + 2,
- data_length);
- tty_flip_buffer_push(tty);
- tty_kref_put(tty);
- }
- } else {
- if ((data[0] == 0x00) && (data[1] == 0x01)) {
- spin_lock_irqsave(&priv->lock, flags);
- /* CTS status information package */
- if (data[2] == 0x00)
- priv->cts = false;
- else
- priv->cts = true;
- spin_unlock_irqrestore(&priv->lock, flags);
- } else {
- dev_dbg(&priv->udev->dev,
- "Unknown data packet received from the device:"
- " %2x %2x\n",
- data[0], data[1]);
- }
- }
+ /*
+ * Data from the device comes with a 2 byte header:
+ *
+ * <0x00><0x00>data...
+ * This is real data to be sent to the tty layer
+ * <0x00><0x01>level
+ * This is a CTS level change, the third byte is the CTS
+ * value (0 for low, 1 for high).
+ */
+ if ((hdr[0] == 0x00) && (hdr[1] == 0x00)) {
+ opticon_process_data_packet(port, data, data_len);
+ } else if ((hdr[0] == 0x00) && (hdr[1] == 0x01)) {
+ opticon_process_status_packet(port, data, data_len);
} else {
- dev_dbg(&priv->udev->dev,
- "Improper amount of data received from the device, "
- "%d bytes", urb->actual_length);
+ dev_dbg(&port->dev, "unknown packet received: %02x %02x\n",
+ hdr[0], hdr[1]);
}
-
-exit:
- spin_lock(&priv->lock);
-
- /* Continue trying to always read if we should */
- if (!priv->throttled) {
- usb_fill_bulk_urb(priv->bulk_read_urb, priv->udev,
- usb_rcvbulkpipe(priv->udev,
- priv->bulk_address),
- priv->bulk_in_buffer, priv->buffer_size,
- opticon_read_bulk_callback, priv);
- result = usb_submit_urb(priv->bulk_read_urb, GFP_ATOMIC);
- if (result)
- dev_err(&port->dev,
- "%s - failed resubmitting read urb, error %d\n",
- __func__, result);
- } else
- priv->actually_throttled = true;
- spin_unlock(&priv->lock);
}
static int send_control_msg(struct usb_serial_port *port, u8 requesttype,
@@ -175,52 +132,35 @@ static int send_control_msg(struct usb_serial_port *port, u8 requesttype,
static int opticon_open(struct tty_struct *tty, struct usb_serial_port *port)
{
- struct opticon_private *priv = usb_get_serial_data(port->serial);
+ struct opticon_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
- int result = 0;
+ int res;
spin_lock_irqsave(&priv->lock, flags);
- priv->throttled = false;
- priv->actually_throttled = false;
- priv->port = port;
priv->rts = false;
spin_unlock_irqrestore(&priv->lock, flags);
/* Clear RTS line */
send_control_msg(port, CONTROL_RTS, 0);
- /* Setup the read URB and start reading from the device */
- usb_fill_bulk_urb(priv->bulk_read_urb, priv->udev,
- usb_rcvbulkpipe(priv->udev,
- priv->bulk_address),
- priv->bulk_in_buffer, priv->buffer_size,
- opticon_read_bulk_callback, priv);
-
/* clear the halt status of the enpoint */
- usb_clear_halt(priv->udev, priv->bulk_read_urb->pipe);
+ usb_clear_halt(port->serial->dev, port->read_urb->pipe);
+
+ res = usb_serial_generic_open(tty, port);
+ if (!res)
+ return res;
- result = usb_submit_urb(priv->bulk_read_urb, GFP_KERNEL);
- if (result)
- dev_err(&port->dev,
- "%s - failed resubmitting read urb, error %d\n",
- __func__, result);
/* Request CTS line state, sometimes during opening the current
* CTS state can be missed. */
send_control_msg(port, RESEND_CTS_STATE, 1);
- return result;
-}
-
-static void opticon_close(struct usb_serial_port *port)
-{
- struct opticon_private *priv = usb_get_serial_data(port->serial);
- /* shutdown our urbs */
- usb_kill_urb(priv->bulk_read_urb);
+ return res;
}
static void opticon_write_control_callback(struct urb *urb)
{
- struct opticon_private *priv = urb->context;
+ struct usb_serial_port *port = urb->context;
+ struct opticon_private *priv = usb_get_serial_port_data(port);
int status = urb->status;
unsigned long flags;
@@ -231,20 +171,21 @@ static void opticon_write_control_callback(struct urb *urb)
kfree(urb->setup_packet);
if (status)
- dev_dbg(&priv->udev->dev, "%s - nonzero write bulk status received: %d\n",
+ dev_dbg(&port->dev,
+ "%s - non-zero urb status received: %d\n",
__func__, status);
spin_lock_irqsave(&priv->lock, flags);
--priv->outstanding_urbs;
spin_unlock_irqrestore(&priv->lock, flags);
- usb_serial_port_softint(priv->port);
+ usb_serial_port_softint(port);
}
static int opticon_write(struct tty_struct *tty, struct usb_serial_port *port,
const unsigned char *buf, int count)
{
- struct opticon_private *priv = usb_get_serial_data(port->serial);
+ struct opticon_private *priv = usb_get_serial_port_data(port);
struct usb_serial *serial = port->serial;
struct urb *urb;
unsigned char *buffer;
@@ -298,7 +239,7 @@ static int opticon_write(struct tty_struct *tty, struct usb_serial_port *port,
usb_fill_control_urb(urb, serial->dev,
usb_sndctrlpipe(serial->dev, 0),
(unsigned char *)dr, buffer, count,
- opticon_write_control_callback, priv);
+ opticon_write_control_callback, port);
/* send it down the pipe */
status = usb_submit_urb(urb, GFP_ATOMIC);
@@ -331,7 +272,7 @@ error_no_buffer:
static int opticon_write_room(struct tty_struct *tty)
{
struct usb_serial_port *port = tty->driver_data;
- struct opticon_private *priv = usb_get_serial_data(port->serial);
+ struct opticon_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
/*
@@ -350,44 +291,10 @@ static int opticon_write_room(struct tty_struct *tty)
return 2048;
}
-static void opticon_throttle(struct tty_struct *tty)
-{
- struct usb_serial_port *port = tty->driver_data;
- struct opticon_private *priv = usb_get_serial_data(port->serial);
- unsigned long flags;
-
- spin_lock_irqsave(&priv->lock, flags);
- priv->throttled = true;
- spin_unlock_irqrestore(&priv->lock, flags);
-}
-
-
-static void opticon_unthrottle(struct tty_struct *tty)
-{
- struct usb_serial_port *port = tty->driver_data;
- struct opticon_private *priv = usb_get_serial_data(port->serial);
- unsigned long flags;
- int result, was_throttled;
-
- spin_lock_irqsave(&priv->lock, flags);
- priv->throttled = false;
- was_throttled = priv->actually_throttled;
- priv->actually_throttled = false;
- spin_unlock_irqrestore(&priv->lock, flags);
-
- if (was_throttled) {
- result = usb_submit_urb(priv->bulk_read_urb, GFP_ATOMIC);
- if (result)
- dev_err(&port->dev,
- "%s - failed submitting read urb, error %d\n",
- __func__, result);
- }
-}
-
static int opticon_tiocmget(struct tty_struct *tty)
{
struct usb_serial_port *port = tty->driver_data;
- struct opticon_private *priv = usb_get_serial_data(port->serial);
+ struct opticon_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
int result = 0;
@@ -407,7 +314,7 @@ static int opticon_tiocmset(struct tty_struct *tty,
{
struct usb_serial_port *port = tty->driver_data;
struct usb_serial *serial = port->serial;
- struct opticon_private *priv = usb_get_serial_data(port->serial);
+ struct opticon_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
bool rts;
bool changed = false;
@@ -438,7 +345,7 @@ static int opticon_tiocmset(struct tty_struct *tty,
return ret;
}
-static int get_serial_info(struct opticon_private *priv,
+static int get_serial_info(struct usb_serial_port *port,
struct serial_struct __user *serial)
{
struct serial_struct tmp;
@@ -450,7 +357,7 @@ static int get_serial_info(struct opticon_private *priv,
/* fake emulate a 16550 uart to make userspace code happy */
tmp.type = PORT_16550A;
- tmp.line = priv->serial->minor;
+ tmp.line = port->serial->minor;
tmp.port = 0;
tmp.irq = 0;
tmp.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ;
@@ -468,13 +375,12 @@ static int opticon_ioctl(struct tty_struct *tty,
unsigned int cmd, unsigned long arg)
{
struct usb_serial_port *port = tty->driver_data;
- struct opticon_private *priv = usb_get_serial_data(port->serial);
dev_dbg(&port->dev, "%s - port %d, cmd = 0x%x\n", __func__, port->number, cmd);
switch (cmd) {
case TIOCGSERIAL:
- return get_serial_info(priv,
+ return get_serial_info(port,
(struct serial_struct __user *)arg);
}
@@ -483,106 +389,36 @@ static int opticon_ioctl(struct tty_struct *tty,
static int opticon_startup(struct usb_serial *serial)
{
- struct opticon_private *priv;
- struct usb_host_interface *intf;
- int i;
- int retval = -ENOMEM;
- bool bulk_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__);
- return -ENOMEM;
- }
- spin_lock_init(&priv->lock);
- priv->serial = serial;
- priv->port = serial->port[0];
- priv->udev = serial->dev;
- priv->outstanding_urbs = 0; /* Init the outstanding urbs */
-
- /* find our bulk 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_bulk_in(endpoint))
- continue;
-
- priv->bulk_read_urb = usb_alloc_urb(0, GFP_KERNEL);
- if (!priv->bulk_read_urb) {
- dev_err(&priv->udev->dev, "out of memory\n");
- goto error;
- }
-
- priv->buffer_size = usb_endpoint_maxp(endpoint) * 2;
- priv->bulk_in_buffer = kmalloc(priv->buffer_size, GFP_KERNEL);
- if (!priv->bulk_in_buffer) {
- dev_err(&priv->udev->dev, "out of memory\n");
- goto error;
- }
-
- priv->bulk_address = endpoint->bEndpointAddress;
-
- bulk_in_found = true;
- break;
- }
-
- if (!bulk_in_found) {
- dev_err(&priv->udev->dev,
- "Error - the proper endpoints were not found!\n");
- goto error;
+ if (!serial->num_bulk_in) {
+ dev_err(&serial->dev->dev, "no bulk in endpoint\n");
+ return -ENODEV;
}
- usb_set_serial_data(serial, priv);
return 0;
-
-error:
- usb_free_urb(priv->bulk_read_urb);
- kfree(priv->bulk_in_buffer);
- kfree(priv);
- return retval;
}
-static void opticon_disconnect(struct usb_serial *serial)
+static int opticon_port_probe(struct usb_serial_port *port)
{
- struct opticon_private *priv = usb_get_serial_data(serial);
-
- usb_kill_urb(priv->bulk_read_urb);
- usb_free_urb(priv->bulk_read_urb);
-}
+ struct opticon_private *priv;
-static void opticon_release(struct usb_serial *serial)
-{
- struct opticon_private *priv = usb_get_serial_data(serial);
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
- kfree(priv->bulk_in_buffer);
- kfree(priv);
-}
+ spin_lock_init(&priv->lock);
-static int opticon_suspend(struct usb_serial *serial, pm_message_t message)
-{
- struct opticon_private *priv = usb_get_serial_data(serial);
+ usb_set_serial_port_data(port, priv);
- usb_kill_urb(priv->bulk_read_urb);
return 0;
}
-static int opticon_resume(struct usb_serial *serial)
+static int opticon_port_remove(struct usb_serial_port *port)
{
- struct opticon_private *priv = usb_get_serial_data(serial);
- struct usb_serial_port *port = serial->port[0];
- int result;
-
- mutex_lock(&port->port.mutex);
- /* This is protected by the port mutex against close/open */
- if (test_bit(ASYNCB_INITIALIZED, &port->port.flags))
- result = usb_submit_urb(priv->bulk_read_urb, GFP_NOIO);
- else
- result = 0;
- mutex_unlock(&port->port.mutex);
- return result;
+ struct opticon_private *priv = usb_get_serial_port_data(port);
+
+ kfree(priv);
+
+ return 0;
}
static struct usb_serial_driver opticon_device = {
@@ -592,20 +428,19 @@ static struct usb_serial_driver opticon_device = {
},
.id_table = id_table,
.num_ports = 1,
+ .bulk_in_size = 256,
.attach = opticon_startup,
+ .port_probe = opticon_port_probe,
+ .port_remove = opticon_port_remove,
.open = opticon_open,
- .close = opticon_close,
.write = opticon_write,
.write_room = opticon_write_room,
- .disconnect = opticon_disconnect,
- .release = opticon_release,
- .throttle = opticon_throttle,
- .unthrottle = opticon_unthrottle,
+ .throttle = usb_serial_generic_throttle,
+ .unthrottle = usb_serial_generic_unthrottle,
.ioctl = opticon_ioctl,
.tiocmget = opticon_tiocmget,
.tiocmset = opticon_tiocmset,
- .suspend = opticon_suspend,
- .resume = opticon_resume,
+ .process_read_urb = opticon_process_read_urb,
};
static struct usb_serial_driver * const serial_drivers[] = {
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index 5dee7d61241e..e6f87b76c715 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -28,7 +28,6 @@
device features.
*/
-#define DRIVER_VERSION "v0.7.2"
#define DRIVER_AUTHOR "Matthias Urlichs <smurf@smurf.noris.de>"
#define DRIVER_DESC "USB Driver for GSM modems"
@@ -81,6 +80,7 @@ static void option_instat_callback(struct urb *urb);
#define OPTION_PRODUCT_GTM380_MODEM 0x7201
#define HUAWEI_VENDOR_ID 0x12D1
+#define HUAWEI_PRODUCT_E173 0x140C
#define HUAWEI_PRODUCT_K4505 0x1464
#define HUAWEI_PRODUCT_K3765 0x1465
#define HUAWEI_PRODUCT_K4605 0x14C6
@@ -158,6 +158,7 @@ static void option_instat_callback(struct urb *urb);
#define NOVATELWIRELESS_PRODUCT_EVDO_EMBEDDED_HIGHSPEED 0x8001
#define NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_FULLSPEED 0x9000
#define NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_HIGHSPEED 0x9001
+#define NOVATELWIRELESS_PRODUCT_E362 0x9010
#define NOVATELWIRELESS_PRODUCT_G1 0xA001
#define NOVATELWIRELESS_PRODUCT_G1_M 0xA002
#define NOVATELWIRELESS_PRODUCT_G2 0xA010
@@ -193,6 +194,9 @@ static void option_instat_callback(struct urb *urb);
#define DELL_PRODUCT_5730_MINICARD_TELUS 0x8181
#define DELL_PRODUCT_5730_MINICARD_VZW 0x8182
+#define DELL_PRODUCT_5800_MINICARD_VZW 0x8195 /* Novatel E362 */
+#define DELL_PRODUCT_5800_V2_MINICARD_VZW 0x8196 /* Novatel E362 */
+
#define KYOCERA_VENDOR_ID 0x0c88
#define KYOCERA_PRODUCT_KPC650 0x17da
#define KYOCERA_PRODUCT_KPC680 0x180a
@@ -283,6 +287,7 @@ static void option_instat_callback(struct urb *urb);
/* ALCATEL PRODUCTS */
#define ALCATEL_VENDOR_ID 0x1bbb
#define ALCATEL_PRODUCT_X060S_X200 0x0000
+#define ALCATEL_PRODUCT_X220_X500D 0x0017
#define PIRELLI_VENDOR_ID 0x1266
#define PIRELLI_PRODUCT_C100_1 0x1002
@@ -548,6 +553,8 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE(QUANTA_VENDOR_ID, QUANTA_PRODUCT_GLX) },
{ USB_DEVICE(QUANTA_VENDOR_ID, QUANTA_PRODUCT_GKE) },
{ USB_DEVICE(QUANTA_VENDOR_ID, QUANTA_PRODUCT_GLE) },
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E173, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t) &net_intf1_blacklist },
{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4505, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t) &huawei_cdc12_blacklist },
{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3765, 0xff, 0xff, 0xff),
@@ -706,6 +713,7 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_G2) },
/* Novatel Ovation MC551 a.k.a. Verizon USB551L */
{ USB_DEVICE_AND_INTERFACE_INFO(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC551, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_E362, 0xff, 0xff, 0xff) },
{ USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_H01) },
{ USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_H01A) },
@@ -728,28 +736,30 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5730_MINICARD_SPRINT) }, /* Dell Wireless 5730 Mobile Broadband EVDO/HSPA Mini-Card */
{ USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5730_MINICARD_TELUS) }, /* Dell Wireless 5730 Mobile Broadband EVDO/HSPA Mini-Card */
{ USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5730_MINICARD_VZW) }, /* Dell Wireless 5730 Mobile Broadband EVDO/HSPA Mini-Card */
+ { USB_DEVICE_AND_INTERFACE_INFO(DELL_VENDOR_ID, DELL_PRODUCT_5800_MINICARD_VZW, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(DELL_VENDOR_ID, DELL_PRODUCT_5800_V2_MINICARD_VZW, 0xff, 0xff, 0xff) },
{ USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_E100A) }, /* ADU-E100, ADU-310 */
{ USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_500A) },
{ USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_620UW) },
{ USB_DEVICE(AXESSTEL_VENDOR_ID, AXESSTEL_PRODUCT_MV110H) },
{ USB_DEVICE(YISO_VENDOR_ID, YISO_PRODUCT_U893) },
- { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_C100_1) },
- { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_C100_2) },
- { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1004) },
- { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1005) },
- { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1006) },
- { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1007) },
- { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1008) },
- { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1009) },
- { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100A) },
- { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100B) },
- { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100C) },
- { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100D) },
- { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100E) },
- { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100F) },
- { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1010) },
- { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1011) },
- { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1012) },
+ { USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_C100_1, 0xff) },
+ { USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_C100_2, 0xff) },
+ { USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1004, 0xff) },
+ { USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1005, 0xff) },
+ { USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1006, 0xff) },
+ { USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1007, 0xff) },
+ { USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1008, 0xff) },
+ { USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1009, 0xff) },
+ { USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100A, 0xff) },
+ { USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100B, 0xff) },
+ { USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100C, 0xff) },
+ { USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100D, 0xff) },
+ { USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100E, 0xff) },
+ { USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100F, 0xff) },
+ { USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1010, 0xff) },
+ { USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1011, 0xff) },
+ { USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1012, 0xff) },
{ USB_DEVICE(KYOCERA_VENDOR_ID, KYOCERA_PRODUCT_KPC650) },
{ USB_DEVICE(KYOCERA_VENDOR_ID, KYOCERA_PRODUCT_KPC680) },
{ USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6000)}, /* ZTE AC8700 */
@@ -876,6 +886,10 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0126, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&net_intf5_blacklist },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0128, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0135, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0136, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0137, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0139, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0142, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0143, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0144, 0xff, 0xff, 0xff) },
@@ -896,20 +910,34 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0165, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0167, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&net_intf4_blacklist },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0189, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0191, 0xff, 0xff, 0xff), /* ZTE EuFi890 */
.driver_info = (kernel_ulong_t)&net_intf4_blacklist },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0196, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0197, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0199, 0xff, 0xff, 0xff), /* ZTE MF820S */
.driver_info = (kernel_ulong_t)&net_intf1_blacklist },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0200, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0201, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0254, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0257, 0xff, 0xff, 0xff), /* ZTE MF821 */
.driver_info = (kernel_ulong_t)&net_intf3_blacklist },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0265, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0284, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0317, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0326, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&net_intf4_blacklist },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0330, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0395, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0414, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0417, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1008, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&net_intf4_blacklist },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1010, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&net_intf4_blacklist },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1012, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&net_intf4_blacklist },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1018, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1021, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&net_intf2_blacklist },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1057, 0xff, 0xff, 0xff) },
@@ -1089,6 +1117,10 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1298, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1299, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1300, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1301, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1302, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1303, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1333, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1401, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&net_intf2_blacklist },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1402, 0xff, 0xff, 0xff),
@@ -1157,6 +1189,7 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X060S_X200),
.driver_info = (kernel_ulong_t)&alcatel_x200_blacklist
},
+ { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X220_X500D) },
{ USB_DEVICE(AIRPLUS_VENDOR_ID, AIRPLUS_PRODUCT_MCD650) },
{ USB_DEVICE(TLAYTECH_VENDOR_ID, TLAYTECH_PRODUCT_TEU800) },
{ USB_DEVICE(LONGCHEER_VENDOR_ID, FOUR_G_SYSTEMS_PRODUCT_W14),
@@ -1165,22 +1198,22 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE(LONGCHEER_VENDOR_ID, ZOOM_PRODUCT_4597) },
{ USB_DEVICE(HAIER_VENDOR_ID, HAIER_PRODUCT_CE100) },
/* Pirelli */
- { USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_C100_1)},
- { USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_C100_2)},
- { USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1004)},
- { USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1005)},
- { USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1006)},
- { USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1007)},
- { USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1008)},
- { USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1009)},
- { USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100A)},
- { USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100B) },
- { USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100C) },
- { USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100D) },
- { USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100E) },
- { USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100F) },
- { USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1011)},
- { USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1012)},
+ { USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_C100_1, 0xff) },
+ { USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_C100_2, 0xff) },
+ { USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1004, 0xff) },
+ { USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1005, 0xff) },
+ { USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1006, 0xff) },
+ { USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1007, 0xff) },
+ { USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1008, 0xff) },
+ { USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1009, 0xff) },
+ { USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100A, 0xff) },
+ { USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100B, 0xff) },
+ { USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100C, 0xff) },
+ { USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100D, 0xff) },
+ { USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100E, 0xff) },
+ { USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100F, 0xff) },
+ { USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1011, 0xff) },
+ { USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1012, 0xff) },
/* Cinterion */
{ USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_EU3_E) },
{ USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_EU3_P) },
@@ -1341,20 +1374,10 @@ static int option_probe(struct usb_serial *serial,
&serial->interface->cur_altsetting->desc;
struct usb_device_descriptor *dev_desc = &serial->dev->descriptor;
- /*
- * D-Link DWM 652 still exposes CD-Rom emulation interface in modem
- * mode.
- */
- if (dev_desc->idVendor == DLINK_VENDOR_ID &&
- dev_desc->idProduct == DLINK_PRODUCT_DWM_652 &&
- iface_desc->bInterfaceClass == 0x08)
+ /* Never bind to the CD-Rom emulation interface */
+ if (iface_desc->bInterfaceClass == 0x08)
return -ENODEV;
- /* Bandrich modem and AT command interface is 0xff */
- if ((dev_desc->idVendor == BANDRICH_VENDOR_ID ||
- dev_desc->idVendor == PIRELLI_VENDOR_ID) &&
- iface_desc->bInterfaceClass != 0xff)
- return -ENODEV;
/*
* Don't bind reserved interfaces (like network ones) which often have
* the same class/subclass/protocol as the serial interfaces. Look at
@@ -1369,9 +1392,9 @@ static int option_probe(struct usb_serial *serial,
* Don't bind network interface on Samsung GT-B3730, it is handled by
* a separate module.
*/
- if (dev_desc->idVendor == SAMSUNG_VENDOR_ID &&
- dev_desc->idProduct == SAMSUNG_PRODUCT_GT_B3730 &&
- iface_desc->bInterfaceClass != USB_CLASS_CDC_DATA)
+ if (dev_desc->idVendor == cpu_to_le16(SAMSUNG_VENDOR_ID) &&
+ dev_desc->idProduct == cpu_to_le16(SAMSUNG_PRODUCT_GT_B3730) &&
+ iface_desc->bInterfaceClass != USB_CLASS_CDC_DATA)
return -ENODEV;
/* Store device id so we can use it during attach. */
@@ -1509,5 +1532,4 @@ static int option_send_setup(struct usb_serial_port *port)
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_VERSION(DRIVER_VERSION);
MODULE_LICENSE("GPL");
diff --git a/drivers/usb/serial/oti6858.c b/drivers/usb/serial/oti6858.c
index cee9a52ca891..d217fd6ee43f 100644
--- a/drivers/usb/serial/oti6858.c
+++ b/drivers/usb/serial/oti6858.c
@@ -57,7 +57,6 @@
#define OTI6858_DESCRIPTION \
"Ours Technology Inc. OTi-6858 USB to serial adapter driver"
#define OTI6858_AUTHOR "Tomasz Michal Lukaszewski <FIXME@FIXME>"
-#define OTI6858_VERSION "0.2"
static const struct usb_device_id id_table[] = {
{ USB_DEVICE(OTI6858_VENDOR_ID, OTI6858_PRODUCT_ID) },
@@ -899,5 +898,4 @@ module_usb_serial_driver(serial_drivers, id_table);
MODULE_DESCRIPTION(OTI6858_DESCRIPTION);
MODULE_AUTHOR(OTI6858_AUTHOR);
-MODULE_VERSION(OTI6858_VERSION);
MODULE_LICENSE("GPL");
diff --git a/drivers/usb/serial/quatech2.c b/drivers/usb/serial/quatech2.c
index ffcfc962ab10..d152be97d041 100644
--- a/drivers/usb/serial/quatech2.c
+++ b/drivers/usb/serial/quatech2.c
@@ -65,8 +65,6 @@
#define QT2_WRITE_BUFFER_SIZE 512 /* size of write buffer */
#define QT2_WRITE_CONTROL_SIZE 5 /* control bytes used for a write */
-/* Version Information */
-#define DRIVER_VERSION "v0.1"
#define DRIVER_DESC "Quatech 2nd gen USB to Serial Driver"
#define USB_VENDOR_ID_QUATECH 0x061d
diff --git a/drivers/usb/serial/siemens_mpi.c b/drivers/usb/serial/siemens_mpi.c
index e4a1787cdbac..a76b1ae54a2a 100644
--- a/drivers/usb/serial/siemens_mpi.c
+++ b/drivers/usb/serial/siemens_mpi.c
@@ -16,8 +16,6 @@
#include <linux/usb.h>
#include <linux/usb/serial.h>
-/* Version Information */
-#define DRIVER_VERSION "Version 0.1 09/26/2005"
#define DRIVER_AUTHOR "Thomas Hergenhahn@web.de http://libnodave.sf.net"
#define DRIVER_DESC "Driver for Siemens USB/MPI adapter"
diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c
index 270860f6bb2a..af06f2f5f38b 100644
--- a/drivers/usb/serial/sierra.c
+++ b/drivers/usb/serial/sierra.c
@@ -18,7 +18,7 @@
*/
/* Uncomment to log function calls */
/* #define DEBUG */
-#define DRIVER_VERSION "v.1.7.16"
+
#define DRIVER_AUTHOR "Kevin Lloyd, Elina Pasheva, Matthew Safar, Rory Filer"
#define DRIVER_DESC "USB Driver for Sierra Wireless USB modems"
@@ -1078,7 +1078,6 @@ module_usb_serial_driver(serial_drivers, id_table);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_VERSION(DRIVER_VERSION);
MODULE_LICENSE("GPL");
module_param(nmea, bool, S_IRUGO | S_IWUSR);
diff --git a/drivers/usb/serial/spcp8x5.c b/drivers/usb/serial/spcp8x5.c
index 769c137f8975..a42536af1256 100644
--- a/drivers/usb/serial/spcp8x5.c
+++ b/drivers/usb/serial/spcp8x5.c
@@ -28,9 +28,6 @@
#include <linux/usb.h>
#include <linux/usb/serial.h>
-
-/* Version Information */
-#define DRIVER_VERSION "v0.10"
#define DRIVER_DESC "SPCP8x5 USB to serial adaptor driver"
#define SPCP8x5_007_VID 0x04FC
@@ -651,5 +648,4 @@ static struct usb_serial_driver * const serial_drivers[] = {
module_usb_serial_driver(serial_drivers, id_table);
MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_VERSION(DRIVER_VERSION);
MODULE_LICENSE("GPL");
diff --git a/drivers/usb/serial/ssu100.c b/drivers/usb/serial/ssu100.c
index 868d1e6852e2..4543ea350229 100644
--- a/drivers/usb/serial/ssu100.c
+++ b/drivers/usb/serial/ssu100.c
@@ -46,8 +46,6 @@
#define FULLPWRBIT 0x00000080
#define NEXT_BOARD_POWER_BIT 0x00000004
-/* Version Information */
-#define DRIVER_VERSION "v0.1"
#define DRIVER_DESC "Quatech SSU-100 USB to Serial Driver"
#define USB_VENDOR_ID_QUATECH 0x061d /* Quatech VID */
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index 73b8e0569164..64bda135ba7e 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -597,6 +597,7 @@ static void port_release(struct device *dev)
kfifo_free(&port->write_fifo);
kfree(port->interrupt_in_buffer);
kfree(port->interrupt_out_buffer);
+ tty_port_destroy(&port->port);
kfree(port);
}
diff --git a/drivers/usb/serial/usb_wwan.c b/drivers/usb/serial/usb_wwan.c
index 61a73ad1a187..01c94aada56c 100644
--- a/drivers/usb/serial/usb_wwan.c
+++ b/drivers/usb/serial/usb_wwan.c
@@ -19,7 +19,6 @@
- controlling the baud rate doesn't make sense
*/
-#define DRIVER_VERSION "v0.7.2"
#define DRIVER_AUTHOR "Matthias Urlichs <smurf@smurf.noris.de>"
#define DRIVER_DESC "USB Driver for GSM modems"
@@ -455,9 +454,6 @@ static struct urb *usb_wwan_setup_urb(struct usb_serial_port *port,
struct usb_serial *serial = port->serial;
struct urb *urb;
- if (endpoint == -1)
- return NULL; /* endpoint not needed */
-
urb = usb_alloc_urb(0, GFP_KERNEL); /* No ISO */
if (urb == NULL) {
dev_dbg(&serial->interface->dev,
@@ -489,6 +485,9 @@ int usb_wwan_port_probe(struct usb_serial_port *port)
init_usb_anchor(&portdata->delayed);
for (i = 0; i < N_IN_URB; i++) {
+ if (!port->bulk_in_size)
+ break;
+
buffer = (u8 *)__get_free_page(GFP_KERNEL);
if (!buffer)
goto bail_out_error;
@@ -502,8 +501,8 @@ int usb_wwan_port_probe(struct usb_serial_port *port)
}
for (i = 0; i < N_OUT_URB; i++) {
- if (port->bulk_out_endpointAddress == -1)
- continue;
+ if (!port->bulk_out_size)
+ break;
buffer = kmalloc(OUT_BUFLEN, GFP_KERNEL);
if (!buffer)
@@ -710,5 +709,4 @@ EXPORT_SYMBOL(usb_wwan_resume);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_VERSION(DRIVER_VERSION);
MODULE_LICENSE("GPL");
diff --git a/drivers/usb/serial/vivopay-serial.c b/drivers/usb/serial/vivopay-serial.c
index 0c0aa876c209..6299526ff8c3 100644
--- a/drivers/usb/serial/vivopay-serial.c
+++ b/drivers/usb/serial/vivopay-serial.c
@@ -10,8 +10,6 @@
#include <linux/usb.h>
#include <linux/usb/serial.h>
-
-#define DRIVER_VERSION "v1.0"
#define DRIVER_DESC "ViVOpay USB Serial Driver"
#define VIVOPAY_VENDOR_ID 0x1d5f
@@ -42,5 +40,4 @@ module_usb_serial_driver(serial_drivers, id_table);
MODULE_AUTHOR("Forest Bond <forest.bond@outpostembedded.com>");
MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_VERSION(DRIVER_VERSION);
MODULE_LICENSE("GPL");
diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig
index 0ae7bb64b5ea..eab04a6b5fbc 100644
--- a/drivers/usb/storage/Kconfig
+++ b/drivers/usb/storage/Kconfig
@@ -203,7 +203,7 @@ config USB_STORAGE_ENE_UB6250
config USB_UAS
tristate "USB Attached SCSI"
- depends on USB && SCSI
+ depends on USB && 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/realtek_cr.c b/drivers/usb/storage/realtek_cr.c
index d36446dd7ae8..ea5f2586fbdd 100644
--- a/drivers/usb/storage/realtek_cr.c
+++ b/drivers/usb/storage/realtek_cr.c
@@ -455,7 +455,7 @@ static int rts51x_check_status(struct us_data *us, u8 lun)
u8 buf[16];
retval = rts51x_read_status(us, lun, buf, 16, &(chip->status_len));
- if (retval < 0)
+ if (retval != STATUS_SUCCESS)
return -EIO;
US_DEBUGP("chip->status_len = %d\n", chip->status_len);
diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
index a3d54366afcc..92f35abee92d 100644
--- a/drivers/usb/storage/scsiglue.c
+++ b/drivers/usb/storage/scsiglue.c
@@ -186,6 +186,12 @@ static int slave_configure(struct scsi_device *sdev)
/* Some devices don't handle VPD pages correctly */
sdev->skip_vpd_pages = 1;
+ /* Do not attempt to use REPORT SUPPORTED OPERATION CODES */
+ sdev->no_report_opcodes = 1;
+
+ /* Do not attempt to use WRITE SAME */
+ sdev->no_write_same = 1;
+
/* Some disks return the total number of blocks in response
* to READ CAPACITY rather than the highest block number.
* If this device makes that mistake, tell the sd driver. */
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
index 12aa72630aed..31b3e1a61bbd 100644
--- a/drivers/usb/storage/usb.c
+++ b/drivers/usb/storage/usb.c
@@ -925,7 +925,6 @@ int usb_stor_probe1(struct us_data **pus,
host->max_cmd_len = 16;
host->sg_tablesize = usb_stor_sg_tablesize(intf);
*pus = us = host_to_us(host);
- memset(us, 0, sizeof(struct us_data));
mutex_init(&(us->dev_mutex));
us_set_lock_class(&us->dev_mutex, intf);
init_completion(&us->cmnd_ready);
diff --git a/drivers/usb/usb-skeleton.c b/drivers/usb/usb-skeleton.c
index 0616f235bd6b..ce310170829f 100644
--- a/drivers/usb/usb-skeleton.c
+++ b/drivers/usb/usb-skeleton.c
@@ -105,20 +105,15 @@ static int skel_open(struct inode *inode, struct file *file)
goto exit;
}
- /* increment our usage count for the device */
- kref_get(&dev->kref);
-
- /* lock the device to allow correctly handling errors
- * in resumption */
- mutex_lock(&dev->io_mutex);
-
retval = usb_autopm_get_interface(interface);
if (retval)
- goto out_err;
+ goto exit;
+
+ /* increment our usage count for the device */
+ kref_get(&dev->kref);
/* save our object in the file's private structure */
file->private_data = dev;
- mutex_unlock(&dev->io_mutex);
exit:
return retval;
diff --git a/drivers/usb/wusbcore/devconnect.c b/drivers/usb/wusbcore/devconnect.c
index 231009af65a3..1d365316960c 100644
--- a/drivers/usb/wusbcore/devconnect.c
+++ b/drivers/usb/wusbcore/devconnect.c
@@ -847,19 +847,6 @@ static void wusb_dev_bos_rm(struct wusb_dev *wusb_dev)
wusb_dev->wusb_cap_descr = NULL;
};
-static struct usb_wireless_cap_descriptor wusb_cap_descr_default = {
- .bLength = sizeof(wusb_cap_descr_default),
- .bDescriptorType = USB_DT_DEVICE_CAPABILITY,
- .bDevCapabilityType = USB_CAP_TYPE_WIRELESS_USB,
-
- .bmAttributes = USB_WIRELESS_BEACON_NONE,
- .wPHYRates = cpu_to_le16(USB_WIRELESS_PHY_53),
- .bmTFITXPowerInfo = 0,
- .bmFFITXPowerInfo = 0,
- .bmBandGroup = cpu_to_le16(0x0001), /* WUSB1.0[7.4.1] bottom */
- .bReserved = 0
-};
-
/*
* USB stack's device addition Notifier Callback
*