Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6

* git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6: (141 commits)
  USB: mct_u232: fix broken close
  USB: gadget: amd5536udc.c: fix error path
  USB: imx21-hcd - fix off by one resource size calculation
  usb: gadget: fix Kconfig warning
  usb: r8a66597-udc: Add processing when USB was removed.
  mxc_udc: add workaround for ENGcm09152 for i.MX35
  USB: ftdi_sio: add device ids for ScienceScope
  USB: musb: AM35x: Workaround for fifo read issue
  USB: musb: add musb support for AM35x
  USB: AM35x: Add musb support
  usb: Fix linker errors with CONFIG_PM=n
  USB: ohci-sh - use resource_size instead of defining its own resource_len macro
  USB: isp1362-hcd - use resource_size instead of defining its own resource_len macro
  USB: isp116x-hcd - use resource_size instead of defining its own resource_len macro
  USB: xhci: Fix compile error when CONFIG_PM=n
  USB: accept some invalid ep0-maxpacket values
  USB: xHCI: PCI power management implementation
  USB: xHCI: bus power management implementation
  USB: xHCI: port remote wakeup implementation
  USB: xHCI: port power management implementation
  ...

Manually fix up (non-data) conflict: the SCSI merge gad renamed the
'hw_sector_size' member to 'physical_block_size', and the USB tree
brought a new use of it.
This commit is contained in:
Linus Torvalds 2010-10-22 20:30:48 -07:00
commit 5cc1035062
179 changed files with 9944 additions and 2873 deletions

View File

@ -2554,7 +2554,10 @@ Your cooperation is appreciated.
175 = /dev/usb/legousbtower15 16th USB Legotower device
176 = /dev/usb/usbtmc1 First USB TMC device
...
192 = /dev/usb/usbtmc16 16th USB TMC device
191 = /dev/usb/usbtmc16 16th USB TMC device
192 = /dev/usb/yurex1 First USB Yurex device
...
209 = /dev/usb/yurex16 16th USB Yurex device
240 = /dev/usb/dabusb0 First daubusb device
...
243 = /dev/usb/dabusb3 Fourth dabusb device

View File

@ -8,6 +8,7 @@ and additions :
Required properties :
- compatible : Should be "fsl-usb2-mph" for multi port host USB
controllers, or "fsl-usb2-dr" for dual role USB controllers
or "fsl,mpc5121-usb2-dr" for dual role USB controllers of MPC5121
- phy_type : For multi port host USB controllers, should be one of
"ulpi", or "serial". For dual role USB controllers, should be
one of "ulpi", "utmi", "utmi_wide", or "serial".
@ -33,6 +34,12 @@ Recommended properties :
- interrupt-parent : the phandle for the interrupt controller that
services interrupts for this device.
Optional properties :
- fsl,invert-drvvbus : boolean; for MPC5121 USB0 only. Indicates the
port power polarity of internal PHY signal DRVVBUS is inverted.
- fsl,invert-pwr-fault : boolean; for MPC5121 USB0 only. Indicates
the PWR_FAULT signal polarity is inverted.
Example multi port host USB controller device node :
usb@22000 {
compatible = "fsl-usb2-mph";
@ -57,3 +64,18 @@ Example dual role USB controller device node :
dr_mode = "otg";
phy = "ulpi";
};
Example dual role USB controller device node for MPC5121ADS:
usb@4000 {
compatible = "fsl,mpc5121-usb2-dr";
reg = <0x4000 0x1000>;
#address-cells = <1>;
#size-cells = <0>;
interrupt-parent = < &ipic >;
interrupts = <44 0x8>;
dr_mode = "otg";
phy_type = "utmi_wide";
fsl,invert-drvvbus;
fsl,invert-pwr-fault;
};

View File

@ -1,12 +1,17 @@
/proc/bus/usb filesystem output
===============================
(version 2003.05.30)
(version 2010.09.13)
The usbfs filesystem for USB devices is traditionally mounted at
/proc/bus/usb. It provides the /proc/bus/usb/devices file, as well as
the /proc/bus/usb/BBB/DDD files.
In many modern systems the usbfs filsystem isn't used at all. Instead
USB device nodes are created under /dev/usb/ or someplace similar. The
"devices" file is available in debugfs, typically as
/sys/kernel/debug/usb/devices.
**NOTE**: If /proc/bus/usb appears empty, and a host controller
driver has been linked, then you need to mount the
@ -106,8 +111,8 @@ Legend:
Topology info:
T: Bus=dd Lev=dd Prnt=dd Port=dd Cnt=dd Dev#=ddd Spd=ddd MxCh=dd
| | | | | | | | |__MaxChildren
T: Bus=dd Lev=dd Prnt=dd Port=dd Cnt=dd Dev#=ddd Spd=dddd MxCh=dd
| | | | | | | | |__MaxChildren
| | | | | | | |__Device Speed in Mbps
| | | | | | |__DeviceNumber
| | | | | |__Count of devices at this level
@ -120,8 +125,13 @@ T: Bus=dd Lev=dd Prnt=dd Port=dd Cnt=dd Dev#=ddd Spd=ddd MxCh=dd
Speed may be:
1.5 Mbit/s for low speed USB
12 Mbit/s for full speed USB
480 Mbit/s for high speed USB (added for USB 2.0)
480 Mbit/s for high speed USB (added for USB 2.0);
also used for Wireless USB, which has no fixed speed
5000 Mbit/s for SuperSpeed USB (added for USB 3.0)
For reasons lost in the mists of time, the Port number is always
too low by 1. For example, a device plugged into port 4 will
show up with "Port=03".
Bandwidth info:
B: Alloc=ddd/ddd us (xx%), #Int=ddd, #Iso=ddd
@ -291,7 +301,7 @@ Here's an example, from a system which has a UHCI root hub,
an external hub connected to the root hub, and a mouse and
a serial converter connected to the external hub.
T: Bus=00 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#= 1 Spd=12 MxCh= 2
T: Bus=00 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#= 1 Spd=12 MxCh= 2
B: Alloc= 28/900 us ( 3%), #Int= 2, #Iso= 0
D: Ver= 1.00 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1
P: Vendor=0000 ProdID=0000 Rev= 0.00
@ -301,21 +311,21 @@ C:* #Ifs= 1 Cfg#= 1 Atr=40 MxPwr= 0mA
I: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub
E: Ad=81(I) Atr=03(Int.) MxPS= 8 Ivl=255ms
T: Bus=00 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 2 Spd=12 MxCh= 4
T: Bus=00 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 2 Spd=12 MxCh= 4
D: Ver= 1.00 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1
P: Vendor=0451 ProdID=1446 Rev= 1.00
C:* #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr=100mA
I: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub
E: Ad=81(I) Atr=03(Int.) MxPS= 1 Ivl=255ms
T: Bus=00 Lev=02 Prnt=02 Port=00 Cnt=01 Dev#= 3 Spd=1.5 MxCh= 0
T: Bus=00 Lev=02 Prnt=02 Port=00 Cnt=01 Dev#= 3 Spd=1.5 MxCh= 0
D: Ver= 1.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1
P: Vendor=04b4 ProdID=0001 Rev= 0.00
C:* #Ifs= 1 Cfg#= 1 Atr=80 MxPwr=100mA
I: If#= 0 Alt= 0 #EPs= 1 Cls=03(HID ) Sub=01 Prot=02 Driver=mouse
E: Ad=81(I) Atr=03(Int.) MxPS= 3 Ivl= 10ms
T: Bus=00 Lev=02 Prnt=02 Port=02 Cnt=02 Dev#= 4 Spd=12 MxCh= 0
T: Bus=00 Lev=02 Prnt=02 Port=02 Cnt=02 Dev#= 4 Spd=12 MxCh= 0
D: Ver= 1.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1
P: Vendor=0565 ProdID=0001 Rev= 1.08
S: Manufacturer=Peracom Networks, Inc.
@ -330,12 +340,12 @@ E: Ad=82(I) Atr=03(Int.) MxPS= 8 Ivl= 8ms
Selecting only the "T:" and "I:" lines from this (for example, by using
"procusb ti"), we have:
T: Bus=00 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#= 1 Spd=12 MxCh= 2
T: Bus=00 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 2 Spd=12 MxCh= 4
T: Bus=00 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#= 1 Spd=12 MxCh= 2
T: Bus=00 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 2 Spd=12 MxCh= 4
I: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub
T: Bus=00 Lev=02 Prnt=02 Port=00 Cnt=01 Dev#= 3 Spd=1.5 MxCh= 0
T: Bus=00 Lev=02 Prnt=02 Port=00 Cnt=01 Dev#= 3 Spd=1.5 MxCh= 0
I: If#= 0 Alt= 0 #EPs= 1 Cls=03(HID ) Sub=01 Prot=02 Driver=mouse
T: Bus=00 Lev=02 Prnt=02 Port=02 Cnt=02 Dev#= 4 Spd=12 MxCh= 0
T: Bus=00 Lev=02 Prnt=02 Port=02 Cnt=02 Dev#= 4 Spd=12 MxCh= 0
I: If#= 0 Alt= 0 #EPs= 3 Cls=00(>ifc ) Sub=00 Prot=00 Driver=serial

View File

@ -5973,6 +5973,14 @@ S: Maintained
F: Documentation/usb/acm.txt
F: drivers/usb/class/cdc-acm.*
USB ATTACHED SCSI
M: Matthew Wilcox <willy@linux.intel.com>
M: Sarah Sharp <sarah.a.sharp@linux.intel.com>
L: linux-usb@vger.kernel.org
L: linux-scsi@vger.kernel.org
S: Supported
F: drivers/usb/storage/uas.c
USB BLOCK DRIVER (UB ub)
M: Pete Zaitcev <zaitcev@redhat.com>
L: linux-usb@vger.kernel.org

View File

@ -131,6 +131,7 @@ static struct mxc_usbh_platform_data __maybe_unused usbh1_pdata = {
static struct fsl_usb2_platform_data otg_device_pdata = {
.operating_mode = FSL_USB2_DR_DEVICE,
.phy_mode = FSL_USB2_PHY_UTMI,
.workaround = FLS_USB2_WORKAROUND_ENGCM09152,
};
static int otg_mode_host;

View File

@ -375,6 +375,31 @@ static void __init am3517_evm_init_irq(void)
omap_gpio_init();
}
static struct omap_musb_board_data musb_board_data = {
.interface_type = MUSB_INTERFACE_ULPI,
.mode = MUSB_OTG,
.power = 500,
};
static __init void am3517_evm_musb_init(void)
{
u32 devconf2;
/*
* Set up USB clock/mode in the DEVCONF2 register.
*/
devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2);
/* USB2.0 PHY reference clock is 13 MHz */
devconf2 &= ~(CONF2_REFFREQ | CONF2_OTGMODE | CONF2_PHY_GPIOMODE);
devconf2 |= CONF2_REFFREQ_13MHZ | CONF2_SESENDEN | CONF2_VBDTCTEN
| CONF2_DATPOL;
omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2);
usb_musb_init(&musb_board_data);
}
static const struct ehci_hcd_omap_platform_data ehci_pdata __initconst = {
.port_mode[0] = EHCI_HCD_OMAP_MODE_PHY,
#if defined(CONFIG_PANEL_SHARP_LQ043T1DG01) || \
@ -393,6 +418,8 @@ static const struct ehci_hcd_omap_platform_data ehci_pdata __initconst = {
#ifdef CONFIG_OMAP_MUX
static struct omap_board_mux board_mux[] __initdata = {
/* USB OTG DRVVBUS offset = 0x212 */
OMAP3_MUX(SAD2D_MCAD23, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLDOWN),
{ .reg_offset = OMAP_MUX_TERMINATOR },
};
#else
@ -459,6 +486,9 @@ static void __init am3517_evm_init(void)
ARRAY_SIZE(am3517evm_i2c1_boardinfo));
/*Ethernet*/
am3517_evm_ethernet_init(&am3517_evm_emac_pdata);
/* MUSB */
am3517_evm_musb_init();
}
MACHINE_START(OMAP3517EVM, "OMAP3517/AM3517 EVM")

View File

@ -28,6 +28,7 @@
#include <mach/hardware.h>
#include <mach/irqs.h>
#include <mach/am35xx.h>
#include <plat/usb.h>
#ifdef CONFIG_USB_MUSB_SOC
@ -89,6 +90,9 @@ void __init usb_musb_init(struct omap_musb_board_data *board_data)
{
if (cpu_is_omap243x()) {
musb_resources[0].start = OMAP243X_HS_BASE;
} else if (cpu_is_omap3517() || cpu_is_omap3505()) {
musb_resources[0].start = AM35XX_IPSS_USBOTGSS_BASE;
musb_resources[1].start = INT_35XX_USBOTG_IRQ;
} else if (cpu_is_omap34xx()) {
musb_resources[0].start = OMAP34XX_HSUSB_OTG_BASE;
} else if (cpu_is_omap44xx()) {

View File

@ -218,6 +218,27 @@ static inline omap2_usbfs_init(struct omap_usb_config *pdata)
# define USBT2TLL5PI (1 << 17)
# define USB0PUENACTLOI (1 << 16)
# define USBSTANDBYCTRL (1 << 15)
/* AM35x */
/* USB 2.0 PHY Control */
#define CONF2_PHY_GPIOMODE (1 << 23)
#define CONF2_OTGMODE (3 << 14)
#define CONF2_NO_OVERRIDE (0 << 14)
#define CONF2_FORCE_HOST (1 << 14)
#define CONF2_FORCE_DEVICE (2 << 14)
#define CONF2_FORCE_HOST_VBUS_LOW (3 << 14)
#define CONF2_SESENDEN (1 << 13)
#define CONF2_VBDTCTEN (1 << 12)
#define CONF2_REFFREQ_24MHZ (2 << 8)
#define CONF2_REFFREQ_26MHZ (7 << 8)
#define CONF2_REFFREQ_13MHZ (6 << 8)
#define CONF2_REFFREQ (0xf << 8)
#define CONF2_PHYCLKGD (1 << 7)
#define CONF2_VBUSSENSE (1 << 6)
#define CONF2_PHY_PLLON (1 << 5)
#define CONF2_RESET (1 << 4)
#define CONF2_PHYPWRDN (1 << 3)
#define CONF2_OTGPWRDN (1 << 2)
#define CONF2_DATPOL (1 << 1)
#if defined(CONFIG_ARCH_OMAP1) && defined(CONFIG_USB)
u32 omap1_usb0_init(unsigned nwires, unsigned is_device);

View File

@ -209,169 +209,6 @@ static int __init of_add_fixed_phys(void)
arch_initcall(of_add_fixed_phys);
#endif /* CONFIG_FIXED_PHY */
static enum fsl_usb2_phy_modes determine_usb_phy(const char *phy_type)
{
if (!phy_type)
return FSL_USB2_PHY_NONE;
if (!strcasecmp(phy_type, "ulpi"))
return FSL_USB2_PHY_ULPI;
if (!strcasecmp(phy_type, "utmi"))
return FSL_USB2_PHY_UTMI;
if (!strcasecmp(phy_type, "utmi_wide"))
return FSL_USB2_PHY_UTMI_WIDE;
if (!strcasecmp(phy_type, "serial"))
return FSL_USB2_PHY_SERIAL;
return FSL_USB2_PHY_NONE;
}
static int __init fsl_usb_of_init(void)
{
struct device_node *np;
unsigned int i = 0;
struct platform_device *usb_dev_mph = NULL, *usb_dev_dr_host = NULL,
*usb_dev_dr_client = NULL;
int ret;
for_each_compatible_node(np, NULL, "fsl-usb2-mph") {
struct resource r[2];
struct fsl_usb2_platform_data usb_data;
const unsigned char *prop = NULL;
memset(&r, 0, sizeof(r));
memset(&usb_data, 0, sizeof(usb_data));
ret = of_address_to_resource(np, 0, &r[0]);
if (ret)
goto err;
of_irq_to_resource(np, 0, &r[1]);
usb_dev_mph =
platform_device_register_simple("fsl-ehci", i, r, 2);
if (IS_ERR(usb_dev_mph)) {
ret = PTR_ERR(usb_dev_mph);
goto err;
}
usb_dev_mph->dev.coherent_dma_mask = 0xffffffffUL;
usb_dev_mph->dev.dma_mask = &usb_dev_mph->dev.coherent_dma_mask;
usb_data.operating_mode = FSL_USB2_MPH_HOST;
prop = of_get_property(np, "port0", NULL);
if (prop)
usb_data.port_enables |= FSL_USB2_PORT0_ENABLED;
prop = of_get_property(np, "port1", NULL);
if (prop)
usb_data.port_enables |= FSL_USB2_PORT1_ENABLED;
prop = of_get_property(np, "phy_type", NULL);
usb_data.phy_mode = determine_usb_phy(prop);
ret =
platform_device_add_data(usb_dev_mph, &usb_data,
sizeof(struct
fsl_usb2_platform_data));
if (ret)
goto unreg_mph;
i++;
}
for_each_compatible_node(np, NULL, "fsl-usb2-dr") {
struct resource r[2];
struct fsl_usb2_platform_data usb_data;
const unsigned char *prop = NULL;
if (!of_device_is_available(np))
continue;
memset(&r, 0, sizeof(r));
memset(&usb_data, 0, sizeof(usb_data));
ret = of_address_to_resource(np, 0, &r[0]);
if (ret)
goto unreg_mph;
of_irq_to_resource(np, 0, &r[1]);
prop = of_get_property(np, "dr_mode", NULL);
if (!prop || !strcmp(prop, "host")) {
usb_data.operating_mode = FSL_USB2_DR_HOST;
usb_dev_dr_host = platform_device_register_simple(
"fsl-ehci", i, r, 2);
if (IS_ERR(usb_dev_dr_host)) {
ret = PTR_ERR(usb_dev_dr_host);
goto err;
}
} else if (prop && !strcmp(prop, "peripheral")) {
usb_data.operating_mode = FSL_USB2_DR_DEVICE;
usb_dev_dr_client = platform_device_register_simple(
"fsl-usb2-udc", i, r, 2);
if (IS_ERR(usb_dev_dr_client)) {
ret = PTR_ERR(usb_dev_dr_client);
goto err;
}
} else if (prop && !strcmp(prop, "otg")) {
usb_data.operating_mode = FSL_USB2_DR_OTG;
usb_dev_dr_host = platform_device_register_simple(
"fsl-ehci", i, r, 2);
if (IS_ERR(usb_dev_dr_host)) {
ret = PTR_ERR(usb_dev_dr_host);
goto err;
}
usb_dev_dr_client = platform_device_register_simple(
"fsl-usb2-udc", i, r, 2);
if (IS_ERR(usb_dev_dr_client)) {
ret = PTR_ERR(usb_dev_dr_client);
goto err;
}
} else {
ret = -EINVAL;
goto err;
}
prop = of_get_property(np, "phy_type", NULL);
usb_data.phy_mode = determine_usb_phy(prop);
if (usb_dev_dr_host) {
usb_dev_dr_host->dev.coherent_dma_mask = 0xffffffffUL;
usb_dev_dr_host->dev.dma_mask = &usb_dev_dr_host->
dev.coherent_dma_mask;
if ((ret = platform_device_add_data(usb_dev_dr_host,
&usb_data, sizeof(struct
fsl_usb2_platform_data))))
goto unreg_dr;
}
if (usb_dev_dr_client) {
usb_dev_dr_client->dev.coherent_dma_mask = 0xffffffffUL;
usb_dev_dr_client->dev.dma_mask = &usb_dev_dr_client->
dev.coherent_dma_mask;
if ((ret = platform_device_add_data(usb_dev_dr_client,
&usb_data, sizeof(struct
fsl_usb2_platform_data))))
goto unreg_dr;
}
i++;
}
return 0;
unreg_dr:
if (usb_dev_dr_host)
platform_device_unregister(usb_dev_dr_host);
if (usb_dev_dr_client)
platform_device_unregister(usb_dev_dr_client);
unreg_mph:
if (usb_dev_mph)
platform_device_unregister(usb_dev_mph);
err:
return ret;
}
arch_initcall(fsl_usb_of_init);
#if defined(CONFIG_FSL_SOC_BOOKE) || defined(CONFIG_PPC_86xx)
static __be32 __iomem *rstcr;

View File

@ -397,7 +397,7 @@ static int ub_probe_lun(struct ub_dev *sc, int lnum);
#else
static const struct usb_device_id ub_usb_ids[] = {
{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_SCSI, US_PR_BULK) },
{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, USB_SC_SCSI, USB_PR_BULK) },
{ }
};

View File

@ -1662,6 +1662,7 @@ static const struct hid_device_id hid_ignore_list[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1006) },
{ HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1007) },
{ HID_USB_DEVICE(USB_VENDOR_ID_IMATION, USB_DEVICE_ID_DISC_STAKKA) },
{ HID_USB_DEVICE(USB_VENDOR_ID_JESS, USB_DEVICE_ID_JESS_YUREX) },
{ HID_USB_DEVICE(USB_VENDOR_ID_KBGEAR, USB_DEVICE_ID_KBGEAR_JAMSTUDIO) },
{ HID_USB_DEVICE(USB_VENDOR_ID_KWORLD, USB_DEVICE_ID_KWORLD_RADIO_FM700) },
{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_GPEN_560) },

View File

@ -304,6 +304,9 @@
#define USB_VENDOR_ID_IMATION 0x0718
#define USB_DEVICE_ID_DISC_STAKKA 0xd000
#define USB_VENDOR_ID_JESS 0x0c45
#define USB_DEVICE_ID_JESS_YUREX 0x1010
#define USB_VENDOR_ID_KBGEAR 0x084e
#define USB_DEVICE_ID_KBGEAR_JAMSTUDIO 0x1001

View File

@ -1498,6 +1498,9 @@ static int read_capacity_16(struct scsi_disk *sdkp, struct scsi_device *sdp,
unsigned long long lba;
unsigned sector_size;
if (sdp->no_read_capacity_16)
return -EINVAL;
do {
memset(cmd, 0, 16);
cmd[0] = SERVICE_ACTION_IN;
@ -1626,6 +1629,15 @@ static int read_capacity_10(struct scsi_disk *sdkp, struct scsi_device *sdp,
sector_size = get_unaligned_be32(&buffer[4]);
lba = get_unaligned_be32(&buffer[0]);
if (sdp->no_read_capacity_16 && (lba == 0xffffffff)) {
/* Some buggy (usb cardreader) devices return an lba of
0xffffffff when the want to report a size of 0 (with
which they really mean no media is present) */
sdkp->capacity = 0;
sdkp->physical_block_size = sector_size;
return sector_size;
}
if ((sizeof(sdkp->capacity) == 4) && (lba == 0xffffffff)) {
sd_printk(KERN_ERR, sdkp, "Too big for this kernel. Use a "
"kernel compiled with support for large block "

View File

@ -862,10 +862,16 @@ static void get_capabilities(struct scsi_cd *cd)
static int sr_packet(struct cdrom_device_info *cdi,
struct packet_command *cgc)
{
struct scsi_cd *cd = cdi->handle;
struct scsi_device *sdev = cd->device;
if (cgc->cmd[0] == GPCMD_READ_DISC_INFO && sdev->no_read_disc_info)
return -EDRIVE_CANT_DO_THIS;
if (cgc->timeout <= 0)
cgc->timeout = IOCTL_TIMEOUT;
sr_do_ioctl(cdi->handle, cgc);
sr_do_ioctl(cd, cgc);
return cgc->stat;
}

View File

@ -59,6 +59,7 @@ config USB_ARCH_HAS_OHCI
config USB_ARCH_HAS_EHCI
boolean
default y if PPC_83xx
default y if PPC_MPC512x
default y if SOC_AU1200
default y if ARCH_IXP4XX
default y if ARCH_W90X900

View File

@ -2,12 +2,10 @@
# Makefile for USB ATM/xDSL drivers
#
ccflags-$(CONFIG_USB_DEBUG) := -DDEBUG
obj-$(CONFIG_USB_CXACRU) += cxacru.o
obj-$(CONFIG_USB_SPEEDTOUCH) += speedtch.o
obj-$(CONFIG_USB_UEAGLEATM) += ueagle-atm.o
obj-$(CONFIG_USB_ATM) += usbatm.o
obj-$(CONFIG_USB_XUSBATM) += xusbatm.o
ifeq ($(CONFIG_USB_DEBUG),y)
EXTRA_CFLAGS += -DDEBUG
endif

View File

@ -2,8 +2,8 @@
# Makefile for Cypress C67X00 USB Controller
#
ccflags-$(CONFIG_USB_DEBUG) += -DDEBUG
ccflags-$(CONFIG_USB_DEBUG) := -DDEBUG
obj-$(CONFIG_USB_C67X00_HCD) += c67x00.o
obj-$(CONFIG_USB_C67X00_HCD) += c67x00.o
c67x00-objs := c67x00-drv.o c67x00-ll-hpi.o c67x00-hcd.o c67x00-sched.o
c67x00-y := c67x00-drv.o c67x00-ll-hpi.o c67x00-hcd.o c67x00-sched.o

View File

@ -1614,7 +1614,7 @@ static const struct usb_device_id acm_ids[] = {
/* Support Lego NXT using pbLua firmware */
{ USB_DEVICE(0x0694, 0xff00),
.driver_info = NOT_A_MODEM,
},
},
/* control interfaces without any protocol set */
{ USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM,

View File

@ -2,20 +2,13 @@
# Makefile for USB Core files and filesystem
#
usbcore-objs := usb.o hub.o hcd.o urb.o message.o driver.o \
config.o file.o buffer.o sysfs.o endpoint.o \
devio.o notify.o generic.o quirks.o devices.o
ccflags-$(CONFIG_USB_DEBUG) := -DDEBUG
ifeq ($(CONFIG_PCI),y)
usbcore-objs += hcd-pci.o
endif
usbcore-y := usb.o hub.o hcd.o urb.o message.o driver.o
usbcore-y += config.o file.o buffer.o sysfs.o endpoint.o
usbcore-y += devio.o notify.o generic.o quirks.o devices.o
ifeq ($(CONFIG_USB_DEVICEFS),y)
usbcore-objs += inode.o
endif
usbcore-$(CONFIG_PCI) += hcd-pci.o
usbcore-$(CONFIG_USB_DEVICEFS) += inode.o
obj-$(CONFIG_USB) += usbcore.o
ifeq ($(CONFIG_USB_DEBUG),y)
EXTRA_CFLAGS += -DDEBUG
endif
obj-$(CONFIG_USB) += usbcore.o

View File

@ -66,8 +66,8 @@
#define ALLOW_SERIAL_NUMBER
static const char *format_topo =
/* T: Bus=dd Lev=dd Prnt=dd Port=dd Cnt=dd Dev#=ddd Spd=ddd MxCh=dd */
"\nT: Bus=%2.2d Lev=%2.2d Prnt=%2.2d Port=%2.2d Cnt=%2.2d Dev#=%3d Spd=%3s MxCh=%2d\n";
/* T: Bus=dd Lev=dd Prnt=dd Port=dd Cnt=dd Dev#=ddd Spd=dddd MxCh=dd */
"\nT: Bus=%2.2d Lev=%2.2d Prnt=%2.2d Port=%2.2d Cnt=%2.2d Dev#=%3d Spd=%-4s MxCh=%2d\n";
static const char *format_string_manufacturer =
/* S: Manufacturer=xxxx */
@ -520,11 +520,14 @@ static ssize_t usb_device_dump(char __user **buffer, size_t *nbytes,
speed = "1.5"; break;
case USB_SPEED_UNKNOWN: /* usb 1.1 root hub code */
case USB_SPEED_FULL:
speed = "12 "; break;
speed = "12"; break;
case USB_SPEED_WIRELESS: /* Wireless has no real fixed speed */
case USB_SPEED_HIGH:
speed = "480"; break;
case USB_SPEED_SUPER:
speed = "5000"; break;
default:
speed = "?? ";
speed = "??";
}
data_end = pages_start + sprintf(pages_start, format_topo,
bus->busnum, level, parent_devnum,

View File

@ -1337,7 +1337,7 @@ int usb_resume(struct device *dev, pm_message_t msg)
/* Avoid PM error messages for devices disconnected while suspended
* as we'll display regular disconnect messages just a bit later.
*/
if (status == -ENODEV)
if (status == -ENODEV || status == -ESHUTDOWN)
status = 0;
return status;
}

View File

@ -202,7 +202,7 @@ int usb_create_ep_devs(struct device *parent,
return retval;
error_register:
kfree(ep_dev);
put_device(&ep_dev->dev);
exit:
return retval;
}

View File

@ -329,8 +329,10 @@ void usb_hcd_pci_shutdown(struct pci_dev *dev)
return;
if (test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags) &&
hcd->driver->shutdown)
hcd->driver->shutdown) {
hcd->driver->shutdown(hcd);
pci_disable_device(dev);
}
}
EXPORT_SYMBOL_GPL(usb_hcd_pci_shutdown);

View File

@ -1263,10 +1263,8 @@ static void hcd_free_coherent(struct usb_bus *bus, dma_addr_t *dma_handle,
*dma_handle = 0;
}
static void unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb)
void unmap_urb_setup_for_dma(struct usb_hcd *hcd, struct urb *urb)
{
enum dma_data_direction dir;
if (urb->transfer_flags & URB_SETUP_MAP_SINGLE)
dma_unmap_single(hcd->self.controller,
urb->setup_dma,
@ -1279,6 +1277,17 @@ static void unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb)
sizeof(struct usb_ctrlrequest),
DMA_TO_DEVICE);
/* Make it safe to call this routine more than once */
urb->transfer_flags &= ~(URB_SETUP_MAP_SINGLE | URB_SETUP_MAP_LOCAL);
}
EXPORT_SYMBOL_GPL(unmap_urb_setup_for_dma);
void unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb)
{
enum dma_data_direction dir;
unmap_urb_setup_for_dma(hcd, urb);
dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
if (urb->transfer_flags & URB_DMA_MAP_SG)
dma_unmap_sg(hcd->self.controller,
@ -1303,10 +1312,10 @@ static void unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb)
dir);
/* Make it safe to call this routine more than once */
urb->transfer_flags &= ~(URB_SETUP_MAP_SINGLE | URB_SETUP_MAP_LOCAL |
URB_DMA_MAP_SG | URB_DMA_MAP_PAGE |
urb->transfer_flags &= ~(URB_DMA_MAP_SG | URB_DMA_MAP_PAGE |
URB_DMA_MAP_SINGLE | URB_MAP_LOCAL);
}
EXPORT_SYMBOL_GPL(unmap_urb_for_dma);
static int map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
gfp_t mem_flags)

View File

@ -758,6 +758,9 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
clear_port_feature(hdev, port1,
USB_PORT_FEAT_ENABLE);
portstatus &= ~USB_PORT_STAT_ENABLE;
} else {
/* Pretend that power was lost for USB3 devs */
portstatus &= ~USB_PORT_STAT_ENABLE;
}
}
@ -2594,16 +2597,14 @@ static int hub_set_address(struct usb_device *udev, int devnum)
return 0;
if (udev->state != USB_STATE_DEFAULT)
return -EINVAL;
if (hcd->driver->address_device) {
if (hcd->driver->address_device)
retval = hcd->driver->address_device(hcd, udev);
} else {
else
retval = usb_control_msg(udev, usb_sndaddr0pipe(),
USB_REQ_SET_ADDRESS, 0, devnum, 0,
NULL, 0, USB_CTRL_SET_TIMEOUT);
if (retval == 0)
update_address(udev, devnum);
}
if (retval == 0) {
update_address(udev, devnum);
/* Device now using proper address. */
usb_set_device_state(udev, USB_STATE_ADDRESS);
usb_ep0_reinit(udev);
@ -2860,13 +2861,16 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
else
i = udev->descriptor.bMaxPacketSize0;
if (le16_to_cpu(udev->ep0.desc.wMaxPacketSize) != i) {
if (udev->speed != USB_SPEED_FULL ||
if (udev->speed == USB_SPEED_LOW ||
!(i == 8 || i == 16 || i == 32 || i == 64)) {
dev_err(&udev->dev, "ep0 maxpacket = %d\n", i);
dev_err(&udev->dev, "Invalid ep0 maxpacket: %d\n", i);
retval = -EMSGSIZE;
goto fail;
}
dev_dbg(&udev->dev, "ep0 maxpacket = %d\n", i);
if (udev->speed == USB_SPEED_FULL)
dev_dbg(&udev->dev, "ep0 maxpacket = %d\n", i);
else
dev_warn(&udev->dev, "Using ep0 maxpacket: %d\n", i);
udev->ep0.desc.wMaxPacketSize = cpu_to_le16(i);
usb_ep0_reinit(udev);
}
@ -3097,16 +3101,17 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
udev->speed = USB_SPEED_UNKNOWN;
/*
* xHCI needs to issue an address device command later
* in the hub_port_init sequence for SS/HS/FS/LS devices.
* Set the address.
* Note xHCI needs to issue an address device command later
* in the hub_port_init sequence for SS/HS/FS/LS devices,
* and xHC will assign an address to the device. But use
* kernel assigned address here, to avoid any address conflict
* issue.
*/
if (!(hcd->driver->flags & HCD_USB3)) {
/* set the address */
choose_address(udev);
if (udev->devnum <= 0) {
status = -ENOTCONN; /* Don't retry */
goto loop;
}
choose_address(udev);
if (udev->devnum <= 0) {
status = -ENOTCONN; /* Don't retry */
goto loop;
}
/* reset (non-USB 3.0 devices) and get descriptor */
@ -3629,7 +3634,7 @@ static int usb_reset_and_verify_device(struct usb_device *udev)
}
if (!parent_hdev) {
/* this requires hcd-specific logic; see OHCI hc_restart() */
/* this requires hcd-specific logic; see ohci_restart() */
dev_dbg(&udev->dev, "%s for root hub!\n", __func__);
return -EISDIR;
}

View File

@ -1140,13 +1140,6 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0)
{
int i;
dev_dbg(&dev->dev, "%s nuking %s URBs\n", __func__,
skip_ep0 ? "non-ep0" : "all");
for (i = skip_ep0; i < 16; ++i) {
usb_disable_endpoint(dev, i, true);
usb_disable_endpoint(dev, i + USB_DIR_IN, true);
}
/* getting rid of interfaces will disconnect
* any drivers bound to them (a key side effect)
*/
@ -1176,6 +1169,13 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0)
if (dev->state == USB_STATE_CONFIGURED)
usb_set_device_state(dev, USB_STATE_ADDRESS);
}
dev_dbg(&dev->dev, "%s nuking %s URBs\n", __func__,
skip_ep0 ? "non-ep0" : "all");
for (i = skip_ep0; i < 16; ++i) {
usb_disable_endpoint(dev, i, true);
usb_disable_endpoint(dev, i + USB_DIR_IN, true);
}
}
/**

View File

@ -401,8 +401,11 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
};
/* Check that the pipe's type matches the endpoint's type */
if (usb_pipetype(urb->pipe) != pipetypes[xfertype])
if (usb_pipetype(urb->pipe) != pipetypes[xfertype]) {
dev_err(&dev->dev, "BOGUS urb xfer, pipe %x != type %x\n",
usb_pipetype(urb->pipe), pipetypes[xfertype]);
return -EPIPE; /* The most suitable error code :-) */
}
/* enforce simple/standard policy */
allowed = (URB_NO_TRANSFER_DMA_MAP | URB_NO_INTERRUPT | URB_DIR_MASK |

View File

@ -2,4 +2,4 @@
# Makefile for early USB devices
#
obj-$(CONFIG_EARLY_PRINTK_DBGP) += ehci-dbgp.o
obj-$(CONFIG_EARLY_PRINTK_DBGP) += ehci-dbgp.o

View File

@ -158,6 +158,7 @@ config USB_GADGET_FSL_USB2
boolean "Freescale Highspeed USB DR Peripheral Controller"
depends on FSL_SOC || ARCH_MXC
select USB_GADGET_DUALSPEED
select USB_FSL_MPH_DR_OF
help
Some of Freescale PowerPC processors have a High Speed
Dual-Role(DR) USB controller, which supports device mode.
@ -209,17 +210,6 @@ config USB_OMAP
default USB_GADGET
select USB_GADGET_SELECTED
config USB_OTG
boolean "OTG Support"
depends on USB_GADGET_OMAP && ARCH_OMAP_OTG && USB_OHCI_HCD
help
The most notable feature of USB OTG is support for a
"Dual-Role" device, which can act as either a device
or a host. The initial role choice can be changed
later, when two dual-role devices talk to each other.
Select this only if your OMAP board has a Mini-AB connector.
config USB_GADGET_PXA25X
boolean "PXA 25x or IXP 4xx"
depends on (ARCH_PXA && PXA25x) || ARCH_IXP4XX
@ -716,8 +706,8 @@ config USB_FUNCTIONFS
depends on EXPERIMENTAL
select USB_FUNCTIONFS_GENERIC if !(USB_FUNCTIONFS_ETH || USB_FUNCTIONFS_RNDIS)
help
The Function Filesystem (FunctioFS) lets one create USB
composite functions in user space in the same way as GadgetFS
The Function Filesystem (FunctionFS) lets one create USB
composite functions in user space in the same way GadgetFS
lets one create USB gadgets in user space. This allows creation
of composite gadgets such that some of the functions are
implemented in kernel space (for instance Ethernet, serial or
@ -733,14 +723,14 @@ config USB_FUNCTIONFS_ETH
bool "Include configuration with CDC ECM (Ethernet)"
depends on USB_FUNCTIONFS && NET
help
Include a configuration with CDC ECM funcion (Ethernet) and the
Funcion Filesystem.
Include a configuration with CDC ECM function (Ethernet) and the
Function Filesystem.
config USB_FUNCTIONFS_RNDIS
bool "Include configuration with RNDIS (Ethernet)"
depends on USB_FUNCTIONFS && NET
help
Include a configuration with RNDIS funcion (Ethernet) and the Filesystem.
Include a configuration with RNDIS function (Ethernet) and the Filesystem.
config USB_FUNCTIONFS_GENERIC
bool "Include 'pure' configuration"

View File

@ -1,9 +1,7 @@
#
# USB peripheral controller drivers
#
ifeq ($(CONFIG_USB_GADGET_DEBUG),y)
EXTRA_CFLAGS += -DDEBUG
endif
ccflags-$(CONFIG_USB_GADGET_DEBUG) := -DDEBUG
obj-$(CONFIG_USB_DUMMY_HCD) += dummy_hcd.o
obj-$(CONFIG_USB_NET2280) += net2280.o
@ -18,10 +16,8 @@ obj-$(CONFIG_USB_S3C2410) += s3c2410_udc.o
obj-$(CONFIG_USB_AT91) += at91_udc.o
obj-$(CONFIG_USB_ATMEL_USBA) += atmel_usba_udc.o
obj-$(CONFIG_USB_FSL_USB2) += fsl_usb2_udc.o
fsl_usb2_udc-objs := fsl_udc_core.o
ifeq ($(CONFIG_ARCH_MXC),y)
fsl_usb2_udc-objs += fsl_mxc_udc.o
endif
fsl_usb2_udc-y := fsl_udc_core.o
fsl_usb2_udc-$(CONFIG_ARCH_MXC) += fsl_mxc_udc.o
obj-$(CONFIG_USB_M66592) += m66592-udc.o
obj-$(CONFIG_USB_R8A66597) += r8a66597-udc.o
obj-$(CONFIG_USB_FSL_QE) += fsl_qe_udc.o
@ -32,21 +28,21 @@ obj-$(CONFIG_USB_LANGWELL) += langwell_udc.o
#
# USB gadget drivers
#
g_zero-objs := zero.o
g_audio-objs := audio.o
g_ether-objs := ether.o
g_serial-objs := serial.o
g_midi-objs := gmidi.o
gadgetfs-objs := inode.o
g_file_storage-objs := file_storage.o
g_mass_storage-objs := mass_storage.o
g_printer-objs := printer.o
g_cdc-objs := cdc2.o
g_multi-objs := multi.o
g_hid-objs := hid.o
g_dbgp-objs := dbgp.o
g_nokia-objs := nokia.o
g_webcam-objs := webcam.o
g_zero-y := zero.o
g_audio-y := audio.o
g_ether-y := ether.o
g_serial-y := serial.o
g_midi-y := gmidi.o
gadgetfs-y := inode.o
g_file_storage-y := file_storage.o
g_mass_storage-y := mass_storage.o
g_printer-y := printer.o
g_cdc-y := cdc2.o
g_multi-y := multi.o
g_hid-y := hid.o
g_dbgp-y := dbgp.o
g_nokia-y := nokia.o
g_webcam-y := webcam.o
obj-$(CONFIG_USB_ZERO) += g_zero.o
obj-$(CONFIG_USB_AUDIO) += g_audio.o
@ -64,4 +60,3 @@ obj-$(CONFIG_USB_G_DBGP) += g_dbgp.o
obj-$(CONFIG_USB_G_MULTI) += g_multi.o
obj-$(CONFIG_USB_G_NOKIA) += g_nokia.o
obj-$(CONFIG_USB_G_WEBCAM) += g_webcam.o

View File

@ -203,7 +203,7 @@ static void print_regs(struct udc *dev)
DBG(dev, "DMA mode = PPBNDU (packet per buffer "
"WITHOUT desc. update)\n");
dev_info(&dev->pdev->dev, "DMA mode (%s)\n", "PPBNDU");
} else if (use_dma && use_dma_ppb_du && use_dma_ppb_du) {
} else if (use_dma && use_dma_ppb && use_dma_ppb_du) {
DBG(dev, "DMA mode = PPBDU (packet per buffer "
"WITH desc. update)\n");
dev_info(&dev->pdev->dev, "DMA mode (%s)\n", "PPBDU");
@ -1954,13 +1954,14 @@ static int setup_ep0(struct udc *dev)
}
/* Called by gadget driver to register itself */
int usb_gadget_register_driver(struct usb_gadget_driver *driver)
int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
int (*bind)(struct usb_gadget *))
{
struct udc *dev = udc;
int retval;
u32 tmp;
if (!driver || !driver->bind || !driver->setup
if (!driver || !bind || !driver->setup
|| driver->speed != USB_SPEED_HIGH)
return -EINVAL;
if (!dev)
@ -1972,7 +1973,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
dev->driver = driver;
dev->gadget.dev.driver = &driver->driver;
retval = driver->bind(&dev->gadget);
retval = bind(&dev->gadget);
/* Some gadget drivers use both ep0 directions.
* NOTE: to gadget driver, ep0 is just one endpoint...
@ -2000,7 +2001,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
return 0;
}
EXPORT_SYMBOL(usb_gadget_register_driver);
EXPORT_SYMBOL(usb_gadget_probe_driver);
/* shutdown requests and disconnect from gadget */
static void
@ -3382,8 +3383,10 @@ static int udc_probe(struct udc *dev)
udc = dev;
retval = device_register(&dev->gadget.dev);
if (retval)
if (retval) {
put_device(&dev->gadget.dev);
goto finished;
}
/* timer init */
init_timer(&udc_timer);

View File

@ -1628,7 +1628,8 @@ static void at91_vbus_timer(unsigned long data)
schedule_work(&udc->vbus_timer_work);
}
int usb_gadget_register_driver (struct usb_gadget_driver *driver)
int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
int (*bind)(struct usb_gadget *))
{
struct at91_udc *udc = &controller;
int retval;
@ -1636,7 +1637,7 @@ int usb_gadget_register_driver (struct usb_gadget_driver *driver)
if (!driver
|| driver->speed < USB_SPEED_FULL
|| !driver->bind
|| !bind
|| !driver->setup) {
DBG("bad parameter.\n");
return -EINVAL;
@ -1653,9 +1654,9 @@ int usb_gadget_register_driver (struct usb_gadget_driver *driver)
udc->enabled = 1;
udc->selfpowered = 1;
retval = driver->bind(&udc->gadget);
retval = bind(&udc->gadget);
if (retval) {
DBG("driver->bind() returned %d\n", retval);
DBG("bind() returned %d\n", retval);
udc->driver = NULL;
udc->gadget.dev.driver = NULL;
dev_set_drvdata(&udc->gadget.dev, NULL);
@ -1671,7 +1672,7 @@ int usb_gadget_register_driver (struct usb_gadget_driver *driver)
DBG("bound to %s\n", driver->driver.name);
return 0;
}
EXPORT_SYMBOL (usb_gadget_register_driver);
EXPORT_SYMBOL(usb_gadget_probe_driver);
int usb_gadget_unregister_driver (struct usb_gadget_driver *driver)
{

View File

@ -1789,7 +1789,8 @@ static irqreturn_t usba_vbus_irq(int irq, void *devid)
return IRQ_HANDLED;
}
int usb_gadget_register_driver(struct usb_gadget_driver *driver)
int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
int (*bind)(struct usb_gadget *))
{
struct usba_udc *udc = &the_udc;
unsigned long flags;
@ -1812,7 +1813,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
clk_enable(udc->pclk);
clk_enable(udc->hclk);
ret = driver->bind(&udc->gadget);
ret = bind(&udc->gadget);
if (ret) {
DBG(DBG_ERR, "Could not bind to driver %s: error %d\n",
driver->driver.name, ret);
@ -1841,7 +1842,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
udc->gadget.dev.driver = NULL;
return ret;
}
EXPORT_SYMBOL(usb_gadget_register_driver);
EXPORT_SYMBOL(usb_gadget_probe_driver);
int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
{
@ -2014,6 +2015,9 @@ static int __init usba_udc_probe(struct platform_device *pdev)
} else {
disable_irq(gpio_to_irq(udc->vbus_pin));
}
} else {
/* gpio_request fail so use -EINVAL for gpio_is_valid */
ubc->vbus_pin = -EINVAL;
}
}

View File

@ -89,7 +89,7 @@ static const struct usb_descriptor_header *otg_desc[] = {
/*-------------------------------------------------------------------------*/
static int __ref audio_do_config(struct usb_configuration *c)
static int __init audio_do_config(struct usb_configuration *c)
{
/* FIXME alloc iConfiguration string, set it in c->strings */
@ -105,7 +105,6 @@ static int __ref audio_do_config(struct usb_configuration *c)
static struct usb_configuration audio_config_driver = {
.label = DRIVER_DESC,
.bind = audio_do_config,
.bConfigurationValue = 1,
/* .iConfiguration = DYNAMIC */
.bmAttributes = USB_CONFIG_ATT_SELFPOWER,
@ -113,7 +112,7 @@ static struct usb_configuration audio_config_driver = {
/*-------------------------------------------------------------------------*/
static int __ref audio_bind(struct usb_composite_dev *cdev)
static int __init audio_bind(struct usb_composite_dev *cdev)
{
int gcnum;
int status;
@ -145,7 +144,7 @@ static int __ref audio_bind(struct usb_composite_dev *cdev)
strings_dev[STRING_PRODUCT_IDX].id = status;
device_desc.iProduct = status;
status = usb_add_config(cdev, &audio_config_driver);
status = usb_add_config(cdev, &audio_config_driver, audio_do_config);
if (status < 0)
goto fail;
@ -166,13 +165,12 @@ static struct usb_composite_driver audio_driver = {
.name = "g_audio",
.dev = &device_desc,
.strings = audio_strings,
.bind = audio_bind,
.unbind = __exit_p(audio_unbind),
};
static int __init init(void)
{
return usb_composite_register(&audio_driver);
return usb_composite_probe(&audio_driver, audio_bind);
}
module_init(init);

View File

@ -129,7 +129,7 @@ static u8 hostaddr[ETH_ALEN];
/*
* We _always_ have both CDC ECM and CDC ACM functions.
*/
static int __ref cdc_do_config(struct usb_configuration *c)
static int __init cdc_do_config(struct usb_configuration *c)
{
int status;
@ -151,7 +151,6 @@ static int __ref cdc_do_config(struct usb_configuration *c)
static struct usb_configuration cdc_config_driver = {
.label = "CDC Composite (ECM + ACM)",
.bind = cdc_do_config,
.bConfigurationValue = 1,
/* .iConfiguration = DYNAMIC */
.bmAttributes = USB_CONFIG_ATT_SELFPOWER,
@ -159,7 +158,7 @@ static struct usb_configuration cdc_config_driver = {
/*-------------------------------------------------------------------------*/
static int __ref cdc_bind(struct usb_composite_dev *cdev)
static int __init cdc_bind(struct usb_composite_dev *cdev)
{
int gcnum;
struct usb_gadget *gadget = cdev->gadget;
@ -218,7 +217,7 @@ static int __ref cdc_bind(struct usb_composite_dev *cdev)
device_desc.iProduct = status;
/* register our configuration */
status = usb_add_config(cdev, &cdc_config_driver);
status = usb_add_config(cdev, &cdc_config_driver, cdc_do_config);
if (status < 0)
goto fail1;
@ -245,7 +244,6 @@ static struct usb_composite_driver cdc_driver = {
.name = "g_cdc",
.dev = &device_desc,
.strings = dev_strings,
.bind = cdc_bind,
.unbind = __exit_p(cdc_unbind),
};
@ -255,7 +253,7 @@ MODULE_LICENSE("GPL");
static int __init init(void)
{
return usb_composite_register(&cdc_driver);
return usb_composite_probe(&cdc_driver, cdc_bind);
}
module_init(init);

View File

@ -2340,12 +2340,15 @@ static const struct usb_ep_ops usb_ep_ops = {
static const struct usb_gadget_ops usb_gadget_ops;
/**
* usb_gadget_register_driver: register a gadget driver
* usb_gadget_probe_driver: register a gadget driver
* @driver: the driver being registered
* @bind: the driver's bind callback
*
* Check usb_gadget_register_driver() at "usb_gadget.h" for details
* Interrupts are enabled here
* Check usb_gadget_probe_driver() at <linux/usb/gadget.h> for details.
* Interrupts are enabled here.
*/
int usb_gadget_register_driver(struct usb_gadget_driver *driver)
int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
int (*bind)(struct usb_gadget *))
{
struct ci13xxx *udc = _udc;
unsigned long i, k, flags;
@ -2354,7 +2357,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
trace("%p", driver);
if (driver == NULL ||
driver->bind == NULL ||
bind == NULL ||
driver->unbind == NULL ||
driver->setup == NULL ||
driver->disconnect == NULL ||
@ -2430,7 +2433,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
udc->gadget.dev.driver = &driver->driver;
spin_unlock_irqrestore(udc->lock, flags);
retval = driver->bind(&udc->gadget); /* MAY SLEEP */
retval = bind(&udc->gadget); /* MAY SLEEP */
spin_lock_irqsave(udc->lock, flags);
if (retval) {
@ -2447,7 +2450,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
usb_gadget_unregister_driver(driver);
return retval;
}
EXPORT_SYMBOL(usb_gadget_register_driver);
EXPORT_SYMBOL(usb_gadget_probe_driver);
/**
* usb_gadget_unregister_driver: unregister a gadget driver
@ -2462,7 +2465,6 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
trace("%p", driver);
if (driver == NULL ||
driver->bind == NULL ||
driver->unbind == NULL ||
driver->setup == NULL ||
driver->disconnect == NULL ||

View File

@ -24,6 +24,7 @@
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/device.h>
#include <linux/utsname.h>
#include <linux/usb/composite.h>
@ -39,6 +40,7 @@
#define USB_BUFSIZ 1024
static struct usb_composite_driver *composite;
static int (*composite_gadget_bind)(struct usb_composite_dev *cdev);
/* Some systems will need runtime overrides for the product identifers
* published in the device descriptor, either numbers or strings or both.
@ -69,6 +71,8 @@ static char *iSerialNumber;
module_param(iSerialNumber, charp, 0);
MODULE_PARM_DESC(iSerialNumber, "SerialNumber string");
static char composite_manufacturer[50];
/*-------------------------------------------------------------------------*/
/**
@ -470,18 +474,20 @@ static int set_config(struct usb_composite_dev *cdev,
* usb_add_config() - add a configuration to a device.
* @cdev: wraps the USB gadget
* @config: the configuration, with bConfigurationValue assigned
* @bind: the configuration's bind function
* Context: single threaded during gadget setup
*
* One of the main tasks of a composite driver's bind() routine is to
* One of the main tasks of a composite @bind() routine is to
* add each of the configurations it supports, using this routine.
*
* This function returns the value of the configuration's bind(), which
* This function returns the value of the configuration's @bind(), which
* is zero for success else a negative errno value. Binding configurations
* assigns global resources including string IDs, and per-configuration
* resources such as interface IDs and endpoints.
*/
int usb_add_config(struct usb_composite_dev *cdev,
struct usb_configuration *config)
struct usb_configuration *config,
int (*bind)(struct usb_configuration *))
{
int status = -EINVAL;
struct usb_configuration *c;
@ -490,7 +496,7 @@ int usb_add_config(struct usb_composite_dev *cdev,
config->bConfigurationValue,
config->label, config);
if (!config->bConfigurationValue || !config->bind)
if (!config->bConfigurationValue || !bind)
goto done;
/* Prevent duplicate configuration identifiers */
@ -507,7 +513,7 @@ int usb_add_config(struct usb_composite_dev *cdev,
INIT_LIST_HEAD(&config->functions);
config->next_interface_id = 0;
status = config->bind(config);
status = bind(config);
if (status < 0) {
list_del(&config->list);
config->cdev = NULL;
@ -533,7 +539,7 @@ int usb_add_config(struct usb_composite_dev *cdev,
}
}
/* set_alt(), or next config->bind(), sets up
/* set_alt(), or next bind(), sets up
* ep->driver_data as needed.
*/
usb_ep_autoconfig_reset(cdev->gadget);
@ -599,6 +605,7 @@ static int get_string(struct usb_composite_dev *cdev,
struct usb_configuration *c;
struct usb_function *f;
int len;
const char *str;
/* Yes, not only is USB's I18N support probably more than most
* folk will ever care about ... also, it's all supported here.
@ -638,9 +645,29 @@ static int get_string(struct usb_composite_dev *cdev,
return s->bLength;
}
/* Otherwise, look up and return a specified string. String IDs
* are device-scoped, so we look up each string table we're told
* about. These lookups are infrequent; simpler-is-better here.
/* Otherwise, look up and return a specified string. First
* check if the string has not been overridden.
*/
if (cdev->manufacturer_override == id)
str = iManufacturer ?: composite->iManufacturer ?:
composite_manufacturer;
else if (cdev->product_override == id)
str = iProduct ?: composite->iProduct;
else if (cdev->serial_override == id)
str = iSerialNumber;
else
str = NULL;
if (str) {
struct usb_gadget_strings strings = {
.language = language,
.strings = &(struct usb_string) { 0xff, str }
};
return usb_gadget_get_string(&strings, 0xff, buf);
}
/* String IDs are device-scoped, so we look up each string
* table we're told about. These lookups are infrequent;
* simpler-is-better here.
*/
if (composite->strings) {
len = lookup_string(composite->strings, buf, language, id);
@ -901,7 +928,8 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
*/
switch (ctrl->bRequestType & USB_RECIP_MASK) {
case USB_RECIP_INTERFACE:
f = cdev->config->interface[intf];
if (cdev->config)
f = cdev->config->interface[intf];
break;
case USB_RECIP_ENDPOINT:
@ -1025,26 +1053,17 @@ composite_unbind(struct usb_gadget *gadget)
composite = NULL;
}
static void
string_override_one(struct usb_gadget_strings *tab, u8 id, const char *s)
static u8 override_id(struct usb_composite_dev *cdev, u8 *desc)
{
struct usb_string *str = tab->strings;
for (str = tab->strings; str->s; str++) {
if (str->id == id) {
str->s = s;
return;
}
if (!*desc) {
int ret = usb_string_id(cdev);
if (unlikely(ret < 0))
WARNING(cdev, "failed to override string ID\n");
else
*desc = ret;
}
}
static void
string_override(struct usb_gadget_strings **tab, u8 id, const char *s)
{
while (*tab) {
string_override_one(*tab, id, s);
tab++;
}
return *desc;
}
static int composite_bind(struct usb_gadget *gadget)
@ -1074,7 +1093,13 @@ static int composite_bind(struct usb_gadget *gadget)
cdev->bufsiz = USB_BUFSIZ;
cdev->driver = composite;
usb_gadget_set_selfpowered(gadget);
/*
* As per USB compliance update, a device that is actively drawing
* more than 100mA from USB must report itself as bus-powered in
* the GetStatus(DEVICE) call.
*/
if (CONFIG_USB_GADGET_VBUS_DRAW <= USB_SELF_POWER_VBUS_MAX_DRAW)
usb_gadget_set_selfpowered(gadget);
/* interface and string IDs start at zero via kzalloc.
* we force endpoints to start unassigned; few controller
@ -1094,26 +1119,41 @@ static int composite_bind(struct usb_gadget *gadget)
* serial number), register function drivers, potentially update
* power state and consumption, etc
*/
status = composite->bind(cdev);
status = composite_gadget_bind(cdev);
if (status < 0)
goto fail;
cdev->desc = *composite->dev;
cdev->desc.bMaxPacketSize0 = gadget->ep0->maxpacket;
/* strings can't be assigned before bind() allocates the
* releavnt identifiers
*/
if (cdev->desc.iManufacturer && iManufacturer)
string_override(composite->strings,
cdev->desc.iManufacturer, iManufacturer);
if (cdev->desc.iProduct && iProduct)
string_override(composite->strings,
cdev->desc.iProduct, iProduct);
if (cdev->desc.iSerialNumber && iSerialNumber)
string_override(composite->strings,
cdev->desc.iSerialNumber, iSerialNumber);
/* stirng overrides */
if (iManufacturer || !cdev->desc.iManufacturer) {
if (!iManufacturer && !composite->iManufacturer &&
!*composite_manufacturer)
snprintf(composite_manufacturer,
sizeof composite_manufacturer,
"%s %s with %s",
init_utsname()->sysname,
init_utsname()->release,
gadget->name);
cdev->manufacturer_override =
override_id(cdev, &cdev->desc.iManufacturer);
}
if (iProduct || (!cdev->desc.iProduct && composite->iProduct))
cdev->product_override =
override_id(cdev, &cdev->desc.iProduct);
if (iSerialNumber)
cdev->serial_override =
override_id(cdev, &cdev->desc.iSerialNumber);
/* has userspace failed to provide a serial number? */
if (composite->needs_serial && !cdev->desc.iSerialNumber)
WARNING(cdev, "userspace failed to provide iSerialNumber\n");
/* finish up */
status = device_create_file(&gadget->dev, &dev_attr_suspended);
if (status)
goto fail;
@ -1177,7 +1217,6 @@ composite_resume(struct usb_gadget *gadget)
static struct usb_gadget_driver composite_driver = {
.speed = USB_SPEED_HIGH,
.bind = composite_bind,
.unbind = composite_unbind,
.setup = composite_setup,
@ -1192,8 +1231,12 @@ static struct usb_gadget_driver composite_driver = {
};
/**
* usb_composite_register() - register a composite driver
* usb_composite_probe() - register a composite driver
* @driver: the driver to register
* @bind: the callback used to allocate resources that are shared across the
* whole device, such as string IDs, and add its configurations using
* @usb_add_config(). This may fail by returning a negative errno
* value; it should return zero on successful initialization.
* Context: single threaded during gadget setup
*
* This function is used to register drivers using the composite driver
@ -1206,18 +1249,22 @@ static struct usb_gadget_driver composite_driver = {
* while it was binding. That would usually be done in order to wait for
* some userspace participation.
*/
int usb_composite_register(struct usb_composite_driver *driver)
extern int usb_composite_probe(struct usb_composite_driver *driver,
int (*bind)(struct usb_composite_dev *cdev))
{
if (!driver || !driver->dev || !driver->bind || composite)
if (!driver || !driver->dev || !bind || composite)
return -EINVAL;
if (!driver->iProduct)
driver->iProduct = driver->name;
if (!driver->name)
driver->name = "composite";
composite_driver.function = (char *) driver->name;
composite_driver.driver.name = driver->name;
composite = driver;
composite_gadget_bind = bind;
return usb_gadget_register_driver(&composite_driver);
return usb_gadget_probe_driver(&composite_driver, composite_bind);
}
/**

View File

@ -386,15 +386,13 @@ static int dbgp_setup(struct usb_gadget *gadget,
} else
goto fail;
if (len >= 0) {
req->length = min(length, len);
req->zero = len < req->length;
if (data && req->length)
memcpy(req->buf, data, req->length);
req->length = min(length, len);
req->zero = len < req->length;
if (data && req->length)
memcpy(req->buf, data, req->length);
req->complete = dbgp_setup_complete;
return usb_ep_queue(gadget->ep0, req, GFP_ATOMIC);
}
req->complete = dbgp_setup_complete;
return usb_ep_queue(gadget->ep0, req, GFP_ATOMIC);
fail:
dev_dbg(&dbgp.gadget->dev,
@ -405,7 +403,6 @@ static int dbgp_setup(struct usb_gadget *gadget,
static struct usb_gadget_driver dbgp_driver = {
.function = "dbgp",
.speed = USB_SPEED_HIGH,
.bind = dbgp_bind,
.unbind = dbgp_unbind,
.setup = dbgp_setup,
.disconnect = dbgp_disconnect,
@ -417,7 +414,7 @@ static struct usb_gadget_driver dbgp_driver = {
static int __init dbgp_init(void)
{
return usb_gadget_register_driver(&dbgp_driver);
return usb_gadget_probe_driver(&dbgp_driver, dbgp_bind);
}
static void __exit dbgp_exit(void)

View File

@ -748,7 +748,8 @@ static DEVICE_ATTR (function, S_IRUGO, show_function, NULL);
*/
int
usb_gadget_register_driver (struct usb_gadget_driver *driver)
usb_gadget_probe_driver(struct usb_gadget_driver *driver,
int (*bind)(struct usb_gadget *))
{
struct dummy *dum = the_controller;
int retval, i;
@ -757,8 +758,7 @@ usb_gadget_register_driver (struct usb_gadget_driver *driver)
return -EINVAL;
if (dum->driver)
return -EBUSY;
if (!driver->bind || !driver->setup
|| driver->speed == USB_SPEED_UNKNOWN)
if (!bind || !driver->setup || driver->speed == USB_SPEED_UNKNOWN)
return -EINVAL;
/*
@ -796,7 +796,7 @@ usb_gadget_register_driver (struct usb_gadget_driver *driver)
dum->gadget.dev.driver = &driver->driver;
dev_dbg (udc_dev(dum), "binding gadget driver '%s'\n",
driver->driver.name);
retval = driver->bind(&dum->gadget);
retval = bind(&dum->gadget);
if (retval) {
dum->driver = NULL;
dum->gadget.dev.driver = NULL;
@ -812,7 +812,7 @@ usb_gadget_register_driver (struct usb_gadget_driver *driver)
usb_hcd_poll_rh_status (dummy_to_hcd (dum));
return 0;
}
EXPORT_SYMBOL (usb_gadget_register_driver);
EXPORT_SYMBOL(usb_gadget_probe_driver);
int
usb_gadget_unregister_driver (struct usb_gadget_driver *driver)
@ -874,6 +874,8 @@ static int dummy_udc_probe (struct platform_device *pdev)
struct dummy *dum = the_controller;
int rc;
usb_get_hcd(dummy_to_hcd(dum));
dum->gadget.name = gadget_name;
dum->gadget.ops = &dummy_ops;
dum->gadget.is_dualspeed = 1;
@ -885,10 +887,10 @@ static int dummy_udc_probe (struct platform_device *pdev)
dum->gadget.dev.parent = &pdev->dev;
dum->gadget.dev.release = dummy_gadget_release;
rc = device_register (&dum->gadget.dev);
if (rc < 0)
if (rc < 0) {
put_device(&dum->gadget.dev);
return rc;
usb_get_hcd (dummy_to_hcd (dum));
}
platform_set_drvdata (pdev, dum);
rc = device_create_file (&dum->gadget.dev, &dev_attr_function);

View File

@ -237,7 +237,7 @@ static u8 hostaddr[ETH_ALEN];
* the first one present. That's to make Microsoft's drivers happy,
* and to follow DOCSIS 1.0 (cable modem standard).
*/
static int __ref rndis_do_config(struct usb_configuration *c)
static int __init rndis_do_config(struct usb_configuration *c)
{
/* FIXME alloc iConfiguration string, set it in c->strings */
@ -251,7 +251,6 @@ static int __ref rndis_do_config(struct usb_configuration *c)
static struct usb_configuration rndis_config_driver = {
.label = "RNDIS",
.bind = rndis_do_config,
.bConfigurationValue = 2,
/* .iConfiguration = DYNAMIC */
.bmAttributes = USB_CONFIG_ATT_SELFPOWER,
@ -270,7 +269,7 @@ MODULE_PARM_DESC(use_eem, "use CDC EEM mode");
/*
* We _always_ have an ECM, CDC Subset, or EEM configuration.
*/
static int __ref eth_do_config(struct usb_configuration *c)
static int __init eth_do_config(struct usb_configuration *c)
{
/* FIXME alloc iConfiguration string, set it in c->strings */
@ -289,7 +288,6 @@ static int __ref eth_do_config(struct usb_configuration *c)
static struct usb_configuration eth_config_driver = {
/* .label = f(hardware) */
.bind = eth_do_config,
.bConfigurationValue = 1,
/* .iConfiguration = DYNAMIC */
.bmAttributes = USB_CONFIG_ATT_SELFPOWER,
@ -297,7 +295,7 @@ static struct usb_configuration eth_config_driver = {
/*-------------------------------------------------------------------------*/
static int __ref eth_bind(struct usb_composite_dev *cdev)
static int __init eth_bind(struct usb_composite_dev *cdev)
{
int gcnum;
struct usb_gadget *gadget = cdev->gadget;
@ -373,12 +371,13 @@ static int __ref eth_bind(struct usb_composite_dev *cdev)
/* register our configuration(s); RNDIS first, if it's used */
if (has_rndis()) {
status = usb_add_config(cdev, &rndis_config_driver);
status = usb_add_config(cdev, &rndis_config_driver,
rndis_do_config);
if (status < 0)
goto fail;
}
status = usb_add_config(cdev, &eth_config_driver);
status = usb_add_config(cdev, &eth_config_driver, eth_do_config);
if (status < 0)
goto fail;
@ -402,7 +401,6 @@ static struct usb_composite_driver eth_driver = {
.name = "g_ether",
.dev = &device_desc,
.strings = dev_strings,
.bind = eth_bind,
.unbind = __exit_p(eth_unbind),
};
@ -412,7 +410,7 @@ MODULE_LICENSE("GPL");
static int __init init(void)
{
return usb_composite_register(&eth_driver);
return usb_composite_probe(&eth_driver, eth_bind);
}
module_init(init);

View File

@ -111,7 +111,7 @@ acm_iad_descriptor = {
.bInterfaceCount = 2, // control + data
.bFunctionClass = USB_CLASS_COMM,
.bFunctionSubClass = USB_CDC_SUBCLASS_ACM,
.bFunctionProtocol = USB_CDC_PROTO_NONE,
.bFunctionProtocol = USB_CDC_ACM_PROTO_AT_V25TER,
/* .iFunction = DYNAMIC */
};

View File

@ -324,7 +324,7 @@ static void loopback_disable(struct usb_function *f)
/*-------------------------------------------------------------------------*/
static int __ref loopback_bind_config(struct usb_configuration *c)
static int __init loopback_bind_config(struct usb_configuration *c)
{
struct f_loopback *loop;
int status;
@ -346,10 +346,9 @@ static int __ref loopback_bind_config(struct usb_configuration *c)
return status;
}
static struct usb_configuration loopback_driver = {
static struct usb_configuration loopback_driver = {
.label = "loopback",
.strings = loopback_strings,
.bind = loopback_bind_config,
.bConfigurationValue = 2,
.bmAttributes = USB_CONFIG_ATT_SELFPOWER,
/* .iConfiguration = DYNAMIC */
@ -382,5 +381,5 @@ int __init loopback_add(struct usb_composite_dev *cdev, bool autoresume)
loopback_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
}
return usb_add_config(cdev, &loopback_driver);
return usb_add_config(cdev, &loopback_driver, loopback_bind_config);
}

View File

@ -73,6 +73,8 @@
* being removable.
* ->cdrom Flag specifying that LUN shall be reported as
* being a CD-ROM.
* ->nofua Flag specifying that FUA flag in SCSI WRITE(10,12)
* commands for this LUN shall be ignored.
*
* lun_name_format A printf-like format for names of the LUN
* devices. This determines how the
@ -127,6 +129,8 @@
* Default true, boolean for removable media.
* cdrom=b[,b...] Default false, boolean for whether to emulate
* a CD-ROM drive.
* nofua=b[,b...] Default false, booleans for ignore FUA flag
* in SCSI WRITE(10,12) commands
* luns=N Default N = number of filenames, number of
* LUNs to support.
* stall Default determined according to the type of
@ -409,6 +413,7 @@ struct fsg_config {
char ro;
char removable;
char cdrom;
char nofua;
} luns[FSG_MAX_LUNS];
const char *lun_name_format;
@ -736,7 +741,7 @@ static int do_read(struct fsg_common *common)
/* Get the starting Logical Block Address and check that it's
* not too big */
if (common->cmnd[0] == SC_READ_6)
if (common->cmnd[0] == READ_6)
lba = get_unaligned_be24(&common->cmnd[1]);
else {
lba = get_unaligned_be32(&common->cmnd[2]);
@ -874,7 +879,7 @@ static int do_write(struct fsg_common *common)
/* Get the starting Logical Block Address and check that it's
* not too big */
if (common->cmnd[0] == SC_WRITE_6)
if (common->cmnd[0] == WRITE_6)
lba = get_unaligned_be24(&common->cmnd[1]);
else {
lba = get_unaligned_be32(&common->cmnd[2]);
@ -887,7 +892,7 @@ static int do_write(struct fsg_common *common)
curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
return -EINVAL;
}
if (common->cmnd[1] & 0x08) { /* FUA */
if (!curlun->nofua && (common->cmnd[1] & 0x08)) { /* FUA */
spin_lock(&curlun->filp->f_lock);
curlun->filp->f_flags |= O_SYNC;
spin_unlock(&curlun->filp->f_lock);
@ -1181,7 +1186,7 @@ static int do_inquiry(struct fsg_common *common, struct fsg_buffhd *bh)
return 36;
}
buf[0] = curlun->cdrom ? TYPE_CDROM : TYPE_DISK;
buf[0] = curlun->cdrom ? TYPE_ROM : TYPE_DISK;
buf[1] = curlun->removable ? 0x80 : 0;
buf[2] = 2; /* ANSI SCSI level 2 */
buf[3] = 2; /* SCSI-2 INQUIRY data format */
@ -1348,11 +1353,11 @@ static int do_mode_sense(struct fsg_common *common, struct fsg_buffhd *bh)
* The only variable value is the WriteProtect bit. We will fill in
* the mode data length later. */
memset(buf, 0, 8);
if (mscmnd == SC_MODE_SENSE_6) {
if (mscmnd == MODE_SENSE) {
buf[2] = (curlun->ro ? 0x80 : 0x00); /* WP, DPOFUA */
buf += 4;
limit = 255;
} else { /* SC_MODE_SENSE_10 */
} else { /* MODE_SENSE_10 */
buf[3] = (curlun->ro ? 0x80 : 0x00); /* WP, DPOFUA */
buf += 8;
limit = 65535; /* Should really be FSG_BUFLEN */
@ -1392,7 +1397,7 @@ static int do_mode_sense(struct fsg_common *common, struct fsg_buffhd *bh)
}
/* Store the mode data length */
if (mscmnd == SC_MODE_SENSE_6)
if (mscmnd == MODE_SENSE)
buf0[0] = len - 1;
else
put_unaligned_be16(len - 2, buf0);
@ -1881,7 +1886,7 @@ static int check_command(struct fsg_common *common, int cmnd_size,
if (common->lun >= 0 && common->lun < common->nluns) {
curlun = &common->luns[common->lun];
common->curlun = curlun;
if (common->cmnd[0] != SC_REQUEST_SENSE) {
if (common->cmnd[0] != REQUEST_SENSE) {
curlun->sense_data = SS_NO_SENSE;
curlun->sense_data_info = 0;
curlun->info_valid = 0;
@ -1893,8 +1898,8 @@ static int check_command(struct fsg_common *common, int cmnd_size,
/* INQUIRY and REQUEST SENSE commands are explicitly allowed
* to use unsupported LUNs; all others may not. */
if (common->cmnd[0] != SC_INQUIRY &&
common->cmnd[0] != SC_REQUEST_SENSE) {
if (common->cmnd[0] != INQUIRY &&
common->cmnd[0] != REQUEST_SENSE) {
DBG(common, "unsupported LUN %d\n", common->lun);
return -EINVAL;
}
@ -1903,8 +1908,8 @@ static int check_command(struct fsg_common *common, int cmnd_size,
/* 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 &&
common->cmnd[0] != SC_INQUIRY &&
common->cmnd[0] != SC_REQUEST_SENSE) {
common->cmnd[0] != INQUIRY &&
common->cmnd[0] != REQUEST_SENSE) {
curlun->sense_data = curlun->unit_attention_data;
curlun->unit_attention_data = SS_NO_SENSE;
return -EINVAL;
@ -1955,7 +1960,7 @@ static int do_scsi_command(struct fsg_common *common)
down_read(&common->filesem); /* We're using the backing file */
switch (common->cmnd[0]) {
case SC_INQUIRY:
case INQUIRY:
common->data_size_from_cmnd = common->cmnd[4];
reply = check_command(common, 6, DATA_DIR_TO_HOST,
(1<<4), 0,
@ -1964,7 +1969,7 @@ static int do_scsi_command(struct fsg_common *common)
reply = do_inquiry(common, bh);
break;
case SC_MODE_SELECT_6:
case MODE_SELECT:
common->data_size_from_cmnd = common->cmnd[4];
reply = check_command(common, 6, DATA_DIR_FROM_HOST,
(1<<1) | (1<<4), 0,
@ -1973,7 +1978,7 @@ static int do_scsi_command(struct fsg_common *common)
reply = do_mode_select(common, bh);
break;
case SC_MODE_SELECT_10:
case MODE_SELECT_10:
common->data_size_from_cmnd =
get_unaligned_be16(&common->cmnd[7]);
reply = check_command(common, 10, DATA_DIR_FROM_HOST,
@ -1983,7 +1988,7 @@ static int do_scsi_command(struct fsg_common *common)
reply = do_mode_select(common, bh);
break;
case SC_MODE_SENSE_6:
case MODE_SENSE:
common->data_size_from_cmnd = common->cmnd[4];
reply = check_command(common, 6, DATA_DIR_TO_HOST,
(1<<1) | (1<<2) | (1<<4), 0,
@ -1992,7 +1997,7 @@ static int do_scsi_command(struct fsg_common *common)
reply = do_mode_sense(common, bh);
break;
case SC_MODE_SENSE_10:
case MODE_SENSE_10:
common->data_size_from_cmnd =
get_unaligned_be16(&common->cmnd[7]);
reply = check_command(common, 10, DATA_DIR_TO_HOST,
@ -2002,7 +2007,7 @@ static int do_scsi_command(struct fsg_common *common)
reply = do_mode_sense(common, bh);
break;
case SC_PREVENT_ALLOW_MEDIUM_REMOVAL:
case ALLOW_MEDIUM_REMOVAL:
common->data_size_from_cmnd = 0;
reply = check_command(common, 6, DATA_DIR_NONE,
(1<<4), 0,
@ -2011,7 +2016,7 @@ static int do_scsi_command(struct fsg_common *common)
reply = do_prevent_allow(common);
break;
case SC_READ_6:
case READ_6:
i = common->cmnd[4];
common->data_size_from_cmnd = (i == 0 ? 256 : i) << 9;
reply = check_command(common, 6, DATA_DIR_TO_HOST,
@ -2021,7 +2026,7 @@ static int do_scsi_command(struct fsg_common *common)
reply = do_read(common);
break;
case SC_READ_10:
case READ_10:
common->data_size_from_cmnd =
get_unaligned_be16(&common->cmnd[7]) << 9;
reply = check_command(common, 10, DATA_DIR_TO_HOST,
@ -2031,7 +2036,7 @@ static int do_scsi_command(struct fsg_common *common)
reply = do_read(common);
break;
case SC_READ_12:
case READ_12:
common->data_size_from_cmnd =
get_unaligned_be32(&common->cmnd[6]) << 9;
reply = check_command(common, 12, DATA_DIR_TO_HOST,
@ -2041,7 +2046,7 @@ static int do_scsi_command(struct fsg_common *common)
reply = do_read(common);
break;
case SC_READ_CAPACITY:
case READ_CAPACITY:
common->data_size_from_cmnd = 8;
reply = check_command(common, 10, DATA_DIR_TO_HOST,
(0xf<<2) | (1<<8), 1,
@ -2050,7 +2055,7 @@ static int do_scsi_command(struct fsg_common *common)
reply = do_read_capacity(common, bh);
break;
case SC_READ_HEADER:
case READ_HEADER:
if (!common->curlun || !common->curlun->cdrom)
goto unknown_cmnd;
common->data_size_from_cmnd =
@ -2062,7 +2067,7 @@ static int do_scsi_command(struct fsg_common *common)
reply = do_read_header(common, bh);
break;
case SC_READ_TOC:
case READ_TOC:
if (!common->curlun || !common->curlun->cdrom)
goto unknown_cmnd;
common->data_size_from_cmnd =
@ -2074,7 +2079,7 @@ static int do_scsi_command(struct fsg_common *common)
reply = do_read_toc(common, bh);
break;
case SC_READ_FORMAT_CAPACITIES:
case READ_FORMAT_CAPACITIES:
common->data_size_from_cmnd =
get_unaligned_be16(&common->cmnd[7]);
reply = check_command(common, 10, DATA_DIR_TO_HOST,
@ -2084,7 +2089,7 @@ static int do_scsi_command(struct fsg_common *common)
reply = do_read_format_capacities(common, bh);
break;
case SC_REQUEST_SENSE:
case REQUEST_SENSE:
common->data_size_from_cmnd = common->cmnd[4];
reply = check_command(common, 6, DATA_DIR_TO_HOST,
(1<<4), 0,
@ -2093,7 +2098,7 @@ static int do_scsi_command(struct fsg_common *common)
reply = do_request_sense(common, bh);
break;
case SC_START_STOP_UNIT:
case START_STOP:
common->data_size_from_cmnd = 0;
reply = check_command(common, 6, DATA_DIR_NONE,
(1<<1) | (1<<4), 0,
@ -2102,7 +2107,7 @@ static int do_scsi_command(struct fsg_common *common)
reply = do_start_stop(common);
break;
case SC_SYNCHRONIZE_CACHE:
case SYNCHRONIZE_CACHE:
common->data_size_from_cmnd = 0;
reply = check_command(common, 10, DATA_DIR_NONE,
(0xf<<2) | (3<<7), 1,
@ -2111,7 +2116,7 @@ static int do_scsi_command(struct fsg_common *common)
reply = do_synchronize_cache(common);
break;
case SC_TEST_UNIT_READY:
case TEST_UNIT_READY:
common->data_size_from_cmnd = 0;
reply = check_command(common, 6, DATA_DIR_NONE,
0, 1,
@ -2120,7 +2125,7 @@ static int do_scsi_command(struct fsg_common *common)
/* Although optional, this command is used by MS-Windows. We
* support a minimal version: BytChk must be 0. */
case SC_VERIFY:
case VERIFY:
common->data_size_from_cmnd = 0;
reply = check_command(common, 10, DATA_DIR_NONE,
(1<<1) | (0xf<<2) | (3<<7), 1,
@ -2129,7 +2134,7 @@ static int do_scsi_command(struct fsg_common *common)
reply = do_verify(common);
break;
case SC_WRITE_6:
case WRITE_6:
i = common->cmnd[4];
common->data_size_from_cmnd = (i == 0 ? 256 : i) << 9;
reply = check_command(common, 6, DATA_DIR_FROM_HOST,
@ -2139,7 +2144,7 @@ static int do_scsi_command(struct fsg_common *common)
reply = do_write(common);
break;
case SC_WRITE_10:
case WRITE_10:
common->data_size_from_cmnd =
get_unaligned_be16(&common->cmnd[7]) << 9;
reply = check_command(common, 10, DATA_DIR_FROM_HOST,
@ -2149,7 +2154,7 @@ static int do_scsi_command(struct fsg_common *common)
reply = do_write(common);
break;
case SC_WRITE_12:
case WRITE_12:
common->data_size_from_cmnd =
get_unaligned_be32(&common->cmnd[6]) << 9;
reply = check_command(common, 12, DATA_DIR_FROM_HOST,
@ -2163,10 +2168,10 @@ static int do_scsi_command(struct fsg_common *common)
* 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 SC_FORMAT_UNIT:
case SC_RELEASE:
case SC_RESERVE:
case SC_SEND_DIAGNOSTIC:
case FORMAT_UNIT:
case RELEASE:
case RESERVE:
case SEND_DIAGNOSTIC:
/* Fall through */
default:
@ -2662,6 +2667,7 @@ static int fsg_main_thread(void *common_)
/* Write permission is checked per LUN in store_*() functions. */
static DEVICE_ATTR(ro, 0644, fsg_show_ro, fsg_store_ro);
static DEVICE_ATTR(nofua, 0644, fsg_show_nofua, fsg_store_nofua);
static DEVICE_ATTR(file, 0644, fsg_show_file, fsg_store_file);
@ -2766,6 +2772,9 @@ static struct fsg_common *fsg_common_init(struct fsg_common *common,
if (rc)
goto error_luns;
rc = device_create_file(&curlun->dev, &dev_attr_file);
if (rc)
goto error_luns;
rc = device_create_file(&curlun->dev, &dev_attr_nofua);
if (rc)
goto error_luns;
@ -2911,6 +2920,7 @@ static void fsg_common_release(struct kref *ref)
/* In error recovery common->nluns may be zero. */
for (; i; --i, ++lun) {
device_remove_file(&lun->dev, &dev_attr_nofua);
device_remove_file(&lun->dev, &dev_attr_ro);
device_remove_file(&lun->dev, &dev_attr_file);
fsg_lun_close(lun);
@ -3069,8 +3079,10 @@ struct fsg_module_parameters {
int ro[FSG_MAX_LUNS];
int removable[FSG_MAX_LUNS];
int cdrom[FSG_MAX_LUNS];
int nofua[FSG_MAX_LUNS];
unsigned int file_count, ro_count, removable_count, cdrom_count;
unsigned int nofua_count;
unsigned int luns; /* nluns */
int stall; /* can_stall */
};
@ -3096,6 +3108,8 @@ struct fsg_module_parameters {
"true to simulate removable media"); \
_FSG_MODULE_PARAM_ARRAY(prefix, params, cdrom, bool, \
"true to simulate CD-ROM instead of disk"); \
_FSG_MODULE_PARAM_ARRAY(prefix, params, nofua, bool, \
"true to ignore SCSI WRITE(10,12) FUA bit"); \
_FSG_MODULE_PARAM(prefix, params, luns, uint, \
"number of LUNs"); \
_FSG_MODULE_PARAM(prefix, params, stall, bool, \

View File

@ -404,7 +404,7 @@ static void sourcesink_disable(struct usb_function *f)
/*-------------------------------------------------------------------------*/
static int __ref sourcesink_bind_config(struct usb_configuration *c)
static int __init sourcesink_bind_config(struct usb_configuration *c)
{
struct f_sourcesink *ss;
int status;
@ -498,7 +498,6 @@ static int sourcesink_setup(struct usb_configuration *c,
static struct usb_configuration sourcesink_driver = {
.label = "source/sink",
.strings = sourcesink_strings,
.bind = sourcesink_bind_config,
.setup = sourcesink_setup,
.bConfigurationValue = 3,
.bmAttributes = USB_CONFIG_ATT_SELFPOWER,
@ -532,5 +531,5 @@ int __init sourcesink_add(struct usb_composite_dev *cdev, bool autoresume)
sourcesink_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
}
return usb_add_config(cdev, &sourcesink_driver);
return usb_add_config(cdev, &sourcesink_driver, sourcesink_bind_config);
}

View File

@ -89,6 +89,7 @@
* 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
@ -108,12 +109,11 @@
* vendor=0xVVVV Default 0x0525 (NetChip), USB Vendor ID
* product=0xPPPP Default 0xa4a5 (FSG), USB Product ID
* release=0xRRRR Override the USB release number (bcdDevice)
* serial=HHHH... Override serial number (string of hex chars)
* 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", "ro",
* 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.
*
@ -273,13 +273,10 @@
#define DRIVER_DESC "File-backed Storage Gadget"
#define DRIVER_NAME "g_file_storage"
/* DRIVER_VERSION must be at least 6 characters long, as it is used
* to generate a fallback serial number. */
#define DRIVER_VERSION "20 November 2008"
#define DRIVER_VERSION "1 September 2010"
static char fsg_string_manufacturer[64];
static const char fsg_string_product[] = DRIVER_DESC;
static char fsg_string_serial[13];
static const char fsg_string_config[] = "Self-powered";
static const char fsg_string_interface[] = "Mass Storage";
@ -305,6 +302,7 @@ MODULE_LICENSE("Dual BSD/GPL");
static struct {
char *file[FSG_MAX_LUNS];
char *serial;
int ro[FSG_MAX_LUNS];
int nofua[FSG_MAX_LUNS];
unsigned int num_filenames;
@ -321,7 +319,6 @@ static struct {
unsigned short vendor;
unsigned short product;
unsigned short release;
char *serial;
unsigned int buflen;
int transport_type;
@ -346,6 +343,9 @@ 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");
@ -365,9 +365,6 @@ 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");
module_param_named(serial, mod_data.serial, charp, S_IRUGO);
MODULE_PARM_DESC(serial, "USB serial number");
/* In the non-TEST version, only the module parameters listed above
* are available. */
#ifdef CONFIG_USB_FILE_STORAGE_TEST
@ -786,7 +783,7 @@ 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] = {
SC_SEND_DIAGNOSTIC, 4, 0xff, 0xff, 0xff, 0xff};
SEND_DIAGNOSTIC, 4, 0xff, 0xff, 0xff, 0xff};
/* Error in command transfer? */
if (req->status || req->length != req->actual ||
@ -1138,7 +1135,7 @@ static int do_read(struct fsg_dev *fsg)
/* Get the starting Logical Block Address and check that it's
* not too big */
if (fsg->cmnd[0] == SC_READ_6)
if (fsg->cmnd[0] == READ_6)
lba = get_unaligned_be24(&fsg->cmnd[1]);
else {
lba = get_unaligned_be32(&fsg->cmnd[2]);
@ -1273,7 +1270,7 @@ static int do_write(struct fsg_dev *fsg)
/* Get the starting Logical Block Address and check that it's
* not too big */
if (fsg->cmnd[0] == SC_WRITE_6)
if (fsg->cmnd[0] == WRITE_6)
lba = get_unaligned_be24(&fsg->cmnd[1]);
else {
lba = get_unaligned_be32(&fsg->cmnd[2]);
@ -1581,7 +1578,7 @@ static int do_inquiry(struct fsg_dev *fsg, struct fsg_buffhd *bh)
}
memset(buf, 0, 8);
buf[0] = (mod_data.cdrom ? TYPE_CDROM : TYPE_DISK);
buf[0] = (mod_data.cdrom ? TYPE_ROM : TYPE_DISK);
if (mod_data.removable)
buf[1] = 0x80;
buf[2] = 2; // ANSI SCSI level 2
@ -1750,11 +1747,11 @@ static int do_mode_sense(struct fsg_dev *fsg, struct fsg_buffhd *bh)
* The only variable value is the WriteProtect bit. We will fill in
* the mode data length later. */
memset(buf, 0, 8);
if (mscmnd == SC_MODE_SENSE_6) {
if (mscmnd == MODE_SENSE) {
buf[2] = (curlun->ro ? 0x80 : 0x00); // WP, DPOFUA
buf += 4;
limit = 255;
} else { // SC_MODE_SENSE_10
} else { // MODE_SENSE_10
buf[3] = (curlun->ro ? 0x80 : 0x00); // WP, DPOFUA
buf += 8;
limit = 65535; // Should really be mod_data.buflen
@ -1794,7 +1791,7 @@ static int do_mode_sense(struct fsg_dev *fsg, struct fsg_buffhd *bh)
}
/* Store the mode data length */
if (mscmnd == SC_MODE_SENSE_6)
if (mscmnd == MODE_SENSE)
buf0[0] = len - 1;
else
put_unaligned_be16(len - 2, buf0);
@ -2319,7 +2316,7 @@ static int check_command(struct fsg_dev *fsg, int cmnd_size,
/* Check the LUN */
if (fsg->lun >= 0 && fsg->lun < fsg->nluns) {
fsg->curlun = curlun = &fsg->luns[fsg->lun];
if (fsg->cmnd[0] != SC_REQUEST_SENSE) {
if (fsg->cmnd[0] != REQUEST_SENSE) {
curlun->sense_data = SS_NO_SENSE;
curlun->sense_data_info = 0;
curlun->info_valid = 0;
@ -2330,8 +2327,8 @@ static int check_command(struct fsg_dev *fsg, int cmnd_size,
/* INQUIRY and REQUEST SENSE commands are explicitly allowed
* to use unsupported LUNs; all others may not. */
if (fsg->cmnd[0] != SC_INQUIRY &&
fsg->cmnd[0] != SC_REQUEST_SENSE) {
if (fsg->cmnd[0] != INQUIRY &&
fsg->cmnd[0] != REQUEST_SENSE) {
DBG(fsg, "unsupported LUN %d\n", fsg->lun);
return -EINVAL;
}
@ -2340,8 +2337,8 @@ static int check_command(struct fsg_dev *fsg, int cmnd_size,
/* 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] != SC_INQUIRY &&
fsg->cmnd[0] != SC_REQUEST_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;
@ -2391,7 +2388,7 @@ static int do_scsi_command(struct fsg_dev *fsg)
down_read(&fsg->filesem); // We're using the backing file
switch (fsg->cmnd[0]) {
case SC_INQUIRY:
case INQUIRY:
fsg->data_size_from_cmnd = fsg->cmnd[4];
if ((reply = check_command(fsg, 6, DATA_DIR_TO_HOST,
(1<<4), 0,
@ -2399,7 +2396,7 @@ static int do_scsi_command(struct fsg_dev *fsg)
reply = do_inquiry(fsg, bh);
break;
case SC_MODE_SELECT_6:
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,
@ -2407,7 +2404,7 @@ static int do_scsi_command(struct fsg_dev *fsg)
reply = do_mode_select(fsg, bh);
break;
case SC_MODE_SELECT_10:
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,
@ -2415,7 +2412,7 @@ static int do_scsi_command(struct fsg_dev *fsg)
reply = do_mode_select(fsg, bh);
break;
case SC_MODE_SENSE_6:
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,
@ -2423,7 +2420,7 @@ static int do_scsi_command(struct fsg_dev *fsg)
reply = do_mode_sense(fsg, bh);
break;
case SC_MODE_SENSE_10:
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,
@ -2431,7 +2428,7 @@ static int do_scsi_command(struct fsg_dev *fsg)
reply = do_mode_sense(fsg, bh);
break;
case SC_PREVENT_ALLOW_MEDIUM_REMOVAL:
case ALLOW_MEDIUM_REMOVAL:
fsg->data_size_from_cmnd = 0;
if ((reply = check_command(fsg, 6, DATA_DIR_NONE,
(1<<4), 0,
@ -2439,7 +2436,7 @@ static int do_scsi_command(struct fsg_dev *fsg)
reply = do_prevent_allow(fsg);
break;
case SC_READ_6:
case READ_6:
i = fsg->cmnd[4];
fsg->data_size_from_cmnd = (i == 0 ? 256 : i) << 9;
if ((reply = check_command(fsg, 6, DATA_DIR_TO_HOST,
@ -2448,7 +2445,7 @@ static int do_scsi_command(struct fsg_dev *fsg)
reply = do_read(fsg);
break;
case SC_READ_10:
case READ_10:
fsg->data_size_from_cmnd =
get_unaligned_be16(&fsg->cmnd[7]) << 9;
if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST,
@ -2457,7 +2454,7 @@ static int do_scsi_command(struct fsg_dev *fsg)
reply = do_read(fsg);
break;
case SC_READ_12:
case READ_12:
fsg->data_size_from_cmnd =
get_unaligned_be32(&fsg->cmnd[6]) << 9;
if ((reply = check_command(fsg, 12, DATA_DIR_TO_HOST,
@ -2466,7 +2463,7 @@ static int do_scsi_command(struct fsg_dev *fsg)
reply = do_read(fsg);
break;
case SC_READ_CAPACITY:
case READ_CAPACITY:
fsg->data_size_from_cmnd = 8;
if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST,
(0xf<<2) | (1<<8), 1,
@ -2474,7 +2471,7 @@ static int do_scsi_command(struct fsg_dev *fsg)
reply = do_read_capacity(fsg, bh);
break;
case SC_READ_HEADER:
case READ_HEADER:
if (!mod_data.cdrom)
goto unknown_cmnd;
fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]);
@ -2484,7 +2481,7 @@ static int do_scsi_command(struct fsg_dev *fsg)
reply = do_read_header(fsg, bh);
break;
case SC_READ_TOC:
case READ_TOC:
if (!mod_data.cdrom)
goto unknown_cmnd;
fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]);
@ -2494,7 +2491,7 @@ static int do_scsi_command(struct fsg_dev *fsg)
reply = do_read_toc(fsg, bh);
break;
case SC_READ_FORMAT_CAPACITIES:
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,
@ -2502,7 +2499,7 @@ static int do_scsi_command(struct fsg_dev *fsg)
reply = do_read_format_capacities(fsg, bh);
break;
case SC_REQUEST_SENSE:
case REQUEST_SENSE:
fsg->data_size_from_cmnd = fsg->cmnd[4];
if ((reply = check_command(fsg, 6, DATA_DIR_TO_HOST,
(1<<4), 0,
@ -2510,7 +2507,7 @@ static int do_scsi_command(struct fsg_dev *fsg)
reply = do_request_sense(fsg, bh);
break;
case SC_START_STOP_UNIT:
case START_STOP:
fsg->data_size_from_cmnd = 0;
if ((reply = check_command(fsg, 6, DATA_DIR_NONE,
(1<<1) | (1<<4), 0,
@ -2518,7 +2515,7 @@ static int do_scsi_command(struct fsg_dev *fsg)
reply = do_start_stop(fsg);
break;
case SC_SYNCHRONIZE_CACHE:
case SYNCHRONIZE_CACHE:
fsg->data_size_from_cmnd = 0;
if ((reply = check_command(fsg, 10, DATA_DIR_NONE,
(0xf<<2) | (3<<7), 1,
@ -2526,7 +2523,7 @@ static int do_scsi_command(struct fsg_dev *fsg)
reply = do_synchronize_cache(fsg);
break;
case SC_TEST_UNIT_READY:
case TEST_UNIT_READY:
fsg->data_size_from_cmnd = 0;
reply = check_command(fsg, 6, DATA_DIR_NONE,
0, 1,
@ -2535,7 +2532,7 @@ static int do_scsi_command(struct fsg_dev *fsg)
/* Although optional, this command is used by MS-Windows. We
* support a minimal version: BytChk must be 0. */
case SC_VERIFY:
case VERIFY:
fsg->data_size_from_cmnd = 0;
if ((reply = check_command(fsg, 10, DATA_DIR_NONE,
(1<<1) | (0xf<<2) | (3<<7), 1,
@ -2543,7 +2540,7 @@ static int do_scsi_command(struct fsg_dev *fsg)
reply = do_verify(fsg);
break;
case SC_WRITE_6:
case WRITE_6:
i = fsg->cmnd[4];
fsg->data_size_from_cmnd = (i == 0 ? 256 : i) << 9;
if ((reply = check_command(fsg, 6, DATA_DIR_FROM_HOST,
@ -2552,7 +2549,7 @@ static int do_scsi_command(struct fsg_dev *fsg)
reply = do_write(fsg);
break;
case SC_WRITE_10:
case WRITE_10:
fsg->data_size_from_cmnd =
get_unaligned_be16(&fsg->cmnd[7]) << 9;
if ((reply = check_command(fsg, 10, DATA_DIR_FROM_HOST,
@ -2561,7 +2558,7 @@ static int do_scsi_command(struct fsg_dev *fsg)
reply = do_write(fsg);
break;
case SC_WRITE_12:
case WRITE_12:
fsg->data_size_from_cmnd =
get_unaligned_be32(&fsg->cmnd[6]) << 9;
if ((reply = check_command(fsg, 12, DATA_DIR_FROM_HOST,
@ -2574,10 +2571,10 @@ static int do_scsi_command(struct fsg_dev *fsg)
* 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 SC_FORMAT_UNIT:
case SC_RELEASE:
case SC_RESERVE:
case SC_SEND_DIAGNOSTIC:
case FORMAT_UNIT:
case RELEASE:
case RESERVE:
case SEND_DIAGNOSTIC:
// Fall through
default:
@ -3178,6 +3175,7 @@ static void /* __init_or_exit */ fsg_unbind(struct usb_gadget *gadget)
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);
@ -3213,7 +3211,6 @@ static int __init check_parameters(struct fsg_dev *fsg)
{
int prot;
int gcnum;
int i;
/* Store the default values */
mod_data.transport_type = USB_PR_BULK;
@ -3309,45 +3306,29 @@ static int __init check_parameters(struct fsg_dev *fsg)
if ((*ch < '0' || *ch > '9') &&
(*ch < 'A' || *ch > 'F')) { /* not uppercase hex */
WARNING(fsg,
"Invalid serial string character: %c; "
"Failing back to default\n",
"Invalid serial string character: %c\n",
*ch);
goto fill_serial;
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; "
"Failing back to default\n");
goto fill_serial;
WARNING(fsg, "Invalid serial string length!\n");
goto no_serial;
}
fsg_strings[FSG_STRING_SERIAL - 1].s = mod_data.serial;
} else {
WARNING(fsg,
"Userspace failed to provide serial number; "
"Failing back to default\n");
fill_serial:
/* Serial number not specified or invalid, make our own.
* We just encode it from the driver version string,
* 12 characters to comply with both CB[I] and BBB spec.
* Warning : Two devices running the same kernel will have
* the same fallback serial number. */
for (i = 0; i < 12; i += 2) {
unsigned char c = DRIVER_VERSION[i / 2];
if (!c)
break;
sprintf(&fsg_string_serial[i], "%02X", c);
}
WARNING(fsg, "No serial-number string provided!\n");
no_serial:
device_desc.iSerialNumber = 0;
}
return 0;
}
static int __ref fsg_bind(struct usb_gadget *gadget)
static int __init fsg_bind(struct usb_gadget *gadget)
{
struct fsg_dev *fsg = the_fsg;
int rc;
@ -3607,7 +3588,6 @@ static struct usb_gadget_driver fsg_driver = {
.speed = USB_SPEED_FULL,
#endif
.function = (char *) fsg_string_product,
.bind = fsg_bind,
.unbind = fsg_unbind,
.disconnect = fsg_disconnect,
.setup = fsg_setup,
@ -3649,7 +3629,7 @@ static int __init fsg_init(void)
if ((rc = fsg_alloc()) != 0)
return rc;
fsg = the_fsg;
if ((rc = usb_gadget_register_driver(&fsg_driver)) != 0)
if ((rc = usb_gadget_probe_driver(&fsg_driver, fsg_bind)) != 0)
kref_put(&fsg->ref, fsg_release);
return rc;
}

View File

@ -22,6 +22,10 @@
static struct clk *mxc_ahb_clk;
static struct clk *mxc_usb_clk;
/* workaround ENGcm09152 for i.MX35 */
#define USBPHYCTRL_OTGBASE_OFFSET 0x608
#define USBPHYCTRL_EVDO (1 << 23)
int fsl_udc_clk_init(struct platform_device *pdev)
{
struct fsl_usb2_platform_data *pdata;
@ -84,6 +88,17 @@ int fsl_udc_clk_init(struct platform_device *pdev)
void fsl_udc_clk_finalize(struct platform_device *pdev)
{
struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
#if defined(CONFIG_ARCH_MX35)
unsigned int v;
/* workaround ENGcm09152 for i.MX35 */
if (pdata->workaround & FLS_USB2_WORKAROUND_ENGCM09152) {
v = readl(MX35_IO_ADDRESS(MX35_OTG_BASE_ADDR +
USBPHYCTRL_OTGBASE_OFFSET));
writel(v | USBPHYCTRL_EVDO, MX35_IO_ADDRESS(MX35_OTG_BASE_ADDR +
USBPHYCTRL_OTGBASE_OFFSET));
}
#endif
/* ULPI transceivers don't need usbpll */
if (pdata->phy_mode == FSL_USB2_PHY_ULPI) {

View File

@ -2302,9 +2302,10 @@ static irqreturn_t qe_udc_irq(int irq, void *_udc)
}
/*-------------------------------------------------------------------------
Gadget driver register and unregister.
Gadget driver probe and unregister.
--------------------------------------------------------------------------*/
int usb_gadget_register_driver(struct usb_gadget_driver *driver)
int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
int (*bind)(struct usb_gadget *))
{
int retval;
unsigned long flags = 0;
@ -2315,8 +2316,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
if (!driver || (driver->speed != USB_SPEED_FULL
&& driver->speed != USB_SPEED_HIGH)
|| !driver->bind || !driver->disconnect
|| !driver->setup)
|| !bind || !driver->disconnect || !driver->setup)
return -EINVAL;
if (udc_controller->driver)
@ -2332,7 +2332,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
udc_controller->gadget.speed = (enum usb_device_speed)(driver->speed);
spin_unlock_irqrestore(&udc_controller->lock, flags);
retval = driver->bind(&udc_controller->gadget);
retval = bind(&udc_controller->gadget);
if (retval) {
dev_err(udc_controller->dev, "bind to %s --> %d",
driver->driver.name, retval);
@ -2353,7 +2353,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
udc_controller->gadget.name, driver->driver.name);
return 0;
}
EXPORT_SYMBOL(usb_gadget_register_driver);
EXPORT_SYMBOL(usb_gadget_probe_driver);
int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
{

View File

@ -1765,7 +1765,8 @@ static irqreturn_t fsl_udc_irq(int irq, void *_udc)
* Hook to gadget drivers
* Called by initialization code of gadget drivers
*----------------------------------------------------------------*/
int usb_gadget_register_driver(struct usb_gadget_driver *driver)
int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
int (*bind)(struct usb_gadget *))
{
int retval = -ENODEV;
unsigned long flags = 0;
@ -1775,8 +1776,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
if (!driver || (driver->speed != USB_SPEED_FULL
&& driver->speed != USB_SPEED_HIGH)
|| !driver->bind || !driver->disconnect
|| !driver->setup)
|| !bind || !driver->disconnect || !driver->setup)
return -EINVAL;
if (udc_controller->driver)
@ -1792,7 +1792,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
spin_unlock_irqrestore(&udc_controller->lock, flags);
/* bind udc driver to gadget driver */
retval = driver->bind(&udc_controller->gadget);
retval = bind(&udc_controller->gadget);
if (retval) {
VDBG("bind to %s --> %d", driver->driver.name, retval);
udc_controller->gadget.dev.driver = NULL;
@ -1814,7 +1814,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
retval);
return retval;
}
EXPORT_SYMBOL(usb_gadget_register_driver);
EXPORT_SYMBOL(usb_gadget_probe_driver);
/* Disconnect from gadget driver */
int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)

View File

@ -52,9 +52,8 @@ MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_AUTHOR("Michal Nazarewicz");
MODULE_LICENSE("GPL");
static unsigned short gfs_vendor_id = 0x0525; /* XXX NetChip */
static unsigned short gfs_product_id = 0xa4ac; /* XXX */
#define GFS_VENDOR_ID 0x1d6b /* Linux Foundation */
#define GFS_PRODUCT_ID 0x0105 /* FunctionFS Gadget */
static struct usb_device_descriptor gfs_dev_desc = {
.bLength = sizeof gfs_dev_desc,
@ -63,29 +62,16 @@ static struct usb_device_descriptor gfs_dev_desc = {
.bcdUSB = cpu_to_le16(0x0200),
.bDeviceClass = USB_CLASS_PER_INTERFACE,
/* Vendor and product id can be overridden by module parameters. */
/* .idVendor = cpu_to_le16(gfs_vendor_id), */
/* .idProduct = cpu_to_le16(gfs_product_id), */
/* .bcdDevice = f(hardware) */
/* .iManufacturer = DYNAMIC */
/* .iProduct = DYNAMIC */
/* NO SERIAL NUMBER */
.bNumConfigurations = 1,
.idVendor = cpu_to_le16(GFS_VENDOR_ID),
.idProduct = cpu_to_le16(GFS_PRODUCT_ID),
};
#define GFS_MODULE_PARAM_DESC(name, field) \
MODULE_PARM_DESC(name, "Value of the " #field " field of the device descriptor sent to the host. Takes effect only prior to the user-space driver registering to the FunctionFS.")
module_param_named(usb_class, gfs_dev_desc.bDeviceClass, byte, 0644);
GFS_MODULE_PARAM_DESC(usb_class, bDeviceClass);
module_param_named(usb_subclass, gfs_dev_desc.bDeviceSubClass, byte, 0644);
GFS_MODULE_PARAM_DESC(usb_subclass, bDeviceSubClass);
module_param_named(usb_protocol, gfs_dev_desc.bDeviceProtocol, byte, 0644);
GFS_MODULE_PARAM_DESC(usb_protocol, bDeviceProtocol);
module_param_named(usb_vendor, gfs_vendor_id, ushort, 0644);
GFS_MODULE_PARAM_DESC(usb_vendor, idVendor);
module_param_named(usb_product, gfs_product_id, ushort, 0644);
GFS_MODULE_PARAM_DESC(usb_product, idProduct);
module_param_named(bDeviceClass, gfs_dev_desc.bDeviceClass, byte, 0644);
MODULE_PARM_DESC(bDeviceClass, "USB Device class");
module_param_named(bDeviceSubClass, gfs_dev_desc.bDeviceSubClass, byte, 0644);
MODULE_PARM_DESC(bDeviceSubClass, "USB Device subclass");
module_param_named(bDeviceProtocol, gfs_dev_desc.bDeviceProtocol, byte, 0644);
MODULE_PARM_DESC(bDeviceProtocol, "USB Device protocol");
@ -95,8 +81,10 @@ static const struct usb_descriptor_header *gfs_otg_desc[] = {
.bLength = sizeof(struct usb_otg_descriptor),
.bDescriptorType = USB_DT_OTG,
/* REVISIT SRP-only hardware is possible, although
* it would not be called "OTG" ... */
/*
* REVISIT SRP-only hardware is possible, although
* it would not be called "OTG" ...
*/
.bmAttributes = USB_OTG_SRP | USB_OTG_HNP,
},
@ -105,19 +93,7 @@ static const struct usb_descriptor_header *gfs_otg_desc[] = {
/* string IDs are assigned dynamically */
enum {
GFS_STRING_MANUFACTURER_IDX,
GFS_STRING_PRODUCT_IDX,
GFS_STRING_FIRST_CONFIG_IDX,
};
static char gfs_manufacturer[50];
static const char gfs_driver_desc[] = DRIVER_DESC;
static const char gfs_short_name[] = DRIVER_NAME;
static struct usb_string gfs_strings[] = {
[GFS_STRING_MANUFACTURER_IDX].s = gfs_manufacturer,
[GFS_STRING_PRODUCT_IDX].s = gfs_driver_desc,
#ifdef CONFIG_USB_FUNCTIONFS_RNDIS
{ .s = "FunctionFS + RNDIS" },
#endif
@ -168,11 +144,11 @@ static int gfs_unbind(struct usb_composite_dev *cdev);
static int gfs_do_config(struct usb_configuration *c);
static struct usb_composite_driver gfs_driver = {
.name = gfs_short_name,
.name = DRIVER_NAME,
.dev = &gfs_dev_desc,
.strings = gfs_dev_strings,
.bind = gfs_bind,
.unbind = gfs_unbind,
.iProduct = DRIVER_DESC,
};
@ -210,7 +186,7 @@ static int functionfs_ready_callback(struct ffs_data *ffs)
return -EBUSY;
gfs_ffs_data = ffs;
ret = usb_composite_register(&gfs_driver);
ret = usb_composite_probe(&gfs_driver, gfs_bind);
if (unlikely(ret < 0))
clear_bit(0, &gfs_registered);
return ret;
@ -245,20 +221,10 @@ static int gfs_bind(struct usb_composite_dev *cdev)
if (unlikely(ret < 0))
goto error_quick;
gfs_dev_desc.idVendor = cpu_to_le16(gfs_vendor_id);
gfs_dev_desc.idProduct = cpu_to_le16(gfs_product_id);
snprintf(gfs_manufacturer, sizeof gfs_manufacturer, "%s %s with %s",
init_utsname()->sysname, init_utsname()->release,
cdev->gadget->name);
ret = usb_string_ids_tab(cdev, gfs_strings);
if (unlikely(ret < 0))
goto error;
gfs_dev_desc.iManufacturer = gfs_strings[GFS_STRING_MANUFACTURER_IDX].id;
gfs_dev_desc.iProduct = gfs_strings[GFS_STRING_PRODUCT_IDX].id;
ret = functionfs_bind(gfs_ffs_data, cdev);
if (unlikely(ret < 0))
goto error;
@ -266,14 +232,12 @@ static int gfs_bind(struct usb_composite_dev *cdev)
for (i = 0; i < ARRAY_SIZE(gfs_configurations); ++i) {
struct gfs_configuration *c = gfs_configurations + i;
ret = GFS_STRING_FIRST_CONFIG_IDX + i;
c->c.label = gfs_strings[ret].s;
c->c.iConfiguration = gfs_strings[ret].id;
c->c.bind = gfs_do_config;
c->c.label = gfs_strings[i].s;
c->c.iConfiguration = gfs_strings[i].id;
c->c.bConfigurationValue = 1 + i;
c->c.bmAttributes = USB_CONFIG_ATT_SELFPOWER;
ret = usb_add_config(cdev, &c->c);
ret = usb_add_config(cdev, &c->c, gfs_do_config);
if (unlikely(ret < 0))
goto error_unbind;
}
@ -293,13 +257,14 @@ static int gfs_unbind(struct usb_composite_dev *cdev)
{
ENTER();
/* We may have been called in an error recovery frem
/*
* We may have been called in an error recovery from
* composite_bind() after gfs_unbind() failure so we need to
* check if gfs_ffs_data is not NULL since gfs_bind() handles
* all error recovery itself. I'd rather we werent called
* from composite on orror recovery, but what you're gonna
* do...? */
* do...?
*/
if (gfs_ffs_data) {
gether_cleanup();
functionfs_unbind(gfs_ffs_data);
@ -334,14 +299,16 @@ static int gfs_do_config(struct usb_configuration *c)
if (unlikely(ret < 0))
return ret;
/* After previous do_configs there may be some invalid
/*
* After previous do_configs there may be some invalid
* pointers in c->interface array. This happens every time
* a user space function with fewer interfaces than a user
* space function that was run before the new one is run. The
* compasit's set_config() assumes that if there is no more
* then MAX_CONFIG_INTERFACES interfaces in a configuration
* then there is a NULL pointer after the last interface in
* c->interface array. We need to make sure this is true. */
* c->interface array. We need to make sure this is true.
*/
if (c->next_interface_id < ARRAY_SIZE(c->interface))
c->interface[c->next_interface_id] = NULL;
@ -350,10 +317,12 @@ static int gfs_do_config(struct usb_configuration *c)
#ifdef CONFIG_USB_FUNCTIONFS_ETH
static int eth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
{
return can_support_ecm(c->cdev->gadget)
? ecm_bind_config(c, ethaddr)
: geth_bind_config(c, ethaddr);
}
#endif

View File

@ -1157,7 +1157,7 @@ static int gmidi_register_card(struct gmidi_device *dev)
/*
* Creates an output endpoint, and initializes output ports.
*/
static int __ref gmidi_bind(struct usb_gadget *gadget)
static int __init gmidi_bind(struct usb_gadget *gadget)
{
struct gmidi_device *dev;
struct usb_ep *in_ep, *out_ep;
@ -1292,7 +1292,6 @@ static void gmidi_resume(struct usb_gadget *gadget)
static struct usb_gadget_driver gmidi_driver = {
.speed = USB_SPEED_FULL,
.function = (char *)longname,
.bind = gmidi_bind,
.unbind = gmidi_unbind,
.setup = gmidi_setup,
@ -1309,7 +1308,7 @@ static struct usb_gadget_driver gmidi_driver = {
static int __init gmidi_init(void)
{
return usb_gadget_register_driver(&gmidi_driver);
return usb_gadget_probe_driver(&gmidi_driver, gmidi_bind);
}
module_init(gmidi_init);

View File

@ -1343,14 +1343,15 @@ static struct goku_udc *the_controller;
* disconnect is reported. then a host may connect again, or
* the driver might get unbound.
*/
int usb_gadget_register_driver(struct usb_gadget_driver *driver)
int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
int (*bind)(struct usb_gadget *))
{
struct goku_udc *dev = the_controller;
int retval;
if (!driver
|| driver->speed < USB_SPEED_FULL
|| !driver->bind
|| !bind
|| !driver->disconnect
|| !driver->setup)
return -EINVAL;
@ -1363,7 +1364,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
driver->driver.bus = NULL;
dev->driver = driver;
dev->gadget.dev.driver = &driver->driver;
retval = driver->bind(&dev->gadget);
retval = bind(&dev->gadget);
if (retval) {
DBG(dev, "bind to driver %s --> error %d\n",
driver->driver.name, retval);
@ -1380,7 +1381,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
DBG(dev, "registered gadget driver '%s'\n", driver->driver.name);
return 0;
}
EXPORT_SYMBOL(usb_gadget_register_driver);
EXPORT_SYMBOL(usb_gadget_probe_driver);
static void
stop_activity(struct goku_udc *dev, struct usb_gadget_driver *driver)
@ -1744,7 +1745,8 @@ static void goku_remove(struct pci_dev *pdev)
pci_resource_len (pdev, 0));
if (dev->enabled)
pci_disable_device(pdev);
device_unregister(&dev->gadget.dev);
if (dev->registered)
device_unregister(&dev->gadget.dev);
pci_set_drvdata(pdev, NULL);
dev->regs = NULL;
@ -1774,7 +1776,7 @@ static int goku_probe(struct pci_dev *pdev, const struct pci_device_id *id)
if (!pdev->irq) {
printk(KERN_ERR "Check PCI %s IRQ setup!\n", pci_name(pdev));
retval = -ENODEV;
goto done;
goto err;
}
/* alloc, and start init */
@ -1782,7 +1784,7 @@ static int goku_probe(struct pci_dev *pdev, const struct pci_device_id *id)
if (dev == NULL){
pr_debug("enomem %s\n", pci_name(pdev));
retval = -ENOMEM;
goto done;
goto err;
}
spin_lock_init(&dev->lock);
@ -1800,7 +1802,7 @@ static int goku_probe(struct pci_dev *pdev, const struct pci_device_id *id)
retval = pci_enable_device(pdev);
if (retval < 0) {
DBG(dev, "can't enable, %d\n", retval);
goto done;
goto err;
}
dev->enabled = 1;
@ -1809,7 +1811,7 @@ static int goku_probe(struct pci_dev *pdev, const struct pci_device_id *id)
if (!request_mem_region(resource, len, driver_name)) {
DBG(dev, "controller already in use\n");
retval = -EBUSY;
goto done;
goto err;
}
dev->got_region = 1;
@ -1817,7 +1819,7 @@ static int goku_probe(struct pci_dev *pdev, const struct pci_device_id *id)
if (base == NULL) {
DBG(dev, "can't map memory\n");
retval = -EFAULT;
goto done;
goto err;
}
dev->regs = (struct goku_udc_regs __iomem *) base;
@ -1833,7 +1835,7 @@ static int goku_probe(struct pci_dev *pdev, const struct pci_device_id *id)
driver_name, dev) != 0) {
DBG(dev, "request interrupt %d failed\n", pdev->irq);
retval = -EBUSY;
goto done;
goto err;
}
dev->got_irq = 1;
if (use_dma)
@ -1844,13 +1846,16 @@ static int goku_probe(struct pci_dev *pdev, const struct pci_device_id *id)
create_proc_read_entry(proc_node_name, 0, NULL, udc_proc_read, dev);
#endif
/* done */
the_controller = dev;
retval = device_register(&dev->gadget.dev);
if (retval == 0)
return 0;
if (retval) {
put_device(&dev->gadget.dev);
goto err;
}
dev->registered = 1;
return 0;
done:
err:
if (dev)
goku_remove (pdev);
return retval;

View File

@ -127,7 +127,7 @@ static struct usb_gadget_strings *dev_strings[] = {
/****************************** Configurations ******************************/
static int __ref do_config(struct usb_configuration *c)
static int __init do_config(struct usb_configuration *c)
{
struct hidg_func_node *e;
int func = 0, status = 0;
@ -148,7 +148,6 @@ static int __ref do_config(struct usb_configuration *c)
static struct usb_configuration config_driver = {
.label = "HID Gadget",
.bind = do_config,
.bConfigurationValue = 1,
/* .iConfiguration = DYNAMIC */
.bmAttributes = USB_CONFIG_ATT_SELFPOWER,
@ -156,7 +155,7 @@ static struct usb_configuration config_driver = {
/****************************** Gadget Bind ******************************/
static int __ref hid_bind(struct usb_composite_dev *cdev)
static int __init hid_bind(struct usb_composite_dev *cdev)
{
struct usb_gadget *gadget = cdev->gadget;
struct list_head *tmp;
@ -201,7 +200,7 @@ static int __ref hid_bind(struct usb_composite_dev *cdev)
device_desc.iProduct = status;
/* register our configuration */
status = usb_add_config(cdev, &config_driver);
status = usb_add_config(cdev, &config_driver, do_config);
if (status < 0)
return status;
@ -256,7 +255,6 @@ static struct usb_composite_driver hidg_driver = {
.name = "g_hid",
.dev = &device_desc,
.strings = dev_strings,
.bind = hid_bind,
.unbind = __exit_p(hid_unbind),
};
@ -282,7 +280,7 @@ static int __init hidg_init(void)
if (status < 0)
return status;
status = usb_composite_register(&hidg_driver);
status = usb_composite_probe(&hidg_driver, hid_bind);
if (status < 0)
platform_driver_unregister(&hidg_plat_driver);

View File

@ -1319,14 +1319,15 @@ static struct imx_udc_struct controller = {
* USB gadged driver functions
*******************************************************************************
*/
int usb_gadget_register_driver(struct usb_gadget_driver *driver)
int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
int (*bind)(struct usb_gadget *))
{
struct imx_udc_struct *imx_usb = &controller;
int retval;
if (!driver
|| driver->speed < USB_SPEED_FULL
|| !driver->bind
|| !bind
|| !driver->disconnect
|| !driver->setup)
return -EINVAL;
@ -1342,7 +1343,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
retval = device_add(&imx_usb->gadget.dev);
if (retval)
goto fail;
retval = driver->bind(&imx_usb->gadget);
retval = bind(&imx_usb->gadget);
if (retval) {
D_ERR(imx_usb->dev, "<%s> bind to driver %s --> error %d\n",
__func__, driver->driver.name, retval);
@ -1362,7 +1363,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
imx_usb->gadget.dev.driver = NULL;
return retval;
}
EXPORT_SYMBOL(usb_gadget_register_driver);
EXPORT_SYMBOL(usb_gadget_probe_driver);
int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
{

View File

@ -1774,7 +1774,6 @@ static struct usb_gadget_driver gadgetfs_driver = {
.speed = USB_SPEED_FULL,
#endif
.function = (char *) driver_desc,
.bind = gadgetfs_bind,
.unbind = gadgetfs_unbind,
.setup = gadgetfs_setup,
.disconnect = gadgetfs_disconnect,
@ -1797,7 +1796,6 @@ static int gadgetfs_probe (struct usb_gadget *gadget)
static struct usb_gadget_driver probe_driver = {
.speed = USB_SPEED_HIGH,
.bind = gadgetfs_probe,
.unbind = gadgetfs_nop,
.setup = (void *)gadgetfs_nop,
.disconnect = gadgetfs_nop,
@ -1907,7 +1905,7 @@ dev_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
/* triggers gadgetfs_bind(); then we can enumerate. */
spin_unlock_irq (&dev->lock);
value = usb_gadget_register_driver (&gadgetfs_driver);
value = usb_gadget_probe_driver(&gadgetfs_driver, gadgetfs_bind);
if (value != 0) {
kfree (dev->buf);
dev->buf = NULL;
@ -2046,7 +2044,7 @@ gadgetfs_fill_super (struct super_block *sb, void *opts, int silent)
return -ESRCH;
/* fake probe to determine $CHIP */
(void) usb_gadget_register_driver (&probe_driver);
(void) usb_gadget_probe_driver(&probe_driver, gadgetfs_probe);
if (!CHIP)
return -ENODEV;

File diff suppressed because it is too large Load Diff

View File

@ -18,11 +18,7 @@
*/
#include <linux/usb/langwell_udc.h>
#if defined(CONFIG_USB_LANGWELL_OTG)
#include <linux/usb/langwell_otg.h>
#endif
/*-------------------------------------------------------------------------*/
@ -199,7 +195,9 @@ struct langwell_udc {
vbus_active:1,
suspended:1,
stopped:1,
lpm:1; /* LPM capability */
lpm:1, /* LPM capability */
has_sram:1, /* SRAM caching */
got_sram:1;
/* pci state used to access those endpoints */
struct pci_dev *pdev;
@ -224,5 +222,12 @@ struct langwell_udc {
/* make sure release() is done */
struct completion *done;
/* for private SRAM caching */
unsigned int sram_addr;
unsigned int sram_size;
/* device status data for get_status request */
u16 dev_status;
};

View File

@ -408,7 +408,8 @@ static void udc_enable(struct lh7a40x_udc *dev)
/*
Register entry point for the peripheral controller driver.
*/
int usb_gadget_register_driver(struct usb_gadget_driver *driver)
int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
int (*bind)(struct usb_gadget *))
{
struct lh7a40x_udc *dev = the_controller;
int retval;
@ -417,7 +418,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
if (!driver
|| driver->speed != USB_SPEED_FULL
|| !driver->bind
|| !bind
|| !driver->disconnect
|| !driver->setup)
return -EINVAL;
@ -431,7 +432,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
dev->gadget.dev.driver = &driver->driver;
device_add(&dev->gadget.dev);
retval = driver->bind(&dev->gadget);
retval = bind(&dev->gadget);
if (retval) {
printk(KERN_WARNING "%s: bind to driver %s --> error %d\n",
dev->gadget.name, driver->driver.name, retval);
@ -453,8 +454,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
return 0;
}
EXPORT_SYMBOL(usb_gadget_register_driver);
EXPORT_SYMBOL(usb_gadget_probe_driver);
/*
Unregister entry point for the peripheral controller driver.

View File

@ -1454,14 +1454,15 @@ static struct usb_ep_ops m66592_ep_ops = {
/*-------------------------------------------------------------------------*/
static struct m66592 *the_controller;
int usb_gadget_register_driver(struct usb_gadget_driver *driver)
int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
int (*bind)(struct usb_gadget *))
{
struct m66592 *m66592 = the_controller;
int retval;
if (!driver
|| driver->speed != USB_SPEED_HIGH
|| !driver->bind
|| !bind
|| !driver->setup)
return -EINVAL;
if (!m66592)
@ -1480,7 +1481,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
goto error;
}
retval = driver->bind (&m66592->gadget);
retval = bind(&m66592->gadget);
if (retval) {
pr_err("bind to driver error (%d)\n", retval);
device_del(&m66592->gadget.dev);
@ -1505,7 +1506,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
return retval;
}
EXPORT_SYMBOL(usb_gadget_register_driver);
EXPORT_SYMBOL(usb_gadget_probe_driver);
int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
{

View File

@ -75,10 +75,6 @@ static struct usb_device_descriptor msg_device_desc = {
/* Vendor and product id can be overridden by module parameters. */
.idVendor = cpu_to_le16(FSG_VENDOR_ID),
.idProduct = cpu_to_le16(FSG_PRODUCT_ID),
/* .bcdDevice = f(hardware) */
/* .iManufacturer = DYNAMIC */
/* .iProduct = DYNAMIC */
/* NO SERIAL NUMBER */
.bNumConfigurations = 1,
};
@ -86,7 +82,8 @@ static struct usb_otg_descriptor otg_descriptor = {
.bLength = sizeof otg_descriptor,
.bDescriptorType = USB_DT_OTG,
/* REVISIT SRP-only hardware is possible, although
/*
* REVISIT SRP-only hardware is possible, although
* it would not be called "OTG" ...
*/
.bmAttributes = USB_OTG_SRP | USB_OTG_HNP,
@ -98,33 +95,6 @@ static const struct usb_descriptor_header *otg_desc[] = {
};
/* string IDs are assigned dynamically */
#define STRING_MANUFACTURER_IDX 0
#define STRING_PRODUCT_IDX 1
#define STRING_CONFIGURATION_IDX 2
static char manufacturer[50];
static struct usb_string strings_dev[] = {
[STRING_MANUFACTURER_IDX].s = manufacturer,
[STRING_PRODUCT_IDX].s = DRIVER_DESC,
[STRING_CONFIGURATION_IDX].s = "Self Powered",
{ } /* end of list */
};
static struct usb_gadget_strings stringtab_dev = {
.language = 0x0409, /* en-us */
.strings = strings_dev,
};
static struct usb_gadget_strings *dev_strings[] = {
&stringtab_dev,
NULL,
};
/****************************** Configurations ******************************/
static struct fsg_module_parameters mod_data = {
@ -141,7 +111,7 @@ static int msg_thread_exits(struct fsg_common *common)
return 0;
}
static int __ref msg_do_config(struct usb_configuration *c)
static int __init msg_do_config(struct usb_configuration *c)
{
static const struct fsg_operations ops = {
.thread_exits = msg_thread_exits,
@ -171,54 +141,23 @@ static int __ref msg_do_config(struct usb_configuration *c)
static struct usb_configuration msg_config_driver = {
.label = "Linux File-Backed Storage",
.bind = msg_do_config,
.bConfigurationValue = 1,
/* .iConfiguration = DYNAMIC */
.bmAttributes = USB_CONFIG_ATT_SELFPOWER,
};
/****************************** Gadget Bind ******************************/
static int __ref msg_bind(struct usb_composite_dev *cdev)
static int __init msg_bind(struct usb_composite_dev *cdev)
{
struct usb_gadget *gadget = cdev->gadget;
int status;
/* Allocate string descriptor numbers ... note that string
* contents can be overridden by the composite_dev glue.
*/
/* device descriptor strings: manufacturer, product */
snprintf(manufacturer, sizeof manufacturer, "%s %s with %s",
init_utsname()->sysname, init_utsname()->release,
gadget->name);
status = usb_string_id(cdev);
if (status < 0)
return status;
strings_dev[STRING_MANUFACTURER_IDX].id = status;
msg_device_desc.iManufacturer = status;
status = usb_string_id(cdev);
if (status < 0)
return status;
strings_dev[STRING_PRODUCT_IDX].id = status;
msg_device_desc.iProduct = status;
status = usb_string_id(cdev);
if (status < 0)
return status;
strings_dev[STRING_CONFIGURATION_IDX].id = status;
msg_config_driver.iConfiguration = status;
/* register our second configuration */
status = usb_add_config(cdev, &msg_config_driver);
status = usb_add_config(cdev, &msg_config_driver, msg_do_config);
if (status < 0)
return status;
dev_info(&gadget->dev, DRIVER_DESC ", version: " DRIVER_VERSION "\n");
dev_info(&cdev->gadget->dev,
DRIVER_DESC ", version: " DRIVER_VERSION "\n");
set_bit(0, &msg_registered);
return 0;
}
@ -226,12 +165,11 @@ static int __ref msg_bind(struct usb_composite_dev *cdev)
/****************************** Some noise ******************************/
static struct usb_composite_driver msg_driver = {
.name = "g_mass_storage",
.dev = &msg_device_desc,
.strings = dev_strings,
.bind = msg_bind,
.iProduct = DRIVER_DESC,
.needs_serial = 1,
};
MODULE_DESCRIPTION(DRIVER_DESC);
@ -240,7 +178,7 @@ MODULE_LICENSE("GPL");
static int __init msg_init(void)
{
return usb_composite_register(&msg_driver);
return usb_composite_probe(&msg_driver, msg_bind);
}
module_init(msg_init);

View File

@ -74,8 +74,8 @@ MODULE_LICENSE("GPL");
/***************************** Device Descriptor ****************************/
#define MULTI_VENDOR_NUM 0x0525 /* XXX NetChip */
#define MULTI_PRODUCT_NUM 0xa4ab /* XXX */
#define MULTI_VENDOR_NUM 0x1d6b /* Linux Foundation */
#define MULTI_PRODUCT_NUM 0x0104 /* Multifunction Composite Gadget */
enum {
@ -121,8 +121,6 @@ static const struct usb_descriptor_header *otg_desc[] = {
enum {
MULTI_STRING_MANUFACTURER_IDX,
MULTI_STRING_PRODUCT_IDX,
#ifdef CONFIG_USB_G_MULTI_RNDIS
MULTI_STRING_RNDIS_CONFIG_IDX,
#endif
@ -131,11 +129,7 @@ enum {
#endif
};
static char manufacturer[50];
static struct usb_string strings_dev[] = {
[MULTI_STRING_MANUFACTURER_IDX].s = manufacturer,
[MULTI_STRING_PRODUCT_IDX].s = DRIVER_DESC,
#ifdef CONFIG_USB_G_MULTI_RNDIS
[MULTI_STRING_RNDIS_CONFIG_IDX].s = "Multifunction with RNDIS",
#endif
@ -170,7 +164,7 @@ static u8 hostaddr[ETH_ALEN];
#ifdef USB_ETH_RNDIS
static __ref int rndis_do_config(struct usb_configuration *c)
static __init int rndis_do_config(struct usb_configuration *c)
{
int ret;
@ -197,7 +191,6 @@ static __ref int rndis_do_config(struct usb_configuration *c)
static int rndis_config_register(struct usb_composite_dev *cdev)
{
static struct usb_configuration config = {
.bind = rndis_do_config,
.bConfigurationValue = MULTI_RNDIS_CONFIG_NUM,
.bmAttributes = USB_CONFIG_ATT_SELFPOWER,
};
@ -205,7 +198,7 @@ static int rndis_config_register(struct usb_composite_dev *cdev)
config.label = strings_dev[MULTI_STRING_RNDIS_CONFIG_IDX].s;
config.iConfiguration = strings_dev[MULTI_STRING_RNDIS_CONFIG_IDX].id;
return usb_add_config(cdev, &config);
return usb_add_config(cdev, &config, rndis_do_config);
}
#else
@ -222,7 +215,7 @@ static int rndis_config_register(struct usb_composite_dev *cdev)
#ifdef CONFIG_USB_G_MULTI_CDC
static __ref int cdc_do_config(struct usb_configuration *c)
static __init int cdc_do_config(struct usb_configuration *c)
{
int ret;
@ -249,7 +242,6 @@ static __ref int cdc_do_config(struct usb_configuration *c)
static int cdc_config_register(struct usb_composite_dev *cdev)
{
static struct usb_configuration config = {
.bind = cdc_do_config,
.bConfigurationValue = MULTI_CDC_CONFIG_NUM,
.bmAttributes = USB_CONFIG_ATT_SELFPOWER,
};
@ -257,7 +249,7 @@ static int cdc_config_register(struct usb_composite_dev *cdev)
config.label = strings_dev[MULTI_STRING_CDC_CONFIG_IDX].s;
config.iConfiguration = strings_dev[MULTI_STRING_CDC_CONFIG_IDX].id;
return usb_add_config(cdev, &config);
return usb_add_config(cdev, &config, cdc_do_config);
}
#else
@ -314,20 +306,11 @@ static int __ref multi_bind(struct usb_composite_dev *cdev)
device_desc.bcdDevice = cpu_to_le16(0x0300 | 0x0099);
}
/* allocate string descriptor numbers */
snprintf(manufacturer, sizeof manufacturer, "%s %s with %s",
init_utsname()->sysname, init_utsname()->release,
gadget->name);
/* allocate string IDs */
status = usb_string_ids_tab(cdev, strings_dev);
if (unlikely(status < 0))
goto fail2;
device_desc.iManufacturer =
strings_dev[MULTI_STRING_MANUFACTURER_IDX].id;
device_desc.iProduct =
strings_dev[MULTI_STRING_PRODUCT_IDX].id;
/* register configurations */
status = rndis_config_register(cdev);
if (unlikely(status < 0))
@ -368,14 +351,15 @@ static struct usb_composite_driver multi_driver = {
.name = "g_multi",
.dev = &device_desc,
.strings = dev_strings,
.bind = multi_bind,
.unbind = __exit_p(multi_unbind),
.iProduct = DRIVER_DESC,
.needs_serial = 1,
};
static int __init multi_init(void)
{
return usb_composite_register(&multi_driver);
return usb_composite_probe(&multi_driver, multi_bind);
}
module_init(multi_init);

View File

@ -1929,7 +1929,8 @@ static void ep0_start (struct net2280 *dev)
* disconnect is reported. then a host may connect again, or
* the driver might get unbound.
*/
int usb_gadget_register_driver (struct usb_gadget_driver *driver)
int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
int (*bind)(struct usb_gadget *))
{
struct net2280 *dev = the_controller;
int retval;
@ -1941,8 +1942,7 @@ int usb_gadget_register_driver (struct usb_gadget_driver *driver)
*/
if (!driver
|| driver->speed != USB_SPEED_HIGH
|| !driver->bind
|| !driver->setup)
|| !bind || !driver->setup)
return -EINVAL;
if (!dev)
return -ENODEV;
@ -1957,7 +1957,7 @@ int usb_gadget_register_driver (struct usb_gadget_driver *driver)
driver->driver.bus = NULL;
dev->driver = driver;
dev->gadget.dev.driver = &driver->driver;
retval = driver->bind (&dev->gadget);
retval = bind(&dev->gadget);
if (retval) {
DEBUG (dev, "bind to driver %s --> %d\n",
driver->driver.name, retval);
@ -1993,7 +1993,7 @@ int usb_gadget_register_driver (struct usb_gadget_driver *driver)
dev->driver = NULL;
return retval;
}
EXPORT_SYMBOL (usb_gadget_register_driver);
EXPORT_SYMBOL(usb_gadget_probe_driver);
static void
stop_activity (struct net2280 *dev, struct usb_gadget_driver *driver)

View File

@ -135,7 +135,6 @@ static int __init nokia_bind_config(struct usb_configuration *c)
static struct usb_configuration nokia_config_500ma_driver = {
.label = "Bus Powered",
.bind = nokia_bind_config,
.bConfigurationValue = 1,
/* .iConfiguration = DYNAMIC */
.bmAttributes = USB_CONFIG_ATT_ONE,
@ -144,7 +143,6 @@ static struct usb_configuration nokia_config_500ma_driver = {
static struct usb_configuration nokia_config_100ma_driver = {
.label = "Self Powered",
.bind = nokia_bind_config,
.bConfigurationValue = 2,
/* .iConfiguration = DYNAMIC */
.bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
@ -206,11 +204,13 @@ static int __init nokia_bind(struct usb_composite_dev *cdev)
}
/* finaly register the configuration */
status = usb_add_config(cdev, &nokia_config_500ma_driver);
status = usb_add_config(cdev, &nokia_config_500ma_driver,
nokia_bind_config);
if (status < 0)
goto err_usb;
status = usb_add_config(cdev, &nokia_config_100ma_driver);
status = usb_add_config(cdev, &nokia_config_100ma_driver,
nokia_bind_config);
if (status < 0)
goto err_usb;
@ -241,13 +241,12 @@ static struct usb_composite_driver nokia_driver = {
.name = "g_nokia",
.dev = &device_desc,
.strings = dev_strings,
.bind = nokia_bind,
.unbind = __exit_p(nokia_unbind),
};
static int __init nokia_init(void)
{
return usb_composite_register(&nokia_driver);
return usb_composite_probe(&nokia_driver, nokia_bind);
}
module_init(nokia_init);

View File

@ -2102,7 +2102,8 @@ static inline int machine_without_vbus_sense(void)
);
}
int usb_gadget_register_driver (struct usb_gadget_driver *driver)
int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
int (*bind)(struct usb_gadget *))
{
int status = -ENODEV;
struct omap_ep *ep;
@ -2114,8 +2115,7 @@ int usb_gadget_register_driver (struct usb_gadget_driver *driver)
if (!driver
// FIXME if otg, check: driver->is_otg
|| driver->speed < USB_SPEED_FULL
|| !driver->bind
|| !driver->setup)
|| !bind || !driver->setup)
return -EINVAL;
spin_lock_irqsave(&udc->lock, flags);
@ -2145,7 +2145,7 @@ int usb_gadget_register_driver (struct usb_gadget_driver *driver)
if (udc->dc_clk != NULL)
omap_udc_enable_clock(1);
status = driver->bind (&udc->gadget);
status = bind(&udc->gadget);
if (status) {
DBG("bind to %s --> %d\n", driver->driver.name, status);
udc->gadget.dev.driver = NULL;
@ -2186,7 +2186,7 @@ int usb_gadget_register_driver (struct usb_gadget_driver *driver)
omap_udc_enable_clock(0);
return status;
}
EXPORT_SYMBOL(usb_gadget_register_driver);
EXPORT_SYMBOL(usb_gadget_probe_driver);
int usb_gadget_unregister_driver (struct usb_gadget_driver *driver)
{

View File

@ -1348,7 +1348,7 @@ printer_unbind(struct usb_gadget *gadget)
set_gadget_data(gadget, NULL);
}
static int __ref
static int __init
printer_bind(struct usb_gadget *gadget)
{
struct printer_dev *dev;
@ -1544,7 +1544,6 @@ static struct usb_gadget_driver printer_driver = {
.speed = DEVSPEED,
.function = (char *) driver_desc,
.bind = printer_bind,
.unbind = printer_unbind,
.setup = printer_setup,
@ -1580,11 +1579,11 @@ init(void)
return status;
}
status = usb_gadget_register_driver(&printer_driver);
status = usb_gadget_probe_driver(&printer_driver, printer_bind);
if (status) {
class_destroy(usb_gadget_class);
unregister_chrdev_region(g_printer_devno, 1);
DBG(dev, "usb_gadget_register_driver %x\n", status);
DBG(dev, "usb_gadget_probe_driver %x\n", status);
}
return status;

View File

@ -1280,14 +1280,15 @@ static void udc_enable (struct pxa25x_udc *dev)
* disconnect is reported. then a host may connect again, or
* the driver might get unbound.
*/
int usb_gadget_register_driver(struct usb_gadget_driver *driver)
int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
int (*bind)(struct usb_gadget *))
{
struct pxa25x_udc *dev = the_controller;
int retval;
if (!driver
|| driver->speed < USB_SPEED_FULL
|| !driver->bind
|| !bind
|| !driver->disconnect
|| !driver->setup)
return -EINVAL;
@ -1308,7 +1309,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
dev->gadget.dev.driver = NULL;
return retval;
}
retval = driver->bind(&dev->gadget);
retval = bind(&dev->gadget);
if (retval) {
DMSG("bind to driver %s --> error %d\n",
driver->driver.name, retval);
@ -1338,7 +1339,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
bind_fail:
return retval;
}
EXPORT_SYMBOL(usb_gadget_register_driver);
EXPORT_SYMBOL(usb_gadget_probe_driver);
static void
stop_activity(struct pxa25x_udc *dev, struct usb_gadget_driver *driver)

View File

@ -1792,8 +1792,9 @@ static void udc_enable(struct pxa_udc *udc)
}
/**
* usb_gadget_register_driver - Register gadget driver
* usb_gadget_probe_driver - Register gadget driver
* @driver: gadget driver
* @bind: bind function
*
* When a driver is successfully registered, it will receive control requests
* including set_configuration(), which enables non-control requests. Then
@ -1805,12 +1806,13 @@ static void udc_enable(struct pxa_udc *udc)
*
* Returns 0 if no error, -EINVAL, -ENODEV, -EBUSY otherwise
*/
int usb_gadget_register_driver(struct usb_gadget_driver *driver)
int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
int (*bind)(struct usb_gadget *))
{
struct pxa_udc *udc = the_controller;
int retval;
if (!driver || driver->speed < USB_SPEED_FULL || !driver->bind
if (!driver || driver->speed < USB_SPEED_FULL || !bind
|| !driver->disconnect || !driver->setup)
return -EINVAL;
if (!udc)
@ -1828,7 +1830,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
dev_err(udc->dev, "device_add error %d\n", retval);
goto add_fail;
}
retval = driver->bind(&udc->gadget);
retval = bind(&udc->gadget);
if (retval) {
dev_err(udc->dev, "bind to driver %s --> error %d\n",
driver->driver.name, retval);
@ -1859,7 +1861,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
udc->gadget.dev.driver = NULL;
return retval;
}
EXPORT_SYMBOL(usb_gadget_register_driver);
EXPORT_SYMBOL(usb_gadget_probe_driver);
/**

View File

@ -42,6 +42,7 @@ static const char *r8a66597_ep_name[] = {
"ep8", "ep9",
};
static void init_controller(struct r8a66597 *r8a66597);
static void disable_controller(struct r8a66597 *r8a66597);
static void irq_ep0_write(struct r8a66597_ep *ep, struct r8a66597_request *req);
static void irq_packet_write(struct r8a66597_ep *ep,
@ -104,6 +105,8 @@ __acquires(r8a66597->lock)
spin_lock(&r8a66597->lock);
disable_controller(r8a66597);
init_controller(r8a66597);
r8a66597_bset(r8a66597, VBSE, INTENB0);
INIT_LIST_HEAD(&r8a66597->ep[0].queue);
}
@ -274,7 +277,7 @@ static int pipe_buffer_setting(struct r8a66597 *r8a66597,
}
if (buf_bsize && ((bufnum + 16) >= R8A66597_MAX_BUFNUM)) {
pr_err(KERN_ERR "r8a66597 pipe memory is insufficient\n");
pr_err("r8a66597 pipe memory is insufficient\n");
return -ENOMEM;
}
@ -1405,14 +1408,15 @@ static struct usb_ep_ops r8a66597_ep_ops = {
/*-------------------------------------------------------------------------*/
static struct r8a66597 *the_controller;
int usb_gadget_register_driver(struct usb_gadget_driver *driver)
int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
int (*bind)(struct usb_gadget *))
{
struct r8a66597 *r8a66597 = the_controller;
int retval;
if (!driver
|| driver->speed != USB_SPEED_HIGH
|| !driver->bind
|| !bind
|| !driver->setup)
return -EINVAL;
if (!r8a66597)
@ -1431,7 +1435,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
goto error;
}
retval = driver->bind(&r8a66597->gadget);
retval = bind(&r8a66597->gadget);
if (retval) {
printk(KERN_ERR "bind to driver error (%d)\n", retval);
device_del(&r8a66597->gadget.dev);
@ -1456,7 +1460,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
return retval;
}
EXPORT_SYMBOL(usb_gadget_register_driver);
EXPORT_SYMBOL(usb_gadget_probe_driver);
int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
{

View File

@ -136,7 +136,7 @@ static inline void r8a66597_read_fifo(struct r8a66597 *r8a66597,
int len)
{
void __iomem *fifoaddr = r8a66597->reg + offset;
unsigned int data;
unsigned int data = 0;
int i;
if (r8a66597->pdata->on_chip) {

View File

@ -61,17 +61,17 @@ MODULE_PARM_DESC (rndis_debug, "enable debugging");
#define RNDIS_MAX_CONFIGS 1
static rndis_params rndis_per_dev_params [RNDIS_MAX_CONFIGS];
static rndis_params rndis_per_dev_params[RNDIS_MAX_CONFIGS];
/* Driver Version */
static const __le32 rndis_driver_version = cpu_to_le32 (1);
static const __le32 rndis_driver_version = cpu_to_le32(1);
/* Function Prototypes */
static rndis_resp_t *rndis_add_response (int configNr, u32 length);
static rndis_resp_t *rndis_add_response(int configNr, u32 length);
/* supported OIDs */
static const u32 oid_supported_list [] =
static const u32 oid_supported_list[] =
{
/* the general stuff */
OID_GEN_SUPPORTED_LIST,
@ -161,21 +161,20 @@ static const u32 oid_supported_list [] =
/* NDIS Functions */
static int
gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
rndis_resp_t *r)
static int gen_ndis_query_resp(int configNr, u32 OID, u8 *buf,
unsigned buf_len, rndis_resp_t *r)
{
int retval = -ENOTSUPP;
u32 length = 4; /* usually */
__le32 *outbuf;
int i, count;
rndis_query_cmplt_type *resp;
struct net_device *net;
int retval = -ENOTSUPP;
u32 length = 4; /* usually */
__le32 *outbuf;
int i, count;
rndis_query_cmplt_type *resp;
struct net_device *net;
struct rtnl_link_stats64 temp;
const struct rtnl_link_stats64 *stats;
if (!r) return -ENOMEM;
resp = (rndis_query_cmplt_type *) r->buf;
resp = (rndis_query_cmplt_type *)r->buf;
if (!resp) return -ENOMEM;
@ -191,8 +190,8 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
}
/* response goes here, right after the header */
outbuf = (__le32 *) &resp[1];
resp->InformationBufferOffset = cpu_to_le32 (16);
outbuf = (__le32 *)&resp[1];
resp->InformationBufferOffset = cpu_to_le32(16);
net = rndis_per_dev_params[configNr].dev;
stats = dev_get_stats(net, &temp);
@ -204,10 +203,10 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
/* mandatory */
case OID_GEN_SUPPORTED_LIST:
pr_debug("%s: OID_GEN_SUPPORTED_LIST\n", __func__);
length = sizeof (oid_supported_list);
count = length / sizeof (u32);
length = sizeof(oid_supported_list);
count = length / sizeof(u32);
for (i = 0; i < count; i++)
outbuf[i] = cpu_to_le32 (oid_supported_list[i]);
outbuf[i] = cpu_to_le32(oid_supported_list[i]);
retval = 0;
break;
@ -220,14 +219,14 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
* reddite ergo quae sunt Caesaris Caesari
* et quae sunt Dei Deo!
*/
*outbuf = cpu_to_le32 (0);
*outbuf = cpu_to_le32(0);
retval = 0;
break;
/* mandatory */
case OID_GEN_MEDIA_SUPPORTED:
pr_debug("%s: OID_GEN_MEDIA_SUPPORTED\n", __func__);
*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr].medium);
*outbuf = cpu_to_le32(rndis_per_dev_params[configNr].medium);
retval = 0;
break;
@ -235,16 +234,16 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
case OID_GEN_MEDIA_IN_USE:
pr_debug("%s: OID_GEN_MEDIA_IN_USE\n", __func__);
/* one medium, one transport... (maybe you do it better) */
*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr].medium);
*outbuf = cpu_to_le32(rndis_per_dev_params[configNr].medium);
retval = 0;
break;
/* mandatory */
case OID_GEN_MAXIMUM_FRAME_SIZE:
pr_debug("%s: OID_GEN_MAXIMUM_FRAME_SIZE\n", __func__);
if (rndis_per_dev_params [configNr].dev) {
*outbuf = cpu_to_le32 (
rndis_per_dev_params [configNr].dev->mtu);
if (rndis_per_dev_params[configNr].dev) {
*outbuf = cpu_to_le32(
rndis_per_dev_params[configNr].dev->mtu);
retval = 0;
}
break;
@ -253,21 +252,21 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
case OID_GEN_LINK_SPEED:
if (rndis_debug > 1)
pr_debug("%s: OID_GEN_LINK_SPEED\n", __func__);
if (rndis_per_dev_params [configNr].media_state
if (rndis_per_dev_params[configNr].media_state
== NDIS_MEDIA_STATE_DISCONNECTED)
*outbuf = cpu_to_le32 (0);
*outbuf = cpu_to_le32(0);
else
*outbuf = cpu_to_le32 (
rndis_per_dev_params [configNr].speed);
*outbuf = cpu_to_le32(
rndis_per_dev_params[configNr].speed);
retval = 0;
break;
/* mandatory */
case OID_GEN_TRANSMIT_BLOCK_SIZE:
pr_debug("%s: OID_GEN_TRANSMIT_BLOCK_SIZE\n", __func__);
if (rndis_per_dev_params [configNr].dev) {
*outbuf = cpu_to_le32 (
rndis_per_dev_params [configNr].dev->mtu);
if (rndis_per_dev_params[configNr].dev) {
*outbuf = cpu_to_le32(
rndis_per_dev_params[configNr].dev->mtu);
retval = 0;
}
break;
@ -275,9 +274,9 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
/* mandatory */
case OID_GEN_RECEIVE_BLOCK_SIZE:
pr_debug("%s: OID_GEN_RECEIVE_BLOCK_SIZE\n", __func__);
if (rndis_per_dev_params [configNr].dev) {
*outbuf = cpu_to_le32 (
rndis_per_dev_params [configNr].dev->mtu);
if (rndis_per_dev_params[configNr].dev) {
*outbuf = cpu_to_le32(
rndis_per_dev_params[configNr].dev->mtu);
retval = 0;
}
break;
@ -285,18 +284,20 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
/* mandatory */
case OID_GEN_VENDOR_ID:
pr_debug("%s: OID_GEN_VENDOR_ID\n", __func__);
*outbuf = cpu_to_le32 (
rndis_per_dev_params [configNr].vendorID);
*outbuf = cpu_to_le32(
rndis_per_dev_params[configNr].vendorID);
retval = 0;
break;
/* mandatory */
case OID_GEN_VENDOR_DESCRIPTION:
pr_debug("%s: OID_GEN_VENDOR_DESCRIPTION\n", __func__);
if ( rndis_per_dev_params [configNr].vendorDescr ) {
length = strlen (rndis_per_dev_params [configNr].vendorDescr);
memcpy (outbuf,
rndis_per_dev_params [configNr].vendorDescr, length);
if (rndis_per_dev_params[configNr].vendorDescr) {
length = strlen(rndis_per_dev_params[configNr].
vendorDescr);
memcpy(outbuf,
rndis_per_dev_params[configNr].vendorDescr,
length);
} else {
outbuf[0] = 0;
}
@ -313,7 +314,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
/* mandatory */
case OID_GEN_CURRENT_PACKET_FILTER:
pr_debug("%s: OID_GEN_CURRENT_PACKET_FILTER\n", __func__);
*outbuf = cpu_to_le32 (*rndis_per_dev_params[configNr].filter);
*outbuf = cpu_to_le32(*rndis_per_dev_params[configNr].filter);
retval = 0;
break;
@ -328,14 +329,14 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
case OID_GEN_MEDIA_CONNECT_STATUS:
if (rndis_debug > 1)
pr_debug("%s: OID_GEN_MEDIA_CONNECT_STATUS\n", __func__);
*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
*outbuf = cpu_to_le32(rndis_per_dev_params[configNr]
.media_state);
retval = 0;
break;
case OID_GEN_PHYSICAL_MEDIUM:
pr_debug("%s: OID_GEN_PHYSICAL_MEDIUM\n", __func__);
*outbuf = cpu_to_le32 (0);
*outbuf = cpu_to_le32(0);
retval = 0;
break;
@ -409,10 +410,10 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
/* mandatory */
case OID_802_3_PERMANENT_ADDRESS:
pr_debug("%s: OID_802_3_PERMANENT_ADDRESS\n", __func__);
if (rndis_per_dev_params [configNr].dev) {
if (rndis_per_dev_params[configNr].dev) {
length = ETH_ALEN;
memcpy (outbuf,
rndis_per_dev_params [configNr].host_mac,
memcpy(outbuf,
rndis_per_dev_params[configNr].host_mac,
length);
retval = 0;
}
@ -421,9 +422,9 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
/* mandatory */
case OID_802_3_CURRENT_ADDRESS:
pr_debug("%s: OID_802_3_CURRENT_ADDRESS\n", __func__);
if (rndis_per_dev_params [configNr].dev) {
if (rndis_per_dev_params[configNr].dev) {
length = ETH_ALEN;
memcpy (outbuf,
memcpy(outbuf,
rndis_per_dev_params [configNr].host_mac,
length);
retval = 0;
@ -434,7 +435,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
case OID_802_3_MULTICAST_LIST:
pr_debug("%s: OID_802_3_MULTICAST_LIST\n", __func__);
/* Multicast base address only */
*outbuf = cpu_to_le32 (0xE0000000);
*outbuf = cpu_to_le32(0xE0000000);
retval = 0;
break;
@ -442,7 +443,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
case OID_802_3_MAXIMUM_LIST_SIZE:
pr_debug("%s: OID_802_3_MAXIMUM_LIST_SIZE\n", __func__);
/* Multicast base address only */
*outbuf = cpu_to_le32 (1);
*outbuf = cpu_to_le32(1);
retval = 0;
break;
@ -466,14 +467,14 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
/* mandatory */
case OID_802_3_XMIT_ONE_COLLISION:
pr_debug("%s: OID_802_3_XMIT_ONE_COLLISION\n", __func__);
*outbuf = cpu_to_le32 (0);
*outbuf = cpu_to_le32(0);
retval = 0;
break;
/* mandatory */
case OID_802_3_XMIT_MORE_COLLISIONS:
pr_debug("%s: OID_802_3_XMIT_MORE_COLLISIONS\n", __func__);
*outbuf = cpu_to_le32 (0);
*outbuf = cpu_to_le32(0);
retval = 0;
break;
@ -484,22 +485,22 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
if (retval < 0)
length = 0;
resp->InformationBufferLength = cpu_to_le32 (length);
r->length = length + sizeof *resp;
resp->MessageLength = cpu_to_le32 (r->length);
resp->InformationBufferLength = cpu_to_le32(length);
r->length = length + sizeof(*resp);
resp->MessageLength = cpu_to_le32(r->length);
return retval;
}
static int gen_ndis_set_resp (u8 configNr, u32 OID, u8 *buf, u32 buf_len,
rndis_resp_t *r)
static int gen_ndis_set_resp(u8 configNr, u32 OID, u8 *buf, u32 buf_len,
rndis_resp_t *r)
{
rndis_set_cmplt_type *resp;
int i, retval = -ENOTSUPP;
struct rndis_params *params;
rndis_set_cmplt_type *resp;
int i, retval = -ENOTSUPP;
struct rndis_params *params;
if (!r)
return -ENOMEM;
resp = (rndis_set_cmplt_type *) r->buf;
resp = (rndis_set_cmplt_type *)r->buf;
if (!resp)
return -ENOMEM;
@ -514,7 +515,7 @@ static int gen_ndis_set_resp (u8 configNr, u32 OID, u8 *buf, u32 buf_len,
}
}
params = &rndis_per_dev_params [configNr];
params = &rndis_per_dev_params[configNr];
switch (OID) {
case OID_GEN_CURRENT_PACKET_FILTER:
@ -537,11 +538,11 @@ static int gen_ndis_set_resp (u8 configNr, u32 OID, u8 *buf, u32 buf_len,
params->state = RNDIS_DATA_INITIALIZED;
netif_carrier_on(params->dev);
if (netif_running(params->dev))
netif_wake_queue (params->dev);
netif_wake_queue(params->dev);
} else {
params->state = RNDIS_INITIALIZED;
netif_carrier_off (params->dev);
netif_stop_queue (params->dev);
netif_carrier_off(params->dev);
netif_stop_queue(params->dev);
}
break;
@ -563,48 +564,47 @@ static int gen_ndis_set_resp (u8 configNr, u32 OID, u8 *buf, u32 buf_len,
* Response Functions
*/
static int rndis_init_response (int configNr, rndis_init_msg_type *buf)
static int rndis_init_response(int configNr, rndis_init_msg_type *buf)
{
rndis_init_cmplt_type *resp;
rndis_resp_t *r;
struct rndis_params *params = rndis_per_dev_params + configNr;
rndis_init_cmplt_type *resp;
rndis_resp_t *r;
struct rndis_params *params = rndis_per_dev_params + configNr;
if (!params->dev)
return -ENOTSUPP;
r = rndis_add_response (configNr, sizeof (rndis_init_cmplt_type));
r = rndis_add_response(configNr, sizeof(rndis_init_cmplt_type));
if (!r)
return -ENOMEM;
resp = (rndis_init_cmplt_type *) r->buf;
resp = (rndis_init_cmplt_type *)r->buf;
resp->MessageType = cpu_to_le32 (
REMOTE_NDIS_INITIALIZE_CMPLT);
resp->MessageLength = cpu_to_le32 (52);
resp->MessageType = cpu_to_le32(REMOTE_NDIS_INITIALIZE_CMPLT);
resp->MessageLength = cpu_to_le32(52);
resp->RequestID = buf->RequestID; /* Still LE in msg buffer */
resp->Status = cpu_to_le32 (RNDIS_STATUS_SUCCESS);
resp->MajorVersion = cpu_to_le32 (RNDIS_MAJOR_VERSION);
resp->MinorVersion = cpu_to_le32 (RNDIS_MINOR_VERSION);
resp->DeviceFlags = cpu_to_le32 (RNDIS_DF_CONNECTIONLESS);
resp->Medium = cpu_to_le32 (RNDIS_MEDIUM_802_3);
resp->MaxPacketsPerTransfer = cpu_to_le32 (1);
resp->MaxTransferSize = cpu_to_le32 (
resp->Status = cpu_to_le32(RNDIS_STATUS_SUCCESS);
resp->MajorVersion = cpu_to_le32(RNDIS_MAJOR_VERSION);
resp->MinorVersion = cpu_to_le32(RNDIS_MINOR_VERSION);
resp->DeviceFlags = cpu_to_le32(RNDIS_DF_CONNECTIONLESS);
resp->Medium = cpu_to_le32(RNDIS_MEDIUM_802_3);
resp->MaxPacketsPerTransfer = cpu_to_le32(1);
resp->MaxTransferSize = cpu_to_le32(
params->dev->mtu
+ sizeof (struct ethhdr)
+ sizeof (struct rndis_packet_msg_type)
+ sizeof(struct ethhdr)
+ sizeof(struct rndis_packet_msg_type)
+ 22);
resp->PacketAlignmentFactor = cpu_to_le32 (0);
resp->AFListOffset = cpu_to_le32 (0);
resp->AFListSize = cpu_to_le32 (0);
resp->PacketAlignmentFactor = cpu_to_le32(0);
resp->AFListOffset = cpu_to_le32(0);
resp->AFListSize = cpu_to_le32(0);
params->resp_avail(params->v);
return 0;
}
static int rndis_query_response (int configNr, rndis_query_msg_type *buf)
static int rndis_query_response(int configNr, rndis_query_msg_type *buf)
{
rndis_query_cmplt_type *resp;
rndis_resp_t *r;
struct rndis_params *params = rndis_per_dev_params + configNr;
rndis_resp_t *r;
struct rndis_params *params = rndis_per_dev_params + configNr;
/* pr_debug("%s: OID = %08X\n", __func__, cpu_to_le32(buf->OID)); */
if (!params->dev)
@ -616,47 +616,46 @@ static int rndis_query_response (int configNr, rndis_query_msg_type *buf)
* rndis_query_cmplt_type followed by data.
* oid_supported_list is the largest data reply
*/
r = rndis_add_response (configNr,
sizeof (oid_supported_list) + sizeof(rndis_query_cmplt_type));
r = rndis_add_response(configNr,
sizeof(oid_supported_list) + sizeof(rndis_query_cmplt_type));
if (!r)
return -ENOMEM;
resp = (rndis_query_cmplt_type *) r->buf;
resp = (rndis_query_cmplt_type *)r->buf;
resp->MessageType = cpu_to_le32 (REMOTE_NDIS_QUERY_CMPLT);
resp->MessageType = cpu_to_le32(REMOTE_NDIS_QUERY_CMPLT);
resp->RequestID = buf->RequestID; /* Still LE in msg buffer */
if (gen_ndis_query_resp (configNr, le32_to_cpu (buf->OID),
if (gen_ndis_query_resp(configNr, le32_to_cpu(buf->OID),
le32_to_cpu(buf->InformationBufferOffset)
+ 8 + (u8 *) buf,
+ 8 + (u8 *)buf,
le32_to_cpu(buf->InformationBufferLength),
r)) {
/* OID not supported */
resp->Status = cpu_to_le32 (
RNDIS_STATUS_NOT_SUPPORTED);
resp->MessageLength = cpu_to_le32 (sizeof *resp);
resp->InformationBufferLength = cpu_to_le32 (0);
resp->InformationBufferOffset = cpu_to_le32 (0);
resp->Status = cpu_to_le32(RNDIS_STATUS_NOT_SUPPORTED);
resp->MessageLength = cpu_to_le32(sizeof *resp);
resp->InformationBufferLength = cpu_to_le32(0);
resp->InformationBufferOffset = cpu_to_le32(0);
} else
resp->Status = cpu_to_le32 (RNDIS_STATUS_SUCCESS);
resp->Status = cpu_to_le32(RNDIS_STATUS_SUCCESS);
params->resp_avail(params->v);
return 0;
}
static int rndis_set_response (int configNr, rndis_set_msg_type *buf)
static int rndis_set_response(int configNr, rndis_set_msg_type *buf)
{
u32 BufLength, BufOffset;
rndis_set_cmplt_type *resp;
rndis_resp_t *r;
struct rndis_params *params = rndis_per_dev_params + configNr;
u32 BufLength, BufOffset;
rndis_set_cmplt_type *resp;
rndis_resp_t *r;
struct rndis_params *params = rndis_per_dev_params + configNr;
r = rndis_add_response (configNr, sizeof (rndis_set_cmplt_type));
r = rndis_add_response(configNr, sizeof(rndis_set_cmplt_type));
if (!r)
return -ENOMEM;
resp = (rndis_set_cmplt_type *) r->buf;
resp = (rndis_set_cmplt_type *)r->buf;
BufLength = le32_to_cpu (buf->InformationBufferLength);
BufOffset = le32_to_cpu (buf->InformationBufferOffset);
BufLength = le32_to_cpu(buf->InformationBufferLength);
BufOffset = le32_to_cpu(buf->InformationBufferOffset);
#ifdef VERBOSE_DEBUG
pr_debug("%s: Length: %d\n", __func__, BufLength);
@ -670,59 +669,59 @@ static int rndis_set_response (int configNr, rndis_set_msg_type *buf)
pr_debug("\n");
#endif
resp->MessageType = cpu_to_le32 (REMOTE_NDIS_SET_CMPLT);
resp->MessageLength = cpu_to_le32 (16);
resp->MessageType = cpu_to_le32(REMOTE_NDIS_SET_CMPLT);
resp->MessageLength = cpu_to_le32(16);
resp->RequestID = buf->RequestID; /* Still LE in msg buffer */
if (gen_ndis_set_resp (configNr, le32_to_cpu (buf->OID),
((u8 *) buf) + 8 + BufOffset, BufLength, r))
resp->Status = cpu_to_le32 (RNDIS_STATUS_NOT_SUPPORTED);
if (gen_ndis_set_resp(configNr, le32_to_cpu(buf->OID),
((u8 *)buf) + 8 + BufOffset, BufLength, r))
resp->Status = cpu_to_le32(RNDIS_STATUS_NOT_SUPPORTED);
else
resp->Status = cpu_to_le32 (RNDIS_STATUS_SUCCESS);
resp->Status = cpu_to_le32(RNDIS_STATUS_SUCCESS);
params->resp_avail(params->v);
return 0;
}
static int rndis_reset_response (int configNr, rndis_reset_msg_type *buf)
static int rndis_reset_response(int configNr, rndis_reset_msg_type *buf)
{
rndis_reset_cmplt_type *resp;
rndis_resp_t *r;
struct rndis_params *params = rndis_per_dev_params + configNr;
rndis_reset_cmplt_type *resp;
rndis_resp_t *r;
struct rndis_params *params = rndis_per_dev_params + configNr;
r = rndis_add_response (configNr, sizeof (rndis_reset_cmplt_type));
r = rndis_add_response(configNr, sizeof(rndis_reset_cmplt_type));
if (!r)
return -ENOMEM;
resp = (rndis_reset_cmplt_type *) r->buf;
resp = (rndis_reset_cmplt_type *)r->buf;
resp->MessageType = cpu_to_le32 (REMOTE_NDIS_RESET_CMPLT);
resp->MessageLength = cpu_to_le32 (16);
resp->Status = cpu_to_le32 (RNDIS_STATUS_SUCCESS);
resp->MessageType = cpu_to_le32(REMOTE_NDIS_RESET_CMPLT);
resp->MessageLength = cpu_to_le32(16);
resp->Status = cpu_to_le32(RNDIS_STATUS_SUCCESS);
/* resent information */
resp->AddressingReset = cpu_to_le32 (1);
resp->AddressingReset = cpu_to_le32(1);
params->resp_avail(params->v);
return 0;
}
static int rndis_keepalive_response (int configNr,
rndis_keepalive_msg_type *buf)
static int rndis_keepalive_response(int configNr,
rndis_keepalive_msg_type *buf)
{
rndis_keepalive_cmplt_type *resp;
rndis_resp_t *r;
struct rndis_params *params = rndis_per_dev_params + configNr;
rndis_keepalive_cmplt_type *resp;
rndis_resp_t *r;
struct rndis_params *params = rndis_per_dev_params + configNr;
/* host "should" check only in RNDIS_DATA_INITIALIZED state */
r = rndis_add_response (configNr, sizeof (rndis_keepalive_cmplt_type));
r = rndis_add_response(configNr, sizeof(rndis_keepalive_cmplt_type));
if (!r)
return -ENOMEM;
resp = (rndis_keepalive_cmplt_type *) r->buf;
resp = (rndis_keepalive_cmplt_type *)r->buf;
resp->MessageType = cpu_to_le32 (
resp->MessageType = cpu_to_le32(
REMOTE_NDIS_KEEPALIVE_CMPLT);
resp->MessageLength = cpu_to_le32 (16);
resp->MessageLength = cpu_to_le32(16);
resp->RequestID = buf->RequestID; /* Still LE in msg buffer */
resp->Status = cpu_to_le32 (RNDIS_STATUS_SUCCESS);
resp->Status = cpu_to_le32(RNDIS_STATUS_SUCCESS);
params->resp_avail(params->v);
return 0;
@ -732,86 +731,85 @@ static int rndis_keepalive_response (int configNr,
/*
* Device to Host Comunication
*/
static int rndis_indicate_status_msg (int configNr, u32 status)
static int rndis_indicate_status_msg(int configNr, u32 status)
{
rndis_indicate_status_msg_type *resp;
rndis_resp_t *r;
struct rndis_params *params = rndis_per_dev_params + configNr;
rndis_indicate_status_msg_type *resp;
rndis_resp_t *r;
struct rndis_params *params = rndis_per_dev_params + configNr;
if (params->state == RNDIS_UNINITIALIZED)
return -ENOTSUPP;
r = rndis_add_response (configNr,
sizeof (rndis_indicate_status_msg_type));
r = rndis_add_response(configNr,
sizeof(rndis_indicate_status_msg_type));
if (!r)
return -ENOMEM;
resp = (rndis_indicate_status_msg_type *) r->buf;
resp = (rndis_indicate_status_msg_type *)r->buf;
resp->MessageType = cpu_to_le32 (
REMOTE_NDIS_INDICATE_STATUS_MSG);
resp->MessageLength = cpu_to_le32 (20);
resp->Status = cpu_to_le32 (status);
resp->StatusBufferLength = cpu_to_le32 (0);
resp->StatusBufferOffset = cpu_to_le32 (0);
resp->MessageType = cpu_to_le32(REMOTE_NDIS_INDICATE_STATUS_MSG);
resp->MessageLength = cpu_to_le32(20);
resp->Status = cpu_to_le32(status);
resp->StatusBufferLength = cpu_to_le32(0);
resp->StatusBufferOffset = cpu_to_le32(0);
params->resp_avail(params->v);
return 0;
}
int rndis_signal_connect (int configNr)
int rndis_signal_connect(int configNr)
{
rndis_per_dev_params [configNr].media_state
rndis_per_dev_params[configNr].media_state
= NDIS_MEDIA_STATE_CONNECTED;
return rndis_indicate_status_msg (configNr,
return rndis_indicate_status_msg(configNr,
RNDIS_STATUS_MEDIA_CONNECT);
}
int rndis_signal_disconnect (int configNr)
int rndis_signal_disconnect(int configNr)
{
rndis_per_dev_params [configNr].media_state
rndis_per_dev_params[configNr].media_state
= NDIS_MEDIA_STATE_DISCONNECTED;
return rndis_indicate_status_msg (configNr,
return rndis_indicate_status_msg(configNr,
RNDIS_STATUS_MEDIA_DISCONNECT);
}
void rndis_uninit (int configNr)
void rndis_uninit(int configNr)
{
u8 *buf;
u32 length;
if (configNr >= RNDIS_MAX_CONFIGS)
return;
rndis_per_dev_params [configNr].state = RNDIS_UNINITIALIZED;
rndis_per_dev_params[configNr].state = RNDIS_UNINITIALIZED;
/* drain the response queue */
while ((buf = rndis_get_next_response(configNr, &length)))
rndis_free_response(configNr, buf);
}
void rndis_set_host_mac (int configNr, const u8 *addr)
void rndis_set_host_mac(int configNr, const u8 *addr)
{
rndis_per_dev_params [configNr].host_mac = addr;
rndis_per_dev_params[configNr].host_mac = addr;
}
/*
* Message Parser
*/
int rndis_msg_parser (u8 configNr, u8 *buf)
int rndis_msg_parser(u8 configNr, u8 *buf)
{
u32 MsgType, MsgLength;
__le32 *tmp;
struct rndis_params *params;
struct rndis_params *params;
if (!buf)
return -ENOMEM;
tmp = (__le32 *) buf;
tmp = (__le32 *)buf;
MsgType = get_unaligned_le32(tmp++);
MsgLength = get_unaligned_le32(tmp++);
if (configNr >= RNDIS_MAX_CONFIGS)
return -ENOTSUPP;
params = &rndis_per_dev_params [configNr];
params = &rndis_per_dev_params[configNr];
/* NOTE: RNDIS is *EXTREMELY* chatty ... Windows constantly polls for
* rx/tx statistics and link status, in addition to KEEPALIVE traffic
@ -822,41 +820,41 @@ int rndis_msg_parser (u8 configNr, u8 *buf)
switch (MsgType) {
case REMOTE_NDIS_INITIALIZE_MSG:
pr_debug("%s: REMOTE_NDIS_INITIALIZE_MSG\n",
__func__ );
__func__);
params->state = RNDIS_INITIALIZED;
return rndis_init_response (configNr,
(rndis_init_msg_type *) buf);
return rndis_init_response(configNr,
(rndis_init_msg_type *)buf);
case REMOTE_NDIS_HALT_MSG:
pr_debug("%s: REMOTE_NDIS_HALT_MSG\n",
__func__ );
__func__);
params->state = RNDIS_UNINITIALIZED;
if (params->dev) {
netif_carrier_off (params->dev);
netif_stop_queue (params->dev);
netif_carrier_off(params->dev);
netif_stop_queue(params->dev);
}
return 0;
case REMOTE_NDIS_QUERY_MSG:
return rndis_query_response (configNr,
(rndis_query_msg_type *) buf);
return rndis_query_response(configNr,
(rndis_query_msg_type *)buf);
case REMOTE_NDIS_SET_MSG:
return rndis_set_response (configNr,
(rndis_set_msg_type *) buf);
return rndis_set_response(configNr,
(rndis_set_msg_type *)buf);
case REMOTE_NDIS_RESET_MSG:
pr_debug("%s: REMOTE_NDIS_RESET_MSG\n",
__func__ );
return rndis_reset_response (configNr,
(rndis_reset_msg_type *) buf);
__func__);
return rndis_reset_response(configNr,
(rndis_reset_msg_type *)buf);
case REMOTE_NDIS_KEEPALIVE_MSG:
/* For USB: host does this every 5 seconds */
if (rndis_debug > 1)
pr_debug("%s: REMOTE_NDIS_KEEPALIVE_MSG\n",
__func__ );
return rndis_keepalive_response (configNr,
__func__);
return rndis_keepalive_response(configNr,
(rndis_keepalive_msg_type *)
buf);
@ -866,7 +864,7 @@ int rndis_msg_parser (u8 configNr, u8 *buf)
* suspending itself.
*/
pr_warning("%s: unknown RNDIS message 0x%08X len %d\n",
__func__ , MsgType, MsgLength);
__func__, MsgType, MsgLength);
{
unsigned i;
for (i = 0; i < MsgLength; i += 16) {
@ -901,10 +899,10 @@ int rndis_register(void (*resp_avail)(void *v), void *v)
return -EINVAL;
for (i = 0; i < RNDIS_MAX_CONFIGS; i++) {
if (!rndis_per_dev_params [i].used) {
rndis_per_dev_params [i].used = 1;
rndis_per_dev_params [i].resp_avail = resp_avail;
rndis_per_dev_params [i].v = v;
if (!rndis_per_dev_params[i].used) {
rndis_per_dev_params[i].used = 1;
rndis_per_dev_params[i].resp_avail = resp_avail;
rndis_per_dev_params[i].v = v;
pr_debug("%s: configNr = %d\n", __func__, i);
return i;
}
@ -914,12 +912,12 @@ int rndis_register(void (*resp_avail)(void *v), void *v)
return -ENODEV;
}
void rndis_deregister (int configNr)
void rndis_deregister(int configNr)
{
pr_debug("%s: \n", __func__);
pr_debug("%s:\n", __func__);
if (configNr >= RNDIS_MAX_CONFIGS) return;
rndis_per_dev_params [configNr].used = 0;
rndis_per_dev_params[configNr].used = 0;
return;
}
@ -931,76 +929,76 @@ int rndis_set_param_dev(u8 configNr, struct net_device *dev, u16 *cdc_filter)
return -EINVAL;
if (configNr >= RNDIS_MAX_CONFIGS) return -1;
rndis_per_dev_params [configNr].dev = dev;
rndis_per_dev_params [configNr].filter = cdc_filter;
rndis_per_dev_params[configNr].dev = dev;
rndis_per_dev_params[configNr].filter = cdc_filter;
return 0;
}
int rndis_set_param_vendor (u8 configNr, u32 vendorID, const char *vendorDescr)
int rndis_set_param_vendor(u8 configNr, u32 vendorID, const char *vendorDescr)
{
pr_debug("%s:\n", __func__);
if (!vendorDescr) return -1;
if (configNr >= RNDIS_MAX_CONFIGS) return -1;
rndis_per_dev_params [configNr].vendorID = vendorID;
rndis_per_dev_params [configNr].vendorDescr = vendorDescr;
rndis_per_dev_params[configNr].vendorID = vendorID;
rndis_per_dev_params[configNr].vendorDescr = vendorDescr;
return 0;
}
int rndis_set_param_medium (u8 configNr, u32 medium, u32 speed)
int rndis_set_param_medium(u8 configNr, u32 medium, u32 speed)
{
pr_debug("%s: %u %u\n", __func__, medium, speed);
if (configNr >= RNDIS_MAX_CONFIGS) return -1;
rndis_per_dev_params [configNr].medium = medium;
rndis_per_dev_params [configNr].speed = speed;
rndis_per_dev_params[configNr].medium = medium;
rndis_per_dev_params[configNr].speed = speed;
return 0;
}
void rndis_add_hdr (struct sk_buff *skb)
void rndis_add_hdr(struct sk_buff *skb)
{
struct rndis_packet_msg_type *header;
struct rndis_packet_msg_type *header;
if (!skb)
return;
header = (void *) skb_push (skb, sizeof *header);
memset (header, 0, sizeof *header);
header = (void *)skb_push(skb, sizeof(*header));
memset(header, 0, sizeof *header);
header->MessageType = cpu_to_le32(REMOTE_NDIS_PACKET_MSG);
header->MessageLength = cpu_to_le32(skb->len);
header->DataOffset = cpu_to_le32 (36);
header->DataLength = cpu_to_le32(skb->len - sizeof *header);
header->DataOffset = cpu_to_le32(36);
header->DataLength = cpu_to_le32(skb->len - sizeof(*header));
}
void rndis_free_response (int configNr, u8 *buf)
void rndis_free_response(int configNr, u8 *buf)
{
rndis_resp_t *r;
struct list_head *act, *tmp;
rndis_resp_t *r;
struct list_head *act, *tmp;
list_for_each_safe (act, tmp,
&(rndis_per_dev_params [configNr].resp_queue))
list_for_each_safe(act, tmp,
&(rndis_per_dev_params[configNr].resp_queue))
{
r = list_entry (act, rndis_resp_t, list);
r = list_entry(act, rndis_resp_t, list);
if (r && r->buf == buf) {
list_del (&r->list);
kfree (r);
list_del(&r->list);
kfree(r);
}
}
}
u8 *rndis_get_next_response (int configNr, u32 *length)
u8 *rndis_get_next_response(int configNr, u32 *length)
{
rndis_resp_t *r;
struct list_head *act, *tmp;
rndis_resp_t *r;
struct list_head *act, *tmp;
if (!length) return NULL;
list_for_each_safe (act, tmp,
&(rndis_per_dev_params [configNr].resp_queue))
list_for_each_safe(act, tmp,
&(rndis_per_dev_params[configNr].resp_queue))
{
r = list_entry (act, rndis_resp_t, list);
r = list_entry(act, rndis_resp_t, list);
if (!r->send) {
r->send = 1;
*length = r->length;
@ -1011,20 +1009,20 @@ u8 *rndis_get_next_response (int configNr, u32 *length)
return NULL;
}
static rndis_resp_t *rndis_add_response (int configNr, u32 length)
static rndis_resp_t *rndis_add_response(int configNr, u32 length)
{
rndis_resp_t *r;
rndis_resp_t *r;
/* NOTE: this gets copied into ether.c USB_BUFSIZ bytes ... */
r = kmalloc (sizeof (rndis_resp_t) + length, GFP_ATOMIC);
/* NOTE: this gets copied into ether.c USB_BUFSIZ bytes ... */
r = kmalloc(sizeof(rndis_resp_t) + length, GFP_ATOMIC);
if (!r) return NULL;
r->buf = (u8 *) (r + 1);
r->buf = (u8 *)(r + 1);
r->length = length;
r->send = 0;
list_add_tail (&r->list,
&(rndis_per_dev_params [configNr].resp_queue));
list_add_tail(&r->list,
&(rndis_per_dev_params[configNr].resp_queue));
return r;
}
@ -1033,7 +1031,7 @@ int rndis_rm_hdr(struct gether *port,
struct sk_buff_head *list)
{
/* tmp points to a struct rndis_packet_msg_type */
__le32 *tmp = (void *) skb->data;
__le32 *tmp = (void *)skb->data;
/* MessageType, MessageLength */
if (cpu_to_le32(REMOTE_NDIS_PACKET_MSG)
@ -1054,7 +1052,7 @@ int rndis_rm_hdr(struct gether *port,
return 0;
}
#ifdef CONFIG_USB_GADGET_DEBUG_FILES
#ifdef CONFIG_USB_GADGET_DEBUG_FILES
static int rndis_proc_show(struct seq_file *m, void *v)
{
@ -1087,7 +1085,7 @@ static int rndis_proc_show(struct seq_file *m, void *v)
}
static ssize_t rndis_proc_write(struct file *file, const char __user *buffer,
size_t count, loff_t *ppos)
size_t count, loff_t *ppos)
{
rndis_params *p = PDE(file->f_path.dentry->d_inode)->data;
u32 speed = 0;
@ -1109,11 +1107,11 @@ static ssize_t rndis_proc_write(struct file *file, const char __user *buffer,
case '8':
case '9':
fl_speed = 1;
speed = speed*10 + c - '0';
speed = speed * 10 + c - '0';
break;
case 'C':
case 'c':
rndis_signal_connect (p->confignr);
rndis_signal_connect(p->confignr);
break;
case 'D':
case 'd':
@ -1145,11 +1143,11 @@ static const struct file_operations rndis_proc_fops = {
.write = rndis_proc_write,
};
#define NAME_TEMPLATE "driver/rndis-%03d"
#define NAME_TEMPLATE "driver/rndis-%03d"
static struct proc_dir_entry *rndis_connect_state [RNDIS_MAX_CONFIGS];
#endif /* CONFIG_USB_GADGET_DEBUG_FILES */
#endif /* CONFIG_USB_GADGET_DEBUG_FILES */
int rndis_init(void)
@ -1160,42 +1158,40 @@ int rndis_init(void)
#ifdef CONFIG_USB_GADGET_DEBUG_FILES
char name [20];
sprintf (name, NAME_TEMPLATE, i);
if (!(rndis_connect_state [i]
= proc_create_data(name, 0660, NULL,
sprintf(name, NAME_TEMPLATE, i);
rndis_connect_state[i] = proc_create_data(name, 0660, NULL,
&rndis_proc_fops,
(void *)(rndis_per_dev_params + i))))
{
pr_debug("%s :remove entries", __func__);
(void *)(rndis_per_dev_params + i));
if (!rndis_connect_state[i]) {
pr_debug("%s: remove entries", __func__);
while (i) {
sprintf (name, NAME_TEMPLATE, --i);
remove_proc_entry (name, NULL);
sprintf(name, NAME_TEMPLATE, --i);
remove_proc_entry(name, NULL);
}
pr_debug("\n");
return -EIO;
}
#endif
rndis_per_dev_params [i].confignr = i;
rndis_per_dev_params [i].used = 0;
rndis_per_dev_params [i].state = RNDIS_UNINITIALIZED;
rndis_per_dev_params [i].media_state
rndis_per_dev_params[i].confignr = i;
rndis_per_dev_params[i].used = 0;
rndis_per_dev_params[i].state = RNDIS_UNINITIALIZED;
rndis_per_dev_params[i].media_state
= NDIS_MEDIA_STATE_DISCONNECTED;
INIT_LIST_HEAD (&(rndis_per_dev_params [i].resp_queue));
INIT_LIST_HEAD(&(rndis_per_dev_params[i].resp_queue));
}
return 0;
}
void rndis_exit (void)
void rndis_exit(void)
{
#ifdef CONFIG_USB_GADGET_DEBUG_FILES
#ifdef CONFIG_USB_GADGET_DEBUG_FILES
u8 i;
char name [20];
char name[20];
for (i = 0; i < RNDIS_MAX_CONFIGS; i++) {
sprintf (name, NAME_TEMPLATE, i);
remove_proc_entry (name, NULL);
sprintf(name, NAME_TEMPLATE, i);
remove_proc_entry(name, NULL);
}
#endif
}

View File

@ -2523,7 +2523,8 @@ static int s3c_hsotg_corereset(struct s3c_hsotg *hsotg)
return 0;
}
int usb_gadget_register_driver(struct usb_gadget_driver *driver)
int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
int (*bind)(struct usb_gadget *))
{
struct s3c_hsotg *hsotg = our_hsotg;
int ret;
@ -2543,7 +2544,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
dev_err(hsotg->dev, "%s: bad speed\n", __func__);
}
if (!driver->bind || !driver->setup) {
if (!bind || !driver->setup) {
dev_err(hsotg->dev, "%s: missing entry points\n", __func__);
return -EINVAL;
}
@ -2562,7 +2563,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
goto err;
}
ret = driver->bind(&hsotg->gadget);
ret = bind(&hsotg->gadget);
if (ret) {
dev_err(hsotg->dev, "failed bind %s\n", driver->driver.name);
@ -2687,7 +2688,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
hsotg->gadget.dev.driver = NULL;
return ret;
}
EXPORT_SYMBOL(usb_gadget_register_driver);
EXPORT_SYMBOL(usb_gadget_probe_driver);
int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
{

View File

@ -1632,15 +1632,15 @@ static void s3c2410_udc_enable(struct s3c2410_udc *dev)
}
/*
* usb_gadget_register_driver
* usb_gadget_probe_driver
*/
int usb_gadget_register_driver(struct usb_gadget_driver *driver)
int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
int (*bind)(struct usb_gadget *))
{
struct s3c2410_udc *udc = the_controller;
int retval;
dprintk(DEBUG_NORMAL, "usb_gadget_register_driver() '%s'\n",
driver->driver.name);
dprintk(DEBUG_NORMAL, "%s() '%s'\n", __func__, driver->driver.name);
/* Sanity checks */
if (!udc)
@ -1649,10 +1649,9 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
if (udc->driver)
return -EBUSY;
if (!driver->bind || !driver->setup
|| driver->speed < USB_SPEED_FULL) {
if (!bind || !driver->setup || driver->speed < USB_SPEED_FULL) {
printk(KERN_ERR "Invalid driver: bind %p setup %p speed %d\n",
driver->bind, driver->setup, driver->speed);
bind, driver->setup, driver->speed);
return -EINVAL;
}
#if defined(MODULE)
@ -1675,7 +1674,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
dprintk(DEBUG_NORMAL, "binding gadget driver '%s'\n",
driver->driver.name);
if ((retval = driver->bind (&udc->gadget)) != 0) {
if ((retval = bind(&udc->gadget)) != 0) {
device_del(&udc->gadget.dev);
goto register_error;
}
@ -1690,6 +1689,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
udc->gadget.dev.driver = NULL;
return retval;
}
EXPORT_SYMBOL(usb_gadget_probe_driver);
/*
* usb_gadget_unregister_driver
@ -2049,7 +2049,6 @@ static void __exit udc_exit(void)
}
EXPORT_SYMBOL(usb_gadget_unregister_driver);
EXPORT_SYMBOL(usb_gadget_register_driver);
module_init(udc_init);
module_exit(udc_exit);

View File

@ -137,7 +137,7 @@ MODULE_PARM_DESC(n_ports, "number of ports to create, default=1");
/*-------------------------------------------------------------------------*/
static int __ref serial_bind_config(struct usb_configuration *c)
static int __init serial_bind_config(struct usb_configuration *c)
{
unsigned i;
int status = 0;
@ -155,13 +155,12 @@ static int __ref serial_bind_config(struct usb_configuration *c)
static struct usb_configuration serial_config_driver = {
/* .label = f(use_acm) */
.bind = serial_bind_config,
/* .bConfigurationValue = f(use_acm) */
/* .iConfiguration = DYNAMIC */
.bmAttributes = USB_CONFIG_ATT_SELFPOWER,
};
static int __ref gs_bind(struct usb_composite_dev *cdev)
static int __init gs_bind(struct usb_composite_dev *cdev)
{
int gcnum;
struct usb_gadget *gadget = cdev->gadget;
@ -225,7 +224,8 @@ static int __ref gs_bind(struct usb_composite_dev *cdev)
}
/* register our configuration */
status = usb_add_config(cdev, &serial_config_driver);
status = usb_add_config(cdev, &serial_config_driver,
serial_bind_config);
if (status < 0)
goto fail;
@ -242,7 +242,6 @@ static struct usb_composite_driver gserial_driver = {
.name = "g_serial",
.dev = &device_desc,
.strings = dev_strings,
.bind = gs_bind,
};
static int __init init(void)
@ -271,7 +270,7 @@ static int __init init(void)
}
strings_dev[STRING_DESCRIPTION_IDX].s = serial_config_driver.label;
return usb_composite_register(&gserial_driver);
return usb_composite_probe(&gserial_driver, gs_bind);
}
module_init(init);

View File

@ -26,7 +26,6 @@
* be defined (each of type pointer to char):
* - fsg_string_manufacturer -- name of the manufacturer
* - fsg_string_product -- name of the product
* - fsg_string_serial -- product's serial
* - 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
@ -54,6 +53,8 @@
*/
#include <linux/usb/storage.h>
#include <scsi/scsi.h>
#include <asm/unaligned.h>
@ -153,23 +154,6 @@
/*-------------------------------------------------------------------------*/
/* SCSI device types */
#define TYPE_DISK 0x00
#define TYPE_CDROM 0x05
/* USB protocol value = the transport method */
#define USB_PR_CBI 0x00 /* Control/Bulk/Interrupt */
#define USB_PR_CB 0x01 /* Control/Bulk w/o interrupt */
#define USB_PR_BULK 0x50 /* Bulk-only */
/* USB subclass value = the protocol encapsulation */
#define USB_SC_RBC 0x01 /* Reduced Block Commands (flash) */
#define USB_SC_8020 0x02 /* SFF-8020i, MMC-2, ATAPI (CD-ROM) */
#define USB_SC_QIC 0x03 /* QIC-157 (tape) */
#define USB_SC_UFI 0x04 /* UFI (floppy) */
#define USB_SC_8070 0x05 /* SFF-8070i (removable) */
#define USB_SC_SCSI 0x06 /* Transparent SCSI */
/* Bulk-only data structures */
/* Command Block Wrapper */
@ -221,33 +205,6 @@ struct interrupt_data {
/* Length of a SCSI Command Data Block */
#define MAX_COMMAND_SIZE 16
/* SCSI commands that we recognize */
#define SC_FORMAT_UNIT 0x04
#define SC_INQUIRY 0x12
#define SC_MODE_SELECT_6 0x15
#define SC_MODE_SELECT_10 0x55
#define SC_MODE_SENSE_6 0x1a
#define SC_MODE_SENSE_10 0x5a
#define SC_PREVENT_ALLOW_MEDIUM_REMOVAL 0x1e
#define SC_READ_6 0x08
#define SC_READ_10 0x28
#define SC_READ_12 0xa8
#define SC_READ_CAPACITY 0x25
#define SC_READ_FORMAT_CAPACITIES 0x23
#define SC_READ_HEADER 0x44
#define SC_READ_TOC 0x43
#define SC_RELEASE 0x17
#define SC_REQUEST_SENSE 0x03
#define SC_RESERVE 0x16
#define SC_SEND_DIAGNOSTIC 0x1d
#define SC_START_STOP_UNIT 0x1b
#define SC_SYNCHRONIZE_CACHE 0x35
#define SC_TEST_UNIT_READY 0x00
#define SC_VERIFY 0x2f
#define SC_WRITE_6 0x0a
#define SC_WRITE_10 0x2a
#define SC_WRITE_12 0xaa
/* SCSI Sense Key/Additional Sense Code/ASC Qualifier values */
#define SS_NO_SENSE 0
#define SS_COMMUNICATION_FAILURE 0x040800
@ -552,7 +509,7 @@ 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_serial},
{FSG_STRING_SERIAL, ""},
{FSG_STRING_CONFIG, fsg_string_config},
#endif
{FSG_STRING_INTERFACE, fsg_string_interface},

View File

@ -308,7 +308,7 @@ static const struct uvc_descriptor_header * const uvc_hs_streaming_cls[] = {
* USB configuration
*/
static int __ref
static int __init
webcam_config_bind(struct usb_configuration *c)
{
return uvc_bind_config(c, uvc_control_cls, uvc_fs_streaming_cls,
@ -317,7 +317,6 @@ webcam_config_bind(struct usb_configuration *c)
static struct usb_configuration webcam_config_driver = {
.label = webcam_config_label,
.bind = webcam_config_bind,
.bConfigurationValue = 1,
.iConfiguration = 0, /* dynamic */
.bmAttributes = USB_CONFIG_ATT_SELFPOWER,
@ -330,7 +329,7 @@ webcam_unbind(struct usb_composite_dev *cdev)
return 0;
}
static int __ref
static int __init
webcam_bind(struct usb_composite_dev *cdev)
{
int ret;
@ -354,7 +353,8 @@ webcam_bind(struct usb_composite_dev *cdev)
webcam_config_driver.iConfiguration = ret;
/* Register our configuration. */
if ((ret = usb_add_config(cdev, &webcam_config_driver)) < 0)
if ((ret = usb_add_config(cdev, &webcam_config_driver,
webcam_config_bind)) < 0)
goto error;
INFO(cdev, "Webcam Video Gadget\n");
@ -373,14 +373,13 @@ static struct usb_composite_driver webcam_driver = {
.name = "g_webcam",
.dev = &webcam_device_descriptor,
.strings = webcam_device_strings,
.bind = webcam_bind,
.unbind = webcam_unbind,
};
static int __init
webcam_init(void)
{
return usb_composite_register(&webcam_driver);
return usb_composite_probe(&webcam_driver, webcam_bind);
}
static void __exit

View File

@ -264,7 +264,7 @@ static void zero_resume(struct usb_composite_dev *cdev)
/*-------------------------------------------------------------------------*/
static int __ref zero_bind(struct usb_composite_dev *cdev)
static int __init zero_bind(struct usb_composite_dev *cdev)
{
int gcnum;
struct usb_gadget *gadget = cdev->gadget;
@ -340,7 +340,6 @@ static struct usb_composite_driver zero_driver = {
.name = "zero",
.dev = &device_desc,
.strings = dev_strings,
.bind = zero_bind,
.unbind = zero_unbind,
.suspend = zero_suspend,
.resume = zero_resume,
@ -351,7 +350,7 @@ MODULE_LICENSE("GPL");
static int __init init(void)
{
return usb_composite_register(&zero_driver);
return usb_composite_probe(&zero_driver, zero_bind);
}
module_init(init);

View File

@ -93,12 +93,14 @@ config USB_EHCI_TT_NEWSCHED
config USB_EHCI_BIG_ENDIAN_MMIO
bool
depends on USB_EHCI_HCD && (PPC_CELLEB || PPC_PS3 || 440EPX || ARCH_IXP4XX || XPS_USB_HCD_XILINX)
depends on USB_EHCI_HCD && (PPC_CELLEB || PPC_PS3 || 440EPX || ARCH_IXP4XX || \
XPS_USB_HCD_XILINX || PPC_MPC512x)
default y
config USB_EHCI_BIG_ENDIAN_DESC
bool
depends on USB_EHCI_HCD && (440EPX || ARCH_IXP4XX || XPS_USB_HCD_XILINX)
depends on USB_EHCI_HCD && (440EPX || ARCH_IXP4XX || XPS_USB_HCD_XILINX || \
PPC_MPC512x)
default y
config XPS_USB_HCD_XILINX
@ -112,10 +114,14 @@ config XPS_USB_HCD_XILINX
support both high speed and full speed devices, or high speed
devices only.
config USB_FSL_MPH_DR_OF
tristate
config USB_EHCI_FSL
bool "Support for Freescale on-chip EHCI USB controller"
depends on USB_EHCI_HCD && FSL_SOC
select USB_EHCI_ROOT_HUB_TT
select USB_FSL_MPH_DR_OF
---help---
Variation of ARC USB block used in some Freescale chips.

View File

@ -2,17 +2,17 @@
# Makefile for USB Host Controller Drivers
#
ifeq ($(CONFIG_USB_DEBUG),y)
EXTRA_CFLAGS += -DDEBUG
endif
ccflags-$(CONFIG_USB_DEBUG) := -DDEBUG
isp1760-objs := isp1760-hcd.o isp1760-if.o
fhci-objs := fhci-hcd.o fhci-hub.o fhci-q.o fhci-mem.o \
fhci-tds.o fhci-sched.o
ifeq ($(CONFIG_FHCI_DEBUG),y)
fhci-objs += fhci-dbg.o
endif
xhci-hcd-objs := xhci.o xhci-mem.o xhci-pci.o xhci-ring.o xhci-hub.o xhci-dbg.o
isp1760-y := isp1760-hcd.o isp1760-if.o
fhci-y := fhci-hcd.o fhci-hub.o fhci-q.o
fhci-y += fhci-mem.o fhci-tds.o fhci-sched.o
fhci-$(CONFIG_FHCI_DEBUG) += fhci-dbg.o
xhci-hcd-y := xhci.o xhci-mem.o xhci-pci.o
xhci-hcd-y += xhci-ring.o xhci-hub.o xhci-dbg.o
obj-$(CONFIG_USB_WHCI_HCD) += whci/
@ -33,4 +33,4 @@ obj-$(CONFIG_USB_R8A66597_HCD) += r8a66597-hcd.o
obj-$(CONFIG_USB_ISP1760_HCD) += isp1760.o
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

View File

@ -116,13 +116,33 @@ static int usb_hcd_fsl_probe(const struct hc_driver *driver,
goto err3;
}
/* Enable USB controller */
temp = in_be32(hcd->regs + 0x500);
out_be32(hcd->regs + 0x500, temp | 0x4);
pdata->regs = hcd->regs;
/* Set to Host mode */
temp = in_le32(hcd->regs + 0x1a8);
out_le32(hcd->regs + 0x1a8, temp | 0x3);
/*
* do platform specific init: check the clock, grab/config pins, etc.
*/
if (pdata->init && pdata->init(pdev)) {
retval = -ENODEV;
goto err3;
}
/*
* Check if it is MPC5121 SoC, otherwise set pdata->have_sysif_regs
* flag for 83xx or 8536 system interface registers.
*/
if (pdata->big_endian_mmio)
temp = in_be32(hcd->regs + FSL_SOC_USB_ID);
else
temp = in_le32(hcd->regs + FSL_SOC_USB_ID);
if ((temp & ID_MSK) != (~((temp & NID_MSK) >> 8) & ID_MSK))
pdata->have_sysif_regs = 1;
/* Enable USB controller, 83xx or 8536 */
if (pdata->have_sysif_regs)
setbits32(hcd->regs + FSL_SOC_USB_CTRL, 0x4);
/* Don't need to set host mode here. It will be done by tdi_reset() */
retval = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED);
if (retval != 0)
@ -137,6 +157,8 @@ static int usb_hcd_fsl_probe(const struct hc_driver *driver,
usb_put_hcd(hcd);
err1:
dev_err(&pdev->dev, "init %s fail, %d\n", dev_name(&pdev->dev), retval);
if (pdata->exit)
pdata->exit(pdev);
return retval;
}
@ -154,17 +176,30 @@ static int usb_hcd_fsl_probe(const struct hc_driver *driver,
static void usb_hcd_fsl_remove(struct usb_hcd *hcd,
struct platform_device *pdev)
{
struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
usb_remove_hcd(hcd);
/*
* do platform specific un-initialization:
* release iomux pins, disable clock, etc.
*/
if (pdata->exit)
pdata->exit(pdev);
iounmap(hcd->regs);
release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
usb_put_hcd(hcd);
}
static void mpc83xx_setup_phy(struct ehci_hcd *ehci,
enum fsl_usb2_phy_modes phy_mode,
unsigned int port_offset)
static void ehci_fsl_setup_phy(struct ehci_hcd *ehci,
enum fsl_usb2_phy_modes phy_mode,
unsigned int port_offset)
{
u32 portsc = 0;
u32 portsc;
portsc = ehci_readl(ehci, &ehci->regs->port_status[port_offset]);
portsc &= ~(PORT_PTS_MSK | PORT_PTS_PTW);
switch (phy_mode) {
case FSL_USB2_PHY_ULPI:
portsc |= PORT_PTS_ULPI;
@ -184,20 +219,21 @@ static void mpc83xx_setup_phy(struct ehci_hcd *ehci,
ehci_writel(ehci, portsc, &ehci->regs->port_status[port_offset]);
}
static void mpc83xx_usb_setup(struct usb_hcd *hcd)
static void ehci_fsl_usb_setup(struct ehci_hcd *ehci)
{
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
struct usb_hcd *hcd = ehci_to_hcd(ehci);
struct fsl_usb2_platform_data *pdata;
void __iomem *non_ehci = hcd->regs;
u32 temp;
pdata =
(struct fsl_usb2_platform_data *)hcd->self.controller->
platform_data;
pdata = hcd->self.controller->platform_data;
/* Enable PHY interface in the control reg. */
temp = in_be32(non_ehci + FSL_SOC_USB_CTRL);
out_be32(non_ehci + FSL_SOC_USB_CTRL, temp | 0x00000004);
out_be32(non_ehci + FSL_SOC_USB_SNOOP1, 0x0000001b);
if (pdata->have_sysif_regs) {
temp = in_be32(non_ehci + FSL_SOC_USB_CTRL);
out_be32(non_ehci + FSL_SOC_USB_CTRL, temp | 0x00000004);
out_be32(non_ehci + FSL_SOC_USB_SNOOP1, 0x0000001b);
}
#if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
/*
@ -214,7 +250,7 @@ static void mpc83xx_usb_setup(struct usb_hcd *hcd)
if ((pdata->operating_mode == FSL_USB2_DR_HOST) ||
(pdata->operating_mode == FSL_USB2_DR_OTG))
mpc83xx_setup_phy(ehci, pdata->phy_mode, 0);
ehci_fsl_setup_phy(ehci, pdata->phy_mode, 0);
if (pdata->operating_mode == FSL_USB2_MPH_HOST) {
unsigned int chip, rev, svr;
@ -228,27 +264,27 @@ static void mpc83xx_usb_setup(struct usb_hcd *hcd)
ehci->has_fsl_port_bug = 1;
if (pdata->port_enables & FSL_USB2_PORT0_ENABLED)
mpc83xx_setup_phy(ehci, pdata->phy_mode, 0);
ehci_fsl_setup_phy(ehci, pdata->phy_mode, 0);
if (pdata->port_enables & FSL_USB2_PORT1_ENABLED)
mpc83xx_setup_phy(ehci, pdata->phy_mode, 1);
ehci_fsl_setup_phy(ehci, pdata->phy_mode, 1);
}
/* put controller in host mode. */
ehci_writel(ehci, 0x00000003, non_ehci + FSL_SOC_USB_USBMODE);
if (pdata->have_sysif_regs) {
#ifdef CONFIG_PPC_85xx
out_be32(non_ehci + FSL_SOC_USB_PRICTRL, 0x00000008);
out_be32(non_ehci + FSL_SOC_USB_AGECNTTHRSH, 0x00000080);
out_be32(non_ehci + FSL_SOC_USB_PRICTRL, 0x00000008);
out_be32(non_ehci + FSL_SOC_USB_AGECNTTHRSH, 0x00000080);
#else
out_be32(non_ehci + FSL_SOC_USB_PRICTRL, 0x0000000c);
out_be32(non_ehci + FSL_SOC_USB_AGECNTTHRSH, 0x00000040);
out_be32(non_ehci + FSL_SOC_USB_PRICTRL, 0x0000000c);
out_be32(non_ehci + FSL_SOC_USB_AGECNTTHRSH, 0x00000040);
#endif
out_be32(non_ehci + FSL_SOC_USB_SICTRL, 0x00000001);
out_be32(non_ehci + FSL_SOC_USB_SICTRL, 0x00000001);
}
}
/* called after powerup, by probe or system-pm "wakeup" */
static int ehci_fsl_reinit(struct ehci_hcd *ehci)
{
mpc83xx_usb_setup(ehci_to_hcd(ehci));
ehci_fsl_usb_setup(ehci);
ehci_port_power(ehci, 0);
return 0;
@ -259,6 +295,11 @@ static int ehci_fsl_setup(struct usb_hcd *hcd)
{
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
int retval;
struct fsl_usb2_platform_data *pdata;
pdata = hcd->self.controller->platform_data;
ehci->big_endian_desc = pdata->big_endian_desc;
ehci->big_endian_mmio = pdata->big_endian_mmio;
/* EHCI registers start at offset 0x100 */
ehci->caps = hcd->regs + 0x100;
@ -270,6 +311,8 @@ static int ehci_fsl_setup(struct usb_hcd *hcd)
/* cache this readonly data; minimize chip reads */
ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
hcd->has_tt = 1;
retval = ehci_halt(ehci);
if (retval)
return retval;
@ -279,8 +322,6 @@ static int ehci_fsl_setup(struct usb_hcd *hcd)
if (retval)
return retval;
hcd->has_tt = 1;
ehci->sbrn = 0x20;
ehci_reset(ehci);
@ -372,7 +413,7 @@ static const struct hc_driver ehci_fsl_hc_driver = {
* generic hardware linkage
*/
.irq = ehci_irq,
.flags = HCD_USB2,
.flags = HCD_USB2 | HCD_MEMORY,
/*
* basic lifecycle operations

View File

@ -1,4 +1,4 @@
/* Copyright (c) 2005 freescale semiconductor
/* Copyright (C) 2005-2010 Freescale Semiconductor, Inc.
* Copyright (c) 2005 MontaVista Software
*
* This program is free software; you can redistribute it and/or modify it
@ -19,6 +19,9 @@
#define _EHCI_FSL_H
/* offsets for the non-ehci registers in the FSL SOC USB controller */
#define FSL_SOC_USB_ID 0x0
#define ID_MSK 0x3f
#define NID_MSK 0x3f00
#define FSL_SOC_USB_ULPIVP 0x170
#define FSL_SOC_USB_PORTSC1 0x184
#define PORT_PTS_MSK (3<<30)
@ -27,7 +30,14 @@
#define PORT_PTS_SERIAL (3<<30)
#define PORT_PTS_PTW (1<<28)
#define FSL_SOC_USB_PORTSC2 0x188
#define FSL_SOC_USB_USBMODE 0x1a8
#define FSL_SOC_USB_USBGENCTRL 0x200
#define USBGENCTRL_PPP (1 << 3)
#define USBGENCTRL_PFP (1 << 2)
#define FSL_SOC_USB_ISIPHYCTRL 0x204
#define ISIPHYCTRL_PXE (1)
#define ISIPHYCTRL_PHYE (1 << 4)
#define FSL_SOC_USB_SNOOP1 0x400 /* NOTE: big-endian */
#define FSL_SOC_USB_SNOOP2 0x404 /* NOTE: big-endian */
#define FSL_SOC_USB_AGECNTTHRSH 0x408 /* NOTE: big-endian */

View File

@ -194,6 +194,17 @@ static int handshake (struct ehci_hcd *ehci, void __iomem *ptr,
return -ETIMEDOUT;
}
/* check TDI/ARC silicon is in host mode */
static int tdi_in_host_mode (struct ehci_hcd *ehci)
{
u32 __iomem *reg_ptr;
u32 tmp;
reg_ptr = (u32 __iomem *)(((u8 __iomem *)ehci->regs) + USBMODE);
tmp = ehci_readl(ehci, reg_ptr);
return (tmp & 3) == USBMODE_CM_HC;
}
/* force HC to halt state from unknown (EHCI spec section 2.3) */
static int ehci_halt (struct ehci_hcd *ehci)
{
@ -202,6 +213,10 @@ static int ehci_halt (struct ehci_hcd *ehci)
/* disable any irqs left enabled by previous code */
ehci_writel(ehci, 0, &ehci->regs->intr_enable);
if (ehci_is_TDI(ehci) && tdi_in_host_mode(ehci) == 0) {
return 0;
}
if ((temp & STS_HALT) != 0)
return 0;

View File

@ -40,7 +40,7 @@ static inline void ehci_qtd_init(struct ehci_hcd *ehci, struct ehci_qtd *qtd,
{
memset (qtd, 0, sizeof *qtd);
qtd->qtd_dma = dma;
qtd->hw_token = cpu_to_le32 (QTD_STS_HALT);
qtd->hw_token = cpu_to_hc32(ehci, QTD_STS_HALT);
qtd->hw_next = EHCI_LIST_END(ehci);
qtd->hw_alt_next = EHCI_LIST_END(ehci);
INIT_LIST_HEAD (&qtd->qtd_list);

View File

@ -26,9 +26,6 @@
#include <mach/mxc_ehci.h>
#define ULPI_VIEWPORT_OFFSET 0x170
#define PORTSC_OFFSET 0x184
#define USBMODE_OFFSET 0x1a8
#define USBMODE_CM_HOST 3
struct ehci_mxc_priv {
struct clk *usbclk, *ahbclk;
@ -51,6 +48,8 @@ static int ehci_mxc_setup(struct usb_hcd *hcd)
/* cache this readonly data; minimize chip reads */
ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
hcd->has_tt = 1;
retval = ehci_halt(ehci);
if (retval)
return retval;
@ -60,8 +59,6 @@ static int ehci_mxc_setup(struct usb_hcd *hcd)
if (retval)
return retval;
hcd->has_tt = 1;
ehci->sbrn = 0x20;
ehci_reset(ehci);
@ -191,12 +188,8 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev)
clk_enable(priv->ahbclk);
}
/* set USBMODE to host mode */
temp = readl(hcd->regs + USBMODE_OFFSET);
writel(temp | USBMODE_CM_HOST, hcd->regs + USBMODE_OFFSET);
/* set up the PORTSCx register */
writel(pdata->portsc, hcd->regs + PORTSC_OFFSET);
ehci_writel(ehci, pdata->portsc, &ehci->regs->port_status[0]);
mdelay(10);
/* setup specific usb hw */

View File

@ -0,0 +1,308 @@
/*
* Setup platform devices needed by the Freescale multi-port host
* and/or dual-role USB controller modules based on the description
* in flat device tree.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/fsl_devices.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/of_platform.h>
#include <linux/clk.h>
struct fsl_usb2_dev_data {
char *dr_mode; /* controller mode */
char *drivers[3]; /* drivers to instantiate for this mode */
enum fsl_usb2_operating_modes op_mode; /* operating mode */
};
struct fsl_usb2_dev_data dr_mode_data[] __devinitdata = {
{
.dr_mode = "host",
.drivers = { "fsl-ehci", NULL, NULL, },
.op_mode = FSL_USB2_DR_HOST,
},
{
.dr_mode = "otg",
.drivers = { "fsl-usb2-otg", "fsl-ehci", "fsl-usb2-udc", },
.op_mode = FSL_USB2_DR_OTG,
},
{
.dr_mode = "peripheral",
.drivers = { "fsl-usb2-udc", NULL, NULL, },
.op_mode = FSL_USB2_DR_DEVICE,
},
};
struct fsl_usb2_dev_data * __devinit get_dr_mode_data(struct device_node *np)
{
const unsigned char *prop;
int i;
prop = of_get_property(np, "dr_mode", NULL);
if (prop) {
for (i = 0; i < ARRAY_SIZE(dr_mode_data); i++) {
if (!strcmp(prop, dr_mode_data[i].dr_mode))
return &dr_mode_data[i];
}
}
pr_warn("%s: Invalid 'dr_mode' property, fallback to host mode\n",
np->full_name);
return &dr_mode_data[0]; /* mode not specified, use host */
}
static enum fsl_usb2_phy_modes __devinit determine_usb_phy(const char *phy_type)
{
if (!phy_type)
return FSL_USB2_PHY_NONE;
if (!strcasecmp(phy_type, "ulpi"))
return FSL_USB2_PHY_ULPI;
if (!strcasecmp(phy_type, "utmi"))
return FSL_USB2_PHY_UTMI;
if (!strcasecmp(phy_type, "utmi_wide"))
return FSL_USB2_PHY_UTMI_WIDE;
if (!strcasecmp(phy_type, "serial"))
return FSL_USB2_PHY_SERIAL;
return FSL_USB2_PHY_NONE;
}
struct platform_device * __devinit fsl_usb2_device_register(
struct platform_device *ofdev,
struct fsl_usb2_platform_data *pdata,
const char *name, int id)
{
struct platform_device *pdev;
const struct resource *res = ofdev->resource;
unsigned int num = ofdev->num_resources;
int retval;
pdev = platform_device_alloc(name, id);
if (!pdev) {
retval = -ENOMEM;
goto error;
}
pdev->dev.parent = &ofdev->dev;
pdev->dev.coherent_dma_mask = ofdev->dev.coherent_dma_mask;
pdev->dev.dma_mask = &pdev->archdata.dma_mask;
*pdev->dev.dma_mask = *ofdev->dev.dma_mask;
retval = platform_device_add_data(pdev, pdata, sizeof(*pdata));
if (retval)
goto error;
if (num) {
retval = platform_device_add_resources(pdev, res, num);
if (retval)
goto error;
}
retval = platform_device_add(pdev);
if (retval)
goto error;
return pdev;
error:
platform_device_put(pdev);
return ERR_PTR(retval);
}
static const struct of_device_id fsl_usb2_mph_dr_of_match[];
static int __devinit fsl_usb2_mph_dr_of_probe(struct platform_device *ofdev)
{
struct device_node *np = ofdev->dev.of_node;
struct platform_device *usb_dev;
struct fsl_usb2_platform_data data, *pdata;
struct fsl_usb2_dev_data *dev_data;
const struct of_device_id *match;
const unsigned char *prop;
static unsigned int idx;
int i;
if (!of_device_is_available(np))
return -ENODEV;
match = of_match_device(fsl_usb2_mph_dr_of_match, &ofdev->dev);
if (!match)
return -ENODEV;
pdata = &data;
if (match->data)
memcpy(pdata, match->data, sizeof(data));
else
memset(pdata, 0, sizeof(data));
dev_data = get_dr_mode_data(np);
if (of_device_is_compatible(np, "fsl-usb2-mph")) {
if (of_get_property(np, "port0", NULL))
pdata->port_enables |= FSL_USB2_PORT0_ENABLED;
if (of_get_property(np, "port1", NULL))
pdata->port_enables |= FSL_USB2_PORT1_ENABLED;
pdata->operating_mode = FSL_USB2_MPH_HOST;
} else {
if (of_get_property(np, "fsl,invert-drvvbus", NULL))
pdata->invert_drvvbus = 1;
if (of_get_property(np, "fsl,invert-pwr-fault", NULL))
pdata->invert_pwr_fault = 1;
/* setup mode selected in the device tree */
pdata->operating_mode = dev_data->op_mode;
}
prop = of_get_property(np, "phy_type", NULL);
pdata->phy_mode = determine_usb_phy(prop);
for (i = 0; i < ARRAY_SIZE(dev_data->drivers); i++) {
if (!dev_data->drivers[i])
continue;
usb_dev = fsl_usb2_device_register(ofdev, pdata,
dev_data->drivers[i], idx);
if (IS_ERR(usb_dev)) {
dev_err(&ofdev->dev, "Can't register usb device\n");
return PTR_ERR(usb_dev);
}
}
idx++;
return 0;
}
static int __devexit __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)
{
device_for_each_child(&ofdev->dev, NULL, __unregister_subdev);
return 0;
}
#ifdef CONFIG_PPC_MPC512x
#define USBGENCTRL 0x200 /* NOTE: big endian */
#define GC_WU_INT_CLR (1 << 5) /* Wakeup int clear */
#define GC_ULPI_SEL (1 << 4) /* ULPI i/f select (usb0 only)*/
#define GC_PPP (1 << 3) /* Inv. Port Power Polarity */
#define GC_PFP (1 << 2) /* Inv. Power Fault Polarity */
#define GC_WU_ULPI_EN (1 << 1) /* Wakeup on ULPI event */
#define GC_WU_IE (1 << 1) /* Wakeup interrupt enable */
#define ISIPHYCTRL 0x204 /* NOTE: big endian */
#define PHYCTRL_PHYE (1 << 4) /* On-chip UTMI PHY enable */
#define PHYCTRL_BSENH (1 << 3) /* Bit Stuff Enable High */
#define PHYCTRL_BSEN (1 << 2) /* Bit Stuff Enable */
#define PHYCTRL_LSFE (1 << 1) /* Line State Filter Enable */
#define PHYCTRL_PXE (1 << 0) /* PHY oscillator enable */
int fsl_usb2_mpc5121_init(struct platform_device *pdev)
{
struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
struct clk *clk;
char clk_name[10];
int base, clk_num;
base = pdev->resource->start & 0xf000;
if (base == 0x3000)
clk_num = 1;
else if (base == 0x4000)
clk_num = 2;
else
return -ENODEV;
snprintf(clk_name, sizeof(clk_name), "usb%d_clk", clk_num);
clk = clk_get(&pdev->dev, clk_name);
if (IS_ERR(clk)) {
dev_err(&pdev->dev, "failed to get clk\n");
return PTR_ERR(clk);
}
clk_enable(clk);
pdata->clk = clk;
if (pdata->phy_mode == FSL_USB2_PHY_UTMI_WIDE) {
u32 reg = 0;
if (pdata->invert_drvvbus)
reg |= GC_PPP;
if (pdata->invert_pwr_fault)
reg |= GC_PFP;
out_be32(pdata->regs + ISIPHYCTRL, PHYCTRL_PHYE | PHYCTRL_PXE);
out_be32(pdata->regs + USBGENCTRL, reg);
}
return 0;
}
static void fsl_usb2_mpc5121_exit(struct platform_device *pdev)
{
struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
pdata->regs = NULL;
if (pdata->clk) {
clk_disable(pdata->clk);
clk_put(pdata->clk);
}
}
struct fsl_usb2_platform_data fsl_usb2_mpc5121_pd = {
.big_endian_desc = 1,
.big_endian_mmio = 1,
.es = 1,
.le_setup_buf = 1,
.init = fsl_usb2_mpc5121_init,
.exit = fsl_usb2_mpc5121_exit,
};
#endif /* CONFIG_PPC_MPC512x */
static const struct of_device_id fsl_usb2_mph_dr_of_match[] = {
{ .compatible = "fsl-usb2-mph", },
{ .compatible = "fsl-usb2-dr", },
#ifdef CONFIG_PPC_MPC512x
{ .compatible = "fsl,mpc5121-usb2-dr", .data = &fsl_usb2_mpc5121_pd, },
#endif
{},
};
static struct platform_driver fsl_usb2_mph_dr_driver = {
.driver = {
.name = "fsl-usb2-mph-dr",
.owner = THIS_MODULE,
.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),
};
static int __init fsl_usb2_mph_dr_init(void)
{
return platform_driver_register(&fsl_usb2_mph_dr_driver);
}
module_init(fsl_usb2_mph_dr_init);
static void __exit fsl_usb2_mph_dr_exit(void)
{
platform_driver_unregister(&fsl_usb2_mph_dr_driver);
}
module_exit(fsl_usb2_mph_dr_exit);
MODULE_DESCRIPTION("FSL MPH DR OF devices driver");
MODULE_AUTHOR("Anatolij Gustschin <agust@denx.de>");
MODULE_LICENSE("GPL");

View File

@ -57,6 +57,7 @@
#include <linux/slab.h>
#include <linux/usb.h>
#include <linux/usb/hcd.h>
#include <linux/dma-mapping.h>
#include "imx21-hcd.h"
@ -136,9 +137,18 @@ static int imx21_hc_get_frame(struct usb_hcd *hcd)
return wrap_frame(readl(imx21->regs + USBH_FRMNUB));
}
static inline bool unsuitable_for_dma(dma_addr_t addr)
{
return (addr & 3) != 0;
}
#include "imx21-dbg.c"
static void nonisoc_urb_completed_for_etd(
struct imx21 *imx21, struct etd_priv *etd, int status);
static void schedule_nonisoc_etd(struct imx21 *imx21, struct urb *urb);
static void free_dmem(struct imx21 *imx21, struct etd_priv *etd);
/* =========================================== */
/* ETD management */
/* =========================================== */
@ -185,7 +195,8 @@ static void reset_etd(struct imx21 *imx21, int num)
etd_writel(imx21, num, i, 0);
etd->urb = NULL;
etd->ep = NULL;
etd->td = NULL;;
etd->td = NULL;
etd->bounce_buffer = NULL;
}
static void free_etd(struct imx21 *imx21, int num)
@ -221,26 +232,94 @@ static void setup_etd_dword0(struct imx21 *imx21,
((u32) maxpacket << DW0_MAXPKTSIZ));
}
static void activate_etd(struct imx21 *imx21,
int etd_num, dma_addr_t dma, u8 dir)
/**
* Copy buffer to data controller data memory.
* We cannot use memcpy_toio() because the hardware requires 32bit writes
*/
static void copy_to_dmem(
struct imx21 *imx21, int dmem_offset, void *src, int count)
{
void __iomem *dmem = imx21->regs + USBOTG_DMEM + dmem_offset;
u32 word = 0;
u8 *p = src;
int byte = 0;
int i;
for (i = 0; i < count; i++) {
byte = i % 4;
word += (*p++ << (byte * 8));
if (byte == 3) {
writel(word, dmem);
dmem += 4;
word = 0;
}
}
if (count && byte != 3)
writel(word, dmem);
}
static void activate_etd(struct imx21 *imx21, int etd_num, u8 dir)
{
u32 etd_mask = 1 << etd_num;
struct etd_priv *etd = &imx21->etd[etd_num];
if (etd->dma_handle && unsuitable_for_dma(etd->dma_handle)) {
/* For non aligned isoc the condition below is always true */
if (etd->len <= etd->dmem_size) {
/* Fits into data memory, use PIO */
if (dir != TD_DIR_IN) {
copy_to_dmem(imx21,
etd->dmem_offset,
etd->cpu_buffer, etd->len);
}
etd->dma_handle = 0;
} else {
/* Too big for data memory, use bounce buffer */
enum dma_data_direction dmadir;
if (dir == TD_DIR_IN) {
dmadir = DMA_FROM_DEVICE;
etd->bounce_buffer = kmalloc(etd->len,
GFP_ATOMIC);
} else {
dmadir = DMA_TO_DEVICE;
etd->bounce_buffer = kmemdup(etd->cpu_buffer,
etd->len,
GFP_ATOMIC);
}
if (!etd->bounce_buffer) {
dev_err(imx21->dev, "failed bounce alloc\n");
goto err_bounce_alloc;
}
etd->dma_handle =
dma_map_single(imx21->dev,
etd->bounce_buffer,
etd->len,
dmadir);
if (dma_mapping_error(imx21->dev, etd->dma_handle)) {
dev_err(imx21->dev, "failed bounce map\n");
goto err_bounce_map;
}
}
}
clear_toggle_bit(imx21, USBH_ETDDONESTAT, etd_mask);
set_register_bits(imx21, USBH_ETDDONEEN, etd_mask);
clear_toggle_bit(imx21, USBH_XFILLSTAT, etd_mask);
clear_toggle_bit(imx21, USBH_YFILLSTAT, etd_mask);
if (dma) {
if (etd->dma_handle) {
set_register_bits(imx21, USB_ETDDMACHANLCLR, etd_mask);
clear_toggle_bit(imx21, USBH_XBUFSTAT, etd_mask);
clear_toggle_bit(imx21, USBH_YBUFSTAT, etd_mask);
writel(dma, imx21->regs + USB_ETDSMSA(etd_num));
writel(etd->dma_handle, imx21->regs + USB_ETDSMSA(etd_num));
set_register_bits(imx21, USB_ETDDMAEN, etd_mask);
} else {
if (dir != TD_DIR_IN) {
/* need to set for ZLP */
/* need to set for ZLP and PIO */
set_toggle_bit(imx21, USBH_XFILLSTAT, etd_mask);
set_toggle_bit(imx21, USBH_YFILLSTAT, etd_mask);
}
@ -263,6 +342,14 @@ static void activate_etd(struct imx21 *imx21,
etd->active_count = 1;
writel(etd_mask, imx21->regs + USBH_ETDENSET);
return;
err_bounce_map:
kfree(etd->bounce_buffer);
err_bounce_alloc:
free_dmem(imx21, etd);
nonisoc_urb_completed_for_etd(imx21, etd, -ENOMEM);
}
/* =========================================== */
@ -323,16 +410,23 @@ static void activate_queued_etd(struct imx21 *imx21,
etd_writel(imx21, etd_num, 1,
((dmem_offset + maxpacket) << DW1_YBUFSRTAD) | dmem_offset);
etd->dmem_offset = dmem_offset;
urb_priv->active = 1;
activate_etd(imx21, etd_num, etd->dma_handle, dir);
activate_etd(imx21, etd_num, dir);
}
static void free_dmem(struct imx21 *imx21, int offset)
static void free_dmem(struct imx21 *imx21, struct etd_priv *etd)
{
struct imx21_dmem_area *area;
struct etd_priv *etd, *tmp;
struct etd_priv *tmp;
int found = 0;
int offset;
if (!etd->dmem_size)
return;
etd->dmem_size = 0;
offset = etd->dmem_offset;
list_for_each_entry(area, &imx21->dmem_list, list) {
if (area->offset == offset) {
debug_dmem_freed(imx21, area->size);
@ -378,20 +472,23 @@ static void free_epdmem(struct imx21 *imx21, struct usb_host_endpoint *ep)
/* =========================================== */
/* End handling */
/* =========================================== */
static void schedule_nonisoc_etd(struct imx21 *imx21, struct urb *urb);
/* Endpoint now idle - release it's ETD(s) or asssign to queued request */
static void ep_idle(struct imx21 *imx21, struct ep_priv *ep_priv)
{
int etd_num;
int i;
for (i = 0; i < NUM_ISO_ETDS; i++) {
etd_num = ep_priv->etd[i];
int etd_num = ep_priv->etd[i];
struct etd_priv *etd;
if (etd_num < 0)
continue;
etd = &imx21->etd[etd_num];
ep_priv->etd[i] = -1;
free_dmem(imx21, etd); /* for isoc */
if (list_empty(&imx21->queue_for_etd)) {
free_etd(imx21, etd_num);
continue;
@ -437,6 +534,24 @@ __acquires(imx21->lock)
ep_idle(imx21, ep_priv);
}
static void nonisoc_urb_completed_for_etd(
struct imx21 *imx21, struct etd_priv *etd, int status)
{
struct usb_host_endpoint *ep = etd->ep;
urb_done(imx21->hcd, etd->urb, status);
etd->urb = NULL;
if (!list_empty(&ep->urb_list)) {
struct urb *urb = list_first_entry(
&ep->urb_list, struct urb, urb_list);
dev_vdbg(imx21->dev, "next URB %p\n", urb);
schedule_nonisoc_etd(imx21, urb);
}
}
/* =========================================== */
/* ISOC Handling ... */
/* =========================================== */
@ -489,6 +604,8 @@ static void schedule_isoc_etds(struct usb_hcd *hcd,
etd->ep = td->ep;
etd->urb = td->urb;
etd->len = td->len;
etd->dma_handle = td->dma_handle;
etd->cpu_buffer = td->cpu_buffer;
debug_isoc_submitted(imx21, cur_frame, td);
@ -502,16 +619,17 @@ static void schedule_isoc_etds(struct usb_hcd *hcd,
(TD_NOTACCESSED << DW3_COMPCODE0) |
(td->len << DW3_PKTLEN0));
activate_etd(imx21, etd_num, td->data, dir);
activate_etd(imx21, etd_num, dir);
}
}
static void isoc_etd_done(struct usb_hcd *hcd, struct urb *urb, int etd_num)
static void isoc_etd_done(struct usb_hcd *hcd, int etd_num)
{
struct imx21 *imx21 = hcd_to_imx21(hcd);
int etd_mask = 1 << etd_num;
struct urb_priv *urb_priv = urb->hcpriv;
struct etd_priv *etd = imx21->etd + etd_num;
struct urb *urb = etd->urb;
struct urb_priv *urb_priv = urb->hcpriv;
struct td *td = etd->td;
struct usb_host_endpoint *ep = etd->ep;
int isoc_index = td->isoc_index;
@ -545,8 +663,13 @@ static void isoc_etd_done(struct usb_hcd *hcd, struct urb *urb, int etd_num)
bytes_xfrd, td->len, urb, etd_num, isoc_index);
}
if (dir_in)
if (dir_in) {
clear_toggle_bit(imx21, USBH_XFILLSTAT, etd_mask);
if (!etd->dma_handle)
memcpy_fromio(etd->cpu_buffer,
imx21->regs + USBOTG_DMEM + etd->dmem_offset,
bytes_xfrd);
}
urb->actual_length += bytes_xfrd;
urb->iso_frame_desc[isoc_index].actual_length = bytes_xfrd;
@ -569,30 +692,43 @@ static struct ep_priv *alloc_isoc_ep(
int i;
ep_priv = kzalloc(sizeof(struct ep_priv), GFP_ATOMIC);
if (ep_priv == NULL)
if (!ep_priv)
return NULL;
/* Allocate the ETDs */
for (i = 0; i < NUM_ISO_ETDS; i++) {
ep_priv->etd[i] = alloc_etd(imx21);
if (ep_priv->etd[i] < 0) {
int j;
dev_err(imx21->dev, "isoc: Couldn't allocate etd\n");
for (j = 0; j < i; j++)
free_etd(imx21, ep_priv->etd[j]);
goto alloc_etd_failed;
}
imx21->etd[ep_priv->etd[i]].ep = ep;
}
for (i = 0; i < NUM_ISO_ETDS; i++)
ep_priv->etd[i] = -1;
INIT_LIST_HEAD(&ep_priv->td_list);
ep_priv->ep = ep;
ep->hcpriv = ep_priv;
return ep_priv;
}
static int alloc_isoc_etds(struct imx21 *imx21, struct ep_priv *ep_priv)
{
int i, j;
int etd_num;
/* Allocate the ETDs if required */
for (i = 0; i < NUM_ISO_ETDS; i++) {
if (ep_priv->etd[i] < 0) {
etd_num = alloc_etd(imx21);
if (etd_num < 0)
goto alloc_etd_failed;
ep_priv->etd[i] = etd_num;
imx21->etd[etd_num].ep = ep_priv->ep;
}
}
return 0;
alloc_etd_failed:
kfree(ep_priv);
return NULL;
dev_err(imx21->dev, "isoc: Couldn't allocate etd\n");
for (j = 0; j < i; j++) {
free_etd(imx21, ep_priv->etd[j]);
ep_priv->etd[j] = -1;
}
return -ENOMEM;
}
static int imx21_hc_urb_enqueue_isoc(struct usb_hcd *hcd,
@ -632,6 +768,10 @@ static int imx21_hc_urb_enqueue_isoc(struct usb_hcd *hcd,
ep_priv = ep->hcpriv;
}
ret = alloc_isoc_etds(imx21, ep_priv);
if (ret)
goto alloc_etd_failed;
ret = usb_hcd_link_urb_to_ep(hcd, urb);
if (ret)
goto link_failed;
@ -688,12 +828,14 @@ static int imx21_hc_urb_enqueue_isoc(struct usb_hcd *hcd,
/* set up transfers */
td = urb_priv->isoc_td;
for (i = 0; i < urb->number_of_packets; i++, td++) {
unsigned int offset = urb->iso_frame_desc[i].offset;
td->ep = ep;
td->urb = urb;
td->len = urb->iso_frame_desc[i].length;
td->isoc_index = i;
td->frame = wrap_frame(urb->start_frame + urb->interval * i);
td->data = urb->transfer_dma + urb->iso_frame_desc[i].offset;
td->dma_handle = urb->transfer_dma + offset;
td->cpu_buffer = urb->transfer_buffer + offset;
list_add_tail(&td->list, &ep_priv->td_list);
}
@ -711,6 +853,7 @@ static int imx21_hc_urb_enqueue_isoc(struct usb_hcd *hcd,
usb_hcd_unlink_urb_from_ep(hcd, urb);
link_failed:
alloc_etd_failed:
alloc_ep_failed:
spin_unlock_irqrestore(&imx21->lock, flags);
kfree(urb_priv->isoc_td);
@ -734,9 +877,7 @@ static void dequeue_isoc_urb(struct imx21 *imx21,
struct etd_priv *etd = imx21->etd + etd_num;
reset_etd(imx21, etd_num);
if (etd->dmem_size)
free_dmem(imx21, etd->dmem_offset);
etd->dmem_size = 0;
free_dmem(imx21, etd);
}
}
}
@ -761,7 +902,6 @@ static void schedule_nonisoc_etd(struct imx21 *imx21, struct urb *urb)
int state = urb_priv->state;
int etd_num = ep_priv->etd[0];
struct etd_priv *etd;
int dmem_offset;
u32 count;
u16 etd_buf_size;
u16 maxpacket;
@ -786,13 +926,15 @@ static void schedule_nonisoc_etd(struct imx21 *imx21, struct urb *urb)
if (usb_pipecontrol(pipe) && (state != US_CTRL_DATA)) {
if (state == US_CTRL_SETUP) {
dir = TD_DIR_SETUP;
if (unsuitable_for_dma(urb->setup_dma))
unmap_urb_setup_for_dma(imx21->hcd, urb);
etd->dma_handle = urb->setup_dma;
etd->cpu_buffer = urb->setup_packet;
bufround = 0;
count = 8;
datatoggle = TD_TOGGLE_DATA0;
} else { /* US_CTRL_ACK */
dir = usb_pipeout(pipe) ? TD_DIR_IN : TD_DIR_OUT;
etd->dma_handle = urb->transfer_dma;
bufround = 0;
count = 0;
datatoggle = TD_TOGGLE_DATA1;
@ -800,7 +942,11 @@ static void schedule_nonisoc_etd(struct imx21 *imx21, struct urb *urb)
} else {
dir = usb_pipeout(pipe) ? TD_DIR_OUT : TD_DIR_IN;
bufround = (dir == TD_DIR_IN) ? 1 : 0;
if (unsuitable_for_dma(urb->transfer_dma))
unmap_urb_for_dma(imx21->hcd, urb);
etd->dma_handle = urb->transfer_dma;
etd->cpu_buffer = urb->transfer_buffer;
if (usb_pipebulk(pipe) && (state == US_BULK0))
count = 0;
else
@ -855,8 +1001,8 @@ static void schedule_nonisoc_etd(struct imx21 *imx21, struct urb *urb)
/* allocate x and y buffer space at once */
etd->dmem_size = (count > maxpacket) ? maxpacket * 2 : maxpacket;
dmem_offset = alloc_dmem(imx21, etd->dmem_size, urb_priv->ep);
if (dmem_offset < 0) {
etd->dmem_offset = alloc_dmem(imx21, etd->dmem_size, urb_priv->ep);
if (etd->dmem_offset < 0) {
/* Setup everything we can in HW and update when we get DMEM */
etd_writel(imx21, etd_num, 1, (u32)maxpacket << 16);
@ -867,26 +1013,26 @@ static void schedule_nonisoc_etd(struct imx21 *imx21, struct urb *urb)
}
etd_writel(imx21, etd_num, 1,
(((u32) dmem_offset + (u32) maxpacket) << DW1_YBUFSRTAD) |
(u32) dmem_offset);
(((u32) etd->dmem_offset + (u32) maxpacket) << DW1_YBUFSRTAD) |
(u32) etd->dmem_offset);
urb_priv->active = 1;
/* enable the ETD to kick off transfer */
dev_vdbg(imx21->dev, "Activating etd %d for %d bytes %s\n",
etd_num, count, dir != TD_DIR_IN ? "out" : "in");
activate_etd(imx21, etd_num, etd->dma_handle, dir);
activate_etd(imx21, etd_num, dir);
}
static void nonisoc_etd_done(struct usb_hcd *hcd, struct urb *urb, int etd_num)
static void nonisoc_etd_done(struct usb_hcd *hcd, int etd_num)
{
struct imx21 *imx21 = hcd_to_imx21(hcd);
struct etd_priv *etd = &imx21->etd[etd_num];
struct urb *urb = etd->urb;
u32 etd_mask = 1 << etd_num;
struct urb_priv *urb_priv = urb->hcpriv;
int dir;
u16 xbufaddr;
int cc;
u32 bytes_xfrd;
int etd_done;
@ -894,7 +1040,6 @@ static void nonisoc_etd_done(struct usb_hcd *hcd, struct urb *urb, int etd_num)
disactivate_etd(imx21, etd_num);
dir = (etd_readl(imx21, etd_num, 0) >> DW0_DIRECT) & 0x3;
xbufaddr = etd_readl(imx21, etd_num, 1) & 0xffff;
cc = (etd_readl(imx21, etd_num, 2) >> DW2_COMPCODE) & 0xf;
bytes_xfrd = etd->len - (etd_readl(imx21, etd_num, 3) & 0x1fffff);
@ -906,8 +1051,21 @@ static void nonisoc_etd_done(struct usb_hcd *hcd, struct urb *urb, int etd_num)
if (dir == TD_DIR_IN) {
clear_toggle_bit(imx21, USBH_XFILLSTAT, etd_mask);
clear_toggle_bit(imx21, USBH_YFILLSTAT, etd_mask);
if (etd->bounce_buffer) {
memcpy(etd->cpu_buffer, etd->bounce_buffer, bytes_xfrd);
dma_unmap_single(imx21->dev,
etd->dma_handle, etd->len, DMA_FROM_DEVICE);
} else if (!etd->dma_handle && bytes_xfrd) {/* PIO */
memcpy_fromio(etd->cpu_buffer,
imx21->regs + USBOTG_DMEM + etd->dmem_offset,
bytes_xfrd);
}
}
free_dmem(imx21, xbufaddr);
kfree(etd->bounce_buffer);
etd->bounce_buffer = NULL;
free_dmem(imx21, etd);
urb->error_count = 0;
if (!(urb->transfer_flags & URB_SHORT_NOT_OK)
@ -964,24 +1122,15 @@ static void nonisoc_etd_done(struct usb_hcd *hcd, struct urb *urb, int etd_num)
break;
}
if (!etd_done) {
if (etd_done)
nonisoc_urb_completed_for_etd(imx21, etd, cc_to_error[cc]);
else {
dev_vdbg(imx21->dev, "next state=%d\n", urb_priv->state);
schedule_nonisoc_etd(imx21, urb);
} else {
struct usb_host_endpoint *ep = urb->ep;
urb_done(hcd, urb, cc_to_error[cc]);
etd->urb = NULL;
if (!list_empty(&ep->urb_list)) {
urb = list_first_entry(&ep->urb_list,
struct urb, urb_list);
dev_vdbg(imx21->dev, "next URB %p\n", urb);
schedule_nonisoc_etd(imx21, urb);
}
}
}
static struct ep_priv *alloc_ep(void)
{
int i;
@ -1007,7 +1156,6 @@ static int imx21_hc_urb_enqueue(struct usb_hcd *hcd,
struct etd_priv *etd;
int ret;
unsigned long flags;
int new_ep = 0;
dev_vdbg(imx21->dev,
"enqueue urb=%p ep=%p len=%d "
@ -1035,7 +1183,6 @@ static int imx21_hc_urb_enqueue(struct usb_hcd *hcd,
}
ep->hcpriv = ep_priv;
ep_priv->ep = ep;
new_ep = 1;
}
ret = usb_hcd_link_urb_to_ep(hcd, urb);
@ -1124,9 +1271,13 @@ static int imx21_hc_urb_dequeue(struct usb_hcd *hcd, struct urb *urb,
} else if (urb_priv->active) {
int etd_num = ep_priv->etd[0];
if (etd_num != -1) {
struct etd_priv *etd = &imx21->etd[etd_num];
disactivate_etd(imx21, etd_num);
free_dmem(imx21, etd_readl(imx21, etd_num, 1) & 0xffff);
imx21->etd[etd_num].urb = NULL;
free_dmem(imx21, etd);
etd->urb = NULL;
kfree(etd->bounce_buffer);
etd->bounce_buffer = NULL;
}
}
@ -1226,9 +1377,9 @@ static void process_etds(struct usb_hcd *hcd, struct imx21 *imx21, int sof)
}
if (usb_pipeisoc(etd->urb->pipe))
isoc_etd_done(hcd, etd->urb, etd_num);
isoc_etd_done(hcd, etd_num);
else
nonisoc_etd_done(hcd, etd->urb, etd_num);
nonisoc_etd_done(hcd, etd_num);
}
/* only enable SOF interrupt if it may be needed for the kludge */
@ -1696,6 +1847,7 @@ static int imx21_probe(struct platform_device *pdev)
}
imx21 = hcd_to_imx21(hcd);
imx21->hcd = hcd;
imx21->dev = &pdev->dev;
imx21->pdata = pdev->dev.platform_data;
if (!imx21->pdata)
@ -1754,7 +1906,7 @@ static int imx21_probe(struct platform_device *pdev)
failed_clock_get:
iounmap(imx21->regs);
failed_ioremap:
release_mem_region(res->start, res->end - res->start);
release_mem_region(res->start, resource_size(res));
failed_request_mem:
remove_debug_files(imx21);
usb_put_hcd(hcd);

View File

@ -250,6 +250,7 @@
#define USBCTRL_USB_BYP (1 << 2)
#define USBCTRL_HOST1_TXEN_OE (1 << 1)
#define USBOTG_DMEM 0x1000
/* Values in TD blocks */
#define TD_DIR_SETUP 0
@ -346,8 +347,8 @@ struct td {
struct list_head list;
struct urb *urb;
struct usb_host_endpoint *ep;
dma_addr_t data;
unsigned long buf_addr;
dma_addr_t dma_handle;
void *cpu_buffer;
int len;
int frame;
int isoc_index;
@ -360,6 +361,8 @@ struct etd_priv {
struct td *td;
struct list_head queue;
dma_addr_t dma_handle;
void *cpu_buffer;
void *bounce_buffer;
int alloc;
int len;
int dmem_size;
@ -412,6 +415,7 @@ struct debug_isoc_trace {
struct imx21 {
spinlock_t lock;
struct device *dev;
struct usb_hcd *hcd;
struct mx21_usbh_platform_data *pdata;
struct list_head dmem_list;
struct list_head queue_for_etd; /* eps queued due to etd shortage */

View File

@ -1557,8 +1557,6 @@ static int isp116x_remove(struct platform_device *pdev)
return 0;
}
#define resource_len(r) (((r)->end - (r)->start) + 1)
static int __devinit isp116x_probe(struct platform_device *pdev)
{
struct usb_hcd *hcd;
@ -1597,7 +1595,7 @@ static int __devinit isp116x_probe(struct platform_device *pdev)
ret = -EBUSY;
goto err1;
}
addr_reg = ioremap(addr->start, resource_len(addr));
addr_reg = ioremap(addr->start, resource_size(addr));
if (addr_reg == NULL) {
ret = -ENOMEM;
goto err2;
@ -1606,7 +1604,7 @@ static int __devinit isp116x_probe(struct platform_device *pdev)
ret = -EBUSY;
goto err3;
}
data_reg = ioremap(data->start, resource_len(data));
data_reg = ioremap(data->start, resource_size(data));
if (data_reg == NULL) {
ret = -ENOMEM;
goto err4;

View File

@ -1676,13 +1676,6 @@ static int isp1362_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
switch (wValue) {
case USB_PORT_FEAT_SUSPEND:
_DBG(0, "USB_PORT_FEAT_SUSPEND\n");
#ifdef CONFIG_USB_OTG
if (ohci->hcd.self.otg_port == (wIndex + 1) &&
ohci->hcd.self.b_hnp_enable) {
start_hnp(ohci);
break;
}
#endif
spin_lock_irqsave(&isp1362_hcd->lock, flags);
isp1362_write_reg32(isp1362_hcd, HCRHPORT1 + wIndex, RH_PS_PSS);
isp1362_hcd->rhport[wIndex] =
@ -2656,8 +2649,6 @@ static struct hc_driver isp1362_hc_driver = {
/*-------------------------------------------------------------------------*/
#define resource_len(r) (((r)->end - (r)->start) + 1)
static int __devexit isp1362_remove(struct platform_device *pdev)
{
struct usb_hcd *hcd = platform_get_drvdata(pdev);
@ -2679,12 +2670,12 @@ static int __devexit isp1362_remove(struct platform_device *pdev)
res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
DBG(0, "%s: release mem_region: %08lx\n", __func__, (long unsigned int)res->start);
if (res)
release_mem_region(res->start, resource_len(res));
release_mem_region(res->start, resource_size(res));
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
DBG(0, "%s: release mem_region: %08lx\n", __func__, (long unsigned int)res->start);
if (res)
release_mem_region(res->start, resource_len(res));
release_mem_region(res->start, resource_size(res));
DBG(0, "%s: put_hcd\n", __func__);
usb_put_hcd(hcd);
@ -2730,21 +2721,21 @@ static int __init isp1362_probe(struct platform_device *pdev)
goto err1;
}
if (!request_mem_region(addr->start, resource_len(addr), hcd_name)) {
if (!request_mem_region(addr->start, resource_size(addr), hcd_name)) {
retval = -EBUSY;
goto err1;
}
addr_reg = ioremap(addr->start, resource_len(addr));
addr_reg = ioremap(addr->start, resource_size(addr));
if (addr_reg == NULL) {
retval = -ENOMEM;
goto err2;
}
if (!request_mem_region(data->start, resource_len(data), hcd_name)) {
if (!request_mem_region(data->start, resource_size(data), hcd_name)) {
retval = -EBUSY;
goto err3;
}
data_reg = ioremap(data->start, resource_len(data));
data_reg = ioremap(data->start, resource_size(data));
if (data_reg == NULL) {
retval = -ENOMEM;
goto err4;
@ -2802,13 +2793,13 @@ static int __init isp1362_probe(struct platform_device *pdev)
iounmap(data_reg);
err4:
DBG(0, "%s: Releasing mem region %08lx\n", __func__, (long unsigned int)data->start);
release_mem_region(data->start, resource_len(data));
release_mem_region(data->start, resource_size(data));
err3:
DBG(0, "%s: Unmapping addr_reg @ %p\n", __func__, addr_reg);
iounmap(addr_reg);
err2:
DBG(0, "%s: Releasing mem region %08lx\n", __func__, (long unsigned int)addr->start);
release_mem_region(addr->start, resource_len(addr));
release_mem_region(addr->start, resource_size(addr));
err1:
pr_err("%s: init error, %d\n", __func__, retval);

View File

@ -398,7 +398,14 @@ ohci_shutdown (struct usb_hcd *hcd)
ohci = hcd_to_ohci (hcd);
ohci_writel (ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable);
ohci_usb_reset (ohci);
ohci->hc_control = ohci_readl(ohci, &ohci->regs->control);
/* If the SHUTDOWN quirk is set, don't put the controller in RESET */
ohci->hc_control &= (ohci->flags & OHCI_QUIRK_SHUTDOWN ?
OHCI_CTRL_RWC | OHCI_CTRL_HCFS :
OHCI_CTRL_RWC);
ohci_writel(ohci, ohci->hc_control, &ohci->regs->control);
/* flush the writes */
(void) ohci_readl (ohci, &ohci->regs->control);
}
@ -1270,6 +1277,9 @@ static void __exit ohci_hcd_mod_exit(void)
#ifdef PLATFORM_DRIVER
platform_driver_unregister(&PLATFORM_DRIVER);
#endif
#ifdef OMAP3_PLATFORM_DRIVER
platform_driver_unregister(&OMAP3_PLATFORM_DRIVER);
#endif
#ifdef PS3_SYSTEM_BUS_DRIVER
ps3_ohci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);
#endif

View File

@ -201,6 +201,20 @@ static int ohci_quirk_amd700(struct usb_hcd *hcd)
return 0;
}
/* nVidia controllers continue to drive Reset signalling on the bus
* even after system shutdown, wasting power. This flag tells the
* shutdown routine to leave the controller OPERATIONAL instead of RESET.
*/
static int ohci_quirk_nvidia_shutdown(struct usb_hcd *hcd)
{
struct ohci_hcd *ohci = hcd_to_ohci(hcd);
ohci->flags |= OHCI_QUIRK_SHUTDOWN;
ohci_dbg(ohci, "enabled nVidia shutdown quirk\n");
return 0;
}
/*
* The hardware normally enables the A-link power management feature, which
* lets the system lower the power consumption in idle states.
@ -332,6 +346,10 @@ static const struct pci_device_id ohci_pci_quirks[] = {
PCI_DEVICE(PCI_VENDOR_ID_ATI, 0x4399),
.driver_data = (unsigned long)ohci_quirk_amd700,
},
{
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID),
.driver_data = (unsigned long) ohci_quirk_nvidia_shutdown,
},
/* FIXME for some of the early AMD 760 southbridges, OHCI
* won't work at all. blacklist them.

View File

@ -77,7 +77,6 @@ static const struct hc_driver ohci_sh_hc_driver = {
/*-------------------------------------------------------------------------*/
#define resource_len(r) (((r)->end - (r)->start) + 1)
static int ohci_hcd_sh_probe(struct platform_device *pdev)
{
struct resource *res = NULL;
@ -109,7 +108,7 @@ static int ohci_hcd_sh_probe(struct platform_device *pdev)
hcd->regs = (void __iomem *)res->start;
hcd->rsrc_start = res->start;
hcd->rsrc_len = resource_len(res);
hcd->rsrc_len = resource_size(res);
ret = usb_add_hcd(hcd, irq, IRQF_DISABLED);
if (ret != 0) {
err("Failed to add hcd");

View File

@ -168,7 +168,7 @@ static int ohci_hcd_sm501_drv_probe(struct platform_device *pdev)
retval = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED);
if (retval)
goto err4;
goto err5;
/* enable power and unmask interrupts */
@ -176,6 +176,8 @@ static int ohci_hcd_sm501_drv_probe(struct platform_device *pdev)
sm501_modify_reg(dev->parent, SM501_IRQ_MASK, 1 << 6, 0);
return 0;
err5:
iounmap(hcd->regs);
err4:
release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
err3:

View File

@ -403,6 +403,7 @@ struct ohci_hcd {
#define OHCI_QUIRK_HUB_POWER 0x100 /* distrust firmware power/oc setup */
#define OHCI_QUIRK_AMD_ISO 0x200 /* ISO transfers*/
#define OHCI_QUIRK_AMD_PREFETCH 0x400 /* pre-fetch for ISO transfer */
#define OHCI_QUIRK_SHUTDOWN 0x800 /* nVidia power bug */
// there are also chip quirks/bugs in init logic
struct work_struct nec_work; /* Worker for NEC quirk */

View File

@ -3696,7 +3696,7 @@ static void oxu_configuration(struct platform_device *pdev, void *base)
static int oxu_verify_id(struct platform_device *pdev, void *base)
{
u32 id;
char *bo[] = {
static const char * const bo[] = {
"reserved",
"128-pin LQFP",
"84-pin TFBGA",

View File

@ -169,6 +169,7 @@ static int __devinit mmio_resource_enabled(struct pci_dev *pdev, int idx)
static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev)
{
void __iomem *base;
u32 control;
if (!mmio_resource_enabled(pdev, 0))
return;
@ -177,10 +178,14 @@ static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev)
if (base == NULL)
return;
control = readl(base + OHCI_CONTROL);
/* On PA-RISC, PDC can leave IR set incorrectly; ignore it there. */
#ifndef __hppa__
{
u32 control = readl(base + OHCI_CONTROL);
#ifdef __hppa__
#define OHCI_CTRL_MASK (OHCI_CTRL_RWC | OHCI_CTRL_IR)
#else
#define OHCI_CTRL_MASK OHCI_CTRL_RWC
if (control & OHCI_CTRL_IR) {
int wait_time = 500; /* arbitrary; 5 seconds */
writel(OHCI_INTR_OC, base + OHCI_INTRENABLE);
@ -194,13 +199,12 @@ static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev)
dev_warn(&pdev->dev, "OHCI: BIOS handoff failed"
" (BIOS bug?) %08x\n",
readl(base + OHCI_CONTROL));
/* reset controller, preserving RWC */
writel(control & OHCI_CTRL_RWC, base + OHCI_CONTROL);
}
}
#endif
/* reset controller, preserving RWC (and possibly IR) */
writel(control & OHCI_CTRL_MASK, base + OHCI_CONTROL);
/*
* disable interrupts
*/

View File

@ -227,7 +227,7 @@ static inline void r8a66597_write_fifo(struct r8a66597 *r8a66597,
int odd = len & 0x0001;
len = len / 2;
ioread16_rep(fifoaddr, buf, len);
iowrite16_rep(fifoaddr, buf, len);
if (unlikely(odd)) {
buf = &buf[len];
iowrite8((unsigned char)*buf, fifoaddr);

View File

@ -917,10 +917,13 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb,
unsigned long destination, status;
int maxsze = le16_to_cpu(qh->hep->desc.wMaxPacketSize);
int len = urb->transfer_buffer_length;
dma_addr_t data = urb->transfer_dma;
int this_sg_len;
dma_addr_t data;
__le32 *plink;
struct urb_priv *urbp = urb->hcpriv;
unsigned int toggle;
struct scatterlist *sg;
int i;
if (len < 0)
return -EINVAL;
@ -937,12 +940,26 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb,
if (usb_pipein(urb->pipe))
status |= TD_CTRL_SPD;
i = urb->num_sgs;
if (len > 0 && i > 0) {
sg = urb->sg;
data = sg_dma_address(sg);
/* urb->transfer_buffer_length may be smaller than the
* size of the scatterlist (or vice versa)
*/
this_sg_len = min_t(int, sg_dma_len(sg), len);
} else {
sg = NULL;
data = urb->transfer_dma;
this_sg_len = len;
}
/*
* Build the DATA TDs
*/
plink = NULL;
td = qh->dummy_td;
do { /* Allow zero length packets */
for (;;) { /* Allow zero length packets */
int pktsze = maxsze;
if (len <= pktsze) { /* The last packet */
@ -965,10 +982,18 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb,
plink = &td->link;
status |= TD_CTRL_ACTIVE;
data += pktsze;
len -= maxsze;
toggle ^= 1;
} while (len > 0);
data += pktsze;
this_sg_len -= pktsze;
len -= maxsze;
if (this_sg_len <= 0) {
if (--i <= 0 || len <= 0)
break;
sg = sg_next(sg);
data = sg_dma_address(sg);
this_sg_len = min_t(int, sg_dma_len(sg), len);
}
}
/*
* URB_ZERO_PACKET means adding a 0-length packet, if direction

View File

@ -3,7 +3,7 @@ obj-$(CONFIG_USB_WHCI_HCD) += whci-hcd.o
whci-hcd-y := \
asl.o \
debug.o \
hcd.o \
hcd.o \
hw.o \
init.o \
int.o \

View File

@ -24,6 +24,10 @@
#include "xhci.h"
#define PORT_WAKE_BITS (PORT_WKOC_E | PORT_WKDISC_E | PORT_WKCONN_E)
#define PORT_RWC_BITS (PORT_CSC | PORT_PEC | PORT_WRC | PORT_OCC | \
PORT_RC | PORT_PLC | PORT_PE)
static void xhci_hub_descriptor(struct xhci_hcd *xhci,
struct usb_hub_descriptor *desc)
{
@ -123,12 +127,105 @@ static unsigned int xhci_port_speed(unsigned int port_status)
* writing a 0 clears the bit and writing a 1 sets the bit (RWS).
* For all other types (RW1S, RW1CS, RW, and RZ), writing a '0' has no effect.
*/
static u32 xhci_port_state_to_neutral(u32 state)
u32 xhci_port_state_to_neutral(u32 state)
{
/* Save read-only status and port state */
return (state & XHCI_PORT_RO) | (state & XHCI_PORT_RWS);
}
/*
* find slot id based on port number.
*/
int xhci_find_slot_id_by_port(struct xhci_hcd *xhci, u16 port)
{
int slot_id;
int i;
slot_id = 0;
for (i = 0; i < MAX_HC_SLOTS; i++) {
if (!xhci->devs[i])
continue;
if (xhci->devs[i]->port == port) {
slot_id = i;
break;
}
}
return slot_id;
}
/*
* Stop device
* It issues stop endpoint command for EP 0 to 30. And wait the last command
* to complete.
* suspend will set to 1, if suspend bit need to set in command.
*/
static int xhci_stop_device(struct xhci_hcd *xhci, int slot_id, int suspend)
{
struct xhci_virt_device *virt_dev;
struct xhci_command *cmd;
unsigned long flags;
int timeleft;
int ret;
int i;
ret = 0;
virt_dev = xhci->devs[slot_id];
cmd = xhci_alloc_command(xhci, false, true, GFP_NOIO);
if (!cmd) {
xhci_dbg(xhci, "Couldn't allocate command structure.\n");
return -ENOMEM;
}
spin_lock_irqsave(&xhci->lock, flags);
for (i = LAST_EP_INDEX; i > 0; i--) {
if (virt_dev->eps[i].ring && virt_dev->eps[i].ring->dequeue)
xhci_queue_stop_endpoint(xhci, slot_id, i, suspend);
}
cmd->command_trb = xhci->cmd_ring->enqueue;
list_add_tail(&cmd->cmd_list, &virt_dev->cmd_list);
xhci_queue_stop_endpoint(xhci, slot_id, 0, suspend);
xhci_ring_cmd_db(xhci);
spin_unlock_irqrestore(&xhci->lock, flags);
/* Wait for last stop endpoint command to finish */
timeleft = wait_for_completion_interruptible_timeout(
cmd->completion,
USB_CTRL_SET_TIMEOUT);
if (timeleft <= 0) {
xhci_warn(xhci, "%s while waiting for stop endpoint command\n",
timeleft == 0 ? "Timeout" : "Signal");
spin_lock_irqsave(&xhci->lock, flags);
/* The timeout might have raced with the event ring handler, so
* only delete from the list if the item isn't poisoned.
*/
if (cmd->cmd_list.next != LIST_POISON1)
list_del(&cmd->cmd_list);
spin_unlock_irqrestore(&xhci->lock, flags);
ret = -ETIME;
goto command_cleanup;
}
command_cleanup:
xhci_free_command(xhci, cmd);
return ret;
}
/*
* Ring device, it rings the all doorbells unconditionally.
*/
void xhci_ring_device(struct xhci_hcd *xhci, int slot_id)
{
int i;
for (i = 0; i < LAST_EP_INDEX + 1; i++)
if (xhci->devs[slot_id]->eps[i].ring &&
xhci->devs[slot_id]->eps[i].ring->dequeue)
xhci_ring_ep_doorbell(xhci, slot_id, i, 0);
return;
}
static void xhci_disable_port(struct xhci_hcd *xhci, u16 wIndex,
u32 __iomem *addr, u32 port_status)
{
@ -162,6 +259,10 @@ static void xhci_clear_port_change_bit(struct xhci_hcd *xhci, u16 wValue,
status = PORT_PEC;
port_change_bit = "enable/disable";
break;
case USB_PORT_FEAT_C_SUSPEND:
status = PORT_PLC;
port_change_bit = "suspend/resume";
break;
default:
/* Should never happen */
return;
@ -179,9 +280,10 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
int ports;
unsigned long flags;
u32 temp, status;
u32 temp, temp1, status;
int retval = 0;
u32 __iomem *addr;
int slot_id;
ports = HCS_MAX_PORTS(xhci->hcs_params1);
@ -211,9 +313,49 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
if ((temp & PORT_OCC))
status |= USB_PORT_STAT_C_OVERCURRENT << 16;
/*
* FIXME ignoring suspend, reset, and USB 2.1/3.0 specific
* FIXME ignoring reset and USB 2.1/3.0 specific
* changes
*/
if ((temp & PORT_PLS_MASK) == XDEV_U3
&& (temp & PORT_POWER))
status |= 1 << USB_PORT_FEAT_SUSPEND;
if ((temp & PORT_PLS_MASK) == XDEV_RESUME) {
if ((temp & PORT_RESET) || !(temp & PORT_PE))
goto error;
if (!DEV_SUPERSPEED(temp) && time_after_eq(jiffies,
xhci->resume_done[wIndex])) {
xhci_dbg(xhci, "Resume USB2 port %d\n",
wIndex + 1);
xhci->resume_done[wIndex] = 0;
temp1 = xhci_port_state_to_neutral(temp);
temp1 &= ~PORT_PLS_MASK;
temp1 |= PORT_LINK_STROBE | XDEV_U0;
xhci_writel(xhci, temp1, addr);
xhci_dbg(xhci, "set port %d resume\n",
wIndex + 1);
slot_id = xhci_find_slot_id_by_port(xhci,
wIndex + 1);
if (!slot_id) {
xhci_dbg(xhci, "slot_id is zero\n");
goto error;
}
xhci_ring_device(xhci, slot_id);
xhci->port_c_suspend[wIndex >> 5] |=
1 << (wIndex & 31);
xhci->suspended_ports[wIndex >> 5] &=
~(1 << (wIndex & 31));
}
}
if ((temp & PORT_PLS_MASK) == XDEV_U0
&& (temp & PORT_POWER)
&& (xhci->suspended_ports[wIndex >> 5] &
(1 << (wIndex & 31)))) {
xhci->suspended_ports[wIndex >> 5] &=
~(1 << (wIndex & 31));
xhci->port_c_suspend[wIndex >> 5] |=
1 << (wIndex & 31);
}
if (temp & PORT_CONNECT) {
status |= USB_PORT_STAT_CONNECTION;
status |= xhci_port_speed(temp);
@ -226,6 +368,8 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
status |= USB_PORT_STAT_RESET;
if (temp & PORT_POWER)
status |= USB_PORT_STAT_POWER;
if (xhci->port_c_suspend[wIndex >> 5] & (1 << (wIndex & 31)))
status |= 1 << USB_PORT_FEAT_C_SUSPEND;
xhci_dbg(xhci, "Get port status returned 0x%x\n", status);
put_unaligned(cpu_to_le32(status), (__le32 *) buf);
break;
@ -238,6 +382,42 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
temp = xhci_readl(xhci, addr);
temp = xhci_port_state_to_neutral(temp);
switch (wValue) {
case USB_PORT_FEAT_SUSPEND:
temp = xhci_readl(xhci, addr);
/* In spec software should not attempt to suspend
* a port unless the port reports that it is in the
* enabled (PED = 1,PLS < 3) state.
*/
if ((temp & PORT_PE) == 0 || (temp & PORT_RESET)
|| (temp & PORT_PLS_MASK) >= XDEV_U3) {
xhci_warn(xhci, "USB core suspending device "
"not in U0/U1/U2.\n");
goto error;
}
slot_id = xhci_find_slot_id_by_port(xhci, wIndex + 1);
if (!slot_id) {
xhci_warn(xhci, "slot_id is zero\n");
goto error;
}
/* unlock to execute stop endpoint commands */
spin_unlock_irqrestore(&xhci->lock, flags);
xhci_stop_device(xhci, slot_id, 1);
spin_lock_irqsave(&xhci->lock, flags);
temp = xhci_port_state_to_neutral(temp);
temp &= ~PORT_PLS_MASK;
temp |= PORT_LINK_STROBE | XDEV_U3;
xhci_writel(xhci, temp, addr);
spin_unlock_irqrestore(&xhci->lock, flags);
msleep(10); /* wait device to enter */
spin_lock_irqsave(&xhci->lock, flags);
temp = xhci_readl(xhci, addr);
xhci->suspended_ports[wIndex >> 5] |=
1 << (wIndex & (31));
break;
case USB_PORT_FEAT_POWER:
/*
* Turn on ports, even if there isn't per-port switching.
@ -271,6 +451,52 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
temp = xhci_readl(xhci, addr);
temp = xhci_port_state_to_neutral(temp);
switch (wValue) {
case USB_PORT_FEAT_SUSPEND:
temp = xhci_readl(xhci, addr);
xhci_dbg(xhci, "clear USB_PORT_FEAT_SUSPEND\n");
xhci_dbg(xhci, "PORTSC %04x\n", temp);
if (temp & PORT_RESET)
goto error;
if (temp & XDEV_U3) {
if ((temp & PORT_PE) == 0)
goto error;
if (DEV_SUPERSPEED(temp)) {
temp = xhci_port_state_to_neutral(temp);
temp &= ~PORT_PLS_MASK;
temp |= PORT_LINK_STROBE | XDEV_U0;
xhci_writel(xhci, temp, addr);
xhci_readl(xhci, addr);
} else {
temp = xhci_port_state_to_neutral(temp);
temp &= ~PORT_PLS_MASK;
temp |= PORT_LINK_STROBE | XDEV_RESUME;
xhci_writel(xhci, temp, addr);
spin_unlock_irqrestore(&xhci->lock,
flags);
msleep(20);
spin_lock_irqsave(&xhci->lock, flags);
temp = xhci_readl(xhci, addr);
temp = xhci_port_state_to_neutral(temp);
temp &= ~PORT_PLS_MASK;
temp |= PORT_LINK_STROBE | XDEV_U0;
xhci_writel(xhci, temp, addr);
}
xhci->port_c_suspend[wIndex >> 5] |=
1 << (wIndex & 31);
}
slot_id = xhci_find_slot_id_by_port(xhci, wIndex + 1);
if (!slot_id) {
xhci_dbg(xhci, "slot_id is zero\n");
goto error;
}
xhci_ring_device(xhci, slot_id);
break;
case USB_PORT_FEAT_C_SUSPEND:
xhci->port_c_suspend[wIndex >> 5] &=
~(1 << (wIndex & 31));
case USB_PORT_FEAT_C_RESET:
case USB_PORT_FEAT_C_CONNECTION:
case USB_PORT_FEAT_C_OVER_CURRENT:
@ -306,6 +532,7 @@ int xhci_hub_status_data(struct usb_hcd *hcd, char *buf)
{
unsigned long flags;
u32 temp, status;
u32 mask;
int i, retval;
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
int ports;
@ -318,13 +545,18 @@ int xhci_hub_status_data(struct usb_hcd *hcd, char *buf)
memset(buf, 0, retval);
status = 0;
mask = PORT_CSC | PORT_PEC | PORT_OCC;
spin_lock_irqsave(&xhci->lock, flags);
/* For each port, did anything change? If so, set that bit in buf. */
for (i = 0; i < ports; i++) {
addr = &xhci->op_regs->port_status_base +
NUM_PORT_REGS*i;
temp = xhci_readl(xhci, addr);
if (temp & (PORT_CSC | PORT_PEC | PORT_OCC)) {
if ((temp & mask) != 0 ||
(xhci->port_c_suspend[i >> 5] & 1 << (i & 31)) ||
(xhci->resume_done[i] && time_after_eq(
jiffies, xhci->resume_done[i]))) {
buf[(i + 1) / 8] |= 1 << (i + 1) % 8;
status = 1;
}
@ -332,3 +564,182 @@ int xhci_hub_status_data(struct usb_hcd *hcd, char *buf)
spin_unlock_irqrestore(&xhci->lock, flags);
return status ? retval : 0;
}
#ifdef CONFIG_PM
int xhci_bus_suspend(struct usb_hcd *hcd)
{
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
int port;
unsigned long flags;
xhci_dbg(xhci, "suspend root hub\n");
spin_lock_irqsave(&xhci->lock, flags);
if (hcd->self.root_hub->do_remote_wakeup) {
port = HCS_MAX_PORTS(xhci->hcs_params1);
while (port--) {
if (xhci->resume_done[port] != 0) {
spin_unlock_irqrestore(&xhci->lock, flags);
xhci_dbg(xhci, "suspend failed because "
"port %d is resuming\n",
port + 1);
return -EBUSY;
}
}
}
port = HCS_MAX_PORTS(xhci->hcs_params1);
xhci->bus_suspended = 0;
while (port--) {
/* suspend the port if the port is not suspended */
u32 __iomem *addr;
u32 t1, t2;
int slot_id;
addr = &xhci->op_regs->port_status_base +
NUM_PORT_REGS * (port & 0xff);
t1 = xhci_readl(xhci, addr);
t2 = xhci_port_state_to_neutral(t1);
if ((t1 & PORT_PE) && !(t1 & PORT_PLS_MASK)) {
xhci_dbg(xhci, "port %d not suspended\n", port);
slot_id = xhci_find_slot_id_by_port(xhci, port + 1);
if (slot_id) {
spin_unlock_irqrestore(&xhci->lock, flags);
xhci_stop_device(xhci, slot_id, 1);
spin_lock_irqsave(&xhci->lock, flags);
}
t2 &= ~PORT_PLS_MASK;
t2 |= PORT_LINK_STROBE | XDEV_U3;
set_bit(port, &xhci->bus_suspended);
}
if (hcd->self.root_hub->do_remote_wakeup) {
if (t1 & PORT_CONNECT) {
t2 |= PORT_WKOC_E | PORT_WKDISC_E;
t2 &= ~PORT_WKCONN_E;
} else {
t2 |= PORT_WKOC_E | PORT_WKCONN_E;
t2 &= ~PORT_WKDISC_E;
}
} else
t2 &= ~PORT_WAKE_BITS;
t1 = xhci_port_state_to_neutral(t1);
if (t1 != t2)
xhci_writel(xhci, t2, addr);
if (DEV_HIGHSPEED(t1)) {
/* enable remote wake up for USB 2.0 */
u32 __iomem *addr;
u32 tmp;
addr = &xhci->op_regs->port_power_base +
NUM_PORT_REGS * (port & 0xff);
tmp = xhci_readl(xhci, addr);
tmp |= PORT_RWE;
xhci_writel(xhci, tmp, addr);
}
}
hcd->state = HC_STATE_SUSPENDED;
xhci->next_statechange = jiffies + msecs_to_jiffies(10);
spin_unlock_irqrestore(&xhci->lock, flags);
return 0;
}
int xhci_bus_resume(struct usb_hcd *hcd)
{
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
int port;
u32 temp;
unsigned long flags;
xhci_dbg(xhci, "resume root hub\n");
if (time_before(jiffies, xhci->next_statechange))
msleep(5);
spin_lock_irqsave(&xhci->lock, flags);
if (!HCD_HW_ACCESSIBLE(hcd)) {
spin_unlock_irqrestore(&xhci->lock, flags);
return -ESHUTDOWN;
}
/* delay the irqs */
temp = xhci_readl(xhci, &xhci->op_regs->command);
temp &= ~CMD_EIE;
xhci_writel(xhci, temp, &xhci->op_regs->command);
port = HCS_MAX_PORTS(xhci->hcs_params1);
while (port--) {
/* Check whether need resume ports. If needed
resume port and disable remote wakeup */
u32 __iomem *addr;
u32 temp;
int slot_id;
addr = &xhci->op_regs->port_status_base +
NUM_PORT_REGS * (port & 0xff);
temp = xhci_readl(xhci, addr);
if (DEV_SUPERSPEED(temp))
temp &= ~(PORT_RWC_BITS | PORT_CEC | PORT_WAKE_BITS);
else
temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS);
if (test_bit(port, &xhci->bus_suspended) &&
(temp & PORT_PLS_MASK)) {
if (DEV_SUPERSPEED(temp)) {
temp = xhci_port_state_to_neutral(temp);
temp &= ~PORT_PLS_MASK;
temp |= PORT_LINK_STROBE | XDEV_U0;
xhci_writel(xhci, temp, addr);
} else {
temp = xhci_port_state_to_neutral(temp);
temp &= ~PORT_PLS_MASK;
temp |= PORT_LINK_STROBE | XDEV_RESUME;
xhci_writel(xhci, temp, addr);
spin_unlock_irqrestore(&xhci->lock, flags);
msleep(20);
spin_lock_irqsave(&xhci->lock, flags);
temp = xhci_readl(xhci, addr);
temp = xhci_port_state_to_neutral(temp);
temp &= ~PORT_PLS_MASK;
temp |= PORT_LINK_STROBE | XDEV_U0;
xhci_writel(xhci, temp, addr);
}
slot_id = xhci_find_slot_id_by_port(xhci, port + 1);
if (slot_id)
xhci_ring_device(xhci, slot_id);
} else
xhci_writel(xhci, temp, addr);
if (DEV_HIGHSPEED(temp)) {
/* disable remote wake up for USB 2.0 */
u32 __iomem *addr;
u32 tmp;
addr = &xhci->op_regs->port_power_base +
NUM_PORT_REGS * (port & 0xff);
tmp = xhci_readl(xhci, addr);
tmp &= ~PORT_RWE;
xhci_writel(xhci, tmp, addr);
}
}
(void) xhci_readl(xhci, &xhci->op_regs->command);
xhci->next_statechange = jiffies + msecs_to_jiffies(5);
hcd->state = HC_STATE_RUNNING;
/* re-enable irqs */
temp = xhci_readl(xhci, &xhci->op_regs->command);
temp |= CMD_EIE;
xhci_writel(xhci, temp, &xhci->op_regs->command);
temp = xhci_readl(xhci, &xhci->op_regs->command);
spin_unlock_irqrestore(&xhci->lock, flags);
return 0;
}
#endif /* CONFIG_PM */

View File

@ -778,6 +778,7 @@ int xhci_alloc_virt_device(struct xhci_hcd *xhci, int slot_id,
init_completion(&dev->cmd_completion);
INIT_LIST_HEAD(&dev->cmd_list);
dev->udev = udev;
/* Point to output device context in dcbaa. */
xhci->dcbaa->dev_context_ptrs[slot_id] = dev->out_ctx->dma;
@ -866,6 +867,7 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud
top_dev = top_dev->parent)
/* Found device below root hub */;
slot_ctx->dev_info2 |= (u32) ROOT_HUB_PORT(top_dev->portnum);
dev->port = top_dev->portnum;
xhci_dbg(xhci, "Set root hub portnum to %d\n", top_dev->portnum);
/* Is this a LS/FS device under a HS hub? */
@ -1443,6 +1445,7 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)
scratchpad_free(xhci);
xhci->page_size = 0;
xhci->page_shift = 0;
xhci->bus_suspended = 0;
}
static int xhci_test_trb_in_td(struct xhci_hcd *xhci,
@ -1801,6 +1804,8 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
init_completion(&xhci->addr_dev);
for (i = 0; i < MAX_HC_SLOTS; ++i)
xhci->devs[i] = NULL;
for (i = 0; i < MAX_HC_PORTS; ++i)
xhci->resume_done[i] = 0;
if (scratchpad_alloc(xhci, flags))
goto fail;

View File

@ -116,6 +116,30 @@ static int xhci_pci_setup(struct usb_hcd *hcd)
return xhci_pci_reinit(xhci, pdev);
}
#ifdef CONFIG_PM
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)
return -EINVAL;
retval = xhci_suspend(xhci);
return retval;
}
static int xhci_pci_resume(struct usb_hcd *hcd, bool hibernated)
{
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
int retval = 0;
retval = xhci_resume(xhci, hibernated);
return retval;
}
#endif /* CONFIG_PM */
static const struct hc_driver xhci_pci_hc_driver = {
.description = hcd_name,
.product_desc = "xHCI Host Controller",
@ -132,7 +156,10 @@ static const struct hc_driver xhci_pci_hc_driver = {
*/
.reset = xhci_pci_setup,
.start = xhci_run,
/* suspend and resume implemented later */
#ifdef CONFIG_PM
.pci_suspend = xhci_pci_suspend,
.pci_resume = xhci_pci_resume,
#endif
.stop = xhci_stop,
.shutdown = xhci_shutdown,
@ -152,7 +179,7 @@ static const struct hc_driver xhci_pci_hc_driver = {
.reset_bandwidth = xhci_reset_bandwidth,
.address_device = xhci_address_device,
.update_hub_device = xhci_update_hub_device,
.reset_device = xhci_reset_device,
.reset_device = xhci_discover_or_reset_device,
/*
* scheduling support
@ -162,6 +189,8 @@ static const struct hc_driver xhci_pci_hc_driver = {
/* Root hub support */
.hub_control = xhci_hub_control,
.hub_status_data = xhci_hub_status_data,
.bus_suspend = xhci_bus_suspend,
.bus_resume = xhci_bus_resume,
};
/*-------------------------------------------------------------------------*/
@ -186,6 +215,11 @@ static struct pci_driver xhci_pci_driver = {
/* suspend and resume implemented later */
.shutdown = usb_hcd_pci_shutdown,
#ifdef CONFIG_PM_SLEEP
.driver = {
.pm = &usb_hcd_pci_pm_ops
},
#endif
};
int xhci_register_pci(void)

Some files were not shown because too many files have changed in this diff Show More