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: (81 commits) [PATCH] USB: omninet: fix up debugging comments [PATCH] USB serial: add navman driver [PATCH] USB: Fix irda-usb use after use [PATCH] USB: rtl8150 small fix [PATCH] USB: ftdi_sio: add Icom ID1 USB product and vendor ids [PATCH] USB: cp2101: add new device IDs [PATCH] USB: fix check_ctrlrecip to allow control transfers in state ADDRESS [PATCH] USB: vicam.c: fix a NULL pointer dereference [PATCH] USB: ZC0301 driver bugfix [PATCH] USB: add support for Creativelabs Silvercrest USB keyboard [PATCH] USB: storage: new unusual_devs.h entry: Mitsumi 7in1 Card Reader [PATCH] USB: storage: unusual_devs.h entry 0420:0001 [PATCH] USB: storage: another unusual_devs.h entry [PATCH] USB: storage: sandisk unusual_devices entry [PATCH] USB: fix initdata issue in isp116x-hcd [PATCH] USB: usbcore: usb_set_configuration oops (NULL ptr dereference) [PATCH] USB: usbcore: Don't assume a USB configuration includes any interfaces [PATCH] USB: ub 03 drop stall clearing [PATCH] USB: ub 02 remove diag [PATCH] USB: ub 01 remove first_open ...
This commit is contained in:
@@ -57,6 +57,7 @@
|
||||
#include <linux/usb.h>
|
||||
#include <linux/smp_lock.h>
|
||||
#include <linux/usbdevice_fs.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <asm/uaccess.h>
|
||||
|
||||
#include "usb.h"
|
||||
@@ -570,7 +571,7 @@ static ssize_t usb_device_read(struct file *file, char __user *buf, size_t nbyte
|
||||
if (!access_ok(VERIFY_WRITE, buf, nbytes))
|
||||
return -EFAULT;
|
||||
|
||||
down (&usb_bus_list_lock);
|
||||
mutex_lock(&usb_bus_list_lock);
|
||||
/* print devices for all busses */
|
||||
list_for_each_entry(bus, &usb_bus_list, bus_list) {
|
||||
/* recurse through all children of the root hub */
|
||||
@@ -580,12 +581,12 @@ static ssize_t usb_device_read(struct file *file, char __user *buf, size_t nbyte
|
||||
ret = usb_device_dump(&buf, &nbytes, &skip_bytes, ppos, bus->root_hub, bus, 0, 0, 0);
|
||||
usb_unlock_device(bus->root_hub);
|
||||
if (ret < 0) {
|
||||
up(&usb_bus_list_lock);
|
||||
mutex_unlock(&usb_bus_list_lock);
|
||||
return ret;
|
||||
}
|
||||
total_written += ret;
|
||||
}
|
||||
up (&usb_bus_list_lock);
|
||||
mutex_unlock(&usb_bus_list_lock);
|
||||
return total_written;
|
||||
}
|
||||
|
||||
|
||||
@@ -134,26 +134,21 @@ static ssize_t usbdev_read(struct file *file, char __user *buf, size_t nbytes, l
|
||||
}
|
||||
|
||||
if (pos < sizeof(struct usb_device_descriptor)) {
|
||||
struct usb_device_descriptor *desc = kmalloc(sizeof(*desc), GFP_KERNEL);
|
||||
if (!desc) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
memcpy(desc, &dev->descriptor, sizeof(dev->descriptor));
|
||||
le16_to_cpus(&desc->bcdUSB);
|
||||
le16_to_cpus(&desc->idVendor);
|
||||
le16_to_cpus(&desc->idProduct);
|
||||
le16_to_cpus(&desc->bcdDevice);
|
||||
struct usb_device_descriptor temp_desc ; /* 18 bytes - fits on the stack */
|
||||
|
||||
memcpy(&temp_desc, &dev->descriptor, sizeof(dev->descriptor));
|
||||
le16_to_cpus(&temp_desc.bcdUSB);
|
||||
le16_to_cpus(&temp_desc.idVendor);
|
||||
le16_to_cpus(&temp_desc.idProduct);
|
||||
le16_to_cpus(&temp_desc.bcdDevice);
|
||||
|
||||
len = sizeof(struct usb_device_descriptor) - pos;
|
||||
if (len > nbytes)
|
||||
len = nbytes;
|
||||
if (copy_to_user(buf, ((char *)desc) + pos, len)) {
|
||||
kfree(desc);
|
||||
if (copy_to_user(buf, ((char *)&temp_desc) + pos, len)) {
|
||||
ret = -EFAULT;
|
||||
goto err;
|
||||
}
|
||||
kfree(desc);
|
||||
|
||||
*ppos += len;
|
||||
buf += len;
|
||||
@@ -498,7 +493,8 @@ static int check_ctrlrecip(struct dev_state *ps, unsigned int requesttype, unsig
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (ps->dev->state != USB_STATE_CONFIGURED)
|
||||
if (ps->dev->state != USB_STATE_ADDRESS
|
||||
&& ps->dev->state != USB_STATE_CONFIGURED)
|
||||
return -EHOSTUNREACH;
|
||||
if (USB_TYPE_VENDOR == (USB_TYPE_MASK & requesttype))
|
||||
return 0;
|
||||
|
||||
@@ -264,14 +264,19 @@ int usb_hcd_pci_suspend (struct pci_dev *dev, pm_message_t message)
|
||||
*/
|
||||
retval = pci_set_power_state (dev, PCI_D3hot);
|
||||
if (retval == 0) {
|
||||
dev_dbg (hcd->self.controller, "--> PCI D3\n");
|
||||
int wake = device_can_wakeup(&hcd->self.root_hub->dev);
|
||||
|
||||
wake = wake && device_may_wakeup(hcd->self.controller);
|
||||
|
||||
dev_dbg (hcd->self.controller, "--> PCI D3%s\n",
|
||||
wake ? "/wakeup" : "");
|
||||
|
||||
/* Ignore these return values. We rely on pci code to
|
||||
* reject requests the hardware can't implement, rather
|
||||
* than coding the same thing.
|
||||
*/
|
||||
(void) pci_enable_wake (dev, PCI_D3hot, hcd->remote_wakeup);
|
||||
(void) pci_enable_wake (dev, PCI_D3cold, hcd->remote_wakeup);
|
||||
(void) pci_enable_wake (dev, PCI_D3hot, wake);
|
||||
(void) pci_enable_wake (dev, PCI_D3cold, wake);
|
||||
} else {
|
||||
dev_dbg (&dev->dev, "PCI D3 suspend fail, %d\n",
|
||||
retval);
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include <asm/scatterlist.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/byteorder.h>
|
||||
|
||||
@@ -93,7 +94,7 @@ struct usb_busmap {
|
||||
static struct usb_busmap busmap;
|
||||
|
||||
/* used when updating list of hcds */
|
||||
DECLARE_MUTEX (usb_bus_list_lock); /* exported only for usbfs */
|
||||
DEFINE_MUTEX(usb_bus_list_lock); /* exported only for usbfs */
|
||||
EXPORT_SYMBOL_GPL (usb_bus_list_lock);
|
||||
|
||||
/* used for controlling access to virtual root hubs */
|
||||
@@ -366,21 +367,39 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb)
|
||||
|
||||
/* DEVICE REQUESTS */
|
||||
|
||||
/* The root hub's remote wakeup enable bit is implemented using
|
||||
* driver model wakeup flags. If this system supports wakeup
|
||||
* through USB, userspace may change the default "allow wakeup"
|
||||
* policy through sysfs or these calls.
|
||||
*
|
||||
* Most root hubs support wakeup from downstream devices, for
|
||||
* runtime power management (disabling USB clocks and reducing
|
||||
* VBUS power usage). However, not all of them do so; silicon,
|
||||
* board, and BIOS bugs here are not uncommon, so these can't
|
||||
* be treated quite like external hubs.
|
||||
*
|
||||
* Likewise, not all root hubs will pass wakeup events upstream,
|
||||
* to wake up the whole system. So don't assume root hub and
|
||||
* controller capabilities are identical.
|
||||
*/
|
||||
|
||||
case DeviceRequest | USB_REQ_GET_STATUS:
|
||||
tbuf [0] = (hcd->remote_wakeup << USB_DEVICE_REMOTE_WAKEUP)
|
||||
tbuf [0] = (device_may_wakeup(&hcd->self.root_hub->dev)
|
||||
<< USB_DEVICE_REMOTE_WAKEUP)
|
||||
| (1 << USB_DEVICE_SELF_POWERED);
|
||||
tbuf [1] = 0;
|
||||
len = 2;
|
||||
break;
|
||||
case DeviceOutRequest | USB_REQ_CLEAR_FEATURE:
|
||||
if (wValue == USB_DEVICE_REMOTE_WAKEUP)
|
||||
hcd->remote_wakeup = 0;
|
||||
device_set_wakeup_enable(&hcd->self.root_hub->dev, 0);
|
||||
else
|
||||
goto error;
|
||||
break;
|
||||
case DeviceOutRequest | USB_REQ_SET_FEATURE:
|
||||
if (hcd->can_wakeup && wValue == USB_DEVICE_REMOTE_WAKEUP)
|
||||
hcd->remote_wakeup = 1;
|
||||
if (device_can_wakeup(&hcd->self.root_hub->dev)
|
||||
&& wValue == USB_DEVICE_REMOTE_WAKEUP)
|
||||
device_set_wakeup_enable(&hcd->self.root_hub->dev, 1);
|
||||
else
|
||||
goto error;
|
||||
break;
|
||||
@@ -409,7 +428,7 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb)
|
||||
bufp = fs_rh_config_descriptor;
|
||||
len = sizeof fs_rh_config_descriptor;
|
||||
}
|
||||
if (hcd->can_wakeup)
|
||||
if (device_can_wakeup(&hcd->self.root_hub->dev))
|
||||
patch_wakeup = 1;
|
||||
break;
|
||||
case USB_DT_STRING << 8:
|
||||
@@ -761,14 +780,14 @@ static int usb_register_bus(struct usb_bus *bus)
|
||||
{
|
||||
int busnum;
|
||||
|
||||
down (&usb_bus_list_lock);
|
||||
mutex_lock(&usb_bus_list_lock);
|
||||
busnum = find_next_zero_bit (busmap.busmap, USB_MAXBUS, 1);
|
||||
if (busnum < USB_MAXBUS) {
|
||||
set_bit (busnum, busmap.busmap);
|
||||
bus->busnum = busnum;
|
||||
} else {
|
||||
printk (KERN_ERR "%s: too many buses\n", usbcore_name);
|
||||
up(&usb_bus_list_lock);
|
||||
mutex_unlock(&usb_bus_list_lock);
|
||||
return -E2BIG;
|
||||
}
|
||||
|
||||
@@ -776,7 +795,7 @@ static int usb_register_bus(struct usb_bus *bus)
|
||||
bus->controller, "usb_host%d", busnum);
|
||||
if (IS_ERR(bus->class_dev)) {
|
||||
clear_bit(busnum, busmap.busmap);
|
||||
up(&usb_bus_list_lock);
|
||||
mutex_unlock(&usb_bus_list_lock);
|
||||
return PTR_ERR(bus->class_dev);
|
||||
}
|
||||
|
||||
@@ -784,7 +803,7 @@ static int usb_register_bus(struct usb_bus *bus)
|
||||
|
||||
/* Add it to the local list of buses */
|
||||
list_add (&bus->bus_list, &usb_bus_list);
|
||||
up (&usb_bus_list_lock);
|
||||
mutex_unlock(&usb_bus_list_lock);
|
||||
|
||||
usb_notify_add_bus(bus);
|
||||
|
||||
@@ -809,9 +828,9 @@ static void usb_deregister_bus (struct usb_bus *bus)
|
||||
* controller code, as well as having it call this when cleaning
|
||||
* itself up
|
||||
*/
|
||||
down (&usb_bus_list_lock);
|
||||
mutex_lock(&usb_bus_list_lock);
|
||||
list_del (&bus->bus_list);
|
||||
up (&usb_bus_list_lock);
|
||||
mutex_unlock(&usb_bus_list_lock);
|
||||
|
||||
usb_notify_remove_bus(bus);
|
||||
|
||||
@@ -822,18 +841,17 @@ static void usb_deregister_bus (struct usb_bus *bus)
|
||||
|
||||
/**
|
||||
* register_root_hub - called by usb_add_hcd() to register a root hub
|
||||
* @usb_dev: the usb root hub device to be registered.
|
||||
* @hcd: host controller for this root hub
|
||||
*
|
||||
* This function registers the root hub with the USB subsystem. It sets up
|
||||
* the device properly in the device tree and stores the root_hub pointer
|
||||
* in the bus structure, then calls usb_new_device() to register the usb
|
||||
* device. It also assigns the root hub's USB address (always 1).
|
||||
* the device properly in the device tree and then calls usb_new_device()
|
||||
* to register the usb device. It also assigns the root hub's USB address
|
||||
* (always 1).
|
||||
*/
|
||||
static int register_root_hub (struct usb_device *usb_dev,
|
||||
struct usb_hcd *hcd)
|
||||
static int register_root_hub(struct usb_hcd *hcd)
|
||||
{
|
||||
struct device *parent_dev = hcd->self.controller;
|
||||
struct usb_device *usb_dev = hcd->self.root_hub;
|
||||
const int devnum = 1;
|
||||
int retval;
|
||||
|
||||
@@ -844,14 +862,12 @@ static int register_root_hub (struct usb_device *usb_dev,
|
||||
set_bit (devnum, usb_dev->bus->devmap.devicemap);
|
||||
usb_set_device_state(usb_dev, USB_STATE_ADDRESS);
|
||||
|
||||
down (&usb_bus_list_lock);
|
||||
usb_dev->bus->root_hub = usb_dev;
|
||||
mutex_lock(&usb_bus_list_lock);
|
||||
|
||||
usb_dev->ep0.desc.wMaxPacketSize = __constant_cpu_to_le16(64);
|
||||
retval = usb_get_device_descriptor(usb_dev, USB_DT_DEVICE_SIZE);
|
||||
if (retval != sizeof usb_dev->descriptor) {
|
||||
usb_dev->bus->root_hub = NULL;
|
||||
up (&usb_bus_list_lock);
|
||||
mutex_unlock(&usb_bus_list_lock);
|
||||
dev_dbg (parent_dev, "can't read %s device descriptor %d\n",
|
||||
usb_dev->dev.bus_id, retval);
|
||||
return (retval < 0) ? retval : -EMSGSIZE;
|
||||
@@ -859,11 +875,10 @@ static int register_root_hub (struct usb_device *usb_dev,
|
||||
|
||||
retval = usb_new_device (usb_dev);
|
||||
if (retval) {
|
||||
usb_dev->bus->root_hub = NULL;
|
||||
dev_err (parent_dev, "can't register root hub for %s, %d\n",
|
||||
usb_dev->dev.bus_id, retval);
|
||||
}
|
||||
up (&usb_bus_list_lock);
|
||||
mutex_unlock(&usb_bus_list_lock);
|
||||
|
||||
if (retval == 0) {
|
||||
spin_lock_irq (&hcd_root_hub_lock);
|
||||
@@ -1090,7 +1105,6 @@ static void urb_unlink (struct urb *urb)
|
||||
spin_lock_irqsave (&hcd_data_lock, flags);
|
||||
list_del_init (&urb->urb_list);
|
||||
spin_unlock_irqrestore (&hcd_data_lock, flags);
|
||||
usb_put_dev (urb->dev);
|
||||
}
|
||||
|
||||
|
||||
@@ -1130,7 +1144,6 @@ static int hcd_submit_urb (struct urb *urb, gfp_t mem_flags)
|
||||
case HC_STATE_RUNNING:
|
||||
case HC_STATE_RESUMING:
|
||||
doit:
|
||||
usb_get_dev (urb->dev);
|
||||
list_add_tail (&urb->urb_list, &ep->urb_list);
|
||||
status = 0;
|
||||
break;
|
||||
@@ -1771,12 +1784,10 @@ int usb_add_hcd(struct usb_hcd *hcd,
|
||||
|
||||
set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
|
||||
|
||||
/* till now HC has been in an indeterminate state ... */
|
||||
if (hcd->driver->reset && (retval = hcd->driver->reset(hcd)) < 0) {
|
||||
dev_err(hcd->self.controller, "can't reset\n");
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* HC is in reset state, but accessible. Now do the one-time init,
|
||||
* bottom up so that hcds can customize the root hubs before khubd
|
||||
* starts talking to them. (Note, bus id is assigned early too.)
|
||||
*/
|
||||
if ((retval = hcd_buffer_create(hcd)) != 0) {
|
||||
dev_dbg(hcd->self.controller, "pool alloc failed\n");
|
||||
return retval;
|
||||
@@ -1785,6 +1796,36 @@ int usb_add_hcd(struct usb_hcd *hcd,
|
||||
if ((retval = usb_register_bus(&hcd->self)) < 0)
|
||||
goto err_register_bus;
|
||||
|
||||
if ((rhdev = usb_alloc_dev(NULL, &hcd->self, 0)) == NULL) {
|
||||
dev_err(hcd->self.controller, "unable to allocate root hub\n");
|
||||
retval = -ENOMEM;
|
||||
goto err_allocate_root_hub;
|
||||
}
|
||||
rhdev->speed = (hcd->driver->flags & HCD_USB2) ? USB_SPEED_HIGH :
|
||||
USB_SPEED_FULL;
|
||||
hcd->self.root_hub = rhdev;
|
||||
|
||||
/* "reset" is misnamed; its role is now one-time init. the controller
|
||||
* should already have been reset (and boot firmware kicked off etc).
|
||||
*/
|
||||
if (hcd->driver->reset && (retval = hcd->driver->reset(hcd)) < 0) {
|
||||
dev_err(hcd->self.controller, "can't setup\n");
|
||||
goto err_hcd_driver_setup;
|
||||
}
|
||||
|
||||
/* wakeup flag init is in transition; for now we can't rely on PCI to
|
||||
* initialize these bits properly, so we let reset() override it.
|
||||
* This init should _precede_ the reset() once PCI behaves.
|
||||
*/
|
||||
device_init_wakeup(&rhdev->dev,
|
||||
device_can_wakeup(hcd->self.controller));
|
||||
|
||||
/* NOTE: root hub and controller capabilities may not be the same */
|
||||
if (device_can_wakeup(hcd->self.controller)
|
||||
&& device_can_wakeup(&hcd->self.root_hub->dev))
|
||||
dev_dbg(hcd->self.controller, "supports USB remote wakeup\n");
|
||||
|
||||
/* enable irqs just before we start the controller */
|
||||
if (hcd->driver->irq) {
|
||||
char buf[8], *bufp = buf;
|
||||
|
||||
@@ -1816,56 +1857,32 @@ int usb_add_hcd(struct usb_hcd *hcd,
|
||||
(unsigned long long)hcd->rsrc_start);
|
||||
}
|
||||
|
||||
/* Allocate the root hub before calling hcd->driver->start(),
|
||||
* but don't register it until afterward so that the hardware
|
||||
* is running.
|
||||
*/
|
||||
if ((rhdev = usb_alloc_dev(NULL, &hcd->self, 0)) == NULL) {
|
||||
dev_err(hcd->self.controller, "unable to allocate root hub\n");
|
||||
retval = -ENOMEM;
|
||||
goto err_allocate_root_hub;
|
||||
}
|
||||
|
||||
/* Although in principle hcd->driver->start() might need to use rhdev,
|
||||
* none of the current drivers do.
|
||||
*/
|
||||
if ((retval = hcd->driver->start(hcd)) < 0) {
|
||||
dev_err(hcd->self.controller, "startup error %d\n", retval);
|
||||
goto err_hcd_driver_start;
|
||||
}
|
||||
|
||||
/* hcd->driver->start() reported can_wakeup, probably with
|
||||
* assistance from board's boot firmware.
|
||||
* NOTE: normal devices won't enable wakeup by default.
|
||||
*/
|
||||
if (hcd->can_wakeup)
|
||||
dev_dbg(hcd->self.controller, "supports USB remote wakeup\n");
|
||||
hcd->remote_wakeup = hcd->can_wakeup;
|
||||
|
||||
rhdev->speed = (hcd->driver->flags & HCD_USB2) ? USB_SPEED_HIGH :
|
||||
USB_SPEED_FULL;
|
||||
/* starting here, usbcore will pay attention to this root hub */
|
||||
rhdev->bus_mA = min(500u, hcd->power_budget);
|
||||
if ((retval = register_root_hub(rhdev, hcd)) != 0)
|
||||
if ((retval = register_root_hub(hcd)) != 0)
|
||||
goto err_register_root_hub;
|
||||
|
||||
if (hcd->uses_new_polling && hcd->poll_rh)
|
||||
usb_hcd_poll_rh_status(hcd);
|
||||
return retval;
|
||||
|
||||
err_register_root_hub:
|
||||
err_register_root_hub:
|
||||
hcd->driver->stop(hcd);
|
||||
|
||||
err_hcd_driver_start:
|
||||
usb_put_dev(rhdev);
|
||||
|
||||
err_allocate_root_hub:
|
||||
err_hcd_driver_start:
|
||||
if (hcd->irq >= 0)
|
||||
free_irq(irqnum, hcd);
|
||||
|
||||
err_request_irq:
|
||||
err_request_irq:
|
||||
err_hcd_driver_setup:
|
||||
hcd->self.root_hub = NULL;
|
||||
usb_put_dev(rhdev);
|
||||
err_allocate_root_hub:
|
||||
usb_deregister_bus(&hcd->self);
|
||||
|
||||
err_register_bus:
|
||||
err_register_bus:
|
||||
hcd_buffer_destroy(hcd);
|
||||
return retval;
|
||||
}
|
||||
@@ -1891,9 +1908,9 @@ void usb_remove_hcd(struct usb_hcd *hcd)
|
||||
hcd->rh_registered = 0;
|
||||
spin_unlock_irq (&hcd_root_hub_lock);
|
||||
|
||||
down(&usb_bus_list_lock);
|
||||
mutex_lock(&usb_bus_list_lock);
|
||||
usb_disconnect(&hcd->self.root_hub);
|
||||
up(&usb_bus_list_lock);
|
||||
mutex_unlock(&usb_bus_list_lock);
|
||||
|
||||
hcd->poll_rh = 0;
|
||||
del_timer_sync(&hcd->rh_timer);
|
||||
|
||||
@@ -78,8 +78,6 @@ struct usb_hcd { /* usb_bus.hcpriv points to this */
|
||||
#define HCD_FLAG_HW_ACCESSIBLE 0x00000001
|
||||
#define HCD_FLAG_SAW_IRQ 0x00000002
|
||||
|
||||
unsigned can_wakeup:1; /* hw supports wakeup? */
|
||||
unsigned remote_wakeup:1;/* sw should use wakeup? */
|
||||
unsigned rh_registered:1;/* is root hub registered? */
|
||||
|
||||
/* The next flag is a stopgap, to be removed when all the HCDs
|
||||
@@ -364,7 +362,7 @@ extern void usb_set_device_state(struct usb_device *udev,
|
||||
/* exported only within usbcore */
|
||||
|
||||
extern struct list_head usb_bus_list;
|
||||
extern struct semaphore usb_bus_list_lock;
|
||||
extern struct mutex usb_bus_list_lock;
|
||||
extern wait_queue_head_t usb_kill_urb_queue;
|
||||
|
||||
extern struct usb_bus *usb_bus_get (struct usb_bus *bus);
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <linux/usb.h>
|
||||
#include <linux/usbdevice_fs.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/mutex.h>
|
||||
|
||||
#include <asm/semaphore.h>
|
||||
#include <asm/uaccess.h>
|
||||
@@ -1005,12 +1006,18 @@ void usb_set_device_state(struct usb_device *udev,
|
||||
; /* do nothing */
|
||||
else if (new_state != USB_STATE_NOTATTACHED) {
|
||||
udev->state = new_state;
|
||||
if (new_state == USB_STATE_CONFIGURED)
|
||||
device_init_wakeup(&udev->dev,
|
||||
(udev->actconfig->desc.bmAttributes
|
||||
& USB_CONFIG_ATT_WAKEUP));
|
||||
else if (new_state != USB_STATE_SUSPENDED)
|
||||
device_init_wakeup(&udev->dev, 0);
|
||||
|
||||
/* root hub wakeup capabilities are managed out-of-band
|
||||
* and may involve silicon errata ... ignore them here.
|
||||
*/
|
||||
if (udev->parent) {
|
||||
if (new_state == USB_STATE_CONFIGURED)
|
||||
device_init_wakeup(&udev->dev,
|
||||
(udev->actconfig->desc.bmAttributes
|
||||
& USB_CONFIG_ATT_WAKEUP));
|
||||
else if (new_state != USB_STATE_SUSPENDED)
|
||||
device_init_wakeup(&udev->dev, 0);
|
||||
}
|
||||
} else
|
||||
recursively_mark_NOTATTACHED(udev);
|
||||
spin_unlock_irqrestore(&device_state_lock, flags);
|
||||
@@ -1172,8 +1179,11 @@ static int choose_configuration(struct usb_device *udev)
|
||||
c = udev->config;
|
||||
num_configs = udev->descriptor.bNumConfigurations;
|
||||
for (i = 0; i < num_configs; (i++, c++)) {
|
||||
struct usb_interface_descriptor *desc =
|
||||
&c->intf_cache[0]->altsetting->desc;
|
||||
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
|
||||
@@ -1208,7 +1218,8 @@ static int choose_configuration(struct usb_device *udev)
|
||||
/* 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->bInterfaceClass == USB_CLASS_COMM
|
||||
if (i == 0 && desc
|
||||
&& desc->bInterfaceClass == USB_CLASS_COMM
|
||||
&& desc->bInterfaceSubClass == 2
|
||||
&& desc->bInterfaceProtocol == 0xff) {
|
||||
#ifndef CONFIG_USB_NET_RNDIS
|
||||
@@ -1224,8 +1235,8 @@ static int choose_configuration(struct usb_device *udev)
|
||||
* than a vendor-specific driver. */
|
||||
else if (udev->descriptor.bDeviceClass !=
|
||||
USB_CLASS_VENDOR_SPEC &&
|
||||
desc->bInterfaceClass !=
|
||||
USB_CLASS_VENDOR_SPEC) {
|
||||
(!desc || desc->bInterfaceClass !=
|
||||
USB_CLASS_VENDOR_SPEC)) {
|
||||
best = c;
|
||||
break;
|
||||
}
|
||||
@@ -1876,18 +1887,18 @@ int usb_resume_device(struct usb_device *udev)
|
||||
if (udev->state == USB_STATE_NOTATTACHED)
|
||||
return -ENODEV;
|
||||
|
||||
#ifdef CONFIG_USB_SUSPEND
|
||||
/* selective resume of one downstream hub-to-device port */
|
||||
if (udev->parent) {
|
||||
#ifdef CONFIG_USB_SUSPEND
|
||||
if (udev->state == USB_STATE_SUSPENDED) {
|
||||
// NOTE swsusp may bork us, device state being wrong...
|
||||
// NOTE this fails if parent is also suspended...
|
||||
status = hub_port_resume(hdev_to_hub(udev->parent),
|
||||
udev->portnum, udev);
|
||||
} else
|
||||
#endif
|
||||
status = 0;
|
||||
} else
|
||||
#endif
|
||||
status = finish_device_resume(udev);
|
||||
if (status < 0)
|
||||
dev_dbg(&udev->dev, "can't resume, status %d\n",
|
||||
@@ -2162,7 +2173,7 @@ static int
|
||||
hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
|
||||
int retry_counter)
|
||||
{
|
||||
static DECLARE_MUTEX(usb_address0_sem);
|
||||
static DEFINE_MUTEX(usb_address0_mutex);
|
||||
|
||||
struct usb_device *hdev = hub->hdev;
|
||||
int i, j, retval;
|
||||
@@ -2183,7 +2194,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
|
||||
if (oldspeed == USB_SPEED_LOW)
|
||||
delay = HUB_LONG_RESET_TIME;
|
||||
|
||||
down(&usb_address0_sem);
|
||||
mutex_lock(&usb_address0_mutex);
|
||||
|
||||
/* Reset the device; full speed may morph to high speed */
|
||||
retval = hub_port_reset(hub, port1, udev, delay);
|
||||
@@ -2381,7 +2392,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
|
||||
fail:
|
||||
if (retval)
|
||||
hub_port_disable(hub, port1, 0);
|
||||
up(&usb_address0_sem);
|
||||
mutex_unlock(&usb_address0_mutex);
|
||||
return retval;
|
||||
}
|
||||
|
||||
@@ -3017,7 +3028,7 @@ int usb_reset_device(struct usb_device *udev)
|
||||
parent_hub = hdev_to_hub(parent_hdev);
|
||||
|
||||
/* If we're resetting an active hub, take some special actions */
|
||||
if (udev->actconfig &&
|
||||
if (udev->actconfig && udev->actconfig->desc.bNumInterfaces > 0 &&
|
||||
udev->actconfig->interface[0]->dev.driver ==
|
||||
&hub_driver.driver &&
|
||||
(hub = hdev_to_hub(udev)) != NULL) {
|
||||
|
||||
@@ -631,8 +631,8 @@ int usb_get_descriptor(struct usb_device *dev, unsigned char type, unsigned char
|
||||
* Returns the number of bytes received on success, or else the status code
|
||||
* returned by the underlying usb_control_msg() call.
|
||||
*/
|
||||
int usb_get_string(struct usb_device *dev, unsigned short langid,
|
||||
unsigned char index, void *buf, int size)
|
||||
static int usb_get_string(struct usb_device *dev, unsigned short langid,
|
||||
unsigned char index, void *buf, int size)
|
||||
{
|
||||
int i;
|
||||
int result;
|
||||
@@ -1388,11 +1388,13 @@ free_interfaces:
|
||||
if (dev->state != USB_STATE_ADDRESS)
|
||||
usb_disable_device (dev, 1); // Skip ep0
|
||||
|
||||
i = dev->bus_mA - cp->desc.bMaxPower * 2;
|
||||
if (i < 0)
|
||||
dev_warn(&dev->dev, "new config #%d exceeds power "
|
||||
"limit by %dmA\n",
|
||||
configuration, -i);
|
||||
if (cp) {
|
||||
i = dev->bus_mA - cp->desc.bMaxPower * 2;
|
||||
if (i < 0)
|
||||
dev_warn(&dev->dev, "new config #%d exceeds power "
|
||||
"limit by %dmA\n",
|
||||
configuration, -i);
|
||||
}
|
||||
|
||||
if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
|
||||
USB_REQ_SET_CONFIGURATION, 0, configuration, 0,
|
||||
@@ -1488,7 +1490,6 @@ EXPORT_SYMBOL(usb_sg_wait);
|
||||
// synchronous control message convenience routines
|
||||
EXPORT_SYMBOL(usb_get_descriptor);
|
||||
EXPORT_SYMBOL(usb_get_status);
|
||||
EXPORT_SYMBOL(usb_get_string);
|
||||
EXPORT_SYMBOL(usb_string);
|
||||
|
||||
// synchronous calls that also maintain usbcore state
|
||||
|
||||
@@ -13,16 +13,17 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/notifier.h>
|
||||
#include <linux/usb.h>
|
||||
#include <linux/mutex.h>
|
||||
#include "usb.h"
|
||||
|
||||
|
||||
static struct notifier_block *usb_notifier_list;
|
||||
static DECLARE_MUTEX(usb_notifier_lock);
|
||||
static DEFINE_MUTEX(usb_notifier_lock);
|
||||
|
||||
static void usb_notifier_chain_register(struct notifier_block **list,
|
||||
struct notifier_block *n)
|
||||
{
|
||||
down(&usb_notifier_lock);
|
||||
mutex_lock(&usb_notifier_lock);
|
||||
while (*list) {
|
||||
if (n->priority > (*list)->priority)
|
||||
break;
|
||||
@@ -30,13 +31,13 @@ static void usb_notifier_chain_register(struct notifier_block **list,
|
||||
}
|
||||
n->next = *list;
|
||||
*list = n;
|
||||
up(&usb_notifier_lock);
|
||||
mutex_unlock(&usb_notifier_lock);
|
||||
}
|
||||
|
||||
static void usb_notifier_chain_unregister(struct notifier_block **nl,
|
||||
struct notifier_block *n)
|
||||
{
|
||||
down(&usb_notifier_lock);
|
||||
mutex_lock(&usb_notifier_lock);
|
||||
while ((*nl)!=NULL) {
|
||||
if ((*nl)==n) {
|
||||
*nl = n->next;
|
||||
@@ -45,7 +46,7 @@ static void usb_notifier_chain_unregister(struct notifier_block **nl,
|
||||
nl=&((*nl)->next);
|
||||
}
|
||||
exit:
|
||||
up(&usb_notifier_lock);
|
||||
mutex_unlock(&usb_notifier_lock);
|
||||
}
|
||||
|
||||
static int usb_notifier_call_chain(struct notifier_block **n,
|
||||
@@ -54,7 +55,7 @@ static int usb_notifier_call_chain(struct notifier_block **n,
|
||||
int ret=NOTIFY_DONE;
|
||||
struct notifier_block *nb = *n;
|
||||
|
||||
down(&usb_notifier_lock);
|
||||
mutex_lock(&usb_notifier_lock);
|
||||
while (nb) {
|
||||
ret = nb->notifier_call(nb,val,v);
|
||||
if (ret&NOTIFY_STOP_MASK) {
|
||||
@@ -63,7 +64,7 @@ static int usb_notifier_call_chain(struct notifier_block **n,
|
||||
nb = nb->next;
|
||||
}
|
||||
exit:
|
||||
up(&usb_notifier_lock);
|
||||
mutex_unlock(&usb_notifier_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include <linux/errno.h>
|
||||
#include <linux/smp_lock.h>
|
||||
#include <linux/usb.h>
|
||||
#include <linux/mutex.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <asm/scatterlist.h>
|
||||
@@ -639,7 +640,7 @@ struct usb_device *usb_find_device(u16 vendor_id, u16 product_id)
|
||||
struct usb_bus *bus;
|
||||
struct usb_device *dev = NULL;
|
||||
|
||||
down(&usb_bus_list_lock);
|
||||
mutex_lock(&usb_bus_list_lock);
|
||||
for (buslist = usb_bus_list.next;
|
||||
buslist != &usb_bus_list;
|
||||
buslist = buslist->next) {
|
||||
@@ -653,7 +654,7 @@ struct usb_device *usb_find_device(u16 vendor_id, u16 product_id)
|
||||
goto exit;
|
||||
}
|
||||
exit:
|
||||
up(&usb_bus_list_lock);
|
||||
mutex_unlock(&usb_bus_list_lock);
|
||||
return dev;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user