diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-03-19 16:39:21 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-03-19 16:39:21 -0400 |
| commit | 8fdb7e9f612b7c6ba6c3ba460c14263b5ce90f79 (patch) | |
| tree | 09f007a62475c22546ba693e5171024cc67fb38c | |
| parent | fc7f99cf36ebae853639dabb43bc2f0098c59aef (diff) | |
| parent | 4cb80cda51ff950614701fb30c9d4e583fe5a31f (diff) | |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6: (45 commits)
USB: gadget/multi: cdc_do_config: remove redundant check
usb: r8a66597-hcd: fix removed from an attached hub
USB: xhci: Make endpoint interval debugging clearer.
USB: Fix usb_fill_int_urb for SuperSpeed devices
USB: cp210x: Remove double usb_control_msg from cp210x_set_config
USB: Remove last bit of CONFIG_USB_BERRY_CHARGE
USB: gadget: add gadget controller number for s3c-hsotg driver
USB: ftdi_sio: Fix locking for change_speed() function
USB: g_mass_storage: fixed module name in Kconfig
USB: gadget: f_mass_storage::fsg_bind(): fix error handling
USB: g_mass_storage: fix section mismatch warnings
USB: gadget: fix Blackfin builds after gadget cleansing
USB: goku_udc: remove potential null dereference
USB: option.c: Add Pirelli VID/PID and indicate Pirelli's modem interface is 0xff
USB: serial: Fix module name typo for qcaux Kconfig entry.
usb: cdc-wdm: Fix deadlock between write and resume
usb: cdc-wdm: Fix order in disconnect and fix locking
usb: cdc-wdm:Fix loss of data due to autosuspend
usb: cdc-wdm: Fix submission of URB after suspension
usb: cdc-wdm: Fix race between disconnect and debug messages
...
32 files changed, 335 insertions, 148 deletions
diff --git a/Documentation/ABI/testing/sysfs-bus-usb b/Documentation/ABI/testing/sysfs-bus-usb index a986e9bbba3d..bcebb9eaedce 100644 --- a/Documentation/ABI/testing/sysfs-bus-usb +++ b/Documentation/ABI/testing/sysfs-bus-usb | |||
| @@ -160,7 +160,7 @@ Description: | |||
| 160 | match the driver to the device. For example: | 160 | match the driver to the device. For example: |
| 161 | # echo "046d c315" > /sys/bus/usb/drivers/foo/remove_id | 161 | # echo "046d c315" > /sys/bus/usb/drivers/foo/remove_id |
| 162 | 162 | ||
| 163 | What: /sys/bus/usb/device/.../avoid_reset | 163 | What: /sys/bus/usb/device/.../avoid_reset_quirk |
| 164 | Date: December 2009 | 164 | Date: December 2009 |
| 165 | Contact: Oliver Neukum <oliver@neukum.org> | 165 | Contact: Oliver Neukum <oliver@neukum.org> |
| 166 | Description: | 166 | Description: |
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 975d556b4787..be6331e2c276 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c | |||
| @@ -1441,7 +1441,7 @@ static int acm_resume(struct usb_interface *intf) | |||
| 1441 | wb = acm->delayed_wb; | 1441 | wb = acm->delayed_wb; |
| 1442 | acm->delayed_wb = NULL; | 1442 | acm->delayed_wb = NULL; |
| 1443 | spin_unlock_irq(&acm->write_lock); | 1443 | spin_unlock_irq(&acm->write_lock); |
| 1444 | acm_start_wb(acm, acm->delayed_wb); | 1444 | acm_start_wb(acm, wb); |
| 1445 | } else { | 1445 | } else { |
| 1446 | spin_unlock_irq(&acm->write_lock); | 1446 | spin_unlock_irq(&acm->write_lock); |
| 1447 | } | 1447 | } |
diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c index 18aafcb08fc8..189141ca4e05 100644 --- a/drivers/usb/class/cdc-wdm.c +++ b/drivers/usb/class/cdc-wdm.c | |||
| @@ -52,7 +52,8 @@ MODULE_DEVICE_TABLE (usb, wdm_ids); | |||
| 52 | #define WDM_READ 4 | 52 | #define WDM_READ 4 |
| 53 | #define WDM_INT_STALL 5 | 53 | #define WDM_INT_STALL 5 |
| 54 | #define WDM_POLL_RUNNING 6 | 54 | #define WDM_POLL_RUNNING 6 |
| 55 | 55 | #define WDM_RESPONDING 7 | |
| 56 | #define WDM_SUSPENDING 8 | ||
| 56 | 57 | ||
| 57 | #define WDM_MAX 16 | 58 | #define WDM_MAX 16 |
| 58 | 59 | ||
| @@ -87,9 +88,7 @@ struct wdm_device { | |||
| 87 | int count; | 88 | int count; |
| 88 | dma_addr_t shandle; | 89 | dma_addr_t shandle; |
| 89 | dma_addr_t ihandle; | 90 | dma_addr_t ihandle; |
| 90 | struct mutex wlock; | 91 | struct mutex lock; |
| 91 | struct mutex rlock; | ||
| 92 | struct mutex plock; | ||
| 93 | wait_queue_head_t wait; | 92 | wait_queue_head_t wait; |
| 94 | struct work_struct rxwork; | 93 | struct work_struct rxwork; |
| 95 | int werr; | 94 | int werr; |
| @@ -117,21 +116,22 @@ static void wdm_in_callback(struct urb *urb) | |||
| 117 | int status = urb->status; | 116 | int status = urb->status; |
| 118 | 117 | ||
| 119 | spin_lock(&desc->iuspin); | 118 | spin_lock(&desc->iuspin); |
| 119 | clear_bit(WDM_RESPONDING, &desc->flags); | ||
| 120 | 120 | ||
| 121 | if (status) { | 121 | if (status) { |
| 122 | switch (status) { | 122 | switch (status) { |
| 123 | case -ENOENT: | 123 | case -ENOENT: |
| 124 | dev_dbg(&desc->intf->dev, | 124 | dev_dbg(&desc->intf->dev, |
| 125 | "nonzero urb status received: -ENOENT"); | 125 | "nonzero urb status received: -ENOENT"); |
| 126 | break; | 126 | goto skip_error; |
| 127 | case -ECONNRESET: | 127 | case -ECONNRESET: |
| 128 | dev_dbg(&desc->intf->dev, | 128 | dev_dbg(&desc->intf->dev, |
| 129 | "nonzero urb status received: -ECONNRESET"); | 129 | "nonzero urb status received: -ECONNRESET"); |
| 130 | break; | 130 | goto skip_error; |
| 131 | case -ESHUTDOWN: | 131 | case -ESHUTDOWN: |
| 132 | dev_dbg(&desc->intf->dev, | 132 | dev_dbg(&desc->intf->dev, |
| 133 | "nonzero urb status received: -ESHUTDOWN"); | 133 | "nonzero urb status received: -ESHUTDOWN"); |
| 134 | break; | 134 | goto skip_error; |
| 135 | case -EPIPE: | 135 | case -EPIPE: |
| 136 | dev_err(&desc->intf->dev, | 136 | dev_err(&desc->intf->dev, |
| 137 | "nonzero urb status received: -EPIPE\n"); | 137 | "nonzero urb status received: -EPIPE\n"); |
| @@ -147,6 +147,7 @@ static void wdm_in_callback(struct urb *urb) | |||
| 147 | desc->reslength = urb->actual_length; | 147 | desc->reslength = urb->actual_length; |
| 148 | memmove(desc->ubuf + desc->length, desc->inbuf, desc->reslength); | 148 | memmove(desc->ubuf + desc->length, desc->inbuf, desc->reslength); |
| 149 | desc->length += desc->reslength; | 149 | desc->length += desc->reslength; |
| 150 | skip_error: | ||
| 150 | wake_up(&desc->wait); | 151 | wake_up(&desc->wait); |
| 151 | 152 | ||
| 152 | set_bit(WDM_READ, &desc->flags); | 153 | set_bit(WDM_READ, &desc->flags); |
| @@ -229,13 +230,16 @@ static void wdm_int_callback(struct urb *urb) | |||
| 229 | desc->response->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | 230 | desc->response->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; |
| 230 | spin_lock(&desc->iuspin); | 231 | spin_lock(&desc->iuspin); |
| 231 | clear_bit(WDM_READ, &desc->flags); | 232 | clear_bit(WDM_READ, &desc->flags); |
| 232 | if (!test_bit(WDM_DISCONNECTING, &desc->flags)) { | 233 | set_bit(WDM_RESPONDING, &desc->flags); |
| 234 | if (!test_bit(WDM_DISCONNECTING, &desc->flags) | ||
| 235 | && !test_bit(WDM_SUSPENDING, &desc->flags)) { | ||
| 233 | rv = usb_submit_urb(desc->response, GFP_ATOMIC); | 236 | rv = usb_submit_urb(desc->response, GFP_ATOMIC); |
| 234 | dev_dbg(&desc->intf->dev, "%s: usb_submit_urb %d", | 237 | dev_dbg(&desc->intf->dev, "%s: usb_submit_urb %d", |
| 235 | __func__, rv); | 238 | __func__, rv); |
| 236 | } | 239 | } |
| 237 | spin_unlock(&desc->iuspin); | 240 | spin_unlock(&desc->iuspin); |
| 238 | if (rv < 0) { | 241 | if (rv < 0) { |
| 242 | clear_bit(WDM_RESPONDING, &desc->flags); | ||
| 239 | if (rv == -EPERM) | 243 | if (rv == -EPERM) |
| 240 | return; | 244 | return; |
| 241 | if (rv == -ENOMEM) { | 245 | if (rv == -ENOMEM) { |
| @@ -305,14 +309,38 @@ static ssize_t wdm_write | |||
| 305 | if (we < 0) | 309 | if (we < 0) |
| 306 | return -EIO; | 310 | return -EIO; |
| 307 | 311 | ||
| 308 | r = mutex_lock_interruptible(&desc->wlock); /* concurrent writes */ | 312 | desc->outbuf = buf = kmalloc(count, GFP_KERNEL); |
| 313 | if (!buf) { | ||
| 314 | rv = -ENOMEM; | ||
| 315 | goto outnl; | ||
| 316 | } | ||
| 317 | |||
