Commit 50f732ee authored by Linus Torvalds's avatar 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: (78 commits)
  USB: update MAINAINERS and CREDITS for Freescale USB driver
  USB: update gadget files for fsl_usb2_udc driver
  USB: add Freescale high-speed USB SOC device controller driver
  USB: quirk for broken suspend of IT8152F/G
  USB: iowarrior.c: timeouts too small in usb_control_msg calls
  USB: dell device id for option.c
  USB: Remove Huawei unusual_devs entry
  USB: CP2101 New Device IDs
  USB: add picdem device to ldusb
  usbfs micro optimitation
  USB: remove ancient/broken CRIS hcd
  usb ethernet gadget, workaround network stack API glitch
  USB: add "busnum" attribute for USB devices
  USB: cxacru: ADSL state management
  usbatm: Detect usb device shutdown and ignore failed urbs
  USB: Remove duplicate define of OHCI_QUIRK_ZFMICRO
  USB: BandRich BandLuxe HSDPA Data Card Driver
  USB gadget rndis: fix struct rndis_packet_msg_type unaligned bug
  USB Elan FTDI: check for driver registration status
  USB: sierra: add more checks on shutdown
  ...
parents aa5bc2b5 a7205b30
...@@ -3301,6 +3301,14 @@ S: 12725 SW Millikan Way, Suite 400 ...@@ -3301,6 +3301,14 @@ S: 12725 SW Millikan Way, Suite 400
S: Beaverton, Oregon 97005 S: Beaverton, Oregon 97005
S: USA S: USA
N: Li Yang
E: leoli@freescale.com
D: Freescale Highspeed USB device driver
D: Freescale QE SoC support and Ethernet driver
S: B-1206 Jingmao Guojigongyu
S: 16 Baliqiao Nanjie, Beijing 101100
S: People's Repulic of China
N: Marcelo Tosatti N: Marcelo Tosatti
E: marcelo@kvack.org E: marcelo@kvack.org
D: v2.4 kernel maintainer D: v2.4 kernel maintainer
......
What: /sys/bus/usb/devices/.../power/autosuspend
Date: March 2007
KernelVersion: 2.6.21
Contact: Alan Stern <stern@rowland.harvard.edu>
Description:
Each USB device directory will contain a file named
power/autosuspend. This file holds the time (in seconds)
the device must be idle before it will be autosuspended.
0 means the device will be autosuspended as soon as
possible. Negative values will prevent the device from
being autosuspended at all, and writing a negative value
will resume the device if it is already suspended.
The autosuspend delay for newly-created devices is set to
the value of the usbcore.autosuspend module parameter.
What: /sys/bus/usb/devices/.../power/level
Date: March 2007
KernelVersion: 2.6.21
Contact: Alan Stern <stern@rowland.harvard.edu>
Description:
Each USB device directory will contain a file named
power/level. This file holds a power-level setting for
the device, one of "on", "auto", or "suspend".
"on" means that the device is not allowed to autosuspend,
although normal suspends for system sleep will still
be honored. "auto" means the device will autosuspend
and autoresume in the usual manner, according to the
capabilities of its driver. "suspend" means the device
is forced into a suspended state and it will not autoresume
in response to I/O requests. However remote-wakeup requests
from the device may still be enabled (the remote-wakeup
setting is controlled separately by the power/wakeup
attribute).
During normal use, devices should be left in the "auto"
level. The other levels are meant for administrative uses.
If you want to suspend a device immediately but leave it
free to wake up in response to I/O requests, you should
write "0" to power/autosuspend.
...@@ -1792,7 +1792,7 @@ and is between 256 and 4096 characters. It is defined in the file ...@@ -1792,7 +1792,7 @@ and is between 256 and 4096 characters. It is defined in the file
for newly-detected USB devices (default 2). This for newly-detected USB devices (default 2). This
is the time required before an idle device will be is the time required before an idle device will be
autosuspended. Devices for which the delay is set autosuspended. Devices for which the delay is set
to 0 won't be autosuspended at all. to a negative value won't be autosuspended at all.
usbhid.mousepoll= usbhid.mousepoll=
[USBHID] The interval which mice are to be polled at. [USBHID] The interval which mice are to be polled at.
......
...@@ -16,7 +16,7 @@ situation as with tcpdump. ...@@ -16,7 +16,7 @@ situation as with tcpdump.
Unlike the packet socket, usbmon has an interface which provides traces Unlike the packet socket, usbmon has an interface which provides traces
in a text format. This is used for two purposes. First, it serves as a in a text format. This is used for two purposes. First, it serves as a
common trace exchange format for tools while most sophisticated formats common trace exchange format for tools while more sophisticated formats
are finalized. Second, humans can read it in case tools are not available. are finalized. Second, humans can read it in case tools are not available.
To collect a raw text trace, execute following steps. To collect a raw text trace, execute following steps.
...@@ -34,7 +34,7 @@ if usbmon is built into the kernel. ...@@ -34,7 +34,7 @@ if usbmon is built into the kernel.
Verify that bus sockets are present. Verify that bus sockets are present.
# ls /sys/kernel/debug/usbmon # ls /sys/kernel/debug/usbmon
1s 1t 2s 2t 3s 3t 4s 4t 1s 1t 1u 2s 2t 2u 3s 3t 3u 4s 4t 4u
# #
2. Find which bus connects to the desired device 2. Find which bus connects to the desired device
...@@ -54,7 +54,7 @@ Bus=03 means it's bus 3. ...@@ -54,7 +54,7 @@ Bus=03 means it's bus 3.
3. Start 'cat' 3. Start 'cat'
# cat /sys/kernel/debug/usbmon/3t > /tmp/1.mon.out # cat /sys/kernel/debug/usbmon/3u > /tmp/1.mon.out
This process will be reading until killed. Naturally, the output can be This process will be reading until killed. Naturally, the output can be
redirected to a desirable location. This is preferred, because it is going redirected to a desirable location. This is preferred, because it is going
...@@ -75,46 +75,80 @@ that the file size is not excessive for your favourite editor. ...@@ -75,46 +75,80 @@ that the file size is not excessive for your favourite editor.
* Raw text data format * Raw text data format
The '1t' type data consists of a stream of events, such as URB submission, Two formats are supported currently: the original, or '1t' format, and
the '1u' format. The '1t' format is deprecated in kernel 2.6.21. The '1u'
format adds a few fields, such as ISO frame descriptors, interval, etc.
It produces slightly longer lines, but otherwise is a perfect superset
of '1t' format.
If it is desired to recognize one from the other in a program, look at the
"address" word (see below), where '1u' format adds a bus number. If 2 colons
are present, it's the '1t' format, otherwise '1u'.
Any text format data consists of a stream of events, such as URB submission,
URB callback, submission error. Every event is a text line, which consists URB callback, submission error. Every event is a text line, which consists
of whitespace separated words. The number or position of words may depend of whitespace separated words. The number or position of words may depend
on the event type, but there is a set of words, common for all types. on the event type, but there is a set of words, common for all types.
Here is the list of words, from left to right: Here is the list of words, from left to right:
- URB Tag. This is used to identify URBs is normally a kernel mode address - URB Tag. This is used to identify URBs is normally a kernel mode address
of the URB structure in hexadecimal. of the URB structure in hexadecimal.
- Timestamp in microseconds, a decimal number. The timestamp's resolution - Timestamp in microseconds, a decimal number. The timestamp's resolution
depends on available clock, and so it can be much worse than a microsecond depends on available clock, and so it can be much worse than a microsecond
(if the implementation uses jiffies, for example). (if the implementation uses jiffies, for example).
- Event Type. This type refers to the format of the event, not URB type. - Event Type. This type refers to the format of the event, not URB type.
Available types are: S - submission, C - callback, E - submission error. Available types are: S - submission, C - callback, E - submission error.
- "Pipe". The pipe concept is deprecated. This is a composite word, used to
be derived from information in pipes. It consists of three fields, separated - "Address" word (formerly a "pipe"). It consists of four fields, separated by
by colons: URB type and direction, Device address, Endpoint number. colons: URB type and direction, Bus number, Device address, Endpoint number.
Type and direction are encoded with two bytes in the following manner: Type and direction are encoded with two bytes in the following manner:
Ci Co Control input and output Ci Co Control input and output
Zi Zo Isochronous input and output Zi Zo Isochronous input and output
Ii Io Interrupt input and output Ii Io Interrupt input and output
Bi Bo Bulk input and output Bi Bo Bulk input and output
Device address and Endpoint number are 3-digit and 2-digit (respectively) Bus number, Device address, and Endpoint are decimal numbers, but they may
decimal numbers, with leading zeroes. have leading zeros, for the sake of human readers.
- URB Status. In most cases, this field contains a number, sometimes negative,
which represents a "status" field of the URB. This field makes no sense for - URB Status word. This is either a letter, or several numbers separated
submissions, but is present anyway to help scripts with parsing. When an by colons: URB status, interval, start frame, and error count. Unlike the
error occurs, the field contains the error code. In case of a submission of "address" word, all fields save the status are optional. Interval is printed
a Control packet, this field contains a Setup Tag instead of an error code. only for interrupt and isochronous URBs. Start frame is printed only for
It is easy to tell whether the Setup Tag is present because it is never a isochronous URBs. Error count is printed only for isochronous callback
number. Thus if scripts find a number in this field, they proceed to read events.
Data Length. If they find something else, like a letter, they read the setup
packet before reading the Data Length. The status field is a decimal number, sometimes negative, which represents
a "status" field of the URB. This field makes no sense for submissions, but
is present anyway to help scripts with parsing. When an error occurs, the
field contains the error code.
In case of a submission of a Control packet, this field contains a Setup Tag
instead of an group of numbers. It is easy to tell whether the Setup Tag is
present because it is never a number. Thus if scripts find a set of numbers
in this word, they proceed to read Data Length (except for isochronous URBs).
If they find something else, like a letter, they read the setup packet before
reading the Data Length or isochronous descriptors.
- Setup packet, if present, consists of 5 words: one of each for bmRequestType, - Setup packet, if present, consists of 5 words: one of each for bmRequestType,
bRequest, wValue, wIndex, wLength, as specified by the USB Specification 2.0. bRequest, wValue, wIndex, wLength, as specified by the USB Specification 2.0.
These words are safe to decode if Setup Tag was 's'. Otherwise, the setup These words are safe to decode if Setup Tag was 's'. Otherwise, the setup
packet was present, but not captured, and the fields contain filler. packet was present, but not captured, and the fields contain filler.
- Number of isochronous frame descriptors and descriptors themselves.
If an Isochronous transfer event has a set of descriptors, a total number
of them in an URB is printed first, then a word per descriptor, up to a
total of 5. The word consists of 3 colon-separated decimal numbers for
status, offset, and length respectively. For submissions, initial length
is reported. For callbacks, actual length is reported.
- Data Length. For submissions, this is the requested length. For callbacks, - Data Length. For submissions, this is the requested length. For callbacks,
this is the actual length. this is the actual length.
- Data tag. The usbmon may not always capture data, even if length is nonzero. - Data tag. The usbmon may not always capture data, even if length is nonzero.
The data words are present only if this tag is '='. The data words are present only if this tag is '='.
- Data words follow, in big endian hexadecimal format. Notice that they are - Data words follow, in big endian hexadecimal format. Notice that they are
not machine words, but really just a byte stream split into words to make not machine words, but really just a byte stream split into words to make
it easier to read. Thus, the last word may contain from one to four bytes. it easier to read. Thus, the last word may contain from one to four bytes.
...@@ -153,20 +187,18 @@ class ParsedLine { ...@@ -153,20 +187,18 @@ class ParsedLine {
} }
} }
This format may be changed in the future.
Examples: Examples:
An input control transfer to get a port status. An input control transfer to get a port status.
d5ea89a0 3575914555 S Ci:001:00 s a3 00 0000 0003 0004 4 < d5ea89a0 3575914555 S Ci:1:001:0 s a3 00 0000 0003 0004 4 <
d5ea89a0 3575914560 C Ci:001:00 0 4 = 01050000 d5ea89a0 3575914560 C Ci:1:001:0 0 4 = 01050000
An output bulk transfer to send a SCSI command 0x5E in a 31-byte Bulk wrapper An output bulk transfer to send a SCSI command 0x5E in a 31-byte Bulk wrapper
to a storage device at address 5: to a storage device at address 5:
dd65f0e8 4128379752 S Bo:005:02 -115 31 = 55534243 5e000000 00000000 00000600 00000000 00000000 00000000 000000 dd65f0e8 4128379752 S Bo:1:005:2 -115 31 = 55534243 5e000000 00000000 00000600 00000000 00000000 00000000 000000
dd65f0e8 4128379808 C Bo:005:02 0 31 > dd65f0e8 4128379808 C Bo:1:005:2 0 31 >
* Raw binary format and API * Raw binary format and API
......
...@@ -981,6 +981,11 @@ M: mhw@wittsend.com ...@@ -981,6 +981,11 @@ M: mhw@wittsend.com
W: http://www.wittsend.com/computone.html W: http://www.wittsend.com/computone.html
S: Maintained S: Maintained
CONEXANT ACCESSRUNNER USB DRIVER
P: Simon Arlott
M: cxacru@fire.lp0.eu
S: Maintained
COSA/SRP SYNC SERIAL DRIVER COSA/SRP SYNC SERIAL DRIVER
P: Jan "Yenya" Kasprzak P: Jan "Yenya" Kasprzak
M: kas@fi.muni.cz M: kas@fi.muni.cz
...@@ -1389,6 +1394,13 @@ L: linuxppc-embedded@ozlabs.org ...@@ -1389,6 +1394,13 @@ L: linuxppc-embedded@ozlabs.org
L: netdev@vger.kernel.org L: netdev@vger.kernel.org
S: Maintained S: Maintained
FREESCALE HIGHSPEED USB DEVICE DRIVER
P: Li Yang
M: leoli@freescale.com
L: linux-usb-devel@lists.sourceforge.net
L: linuxppc-embedded@ozlabs.org
S: Maintained
FILE LOCKING (flock() and fcntl()/lockf()) FILE LOCKING (flock() and fcntl()/lockf())
P: Matthew Wilcox P: Matthew Wilcox
M: matthew@wil.cx M: matthew@wil.cx
......
...@@ -2132,12 +2132,15 @@ static int ub_get_pipes(struct ub_dev *sc, struct usb_device *dev, ...@@ -2132,12 +2132,15 @@ static int ub_get_pipes(struct ub_dev *sc, struct usb_device *dev,
if ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) if ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
== USB_ENDPOINT_XFER_BULK) { == USB_ENDPOINT_XFER_BULK) {
/* BULK in or out? */ /* BULK in or out? */
if (ep->bEndpointAddress & USB_DIR_IN) if (ep->bEndpointAddress & USB_DIR_IN) {
if (ep_in == NULL)
ep_in = ep; ep_in = ep;
else } else {
if (ep_out == NULL)
ep_out = ep; ep_out = ep;
} }
} }
}
if (ep_in == NULL || ep_out == NULL) { if (ep_in == NULL || ep_out == NULL) {
printk(KERN_NOTICE "%s: failed endpoint check\n", printk(KERN_NOTICE "%s: failed endpoint check\n",
......
...@@ -15,7 +15,6 @@ obj-$(CONFIG_USB_OHCI_HCD) += host/ ...@@ -15,7 +15,6 @@ 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_USB_U132_HCD) += host/
obj-$(CONFIG_ETRAX_USB_HOST) += host/
obj-$(CONFIG_USB_OHCI_AT91) += host/ obj-$(CONFIG_USB_OHCI_AT91) += host/
obj-$(CONFIG_USB_ACM) += class/ obj-$(CONFIG_USB_ACM) += class/
......
This diff is collapsed.
...@@ -274,6 +274,9 @@ static void usbatm_complete(struct urb *urb) ...@@ -274,6 +274,9 @@ static void usbatm_complete(struct urb *urb)
(!(channel->usbatm->flags & UDSL_IGNORE_EILSEQ) || (!(channel->usbatm->flags & UDSL_IGNORE_EILSEQ) ||
urb->status != -EILSEQ )) urb->status != -EILSEQ ))
{ {
if (urb->status == -ESHUTDOWN)
return;
if (printk_ratelimit()) if (printk_ratelimit())
atm_warn(channel->usbatm, "%s: urb 0x%p failed (%d)!\n", atm_warn(channel->usbatm, "%s: urb 0x%p failed (%d)!\n",
__func__, urb, urb->status); __func__, urb, urb->status);
...@@ -968,6 +971,14 @@ static int usbatm_atm_init(struct usbatm_data *instance) ...@@ -968,6 +971,14 @@ static int usbatm_atm_init(struct usbatm_data *instance)
/* temp init ATM device, set to 128kbit */ /* temp init ATM device, set to 128kbit */
atm_dev->link_rate = 128 * 1000 / 424; atm_dev->link_rate = 128 * 1000 / 424;
ret = sysfs_create_link(&atm_dev->class_dev.kobj,
&instance->usb_intf->dev.kobj, "device");
if (ret) {
atm_err(instance, "%s: sysfs_create_link failed: %d\n",
__func__, ret);
goto fail_sysfs;
}
if (instance->driver->atm_start && ((ret = instance->driver->atm_start(instance, atm_dev)) < 0)) { if (instance->driver->atm_start && ((ret = instance->driver->atm_start(instance, atm_dev)) < 0)) {
atm_err(instance, "%s: atm_start failed: %d!\n", __func__, ret); atm_err(instance, "%s: atm_start failed: %d!\n", __func__, ret);
goto fail; goto fail;
...@@ -986,6 +997,8 @@ static int usbatm_atm_init(struct usbatm_data *instance) ...@@ -986,6 +997,8 @@ static int usbatm_atm_init(struct usbatm_data *instance)
return 0; return 0;
fail: fail:
sysfs_remove_link(&atm_dev->class_dev.kobj, "device");
fail_sysfs:
instance->atm_dev = NULL; instance->atm_dev = NULL;
atm_dev_deregister(atm_dev); /* usbatm_atm_dev_close will eventually be called */ atm_dev_deregister(atm_dev); /* usbatm_atm_dev_close will eventually be called */
return ret; return ret;
...@@ -1318,8 +1331,10 @@ void usbatm_usb_disconnect(struct usb_interface *intf) ...@@ -1318,8 +1331,10 @@ void usbatm_usb_disconnect(struct usb_interface *intf)
kfree(instance->cell_buf); kfree(instance->cell_buf);
/* ATM finalize */ /* ATM finalize */
if (instance->atm_dev) if (instance->atm_dev) {
sysfs_remove_link(&instance->atm_dev->class_dev.kobj, "device");
atm_dev_deregister(instance->atm_dev); atm_dev_deregister(instance->atm_dev);
}
usbatm_put_instance(instance); /* taken in usbatm_usb_probe */ usbatm_put_instance(instance); /* taken in usbatm_usb_probe */
} }
......
...@@ -212,7 +212,41 @@ static int acm_write_start(struct acm *acm) ...@@ -212,7 +212,41 @@ static int acm_write_start(struct acm *acm)
} }
return rc; return rc;
} }
/*
* attributes exported through sysfs
*/
static ssize_t show_caps
(struct device *dev, struct device_attribute *attr, char *buf)
{
struct usb_interface *intf = to_usb_interface(dev);
struct acm *acm = usb_get_intfdata(intf);
return sprintf(buf, "%d", acm->ctrl_caps);
}
static DEVICE_ATTR(bmCapabilities, S_IRUGO, show_caps, NULL);
static ssize_t show_country_codes
(struct device *dev, struct device_attribute *attr, char *buf)
{
struct usb_interface *intf = to_usb_interface(dev);
struct acm *acm = usb_get_intfdata(intf);
memcpy(buf, acm->country_codes, acm->country_code_size);
return acm->country_code_size;
}
static DEVICE_ATTR(wCountryCodes, S_IRUGO, show_country_codes, NULL);
static ssize_t show_country_rel_date
(struct device *dev, struct device_attribute *attr, char *buf)
{
struct usb_interface *intf = to_usb_interface(dev);
struct acm *acm = usb_get_intfdata(intf);
return sprintf(buf, "%d", acm->country_rel_date);
}
static DEVICE_ATTR(iCountryCodeRelDate, S_IRUGO, show_country_rel_date, NULL);
/* /*
* Interrupt handlers for various ACM device responses * Interrupt handlers for various ACM device responses
*/ */
...@@ -514,6 +548,7 @@ static void acm_tty_unregister(struct acm *acm) ...@@ -514,6 +548,7 @@ static void acm_tty_unregister(struct acm *acm)
usb_free_urb(acm->writeurb); usb_free_urb(acm->writeurb);
for (i = 0; i < nr; i++) for (i = 0; i < nr; i++)
usb_free_urb(acm->ru[i].urb); usb_free_urb(acm->ru[i].urb);
kfree(acm->country_codes);
kfree(acm); kfree(acm);
} }
...@@ -761,6 +796,7 @@ static int acm_probe (struct usb_interface *intf, ...@@ -761,6 +796,7 @@ static int acm_probe (struct usb_interface *intf,
const struct usb_device_id *id) const struct usb_device_id *id)
{ {
struct usb_cdc_union_desc *union_header = NULL; struct usb_cdc_union_desc *union_header = NULL;
struct usb_cdc_country_functional_desc *cfd = NULL;
char *buffer = intf->altsetting->extra; char *buffer = intf->altsetting->extra;
int buflen = intf->altsetting->extralen; int buflen = intf->altsetting->extralen;
struct usb_interface *control_interface; struct usb_interface *control_interface;
...@@ -824,8 +860,9 @@ static int acm_probe (struct usb_interface *intf, ...@@ -824,8 +860,9 @@ static int acm_probe (struct usb_interface *intf,
union_header = (struct usb_cdc_union_desc *) union_header = (struct usb_cdc_union_desc *)
buffer; buffer;
break; break;
case USB_CDC_COUNTRY_TYPE: /* maybe somehow export */ case USB_CDC_COUNTRY_TYPE: /* export through sysfs*/
break; /* for now we ignore it */ cfd = (struct usb_cdc_country_functional_desc *)buffer;
break;
case USB_CDC_HEADER_TYPE: /* maybe check version */ case USB_CDC_HEADER_TYPE: /* maybe check version */
break; /* for now we ignore it */ break; /* for now we ignore it */
case USB_CDC_ACM_TYPE: case USB_CDC_ACM_TYPE:
...@@ -983,6 +1020,34 @@ static int acm_probe (struct usb_interface *intf, ...@@ -983,6 +1020,34 @@ static int acm_probe (struct usb_interface *intf,
goto alloc_fail7; goto alloc_fail7;
} }
usb_set_intfdata (intf, acm);
i = device_create_file(&intf->dev, &dev_attr_bmCapabilities);
if (i < 0)
goto alloc_fail8;
if (cfd) { /* export the country data */
acm->country_codes = kmalloc(cfd->bLength - 4, GFP_KERNEL);
if (!acm->country_codes)
goto skip_countries;
acm->country_code_size = cfd->bLength - 4;
memcpy(acm->country_codes, (u8 *)&cfd->wCountyCode0, cfd->bLength - 4);
acm->country_rel_date = cfd->iCountryCodeRelDate;
i = device_create_file(&intf->dev, &dev_attr_wCountryCodes);
if (i < 0) {
kfree(acm->country_codes);
goto skip_countries;
}
i = device_create_file(&intf->dev, &dev_attr_iCountryCodeRelDate);
if (i < 0) {
kfree(acm->country_codes);
goto skip_countries;
}
}
skip_countries:
usb_fill_int_urb(acm->ctrlurb, usb_dev, usb_rcvintpipe(usb_dev, epctrl->bEndpointAddress), usb_fill_int_urb(acm->ctrlurb, usb_dev, usb_rcvintpipe(usb_dev, epctrl->bEndpointAddress),
acm->ctrl_buffer, ctrlsize, acm_ctrl_irq, acm, epctrl->bInterval); acm->ctrl_buffer, ctrlsize, acm_ctrl_irq, acm, epctrl->bInterval);
acm->ctrlurb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; acm->ctrlurb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
...@@ -1006,9 +1071,10 @@ static int acm_probe (struct usb_interface *intf, ...@@ -1006,9 +1071,10 @@ static int acm_probe (struct usb_interface *intf,
tty_register_device(acm_tty_driver, minor, &control_interface->dev); tty_register_device(acm_tty_driver, minor, &control_interface->dev);
acm_table[minor] = acm; acm_table[minor] = acm;
usb_set_intfdata (intf, acm);
return 0;
return 0;
alloc_fail8:
usb_free_urb(acm->writeurb);
alloc_fail7: alloc_fail7:
for (i = 0; i < num_rx_buf; i++) for (i = 0; i < num_rx_buf; i++)
usb_buffer_free(usb_dev, acm->readsize, acm->rb[i].base, acm->rb[i].dma); usb_buffer_free(usb_dev, acm->readsize, acm->rb[i].base, acm->rb[i].dma);
...@@ -1027,7 +1093,7 @@ static int acm_probe (struct usb_interface *intf, ...@@ -1027,7 +1093,7 @@ static int acm_probe (struct usb_interface *intf,
static void acm_disconnect(struct usb_interface *intf) static void acm_disconnect(struct usb_interface *intf)
{ {
struct acm *acm = usb_get_intfdata (intf); struct acm *acm = usb_get_intfdata(intf);
struct usb_device *usb_dev = interface_to_usbdev(intf); struct usb_device *usb_dev = interface_to_usbdev(intf);
int i; int i;
...@@ -1041,6 +1107,11 @@ static void acm_disconnect(struct usb_interface *intf) ...@@ -1041,6 +1107,11 @@ static void acm_disconnect(struct usb_interface *intf)
mutex_unlock(&open_mutex); mutex_unlock(&open_mutex);
return; return;
} }
if (acm->country_codes){
device_remove_file(&intf->dev, &dev_attr_wCountryCodes);
device_remove_file(&intf->dev, &dev_attr_iCountryCodeRelDate);
}
device_remove_file(&intf->dev, &dev_attr_bmCapabilities);
acm->dev = NULL; acm->dev = NULL;
usb_set_intfdata(acm->control, NULL); usb_set_intfdata(acm->control, NULL);
usb_set_intfdata(acm->data, NULL); usb_set_intfdata(acm->data, NULL);
......
...@@ -91,6 +91,9 @@ struct acm { ...@@ -91,6 +91,9 @@ struct acm {
struct urb *ctrlurb, *writeurb; /* urbs */ struct urb *ctrlurb, *writeurb; /* urbs */
u8 *ctrl_buffer; /* buffers of urbs */ u8 *ctrl_buffer; /* buffers of urbs */
dma_addr_t ctrl_dma; /* dma handles of buffers */ dma_addr_t ctrl_dma; /* dma handles of buffers */
u8 *country_codes; /* country codes from device */
unsigned int country_code_size; /* size of this buffer */
unsigned int country_rel_date; /* release date of version */
struct acm_wb wb[ACM_NW]; struct acm_wb wb[ACM_NW];
struct acm_ru ru[ACM_NR]; struct acm_ru ru[ACM_NR];
struct acm_rb rb[ACM_NR]; struct acm_rb rb[ACM_NR];
......
...@@ -31,7 +31,30 @@ config USB_DEVICEFS ...@@ -31,7 +31,30 @@ config USB_DEVICEFS
For the format of the various /proc/bus/usb/ files, please read For the format of the various /proc/bus/usb/ files, please read
<file:Documentation/usb/proc_usb_info.txt>. <file:Documentation/usb/proc_usb_info.txt>.
Most users want to say Y here. Usbfs files can't handle Access Control Lists (ACL), which are the
default way to grant access to USB devices for untrusted users of a
desktop system. The usbfs functionality is replaced by real
device-nodes managed by udev. These nodes live in /dev/bus/usb and
are used by libusb.
config USB_DEVICE_CLASS
bool "USB device class-devices (DEPRECATED)"
depends on USB
default n
---help---
Userspace access to USB devices is granted by device-nodes exported
directly from the usbdev in sysfs. Old versions of the driver
core and udev needed additional class devices to export device nodes.
These additional devices are difficult to handle in userspace, if
information about USB interfaces must be available. One device contains
the device node, the other device contains the interface data. Both
devices are at the same level in sysfs (siblings) and one can't access
the other. The device node created directly by the usbdev is the parent
device of the interface and therefore easily accessible from the interface
event.
This option provides backward compatibility if needed.
config USB_DYNAMIC_MINORS config USB_DYNAMIC_MINORS
bool "Dynamic USB minor allocation (EXPERIMENTAL)" bool "Dynamic USB minor allocation (EXPERIMENTAL)"
......
...@@ -57,7 +57,6 @@ ...@@ -57,7 +57,6 @@
#define USB_MAXBUS 64 #define USB_MAXBUS 64
#define USB_DEVICE_MAX USB_MAXBUS * 128 #define USB_DEVICE_MAX USB_MAXBUS * 128
static struct class *usb_device_class;
/* Mutual exclusion for removal, open, and release */ /* Mutual exclusion for removal, open, and release */
DEFINE_MUTEX(usbfs_mutex); DEFINE_MUTEX(usbfs_mutex);
...@@ -514,22 +513,25 @@ static int check_ctrlrecip(struct dev_state *ps, unsigned int requesttype, unsig ...@@ -514,22 +513,25 @@ static int check_ctrlrecip(struct dev_state *ps, unsigned int requesttype, unsig
return ret; return ret;
} }
static struct usb_device *usbdev_lookup_minor(int minor) static int __match_minor(struct device *dev, void *data)
{ {
struct device *device; int minor = *((int *)data);
struct usb_device *udev = NULL;
down(&usb_device_class->sem); if (dev->devt == MKDEV(USB_DEVICE_MAJOR, minor))
list_for_each_entry(device, &usb_device_class->devices, node) { return 1;
if (device->devt == MKDEV(USB_DEVICE_MAJOR, minor)) { return 0;
udev = device->platform_data; }
break;
}
}
up(&usb_device_class->sem);
return udev; static struct usb_device *usbdev_lookup_by_minor(int minor)
}; {
struct device *dev;
dev = bus_find_device(&usb_bus_type, NULL, &minor, __match_minor);
if (!dev)
return NULL;
put_device(dev);
return container_of(dev, struct usb_device, dev);
}
/* /*
* file operations * file operations
...@@ -548,11 +550,14 @@ static int usbdev_open(struct inode *inode, struct file *file) ...@@ -548,11 +550,14 @@ static int usbdev_open(struct inode *inode, struct file *file)
goto out; goto out;
ret = -ENOENT; ret = -ENOENT;
/* check if we are called from a real node or usbfs */ /* usbdev device-node */
if (imajor(inode) == USB_DEVICE_MAJOR) if (imajor(inode) == USB_DEVICE_MAJOR)
dev = usbdev_lookup_minor(iminor(inode)); dev = usbdev_lookup_by_minor(iminor(inode));
#ifdef CONFIG_USB_DEVICEFS
/* procfs file */
if (!dev) if (!dev)
dev = inode->i_private; dev = inode->i_private;
#endif
if (!dev) if (!dev)
goto out; goto out;
ret = usb_autoresume_device(dev); ret = usb_autoresume_device(dev);
...@@ -575,7 +580,7 @@ static int usbdev_open(struct inode *inode, struct file *file) ...@@ -575,7 +580,7 @@ static int usbdev_open(struct inode *inode, struct file *file)
ps->disccontext = NULL; ps->disccontext = NULL;
ps->ifclaimed = 0; ps->ifclaimed = 0;
security_task_getsecid(current, &ps->secid); security_task_getsecid(current, &ps->secid);
wmb(); smp_wmb();
list_add_tail(&ps->list, &dev->filelist); list_add_tail(&ps->list, &dev->filelist);
file->private_data = ps; file->private_data = ps;
out: out:
...@@ -1570,7 +1575,7 @@ static unsigned int usbdev_poll(struct file *file, struct poll_table_struct *wai ...@@ -1570,7 +1575,7 @@ static unsigned int usbdev_poll(struct file *file, struct poll_table_struct *wai
return mask; return mask;
} }
const struct file_operations usbfs_device_file_operations = { const struct file_operations usbdev_file_operations = {
.llseek = usbdev_lseek, .llseek = usbdev_lseek,
.read = usbdev_read, .read = usbdev_read,
.poll = usbdev_poll, .poll = usbdev_poll,
...@@ -1579,50 +1584,53 @@ const struct file_operations usbfs_device_file_operations = { ...@@ -1579,50 +1584,53 @@ const struct file_operations usbfs_device_file_operations = {
.release = usbdev_release, .release = usbdev_release,
}; };
static int usbdev_add(struct usb_device *dev) #ifdef CONFIG_USB_DEVICE_CLASS
static struct class *usb_classdev_class;
static int usb_classdev_add(struct usb_device *dev)
{ {
int minor = ((dev->bus->busnum-1) * 128) + (dev->devnum-1); int minor = ((dev->bus->busnum-1) * 128) + (dev->devnum-1);
dev->usbfs_dev = device_create(usb_device_class, &dev->dev, dev->usb_classdev = device_create(usb_classdev_class, &dev->dev,
MKDEV(USB_DEVICE_MAJOR, minor), MKDEV(USB_DEVICE_MAJOR, minor),
"usbdev%d.%d", dev->bus->busnum, dev->devnum); "usbdev%d.%d", dev->bus->busnum, dev->devnum);
if (IS_ERR(dev->usbfs_dev)) if (IS_ERR(dev->usb_classdev))
return PTR_ERR(dev->usbfs_dev); return PTR_ERR(dev->usb_classdev);
dev->usbfs_dev->platform_data = dev;
return 0; return 0;
} }
static void usbdev_remove(struct usb_device *dev) static void usb_classdev_remove(struct usb_device *dev)
{ {
device_unregister(dev->usbfs_dev); device_unregister(dev->usb_classdev);
} }
static int usbdev_notify(struct notifier_block *self, unsigned long action, static int usb_classdev_notify(struct notifier_block *self,
void *dev) unsigned long action, void *dev)
{ {
switch (action) { switch (action) {
case USB_DEVICE_ADD: case USB_DEVICE_ADD:
if (usbdev_add(dev)) if (usb_classdev_add(dev))
return NOTIFY_BAD; return NOTIFY_BAD;
break; break;
case USB_DEVICE_REMOVE: case USB_DEVICE_REMOVE:
usbdev_remove(dev); usb_classdev_remove(dev);
break; break;
} }
return NOTIFY_OK; return NOTIFY_OK;
} }
static struct notifier_block usbdev_nb = { static struct notifier_block usbdev_nb = {
.notifier_call = usbdev_notify, .notifier_call = usb_classdev_notify,
}; };
#endif
static struct cdev usb_device_cdev = { static struct cdev usb_device_cdev = {
.kobj = {.name = "usb_device", }, .kobj = {.name = "usb_device", },
.owner = THIS_MODULE, .owner = THIS_MODULE,
}; };
int __init usbdev_init(void) int __init usb_devio_init(void)
{ {
int retval; int retval;
...@@ -1632,38 +1640,38 @@ int __init usbdev_init(void) ...@@ -1632,38 +1640,38 @@ int __init usbdev_init(void)
err("unable to register minors for usb_device"); err("unable to register minors for usb_device");
goto out; goto out;
} }
cdev_init(&usb_device_cdev, &usbfs_device_file_operations); cdev_init(&usb_device_cdev, &usbdev_file_operations);
retval = cdev_add(&usb_device_cdev, USB_DEVICE_DEV, USB_DEVICE_MAX); retval = cdev_add(&usb_device_cdev, USB_DEVICE_DEV, USB_DEVICE_MAX);
if (retval) { if (retval) {
err("unable to get usb_device major %d", USB_DEVICE_MAJOR); err("unable to get usb_device major %d", USB_DEVICE_MAJOR);
goto error_cdev; goto error_cdev;
} }
usb_device_class = class_create(THIS_MODULE, "usb_device"); #ifdef CONFIG_USB_DEVICE_CLASS
if (IS_ERR(usb_device_class)) { usb_classdev_class = class_create(THIS_MODULE, "usb_device");
if (IS_ERR(usb_classdev_class)) {
err("unable to register usb_device class"); err("unable to register usb_device class");
retval = PTR_ERR(usb_device_class); retval = PTR_ERR(usb_classdev_class);
goto error_class; cdev_del(&usb_device_cdev);
usb_classdev_class = NULL;
goto out;
} }
usb_register_notify(&usbdev_nb); usb_register_notify(&usbdev_nb);
#endif
out: out:
return retval; return retval;
error_class:
usb_device_class = NULL;
cdev_del(&usb_device_cdev);
error_cdev: error_cdev:
unregister_chrdev_region(USB_DEVICE_DEV, USB_DEVICE_MAX); unregister_chrdev_region(USB_DEVICE_DEV, USB_DEVICE_MAX);
goto out; goto out;
} }
void usbdev_cleanup(void) void usb_devio_cleanup(void)
{ {
#ifdef CONFIG_USB_DEVICE_CLASS
usb_unregister_notify(&usbdev_nb); usb_unregister_notify(&usbdev_nb);
class_destroy(usb_device_class); class_destroy(usb_classdev_class);
#endif
cdev_del(&usb_device_cdev); cdev_del(&usb_device_cdev);
unregister_chrdev_region(USB_DEVICE_DEV, USB_DEVICE_MAX); unregister_chrdev_region(USB_DEVICE_DEV, USB_DEVICE_MAX);
} }
This diff is collapsed.
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
#include <asm/irq.h> #include <asm/irq.h>
#include <asm/byteorder.h> #include <asm/byteorder.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/workqueue.h>
#include <linux/usb.h> #include <linux/usb.h>
...@@ -544,6 +545,8 @@ void usb_hcd_poll_rh_status(struct usb_hcd *hcd) ...@@ -544,6 +545,8 @@ void usb_hcd_poll_rh_status(struct usb_hcd *hcd)
unsigned long flags; unsigned long flags;
char buffer[4]; /* Any root hubs with > 31 ports? */ char buffer[4]; /* Any root hubs with > 31 ports? */
if (unlikely(!hcd->rh_registered))
return;
if (!hcd->uses_new_polling && !hcd->status_urb) if (!hcd->uses_new_polling && !hcd->status_urb)
return; return;
...@@ -1296,14 +1299,26 @@ int hcd_bus_resume (struct usb_bus *bus) ...@@ -1296,14 +1299,26 @@ int hcd_bus_resume (struct usb_bus *bus)
return status; return status;
} }
/* Workqueue routine for root-hub remote wakeup */
static void hcd_resume_work(struct work_struct *work)
{
struct usb_hcd *hcd = container_of(work, struct usb_hcd, wakeup_work);
struct usb_device *udev = hcd->self.root_hub;
usb_lock_device(udev);
usb_mark_last_busy(udev);
usb_external_resume_device(udev);
usb_unlock_device(udev);
}
/** /**
* 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
* *
* The USB host controller calls this function when its root hub is * The USB host controller calls this function when its root hub is
* suspended (with the remote wakeup feature enabled) and a remote * suspended (with the remote wakeup feature enabled) and a remote
* wakeup request is received. It queues a request for khubd to * wakeup request is received. The routine submits a workqueue request
* resume the root hub (that is, manage its downstream ports again). * to resume the root hub (that is, manage its downstream ports again).
*/ */
void usb_hcd_resume_root_hub (struct usb_hcd *hcd) void usb_hcd_resume_root_hub (struct usb_hcd *hcd)
{ {
...@@ -1311,7 +1326,7 @@ void usb_hcd_resume_root_hub (struct usb_hcd *hcd) ...@@ -1311,7 +1326,7 @@ void usb_hcd_resume_root_hub (struct usb_hcd *hcd)
spin_lock_irqsave (&hcd_root_hub_lock, flags); spin_lock_irqsave (&hcd_root_hub_lock, flags);
if (hcd->rh_registered) if (hcd->rh_registered)
usb_resume_root_hub (hcd->self.root_hub); queue_work(ksuspend_usb_wq, &hcd->wakeup_work);
spin_unlock_irqrestore (&hcd_root_hub_lock, flags); spin_unlock_irqrestore (&hcd_root_hub_lock, flags);
} }
EXPORT_SYMBOL_GPL(usb_hcd_resume_root_hub); EXPORT_SYMBOL_GPL(usb_hcd_resume_root_hub);
...@@ -1500,6 +1515,9 @@ struct usb_hcd *usb_create_hcd (const struct hc_driver *driver, ...@@ -1500,6 +1515,9 @@ struct usb_hcd *usb_create_hcd (const struct hc_driver *driver,
init_timer(&hcd->rh_timer); init_timer(&hcd->rh_timer);
hcd->rh_timer.function = rh_timer_func; hcd->rh_timer.function = rh_timer_func;
hcd->rh_timer.data = (unsigned long) hcd; hcd->rh_timer.data = (unsigned long) hcd;
#ifdef CONFIG_PM
INIT_WORK(&hcd->wakeup_work, hcd_resume_work);
#endif
hcd->driver = driver; hcd->driver = driver;
hcd->product_desc = (driver->product_desc) ? driver->product_desc : hcd->product_desc = (driver->product_desc) ? driver->product_desc :
...@@ -1666,16 +1684,20 @@ void usb_remove_hcd(struct usb_hcd *hcd) ...@@ -1666,16 +1684,20 @@ void usb_remove_hcd(struct usb_hcd *hcd)
hcd->rh_registered = 0; hcd->rh_registered = 0;
spin_unlock_irq (&hcd_root_hub_lock); spin_unlock_irq (&hcd_root_hub_lock);
#ifdef CONFIG_PM
flush_workqueue(ksuspend_usb_wq);
#endif
mutex_lock(&usb_bus_list_lock); mutex_lock(&usb_bus_list_lock);
usb_disconnect(&hcd->self.root_hub); usb_disconnect(&hcd->self.root_hub);
mutex_unlock(&usb_bus_list_lock); mutex_unlock(&usb_bus_list_lock);
hcd->poll_rh = 0;
del_timer_sync(&hcd->rh_timer);
hcd->driver->stop(hcd); hcd->driver->stop(hcd);
hcd->state = HC_STATE_HALT; hcd->state = HC_STATE_HALT;
hcd->poll_rh = 0;
del_timer_sync(&hcd->rh_timer);
if (hcd->irq >= 0) if (hcd->irq >= 0)
free_irq(hcd->irq, hcd); free_irq(hcd->irq, hcd);
usb_deregister_bus(&hcd->self); usb_deregister_bus(&hcd->self);
......
...@@ -68,6 +68,9 @@ struct usb_hcd { ...@@ -68,6 +68,9 @@ struct usb_hcd {
struct timer_list rh_timer; /* drives root-hub polling */ struct timer_list rh_timer; /* drives root-hub polling */
struct urb *status_urb; /* the current status urb */ struct urb *status_urb; /* the current status urb */
#ifdef CONFIG_PM
struct work_struct wakeup_work; /* for remote wakeup */
#endif
/* /*
* hardware info/state * hardware info/state
......
...@@ -1367,11 +1367,15 @@ int usb_new_device(struct usb_device *udev) ...@@ -1367,11 +1367,15 @@ int usb_new_device(struct usb_device *udev)
} }
#endif #endif
/* export the usbdev device-node for libusb */
udev->dev.devt = MKDEV(USB_DEVICE_MAJOR,
(((udev->bus->busnum-1) * 128) + (udev->devnum-1)));
/* Register the device. The device driver is responsible /* Register the device. The device driver is responsible
* for adding the device files to usbfs and sysfs and for * for adding the device files to sysfs and for configuring
* configuring the device. * the device.
*/ */
err = device_add (&udev->dev); err = device_add(&udev->dev);
if (err) { if (err) {
dev_err(&udev->dev, "can't device_add, error %d\n", err); dev_err(&udev->dev, "can't device_add, error %d\n", err);
goto fail; goto fail;
...@@ -1855,12 +1859,8 @@ static int remote_wakeup(struct usb_device *udev) ...@@ -1855,12 +1859,8 @@ static int remote_wakeup(struct usb_device *udev)
usb_lock_device(udev); usb_lock_device(udev);
if (udev->state == USB_STATE_SUSPENDED) { if (udev->state == USB_STATE_SUSPENDED) {
dev_dbg(&udev->dev, "usb %sresume\n", "wakeup-"); dev_dbg(&udev->dev, "usb %sresume\n", "wakeup-");
status = usb_autoresume_device(udev); usb_mark_last_busy(udev);
status = usb_external_resume_device(udev);
/* Give the interface drivers a chance to do something,
* then autosuspend the device again. */
if (status == 0)
usb_autosuspend_device(udev);
} }
usb_unlock_device(udev); usb_unlock_device(udev);
return status; return status;
...@@ -1984,13 +1984,6 @@ static inline int remote_wakeup(struct usb_device *udev) ...@@ -1984,13 +1984,6 @@ static inline int remote_wakeup(struct usb_device *udev)
#define hub_resume NULL #define hub_resume NULL
#endif #endif
void usb_resume_root_hub(struct usb_device *hdev)
{
struct usb_hub *hub = hdev_to_hub(hdev);
kick_khubd(hub);
}
/* USB 2.0 spec, 7.1.7.3 / fig 7-29: /* USB 2.0 spec, 7.1.7.3 / fig 7-29:
* *
......
...@@ -662,7 +662,7 @@ static void usbfs_add_device(struct usb_device *dev) ...@@ -662,7 +662,7 @@ static void usbfs_add_device(struct usb_device *dev)
sprintf (name, "%03d", dev->devnum); sprintf (name, "%03d", dev->devnum);
dev->usbfs_dentry = fs_create_file (name, devmode | S_IFREG, dev->usbfs_dentry = fs_create_file (name, devmode | S_IFREG,
dev->bus->usbfs_dentry, dev, dev->bus->usbfs_dentry, dev,
&usbfs_device_file_operations, &usbdev_file_operations,
devuid, devgid); devuid, devgid);
if (dev->usbfs_dentry == NULL) { if (dev->usbfs_dentry == NULL) {
err ("error creating usbfs device entry"); err ("error creating usbfs device entry");
......
...@@ -412,10 +412,24 @@ int usb_sg_init ( ...@@ -412,10 +412,24 @@ int usb_sg_init (
io->urbs [i]->status = -EINPROGRESS; io->urbs [i]->status = -EINPROGRESS;
io->urbs [i]->actual_length = 0; io->urbs [i]->actual_length = 0;
/*
* Some systems need to revert to PIO when DMA is temporarily
* unavailable. For their sakes, both transfer_buffer and
* transfer_dma are set when possible. However this can only
* work on systems without HIGHMEM, since DMA buffers located
* in high memory are not directly addressable by the CPU for
* PIO ... so when HIGHMEM is in use, transfer_buffer is NULL
* to prevent stale pointers and to help spot bugs.
*/
if (dma) { if (dma) {
/* hc may use _only_ transfer_dma */
io->urbs [i]->transfer_dma = sg_dma_address (sg + i); io->urbs [i]->transfer_dma = sg_dma_address (sg + i);
len = sg_dma_len (sg + i); len = sg_dma_len (sg + i);
#ifdef CONFIG_HIGHMEM
io->urbs[i]->transfer_buffer = NULL;
#else
io->urbs[i]->transfer_buffer =
page_address(sg[i].page) + sg[i].offset;
#endif
} else { } else {
/* hc may use _only_ transfer_buffer */ /* hc may use _only_ transfer_buffer */
io->urbs [i]->transfer_buffer = io->urbs [i]->transfer_buffer =
...@@ -1305,7 +1319,7 @@ int usb_reset_configuration(struct usb_device *dev) ...@@ -1305,7 +1319,7 @@ int usb_reset_configuration(struct usb_device *dev)
return 0; return 0;
} }
static void release_interface(struct device *dev) void usb_release_interface(struct device *dev)
{ {
struct usb_interface *intf = to_usb_interface(dev); struct usb_interface *intf = to_usb_interface(dev);
struct usb_interface_cache *intfc = struct usb_interface_cache *intfc =
...@@ -1315,6 +1329,67 @@ static void release_interface(struct device *dev) ...@@ -1315,6 +1329,67 @@ static void release_interface(struct device *dev)
kfree(intf); kfree(intf);
} }
#ifdef CONFIG_HOTPLUG
static int usb_if_uevent(struct device *dev, char **envp, int num_envp,
char *buffer, int buffer_size)
{
struct usb_device *usb_dev;
struct usb_interface *intf;
struct usb_host_interface *alt;
int i = 0;
int length = 0;
if (!dev)
return -ENODEV;
/* driver is often null here; dev_dbg() would oops */
pr_debug ("usb %s: uevent\n", dev->bus_id);
intf = to_usb_interface(dev);
usb_dev = interface_to_usbdev(intf);
alt = intf->cur_altsetting;
if (add_uevent_var(envp, num_envp, &i,
buffer, buffer_size, &length,
"INTERFACE=%d/%d/%d",
alt->desc.bInterfaceClass,
alt->desc.bInterfaceSubClass,
alt->desc.bInterfaceProtocol))
return -ENOMEM;
if (add_uevent_var(envp, num_envp, &i,
buffer, buffer_size, &length,
"MODALIAS=usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02Xic%02Xisc%02Xip%02X",
le16_to_cpu(usb_dev->descriptor.idVendor),
le16_to_cpu(usb_dev->descriptor.idProduct),
le16_to_cpu(usb_dev->descriptor.bcdDevice),
usb_dev->descriptor.bDeviceClass,
usb_dev->descriptor.bDeviceSubClass,
usb_dev->descriptor.bDeviceProtocol,
alt->desc.bInterfaceClass,
alt->desc.bInterfaceSubClass,
alt->desc.bInterfaceProtocol))
return -ENOMEM;
envp[i] = NULL;
return 0;
}
#else
static int usb_if_uevent(struct device *dev, char **envp,
int num_envp, char *buffer, int buffer_size)
{
return -ENODEV;
}
#endif /* CONFIG_HOTPLUG */
struct device_type usb_if_device_type = {
.name = "usb_interface",
.release = usb_release_interface,
.uevent = usb_if_uevent,
};
/* /*
* usb_set_configuration - Makes a particular device setting be current * usb_set_configuration - Makes a particular device setting be current
* @dev: the device whose configuration is being updated * @dev: the device whose configuration is being updated
...@@ -1478,8 +1553,8 @@ int usb_set_configuration(struct usb_device *dev, int configuration) ...@@ -1478,8 +1553,8 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
intf->dev.parent = &dev->dev; intf->dev.parent = &dev->dev;
intf->dev.driver = NULL; intf->dev.driver = NULL;
intf->dev.bus = &usb_bus_type; intf->dev.bus = &usb_bus_type;
intf->dev.type = &usb_if_device_type;
intf->dev.dma_mask = dev->dev.dma_mask; intf->dev.dma_mask = dev->dev.dma_mask;
intf->dev.release = release_interface;
device_initialize (&intf->dev); device_initialize (&intf->dev);
mark_quiesced(intf); mark_quiesced(intf);
sprintf (&intf->dev.bus_id[0], "%d-%s:%d.%d", sprintf (&intf->dev.bus_id[0], "%d-%s:%d.%d",
......
...@@ -42,7 +42,7 @@ static void usb_autosuspend_quirk(struct usb_device *udev) ...@@ -42,7 +42,7 @@ static void usb_autosuspend_quirk(struct usb_device *udev)
{ {
#ifdef CONFIG_USB_SUSPEND #ifdef CONFIG_USB_SUSPEND
/* disable autosuspend, but allow the user to re-enable it via sysfs */ /* disable autosuspend, but allow the user to re-enable it via sysfs */
udev->autosuspend_delay = 0; udev->autosuspend_disabled = 1;
#endif #endif
} }
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/string.h>
#include <linux/usb.h> #include <linux/usb.h>
#include "usb.h" #include "usb.h"
...@@ -116,6 +117,16 @@ show_speed(struct device *dev, struct device_attribute *attr, char *buf) ...@@ -116,6 +117,16 @@ show_speed(struct device *dev, struct device_attribute *attr, char *buf)
} }
static DEVICE_ATTR(speed, S_IRUGO, show_speed, NULL); static DEVICE_ATTR(speed, S_IRUGO, show_speed, NULL);
static ssize_t
show_busnum(struct device *dev, struct device_attribute *attr, char *buf)
{
struct usb_device *udev;
udev = to_usb_device(dev);
return sprintf(buf, "%d\n", udev->bus->busnum);
}
static DEVICE_ATTR(busnum, S_IRUGO, show_busnum, NULL);
static ssize_t static ssize_t
show_devnum(struct device *dev, struct device_attribute *attr, char *buf) show_devnum(struct device *dev, struct device_attribute *attr, char *buf)
{ {
...@@ -165,7 +176,7 @@ show_autosuspend(struct device *dev, struct device_attribute *attr, char *buf) ...@@ -165,7 +176,7 @@ show_autosuspend(struct device *dev, struct device_attribute *attr, char *buf)
{ {
struct usb_device *udev = to_usb_device(dev); struct usb_device *udev = to_usb_device(dev);
return sprintf(buf, "%u\n", udev->autosuspend_delay / HZ); return sprintf(buf, "%d\n", udev->autosuspend_delay / HZ);
} }
static ssize_t static ssize_t
...@@ -173,38 +184,114 @@ set_autosuspend(struct device *dev, struct device_attribute *attr, ...@@ -173,38 +184,114 @@ set_autosuspend(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count) const char *buf, size_t count)
{ {
struct usb_device *udev = to_usb_device(dev); struct usb_device *udev = to_usb_device(dev);
unsigned value, old; int value;
if (sscanf(buf, "%u", &value) != 1 || value >= INT_MAX/HZ) if (sscanf(buf, "%d", &value) != 1 || value >= INT_MAX/HZ ||
value <= - INT_MAX/HZ)
return -EINVAL; return -EINVAL;
value *= HZ; value *= HZ;
old = udev->autosuspend_delay;
udev->autosuspend_delay = value; udev->autosuspend_delay = value;
if (value > 0 && old == 0) if (value >= 0)
usb_try_autosuspend_device(udev); usb_try_autosuspend_device(udev);
else {
if (usb_autoresume_device(udev) == 0)
usb_autosuspend_device(udev);
}
return count; return count;
} }
static DEVICE_ATTR(autosuspend, S_IRUGO | S_IWUSR, static DEVICE_ATTR(autosuspend, S_IRUGO | S_IWUSR,
show_autosuspend, set_autosuspend); show_autosuspend, set_autosuspend);
static const char on_string[] = "on";
static const char auto_string[] = "auto";
static const char suspend_string[] = "suspend";
static ssize_t
show_level(struct device *dev, struct device_attribute *attr, char *buf)
{
struct usb_device *udev = to_usb_device(dev);
const char *p = auto_string;
if (udev->state == USB_STATE_SUSPENDED) {
if (udev->autoresume_disabled)
p = suspend_string;
} else {
if (udev->autosuspend_disabled)
p = on_string;
}
return sprintf(buf, "%s\n", p);
}
static ssize_t
set_level(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
struct usb_device *udev = to_usb_device(dev);
int len = count;
char *cp;
int rc = 0;
cp = memchr(buf, '\n', count);
if (cp)
len = cp - buf;
usb_lock_device(udev);
/* Setting the flags without calling usb_pm_lock is a subject to
* races, but who cares...
*/
if (len == sizeof on_string - 1 &&
strncmp(buf, on_string, len) == 0) {
udev->autosuspend_disabled = 1;
udev->autoresume_disabled = 0;
rc = usb_external_resume_device(udev);
} else if (len == sizeof auto_string - 1 &&
strncmp(buf, auto_string, len) == 0) {
udev->autosuspend_disabled = 0;
udev->autoresume_disabled = 0;
rc = usb_external_resume_device(udev);
} else if (len == sizeof suspend_string - 1 &&
strncmp(buf, suspend_string, len) == 0) {
udev->autosuspend_disabled = 0;
udev->autoresume_disabled = 1;
rc = usb_external_suspend_device(udev, PMSG_SUSPEND);
} else
rc = -EINVAL;
usb_unlock_device(udev);
return (rc < 0 ? rc : count);
}
static DEVICE_ATTR(level, S_IRUGO | S_IWUSR, show_level, set_level);
static char power_group[] = "power"; static char power_group[] = "power";
static int add_power_attributes(struct device *dev) static int add_power_attributes(struct device *dev)
{ {
int rc = 0; int rc = 0;
if (is_usb_device(dev)) if (is_usb_device(dev)) {
rc = sysfs_add_file_to_group(&dev->kobj, rc = sysfs_add_file_to_group(&dev->kobj,
&dev_attr_autosuspend.attr, &dev_attr_autosuspend.attr,
power_group); power_group);
if (rc == 0)
rc = sysfs_add_file_to_group(&dev->kobj,
&dev_attr_level.attr,
power_group);
}
return rc; return rc;
} }
static void remove_power_attributes(struct device *dev) static void remove_power_attributes(struct device *dev)
{ {
sysfs_remove_file_from_group(&dev->kobj,
&dev_attr_level.attr,
power_group);
sysfs_remove_file_from_group(&dev->kobj, sysfs_remove_file_from_group(&dev->kobj,
&dev_attr_autosuspend.attr, &dev_attr_autosuspend.attr,
power_group); power_group);
...@@ -270,6 +357,7 @@ static struct attribute *dev_attrs[] = { ...@@ -270,6 +357,7 @@ static struct attribute *dev_attrs[] = {
&dev_attr_bNumConfigurations.attr, &dev_attr_bNumConfigurations.attr,
&dev_attr_bMaxPacketSize0.attr, &dev_attr_bMaxPacketSize0.attr,
&dev_attr_speed.attr, &dev_attr_speed.attr,
&dev_attr_busnum.attr,
&dev_attr_devnum.attr, &dev_attr_devnum.attr,
&dev_attr_version.attr, &dev_attr_version.attr,
&dev_attr_maxchild.attr, &dev_attr_maxchild.attr,
......
...@@ -49,12 +49,13 @@ const char *usbcore_name = "usbcore"; ...@@ -49,12 +49,13 @@ const char *usbcore_name = "usbcore";
static int nousb; /* Disable USB when built into kernel image */ static int nousb; /* Disable USB when built into kernel image */
struct workqueue_struct *ksuspend_usb_wq; /* For autosuspend */ /* Workqueue for autosuspend and for remote wakeup of root hubs */
struct workqueue_struct *ksuspend_usb_wq;
#ifdef CONFIG_USB_SUSPEND #ifdef CONFIG_USB_SUSPEND
static int usb_autosuspend_delay = 2; /* Default delay value, static int usb_autosuspend_delay = 2; /* Default delay value,
* in seconds */ * in seconds */
module_param_named(autosuspend, usb_autosuspend_delay, uint, 0644); module_param_named(autosuspend, usb_autosuspend_delay, int, 0644);
MODULE_PARM_DESC(autosuspend, "default autosuspend delay"); MODULE_PARM_DESC(autosuspend, "default autosuspend delay");
#else #else
...@@ -196,6 +197,11 @@ static void usb_release_dev(struct device *dev) ...@@ -196,6 +197,11 @@ static void usb_release_dev(struct device *dev)
kfree(udev); kfree(udev);
} }
struct device_type usb_device_type = {
.name = "usb_device",
.release = usb_release_dev,
};
#ifdef CONFIG_PM #ifdef CONFIG_PM
static int ksuspend_usb_init(void) static int ksuspend_usb_init(void)
...@@ -211,27 +217,6 @@ static void ksuspend_usb_cleanup(void) ...@@ -211,27 +217,6 @@ static void ksuspend_usb_cleanup(void)
destroy_workqueue(ksuspend_usb_wq); destroy_workqueue(ksuspend_usb_wq);
} }
#ifdef CONFIG_USB_SUSPEND
/* usb_autosuspend_work - callback routine to autosuspend a USB device */
static void usb_autosuspend_work(struct work_struct *work)
{
struct usb_device *udev =
container_of(work, struct usb_device, autosuspend.work);
usb_pm_lock(udev);
udev->auto_pm = 1;
usb_suspend_both(udev, PMSG_SUSPEND);
usb_pm_unlock(udev);
}
#else
static void usb_autosuspend_work(struct work_struct *work)
{}
#endif /* CONFIG_USB_SUSPEND */
#else #else
#define ksuspend_usb_init() 0 #define ksuspend_usb_init() 0
...@@ -267,13 +252,10 @@ usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus, unsigned port1) ...@@ -267,13 +252,10 @@ usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus, unsigned port1)
device_initialize(&dev->dev); device_initialize(&dev->dev);
dev->dev.bus = &usb_bus_type; dev->dev.bus = &usb_bus_type;
dev->dev.type = &usb_device_type;
dev->dev.dma_mask = bus->controller->dma_mask; dev->dev.dma_mask = bus->controller->dma_mask;
dev->dev.release = usb_release_dev;
dev->state = USB_STATE_ATTACHED; dev->state = USB_STATE_ATTACHED;
/* This magic assignment distinguishes devices from interfaces */
dev->dev.platform_data = &usb_generic_driver;
INIT_LIST_HEAD(&dev->ep0.urb_list); INIT_LIST_HEAD(&dev->ep0.urb_list);
dev->ep0.desc.bLength = USB_DT_ENDPOINT_SIZE; dev->ep0.desc.bLength = USB_DT_ENDPOINT_SIZE;
dev->ep0.desc.bDescriptorType = USB_DT_ENDPOINT; dev->ep0.desc.bDescriptorType = USB_DT_ENDPOINT;
...@@ -902,9 +884,9 @@ static int __init usb_init(void) ...@@ -902,9 +884,9 @@ static int __init usb_init(void)
retval = usb_register(&usbfs_driver); retval = usb_register(&usbfs_driver);
if (retval) if (retval)
goto driver_register_failed; goto driver_register_failed;
retval = usbdev_init(); retval = usb_devio_init();
if (retval) if (retval)
goto usbdevice_init_failed; goto usb_devio_init_failed;
retval = usbfs_init(); retval = usbfs_init();
if (retval) if (retval)
goto fs_init_failed; goto fs_init_failed;
...@@ -919,8 +901,8 @@ static int __init usb_init(void) ...@@ -919,8 +901,8 @@ static int __init usb_init(void)
hub_init_failed: hub_init_failed:
usbfs_cleanup(); usbfs_cleanup();
fs_init_failed: fs_init_failed:
usbdev_cleanup(); usb_devio_cleanup();
usbdevice_init_failed: usb_devio_init_failed:
usb_deregister(&usbfs_driver); usb_deregister(&usbfs_driver);
driver_register_failed: driver_register_failed:
usb_major_cleanup(); usb_major_cleanup();
...@@ -947,7 +929,7 @@ static void __exit usb_exit(void) ...@@ -947,7 +929,7 @@ static void __exit usb_exit(void)
usb_major_cleanup(); usb_major_cleanup();
usbfs_cleanup(); usbfs_cleanup();
usb_deregister(&usbfs_driver); usb_deregister(&usbfs_driver);
usbdev_cleanup(); usb_devio_cleanup();
usb_hub_cleanup(); usb_hub_cleanup();
usb_host_cleanup(); usb_host_cleanup();
bus_unregister(&usb_bus_type); bus_unregister(&usb_bus_type);
......
...@@ -21,7 +21,6 @@ extern char *usb_cache_string(struct usb_device *udev, int index); ...@@ -21,7 +21,6 @@ extern char *usb_cache_string(struct usb_device *udev, int index);
extern int usb_set_configuration(struct usb_device *dev, int configuration); extern int usb_set_configuration(struct usb_device *dev, int configuration);
extern void usb_kick_khubd(struct usb_device *dev); extern void usb_kick_khubd(struct usb_device *dev);
extern void usb_resume_root_hub(struct usb_device *dev);
extern int usb_match_device(struct usb_device *dev, extern int usb_match_device(struct usb_device *dev,
const struct usb_device_id *id); const struct usb_device_id *id);
...@@ -34,10 +33,12 @@ extern void usb_host_cleanup(void); ...@@ -34,10 +33,12 @@ extern void usb_host_cleanup(void);
#ifdef CONFIG_PM #ifdef CONFIG_PM
extern int usb_suspend_both(struct usb_device *udev, pm_message_t msg); extern void usb_autosuspend_work(struct work_struct *work);
extern int usb_resume_both(struct usb_device *udev);
extern int usb_port_suspend(struct usb_device *dev); extern int usb_port_suspend(struct usb_device *dev);
extern int usb_port_resume(struct usb_device *dev); extern int usb_port_resume(struct usb_device *dev);
extern int usb_external_suspend_device(struct usb_device *udev,
pm_message_t msg);
extern int usb_external_resume_device(struct usb_device *udev);
static inline void usb_pm_lock(struct usb_device *udev) static inline void usb_pm_lock(struct usb_device *udev)
{ {
...@@ -51,11 +52,6 @@ static inline void usb_pm_unlock(struct usb_device *udev) ...@@ -51,11 +52,6 @@ static inline void usb_pm_unlock(struct usb_device *udev)
#else #else
#define usb_suspend_both(udev, msg) 0
static inline int usb_resume_both(struct usb_device *udev)
{
return 0;
}
#define usb_port_suspend(dev) 0 #define usb_port_suspend(dev) 0
#define usb_port_resume(dev) 0 #define usb_port_resume(dev) 0
static inline void usb_pm_lock(struct usb_device *udev) {} static inline void usb_pm_lock(struct usb_device *udev) {}
...@@ -82,15 +78,13 @@ static inline int usb_autoresume_device(struct usb_device *udev) ...@@ -82,15 +78,13 @@ static inline int usb_autoresume_device(struct usb_device *udev)
extern struct workqueue_struct *ksuspend_usb_wq; extern struct workqueue_struct *ksuspend_usb_wq;
extern struct bus_type usb_bus_type; extern struct bus_type usb_bus_type;
extern struct device_type usb_device_type;
extern struct device_type usb_if_device_type;
extern struct usb_device_driver usb_generic_driver; extern struct usb_device_driver usb_generic_driver;
/* Here's how we tell apart devices and interfaces. Luckily there's
* no such thing as a platform USB device, so we can steal the use
* of the platform_data field. */
static inline int is_usb_device(const struct device *dev) static inline int is_usb_device(const struct device *dev)
{ {
return dev->platform_data == &usb_generic_driver; return dev->type == &usb_device_type;
} }
/* Do the same for device drivers and interface drivers. */ /* Do the same for device drivers and interface drivers. */
...@@ -126,11 +120,11 @@ extern const char *usbcore_name; ...@@ -126,11 +120,11 @@ extern const char *usbcore_name;
extern struct mutex usbfs_mutex; extern struct mutex usbfs_mutex;
extern struct usb_driver usbfs_driver; extern struct usb_driver usbfs_driver;
extern const struct file_operations usbfs_devices_fops; extern const struct file_operations usbfs_devices_fops;
extern const struct file_operations usbfs_device_file_operations; extern const struct file_operations usbdev_file_operations;
extern void usbfs_conn_disc_event(void); extern void usbfs_conn_disc_event(void);
extern int usbdev_init(void); extern int usb_devio_init(void);
extern void usbdev_cleanup(void); extern void usb_devio_cleanup(void);
struct dev_state { struct dev_state {
struct list_head list; /* state list */ struct list_head list; /* state list */
......
...@@ -68,6 +68,27 @@ choice ...@@ -68,6 +68,27 @@ choice
Many controller drivers are platform-specific; these Many controller drivers are platform-specific; these
often need board-specific hooks. often need board-specific hooks.
config USB_GADGET_FSL_USB2
boolean "Freescale Highspeed USB DR Peripheral Controller"
depends on MPC834x || PPC_MPC831x
select USB_GADGET_DUALSPEED
help
Some of Freescale PowerPC processors have a High Speed
Dual-Role(DR) USB controller, which supports device mode.
The number of programmable endpoints is different through
SOC revisions.
Say "y" to link the driver statically, or "m" to build a
dynamically linked module called "fsl_usb2_udc" and force
all gadget drivers to also be dynamically linked.
config USB_FSL_USB2
tristate
depends on USB_GADGET_FSL_USB2
default USB_GADGET
select USB_GADGET_SELECTED
config USB_GADGET_NET2280 config USB_GADGET_NET2280
boolean "NetChip 228x" boolean "NetChip 228x"
depends on PCI depends on PCI
...@@ -370,6 +391,7 @@ config USB_GADGETFS ...@@ -370,6 +391,7 @@ config USB_GADGETFS
config USB_FILE_STORAGE config USB_FILE_STORAGE
tristate "File-backed Storage Gadget" tristate "File-backed Storage Gadget"
depends on BLOCK
help help
The File-backed Storage Gadget acts as a USB Mass Storage The File-backed Storage Gadget acts as a USB Mass Storage
disk drive. As its storage repository it can use a regular disk drive. As its storage repository it can use a regular
......
...@@ -8,6 +8,7 @@ obj-$(CONFIG_USB_GOKU) += goku_udc.o ...@@ -8,6 +8,7 @@ obj-$(CONFIG_USB_GOKU) += goku_udc.o
obj-$(CONFIG_USB_OMAP) += omap_udc.o obj-$(CONFIG_USB_OMAP) += omap_udc.o
obj-$(CONFIG_USB_LH7A40X) += lh7a40x_udc.o obj-$(CONFIG_USB_LH7A40X) += lh7a40x_udc.o
obj-$(CONFIG_USB_AT91) += at91_udc.o obj-$(CONFIG_USB_AT91) += at91_udc.o
obj-$(CONFIG_USB_FSL_USB2) += fsl_usb2_udc.o
# #
# USB gadget drivers # USB gadget drivers
......
...@@ -282,6 +282,9 @@ MODULE_PARM_DESC(host_addr, "Host Ethernet Address"); ...@@ -282,6 +282,9 @@ MODULE_PARM_DESC(host_addr, "Host Ethernet Address");
#define DEV_CONFIG_CDC #define DEV_CONFIG_CDC
#endif #endif
#ifdef CONFIG_USB_GADGET_FSL_USB2
#define DEV_CONFIG_CDC
#endif
/* For CDC-incapable hardware, choose the simple cdc subset. /* For CDC-incapable hardware, choose the simple cdc subset.
* Anything that talks bulk (without notable bugs) can do this. * Anything that talks bulk (without notable bugs) can do this.
...@@ -1735,7 +1738,8 @@ rx_submit (struct eth_dev *dev, struct usb_request *req, gfp_t gfp_flags) ...@@ -1735,7 +1738,8 @@ rx_submit (struct eth_dev *dev, struct usb_request *req, gfp_t gfp_flags)
defer_kevent (dev, WORK_RX_MEMORY); defer_kevent (dev, WORK_RX_MEMORY);
if (retval) { if (retval) {
DEBUG (dev, "rx submit --> %d\n", retval); DEBUG (dev, "rx submit --> %d\n", retval);
dev_kfree_skb_any (skb); if (skb)
dev_kfree_skb_any(skb);
spin_lock(&dev->req_lock); spin_lock(&dev->req_lock);
list_add (&req->list, &dev->rx_reqs); list_add (&req->list, &dev->rx_reqs);
spin_unlock(&dev->req_lock); spin_unlock(&dev->req_lock);
......
This diff is collapsed.
This diff is collapsed.
...@@ -99,6 +99,12 @@ ...@@ -99,6 +99,12 @@
#define gadget_is_imx(g) 0 #define gadget_is_imx(g) 0
#endif #endif
#ifdef CONFIG_USB_GADGET_FSL_USB2
#define gadget_is_fsl_usb2(g) !strcmp("fsl-usb2-udc", (g)->name)
#else
#define gadget_is_fsl_usb2(g) 0
#endif
/* Mentor high speed function controller */ /* Mentor high speed function controller */
#ifdef CONFIG_USB_GADGET_MUSBHSFC #ifdef CONFIG_USB_GADGET_MUSBHSFC
#define gadget_is_musbhsfc(g) !strcmp("musbhsfc_udc", (g)->name) #define gadget_is_musbhsfc(g) !strcmp("musbhsfc_udc", (g)->name)
...@@ -177,5 +183,7 @@ static inline int usb_gadget_controller_number(struct usb_gadget *gadget) ...@@ -177,5 +183,7 @@ static inline int usb_gadget_controller_number(struct usb_gadget *gadget)
return 0x17; return 0x17;
else if (gadget_is_husb2dev(gadget)) else if (gadget_is_husb2dev(gadget))
return 0x18; return 0x18;
else if (gadget_is_fsl_usb2(gadget))
return 0x19;
return -ENOENT; return -ENOENT;
} }
...@@ -1464,20 +1464,6 @@ udc_proc_read(char *page, char **start, off_t off, int count, ...@@ -1464,20 +1464,6 @@ udc_proc_read(char *page, char **start, off_t off, int count,
#endif /* CONFIG_USB_GADGET_DEBUG_FILES */ #endif /* CONFIG_USB_GADGET_DEBUG_FILES */
/* "function" sysfs attribute */
static ssize_t
show_function (struct device *_dev, struct device_attribute *attr, char *buf)
{
struct pxa2xx_udc *dev = dev_get_drvdata (_dev);
if (!dev->driver
|| !dev->driver->function
|| strlen (dev->driver->function) > PAGE_SIZE)
return 0;
return scnprintf (buf, PAGE_SIZE, "%s\n", dev->driver->function);
}
static DEVICE_ATTR (function, S_IRUGO, show_function, NULL);
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
/* /*
...@@ -1635,18 +1621,20 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) ...@@ -1635,18 +1621,20 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
dev->gadget.dev.driver = &driver->driver; dev->gadget.dev.driver = &driver->driver;
dev->pullup = 1; dev->pullup = 1;
device_add (&dev->gadget.dev); retval = device_add (&dev->gadget.dev);
if (retval) {
fail:
dev->driver = NULL;
dev->gadget.dev.driver = NULL;
return retval;
}
retval = driver->bind(&dev->gadget); retval = driver->bind(&dev->gadget);
if (retval) { if (retval) {
DMSG("bind to driver %s --> error %d\n", DMSG("bind to driver %s --> error %d\n",
driver->driver.name, retval); driver->driver.name, retval);
device_del (&dev->gadget.dev); device_del (&dev->gadget.dev);
goto fail;
dev->driver = NULL;
dev->gadget.dev.driver = NULL;
return retval;
} }
device_create_file(dev->dev, &dev_attr_function);
/* ... then enable host detection and ep0; and we're ready /* ... then enable host detection and ep0; and we're ready
* for set_configuration as well as eventual disconnect. * for set_configuration as well as eventual disconnect.
...@@ -1704,7 +1692,6 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) ...@@ -1704,7 +1692,6 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
dev->driver = NULL; dev->driver = NULL;
device_del (&dev->gadget.dev); device_del (&dev->gadget.dev);
device_remove_file(dev->dev, &dev_attr_function);
DMSG("unregistered gadget driver '%s'\n", driver->driver.name); DMSG("unregistered gadget driver '%s'\n", driver->driver.name);
dump_state(dev); dump_state(dev);
...@@ -2479,7 +2466,7 @@ static struct pxa2xx_udc memory = { ...@@ -2479,7 +2466,7 @@ static struct pxa2xx_udc memory = {
static int __init pxa2xx_udc_probe(struct platform_device *pdev) static int __init pxa2xx_udc_probe(struct platform_device *pdev)
{ {
struct pxa2xx_udc *dev = &memory; struct pxa2xx_udc *dev = &memory;
int retval, out_dma = 1, vbus_irq; int retval, out_dma = 1, vbus_irq, irq;
u32 chiprev; u32 chiprev;
/* insist on Intel/ARM/XScale */ /* insist on Intel/ARM/XScale */
...@@ -2522,7 +2509,11 @@ static int __init pxa2xx_udc_probe(struct platform_device *pdev) ...@@ -2522,7 +2509,11 @@ static int __init pxa2xx_udc_probe(struct platform_device *pdev)
return -ENODEV; return -ENODEV;
} }
pr_debug("%s: IRQ %d%s%s%s\n", driver_name, IRQ_USB, irq = platform_get_irq(pdev, 0);
if (irq < 0)
return -ENODEV;
pr_debug("%s: IRQ %d%s%s%s\n", driver_name, irq,
dev->has_cfr ? "" : " (!cfr)", dev->has_cfr ? "" : " (!cfr)",
out_dma ? "" : " (broken dma-out)", out_dma ? "" : " (broken dma-out)",
SIZE_STR DMASTR SIZE_STR DMASTR
...@@ -2570,11 +2561,11 @@ static int __init pxa2xx_udc_probe(struct platform_device *pdev) ...@@ -2570,11 +2561,11 @@ static int __init pxa2xx_udc_probe(struct platform_device *pdev)
dev->vbus = is_vbus_present(); dev->vbus = is_vbus_present();
/* irq setup after old hardware state is cleaned up */ /* irq setup after old hardware state is cleaned up */
retval = request_irq(IRQ_USB, pxa2xx_udc_irq, retval = request_irq(irq, pxa2xx_udc_irq,
IRQF_DISABLED, driver_name, dev); IRQF_DISABLED, driver_name, dev);
if (retval != 0) { if (retval != 0) {
printk(KERN_ERR "%s: can't get irq %i, err %d\n", printk(KERN_ERR "%s: can't get irq %d, err %d\n",
driver_name, IRQ_USB, retval); driver_name, irq, retval);
return -EBUSY; return -EBUSY;
} }
dev->got_irq = 1; dev->got_irq = 1;
...@@ -2589,7 +2580,7 @@ static int __init pxa2xx_udc_probe(struct platform_device *pdev) ...@@ -2589,7 +2580,7 @@ static int __init pxa2xx_udc_probe(struct platform_device *pdev)
printk(KERN_ERR "%s: can't get irq %i, err %d\n", printk(KERN_ERR "%s: can't get irq %i, err %d\n",
driver_name, LUBBOCK_USB_DISC_IRQ, retval); driver_name, LUBBOCK_USB_DISC_IRQ, retval);
lubbock_fail0: lubbock_fail0:
free_irq(IRQ_USB, dev); free_irq(irq, dev);
return -EBUSY; return -EBUSY;
} }
retval = request_irq(LUBBOCK_USB_IRQ, retval = request_irq(LUBBOCK_USB_IRQ,
...@@ -2616,7 +2607,7 @@ static int __init pxa2xx_udc_probe(struct platform_device *pdev) ...@@ -2616,7 +2607,7 @@ static int __init pxa2xx_udc_probe(struct platform_device *pdev)
if (retval != 0) { if (retval != 0) {
printk(KERN_ERR "%s: can't get irq %i, err %d\n", printk(KERN_ERR "%s: can't get irq %i, err %d\n",
driver_name, vbus_irq, retval); driver_name, vbus_irq, retval);
free_irq(IRQ_USB, dev); free_irq(irq, dev);
return -EBUSY; return -EBUSY;
} }
} }
...@@ -2641,7 +2632,7 @@ static int __exit pxa2xx_udc_remove(struct platform_device *pdev) ...@@ -2641,7 +2632,7 @@ static int __exit pxa2xx_udc_remove(struct platform_device *pdev)
remove_proc_files(); remove_proc_files();
if (dev->got_irq) { if (dev->got_irq) {
free_irq(IRQ_USB, dev); free_irq(platform_get_irq(pdev, 0), dev);
dev->got_irq = 0; dev->got_irq = 0;
} }
#ifdef CONFIG_ARCH_LUBBOCK #ifdef CONFIG_ARCH_LUBBOCK
...@@ -2701,7 +2692,6 @@ static int pxa2xx_udc_resume(struct platform_device *dev) ...@@ -2701,7 +2692,6 @@ static int pxa2xx_udc_resume(struct platform_device *dev)
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
static struct platform_driver udc_driver = { static struct platform_driver udc_driver = {
.probe = pxa2xx_udc_probe,
.shutdown = pxa2xx_udc_shutdown, .shutdown = pxa2xx_udc_shutdown,
.remove = __exit_p(pxa2xx_udc_remove), .remove = __exit_p(pxa2xx_udc_remove),
.suspend = pxa2xx_udc_suspend, .suspend = pxa2xx_udc_suspend,
...@@ -2715,7 +2705,7 @@ static struct platform_driver udc_driver = { ...@@ -2715,7 +2705,7 @@ static struct platform_driver udc_driver = {
static int __init udc_init(void) static int __init udc_init(void)
{ {
printk(KERN_INFO "%s: version %s\n", driver_name, DRIVER_VERSION); printk(KERN_INFO "%s: version %s\n", driver_name, DRIVER_VERSION);
return platform_driver_register(&udc_driver); return platform_driver_probe(&udc_driver, pxa2xx_udc_probe);
} }
module_init(udc_init); module_init(udc_init);
......
...@@ -195,7 +195,7 @@ struct rndis_packet_msg_type ...@@ -195,7 +195,7 @@ struct rndis_packet_msg_type
__le32 PerPacketInfoLength; __le32 PerPacketInfoLength;
__le32 VcHandle; __le32 VcHandle;
__le32 Reserved; __le32 Reserved;
}; } __attribute__ ((packed));
struct rndis_config_parameter struct rndis_config_parameter
{ {
......
...@@ -15,4 +15,3 @@ obj-$(CONFIG_USB_UHCI_HCD) += uhci-hcd.o ...@@ -15,4 +15,3 @@ obj-$(CONFIG_USB_UHCI_HCD) += uhci-hcd.o
obj-$(CONFIG_USB_SL811_HCD) += sl811-hcd.o obj-$(CONFIG_USB_SL811_HCD) += sl811-hcd.o
obj-$(CONFIG_USB_SL811_CS) += sl811_cs.o obj-$(CONFIG_USB_SL811_CS) += sl811_cs.o
obj-$(CONFIG_USB_U132_HCD) += u132-hcd.o obj-$(CONFIG_USB_U132_HCD) += u132-hcd.o
obj-$(CONFIG_ETRAX_ARCH_V10) += hc_crisv10.o
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
#define FSL_SOC_USB_SNOOP1 0x400 /* NOTE: big-endian */ #define FSL_SOC_USB_SNOOP1 0x400 /* NOTE: big-endian */
#define FSL_SOC_USB_SNOOP2 0x404 /* NOTE: big-endian */ #define FSL_SOC_USB_SNOOP2 0x404 /* NOTE: big-endian */
#define FSL_SOC_USB_AGECNTTHRSH 0x408 /* NOTE: big-endian */ #define FSL_SOC_USB_AGECNTTHRSH 0x408 /* NOTE: big-endian */
#define FSL_SOC_USB_SICTRL 0x40c /* NOTE: big-endian */ #define FSL_SOC_USB_PRICTRL 0x40c /* NOTE: big-endian */
#define FSL_SOC_USB_PRICTRL 0x410 /* NOTE: big-endian */ #define FSL_SOC_USB_SICTRL 0x410 /* NOTE: big-endian */
#define FSL_SOC_USB_CTRL 0x500 /* NOTE: big-endian */ #define FSL_SOC_USB_CTRL 0x500 /* NOTE: big-endian */
#endif /* _EHCI_FSL_H */ #endif /* _EHCI_FSL_H */
...@@ -136,6 +136,10 @@ static int ehci_bus_resume (struct usb_hcd *hcd) ...@@ -136,6 +136,10 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
/* restore CMD_RUN, framelist size, and irq threshold */ /* restore CMD_RUN, framelist size, and irq threshold */
ehci_writel(ehci, ehci->command, &ehci->regs->command); ehci_writel(ehci, ehci->command, &ehci->regs->command);
/* Some controller/firmware combinations need a delay during which
* they set up the port statuses. See Bugzilla #8190. */
mdelay(8);
/* manually resume the ports we suspended during bus_suspend() */ /* manually resume the ports we suspended during bus_suspend() */
i = HCS_N_PORTS (ehci->hcs_params); i = HCS_N_PORTS (ehci->hcs_params);
while (i--) { while (i--) {
......
This diff is collapsed.
This diff is collapsed.
...@@ -20,10 +20,16 @@ ...@@ -20,10 +20,16 @@
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
static int broken_suspend(struct usb_hcd *hcd)
{
device_init_wakeup(&hcd->self.root_hub->dev, 0);
return 0;
}
/* AMD 756, for most chips (early revs), corrupts register /* AMD 756, for most chips (early revs), corrupts register
* values on read ... so enable the vendor workaround. * values on read ... so enable the vendor workaround.
*/ */
static int __devinit ohci_quirk_amd756(struct usb_hcd *hcd) static int ohci_quirk_amd756(struct usb_hcd *hcd)
{ {
struct ohci_hcd *ohci = hcd_to_ohci (hcd); struct ohci_hcd *ohci = hcd_to_ohci (hcd);
...@@ -31,16 +37,14 @@ static int __devinit ohci_quirk_amd756(struct usb_hcd *hcd) ...@@ -31,16 +37,14 @@ static int __devinit ohci_quirk_amd756(struct usb_hcd *hcd)
ohci_dbg (ohci, "AMD756 erratum 4 workaround\n"); ohci_dbg (ohci, "AMD756 erratum 4 workaround\n");
/* also erratum 10 (suspend/resume issues) */ /* also erratum 10 (suspend/resume issues) */
device_init_wakeup(&hcd->self.root_hub->dev, 0); return broken_suspend(hcd);
return 0;
} }
/* Apple's OHCI driver has a lot of bizarre workarounds /* Apple's OHCI driver has a lot of bizarre workarounds
* for this chip. Evidently control and bulk lists * for this chip. Evidently control and bulk lists
* can get confused. (B&W G3 models, and ...) * can get confused. (B&W G3 models, and ...)
*/ */
static int __devinit ohci_quirk_opti(struct usb_hcd *hcd) static int ohci_quirk_opti(struct usb_hcd *hcd)
{ {
struct ohci_hcd *ohci = hcd_to_ohci (hcd); struct ohci_hcd *ohci = hcd_to_ohci (hcd);
...@@ -53,7 +57,7 @@ static int __devinit ohci_quirk_opti(struct usb_hcd *hcd) ...@@ -53,7 +57,7 @@ static int __devinit ohci_quirk_opti(struct usb_hcd *hcd)
* identify the USB (fn2). This quirk might apply to more or * identify the USB (fn2). This quirk might apply to more or
* even all NSC stuff. * even all NSC stuff.
*/ */
static int __devinit ohci_quirk_ns(struct usb_hcd *hcd) static int ohci_quirk_ns(struct usb_hcd *hcd)
{ {
struct pci_dev *pdev = to_pci_dev(hcd->self.controller); struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
struct pci_dev *b; struct pci_dev *b;
...@@ -75,7 +79,7 @@ static int __devinit ohci_quirk_ns(struct usb_hcd *hcd) ...@@ -75,7 +79,7 @@ static int __devinit ohci_quirk_ns(struct usb_hcd *hcd)
* delays before control or bulk queues get re-activated * delays before control or bulk queues get re-activated
* in finish_unlinks() * in finish_unlinks()
*/ */
static int __devinit ohci_quirk_zfmicro(struct usb_hcd *hcd) static int ohci_quirk_zfmicro(struct usb_hcd *hcd)
{ {
struct ohci_hcd *ohci = hcd_to_ohci (hcd); struct ohci_hcd *ohci = hcd_to_ohci (hcd);
...@@ -88,7 +92,7 @@ static int __devinit ohci_quirk_zfmicro(struct usb_hcd *hcd) ...@@ -88,7 +92,7 @@ static int __devinit ohci_quirk_zfmicro(struct usb_hcd *hcd)
/* Check for Toshiba SCC OHCI which has big endian registers /* Check for Toshiba SCC OHCI which has big endian registers
* and little endian in memory data structures * and little endian in memory data structures
*/ */
static int __devinit ohci_quirk_toshiba_scc(struct usb_hcd *hcd) static int ohci_quirk_toshiba_scc(struct usb_hcd *hcd)
{ {
struct ohci_hcd *ohci = hcd_to_ohci (hcd); struct ohci_hcd *ohci = hcd_to_ohci (hcd);
...@@ -129,6 +133,18 @@ static const struct pci_device_id ohci_pci_quirks[] = { ...@@ -129,6 +133,18 @@ static const struct pci_device_id ohci_pci_quirks[] = {
PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA_2, 0x01b6), PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA_2, 0x01b6),
.driver_data = (unsigned long)ohci_quirk_toshiba_scc, .driver_data = (unsigned long)ohci_quirk_toshiba_scc,
}, },
{
/* Toshiba portege 4000 */
.vendor = PCI_VENDOR_ID_AL,
.device = 0x5237,
.subvendor = PCI_VENDOR_ID_TOSHIBA_2,
.subdevice = 0x0004,
.driver_data = (unsigned long) broken_suspend,
},
{
PCI_DEVICE(PCI_VENDOR_ID_ITE, 0x8152),
.driver_data = (unsigned long) broken_suspend,
},
/* FIXME for some of the early AMD 760 southbridges, OHCI /* FIXME for some of the early AMD 760 southbridges, OHCI
* won't work at all. blacklist them. * won't work at all. blacklist them.
*/ */
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment