aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Kubicek <dave@awk.cz>2005-11-01 12:51:34 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2006-01-04 16:48:29 -0500
commit61a87adf2e7b410da8e41799c61c21a7b8c8b001 (patch)
treeb4d09ce45dadd78cd2b92848a96c508f44d12f88
parent2e1dcc1600c1d83b26479edd076866595bbd3523 (diff)
[PATCH] USB: Converting cdc acm to a ring queue
this patch by David converts the sending queue of the CDC ACM driver to a queue of URBs. This is needed for quicker devices. Please apply. Signed-Off-By: Oliver Neukum <oliver@neukum.name> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> drivers/usb/class/cdc-acm.c | 229 ++++++++++++++++++++++++++++++-------------- drivers/usb/class/cdc-acm.h | 33 +++++- 2 files changed, 185 insertions(+), 77 deletions(-)
-rw-r--r--drivers/usb/class/cdc-acm.c227
-rw-r--r--drivers/usb/class/cdc-acm.h33
2 files changed, 184 insertions, 76 deletions
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index 1b4751412970..72936dc15ec9 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -6,6 +6,7 @@
6 * Copyright (c) 1999 Johannes Erdfelt <johannes@erdfelt.com> 6 * Copyright (c) 1999 Johannes Erdfelt <johannes@erdfelt.com>
7 * Copyright (c) 2000 Vojtech Pavlik <vojtech@suse.cz> 7 * Copyright (c) 2000 Vojtech Pavlik <vojtech@suse.cz>
8 * Copyright (c) 2004 Oliver Neukum <oliver@neukum.name> 8 * Copyright (c) 2004 Oliver Neukum <oliver@neukum.name>
9 * Copyright (c) 2005 David Kubicek <dave@awk.cz>
9 * 10 *
10 * USB Abstract Control Model driver for USB modems and ISDN adapters 11 * USB Abstract Control Model driver for USB modems and ISDN adapters
11 * 12 *
@@ -29,6 +30,7 @@
29 * config we want, sysadmin changes bConfigurationValue in sysfs. 30 * config we want, sysadmin changes bConfigurationValue in sysfs.
30 * v0.23 - use softirq for rx processing, as needed by tty layer 31 * v0.23 - use softirq for rx processing, as needed by tty layer
31 * v0.24 - change probe method to evaluate CDC union descriptor 32 * v0.24 - change probe method to evaluate CDC union descriptor
33 * v0.25 - downstream tasks paralelized to maximize throughput
32 */ 34 */
33 35
34/* 36/*
@@ -63,14 +65,15 @@
63#include <linux/usb_cdc.h> 65#include <linux/usb_cdc.h>
64#include <asm/byteorder.h> 66#include <asm/byteorder.h>
65#include <asm/unaligned.h> 67#include <asm/unaligned.h>
68#include <linux/list.h>
66 69
67#include "cdc-acm.h" 70#include "cdc-acm.h"
68 71
69/* 72/*
70 * Version Information 73 * Version Information
71 */ 74 */
72#define DRIVER_VERSION "v0.23" 75#define DRIVER_VERSION "v0.25"
73#define DRIVER_AUTHOR "Armin Fuerst, Pavel Machek, Johannes Erdfelt, Vojtech Pavlik" 76#define DRIVER_AUTHOR "Armin Fuerst, Pavel Machek, Johannes Erdfelt, Vojtech Pavlik, David Kubicek"
74#define DRIVER_DESC "USB Abstract Control Model driver for USB modems and ISDN adapters" 77#define DRIVER_DESC "USB Abstract Control Model driver for USB modems and ISDN adapters"
75 78
76static struct usb_driver acm_driver; 79static struct usb_driver acm_driver;
@@ -284,7 +287,9 @@ exit:
284/* data interface returns incoming bytes, or we got unthrottled */ 287/* data interface returns incoming bytes, or we got unthrottled */
285static void acm_read_bulk(struct urb *urb, struct pt_regs *regs) 288static void acm_read_bulk(struct urb *urb, struct pt_regs *regs)
286{ 289{
287 struct acm *acm = urb->context; 290 struct acm_rb *buf;
291 struct acm_ru *rcv = urb->context;
292 struct acm *acm = rcv->instance;
288 dbg("Entering acm_read_bulk with status %d\n", urb->status); 293 dbg("Entering acm_read_bulk with status %d\n", urb->status);
289 294
290 if (!ACM_READY(acm)) 295 if (!ACM_READY(acm))
@@ -293,49 +298,109 @@ static void acm_read_bulk(struct urb *urb, struct pt_regs *regs)
293 if (urb->status) 298 if (urb->status)
294 dev_dbg(&acm->data->dev, "bulk rx status %d\n", urb->status); 299 dev_dbg(&acm->data->dev, "bulk rx status %d\n", urb->status);
295 300
296 /* calling tty_flip_buffer_push() in_irq() isn't allowed */ 301 buf = rcv->buffer;
297 tasklet_schedule(&acm->bh); 302 buf->size = urb->actual_length;
303
304 spin_lock(&acm->read_lock);
305 list_add_tail(&rcv->list, &acm->spare_read_urbs);
306 list_add_tail(&buf->list, &acm->filled_read_bufs);
307 spin_unlock(&acm->read_lock);
308
309 tasklet_schedule(&acm->urb_task);
298} 310}
299 311
300static void acm_rx_tasklet(unsigned long _acm) 312static void acm_rx_tasklet(unsigned long _acm)
301{ 313{
302 struct acm *acm = (void *)_acm; 314 struct acm *acm = (void *)_acm;
303 struct urb *urb = acm->readurb; 315 struct acm_rb *buf;
304 struct tty_struct *tty = acm->tty; 316 struct tty_struct *tty = acm->tty;
305 unsigned char *data = urb->transfer_buffer; 317 struct acm_ru *rcv;
318 //unsigned long flags;
306 int i = 0; 319 int i = 0;
307 dbg("Entering acm_rx_tasklet"); 320 dbg("Entering acm_rx_tasklet");
308 321
309 if (urb->actual_length > 0 && !acm->throttle) { 322 if (!ACM_READY(acm) || acm->throttle)
310 for (i = 0; i < urb->actual_length && !acm->throttle; i++) { 323 return;
311 /* if we insert more than TTY_FLIPBUF_SIZE characters, 324
312 * we drop them. */ 325next_buffer:
313 if (tty->flip.count >= TTY_FLIPBUF_SIZE) { 326 spin_lock(&acm->read_lock);
314 tty_flip_buffer_push(tty); 327 if (list_empty(&acm->filled_read_bufs)) {
315 } 328 spin_unlock(&acm->read_lock);
316 tty_insert_flip_char(tty, data[i], 0); 329 goto urbs;
317 }
318 dbg("Handed %d bytes to tty layer", i+1);
319 tty_flip_buffer_push(tty);
320 } 330 }
331 buf = list_entry(acm->filled_read_bufs.next,
332 struct acm_rb, list);
333 list_del(&buf->list);
334 spin_unlock(&acm->read_lock);
335
336 dbg("acm_rx_tasklet: procesing buf 0x%p, size = %d\n", buf, buf->size);
337
338 for (i = 0; i < buf->size && !acm->throttle; i++) {
339 /* if we insert more than TTY_FLIPBUF_SIZE characters,
340 we drop them. */
341 if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
342 tty_flip_buffer_push(tty);
343 }
344 tty_insert_flip_char(tty, buf->base[i], 0);
345 }
346 tty_flip_buffer_push(tty);
321 347
322 spin_lock(&acm->throttle_lock); 348 spin_lock(&acm->throttle_lock);
323 if (acm->throttle) { 349 if (acm->throttle) {
324 dbg("Throtteling noticed"); 350 dbg("Throtteling noticed");
325 memmove(data, data + i, urb->actual_length - i); 351 memmove(buf->base, buf->base + i, buf->size - i);
326 urb->actual_length -= i; 352 buf->size -= i;
327 acm->resubmit_to_unthrottle = 1;
328 spin_unlock(&acm->throttle_lock); 353 spin_unlock(&acm->throttle_lock);
354 spin_lock(&acm->read_lock);
355 list_add(&buf->list, &acm->filled_read_bufs);
356 spin_unlock(&acm->read_lock);
329 return; 357 return;
330 } 358 }
331 spin_unlock(&acm->throttle_lock); 359 spin_unlock(&acm->throttle_lock);
332 360
333 urb->actual_length = 0; 361 spin_lock(&acm->read_lock);
334 urb->dev = acm->dev; 362 list_add(&buf->list, &acm->spare_read_bufs);
335 363 spin_unlock(&acm->read_lock);
336 i = usb_submit_urb(urb, GFP_ATOMIC); 364 goto next_buffer;
337 if (i) 365
338 dev_dbg(&acm->data->dev, "bulk rx resubmit %d\n", i); 366urbs:
367 while (!list_empty(&acm->spare_read_bufs)) {
368 spin_lock(&acm->read_lock);
369 if (list_empty(&acm->spare_read_urbs)) {
370 spin_unlock(&acm->read_lock);
371 return;
372 }
373 rcv = list_entry(acm->spare_read_urbs.next,
374 struct acm_ru, list);
375 list_del(&rcv->list);
376 spin_unlock(&acm->read_lock);
377
378 buf = list_entry(acm->spare_read_bufs.next,
379 struct acm_rb, list);
380 list_del(&buf->list);
381
382 rcv->buffer = buf;
383
384 usb_fill_bulk_urb(rcv->urb, acm->dev,
385 acm->rx_endpoint,
386 buf->base,
387 acm->readsize,
388 acm_read_bulk, rcv);
389 rcv->urb->transfer_dma = buf->dma;
390 rcv->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
391
392 dbg("acm_rx_tasklet: sending urb 0x%p, rcv 0x%p, buf 0x%p\n", rcv->urb, rcv, buf);
393
394 /* This shouldn't kill the driver as unsuccessful URBs are returned to the
395 free-urbs-pool and resubmited ASAP */
396 if (usb_submit_urb(rcv->urb, GFP_ATOMIC) < 0) {
397 list_add(&buf->list, &acm->spare_read_bufs);
398 spin_lock(&acm->read_lock);
399 list_add(&rcv->list, &acm->spare_read_urbs);
400 spin_unlock(&acm->read_lock);
401 return;
402 }
403 }
339} 404}
340 405
341/* data interface wrote those outgoing bytes */ 406/* data interface wrote those outgoing bytes */
@@ -369,6 +434,7 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp)
369{ 434{
370 struct acm *acm; 435 struct acm *acm;
371 int rv = -EINVAL; 436 int rv = -EINVAL;
437 int i;
372 dbg("Entering acm_tty_open.\n"); 438 dbg("Entering acm_tty_open.\n");
373 439
374 down(&open_sem); 440 down(&open_sem);
@@ -382,7 +448,9 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp)
382 tty->driver_data = acm; 448 tty->driver_data = acm;
383 acm->tty = tty; 449 acm->tty = tty;
384 450
385 451 /* force low_latency on so that our tty_push actually forces the data through,
452 otherwise it is scheduled, and with high data rates data can get lost. */
453 tty->low_latency = 1;
386 454
387 if (acm->used++) { 455 if (acm->used++) {
388 goto done; 456 goto done;
@@ -394,18 +462,20 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp)
394 goto bail_out; 462 goto bail_out;
395 } 463 }
396 464
397 acm->readurb->dev = acm->dev;
398 if (usb_submit_urb(acm->readurb, GFP_KERNEL)) {
399 dbg("usb_submit_urb(read bulk) failed");
400 goto bail_out_and_unlink;
401 }
402
403 if (0 > acm_set_control(acm, acm->ctrlout = ACM_CTRL_DTR | ACM_CTRL_RTS)) 465 if (0 > acm_set_control(acm, acm->ctrlout = ACM_CTRL_DTR | ACM_CTRL_RTS))
404 goto full_bailout; 466 goto full_bailout;
405 467
406 /* force low_latency on so that our tty_push actually forces the data through, 468 INIT_LIST_HEAD(&acm->spare_read_urbs);
407 otherwise it is scheduled, and with high data rates data can get lost. */ 469 INIT_LIST_HEAD(&acm->spare_read_bufs);
408 tty->low_latency = 1; 470 INIT_LIST_HEAD(&acm->filled_read_bufs);
471 for (i = 0; i < ACM_NRU; i++) {
472 list_add(&(acm->ru[i].list), &acm->spare_read_urbs);
473 }
474 for (i = 0; i < ACM_NRB; i++) {
475 list_add(&(acm->rb[i].list), &acm->spare_read_bufs);
476 }
477
478 tasklet_schedule(&acm->urb_task);
409 479
410done: 480done:
411err_out: 481err_out:
@@ -413,8 +483,6 @@ err_out:
413 return rv; 483 return rv;
414 484
415full_bailout: 485full_bailout:
416 usb_kill_urb(acm->readurb);
417bail_out_and_unlink:
418 usb_kill_urb(acm->ctrlurb); 486 usb_kill_urb(acm->ctrlurb);
419bail_out: 487bail_out:
420 acm->used--; 488 acm->used--;
@@ -424,18 +492,22 @@ bail_out:
424 492
425static void acm_tty_unregister(struct acm *acm) 493static void acm_tty_unregister(struct acm *acm)
426{ 494{
495 int i;
496
427 tty_unregister_device(acm_tty_driver, acm->minor); 497 tty_unregister_device(acm_tty_driver, acm->minor);
428 usb_put_intf(acm->control); 498 usb_put_intf(acm->control);
429 acm_table[acm->minor] = NULL; 499 acm_table[acm->minor] = NULL;
430 usb_free_urb(acm->ctrlurb); 500 usb_free_urb(acm->ctrlurb);
431 usb_free_urb(acm->readurb);
432 usb_free_urb(acm->writeurb); 501 usb_free_urb(acm->writeurb);
502 for (i = 0; i < ACM_NRU; i++)
503 usb_free_urb(acm->ru[i].urb);
433 kfree(acm); 504 kfree(acm);
434} 505}
435 506
436static void acm_tty_close(struct tty_struct *tty, struct file *filp) 507static void acm_tty_close(struct tty_struct *tty, struct file *filp)
437{ 508{
438 struct acm *acm = tty->driver_data; 509 struct acm *acm = tty->driver_data;
510 int i;
439 511
440 if (!acm || !acm->used) 512 if (!acm || !acm->used)
441 return; 513 return;
@@ -446,7 +518,8 @@ static void acm_tty_close(struct tty_struct *tty, struct file *filp)
446 acm_set_control(acm, acm->ctrlout = 0); 518 acm_set_control(acm, acm->ctrlout = 0);
447 usb_kill_urb(acm->ctrlurb); 519 usb_kill_urb(acm->ctrlurb);
448 usb_kill_urb(acm->writeurb); 520 usb_kill_urb(acm->writeurb);
449 usb_kill_urb(acm->readurb); 521 for (i = 0; i < ACM_NRU; i++)
522 usb_kill_urb(acm->ru[i].urb);
450 } else 523 } else
451 acm_tty_unregister(acm); 524 acm_tty_unregister(acm);
452 } 525 }
@@ -528,10 +601,7 @@ static void acm_tty_unthrottle(struct tty_struct *tty)
528 spin_lock_bh(&acm->throttle_lock); 601 spin_lock_bh(&acm->throttle_lock);
529 acm->throttle = 0; 602 acm->throttle = 0;
530 spin_unlock_bh(&acm->throttle_lock); 603 spin_unlock_bh(&acm->throttle_lock);
531 if (acm->resubmit_to_unthrottle) { 604 tasklet_schedule(&acm->urb_task);
532 acm->resubmit_to_unthrottle = 0;
533 acm_read_bulk(acm->readurb, NULL);
534 }
535} 605}
536 606
537static void acm_tty_break_ctl(struct tty_struct *tty, int state) 607static void acm_tty_break_ctl(struct tty_struct *tty, int state)
@@ -694,6 +764,7 @@ static int acm_probe (struct usb_interface *intf,
694 int call_interface_num = -1; 764 int call_interface_num = -1;
695 int data_interface_num; 765 int data_interface_num;
696 unsigned long quirks; 766 unsigned long quirks;
767 int i;
697 768
698 /* handle quirks deadly to normal probing*/ 769 /* handle quirks deadly to normal probing*/
699 quirks = (unsigned long)id->driver_info; 770 quirks = (unsigned long)id->driver_info;
@@ -833,7 +904,7 @@ skip_normal_probe:
833 } 904 }
834 905
835 ctrlsize = le16_to_cpu(epctrl->wMaxPacketSize); 906 ctrlsize = le16_to_cpu(epctrl->wMaxPacketSize);
836 readsize = le16_to_cpu(epread->wMaxPacketSize); 907 readsize = le16_to_cpu(epread->wMaxPacketSize)*2;
837 acm->writesize = le16_to_cpu(epwrite->wMaxPacketSize); 908 acm->writesize = le16_to_cpu(epwrite->wMaxPacketSize);
838 acm->control = control_interface; 909 acm->control = control_interface;
839 acm->data = data_interface; 910 acm->data = data_interface;
@@ -842,12 +913,14 @@ skip_normal_probe:
842 acm->ctrl_caps = ac_management_function; 913 acm->ctrl_caps = ac_management_function;
843 acm->ctrlsize = ctrlsize; 914 acm->ctrlsize = ctrlsize;
844 acm->readsize = readsize; 915 acm->readsize = readsize;
845 acm->bh.func = acm_rx_tasklet; 916 acm->urb_task.func = acm_rx_tasklet;
846 acm->bh.data = (unsigned long) acm; 917 acm->urb_task.data = (unsigned long) acm;
847 INIT_WORK(&acm->work, acm_softint, acm); 918 INIT_WORK(&acm->work, acm_softint, acm);
848 spin_lock_init(&acm->throttle_lock); 919 spin_lock_init(&acm->throttle_lock);
849 spin_lock_init(&acm->write_lock); 920 spin_lock_init(&acm->write_lock);
921 spin_lock_init(&acm->read_lock);
850 acm->write_ready = 1; 922 acm->write_ready = 1;
923 acm->rx_endpoint = usb_rcvbulkpipe(usb_dev, epread->bEndpointAddress);
851 924
852 buf = usb_buffer_alloc(usb_dev, ctrlsize, GFP_KERNEL, &acm->ctrl_dma); 925 buf = usb_buffer_alloc(usb_dev, ctrlsize, GFP_KERNEL, &acm->ctrl_dma);
853 if (!buf) { 926 if (!buf) {
@@ -856,13 +929,6 @@ skip_normal_probe:
856 } 929 }
857 acm->ctrl_buffer = buf; 930 acm->ctrl_buffer = buf;
858 931
859 buf = usb_buffer_alloc(usb_dev, readsize, GFP_KERNEL, &acm->read_dma);
860 if (!buf) {
861 dev_dbg(&intf->dev, "out of memory (read buffer alloc)\n");
862 goto alloc_fail3;
863 }
864 acm->read_buffer = buf;
865
866 if (acm_write_buffers_alloc(acm) < 0) { 932 if (acm_write_buffers_alloc(acm) < 0) {
867 dev_dbg(&intf->dev, "out of memory (write buffer alloc)\n"); 933 dev_dbg(&intf->dev, "out of memory (write buffer alloc)\n");
868 goto alloc_fail4; 934 goto alloc_fail4;
@@ -873,10 +939,25 @@ skip_normal_probe:
873 dev_dbg(&intf->dev, "out of memory (ctrlurb kmalloc)\n"); 939 dev_dbg(&intf->dev, "out of memory (ctrlurb kmalloc)\n");
874 goto alloc_fail5; 940 goto alloc_fail5;
875 } 941 }
876 acm->readurb = usb_alloc_urb(0, GFP_KERNEL); 942 for (i = 0; i < ACM_NRU; i++) {
877 if (!acm->readurb) { 943 struct acm_ru *rcv = &(acm->ru[i]);
878 dev_dbg(&intf->dev, "out of memory (readurb kmalloc)\n"); 944
879 goto alloc_fail6; 945 if (!(rcv->urb = usb_alloc_urb(0, GFP_KERNEL))) {
946 dev_dbg(&intf->dev, "out of memory (read urbs usb_alloc_urb)\n");
947 goto alloc_fail7;
948 }
949
950 rcv->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
951 rcv->instance = acm;
952 }
953 for (i = 0; i < ACM_NRB; i++) {
954 struct acm_rb *buf = &(acm->rb[i]);
955
956 // Using usb_buffer_alloc instead of kmalloc as Oliver suggested
957 if (!(buf->base = usb_buffer_alloc(acm->dev, readsize, GFP_KERNEL, &buf->dma))) {
958 dev_dbg(&intf->dev, "out of memory (read bufs usb_buffer_alloc)\n");
959 goto alloc_fail7;
960 }
880 } 961 }
881 acm->writeurb = usb_alloc_urb(0, GFP_KERNEL); 962 acm->writeurb = usb_alloc_urb(0, GFP_KERNEL);
882 if (!acm->writeurb) { 963 if (!acm->writeurb) {
@@ -889,15 +970,9 @@ skip_normal_probe:
889 acm->ctrlurb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; 970 acm->ctrlurb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
890 acm->ctrlurb->transfer_dma = acm->ctrl_dma; 971 acm->ctrlurb->transfer_dma = acm->ctrl_dma;
891 972
892 usb_fill_bulk_urb(acm->readurb, usb_dev, usb_rcvbulkpipe(usb_dev, epread->bEndpointAddress),
893 acm->read_buffer, readsize, acm_read_bulk, acm);
894 acm->readurb->transfer_flags |= URB_NO_FSBR | URB_NO_TRANSFER_DMA_MAP;
895 acm->readurb->transfer_dma = acm->read_dma;
896
897 usb_fill_bulk_urb(acm->writeurb, usb_dev, usb_sndbulkpipe(usb_dev, epwrite->bEndpointAddress), 973 usb_fill_bulk_urb(acm->writeurb, usb_dev, usb_sndbulkpipe(usb_dev, epwrite->bEndpointAddress),
898 NULL, acm->writesize, acm_write_bulk, acm); 974 NULL, acm->writesize, acm_write_bulk, acm);
899 acm->writeurb->transfer_flags |= URB_NO_FSBR | URB_NO_TRANSFER_DMA_MAP; 975 acm->writeurb->transfer_flags |= URB_NO_FSBR | URB_NO_TRANSFER_DMA_MAP;
900 /* acm->writeurb->transfer_dma = 0; */
901 976
902 dev_info(&intf->dev, "ttyACM%d: USB ACM device\n", minor); 977 dev_info(&intf->dev, "ttyACM%d: USB ACM device\n", minor);
903 978
@@ -917,14 +992,14 @@ skip_normal_probe:
917 return 0; 992 return 0;
918 993
919alloc_fail7: 994alloc_fail7:
920 usb_free_urb(acm->readurb); 995 for (i = 0; i < ACM_NRB; i++)
921alloc_fail6: 996 usb_buffer_free(usb_dev, acm->readsize, acm->rb[i].base, acm->rb[i].dma);
997 for (i = 0; i < ACM_NRU; i++)
998 usb_free_urb(acm->ru[i].urb);
922 usb_free_urb(acm->ctrlurb); 999 usb_free_urb(acm->ctrlurb);
923alloc_fail5: 1000alloc_fail5:
924 acm_write_buffers_free(acm); 1001 acm_write_buffers_free(acm);
925alloc_fail4: 1002alloc_fail4:
926 usb_buffer_free(usb_dev, readsize, acm->read_buffer, acm->read_dma);
927alloc_fail3:
928 usb_buffer_free(usb_dev, ctrlsize, acm->ctrl_buffer, acm->ctrl_dma); 1003 usb_buffer_free(usb_dev, ctrlsize, acm->ctrl_buffer, acm->ctrl_dma);
929alloc_fail2: 1004alloc_fail2:
930 kfree(acm); 1005 kfree(acm);
@@ -936,6 +1011,7 @@ static void acm_disconnect(struct usb_interface *intf)
936{ 1011{
937 struct acm *acm = usb_get_intfdata (intf); 1012 struct acm *acm = usb_get_intfdata (intf);
938 struct usb_device *usb_dev = interface_to_usbdev(intf); 1013 struct usb_device *usb_dev = interface_to_usbdev(intf);
1014 int i;
939 1015
940 if (!acm || !acm->dev) { 1016 if (!acm || !acm->dev) {
941 dbg("disconnect on nonexisting interface"); 1017 dbg("disconnect on nonexisting interface");
@@ -946,15 +1022,24 @@ static void acm_disconnect(struct usb_interface *intf)
946 acm->dev = NULL; 1022 acm->dev = NULL;
947 usb_set_intfdata (intf, NULL); 1023 usb_set_intfdata (intf, NULL);
948 1024
1025 tasklet_disable(&acm->urb_task);
1026
949 usb_kill_urb(acm->ctrlurb); 1027 usb_kill_urb(acm->ctrlurb);
950 usb_kill_urb(acm->readurb);
951 usb_kill_urb(acm->writeurb); 1028 usb_kill_urb(acm->writeurb);
1029 for (i = 0; i < ACM_NRU; i++)
1030 usb_kill_urb(acm->ru[i].urb);
1031
1032 INIT_LIST_HEAD(&acm->filled_read_bufs);
1033 INIT_LIST_HEAD(&acm->spare_read_bufs);
1034
1035 tasklet_enable(&acm->urb_task);
952 1036
953 flush_scheduled_work(); /* wait for acm_softint */ 1037 flush_scheduled_work(); /* wait for acm_softint */
954 1038
955 acm_write_buffers_free(acm); 1039 acm_write_buffers_free(acm);
956 usb_buffer_free(usb_dev, acm->readsize, acm->read_buffer, acm->read_dma);
957 usb_buffer_free(usb_dev, acm->ctrlsize, acm->ctrl_buffer, acm->ctrl_dma); 1040 usb_buffer_free(usb_dev, acm->ctrlsize, acm->ctrl_buffer, acm->ctrl_dma);
1041 for (i = 0; i < ACM_NRB; i++)
1042 usb_buffer_free(usb_dev, acm->readsize, acm->rb[i].base, acm->rb[i].dma);
958 1043
959 usb_driver_release_interface(&acm_driver, acm->data); 1044 usb_driver_release_interface(&acm_driver, acm->data);
960 1045
diff --git a/drivers/usb/class/cdc-acm.h b/drivers/usb/class/cdc-acm.h
index 963a5dfd2096..fd2aaccdcbac 100644
--- a/drivers/usb/class/cdc-acm.h
+++ b/drivers/usb/class/cdc-acm.h
@@ -59,6 +59,9 @@
59 * when processing onlcr, so we only need 2 buffers. 59 * when processing onlcr, so we only need 2 buffers.
60 */ 60 */
61#define ACM_NWB 2 61#define ACM_NWB 2
62#define ACM_NRU 16
63#define ACM_NRB 16
64
62struct acm_wb { 65struct acm_wb {
63 unsigned char *buf; 66 unsigned char *buf;
64 dma_addr_t dmah; 67 dma_addr_t dmah;
@@ -66,22 +69,43 @@ struct acm_wb {
66 int use; 69 int use;
67}; 70};
68 71
72struct acm_rb {
73 struct list_head list;
74 int size;
75 unsigned char *base;
76 dma_addr_t dma;
77};
78
79struct acm_ru {
80 struct list_head list;
81 struct acm_rb *buffer;
82 struct urb *urb;
83 struct acm *instance;
84};
85
69struct acm { 86struct acm {
70 struct usb_device *dev; /* the corresponding usb device */ 87 struct usb_device *dev; /* the corresponding usb device */
71 struct usb_interface *control; /* control interface */ 88 struct usb_interface *control; /* control interface */
72 struct usb_interface *data; /* data interface */ 89 struct usb_interface *data; /* data interface */
73 struct tty_struct *tty; /* the corresponding tty */ 90 struct tty_struct *tty; /* the corresponding tty */
74 struct urb *ctrlurb, *readurb, *writeurb; /* urbs */ 91 struct urb *ctrlurb, *writeurb; /* urbs */
75 u8 *ctrl_buffer, *read_buffer; /* buffers of urbs */ 92 u8 *ctrl_buffer; /* buffers of urbs */
76 dma_addr_t ctrl_dma, read_dma; /* dma handles of buffers */ 93 dma_addr_t ctrl_dma; /* dma handles of buffers */
77 struct acm_wb wb[ACM_NWB]; 94 struct acm_wb wb[ACM_NWB];
95 struct acm_ru ru[ACM_NRU];
96 struct acm_rb rb[ACM_NRB];
97 int rx_endpoint;
98 spinlock_t read_lock;
99 struct list_head spare_read_urbs;
100 struct list_head spare_read_bufs;
101 struct list_head filled_read_bufs;
78 int write_current; /* current write buffer */ 102 int write_current; /* current write buffer */
79 int write_used; /* number of non-empty write buffers */ 103 int write_used; /* number of non-empty write buffers */
80 int write_ready; /* write urb is not running */ 104 int write_ready; /* write urb is not running */
81 spinlock_t write_lock; 105 spinlock_t write_lock;
82 struct usb_cdc_line_coding line; /* bits, stop, parity */ 106 struct usb_cdc_line_coding line; /* bits, stop, parity */
83 struct work_struct work; /* work queue entry for line discipline waking up */ 107 struct work_struct work; /* work queue entry for line discipline waking up */
84 struct tasklet_struct bh; /* rx processing */ 108 struct tasklet_struct urb_task; /* rx processing */
85 spinlock_t throttle_lock; /* synchronize throtteling and read callback */ 109 spinlock_t throttle_lock; /* synchronize throtteling and read callback */
86 unsigned int ctrlin; /* input control lines (DCD, DSR, RI, break, overruns) */ 110 unsigned int ctrlin; /* input control lines (DCD, DSR, RI, break, overruns) */
87 unsigned int ctrlout; /* output control lines (DTR, RTS) */ 111 unsigned int ctrlout; /* output control lines (DTR, RTS) */
@@ -91,7 +115,6 @@ struct acm {
91 unsigned int minor; /* acm minor number */ 115 unsigned int minor; /* acm minor number */
92 unsigned char throttle; /* throttled by tty layer */ 116 unsigned char throttle; /* throttled by tty layer */
93 unsigned char clocal; /* termios CLOCAL */ 117 unsigned char clocal; /* termios CLOCAL */
94 unsigned char resubmit_to_unthrottle; /* throtteling has disabled the read urb */
95 unsigned int ctrl_caps; /* control capabilities from the class specific header */ 118 unsigned int ctrl_caps; /* control capabilities from the class specific header */
96}; 119};
97 120