提交 1f9bd4c9 编写于 作者: L Linus Torvalds

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

* master.kernel.org:/pub/scm/linux/kernel/git/gregkh/usb-2.6: (129 commits)
  [PATCH] USB Storage: fix Rio Karma eject support build error
  USB: Airprime driver improvements to allow full speed EvDO transfers
  USB: remove OTG build warning
  USB: EHCI update VIA workaround
  USB: force root hub resume after power loss
  USB: ohci_usb can oops on shutdown
  USB: Dealias -110 code (more complete)
  USB: Remove unneeded void * casts in core files
  USB: u132-hcd: host controller driver for ELAN U132 adapter
  USB: ftdi-elan: client driver for ELAN Uxxx adapters
  usb serial: support Alcor Micro Corp. USB 2.0 TO RS-232 through pl2303 driver
  USB: Moschip 7840 USB-Serial Driver
  USB: add PlayStation 2 Trance Vibrator driver
  USB: Add ADU support for Ontrak ADU devices
  aircable: fix printk format warnings
  Add AIRcable USB Bluetooth Dongle Driver
  cypress_m8: implement graceful failure handling
  cypress_m8: improve control endpoint error handling
  cypress_m8: use usb_fill_int_urb where appropriate
  cypress_m8: use appropriate URB polling interval
  ...
...@@ -43,59 +43,52 @@ ...@@ -43,59 +43,52 @@
<para>A Universal Serial Bus (USB) is used to connect a host, <para>A Universal Serial Bus (USB) is used to connect a host,
such as a PC or workstation, to a number of peripheral such as a PC or workstation, to a number of peripheral
devices. USB uses a tree structure, with the host at the devices. USB uses a tree structure, with the host as the
root (the system's master), hubs as interior nodes, and root (the system's master), hubs as interior nodes, and
peripheral devices as leaves (and slaves). peripherals as leaves (and slaves).
Modern PCs support several such trees of USB devices, usually Modern PCs support several such trees of USB devices, usually
one USB 2.0 tree (480 Mbit/sec each) with one USB 2.0 tree (480 Mbit/sec each) with
a few USB 1.1 trees (12 Mbit/sec each) that are used when you a few USB 1.1 trees (12 Mbit/sec each) that are used when you
connect a USB 1.1 device directly to the machine's "root hub". connect a USB 1.1 device directly to the machine's "root hub".
</para> </para>
<para>That master/slave asymmetry was designed in part for <para>That master/slave asymmetry was designed-in for a number of
ease of use. It is not physically possible to assemble reasons, one being ease of use. It is not physically possible to
(legal) USB cables incorrectly: all upstream "to-the-host" assemble (legal) USB cables incorrectly: all upstream "to the host"
connectors are the rectangular type, matching the sockets on connectors are the rectangular type (matching the sockets on
root hubs, and the downstream type are the squarish type root hubs), and all downstream connectors are the squarish type
(or they are built in to the peripheral). (or they are built into the peripheral).
Software doesn't need to deal with distributed autoconfiguration Also, the host software doesn't need to deal with distributed
since the pre-designated master node manages all that. auto-configuration since the pre-designated master node manages all that.
At the electrical level, bus protocol overhead is reduced by And finally, at the electrical level, bus protocol overhead is reduced by
eliminating arbitration and moving scheduling into host software. eliminating arbitration and moving scheduling into the host software.
</para> </para>
<para>USB 1.0 was announced in January 1996, and was revised <para>USB 1.0 was announced in January 1996 and was revised
as USB 1.1 (with improvements in hub specification and as USB 1.1 (with improvements in hub specification and
support for interrupt-out transfers) in September 1998. support for interrupt-out transfers) in September 1998.
USB 2.0 was released in April 2000, including high speed USB 2.0 was released in April 2000, adding high-speed
transfers and transaction translating hubs (used for USB 1.1 transfers and transaction-translating hubs (used for USB 1.1
and 1.0 backward compatibility). and 1.0 backward compatibility).
</para> </para>
<para>USB support was added to Linux early in the 2.2 kernel series <para>Kernel developers added USB support to Linux early in the 2.2 kernel
shortly before the 2.3 development forked off. Updates series, shortly before 2.3 development forked. Updates from 2.3 were
from 2.3 were regularly folded back into 2.2 releases, bringing regularly folded back into 2.2 releases, which improved reliability and
new features such as <filename>/sbin/hotplug</filename> support, brought <filename>/sbin/hotplug</filename> support as well more drivers.
more drivers, and more robustness. Such improvements were continued in the 2.5 kernel series, where they added
The 2.5 kernel series continued such improvements, and also USB 2.0 support, improved performance, and made the host controller drivers
worked on USB 2.0 support, (HCDs) more consistent. They also simplified the API (to make bugs less
higher performance, likely) and added internal "kerneldoc" documentation.
better consistency between host controller drivers,
API simplification (to make bugs less likely),
and providing internal "kerneldoc" documentation.
</para> </para>
<para>Linux can run inside USB devices as well as on <para>Linux can run inside USB devices as well as on
the hosts that control the devices. the hosts that control the devices.
Because the Linux 2.x USB support evolved to support mass market But USB device drivers running inside those peripherals
platforms such as Apple Macintosh or PC-compatible systems,
it didn't address design concerns for those types of USB systems.
So it can't be used inside mass-market PDAs, or other peripherals.
USB device drivers running inside those Linux peripherals
don't do the same things as the ones running inside hosts, don't do the same things as the ones running inside hosts,
and so they've been given a different name: so they've been given a different name:
they're called <emphasis>gadget drivers</emphasis>. <emphasis>gadget drivers</emphasis>.
This document does not present gadget drivers. This document does not cover gadget drivers.
</para> </para>
</chapter> </chapter>
...@@ -103,17 +96,14 @@ ...@@ -103,17 +96,14 @@
<chapter id="host"> <chapter id="host">
<title>USB Host-Side API Model</title> <title>USB Host-Side API Model</title>
<para>Within the kernel, <para>Host-side drivers for USB devices talk to the "usbcore" APIs.
host-side drivers for USB devices talk to the "usbcore" APIs. There are two. One is intended for
There are two types of public "usbcore" APIs, targetted at two different <emphasis>general-purpose</emphasis> drivers (exposed through
layers of USB driver. Those are driver frameworks), and the other is for drivers that are
<emphasis>general purpose</emphasis> drivers, exposed through <emphasis>part of the core</emphasis>.
driver frameworks such as block, character, or network devices; Such core drivers include the <emphasis>hub</emphasis> driver
and drivers that are <emphasis>part of the core</emphasis>, (which manages trees of USB devices) and several different kinds
which are involved in managing a USB bus. of <emphasis>host controller drivers</emphasis>,
Such core drivers include the <emphasis>hub</emphasis> driver,
which manages trees of USB devices, and several different kinds
of <emphasis>host controller driver (HCD)</emphasis>,
which control individual busses. which control individual busses.
</para> </para>
...@@ -122,21 +112,21 @@ ...@@ -122,21 +112,21 @@
<itemizedlist> <itemizedlist>
<listitem><para>USB supports four kinds of data transfer <listitem><para>USB supports four kinds of data transfers
(control, bulk, interrupt, and isochronous). Two transfer (control, bulk, interrupt, and isochronous). Two of them (control
types use bandwidth as it's available (control and bulk), and bulk) use bandwidth as it's available,
while the other two types of transfer (interrupt and isochronous) while the other two (interrupt and isochronous)
are scheduled to provide guaranteed bandwidth. are scheduled to provide guaranteed bandwidth.
</para></listitem> </para></listitem>
<listitem><para>The device description model includes one or more <listitem><para>The device description model includes one or more
"configurations" per device, only one of which is active at a time. "configurations" per device, only one of which is active at a time.
Devices that are capable of high speed operation must also support Devices that are capable of high-speed operation must also support
full speed configurations, along with a way to ask about the full-speed configurations, along with a way to ask about the
"other speed" configurations that might be used. "other speed" configurations which might be used.
</para></listitem> </para></listitem>
<listitem><para>Configurations have one or more "interface", each <listitem><para>Configurations have one or more "interfaces", each
of which may have "alternate settings". Interfaces may be of which may have "alternate settings". Interfaces may be
standardized by USB "Class" specifications, or may be specific to standardized by USB "Class" specifications, or may be specific to
a vendor or device.</para> a vendor or device.</para>
...@@ -162,7 +152,7 @@ ...@@ -162,7 +152,7 @@
</para></listitem> </para></listitem>
<listitem><para>The Linux USB API supports synchronous calls for <listitem><para>The Linux USB API supports synchronous calls for
control and bulk messaging. control and bulk messages.
It also supports asynchnous calls for all kinds of data transfer, It also supports asynchnous calls for all kinds of data transfer,
using request structures called "URBs" (USB Request Blocks). using request structures called "URBs" (USB Request Blocks).
</para></listitem> </para></listitem>
...@@ -463,14 +453,25 @@ ...@@ -463,14 +453,25 @@
file in your Linux kernel sources. file in your Linux kernel sources.
</para> </para>
<para>Otherwise the main use for this file from programs <para>This file, in combination with the poll() system call, can
is to poll() it to get notifications of usb devices also be used to detect when devices are added or removed:
as they're plugged or unplugged. <programlisting>int fd;
To see what changed, you'd need to read the file and struct pollfd pfd;
compare "before" and "after" contents, scan the filesystem,
or see its hotplug event. fd = open("/proc/bus/usb/devices", O_RDONLY);
pfd = { fd, POLLIN, 0 };
for (;;) {
/* The first time through, this call will return immediately. */
poll(&amp;pfd, 1, -1);
/* To see what's changed, compare the file's previous and current
contents or scan the filesystem. (Scanning is more precise.) */
}</programlisting>
Note that this behavior is intended to be used for informational
and debug purposes. It would be more appropriate to use programs
such as udev or HAL to initialize a device or start a user-mode
helper program, for instance.
</para> </para>
</sect1> </sect1>
<sect1> <sect1>
......
...@@ -2543,6 +2543,9 @@ Your cooperation is appreciated. ...@@ -2543,6 +2543,9 @@ Your cooperation is appreciated.
64 = /dev/usb/rio500 Diamond Rio 500 64 = /dev/usb/rio500 Diamond Rio 500
65 = /dev/usb/usblcd USBLCD Interface (info@usblcd.de) 65 = /dev/usb/usblcd USBLCD Interface (info@usblcd.de)
66 = /dev/usb/cpad0 Synaptics cPad (mouse/LCD) 66 = /dev/usb/cpad0 Synaptics cPad (mouse/LCD)
67 = /dev/usb/adutux0 1st Ontrak ADU device
...
76 = /dev/usb/adutux10 10th Ontrak ADU device
96 = /dev/usb/hiddev0 1st USB HID device 96 = /dev/usb/hiddev0 1st USB HID device
... ...
111 = /dev/usb/hiddev15 16th USB HID device 111 = /dev/usb/hiddev15 16th USB HID device
......
...@@ -98,13 +98,13 @@ one or more packets could finish before an error stops further endpoint I/O. ...@@ -98,13 +98,13 @@ one or more packets could finish before an error stops further endpoint I/O.
error, a failure to respond (often caused by error, a failure to respond (often caused by
device disconnect), or some other fault. device disconnect), or some other fault.
-ETIMEDOUT (**) No response packet received within the prescribed -ETIME (**) No response packet received within the prescribed
bus turn-around time. This error may instead be bus turn-around time. This error may instead be
reported as -EPROTO or -EILSEQ. reported as -EPROTO or -EILSEQ.
Note that the synchronous USB message functions -ETIMEDOUT Synchronous USB message functions use this code
also use this code to indicate timeout expired to indicate timeout expired before the transfer
before the transfer completed. completed, and no other error was reported by HC.
-EPIPE (**) Endpoint stalled. For non-control endpoints, -EPIPE (**) Endpoint stalled. For non-control endpoints,
reset this status with usb_clear_halt(). reset this status with usb_clear_halt().
...@@ -163,6 +163,3 @@ usb_get_*/usb_set_*(): ...@@ -163,6 +163,3 @@ usb_get_*/usb_set_*():
usb_control_msg(): usb_control_msg():
usb_bulk_msg(): usb_bulk_msg():
-ETIMEDOUT Timeout expired before the transfer completed. -ETIMEDOUT Timeout expired before the transfer completed.
In the future this code may change to -ETIME,
whose definition is a closer match to this sort
of error.
...@@ -433,6 +433,11 @@ Options supported: ...@@ -433,6 +433,11 @@ Options supported:
See http://www.uuhaus.de/linux/palmconnect.html for up-to-date See http://www.uuhaus.de/linux/palmconnect.html for up-to-date
information on this driver. information on this driver.
AIRcable USB Dongle Bluetooth driver
If there is the cdc_acm driver loaded in the system, you will find that the
cdc_acm claims the device before AIRcable can. This is simply corrected
by unloading both modules and then loading the aircable module before
cdc_acm module
Generic Serial driver Generic Serial driver
......
...@@ -284,21 +284,9 @@ static struct pxaficp_platform_data corgi_ficp_platform_data = { ...@@ -284,21 +284,9 @@ static struct pxaficp_platform_data corgi_ficp_platform_data = {
/* /*
* USB Device Controller * USB Device Controller
*/ */
static void corgi_udc_command(int cmd)
{
switch(cmd) {
case PXA2XX_UDC_CMD_CONNECT:
GPSR(CORGI_GPIO_USB_PULLUP) = GPIO_bit(CORGI_GPIO_USB_PULLUP);
break;
case PXA2XX_UDC_CMD_DISCONNECT:
GPCR(CORGI_GPIO_USB_PULLUP) = GPIO_bit(CORGI_GPIO_USB_PULLUP);
break;
}
}
static struct pxa2xx_udc_mach_info udc_info __initdata = { static struct pxa2xx_udc_mach_info udc_info __initdata = {
/* no connect GPIO; corgi can't tell connection status */ /* no connect GPIO; corgi can't tell connection status */
.udc_command = corgi_udc_command, .gpio_pullup = CORGI_GPIO_USB_PULLUP,
}; };
...@@ -350,7 +338,6 @@ static void __init corgi_init(void) ...@@ -350,7 +338,6 @@ static void __init corgi_init(void)
corgi_ssp_set_machinfo(&corgi_ssp_machinfo); corgi_ssp_set_machinfo(&corgi_ssp_machinfo);
pxa_gpio_mode(CORGI_GPIO_IR_ON | GPIO_OUT); pxa_gpio_mode(CORGI_GPIO_IR_ON | GPIO_OUT);
pxa_gpio_mode(CORGI_GPIO_USB_PULLUP | GPIO_OUT);
pxa_gpio_mode(CORGI_GPIO_HSYNC | GPIO_IN); pxa_gpio_mode(CORGI_GPIO_HSYNC | GPIO_IN);
pxa_set_udc_info(&udc_info); pxa_set_udc_info(&udc_info);
......
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/usb_otg.h> #include <linux/usb/otg.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/irq.h> #include <asm/irq.h>
......
...@@ -358,7 +358,7 @@ static void ub_cmd_build_block(struct ub_dev *sc, struct ub_lun *lun, ...@@ -358,7 +358,7 @@ static void ub_cmd_build_block(struct ub_dev *sc, struct ub_lun *lun,
static void ub_cmd_build_packet(struct ub_dev *sc, struct ub_lun *lun, static void ub_cmd_build_packet(struct ub_dev *sc, struct ub_lun *lun,
struct ub_scsi_cmd *cmd, struct ub_request *urq); struct ub_scsi_cmd *cmd, struct ub_request *urq);
static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd); static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd);
static void ub_end_rq(struct request *rq, int uptodate); static void ub_end_rq(struct request *rq, unsigned int status);
static int ub_rw_cmd_retry(struct ub_dev *sc, struct ub_lun *lun, static int ub_rw_cmd_retry(struct ub_dev *sc, struct ub_lun *lun,
struct ub_request *urq, struct ub_scsi_cmd *cmd); struct ub_request *urq, struct ub_scsi_cmd *cmd);
static int ub_submit_scsi(struct ub_dev *sc, struct ub_scsi_cmd *cmd); static int ub_submit_scsi(struct ub_dev *sc, struct ub_scsi_cmd *cmd);
...@@ -639,9 +639,15 @@ static int ub_request_fn_1(struct ub_lun *lun, struct request *rq) ...@@ -639,9 +639,15 @@ static int ub_request_fn_1(struct ub_lun *lun, struct request *rq)
struct ub_request *urq; struct ub_request *urq;
int n_elem; int n_elem;
if (atomic_read(&sc->poison) || lun->changed) { if (atomic_read(&sc->poison)) {
blkdev_dequeue_request(rq);
ub_end_rq(rq, DID_NO_CONNECT << 16);
return 0;
}
if (lun->changed && !blk_pc_request(rq)) {
blkdev_dequeue_request(rq); blkdev_dequeue_request(rq);
ub_end_rq(rq, 0); ub_end_rq(rq, SAM_STAT_CHECK_CONDITION);
return 0; return 0;
} }
...@@ -693,7 +699,7 @@ static int ub_request_fn_1(struct ub_lun *lun, struct request *rq) ...@@ -693,7 +699,7 @@ static int ub_request_fn_1(struct ub_lun *lun, struct request *rq)
drop: drop:
ub_put_cmd(lun, cmd); ub_put_cmd(lun, cmd);
ub_end_rq(rq, 0); ub_end_rq(rq, DID_ERROR << 16);
return 0; return 0;
} }
...@@ -761,47 +767,53 @@ static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd) ...@@ -761,47 +767,53 @@ static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
struct ub_lun *lun = cmd->lun; struct ub_lun *lun = cmd->lun;
struct ub_request *urq = cmd->back; struct ub_request *urq = cmd->back;
struct request *rq; struct request *rq;
int uptodate; unsigned int scsi_status;
rq = urq->rq; rq = urq->rq;
if (cmd->error == 0) { if (cmd->error == 0) {
uptodate = 1;
if (blk_pc_request(rq)) { if (blk_pc_request(rq)) {
if (cmd->act_len >= rq->data_len) if (cmd->act_len >= rq->data_len)
rq->data_len = 0; rq->data_len = 0;
else else
rq->data_len -= cmd->act_len; rq->data_len -= cmd->act_len;
} }
scsi_status = 0;
} else { } else {
uptodate = 0;
if (blk_pc_request(rq)) { if (blk_pc_request(rq)) {
/* UB_SENSE_SIZE is smaller than SCSI_SENSE_BUFFERSIZE */ /* UB_SENSE_SIZE is smaller than SCSI_SENSE_BUFFERSIZE */
memcpy(rq->sense, sc->top_sense, UB_SENSE_SIZE); memcpy(rq->sense, sc->top_sense, UB_SENSE_SIZE);
rq->sense_len = UB_SENSE_SIZE; rq->sense_len = UB_SENSE_SIZE;
if (sc->top_sense[0] != 0) if (sc->top_sense[0] != 0)
rq->errors = SAM_STAT_CHECK_CONDITION; scsi_status = SAM_STAT_CHECK_CONDITION;
else else
rq->errors = DID_ERROR << 16; scsi_status = DID_ERROR << 16;
} else { } else {
if (cmd->error == -EIO) { if (cmd->error == -EIO) {
if (ub_rw_cmd_retry(sc, lun, urq, cmd) == 0) if (ub_rw_cmd_retry(sc, lun, urq, cmd) == 0)
return; return;
} }
scsi_status = SAM_STAT_CHECK_CONDITION;
} }
} }
urq->rq = NULL; urq->rq = NULL;
ub_put_cmd(lun, cmd); ub_put_cmd(lun, cmd);
ub_end_rq(rq, uptodate); ub_end_rq(rq, scsi_status);
blk_start_queue(lun->disk->queue); blk_start_queue(lun->disk->queue);
} }
static void ub_end_rq(struct request *rq, int uptodate) static void ub_end_rq(struct request *rq, unsigned int scsi_status)
{ {
int uptodate;
if (scsi_status == 0) {
uptodate = 1;
} else {
uptodate = 0;
rq->errors = scsi_status;
}
end_that_request_first(rq, uptodate, rq->hard_nr_sectors); end_that_request_first(rq, uptodate, rq->hard_nr_sectors);
end_that_request_last(rq, uptodate); end_that_request_last(rq, uptodate);
} }
......
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
#include <linux/usb_ch9.h> #include <linux/usb_ch9.h>
#include <linux/usb_gadget.h> #include <linux/usb_gadget.h>
#include <linux/usb.h> #include <linux/usb.h>
#include <linux/usb_otg.h> #include <linux/usb/otg.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/workqueue.h> #include <linux/workqueue.h>
......
...@@ -192,7 +192,7 @@ static char *get_usb_statmsg(int status) ...@@ -192,7 +192,7 @@ static char *get_usb_statmsg(int status)
return "bit stuffing error, timeout, or unknown USB error"; return "bit stuffing error, timeout, or unknown USB error";
case -EILSEQ: case -EILSEQ:
return "CRC mismatch, timeout, or unknown USB error"; return "CRC mismatch, timeout, or unknown USB error";
case -ETIMEDOUT: case -ETIME:
return "timed out"; return "timed out";
case -EPIPE: case -EPIPE:
return "endpoint stalled"; return "endpoint stalled";
......
...@@ -137,11 +137,11 @@ static struct hfcusb_symbolic_list urb_errlist[] = { ...@@ -137,11 +137,11 @@ static struct hfcusb_symbolic_list urb_errlist[] = {
{-ENXIO, "URB already queued"}, {-ENXIO, "URB already queued"},
{-EFBIG, "Too much ISO frames requested"}, {-EFBIG, "Too much ISO frames requested"},
{-ENOSR, "Buffer error (overrun)"}, {-ENOSR, "Buffer error (overrun)"},
{-EPIPE, "Specified endpoint is stalled (device not responding)"}, {-EPIPE, "Specified endpoint is stalled"},
{-EOVERFLOW, "Babble (bad cable?)"}, {-EOVERFLOW, "Babble (bad cable?)"},
{-EPROTO, "Bit-stuff error (bad cable?)"}, {-EPROTO, "Bit-stuff error (bad cable?)"},
{-EILSEQ, "CRC/Timeout"}, {-EILSEQ, "CRC or missing token"},
{-ETIMEDOUT, "NAK (device does not respond)"}, {-ETIME, "Device did not respond"},
{-ESHUTDOWN, "Device unplugged"}, {-ESHUTDOWN, "Device unplugged"},
{-1, NULL} {-1, NULL}
}; };
......
...@@ -80,7 +80,6 @@ static void dvb_usb_urb_complete(struct urb *urb, struct pt_regs *ptregs) ...@@ -80,7 +80,6 @@ static void dvb_usb_urb_complete(struct urb *urb, struct pt_regs *ptregs)
switch (urb->status) { switch (urb->status) {
case 0: /* success */ case 0: /* success */
case -ETIMEDOUT: /* NAK */
break; break;
case -ECONNRESET: /* kill */ case -ECONNRESET: /* kill */
case -ENOENT: case -ENOENT:
......
...@@ -215,7 +215,7 @@ static void ttusb_dec_handle_irq( struct urb *urb, struct pt_regs *regs) ...@@ -215,7 +215,7 @@ static void ttusb_dec_handle_irq( struct urb *urb, struct pt_regs *regs)
case -ECONNRESET: case -ECONNRESET:
case -ENOENT: case -ENOENT:
case -ESHUTDOWN: case -ESHUTDOWN:
case -ETIMEDOUT: case -ETIME:
/* this urb is dead, cleanup */ /* this urb is dead, cleanup */
dprintk("%s:urb shutting down with status: %d\n", dprintk("%s:urb shutting down with status: %d\n",
__FUNCTION__, urb->status); __FUNCTION__, urb->status);
......
...@@ -301,10 +301,11 @@ static struct symbolic_list senlist[] = { ...@@ -301,10 +301,11 @@ static struct symbolic_list senlist[] = {
static struct symbolic_list urb_errlist[] = { static struct symbolic_list urb_errlist[] = {
{ -ENOSR, "Buffer error (overrun)" }, { -ENOSR, "Buffer error (overrun)" },
{ -EPIPE, "Stalled (device not responding)" }, { -EPIPE, "Stalled (device not responding)" },
{ -EOVERFLOW, "Babble (bad cable?)" }, { -EOVERFLOW, "Babble (device sends too much data)" },
{ -EPROTO, "Bit-stuff error (bad cable?)" }, { -EPROTO, "Bit-stuff error (bad cable?)" },
{ -EILSEQ, "CRC/Timeout" }, { -EILSEQ, "CRC/Timeout (bad cable?)" },
{ -ETIMEDOUT, "NAK (device does not respond)" }, { -ETIME, "Device does not respond to token" },
{ -ETIMEDOUT, "Device does not respond to command" },
{ -1, NULL } { -1, NULL }
}; };
......
...@@ -711,7 +711,7 @@ static void pwc_isoc_handler(struct urb *urb, struct pt_regs *regs) ...@@ -711,7 +711,7 @@ static void pwc_isoc_handler(struct urb *urb, struct pt_regs *regs)
case -EOVERFLOW: errmsg = "Babble (bad cable?)"; break; case -EOVERFLOW: errmsg = "Babble (bad cable?)"; break;
case -EPROTO: errmsg = "Bit-stuff error (bad cable?)"; break; case -EPROTO: errmsg = "Bit-stuff error (bad cable?)"; break;
case -EILSEQ: errmsg = "CRC/Timeout (could be anything)"; break; case -EILSEQ: errmsg = "CRC/Timeout (could be anything)"; break;
case -ETIMEDOUT: errmsg = "NAK (device does not respond)"; break; case -ETIME: errmsg = "Device does not respond"; break;
} }
PWC_DEBUG_FLOW("pwc_isoc_handler() called with status %d [%s].\n", urb->status, errmsg); PWC_DEBUG_FLOW("pwc_isoc_handler() called with status %d [%s].\n", urb->status, errmsg);
/* Give up after a number of contiguous errors on the USB bus. /* Give up after a number of contiguous errors on the USB bus.
......
...@@ -586,15 +586,14 @@ static struct w9968cf_symbolic_list urb_errlist[] = { ...@@ -586,15 +586,14 @@ static struct w9968cf_symbolic_list urb_errlist[] = {
{ -EFBIG, "Too much ISO frames requested" }, { -EFBIG, "Too much ISO frames requested" },
{ -ENOSR, "Buffer error (overrun)" }, { -ENOSR, "Buffer error (overrun)" },
{ -EPIPE, "Specified endpoint is stalled (device not responding)"}, { -EPIPE, "Specified endpoint is stalled (device not responding)"},
{ -EOVERFLOW, "Babble (bad cable?)" }, { -EOVERFLOW, "Babble (too much data)" },
{ -EPROTO, "Bit-stuff error (bad cable?)" }, { -EPROTO, "Bit-stuff error (bad cable?)" },
{ -EILSEQ, "CRC/Timeout" }, { -EILSEQ, "CRC/Timeout" },
{ -ETIMEDOUT, "NAK (device does not respond)" }, { -ETIME, "Device does not respond to token" },
{ -ETIMEDOUT, "Device does not respond to command" },
{ -1, NULL } { -1, NULL }
}; };
/**************************************************************************** /****************************************************************************
* Memory management functions * * Memory management functions *
****************************************************************************/ ****************************************************************************/
......
...@@ -671,10 +671,8 @@ static void irda_usb_net_timeout(struct net_device *netdev) ...@@ -671,10 +671,8 @@ static void irda_usb_net_timeout(struct net_device *netdev)
* Jean II */ * Jean II */
done = 1; done = 1;
break; break;
case -ECONNABORTED: /* -103 */ case -ECONNRESET:
case -ECONNRESET: /* -104 */ case -ENOENT: /* urb unlinked by us */
case -ETIMEDOUT: /* -110 */
case -ENOENT: /* -2 (urb unlinked by us) */
default: /* ??? - Play safe */ default: /* ??? - Play safe */
urb->status = 0; urb->status = 0;
netif_wake_queue(self->netdev); netif_wake_queue(self->netdev);
...@@ -712,10 +710,8 @@ static void irda_usb_net_timeout(struct net_device *netdev) ...@@ -712,10 +710,8 @@ static void irda_usb_net_timeout(struct net_device *netdev)
* Jean II */ * Jean II */
done = 1; done = 1;
break; break;
case -ECONNABORTED: /* -103 */ case -ECONNRESET:
case -ECONNRESET: /* -104 */ case -ENOENT: /* urb unlinked by us */
case -ETIMEDOUT: /* -110 */
case -ENOENT: /* -2 (urb unlinked by us) */
default: /* ??? - Play safe */ default: /* ??? - Play safe */
if(skb != NULL) { if(skb != NULL) {
dev_kfree_skb_any(skb); dev_kfree_skb_any(skb);
...@@ -845,14 +841,14 @@ static void irda_usb_receive(struct urb *urb, struct pt_regs *regs) ...@@ -845,14 +841,14 @@ static void irda_usb_receive(struct urb *urb, struct pt_regs *regs)
self->stats.rx_crc_errors++; self->stats.rx_crc_errors++;
/* Also precursor to a hot-unplug on UHCI. */ /* Also precursor to a hot-unplug on UHCI. */
/* Fallthrough... */ /* Fallthrough... */
case -ECONNRESET: /* -104 */ case -ECONNRESET:
/* Random error, if I remember correctly */ /* Random error, if I remember correctly */
/* uhci_cleanup_unlink() is going to kill the Rx /* uhci_cleanup_unlink() is going to kill the Rx
* URB just after we return. No problem, at this * URB just after we return. No problem, at this
* point the URB will be idle ;-) - Jean II */ * point the URB will be idle ;-) - Jean II */
case -ESHUTDOWN: /* -108 */ case -ESHUTDOWN:
/* That's usually a hot-unplug. Submit will fail... */ /* That's usually a hot-unplug. Submit will fail... */
case -ETIMEDOUT: /* -110 */ case -ETIME:
/* Usually precursor to a hot-unplug on OHCI. */ /* Usually precursor to a hot-unplug on OHCI. */
default: default:
self->stats.rx_errors++; self->stats.rx_errors++;
......
...@@ -119,7 +119,7 @@ static void zd1201_usbfree(struct urb *urb, struct pt_regs *regs) ...@@ -119,7 +119,7 @@ static void zd1201_usbfree(struct urb *urb, struct pt_regs *regs)
switch(urb->status) { switch(urb->status) {
case -EILSEQ: case -EILSEQ:
case -ENODEV: case -ENODEV:
case -ETIMEDOUT: case -ETIME:
case -ENOENT: case -ENOENT:
case -EPIPE: case -EPIPE:
case -EOVERFLOW: case -EOVERFLOW:
...@@ -201,7 +201,7 @@ static void zd1201_usbrx(struct urb *urb, struct pt_regs *regs) ...@@ -201,7 +201,7 @@ static void zd1201_usbrx(struct urb *urb, struct pt_regs *regs)
switch(urb->status) { switch(urb->status) {
case -EILSEQ: case -EILSEQ:
case -ENODEV: case -ENODEV:
case -ETIMEDOUT: case -ETIME:
case -ENOENT: case -ENOENT:
case -EPIPE: case -EPIPE:
case -EOVERFLOW: case -EOVERFLOW:
......
...@@ -25,6 +25,7 @@ config USB_ARCH_HAS_OHCI ...@@ -25,6 +25,7 @@ config USB_ARCH_HAS_OHCI
default y if PXA27x default y if PXA27x
default y if ARCH_EP93XX default y if ARCH_EP93XX
default y if (ARCH_AT91RM9200 || ARCH_AT91SAM9261) default y if (ARCH_AT91RM9200 || ARCH_AT91SAM9261)
default y if ARCH_PNX4008
# PPC: # PPC:
default y if STB03xxx default y if STB03xxx
default y if PPC_MPC52xx default y if PPC_MPC52xx
......
...@@ -14,6 +14,7 @@ obj-$(CONFIG_USB_ISP116X_HCD) += host/ ...@@ -14,6 +14,7 @@ obj-$(CONFIG_USB_ISP116X_HCD) += host/
obj-$(CONFIG_USB_OHCI_HCD) += host/ obj-$(CONFIG_USB_OHCI_HCD) += host/
obj-$(CONFIG_USB_UHCI_HCD) += host/ obj-$(CONFIG_USB_UHCI_HCD) += host/
obj-$(CONFIG_USB_SL811_HCD) += host/ obj-$(CONFIG_USB_SL811_HCD) += host/
obj-$(CONFIG_USB_U132_HCD) += host/
obj-$(CONFIG_ETRAX_USB_HOST) += host/ obj-$(CONFIG_ETRAX_USB_HOST) += host/
obj-$(CONFIG_USB_OHCI_AT91) += host/ obj-$(CONFIG_USB_OHCI_AT91) += host/
...@@ -23,6 +24,7 @@ obj-$(CONFIG_USB_PRINTER) += class/ ...@@ -23,6 +24,7 @@ obj-$(CONFIG_USB_PRINTER) += class/
obj-$(CONFIG_USB_STORAGE) += storage/ obj-$(CONFIG_USB_STORAGE) += storage/
obj-$(CONFIG_USB) += storage/ obj-$(CONFIG_USB) += storage/
obj-$(CONFIG_USB_ACECAD) += input/
obj-$(CONFIG_USB_AIPTEK) += input/ obj-$(CONFIG_USB_AIPTEK) += input/
obj-$(CONFIG_USB_ATI_REMOTE) += input/ obj-$(CONFIG_USB_ATI_REMOTE) += input/
obj-$(CONFIG_USB_HID) += input/ obj-$(CONFIG_USB_HID) += input/
...@@ -31,8 +33,8 @@ obj-$(CONFIG_USB_KBTAB) += input/ ...@@ -31,8 +33,8 @@ obj-$(CONFIG_USB_KBTAB) += input/
obj-$(CONFIG_USB_MOUSE) += input/ obj-$(CONFIG_USB_MOUSE) += input/
obj-$(CONFIG_USB_MTOUCH) += input/ obj-$(CONFIG_USB_MTOUCH) += input/
obj-$(CONFIG_USB_POWERMATE) += input/ obj-$(CONFIG_USB_POWERMATE) += input/
obj-$(CONFIG_USB_TRANCEVIBRATOR)+= input/
obj-$(CONFIG_USB_WACOM) += input/ obj-$(CONFIG_USB_WACOM) += input/
obj-$(CONFIG_USB_ACECAD) += input/
obj-$(CONFIG_USB_XPAD) += input/ obj-$(CONFIG_USB_XPAD) += input/
obj-$(CONFIG_USB_CATC) += net/ obj-$(CONFIG_USB_CATC) += net/
...@@ -47,22 +49,24 @@ obj-$(CONFIG_USB_MICROTEK) += image/ ...@@ -47,22 +49,24 @@ obj-$(CONFIG_USB_MICROTEK) += image/
obj-$(CONFIG_USB_SERIAL) += serial/ obj-$(CONFIG_USB_SERIAL) += serial/
obj-$(CONFIG_USB_ADUTUX) += misc/
obj-$(CONFIG_USB_APPLEDISPLAY) += misc/
obj-$(CONFIG_USB_AUERSWALD) += misc/ obj-$(CONFIG_USB_AUERSWALD) += misc/
obj-$(CONFIG_USB_CYPRESS_CY7C63)+= misc/ obj-$(CONFIG_USB_CYPRESS_CY7C63)+= misc/
obj-$(CONFIG_USB_CYTHERM) += misc/ obj-$(CONFIG_USB_CYTHERM) += misc/
obj-$(CONFIG_USB_EMI26) += misc/ obj-$(CONFIG_USB_EMI26) += misc/
obj-$(CONFIG_USB_EMI62) += misc/ obj-$(CONFIG_USB_EMI62) += misc/
obj-$(CONFIG_USB_FTDI_ELAN) += misc/
obj-$(CONFIG_USB_IDMOUSE) += misc/ obj-$(CONFIG_USB_IDMOUSE) += misc/
obj-$(CONFIG_USB_LCD) += misc/ obj-$(CONFIG_USB_LCD) += misc/
obj-$(CONFIG_USB_LD) += misc/ obj-$(CONFIG_USB_LD) += misc/
obj-$(CONFIG_USB_LED) += misc/ obj-$(CONFIG_USB_LED) += misc/
obj-$(CONFIG_USB_LEGOTOWER) += misc/ obj-$(CONFIG_USB_LEGOTOWER) += misc/
obj-$(CONFIG_USB_PHIDGETSERVO) += misc/
obj-$(CONFIG_USB_RIO500) += misc/ obj-$(CONFIG_USB_RIO500) += misc/
obj-$(CONFIG_USB_SISUSBVGA) += misc/
obj-$(CONFIG_USB_TEST) += misc/ obj-$(CONFIG_USB_TEST) += misc/
obj-$(CONFIG_USB_USS720) += misc/ obj-$(CONFIG_USB_USS720) += misc/
obj-$(CONFIG_USB_PHIDGETSERVO) += misc/
obj-$(CONFIG_USB_SISUSBVGA) += misc/
obj-$(CONFIG_USB_APPLEDISPLAY) += misc/
obj-$(CONFIG_USB_ATM) += atm/ obj-$(CONFIG_USB_ATM) += atm/
obj-$(CONFIG_USB_SPEEDTOUCH) += atm/ obj-$(CONFIG_USB_SPEEDTOUCH) += atm/
...@@ -1621,26 +1621,32 @@ static int claim_interface(struct usb_device *usb_dev, ...@@ -1621,26 +1621,32 @@ static int claim_interface(struct usb_device *usb_dev,
return ret; return ret;
} }
static void create_fs_entries(struct uea_softc *sc, struct usb_interface *intf) static struct attribute *attrs[] = {
&dev_attr_stat_status.attr,
&dev_attr_stat_mflags.attr,
&dev_attr_stat_human_status.attr,
&dev_attr_stat_delin.attr,
&dev_attr_stat_vidcpe.attr,
&dev_attr_stat_usrate.attr,
&dev_attr_stat_dsrate.attr,
&dev_attr_stat_usattenuation.attr,
&dev_attr_stat_dsattenuation.attr,
&dev_attr_stat_usmargin.attr,
&dev_attr_stat_dsmargin.attr,
&dev_attr_stat_txflow.attr,
&dev_attr_stat_rxflow.attr,
&dev_attr_stat_uscorr.attr,
&dev_attr_stat_dscorr.attr,
&dev_attr_stat_usunc.attr,
&dev_attr_stat_dsunc.attr,
};
static struct attribute_group attr_grp = {
.attrs = attrs,
};
static int create_fs_entries(struct usb_interface *intf)
{ {
/* sysfs interface */ return sysfs_create_group(&intf->dev.kobj, &attr_grp);
device_create_file(&intf->dev, &dev_attr_stat_status);
device_create_file(&intf->dev, &dev_attr_stat_mflags);
device_create_file(&intf->dev, &dev_attr_stat_human_status);
device_create_file(&intf->dev, &dev_attr_stat_delin);
device_create_file(&intf->dev, &dev_attr_stat_vidcpe);
device_create_file(&intf->dev, &dev_attr_stat_usrate);
device_create_file(&intf->dev, &dev_attr_stat_dsrate);
device_create_file(&intf->dev, &dev_attr_stat_usattenuation);
device_create_file(&intf->dev, &dev_attr_stat_dsattenuation);
device_create_file(&intf->dev, &dev_attr_stat_usmargin);
device_create_file(&intf->dev, &dev_attr_stat_dsmargin);
device_create_file(&intf->dev, &dev_attr_stat_txflow);
device_create_file(&intf->dev, &dev_attr_stat_rxflow);
device_create_file(&intf->dev, &dev_attr_stat_uscorr);
device_create_file(&intf->dev, &dev_attr_stat_dscorr);
device_create_file(&intf->dev, &dev_attr_stat_usunc);
device_create_file(&intf->dev, &dev_attr_stat_dsunc);
} }
static int uea_bind(struct usbatm_data *usbatm, struct usb_interface *intf, static int uea_bind(struct usbatm_data *usbatm, struct usb_interface *intf,
...@@ -1708,37 +1714,25 @@ static int uea_bind(struct usbatm_data *usbatm, struct usb_interface *intf, ...@@ -1708,37 +1714,25 @@ static int uea_bind(struct usbatm_data *usbatm, struct usb_interface *intf,
return ret; return ret;
} }
create_fs_entries(sc, intf); ret = create_fs_entries(intf);
if (ret) {
uea_stop(sc);
kfree(sc);
return ret;
}
return 0; return 0;
} }
static void destroy_fs_entries(struct uea_softc *sc, struct usb_interface *intf) static void destroy_fs_entries(struct usb_interface *intf)
{ {
/* sysfs interface */ sysfs_remove_group(&intf->dev.kobj, &attr_grp);
device_remove_file(&intf->dev, &dev_attr_stat_status);
device_remove_file(&intf->dev, &dev_attr_stat_mflags);
device_remove_file(&intf->dev, &dev_attr_stat_human_status);
device_remove_file(&intf->dev, &dev_attr_stat_delin);
device_remove_file(&intf->dev, &dev_attr_stat_vidcpe);
device_remove_file(&intf->dev, &dev_attr_stat_usrate);
device_remove_file(&intf->dev, &dev_attr_stat_dsrate);
device_remove_file(&intf->dev, &dev_attr_stat_usattenuation);
device_remove_file(&intf->dev, &dev_attr_stat_dsattenuation);
device_remove_file(&intf->dev, &dev_attr_stat_usmargin);
device_remove_file(&intf->dev, &dev_attr_stat_dsmargin);
device_remove_file(&intf->dev, &dev_attr_stat_txflow);
device_remove_file(&intf->dev, &dev_attr_stat_rxflow);
device_remove_file(&intf->dev, &dev_attr_stat_uscorr);
device_remove_file(&intf->dev, &dev_attr_stat_dscorr);
device_remove_file(&intf->dev, &dev_attr_stat_usunc);
device_remove_file(&intf->dev, &dev_attr_stat_dsunc);
} }
static void uea_unbind(struct usbatm_data *usbatm, struct usb_interface *intf) static void uea_unbind(struct usbatm_data *usbatm, struct usb_interface *intf)
{ {
struct uea_softc *sc = usbatm->driver_data; struct uea_softc *sc = usbatm->driver_data;
destroy_fs_entries(sc, intf); destroy_fs_entries(intf);
uea_stop(sc); uea_stop(sc);
kfree(sc); kfree(sc);
} }
......
...@@ -813,7 +813,7 @@ static unsigned int usblp_quirks (__u16 vendor, __u16 product) ...@@ -813,7 +813,7 @@ static unsigned int usblp_quirks (__u16 vendor, __u16 product)
return 0; return 0;
} }
static struct file_operations usblp_fops = { static const struct file_operations usblp_fops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.read = usblp_read, .read = usblp_read,
.write = usblp_write, .write = usblp_write,
...@@ -927,7 +927,9 @@ static int usblp_probe(struct usb_interface *intf, ...@@ -927,7 +927,9 @@ static int usblp_probe(struct usb_interface *intf,
/* Retrieve and store the device ID string. */ /* Retrieve and store the device ID string. */
usblp_cache_device_id_string(usblp); usblp_cache_device_id_string(usblp);
device_create_file(&intf->dev, &dev_attr_ieee1284_id); retval = device_create_file(&intf->dev, &dev_attr_ieee1284_id);
if (retval)
goto abort_intfdata;
#ifdef DEBUG #ifdef DEBUG
usblp_check_status(usblp, 0); usblp_check_status(usblp, 0);
...@@ -1021,18 +1023,13 @@ static int usblp_select_alts(struct usblp *usblp) ...@@ -1021,18 +1023,13 @@ static int usblp_select_alts(struct usblp *usblp)
for (e = 0; e < ifd->desc.bNumEndpoints; e++) { for (e = 0; e < ifd->desc.bNumEndpoints; e++) {
epd = &ifd->endpoint[e].desc; epd = &ifd->endpoint[e].desc;
if ((epd->bmAttributes&USB_ENDPOINT_XFERTYPE_MASK)!= if (usb_endpoint_is_bulk_out(epd))
USB_ENDPOINT_XFER_BULK)
continue;
if (!(epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK)) {
if (!epwrite) if (!epwrite)
epwrite = epd; epwrite = epd;
} else { if (usb_endpoint_is_bulk_in(epd))
if (!epread) if (!epread)
epread = epd; epread = epd;
}
} }
/* Ignore buggy hardware without the right endpoints. */ /* Ignore buggy hardware without the right endpoints. */
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
usbcore-objs := usb.o hub.o hcd.o urb.o message.o driver.o \ usbcore-objs := usb.o hub.o hcd.o urb.o message.o driver.o \
config.o file.o buffer.o sysfs.o endpoint.o \ config.o file.o buffer.o sysfs.o endpoint.o \
devio.o notify.o devio.o notify.o generic.o
ifeq ($(CONFIG_PCI),y) ifeq ($(CONFIG_PCI),y)
usbcore-objs += hcd-pci.o usbcore-objs += hcd-pci.o
......
...@@ -104,7 +104,7 @@ void *hcd_buffer_alloc ( ...@@ -104,7 +104,7 @@ void *hcd_buffer_alloc (
dma_addr_t *dma dma_addr_t *dma
) )
{ {
struct usb_hcd *hcd = bus->hcpriv; struct usb_hcd *hcd = bus_to_hcd(bus);
int i; int i;
/* some USB hosts just use PIO */ /* some USB hosts just use PIO */
...@@ -127,7 +127,7 @@ void hcd_buffer_free ( ...@@ -127,7 +127,7 @@ void hcd_buffer_free (
dma_addr_t dma dma_addr_t dma
) )
{ {
struct usb_hcd *hcd = bus->hcpriv; struct usb_hcd *hcd = bus_to_hcd(bus);
int i; int i;
if (!addr) if (!addr)
......
...@@ -475,7 +475,9 @@ int usb_get_configuration(struct usb_device *dev) ...@@ -475,7 +475,9 @@ int usb_get_configuration(struct usb_device *dev)
if (result < 0) { if (result < 0) {
dev_err(ddev, "unable to read config index %d " dev_err(ddev, "unable to read config index %d "
"descriptor/%s\n", cfgno, "start"); "descriptor/%s\n", cfgno, "start");
goto err; dev_err(ddev, "chopping to %d config(s)\n", cfgno);
dev->descriptor.bNumConfigurations = cfgno;
break;
} else if (result < 4) { } else if (result < 4) {
dev_err(ddev, "config index %d descriptor too short " dev_err(ddev, "config index %d descriptor too short "
"(expected %i, got %i)\n", cfgno, "(expected %i, got %i)\n", cfgno,
......
...@@ -593,7 +593,7 @@ static ssize_t usb_device_read(struct file *file, char __user *buf, size_t nbyte ...@@ -593,7 +593,7 @@ static ssize_t usb_device_read(struct file *file, char __user *buf, size_t nbyte
/* Kernel lock for "lastev" protection */ /* Kernel lock for "lastev" protection */
static unsigned int usb_device_poll(struct file *file, struct poll_table_struct *wait) static unsigned int usb_device_poll(struct file *file, struct poll_table_struct *wait)
{ {
struct usb_device_status *st = (struct usb_device_status *)file->private_data; struct usb_device_status *st = file->private_data;
unsigned int mask = 0; unsigned int mask = 0;
lock_kernel(); lock_kernel();
...@@ -603,7 +603,7 @@ static unsigned int usb_device_poll(struct file *file, struct poll_table_struct ...@@ -603,7 +603,7 @@ static unsigned int usb_device_poll(struct file *file, struct poll_table_struct
unlock_kernel(); unlock_kernel();
return POLLIN; return POLLIN;
} }
/* we may have dropped BKL - need to check for having lost the race */ /* we may have dropped BKL - need to check for having lost the race */
if (file->private_data) { if (file->private_data) {
kfree(st); kfree(st);
...@@ -667,7 +667,7 @@ static loff_t usb_device_lseek(struct file * file, loff_t offset, int orig) ...@@ -667,7 +667,7 @@ static loff_t usb_device_lseek(struct file * file, loff_t offset, int orig)
return ret; return ret;
} }
struct file_operations usbfs_devices_fops = { const struct file_operations usbfs_devices_fops = {
.llseek = usb_device_lseek, .llseek = usb_device_lseek,
.read = usb_device_read, .read = usb_device_read,
.poll = usb_device_poll, .poll = usb_device_poll,
......
...@@ -59,6 +59,9 @@ ...@@ -59,6 +59,9 @@
#define USB_DEVICE_MAX USB_MAXBUS * 128 #define USB_DEVICE_MAX USB_MAXBUS * 128
static struct class *usb_device_class; static struct class *usb_device_class;
/* Mutual exclusion for removal, open, and release */
DEFINE_MUTEX(usbfs_mutex);
struct async { struct async {
struct list_head asynclist; struct list_head asynclist;
struct dev_state *ps; struct dev_state *ps;
...@@ -87,9 +90,10 @@ MODULE_PARM_DESC (usbfs_snoop, "true to log all usbfs traffic"); ...@@ -87,9 +90,10 @@ MODULE_PARM_DESC (usbfs_snoop, "true to log all usbfs traffic");
#define MAX_USBFS_BUFFER_SIZE 16384 #define MAX_USBFS_BUFFER_SIZE 16384
static inline int connected (struct usb_device *dev) static inline int connected (struct dev_state *ps)
{ {
return dev->state != USB_STATE_NOTATTACHED; return (!list_empty(&ps->list) &&
ps->dev->state != USB_STATE_NOTATTACHED);
} }
static loff_t usbdev_lseek(struct file *file, loff_t offset, int orig) static loff_t usbdev_lseek(struct file *file, loff_t offset, int orig)
...@@ -118,7 +122,7 @@ static loff_t usbdev_lseek(struct file *file, loff_t offset, int orig) ...@@ -118,7 +122,7 @@ static loff_t usbdev_lseek(struct file *file, loff_t offset, int orig)
static ssize_t usbdev_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos) static ssize_t usbdev_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
{ {
struct dev_state *ps = (struct dev_state *)file->private_data; struct dev_state *ps = file->private_data;
struct usb_device *dev = ps->dev; struct usb_device *dev = ps->dev;
ssize_t ret = 0; ssize_t ret = 0;
unsigned len; unsigned len;
...@@ -127,7 +131,7 @@ static ssize_t usbdev_read(struct file *file, char __user *buf, size_t nbytes, l ...@@ -127,7 +131,7 @@ static ssize_t usbdev_read(struct file *file, char __user *buf, size_t nbytes, l
pos = *ppos; pos = *ppos;
usb_lock_device(dev); usb_lock_device(dev);
if (!connected(dev)) { if (!connected(ps)) {
ret = -ENODEV; ret = -ENODEV;
goto err; goto err;
} else if (pos < 0) { } else if (pos < 0) {
...@@ -301,7 +305,7 @@ static void snoop_urb(struct urb *urb, void __user *userurb) ...@@ -301,7 +305,7 @@ static void snoop_urb(struct urb *urb, void __user *userurb)
static void async_completed(struct urb *urb, struct pt_regs *regs) static void async_completed(struct urb *urb, struct pt_regs *regs)
{ {
struct async *as = (struct async *)urb->context; struct async *as = urb->context;
struct dev_state *ps = as->ps; struct dev_state *ps = as->ps;
struct siginfo sinfo; struct siginfo sinfo;
...@@ -541,25 +545,25 @@ static int usbdev_open(struct inode *inode, struct file *file) ...@@ -541,25 +545,25 @@ static int usbdev_open(struct inode *inode, struct file *file)
struct dev_state *ps; struct dev_state *ps;
int ret; int ret;
/* /* Protect against simultaneous removal or release */
* no locking necessary here, as chrdev_open has the kernel lock mutex_lock(&usbfs_mutex);
* (still acquire the kernel lock for safety)
*/
ret = -ENOMEM; ret = -ENOMEM;
if (!(ps = kmalloc(sizeof(struct dev_state), GFP_KERNEL))) if (!(ps = kmalloc(sizeof(struct dev_state), GFP_KERNEL)))
goto out_nolock; goto out;
lock_kernel();
ret = -ENOENT; ret = -ENOENT;
/* check if we are called from a real node or usbfs */ /* check if we are called from a real node or usbfs */
if (imajor(inode) == USB_DEVICE_MAJOR) if (imajor(inode) == USB_DEVICE_MAJOR)
dev = usbdev_lookup_minor(iminor(inode)); dev = usbdev_lookup_minor(iminor(inode));
if (!dev) if (!dev)
dev = inode->i_private; dev = inode->i_private;
if (!dev) { if (!dev)
kfree(ps);
goto out; goto out;
} ret = usb_autoresume_device(dev, 1);
if (ret)
goto out;
usb_get_dev(dev); usb_get_dev(dev);
ret = 0; ret = 0;
ps->dev = dev; ps->dev = dev;
...@@ -579,30 +583,36 @@ static int usbdev_open(struct inode *inode, struct file *file) ...@@ -579,30 +583,36 @@ static int usbdev_open(struct inode *inode, struct file *file)
list_add_tail(&ps->list, &dev->filelist); list_add_tail(&ps->list, &dev->filelist);
file->private_data = ps; file->private_data = ps;
out: out:
unlock_kernel(); if (ret)
out_nolock: kfree(ps);
return ret; mutex_unlock(&usbfs_mutex);
return ret;
} }
static int usbdev_release(struct inode *inode, struct file *file) static int usbdev_release(struct inode *inode, struct file *file)
{ {
struct dev_state *ps = (struct dev_state *)file->private_data; struct dev_state *ps = file->private_data;
struct usb_device *dev = ps->dev; struct usb_device *dev = ps->dev;
unsigned int ifnum; unsigned int ifnum;
usb_lock_device(dev); usb_lock_device(dev);
/* Protect against simultaneous open */
mutex_lock(&usbfs_mutex);
list_del_init(&ps->list); list_del_init(&ps->list);
mutex_unlock(&usbfs_mutex);
for (ifnum = 0; ps->ifclaimed && ifnum < 8*sizeof(ps->ifclaimed); for (ifnum = 0; ps->ifclaimed && ifnum < 8*sizeof(ps->ifclaimed);
ifnum++) { ifnum++) {
if (test_bit(ifnum, &ps->ifclaimed)) if (test_bit(ifnum, &ps->ifclaimed))
releaseintf(ps, ifnum); releaseintf(ps, ifnum);
} }
destroy_all_async(ps); destroy_all_async(ps);
usb_autosuspend_device(dev, 1);
usb_unlock_device(dev); usb_unlock_device(dev);
usb_put_dev(dev); usb_put_dev(dev);
ps->dev = NULL;
kfree(ps); kfree(ps);
return 0; return 0;
} }
static int proc_control(struct dev_state *ps, void __user *arg) static int proc_control(struct dev_state *ps, void __user *arg)
...@@ -1322,7 +1332,7 @@ static int proc_ioctl(struct dev_state *ps, struct usbdevfs_ioctl *ctl) ...@@ -1322,7 +1332,7 @@ static int proc_ioctl(struct dev_state *ps, struct usbdevfs_ioctl *ctl)
} }
} }
if (!connected(ps->dev)) { if (!connected(ps)) {
kfree(buf); kfree(buf);
return -ENODEV; return -ENODEV;
} }
...@@ -1349,7 +1359,7 @@ static int proc_ioctl(struct dev_state *ps, struct usbdevfs_ioctl *ctl) ...@@ -1349,7 +1359,7 @@ static int proc_ioctl(struct dev_state *ps, struct usbdevfs_ioctl *ctl)
/* let kernel drivers try to (re)bind to the interface */ /* let kernel drivers try to (re)bind to the interface */
case USBDEVFS_CONNECT: case USBDEVFS_CONNECT:
usb_unlock_device(ps->dev); usb_unlock_device(ps->dev);
bus_rescan_devices(intf->dev.bus); retval = bus_rescan_devices(intf->dev.bus);
usb_lock_device(ps->dev); usb_lock_device(ps->dev);
break; break;
...@@ -1413,7 +1423,7 @@ static int proc_ioctl_compat(struct dev_state *ps, compat_uptr_t arg) ...@@ -1413,7 +1423,7 @@ static int proc_ioctl_compat(struct dev_state *ps, compat_uptr_t arg)
*/ */
static int usbdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) static int usbdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{ {
struct dev_state *ps = (struct dev_state *)file->private_data; struct dev_state *ps = file->private_data;
struct usb_device *dev = ps->dev; struct usb_device *dev = ps->dev;
void __user *p = (void __user *)arg; void __user *p = (void __user *)arg;
int ret = -ENOTTY; int ret = -ENOTTY;
...@@ -1421,7 +1431,7 @@ static int usbdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd ...@@ -1421,7 +1431,7 @@ static int usbdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
if (!(file->f_mode & FMODE_WRITE)) if (!(file->f_mode & FMODE_WRITE))
return -EPERM; return -EPERM;
usb_lock_device(dev); usb_lock_device(dev);
if (!connected(dev)) { if (!connected(ps)) {
usb_unlock_device(dev); usb_unlock_device(dev);
return -ENODEV; return -ENODEV;
} }
...@@ -1556,18 +1566,18 @@ static int usbdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd ...@@ -1556,18 +1566,18 @@ static int usbdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
/* No kernel lock - fine */ /* No kernel lock - fine */
static unsigned int usbdev_poll(struct file *file, struct poll_table_struct *wait) static unsigned int usbdev_poll(struct file *file, struct poll_table_struct *wait)
{ {
struct dev_state *ps = (struct dev_state *)file->private_data; struct dev_state *ps = file->private_data;
unsigned int mask = 0; unsigned int mask = 0;
poll_wait(file, &ps->wait, wait); poll_wait(file, &ps->wait, wait);
if (file->f_mode & FMODE_WRITE && !list_empty(&ps->async_completed)) if (file->f_mode & FMODE_WRITE && !list_empty(&ps->async_completed))
mask |= POLLOUT | POLLWRNORM; mask |= POLLOUT | POLLWRNORM;
if (!connected(ps->dev)) if (!connected(ps))
mask |= POLLERR | POLLHUP; mask |= POLLERR | POLLHUP;
return mask; return mask;
} }
struct file_operations usbfs_device_file_operations = { const struct file_operations usbfs_device_file_operations = {
.llseek = usbdev_lseek, .llseek = usbdev_lseek,
.read = usbdev_read, .read = usbdev_read,
.poll = usbdev_poll, .poll = usbdev_poll,
......
此差异已折叠。
...@@ -207,9 +207,9 @@ static void ep_device_release(struct device *dev) ...@@ -207,9 +207,9 @@ static void ep_device_release(struct device *dev)
kfree(ep_dev); kfree(ep_dev);
} }
void usb_create_ep_files(struct device *parent, int usb_create_ep_files(struct device *parent,
struct usb_host_endpoint *endpoint, struct usb_host_endpoint *endpoint,
struct usb_device *udev) struct usb_device *udev)
{ {
char name[8]; char name[8];
struct ep_device *ep_dev; struct ep_device *ep_dev;
...@@ -242,19 +242,33 @@ void usb_create_ep_files(struct device *parent, ...@@ -242,19 +242,33 @@ void usb_create_ep_files(struct device *parent,
retval = device_register(&ep_dev->dev); retval = device_register(&ep_dev->dev);
if (retval) if (retval)
goto error; goto error;
sysfs_create_group(&ep_dev->dev.kobj, &ep_dev_attr_grp); retval = sysfs_create_group(&ep_dev->dev.kobj, &ep_dev_attr_grp);
if (retval)
goto error_group;
endpoint->ep_dev = ep_dev; endpoint->ep_dev = ep_dev;
/* create the symlink to the old-style "ep_XX" directory */ /* create the symlink to the old-style "ep_XX" directory */
sprintf(name, "ep_%02x", endpoint->desc.bEndpointAddress); sprintf(name, "ep_%02x", endpoint->desc.bEndpointAddress);
sysfs_create_link(&parent->kobj, &endpoint->ep_dev->dev.kobj, name); retval = sysfs_create_link(&parent->kobj,
&endpoint->ep_dev->dev.kobj, name);
if (retval)
goto error_link;
exit: exit:
return; return retval;
error_link:
sysfs_remove_group(&ep_dev->dev.kobj, &ep_dev_attr_grp);
error_group:
device_unregister(&ep_dev->dev);
endpoint->ep_dev = NULL;
destroy_endpoint_class();
return retval;
error: error:
kfree(ep_dev); kfree(ep_dev);
return; destroy_endpoint_class();
return retval;
} }
void usb_remove_ep_files(struct usb_host_endpoint *endpoint) void usb_remove_ep_files(struct usb_host_endpoint *endpoint)
......
...@@ -55,7 +55,7 @@ static int usb_open(struct inode * inode, struct file * file) ...@@ -55,7 +55,7 @@ static int usb_open(struct inode * inode, struct file * file)
return err; return err;
} }
static struct file_operations usb_fops = { static const struct file_operations usb_fops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.open = usb_open, .open = usb_open,
}; };
......
/*
* drivers/usb/generic.c - generic driver for USB devices (not interfaces)
*
* (C) Copyright 2005 Greg Kroah-Hartman <gregkh@suse.de>
*
* based on drivers/usb/usb.c which had the following copyrights:
* (C) Copyright Linus Torvalds 1999
* (C) Copyright Johannes Erdfelt 1999-2001
* (C) Copyright Andreas Gal 1999
* (C) Copyright Gregory P. Smith 1999
* (C) Copyright Deti Fliegl 1999 (new USB architecture)
* (C) Copyright Randy Dunlap 2000
* (C) Copyright David Brownell 2000-2004
* (C) Copyright Yggdrasil Computing, Inc. 2000
* (usb_device_id matching changes by Adam J. Richter)
* (C) Copyright Greg Kroah-Hartman 2002-2003
*
*/
#include <linux/config.h>
#include <linux/usb.h>
#include "usb.h"
static inline const char *plural(int n)
{
return (n == 1 ? "" : "s");
}
static int choose_configuration(struct usb_device *udev)
{
int i;
int num_configs;
int insufficient_power = 0;
struct usb_host_config *c, *best;
best = NULL;
c = udev->config;
num_configs = udev->descriptor.bNumConfigurations;
for (i = 0; i < num_configs; (i++, c++)) {
struct usb_interface_descriptor *desc = NULL;
/* It's possible that a config has no interfaces! */
if (c->desc.bNumInterfaces > 0)
desc = &c->intf_cache[0]->altsetting->desc;
/*
* HP's USB bus-powered keyboard has only one configuration
* and it claims to be self-powered; other devices may have
* similar errors in their descriptors. If the next test
* were allowed to execute, such configurations would always
* be rejected and the devices would not work as expected.
* In the meantime, we run the risk of selecting a config
* that requires external power at a time when that power
* isn't available. It seems to be the lesser of two evils.
*
* Bugzilla #6448 reports a device that appears to crash
* when it receives a GET_DEVICE_STATUS request! We don't
* have any other way to tell whether a device is self-powered,
* but since we don't use that information anywhere but here,
* the call has been removed.
*
* Maybe the GET_DEVICE_STATUS call and the test below can
* be reinstated when device firmwares become more reliable.
* Don't hold your breath.
*/
#if 0
/* Rule out self-powered configs for a bus-powered device */
if (bus_powered && (c->desc.bmAttributes &
USB_CONFIG_ATT_SELFPOWER))
continue;
#endif
/*
* The next test may not be as effective as it should be.
* Some hubs have errors in their descriptor, claiming
* to be self-powered when they are really bus-powered.
* We will overestimate the amount of current such hubs
* make available for each port.
*
* This is a fairly benign sort of failure. It won't
* cause us to reject configurations that we should have
* accepted.
*/
/* Rule out configs that draw too much bus current */
if (c->desc.bMaxPower * 2 > udev->bus_mA) {
insufficient_power++;
continue;
}
/* If the first config's first interface is COMM/2/0xff
* (MSFT RNDIS), rule it out unless Linux has host-side
* RNDIS support. */
if (i == 0 && desc
&& desc->bInterfaceClass == USB_CLASS_COMM
&& desc->bInterfaceSubClass == 2
&& desc->bInterfaceProtocol == 0xff) {
#ifndef CONFIG_USB_NET_RNDIS_HOST
continue;
#else
best = c;
#endif
}
/* From the remaining configs, choose the first one whose
* first interface is for a non-vendor-specific class.
* Reason: Linux is more likely to have a class driver
* than a vendor-specific driver. */
else if (udev->descriptor.bDeviceClass !=
USB_CLASS_VENDOR_SPEC &&
(!desc || desc->bInterfaceClass !=
USB_CLASS_VENDOR_SPEC)) {
best = c;
break;
}
/* If all the remaining configs are vendor-specific,
* choose the first one. */
else if (!best)
best = c;
}
if (insufficient_power > 0)
dev_info(&udev->dev, "rejected %d configuration%s "
"due to insufficient available bus power\n",
insufficient_power, plural(insufficient_power));
if (best) {
i = best->desc.bConfigurationValue;
dev_info(&udev->dev,
"configuration #%d chosen from %d choice%s\n",
i, num_configs, plural(num_configs));
} else {
i = -1;
dev_warn(&udev->dev,
"no configuration chosen from %d choice%s\n",
num_configs, plural(num_configs));
}
return i;
}
static int generic_probe(struct usb_device *udev)
{
int err, c;
/* put device-specific files into sysfs */
usb_create_sysfs_dev_files(udev);
/* Choose and set the configuration. This registers the interfaces
* with the driver core and lets interface drivers bind to them.
*/
c = choose_configuration(udev);
if (c >= 0) {
err = usb_set_configuration(udev, c);
if (err) {
dev_err(&udev->dev, "can't set config #%d, error %d\n",
c, err);
/* This need not be fatal. The user can try to
* set other configurations. */
}
}
/* USB device state == configured ... usable */
usb_notify_add_device(udev);
return 0;
}
static void generic_disconnect(struct usb_device *udev)
{
usb_notify_remove_device(udev);
/* if this is only an unbind, not a physical disconnect, then
* unconfigure the device */
if (udev->actconfig)
usb_set_configuration(udev, 0);
usb_remove_sysfs_dev_files(udev);
}
#ifdef CONFIG_PM
static int generic_suspend(struct usb_device *udev, pm_message_t msg)
{
/* USB devices enter SUSPEND state through their hubs, but can be
* marked for FREEZE as soon as their children are already idled.
* But those semantics are useless, so we equate the two (sigh).
*/
return usb_port_suspend(udev);
}
static int generic_resume(struct usb_device *udev)
{
return usb_port_resume(udev);
}
#endif /* CONFIG_PM */
struct usb_device_driver usb_generic_driver = {
.name = "usb",
.probe = generic_probe,
.disconnect = generic_disconnect,
#ifdef CONFIG_PM
.suspend = generic_suspend,
.resume = generic_resume,
#endif
.supports_autosuspend = 1,
};
...@@ -413,4 +413,20 @@ EXPORT_SYMBOL (usb_hcd_pci_resume); ...@@ -413,4 +413,20 @@ EXPORT_SYMBOL (usb_hcd_pci_resume);
#endif /* CONFIG_PM */ #endif /* CONFIG_PM */
/**
* usb_hcd_pci_shutdown - shutdown host controller
* @dev: USB Host Controller being shutdown
*/
void usb_hcd_pci_shutdown (struct pci_dev *dev)
{
struct usb_hcd *hcd;
hcd = pci_get_drvdata(dev);
if (!hcd)
return;
if (hcd->driver->shutdown)
hcd->driver->shutdown(hcd);
}
EXPORT_SYMBOL (usb_hcd_pci_shutdown);
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
#include <linux/mutex.h> #include <linux/mutex.h>
#include <asm/irq.h> #include <asm/irq.h>
#include <asm/byteorder.h> #include <asm/byteorder.h>
#include <linux/platform_device.h>
#include <linux/usb.h> #include <linux/usb.h>
...@@ -632,31 +633,20 @@ static int rh_urb_enqueue (struct usb_hcd *hcd, struct urb *urb) ...@@ -632,31 +633,20 @@ static int rh_urb_enqueue (struct usb_hcd *hcd, struct urb *urb)
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
/* Asynchronous unlinks of root-hub control URBs are legal, but they /* Unlinks of root-hub control URBs are legal, but they don't do anything
* don't do anything. Status URB unlinks must be made in process context * since these URBs always execute synchronously.
* with interrupts enabled.
*/ */
static int usb_rh_urb_dequeue (struct usb_hcd *hcd, struct urb *urb) static int usb_rh_urb_dequeue (struct usb_hcd *hcd, struct urb *urb)
{ {
if (usb_pipeendpoint(urb->pipe) == 0) { /* Control URB */ unsigned long flags;
if (in_interrupt())
return 0; /* nothing to do */
spin_lock_irq(&urb->lock); /* from usb_kill_urb */
++urb->reject;
spin_unlock_irq(&urb->lock);
wait_event(usb_kill_urb_queue,
atomic_read(&urb->use_count) == 0);
spin_lock_irq(&urb->lock); if (usb_pipeendpoint(urb->pipe) == 0) { /* Control URB */
--urb->reject; ; /* Do nothing */
spin_unlock_irq(&urb->lock);
} else { /* Status URB */ } else { /* Status URB */
if (!hcd->uses_new_polling) if (!hcd->uses_new_polling)
del_timer_sync (&hcd->rh_timer); del_timer (&hcd->rh_timer);
local_irq_disable (); local_irq_save (flags);
spin_lock (&hcd_root_hub_lock); spin_lock (&hcd_root_hub_lock);
if (urb == hcd->status_urb) { if (urb == hcd->status_urb) {
hcd->status_urb = NULL; hcd->status_urb = NULL;
...@@ -666,7 +656,7 @@ static int usb_rh_urb_dequeue (struct usb_hcd *hcd, struct urb *urb) ...@@ -666,7 +656,7 @@ static int usb_rh_urb_dequeue (struct usb_hcd *hcd, struct urb *urb)
spin_unlock (&hcd_root_hub_lock); spin_unlock (&hcd_root_hub_lock);
if (urb) if (urb)
usb_hcd_giveback_urb (hcd, urb, NULL); usb_hcd_giveback_urb (hcd, urb, NULL);
local_irq_enable (); local_irq_restore (flags);
} }
return 0; return 0;
...@@ -674,31 +664,6 @@ static int usb_rh_urb_dequeue (struct usb_hcd *hcd, struct urb *urb) ...@@ -674,31 +664,6 @@ static int usb_rh_urb_dequeue (struct usb_hcd *hcd, struct urb *urb)
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
/* exported only within usbcore */
struct usb_bus *usb_bus_get(struct usb_bus *bus)
{
if (bus)
kref_get(&bus->kref);
return bus;
}
static void usb_host_release(struct kref *kref)
{
struct usb_bus *bus = container_of(kref, struct usb_bus, kref);
if (bus->release)
bus->release(bus);
}
/* exported only within usbcore */
void usb_bus_put(struct usb_bus *bus)
{
if (bus)
kref_put(&bus->kref, usb_host_release);
}
/*-------------------------------------------------------------------------*/
static struct class *usb_host_class; static struct class *usb_host_class;
int usb_host_init(void) int usb_host_init(void)
...@@ -730,39 +695,12 @@ static void usb_bus_init (struct usb_bus *bus) ...@@ -730,39 +695,12 @@ static void usb_bus_init (struct usb_bus *bus)
bus->devnum_next = 1; bus->devnum_next = 1;
bus->root_hub = NULL; bus->root_hub = NULL;
bus->hcpriv = NULL;
bus->busnum = -1; bus->busnum = -1;
bus->bandwidth_allocated = 0; bus->bandwidth_allocated = 0;
bus->bandwidth_int_reqs = 0; bus->bandwidth_int_reqs = 0;
bus->bandwidth_isoc_reqs = 0; bus->bandwidth_isoc_reqs = 0;
INIT_LIST_HEAD (&bus->bus_list); INIT_LIST_HEAD (&bus->bus_list);
kref_init(&bus->kref);
}
/**
* usb_alloc_bus - creates a new USB host controller structure
* @op: pointer to a struct usb_operations that this bus structure should use
* Context: !in_interrupt()
*
* Creates a USB host controller bus structure with the specified
* usb_operations and initializes all the necessary internal objects.
*
* If no memory is available, NULL is returned.
*
* The caller should call usb_put_bus() when it is finished with the structure.
*/
struct usb_bus *usb_alloc_bus (struct usb_operations *op)
{
struct usb_bus *bus;
bus = kzalloc (sizeof *bus, GFP_KERNEL);
if (!bus)
return NULL;
usb_bus_init (bus);
bus->op = op;
return bus;
} }
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
...@@ -1112,10 +1050,10 @@ static void urb_unlink (struct urb *urb) ...@@ -1112,10 +1050,10 @@ static void urb_unlink (struct urb *urb)
* expects usb_submit_urb() to have sanity checked and conditioned all * expects usb_submit_urb() to have sanity checked and conditioned all
* inputs in the urb * inputs in the urb
*/ */
static int hcd_submit_urb (struct urb *urb, gfp_t mem_flags) int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags)
{ {
int status; int status;
struct usb_hcd *hcd = urb->dev->bus->hcpriv; struct usb_hcd *hcd = bus_to_hcd(urb->dev->bus);
struct usb_host_endpoint *ep; struct usb_host_endpoint *ep;
unsigned long flags; unsigned long flags;
...@@ -1186,7 +1124,7 @@ static int hcd_submit_urb (struct urb *urb, gfp_t mem_flags) ...@@ -1186,7 +1124,7 @@ static int hcd_submit_urb (struct urb *urb, gfp_t mem_flags)
/* lower level hcd code should use *_dma exclusively, /* lower level hcd code should use *_dma exclusively,
* unless it uses pio or talks to another transport. * unless it uses pio or talks to another transport.
*/ */
if (hcd->self.controller->dma_mask) { if (hcd->self.uses_dma) {
if (usb_pipecontrol (urb->pipe) if (usb_pipecontrol (urb->pipe)
&& !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP)) && !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP))
urb->setup_dma = dma_map_single ( urb->setup_dma = dma_map_single (
...@@ -1221,9 +1159,10 @@ static int hcd_submit_urb (struct urb *urb, gfp_t mem_flags) ...@@ -1221,9 +1159,10 @@ static int hcd_submit_urb (struct urb *urb, gfp_t mem_flags)
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
/* called in any context */ /* called in any context */
static int hcd_get_frame_number (struct usb_device *udev) int usb_hcd_get_frame_number (struct usb_device *udev)
{ {
struct usb_hcd *hcd = (struct usb_hcd *)udev->bus->hcpriv; struct usb_hcd *hcd = bus_to_hcd(udev->bus);
if (!HC_IS_RUNNING (hcd->state)) if (!HC_IS_RUNNING (hcd->state))
return -ESHUTDOWN; return -ESHUTDOWN;
return hcd->driver->get_frame_number (hcd); return hcd->driver->get_frame_number (hcd);
...@@ -1263,7 +1202,7 @@ unlink1 (struct usb_hcd *hcd, struct urb *urb) ...@@ -1263,7 +1202,7 @@ unlink1 (struct usb_hcd *hcd, struct urb *urb)
* caller guarantees urb won't be recycled till both unlink() * caller guarantees urb won't be recycled till both unlink()
* and the urb's completion function return * and the urb's completion function return
*/ */
static int hcd_unlink_urb (struct urb *urb, int status) int usb_hcd_unlink_urb (struct urb *urb, int status)
{ {
struct usb_host_endpoint *ep; struct usb_host_endpoint *ep;
struct usb_hcd *hcd = NULL; struct usb_hcd *hcd = NULL;
...@@ -1296,7 +1235,7 @@ static int hcd_unlink_urb (struct urb *urb, int status) ...@@ -1296,7 +1235,7 @@ static int hcd_unlink_urb (struct urb *urb, int status)
spin_lock (&hcd_data_lock); spin_lock (&hcd_data_lock);
sys = &urb->dev->dev; sys = &urb->dev->dev;
hcd = urb->dev->bus->hcpriv; hcd = bus_to_hcd(urb->dev->bus);
if (hcd == NULL) { if (hcd == NULL) {
retval = -ENODEV; retval = -ENODEV;
goto done; goto done;
...@@ -1354,41 +1293,33 @@ static int hcd_unlink_urb (struct urb *urb, int status) ...@@ -1354,41 +1293,33 @@ static int hcd_unlink_urb (struct urb *urb, int status)
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
/* disables the endpoint: cancels any pending urbs, then synchronizes with /* disables the endpoint: cancels any pending urbs, then synchronizes with
* the hcd to make sure all endpoint state is gone from hardware. use for * the hcd to make sure all endpoint state is gone from hardware, and then
* waits until the endpoint's queue is completely drained. use for
* set_configuration, set_interface, driver removal, physical disconnect. * set_configuration, set_interface, driver removal, physical disconnect.
* *
* example: a qh stored in ep->hcpriv, holding state related to endpoint * example: a qh stored in ep->hcpriv, holding state related to endpoint
* type, maxpacket size, toggle, halt status, and scheduling. * type, maxpacket size, toggle, halt status, and scheduling.
*/ */
static void void usb_hcd_endpoint_disable (struct usb_device *udev,
hcd_endpoint_disable (struct usb_device *udev, struct usb_host_endpoint *ep) struct usb_host_endpoint *ep)
{ {
struct usb_hcd *hcd; struct usb_hcd *hcd;
struct urb *urb; struct urb *urb;
hcd = udev->bus->hcpriv; hcd = bus_to_hcd(udev->bus);
WARN_ON (!HC_IS_RUNNING (hcd->state) && hcd->state != HC_STATE_HALT && WARN_ON (!HC_IS_RUNNING (hcd->state) && hcd->state != HC_STATE_HALT &&
udev->state != USB_STATE_NOTATTACHED); udev->state != USB_STATE_NOTATTACHED);
local_irq_disable (); local_irq_disable ();
/* FIXME move most of this into message.c as part of its
* endpoint disable logic
*/
/* ep is already gone from udev->ep_{in,out}[]; no more submits */ /* ep is already gone from udev->ep_{in,out}[]; no more submits */
rescan: rescan:
spin_lock (&hcd_data_lock); spin_lock (&hcd_data_lock);
list_for_each_entry (urb, &ep->urb_list, urb_list) { list_for_each_entry (urb, &ep->urb_list, urb_list) {
int tmp; int tmp;
/* another cpu may be in hcd, spinning on hcd_data_lock /* the urb may already have been unlinked */
* to giveback() this urb. the races here should be
* small, but a full fix needs a new "can't submit"
* urb state.
* FIXME urb->reject should allow that...
*/
if (urb->status != -EINPROGRESS) if (urb->status != -EINPROGRESS)
continue; continue;
usb_get_urb (urb); usb_get_urb (urb);
...@@ -1430,6 +1361,30 @@ hcd_endpoint_disable (struct usb_device *udev, struct usb_host_endpoint *ep) ...@@ -1430,6 +1361,30 @@ hcd_endpoint_disable (struct usb_device *udev, struct usb_host_endpoint *ep)
might_sleep (); might_sleep ();
if (hcd->driver->endpoint_disable) if (hcd->driver->endpoint_disable)
hcd->driver->endpoint_disable (hcd, ep); hcd->driver->endpoint_disable (hcd, ep);
/* Wait until the endpoint queue is completely empty. Most HCDs
* will have done this already in their endpoint_disable method,
* but some might not. And there could be root-hub control URBs
* still pending since they aren't affected by the HCDs'
* endpoint_disable methods.
*/
while (!list_empty (&ep->urb_list)) {
spin_lock_irq (&hcd_data_lock);
/* The list may have changed while we acquired the spinlock */
urb = NULL;
if (!list_empty (&ep->urb_list)) {
urb = list_entry (ep->urb_list.prev, struct urb,
urb_list);
usb_get_urb (urb);
}
spin_unlock_irq (&hcd_data_lock);
if (urb) {
usb_kill_urb (urb);
usb_put_urb (urb);
}
}
} }
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
...@@ -1476,50 +1431,6 @@ int hcd_bus_resume (struct usb_bus *bus) ...@@ -1476,50 +1431,6 @@ int hcd_bus_resume (struct usb_bus *bus)
return status; return status;
} }
/*
* usb_hcd_suspend_root_hub - HCD autosuspends downstream ports
* @hcd: host controller for this root hub
*
* This call arranges that usb_hcd_resume_root_hub() is safe to call later;
* that the HCD's root hub polling is deactivated; and that the root's hub
* driver is suspended. HCDs may call this to autosuspend when their root
* hub's downstream ports are all inactive: unpowered, disconnected,
* disabled, or suspended.
*
* The HCD will autoresume on device connect change detection (using SRP
* or a D+/D- pullup). The HCD also autoresumes on remote wakeup signaling
* from any ports that are suspended (if that is enabled). In most cases,
* overcurrent signaling (on powered ports) will also start autoresume.
*
* Always called with IRQs blocked.
*/
void usb_hcd_suspend_root_hub (struct usb_hcd *hcd)
{
struct urb *urb;
spin_lock (&hcd_root_hub_lock);
usb_suspend_root_hub (hcd->self.root_hub);
/* force status urb to complete/unlink while suspended */
if (hcd->status_urb) {
urb = hcd->status_urb;
urb->status = -ECONNRESET;
urb->hcpriv = NULL;
urb->actual_length = 0;
del_timer (&hcd->rh_timer);
hcd->poll_pending = 0;
hcd->status_urb = NULL;
} else
urb = NULL;
spin_unlock (&hcd_root_hub_lock);
hcd->state = HC_STATE_SUSPENDED;
if (urb)
usb_hcd_giveback_urb (hcd, urb, NULL);
}
EXPORT_SYMBOL_GPL(usb_hcd_suspend_root_hub);
/** /**
* usb_hcd_resume_root_hub - called by HCD to resume its root hub * usb_hcd_resume_root_hub - called by HCD to resume its root hub
* @hcd: host controller for this root hub * @hcd: host controller for this root hub
...@@ -1583,20 +1494,6 @@ EXPORT_SYMBOL (usb_bus_start_enum); ...@@ -1583,20 +1494,6 @@ EXPORT_SYMBOL (usb_bus_start_enum);
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
/*
* usb_hcd_operations - adapts usb_bus framework to HCD framework (bus glue)
*/
static struct usb_operations usb_hcd_operations = {
.get_frame_number = hcd_get_frame_number,
.submit_urb = hcd_submit_urb,
.unlink_urb = hcd_unlink_urb,
.buffer_alloc = hcd_buffer_alloc,
.buffer_free = hcd_buffer_free,
.disable = hcd_endpoint_disable,
};
/*-------------------------------------------------------------------------*/
/** /**
* usb_hcd_giveback_urb - return URB from HCD to device driver * usb_hcd_giveback_urb - return URB from HCD to device driver
* @hcd: host controller returning the URB * @hcd: host controller returning the URB
...@@ -1617,8 +1514,9 @@ void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb, struct pt_regs ...@@ -1617,8 +1514,9 @@ void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb, struct pt_regs
at_root_hub = (urb->dev == hcd->self.root_hub); at_root_hub = (urb->dev == hcd->self.root_hub);
urb_unlink (urb); urb_unlink (urb);
/* lower level hcd code should use *_dma exclusively */ /* lower level hcd code should use *_dma exclusively if the
if (hcd->self.controller->dma_mask && !at_root_hub) { * host controller does DMA */
if (hcd->self.uses_dma && !at_root_hub) {
if (usb_pipecontrol (urb->pipe) if (usb_pipecontrol (urb->pipe)
&& !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP)) && !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP))
dma_unmap_single (hcd->self.controller, urb->setup_dma, dma_unmap_single (hcd->self.controller, urb->setup_dma,
...@@ -1704,14 +1602,6 @@ EXPORT_SYMBOL_GPL (usb_hc_died); ...@@ -1704,14 +1602,6 @@ EXPORT_SYMBOL_GPL (usb_hc_died);
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
static void hcd_release (struct usb_bus *bus)
{
struct usb_hcd *hcd;
hcd = container_of(bus, struct usb_hcd, self);
kfree(hcd);
}
/** /**
* usb_create_hcd - create and initialize an HCD structure * usb_create_hcd - create and initialize an HCD structure
* @driver: HC driver that will use this hcd * @driver: HC driver that will use this hcd
...@@ -1736,13 +1626,12 @@ struct usb_hcd *usb_create_hcd (const struct hc_driver *driver, ...@@ -1736,13 +1626,12 @@ struct usb_hcd *usb_create_hcd (const struct hc_driver *driver,
return NULL; return NULL;
} }
dev_set_drvdata(dev, hcd); dev_set_drvdata(dev, hcd);
kref_init(&hcd->kref);
usb_bus_init(&hcd->self); usb_bus_init(&hcd->self);
hcd->self.op = &usb_hcd_operations;
hcd->self.hcpriv = hcd;
hcd->self.release = &hcd_release;
hcd->self.controller = dev; hcd->self.controller = dev;
hcd->self.bus_name = bus_name; hcd->self.bus_name = bus_name;
hcd->self.uses_dma = (dev->dma_mask != NULL);
init_timer(&hcd->rh_timer); init_timer(&hcd->rh_timer);
hcd->rh_timer.function = rh_timer_func; hcd->rh_timer.function = rh_timer_func;
...@@ -1756,10 +1645,25 @@ struct usb_hcd *usb_create_hcd (const struct hc_driver *driver, ...@@ -1756,10 +1645,25 @@ struct usb_hcd *usb_create_hcd (const struct hc_driver *driver,
} }
EXPORT_SYMBOL (usb_create_hcd); EXPORT_SYMBOL (usb_create_hcd);
static void hcd_release (struct kref *kref)
{
struct usb_hcd *hcd = container_of (kref, struct usb_hcd, kref);
kfree(hcd);
}
struct usb_hcd *usb_get_hcd (struct usb_hcd *hcd)
{
if (hcd)
kref_get (&hcd->kref);
return hcd;
}
EXPORT_SYMBOL (usb_get_hcd);
void usb_put_hcd (struct usb_hcd *hcd) void usb_put_hcd (struct usb_hcd *hcd)
{ {
dev_set_drvdata(hcd->self.controller, NULL); if (hcd)
usb_bus_put(&hcd->self); kref_put (&hcd->kref, hcd_release);
} }
EXPORT_SYMBOL (usb_put_hcd); EXPORT_SYMBOL (usb_put_hcd);
...@@ -1915,6 +1819,16 @@ void usb_remove_hcd(struct usb_hcd *hcd) ...@@ -1915,6 +1819,16 @@ void usb_remove_hcd(struct usb_hcd *hcd)
} }
EXPORT_SYMBOL (usb_remove_hcd); EXPORT_SYMBOL (usb_remove_hcd);
void
usb_hcd_platform_shutdown(struct platform_device* dev)
{
struct usb_hcd *hcd = platform_get_drvdata(dev);
if (hcd->driver->shutdown)
hcd->driver->shutdown(hcd);
}
EXPORT_SYMBOL (usb_hcd_platform_shutdown);
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
#if defined(CONFIG_USB_MON) #if defined(CONFIG_USB_MON)
......
...@@ -55,12 +55,13 @@ ...@@ -55,12 +55,13 @@
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
struct usb_hcd { /* usb_bus.hcpriv points to this */ struct usb_hcd {
/* /*
* housekeeping * housekeeping
*/ */
struct usb_bus self; /* hcd is-a bus */ struct usb_bus self; /* hcd is-a bus */
struct kref kref; /* reference counter */
const char *product_desc; /* product/vendor string */ const char *product_desc; /* product/vendor string */
char irq_descr[24]; /* driver + bus # */ char irq_descr[24]; /* driver + bus # */
...@@ -85,6 +86,7 @@ struct usb_hcd { /* usb_bus.hcpriv points to this */ ...@@ -85,6 +86,7 @@ struct usb_hcd { /* usb_bus.hcpriv points to this */
unsigned uses_new_polling:1; unsigned uses_new_polling:1;
unsigned poll_rh:1; /* poll for rh status? */ unsigned poll_rh:1; /* poll for rh status? */
unsigned poll_pending:1; /* status has changed? */ unsigned poll_pending:1; /* status has changed? */
unsigned wireless:1; /* Wireless USB HCD */
int irq; /* irq allocated */ int irq; /* irq allocated */
void __iomem *regs; /* device memory/io */ void __iomem *regs; /* device memory/io */
...@@ -128,8 +130,10 @@ static inline struct usb_bus *hcd_to_bus (struct usb_hcd *hcd) ...@@ -128,8 +130,10 @@ static inline struct usb_bus *hcd_to_bus (struct usb_hcd *hcd)
return &hcd->self; return &hcd->self;
} }
static inline struct usb_hcd *bus_to_hcd (struct usb_bus *bus)
// urb.hcpriv is really hardware-specific {
return container_of(bus, struct usb_hcd, self);
}
struct hcd_timeout { /* timeouts we allocate */ struct hcd_timeout { /* timeouts we allocate */
struct list_head timeout_list; struct list_head timeout_list;
...@@ -138,28 +142,6 @@ struct hcd_timeout { /* timeouts we allocate */ ...@@ -138,28 +142,6 @@ struct hcd_timeout { /* timeouts we allocate */
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
/*
* FIXME usb_operations should vanish or become hc_driver,
* when usb_bus and usb_hcd become the same thing.
*/
struct usb_operations {
int (*get_frame_number) (struct usb_device *usb_dev);
int (*submit_urb) (struct urb *urb, gfp_t mem_flags);
int (*unlink_urb) (struct urb *urb, int status);
/* allocate dma-consistent buffer for URB_DMA_NOMAPPING */
void *(*buffer_alloc)(struct usb_bus *bus, size_t size,
gfp_t mem_flags,
dma_addr_t *dma);
void (*buffer_free)(struct usb_bus *bus, size_t size,
void *addr, dma_addr_t dma);
void (*disable)(struct usb_device *udev,
struct usb_host_endpoint *ep);
};
/* each driver provides one of these, and hardware init support */
struct pt_regs; struct pt_regs;
...@@ -192,6 +174,9 @@ struct hc_driver { ...@@ -192,6 +174,9 @@ struct hc_driver {
/* cleanly make HCD stop writing memory and doing I/O */ /* cleanly make HCD stop writing memory and doing I/O */
void (*stop) (struct usb_hcd *hcd); void (*stop) (struct usb_hcd *hcd);
/* shutdown HCD */
void (*shutdown) (struct usb_hcd *hcd);
/* return current frame number */ /* return current frame number */
int (*get_frame_number) (struct usb_hcd *hcd); int (*get_frame_number) (struct usb_hcd *hcd);
...@@ -218,15 +203,25 @@ struct hc_driver { ...@@ -218,15 +203,25 @@ struct hc_driver {
/* Needed only if port-change IRQs are level-triggered */ /* Needed only if port-change IRQs are level-triggered */
}; };
extern void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb, struct pt_regs *regs); extern int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags);
extern int usb_hcd_unlink_urb (struct urb *urb, int status);
extern void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb,
struct pt_regs *regs);
extern void usb_hcd_endpoint_disable (struct usb_device *udev,
struct usb_host_endpoint *ep);
extern int usb_hcd_get_frame_number (struct usb_device *udev);
extern struct usb_hcd *usb_create_hcd (const struct hc_driver *driver, extern struct usb_hcd *usb_create_hcd (const struct hc_driver *driver,
struct device *dev, char *bus_name); struct device *dev, char *bus_name);
extern struct usb_hcd *usb_get_hcd (struct usb_hcd *hcd);
extern void usb_put_hcd (struct usb_hcd *hcd); extern void usb_put_hcd (struct usb_hcd *hcd);
extern int usb_add_hcd(struct usb_hcd *hcd, extern int usb_add_hcd(struct usb_hcd *hcd,
unsigned int irqnum, unsigned long irqflags); unsigned int irqnum, unsigned long irqflags);
extern void usb_remove_hcd(struct usb_hcd *hcd); extern void usb_remove_hcd(struct usb_hcd *hcd);
struct platform_device;
extern void usb_hcd_platform_shutdown(struct platform_device* dev);
#ifdef CONFIG_PCI #ifdef CONFIG_PCI
struct pci_dev; struct pci_dev;
struct pci_device_id; struct pci_device_id;
...@@ -239,6 +234,8 @@ extern int usb_hcd_pci_suspend (struct pci_dev *dev, pm_message_t state); ...@@ -239,6 +234,8 @@ extern int usb_hcd_pci_suspend (struct pci_dev *dev, pm_message_t state);
extern int usb_hcd_pci_resume (struct pci_dev *dev); extern int usb_hcd_pci_resume (struct pci_dev *dev);
#endif /* CONFIG_PM */ #endif /* CONFIG_PM */
extern void usb_hcd_pci_shutdown (struct pci_dev *dev);
#endif /* CONFIG_PCI */ #endif /* CONFIG_PCI */
/* pci-ish (pdev null is ok) buffer alloc/mapping support */ /* pci-ish (pdev null is ok) buffer alloc/mapping support */
...@@ -352,8 +349,6 @@ extern long usb_calc_bus_time (int speed, int is_input, ...@@ -352,8 +349,6 @@ extern long usb_calc_bus_time (int speed, int is_input,
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
extern struct usb_bus *usb_alloc_bus (struct usb_operations *);
extern void usb_set_device_state(struct usb_device *udev, extern void usb_set_device_state(struct usb_device *udev,
enum usb_device_state new_state); enum usb_device_state new_state);
...@@ -365,9 +360,6 @@ extern struct list_head usb_bus_list; ...@@ -365,9 +360,6 @@ extern struct list_head usb_bus_list;
extern struct mutex usb_bus_list_lock; extern struct mutex usb_bus_list_lock;
extern wait_queue_head_t usb_kill_urb_queue; extern wait_queue_head_t usb_kill_urb_queue;
extern struct usb_bus *usb_bus_get (struct usb_bus *bus);
extern void usb_bus_put (struct usb_bus *bus);
extern void usb_enable_root_hub_irq (struct usb_bus *bus); extern void usb_enable_root_hub_irq (struct usb_bus *bus);
extern int usb_find_interface_driver (struct usb_device *dev, extern int usb_find_interface_driver (struct usb_device *dev,
...@@ -376,17 +368,11 @@ extern int usb_find_interface_driver (struct usb_device *dev, ...@@ -376,17 +368,11 @@ extern int usb_find_interface_driver (struct usb_device *dev,
#define usb_endpoint_out(ep_dir) (!((ep_dir) & USB_DIR_IN)) #define usb_endpoint_out(ep_dir) (!((ep_dir) & USB_DIR_IN))
#ifdef CONFIG_PM #ifdef CONFIG_PM
extern void usb_hcd_suspend_root_hub (struct usb_hcd *hcd);
extern void usb_hcd_resume_root_hub (struct usb_hcd *hcd); extern void usb_hcd_resume_root_hub (struct usb_hcd *hcd);
extern void usb_root_hub_lost_power (struct usb_device *rhdev); extern void usb_root_hub_lost_power (struct usb_device *rhdev);
extern int hcd_bus_suspend (struct usb_bus *bus); extern int hcd_bus_suspend (struct usb_bus *bus);
extern int hcd_bus_resume (struct usb_bus *bus); extern int hcd_bus_resume (struct usb_bus *bus);
#else #else
static inline void usb_hcd_suspend_root_hub(struct usb_hcd *hcd)
{
return;
}
static inline void usb_hcd_resume_root_hub(struct usb_hcd *hcd) static inline void usb_hcd_resume_root_hub(struct usb_hcd *hcd)
{ {
return; return;
......
此差异已折叠。
...@@ -212,7 +212,8 @@ struct usb_hub { ...@@ -212,7 +212,8 @@ struct usb_hub {
unsigned long event_bits[1]; /* status change bitmask */ unsigned long event_bits[1]; /* status change bitmask */
unsigned long change_bits[1]; /* ports with logical connect unsigned long change_bits[1]; /* ports with logical connect
status change */ status change */
unsigned long busy_bits[1]; /* ports being reset */ unsigned long busy_bits[1]; /* ports being reset or
resumed */
#if USB_MAXCHILDREN > 31 /* 8*sizeof(unsigned long) - 1 */ #if USB_MAXCHILDREN > 31 /* 8*sizeof(unsigned long) - 1 */
#error event_bits[] is too short! #error event_bits[] is too short!
#endif #endif
......
...@@ -44,7 +44,7 @@ ...@@ -44,7 +44,7 @@
#include "hcd.h" #include "hcd.h"
static struct super_operations usbfs_ops; static struct super_operations usbfs_ops;
static struct file_operations default_file_operations; static const struct file_operations default_file_operations;
static struct vfsmount *usbfs_mount; static struct vfsmount *usbfs_mount;
static int usbfs_mount_count; /* = 0 */ static int usbfs_mount_count; /* = 0 */
static int ignore_mount = 0; static int ignore_mount = 0;
...@@ -407,7 +407,7 @@ static int default_open (struct inode *inode, struct file *file) ...@@ -407,7 +407,7 @@ static int default_open (struct inode *inode, struct file *file)
return 0; return 0;
} }
static struct file_operations default_file_operations = { static const struct file_operations default_file_operations = {
.read = default_read_file, .read = default_read_file,
.write = default_write_file, .write = default_write_file,
.open = default_open, .open = default_open,
...@@ -494,7 +494,7 @@ static int fs_create_by_name (const char *name, mode_t mode, ...@@ -494,7 +494,7 @@ static int fs_create_by_name (const char *name, mode_t mode,
static struct dentry *fs_create_file (const char *name, mode_t mode, static struct dentry *fs_create_file (const char *name, mode_t mode,
struct dentry *parent, void *data, struct dentry *parent, void *data,
struct file_operations *fops, const struct file_operations *fops,
uid_t uid, gid_t gid) uid_t uid, gid_t gid)
{ {
struct dentry *dentry; struct dentry *dentry;
......
...@@ -23,59 +23,44 @@ static void usb_api_blocking_completion(struct urb *urb, struct pt_regs *regs) ...@@ -23,59 +23,44 @@ static void usb_api_blocking_completion(struct urb *urb, struct pt_regs *regs)
} }
static void timeout_kill(unsigned long data) /*
{ * Starts urb and waits for completion or timeout. Note that this call
struct urb *urb = (struct urb *) data; * is NOT interruptible. Many device driver i/o requests should be
* interruptible and therefore these drivers should implement their
usb_unlink_urb(urb); * own interruptible routines.
} */
static int usb_start_wait_urb(struct urb *urb, int timeout, int *actual_length)
// Starts urb and waits for completion or timeout
// note that this call is NOT interruptible, while
// many device driver i/o requests should be interruptible
static int usb_start_wait_urb(struct urb *urb, int timeout, int* actual_length)
{ {
struct completion done; struct completion done;
struct timer_list timer; unsigned long expire;
int status; int status;
init_completion(&done); init_completion(&done);
urb->context = &done; urb->context = &done;
urb->actual_length = 0; urb->actual_length = 0;
status = usb_submit_urb(urb, GFP_NOIO); status = usb_submit_urb(urb, GFP_NOIO);
if (unlikely(status))
if (status == 0) { goto out;
if (timeout > 0) {
init_timer(&timer); expire = timeout ? msecs_to_jiffies(timeout) : MAX_SCHEDULE_TIMEOUT;
timer.expires = jiffies + msecs_to_jiffies(timeout); if (!wait_for_completion_timeout(&done, expire)) {
timer.data = (unsigned long)urb;
timer.function = timeout_kill; dev_dbg(&urb->dev->dev,
/* grr. timeout _should_ include submit delays. */ "%s timed out on ep%d%s len=%d/%d\n",
add_timer(&timer); current->comm,
} usb_pipeendpoint(urb->pipe),
wait_for_completion(&done); usb_pipein(urb->pipe) ? "in" : "out",
urb->actual_length,
urb->transfer_buffer_length);
usb_kill_urb(urb);
status = urb->status == -ENOENT ? -ETIMEDOUT : urb->status;
} else
status = urb->status; status = urb->status;
/* note: HCDs return ETIMEDOUT for other reasons too */ out:
if (status == -ECONNRESET) {
dev_dbg(&urb->dev->dev,
"%s timed out on ep%d%s len=%d/%d\n",
current->comm,
usb_pipeendpoint(urb->pipe),
usb_pipein(urb->pipe) ? "in" : "out",
urb->actual_length,
urb->transfer_buffer_length
);
if (urb->actual_length > 0)
status = 0;
else
status = -ETIMEDOUT;
}
if (timeout > 0)
del_timer_sync(&timer);
}
if (actual_length) if (actual_length)
*actual_length = urb->actual_length; *actual_length = urb->actual_length;
usb_free_urb(urb); usb_free_urb(urb);
return status; return status;
} }
...@@ -263,7 +248,7 @@ static void sg_clean (struct usb_sg_request *io) ...@@ -263,7 +248,7 @@ static void sg_clean (struct usb_sg_request *io)
static void sg_complete (struct urb *urb, struct pt_regs *regs) static void sg_complete (struct urb *urb, struct pt_regs *regs)
{ {
struct usb_sg_request *io = (struct usb_sg_request *) urb->context; struct usb_sg_request *io = urb->context;
spin_lock (&io->lock); spin_lock (&io->lock);
...@@ -999,8 +984,8 @@ void usb_disable_endpoint(struct usb_device *dev, unsigned int epaddr) ...@@ -999,8 +984,8 @@ void usb_disable_endpoint(struct usb_device *dev, unsigned int epaddr)
ep = dev->ep_in[epnum]; ep = dev->ep_in[epnum];
dev->ep_in[epnum] = NULL; dev->ep_in[epnum] = NULL;
} }
if (ep && dev->bus && dev->bus->op && dev->bus->op->disable) if (ep && dev->bus)
dev->bus->op->disable(dev, ep); usb_hcd_endpoint_disable(dev, ep);
} }
/** /**
...@@ -1381,9 +1366,6 @@ int usb_set_configuration(struct usb_device *dev, int configuration) ...@@ -1381,9 +1366,6 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
if (cp && configuration == 0) if (cp && configuration == 0)
dev_warn(&dev->dev, "config 0 descriptor??\n"); dev_warn(&dev->dev, "config 0 descriptor??\n");
if (dev->state == USB_STATE_SUSPENDED)
return -EHOSTUNREACH;
/* Allocate memory for new interfaces before doing anything else, /* Allocate memory for new interfaces before doing anything else,
* so that if we run out then nothing will have changed. */ * so that if we run out then nothing will have changed. */
n = nintf = 0; n = nintf = 0;
...@@ -1418,6 +1400,11 @@ int usb_set_configuration(struct usb_device *dev, int configuration) ...@@ -1418,6 +1400,11 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
configuration, -i); configuration, -i);
} }
/* Wake up the device so we can send it the Set-Config request */
ret = usb_autoresume_device(dev, 1);
if (ret)
goto free_interfaces;
/* if it's already configured, clear out old state first. /* if it's already configured, clear out old state first.
* getting rid of old interfaces means unbinding their drivers. * getting rid of old interfaces means unbinding their drivers.
*/ */
...@@ -1437,6 +1424,7 @@ int usb_set_configuration(struct usb_device *dev, int configuration) ...@@ -1437,6 +1424,7 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
dev->actconfig = cp; dev->actconfig = cp;
if (!cp) { if (!cp) {
usb_set_device_state(dev, USB_STATE_ADDRESS); usb_set_device_state(dev, USB_STATE_ADDRESS);
usb_autosuspend_device(dev, 1);
goto free_interfaces; goto free_interfaces;
} }
usb_set_device_state(dev, USB_STATE_CONFIGURED); usb_set_device_state(dev, USB_STATE_CONFIGURED);
...@@ -1505,8 +1493,68 @@ int usb_set_configuration(struct usb_device *dev, int configuration) ...@@ -1505,8 +1493,68 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
usb_create_sysfs_intf_files (intf); usb_create_sysfs_intf_files (intf);
} }
usb_autosuspend_device(dev, 1);
return 0;
}
struct set_config_request {
struct usb_device *udev;
int config;
struct work_struct work;
};
/* Worker routine for usb_driver_set_configuration() */
static void driver_set_config_work(void *_req)
{
struct set_config_request *req = _req;
usb_lock_device(req->udev);
usb_set_configuration(req->udev, req->config);
usb_unlock_device(req->udev);
usb_put_dev(req->udev);
kfree(req);
}
/**
* usb_driver_set_configuration - Provide a way for drivers to change device configurations
* @udev: the device whose configuration is being updated
* @config: the configuration being chosen.
* Context: In process context, must be able to sleep
*
* Device interface drivers are not allowed to change device configurations.
* This is because changing configurations will destroy the interface the
* driver is bound to and create new ones; it would be like a floppy-disk
* driver telling the computer to replace the floppy-disk drive with a
* tape drive!
*
* Still, in certain specialized circumstances the need may arise. This
* routine gets around the normal restrictions by using a work thread to
* submit the change-config request.
*
* Returns 0 if the request was succesfully queued, error code otherwise.
* The caller has no way to know whether the queued request will eventually
* succeed.
*/
int usb_driver_set_configuration(struct usb_device *udev, int config)
{
struct set_config_request *req;
req = kmalloc(sizeof(*req), GFP_KERNEL);
if (!req)
return -ENOMEM;
req->udev = udev;
req->config = config;
INIT_WORK(&req->work, driver_set_config_work, req);
usb_get_dev(udev);
if (!schedule_work(&req->work)) {
usb_put_dev(udev);
kfree(req);
return -EINVAL;
}
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(usb_driver_set_configuration);
// synchronous request completion model // synchronous request completion model
EXPORT_SYMBOL(usb_control_msg); EXPORT_SYMBOL(usb_control_msg);
......
...@@ -50,8 +50,11 @@ void usb_notify_add_device(struct usb_device *udev) ...@@ -50,8 +50,11 @@ void usb_notify_add_device(struct usb_device *udev)
void usb_notify_remove_device(struct usb_device *udev) void usb_notify_remove_device(struct usb_device *udev)
{ {
/* Protect against simultaneous usbfs open */
mutex_lock(&usbfs_mutex);
blocking_notifier_call_chain(&usb_notifier_list, blocking_notifier_call_chain(&usb_notifier_list,
USB_DEVICE_REMOVE, udev); USB_DEVICE_REMOVE, udev);
mutex_unlock(&usbfs_mutex);
} }
void usb_notify_add_bus(struct usb_bus *ubus) void usb_notify_add_bus(struct usb_bus *ubus)
......
...@@ -60,7 +60,7 @@ static ssize_t ...@@ -60,7 +60,7 @@ static ssize_t
set_bConfigurationValue (struct device *dev, struct device_attribute *attr, set_bConfigurationValue (struct device *dev, struct device_attribute *attr,
const char *buf, size_t count) const char *buf, size_t count)
{ {
struct usb_device *udev = udev = to_usb_device (dev); struct usb_device *udev = to_usb_device (dev);
int config, value; int config, value;
if (sscanf (buf, "%u", &config) != 1 || config > 255) if (sscanf (buf, "%u", &config) != 1 || config > 255)
...@@ -186,6 +186,7 @@ usb_descriptor_attr (bMaxPacketSize0, "%d\n") ...@@ -186,6 +186,7 @@ usb_descriptor_attr (bMaxPacketSize0, "%d\n")
static struct attribute *dev_attrs[] = { static struct attribute *dev_attrs[] = {
/* current configuration's attributes */ /* current configuration's attributes */
&dev_attr_configuration.attr,
&dev_attr_bNumInterfaces.attr, &dev_attr_bNumInterfaces.attr,
&dev_attr_bConfigurationValue.attr, &dev_attr_bConfigurationValue.attr,
&dev_attr_bmAttributes.attr, &dev_attr_bmAttributes.attr,
...@@ -209,20 +210,40 @@ static struct attribute_group dev_attr_grp = { ...@@ -209,20 +210,40 @@ static struct attribute_group dev_attr_grp = {
.attrs = dev_attrs, .attrs = dev_attrs,
}; };
void usb_create_sysfs_dev_files (struct usb_device *udev) int usb_create_sysfs_dev_files(struct usb_device *udev)
{ {
struct device *dev = &udev->dev; struct device *dev = &udev->dev;
int retval;
sysfs_create_group(&dev->kobj, &dev_attr_grp); retval = sysfs_create_group(&dev->kobj, &dev_attr_grp);
if (retval)
return retval;
if (udev->manufacturer) if (udev->manufacturer) {
device_create_file (dev, &dev_attr_manufacturer); retval = device_create_file (dev, &dev_attr_manufacturer);
if (udev->product) if (retval)
device_create_file (dev, &dev_attr_product); goto error;
if (udev->serial) }
device_create_file (dev, &dev_attr_serial); if (udev->product) {
device_create_file (dev, &dev_attr_configuration); retval = device_create_file (dev, &dev_attr_product);
usb_create_ep_files(dev, &udev->ep0, udev); if (retval)
goto error;
}
if (udev->serial) {
retval = device_create_file (dev, &dev_attr_serial);
if (retval)
goto error;
}
retval = usb_create_ep_files(dev, &udev->ep0, udev);
if (retval)
goto error;
return 0;
error:
usb_remove_ep_files(&udev->ep0);
device_remove_file(dev, &dev_attr_manufacturer);
device_remove_file(dev, &dev_attr_product);
device_remove_file(dev, &dev_attr_serial);
return retval;
} }
void usb_remove_sysfs_dev_files (struct usb_device *udev) void usb_remove_sysfs_dev_files (struct usb_device *udev)
...@@ -238,7 +259,6 @@ void usb_remove_sysfs_dev_files (struct usb_device *udev) ...@@ -238,7 +259,6 @@ void usb_remove_sysfs_dev_files (struct usb_device *udev)
device_remove_file(dev, &dev_attr_product); device_remove_file(dev, &dev_attr_product);
if (udev->serial) if (udev->serial)
device_remove_file(dev, &dev_attr_serial); device_remove_file(dev, &dev_attr_serial);
device_remove_file (dev, &dev_attr_configuration);
} }
/* Interface fields */ /* Interface fields */
...@@ -340,18 +360,28 @@ static inline void usb_remove_intf_ep_files(struct usb_interface *intf) ...@@ -340,18 +360,28 @@ static inline void usb_remove_intf_ep_files(struct usb_interface *intf)
usb_remove_ep_files(&iface_desc->endpoint[i]); usb_remove_ep_files(&iface_desc->endpoint[i]);
} }
void usb_create_sysfs_intf_files (struct usb_interface *intf) int usb_create_sysfs_intf_files(struct usb_interface *intf)
{ {
struct usb_device *udev = interface_to_usbdev(intf); struct usb_device *udev = interface_to_usbdev(intf);
struct usb_host_interface *alt = intf->cur_altsetting; struct usb_host_interface *alt = intf->cur_altsetting;
int retval;
sysfs_create_group(&intf->dev.kobj, &intf_attr_grp); retval = sysfs_create_group(&intf->dev.kobj, &intf_attr_grp);
if (retval)
goto error;
if (alt->string == NULL) if (alt->string == NULL)
alt->string = usb_cache_string(udev, alt->desc.iInterface); alt->string = usb_cache_string(udev, alt->desc.iInterface);
if (alt->string) if (alt->string)
device_create_file(&intf->dev, &dev_attr_interface); retval = device_create_file(&intf->dev, &dev_attr_interface);
usb_create_intf_ep_files(intf, udev); usb_create_intf_ep_files(intf, udev);
return 0;
error:
if (alt->string)
device_remove_file(&intf->dev, &dev_attr_interface);
sysfs_remove_group(&intf->dev.kobj, &intf_attr_grp);
usb_remove_intf_ep_files(intf);
return retval;
} }
void usb_remove_sysfs_intf_files (struct usb_interface *intf) void usb_remove_sysfs_intf_files (struct usb_interface *intf)
......
...@@ -57,7 +57,7 @@ struct urb *usb_alloc_urb(int iso_packets, gfp_t mem_flags) ...@@ -57,7 +57,7 @@ struct urb *usb_alloc_urb(int iso_packets, gfp_t mem_flags)
{ {
struct urb *urb; struct urb *urb;
urb = (struct urb *)kmalloc(sizeof(struct urb) + urb = kmalloc(sizeof(struct urb) +
iso_packets * sizeof(struct usb_iso_packet_descriptor), iso_packets * sizeof(struct usb_iso_packet_descriptor),
mem_flags); mem_flags);
if (!urb) { if (!urb) {
...@@ -221,7 +221,6 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags) ...@@ -221,7 +221,6 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
{ {
int pipe, temp, max; int pipe, temp, max;
struct usb_device *dev; struct usb_device *dev;
struct usb_operations *op;
int is_out; int is_out;
if (!urb || urb->hcpriv || !urb->complete) if (!urb || urb->hcpriv || !urb->complete)
...@@ -233,8 +232,6 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags) ...@@ -233,8 +232,6 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
if (dev->bus->controller->power.power_state.event != PM_EVENT_ON if (dev->bus->controller->power.power_state.event != PM_EVENT_ON
|| dev->state == USB_STATE_SUSPENDED) || dev->state == USB_STATE_SUSPENDED)
return -EHOSTUNREACH; return -EHOSTUNREACH;
if (!(op = dev->bus->op) || !op->submit_urb)
return -ENODEV;
urb->status = -EINPROGRESS; urb->status = -EINPROGRESS;
urb->actual_length = 0; urb->actual_length = 0;
...@@ -376,7 +373,7 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags) ...@@ -376,7 +373,7 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
urb->interval = temp; urb->interval = temp;
} }
return op->submit_urb (urb, mem_flags); return usb_hcd_submit_urb (urb, mem_flags);
} }
/*-------------------------------------------------------------------*/ /*-------------------------------------------------------------------*/
...@@ -440,9 +437,9 @@ int usb_unlink_urb(struct urb *urb) ...@@ -440,9 +437,9 @@ int usb_unlink_urb(struct urb *urb)
{ {
if (!urb) if (!urb)
return -EINVAL; return -EINVAL;
if (!(urb->dev && urb->dev->bus && urb->dev->bus->op)) if (!(urb->dev && urb->dev->bus))
return -ENODEV; return -ENODEV;
return urb->dev->bus->op->unlink_urb(urb, -ECONNRESET); return usb_hcd_unlink_urb(urb, -ECONNRESET);
} }
/** /**
...@@ -468,13 +465,13 @@ int usb_unlink_urb(struct urb *urb) ...@@ -468,13 +465,13 @@ int usb_unlink_urb(struct urb *urb)
void usb_kill_urb(struct urb *urb) void usb_kill_urb(struct urb *urb)
{ {
might_sleep(); might_sleep();
if (!(urb && urb->dev && urb->dev->bus && urb->dev->bus->op)) if (!(urb && urb->dev && urb->dev->bus))
return; return;
spin_lock_irq(&urb->lock); spin_lock_irq(&urb->lock);
++urb->reject; ++urb->reject;
spin_unlock_irq(&urb->lock); spin_unlock_irq(&urb->lock);
urb->dev->bus->op->unlink_urb(urb, -ENOENT); usb_hcd_unlink_urb(urb, -ENOENT);
wait_event(usb_kill_urb_queue, atomic_read(&urb->use_count) == 0); wait_event(usb_kill_urb_queue, atomic_read(&urb->use_count) == 0);
spin_lock_irq(&urb->lock); spin_lock_irq(&urb->lock);
......
此差异已折叠。
此差异已折叠。
...@@ -26,7 +26,7 @@ config USB_GADGET ...@@ -26,7 +26,7 @@ config USB_GADGET
you need a low level bus controller driver, and some software you need a low level bus controller driver, and some software
talking to it. Peripheral controllers are often discrete silicon, talking to it. Peripheral controllers are often discrete silicon,
or are integrated with the CPU in a microcontroller. The more or are integrated with the CPU in a microcontroller. The more
familiar host side controllers have names like like "EHCI", "OHCI", familiar host side controllers have names like "EHCI", "OHCI",
or "UHCI", and are usually integrated into southbridges on PC or "UHCI", and are usually integrated into southbridges on PC
motherboards. motherboards.
...@@ -404,6 +404,20 @@ config USB_G_SERIAL ...@@ -404,6 +404,20 @@ config USB_G_SERIAL
which includes instructions and a "driver info file" needed to which includes instructions and a "driver info file" needed to
make MS-Windows work with this driver. make MS-Windows work with this driver.
config USB_MIDI_GADGET
tristate "MIDI Gadget (EXPERIMENTAL)"
depends on SND && EXPERIMENTAL
select SND_RAWMIDI
help
The MIDI Gadget acts as a USB Audio device, with one MIDI
input and one MIDI output. These MIDI jacks appear as
a sound "card" in the ALSA sound system. Other MIDI
connections can then be made on the gadget system, using
ALSA's aconnect utility etc.
Say "y" to link the driver statically, or "m" to build a
dynamically linked module called "g_midi".
# put drivers that need isochronous transfer support (for audio # put drivers that need isochronous transfer support (for audio
# or video class gadget drivers), or specific hardware, here. # or video class gadget drivers), or specific hardware, here.
......
...@@ -15,6 +15,7 @@ obj-$(CONFIG_USB_AT91) += at91_udc.o ...@@ -15,6 +15,7 @@ obj-$(CONFIG_USB_AT91) += at91_udc.o
g_zero-objs := zero.o usbstring.o config.o epautoconf.o g_zero-objs := zero.o usbstring.o config.o epautoconf.o
g_ether-objs := ether.o usbstring.o config.o epautoconf.o g_ether-objs := ether.o usbstring.o config.o epautoconf.o
g_serial-objs := serial.o usbstring.o config.o epautoconf.o g_serial-objs := serial.o usbstring.o config.o epautoconf.o
g_midi-objs := gmidi.o usbstring.o config.o epautoconf.o
gadgetfs-objs := inode.o gadgetfs-objs := inode.o
g_file_storage-objs := file_storage.o usbstring.o config.o \ g_file_storage-objs := file_storage.o usbstring.o config.o \
epautoconf.o epautoconf.o
...@@ -28,4 +29,5 @@ obj-$(CONFIG_USB_ETH) += g_ether.o ...@@ -28,4 +29,5 @@ obj-$(CONFIG_USB_ETH) += g_ether.o
obj-$(CONFIG_USB_GADGETFS) += gadgetfs.o obj-$(CONFIG_USB_GADGETFS) += gadgetfs.o
obj-$(CONFIG_USB_FILE_STORAGE) += g_file_storage.o obj-$(CONFIG_USB_FILE_STORAGE) += g_file_storage.o
obj-$(CONFIG_USB_G_SERIAL) += g_serial.o obj-$(CONFIG_USB_G_SERIAL) += g_serial.o
obj-$(CONFIG_USB_MIDI_GADGET) += g_midi.o
...@@ -247,7 +247,7 @@ static int proc_udc_open(struct inode *inode, struct file *file) ...@@ -247,7 +247,7 @@ static int proc_udc_open(struct inode *inode, struct file *file)
return single_open(file, proc_udc_show, PDE(inode)->data); return single_open(file, proc_udc_show, PDE(inode)->data);
} }
static struct file_operations proc_ops = { static const struct file_operations proc_ops = {
.open = proc_udc_open, .open = proc_udc_open,
.read = seq_read, .read = seq_read,
.llseek = seq_lseek, .llseek = seq_lseek,
......
...@@ -889,11 +889,9 @@ EXPORT_SYMBOL (net2280_set_fifo_mode); ...@@ -889,11 +889,9 @@ EXPORT_SYMBOL (net2280_set_fifo_mode);
static void static void
dummy_gadget_release (struct device *dev) dummy_gadget_release (struct device *dev)
{ {
#if 0 /* usb_bus_put isn't EXPORTed! */
struct dummy *dum = gadget_dev_to_dummy (dev); struct dummy *dum = gadget_dev_to_dummy (dev);
usb_bus_put (&dummy_to_hcd (dum)->self); usb_put_hcd (dummy_to_hcd (dum));
#endif
} }
static int dummy_udc_probe (struct platform_device *pdev) static int dummy_udc_probe (struct platform_device *pdev)
...@@ -915,9 +913,7 @@ static int dummy_udc_probe (struct platform_device *pdev) ...@@ -915,9 +913,7 @@ static int dummy_udc_probe (struct platform_device *pdev)
if (rc < 0) if (rc < 0)
return rc; return rc;
#if 0 /* usb_bus_get isn't EXPORTed! */ usb_get_hcd (dummy_to_hcd (dum));
usb_bus_get (&dummy_to_hcd (dum)->self);
#endif
platform_set_drvdata (pdev, dum); platform_set_drvdata (pdev, dum);
device_create_file (&dum->gadget.dev, &dev_attr_function); device_create_file (&dum->gadget.dev, &dev_attr_function);
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
...@@ -40,7 +40,7 @@ ...@@ -40,7 +40,7 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/usb_ch9.h> #include <linux/usb_ch9.h>
#include <linux/usb_gadget.h> #include <linux/usb_gadget.h>
#include <linux/usb_otg.h> #include <linux/usb/otg.h>
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
#include <asm/byteorder.h> #include <asm/byteorder.h>
...@@ -2437,7 +2437,7 @@ static int proc_udc_open(struct inode *inode, struct file *file) ...@@ -2437,7 +2437,7 @@ static int proc_udc_open(struct inode *inode, struct file *file)
return single_open(file, proc_udc_show, NULL); return single_open(file, proc_udc_show, NULL);
} }
static struct file_operations proc_ops = { static const struct file_operations proc_ops = {
.open = proc_udc_open, .open = proc_udc_open,
.read = seq_read, .read = seq_read,
.llseek = seq_lseek, .llseek = seq_lseek,
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册