summaryrefslogtreecommitdiffstats
path: root/drivers/usb/class/cdc-acm.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.linux-foundation.org>2007-02-19 12:59:04 -0800
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-02-19 12:59:04 -0800
commit460223d21d960e420775ca4d11ddaa8389af4d25 (patch)
treec1e9d3e661180263f5e4ac72af85a151d3c183e7 /drivers/usb/class/cdc-acm.c
parent255f0385c8e0d6b9005c0e09fffb5bd852f3b506 (diff)
parented077bb714816e942ea9b740156659a28a34112f (diff)
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: (39 commits) USB: at91-ohci, handle extra at91sam9261 ahb clock USB: another id for cp2101 driver USB: ueagle-atm.c needs sched.h USB: at91_udc, shrink runtime footprint usbnet: add missing Kconfig for KC2190 cables usbnet: init fault (oops) cleanup, whitespace fixes usbnet: recognize SiteCom CN-124 usb: Remove Airprime device from option.c USB: change __init to __devinit for isp116x_probe USB: ps3: don't call ps3_system_bus_driver_register on other platforms USB: hid-core.c: Removes GTCO CalComp Interwrite IPanel PIDs from blacklist USB: kernel-doc fixes USB: quirky device for cdc-acm USB: cdc-acm: fix incorrect throtteling, make set_control optional USB: unconfigure devices which have config 0 USB: make usb_iso_packet_descriptor.status signed USB: fix g_serial small error USB: use __u32 rather than u32 in userspace ioctls in usbdevice_fs.h USB Storage: US_FL_IGNORE_RESIDUE needed for Aiptek MP3 Player USB: Fix misspelled "USBNET_MII" kernel config option. ...
Diffstat (limited to 'drivers/usb/class/cdc-acm.c')
-rw-r--r--drivers/usb/class/cdc-acm.c33
1 files changed, 22 insertions, 11 deletions
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index 98199628e39..d38a25f36ea 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -326,10 +326,16 @@ static void acm_rx_tasklet(unsigned long _acm)
struct tty_struct *tty = acm->tty;
struct acm_ru *rcv;
unsigned long flags;
- int i = 0;
+ unsigned char throttled;
dbg("Entering acm_rx_tasklet");
- if (!ACM_READY(acm) || acm->throttle)
+ if (!ACM_READY(acm))
+ return;
+
+ spin_lock(&acm->throttle_lock);
+ throttled = acm->throttle;
+ spin_unlock(&acm->throttle_lock);
+ if (throttled)
return;
next_buffer:
@@ -346,22 +352,20 @@ next_buffer:
dbg("acm_rx_tasklet: procesing buf 0x%p, size = %d", buf, buf->size);
tty_buffer_request_room(tty, buf->size);
- if (!acm->throttle)
+ spin_lock(&acm->throttle_lock);
+ throttled = acm->throttle;
+ spin_unlock(&acm->throttle_lock);
+ if (!throttled)
tty_insert_flip_string(tty, buf->base, buf->size);
tty_flip_buffer_push(tty);
- spin_lock(&acm->throttle_lock);
- if (acm->throttle) {
- dbg("Throtteling noticed");
- memmove(buf->base, buf->base + i, buf->size - i);
- buf->size -= i;
- spin_unlock(&acm->throttle_lock);
+ if (throttled) {
+ dbg("Throttling noticed");
spin_lock_irqsave(&acm->read_lock, flags);
list_add(&buf->list, &acm->filled_read_bufs);
spin_unlock_irqrestore(&acm->read_lock, flags);
return;
}
- spin_unlock(&acm->throttle_lock);
spin_lock_irqsave(&acm->read_lock, flags);
list_add(&buf->list, &acm->spare_read_bufs);
@@ -467,7 +471,8 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp)
goto bail_out;
}
- if (0 > acm_set_control(acm, acm->ctrlout = ACM_CTRL_DTR | ACM_CTRL_RTS))
+ if (0 > acm_set_control(acm, acm->ctrlout = ACM_CTRL_DTR | ACM_CTRL_RTS) &&
+ (acm->ctrl_caps & USB_CDC_CAP_LINE))
goto full_bailout;
INIT_LIST_HEAD(&acm->spare_read_urbs);
@@ -480,6 +485,8 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp)
list_add(&(acm->rb[i].list), &acm->spare_read_bufs);
}
+ acm->throttle = 0;
+
tasklet_schedule(&acm->urb_task);
done:
@@ -1092,6 +1099,10 @@ static struct usb_device_id acm_ids[] = {
{ USB_DEVICE(0x0ace, 0x1611), /* ZyDAS 56K USB MODEM - new version */
.driver_info = SINGLE_RX_URB, /* firmware bug */
},
+ { USB_DEVICE(0x22b8, 0x7000), /* Motorola Q Phone */
+ .driver_info = NO_UNION_NORMAL, /* has no union descriptor */
+ },
+
/* control interfaces with various AT-command sets */
{ USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM,
USB_CDC_ACM_PROTO_AT_V25TER) },