diff options
author | Ian Wisbon <ian.wisbon@timesys.com> | 2011-02-15 15:53:51 -0500 |
---|---|---|
committer | Ian Wisbon <ian.wisbon@timesys.com> | 2011-02-15 15:53:51 -0500 |
commit | dfdbf3f6e2d279f2a46ed95614cb4bf07657394d (patch) | |
tree | 2cc05669c5d3e47f7d4b28e31076b6dc6e771f36 /drivers/usb/core | |
parent | effff5718c380983788fe6c380671c18e15ac7c2 (diff) |
Digi del-5.6 Complete2.6.31-digi-201102151558
Diffstat (limited to 'drivers/usb/core')
-rw-r--r-- | drivers/usb/core/config.c | 2 | ||||
-rw-r--r-- | drivers/usb/core/devices.c | 2 | ||||
-rw-r--r-- | drivers/usb/core/devio.c | 61 | ||||
-rw-r--r-- | drivers/usb/core/driver.c | 2 | ||||
-rw-r--r-- | drivers/usb/core/hub.c | 5 | ||||
-rw-r--r-- | drivers/usb/core/message.c | 8 | ||||
-rw-r--r-- | drivers/usb/core/sysfs.c | 6 | ||||
-rw-r--r-- | drivers/usb/core/usb.c | 31 |
8 files changed, 75 insertions, 42 deletions
diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c index a16c538d0132..0d3af6a6ee49 100644 --- a/drivers/usb/core/config.c +++ b/drivers/usb/core/config.c @@ -105,7 +105,7 @@ static int usb_parse_ss_endpoint_companion(struct device *ddev, int cfgno, ep->ss_ep_comp->extralen = i; buffer += i; size -= i; - retval = buffer - buffer_start + i; + retval = buffer - buffer_start; if (num_skipped > 0) dev_dbg(ddev, "skipped %d descriptor%s after %s\n", num_skipped, plural(num_skipped), diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c index 96f11715cd26..355dffcc23b0 100644 --- a/drivers/usb/core/devices.c +++ b/drivers/usb/core/devices.c @@ -494,7 +494,7 @@ static ssize_t usb_device_dump(char __user **buffer, size_t *nbytes, return 0; /* allocate 2^1 pages = 8K (on i386); * should be more than enough for one device */ - pages_start = (char *)__get_free_pages(GFP_KERNEL, 1); + pages_start = (char *)__get_free_pages(GFP_NOIO, 1); if (!pages_start) return -ENOMEM; diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 4247eccf858c..5ae4099fb4c1 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -1139,6 +1139,13 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, free_async(as); return -ENOMEM; } + /* Isochronous input data may end up being discontiguous + * if some of the packets are short. Clear the buffer so + * that the gaps don't leak kernel data to userspace. + */ + if (is_in && uurb->type == USBDEVFS_URB_TYPE_ISO) + memset(as->urb->transfer_buffer, 0, + uurb->buffer_length); } as->urb->dev = ps->dev; as->urb->pipe = (uurb->type << 30) | @@ -1240,10 +1247,14 @@ static int processcompl(struct async *as, void __user * __user *arg) void __user *addr = as->userurb; unsigned int i; - if (as->userbuffer) - if (copy_to_user(as->userbuffer, urb->transfer_buffer, - urb->transfer_buffer_length)) + if (as->userbuffer && urb->actual_length) { + if (urb->number_of_packets > 0) /* Isochronous */ + i = urb->transfer_buffer_length; + else /* Non-Isoc */ + i = urb->actual_length; + if (copy_to_user(as->userbuffer, urb->transfer_buffer, i)) goto err_out; + } if (put_user(as->status, &userurb->status)) goto err_out; if (put_user(urb->actual_length, &userurb->actual_length)) @@ -1262,14 +1273,11 @@ static int processcompl(struct async *as, void __user * __user *arg) } } - free_async(as); - if (put_user(addr, (void __user * __user *)arg)) return -EFAULT; return 0; err_out: - free_async(as); return -EFAULT; } @@ -1299,8 +1307,11 @@ static struct async *reap_as(struct dev_state *ps) static int proc_reapurb(struct dev_state *ps, void __user *arg) { struct async *as = reap_as(ps); - if (as) - return processcompl(as, (void __user * __user *)arg); + if (as) { + int retval = processcompl(as, (void __user * __user *)arg); + free_async(as); + return retval; + } if (signal_pending(current)) return -EINTR; return -EIO; @@ -1308,11 +1319,16 @@ static int proc_reapurb(struct dev_state *ps, void __user *arg) static int proc_reapurbnonblock(struct dev_state *ps, void __user *arg) { + int retval; struct async *as; - if (!(as = async_getcompleted(ps))) - return -EAGAIN; - return processcompl(as, (void __user * __user *)arg); + as = async_getcompleted(ps); + retval = -EAGAIN; + if (as) { + retval = processcompl(as, (void __user * __user *)arg); + free_async(as); + } + return retval; } #ifdef CONFIG_COMPAT @@ -1363,9 +1379,9 @@ static int processcompl_compat(struct async *as, void __user * __user *arg) void __user *addr = as->userurb; unsigned int i; - if (as->userbuffer) + if (as->userbuffer && urb->actual_length) if (copy_to_user(as->userbuffer, urb->transfer_buffer, - urb->transfer_buffer_length)) + urb->actual_length)) return -EFAULT; if (put_user(as->status, &userurb->status)) return -EFAULT; @@ -1385,7 +1401,6 @@ static int processcompl_compat(struct async *as, void __user * __user *arg) } } - free_async(as); if (put_user(ptr_to_compat(addr), (u32 __user *)arg)) return -EFAULT; return 0; @@ -1394,8 +1409,11 @@ static int processcompl_compat(struct async *as, void __user * __user *arg) static int proc_reapurb_compat(struct dev_state *ps, void __user *arg) { struct async *as = reap_as(ps); - if (as) - return processcompl_compat(as, (void __user * __user *)arg); + if (as) { + int retval = processcompl_compat(as, (void __user * __user *)arg); + free_async(as); + return retval; + } if (signal_pending(current)) return -EINTR; return -EIO; @@ -1403,11 +1421,16 @@ static int proc_reapurb_compat(struct dev_state *ps, void __user *arg) static int proc_reapurbnonblock_compat(struct dev_state *ps, void __user *arg) { + int retval; struct async *as; - if (!(as = async_getcompleted(ps))) - return -EAGAIN; - return processcompl_compat(as, (void __user * __user *)arg); + retval = -EAGAIN; + as = async_getcompleted(ps); + if (as) { + retval = processcompl_compat(as, (void __user * __user *)arg); + free_async(as); + } + return retval; } #endif diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 69e5773abfce..c209dbe4f6c6 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -1765,7 +1765,7 @@ int usb_resume(struct device *dev, pm_message_t msg) /* Avoid PM error messages for devices disconnected while suspended * as we'll display regular disconnect messages just a bit later. */ - if (status == -ENODEV) + if (status == -ENODEV || status == -ESHUTDOWN) return 0; return status; } diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index d47201c75915..3bcd08fbfb71 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -457,7 +457,7 @@ resubmit: static inline int hub_clear_tt_buffer (struct usb_device *hdev, u16 devinfo, u16 tt) { - return usb_control_msg(hdev, usb_rcvctrlpipe(hdev, 0), + return usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0), HUB_CLEAR_TT_BUFFER, USB_RT_PORT, devinfo, tt, NULL, 0, 1000); } @@ -3286,6 +3286,9 @@ static void hub_events(void) USB_PORT_FEAT_C_SUSPEND); udev = hdev->children[i-1]; if (udev) { + /* TRSMRCY = 10 msec */ + msleep(10); + usb_lock_device(udev); ret = remote_wakeup(hdev-> children[i-1]); diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 9720e699f472..8c929daa71f2 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -923,11 +923,11 @@ char *usb_cache_string(struct usb_device *udev, int index) if (index <= 0) return NULL; - buf = kmalloc(MAX_USB_STRING_SIZE, GFP_KERNEL); + buf = kmalloc(MAX_USB_STRING_SIZE, GFP_NOIO); if (buf) { len = usb_string(udev, index, buf, MAX_USB_STRING_SIZE); if (len > 0) { - smallbuf = kmalloc(++len, GFP_KERNEL); + smallbuf = kmalloc(++len, GFP_NOIO); if (!smallbuf) return buf; memcpy(smallbuf, buf, len); @@ -1694,7 +1694,7 @@ int usb_set_configuration(struct usb_device *dev, int configuration) if (cp) { nintf = cp->desc.bNumInterfaces; new_interfaces = kmalloc(nintf * sizeof(*new_interfaces), - GFP_KERNEL); + GFP_NOIO); if (!new_interfaces) { dev_err(&dev->dev, "Out of memory\n"); return -ENOMEM; @@ -1703,7 +1703,7 @@ int usb_set_configuration(struct usb_device *dev, int configuration) for (; n < nintf; ++n) { new_interfaces[n] = kzalloc( sizeof(struct usb_interface), - GFP_KERNEL); + GFP_NOIO); if (!new_interfaces[n]) { dev_err(&dev->dev, "Out of memory\n"); ret = -ENOMEM; diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c index b5c72e458943..7bc1469c8f0e 100644 --- a/drivers/usb/core/sysfs.c +++ b/drivers/usb/core/sysfs.c @@ -111,6 +111,12 @@ show_speed(struct device *dev, struct device_attribute *attr, char *buf) case USB_SPEED_HIGH: speed = "480"; break; + case USB_SPEED_VARIABLE: + speed = "480"; + break; + case USB_SPEED_SUPER: + speed = "5000"; + break; default: speed = "unknown"; } diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index a26f73880c32..b661dbd93208 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c @@ -132,7 +132,7 @@ EXPORT_SYMBOL_GPL(usb_altnum_to_altsetting); struct find_interface_arg { int minor; - struct usb_interface *interface; + struct device_driver *drv; }; static int __find_interface(struct device *dev, void *data) @@ -143,12 +143,10 @@ static int __find_interface(struct device *dev, void *data) if (!is_usb_interface(dev)) return 0; + if (dev->driver != arg->drv) + return 0; intf = to_usb_interface(dev); - if (intf->minor != -1 && intf->minor == arg->minor) { - arg->interface = intf; - return 1; - } - return 0; + return intf->minor == arg->minor; } /** @@ -156,21 +154,24 @@ static int __find_interface(struct device *dev, void *data) * @drv: the driver whose current configuration is considered * @minor: the minor number of the desired device * - * This walks the driver device list and returns a pointer to the interface - * with the matching minor. Note, this only works for devices that share the - * USB major number. + * This walks the bus device list and returns a pointer to the interface + * with the matching minor and driver. Note, this only works for devices + * that share the USB major number. */ struct usb_interface *usb_find_interface(struct usb_driver *drv, int minor) { struct find_interface_arg argb; - int retval; + struct device *dev; argb.minor = minor; - argb.interface = NULL; - /* eat the error, it will be in argb.interface */ - retval = driver_for_each_device(&drv->drvwrap.driver, NULL, &argb, - __find_interface); - return argb.interface; + argb.drv = &drv->drvwrap.driver; + + dev = bus_find_device(&usb_bus_type, NULL, &argb, __find_interface); + + /* Drop reference count from bus_find_device */ + put_device(dev); + + return dev ? to_usb_interface(dev) : NULL; } EXPORT_SYMBOL_GPL(usb_find_interface); |