diff options
Diffstat (limited to 'drivers/usb/core')
-rw-r--r-- | drivers/usb/core/devices.c | 7 | ||||
-rw-r--r-- | drivers/usb/core/devio.c | 24 | ||||
-rw-r--r-- | drivers/usb/core/driver.c | 6 | ||||
-rw-r--r-- | drivers/usb/core/file.c | 6 | ||||
-rw-r--r-- | drivers/usb/core/hcd-pci.c | 15 | ||||
-rw-r--r-- | drivers/usb/core/hcd.c | 153 | ||||
-rw-r--r-- | drivers/usb/core/hcd.h | 4 | ||||
-rw-r--r-- | drivers/usb/core/hub.c | 45 | ||||
-rw-r--r-- | drivers/usb/core/message.c | 17 | ||||
-rw-r--r-- | drivers/usb/core/notify.c | 66 | ||||
-rw-r--r-- | drivers/usb/core/usb.c | 5 |
11 files changed, 165 insertions, 183 deletions
diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c index 2684e15b813b..c0f37343a276 100644 --- a/drivers/usb/core/devices.c +++ b/drivers/usb/core/devices.c @@ -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; } diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 2b68998fe4b3..545da37afca7 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -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; diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index dce9d987f0fc..c196f3845305 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -378,7 +378,7 @@ const struct usb_device_id *usb_match_id(struct usb_interface *interface, return NULL; } -EXPORT_SYMBOL(usb_match_id); +EXPORT_SYMBOL_GPL_FUTURE(usb_match_id); int usb_device_match(struct device *dev, struct device_driver *drv) { @@ -446,7 +446,7 @@ int usb_register_driver(struct usb_driver *new_driver, struct module *owner) return retval; } -EXPORT_SYMBOL(usb_register_driver); +EXPORT_SYMBOL_GPL_FUTURE(usb_register_driver); /** * usb_deregister - unregister a USB driver @@ -469,4 +469,4 @@ void usb_deregister(struct usb_driver *driver) usbfs_update_special(); } -EXPORT_SYMBOL(usb_deregister); +EXPORT_SYMBOL_GPL_FUTURE(usb_deregister); diff --git a/drivers/usb/core/file.c b/drivers/usb/core/file.c index 37b13368c814..b263a54a13c0 100644 --- a/drivers/usb/core/file.c +++ b/drivers/usb/core/file.c @@ -24,15 +24,15 @@ #include "usb.h" #define MAX_USB_MINORS 256 -static struct file_operations *usb_minors[MAX_USB_MINORS]; +static const struct file_operations *usb_minors[MAX_USB_MINORS]; static DEFINE_SPINLOCK(minor_lock); static int usb_open(struct inode * inode, struct file * file) { int minor = iminor(inode); - struct file_operations *c; + const struct file_operations *c; int err = -ENODEV; - struct file_operations *old_fops, *new_fops = NULL; + const struct file_operations *old_fops, *new_fops = NULL; spin_lock (&minor_lock); c = usb_minors[minor]; diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c index 29b5b2a6e183..0d2193b69235 100644 --- a/drivers/usb/core/hcd-pci.c +++ b/drivers/usb/core/hcd-pci.c @@ -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); @@ -291,7 +296,7 @@ done: #ifdef CONFIG_PPC_PMAC /* Disable ASIC clocks for USB */ - if (_machine == _MACH_Pmac) { + if (machine_is(powermac)) { struct device_node *of_node; of_node = pci_device_to_OF_node (dev); @@ -326,7 +331,7 @@ int usb_hcd_pci_resume (struct pci_dev *dev) #ifdef CONFIG_PPC_PMAC /* Reenable ASIC clocks for USB */ - if (_machine == _MACH_Pmac) { + if (machine_is(powermac)) { struct device_node *of_node; of_node = pci_device_to_OF_node (dev); diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 0018bbc4de34..fbd938d4ea58 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -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); diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h index 591b5aad1a18..7022aafb2ae8 100644 --- a/drivers/usb/core/hcd.h +++ b/drivers/usb/core/hcd.h @@ -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); diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 650d5ee5871b..8e65f7a237e4 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -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) { diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 7135e542679d..08fb20f06f3e 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -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 diff --git a/drivers/usb/core/notify.c b/drivers/usb/core/notify.c index fbbebab52fbd..fe0ed54fa0ae 100644 --- a/drivers/usb/core/notify.c +++ b/drivers/usb/core/notify.c @@ -13,59 +13,10 @@ #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 void usb_notifier_chain_register(struct notifier_block **list, - struct notifier_block *n) -{ - down(&usb_notifier_lock); - while (*list) { - if (n->priority > (*list)->priority) - break; - list = &((*list)->next); - } - n->next = *list; - *list = n; - up(&usb_notifier_lock); -} - -static void usb_notifier_chain_unregister(struct notifier_block **nl, - struct notifier_block *n) -{ - down(&usb_notifier_lock); - while ((*nl)!=NULL) { - if ((*nl)==n) { - *nl = n->next; - goto exit; - } - nl=&((*nl)->next); - } -exit: - up(&usb_notifier_lock); -} - -static int usb_notifier_call_chain(struct notifier_block **n, - unsigned long val, void *v) -{ - int ret=NOTIFY_DONE; - struct notifier_block *nb = *n; - - down(&usb_notifier_lock); - while (nb) { - ret = nb->notifier_call(nb,val,v); - if (ret&NOTIFY_STOP_MASK) { - goto exit; - } - nb = nb->next; - } -exit: - up(&usb_notifier_lock); - return ret; -} +static BLOCKING_NOTIFIER_HEAD(usb_notifier_list); /** * usb_register_notify - register a notifier callback whenever a usb change happens @@ -75,7 +26,7 @@ exit: */ void usb_register_notify(struct notifier_block *nb) { - usb_notifier_chain_register(&usb_notifier_list, nb); + blocking_notifier_chain_register(&usb_notifier_list, nb); } EXPORT_SYMBOL_GPL(usb_register_notify); @@ -88,27 +39,28 @@ EXPORT_SYMBOL_GPL(usb_register_notify); */ void usb_unregister_notify(struct notifier_block *nb) { - usb_notifier_chain_unregister(&usb_notifier_list, nb); + blocking_notifier_chain_unregister(&usb_notifier_list, nb); } EXPORT_SYMBOL_GPL(usb_unregister_notify); void usb_notify_add_device(struct usb_device *udev) { - usb_notifier_call_chain(&usb_notifier_list, USB_DEVICE_ADD, udev); + blocking_notifier_call_chain(&usb_notifier_list, USB_DEVICE_ADD, udev); } void usb_notify_remove_device(struct usb_device *udev) { - usb_notifier_call_chain(&usb_notifier_list, USB_DEVICE_REMOVE, udev); + blocking_notifier_call_chain(&usb_notifier_list, + USB_DEVICE_REMOVE, udev); } void usb_notify_add_bus(struct usb_bus *ubus) { - usb_notifier_call_chain(&usb_notifier_list, USB_BUS_ADD, ubus); + blocking_notifier_call_chain(&usb_notifier_list, USB_BUS_ADD, ubus); } void usb_notify_remove_bus(struct usb_bus *ubus) { - usb_notifier_call_chain(&usb_notifier_list, USB_BUS_REMOVE, ubus); + blocking_notifier_call_chain(&usb_notifier_list, USB_BUS_REMOVE, ubus); } diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index 13d1d367f7f1..d7352aa73b5e 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c @@ -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; } |