mirror of
https://github.com/torvalds/linux.git
synced 2024-11-22 12:11:40 +00:00
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:
commit
5cc1035062
@ -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
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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")
|
||||
|
@ -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()) {
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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) },
|
||||
{ }
|
||||
};
|
||||
|
||||
|
@ -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) },
|
||||
|
@ -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
|
||||
|
||||
|
@ -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 "
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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 |
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -1789,7 +1789,8 @@ out:
|
||||
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 @@ err_driver_bind:
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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 ||
|
||||
|
@ -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 @@ done:
|
||||
* 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 @@ unknown:
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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 @@ fail:
|
||||
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)
|
||||
|
@ -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);
|
||||
|
@ -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, ð_config_driver);
|
||||
status = usb_add_config(cdev, ð_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(ð_driver);
|
||||
return usb_composite_probe(ð_driver, eth_bind);
|
||||
}
|
||||
module_init(init);
|
||||
|
||||
|
@ -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 */
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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, \
|
||||
|
@ -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 @@ unknown:
|
||||
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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 @@ eenahb:
|
||||
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) {
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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 @@ out:
|
||||
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)
|
||||
|
@ -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
|
||||
|
@ -1157,7 +1157,7 @@ fail:
|
||||
/*
|
||||
* 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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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 @@ fail:
|
||||
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)
|
||||
{
|
||||
|
@ -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
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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 @@ error:
|
||||
|
||||
return retval;
|
||||
}
|
||||
EXPORT_SYMBOL(usb_gadget_register_driver);
|
||||
EXPORT_SYMBOL(usb_gadget_probe_driver);
|
||||
|
||||
int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
|
||||
{
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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 @@ err_unbind:
|
||||
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)
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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 @@ done:
|
||||
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)
|
||||
{
|
||||
|
@ -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;
|
||||
|
@ -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 @@ fail:
|
||||
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 @@ fail:
|
||||
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)
|
||||
|
@ -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 @@ add_fail:
|
||||
udc->gadget.dev.driver = NULL;
|
||||
return retval;
|
||||
}
|
||||
EXPORT_SYMBOL(usb_gadget_register_driver);
|
||||
EXPORT_SYMBOL(usb_gadget_probe_driver);
|
||||
|
||||
|
||||
/**
|
||||
|
@ -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 @@ error:
|
||||
|
||||
return retval;
|
||||
}
|
||||
EXPORT_SYMBOL(usb_gadget_register_driver);
|
||||
EXPORT_SYMBOL(usb_gadget_probe_driver);
|
||||
|
||||
int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
|
||||
{
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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 @@ err:
|
||||
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)
|
||||
{
|
||||
|
@ -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 @@ register_error:
|
||||
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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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},
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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.
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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 */
|
||||
|
308
drivers/usb/host/fsl-mph-dr-of.c
Normal file
308
drivers/usb/host/fsl-mph-dr-of.c
Normal 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");
|
@ -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 @@ too_late:
|
||||
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 @@ too_late:
|
||||
(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 @@ alloc_dmem_failed:
|
||||
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 @@ failed_clock_set:
|
||||
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);
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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");
|
||||
|
@ -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:
|
||||
|
@ -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 */
|
||||
|
@ -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",
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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 \
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user