aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/class/cdc-acm.c
diff options
context:
space:
mode:
authorOliver Neukum <neukum@fachschaft.cup.uni-muenchen.de>2006-05-13 16:50:47 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2006-06-21 18:04:08 -0400
commit86478944eba887f149e151bacc023ae4b2d23ea6 (patch)
tree21c9871c1524c75cc702e0fbaa7700e82a9f744f /drivers/usb/class/cdc-acm.c
parent5cd330f4f30eb154e7af9210bed42dfcd447997f (diff)
[PATCH] USB: cdc-acm: add a new special case for modems with buggy firmware
this fixes the "duplicated text" bug. There's a modem that cannot cope with large transfers and more than one urb in flight. This patch adds a special case to the driver. Signed-off-by: Oliver Neukum <oliver@neukum.name> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/class/cdc-acm.c')
-rw-r--r--drivers/usb/class/cdc-acm.c82
1 files changed, 50 insertions, 32 deletions
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index 6dd339f4c0fc..506aff60dac5 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -127,8 +127,8 @@ static int acm_wb_alloc(struct acm *acm)
127 wb->use = 1; 127 wb->use = 1;
128 return wbn; 128 return wbn;
129 } 129 }
130 wbn = (wbn + 1) % ACM_NWB; 130 wbn = (wbn + 1) % ACM_NW;
131 if (++i >= ACM_NWB) 131 if (++i >= ACM_NW)
132 return -1; 132 return -1;
133 } 133 }
134} 134}
@@ -142,10 +142,9 @@ static int acm_wb_is_avail(struct acm *acm)
142{ 142{
143 int i, n; 143 int i, n;
144 144
145 n = 0; 145 n = ACM_NW;
146 for (i = 0; i < ACM_NWB; i++) { 146 for (i = 0; i < ACM_NW; i++) {
147 if (!acm->wb[i].use) 147 n -= acm->wb[i].use;
148 n++;
149 } 148 }
150 return n; 149 return n;
151} 150}
@@ -167,7 +166,7 @@ static void acm_write_done(struct acm *acm)
167 acm->write_ready = 1; 166 acm->write_ready = 1;
168 wbn = acm->write_current; 167 wbn = acm->write_current;
169 acm_wb_free(acm, wbn); 168 acm_wb_free(acm, wbn);
170 acm->write_current = (wbn + 1) % ACM_NWB; 169 acm->write_current = (wbn + 1) % ACM_NW;
171 spin_unlock_irqrestore(&acm->write_lock, flags); 170 spin_unlock_irqrestore(&acm->write_lock, flags);
172} 171}
173 172
@@ -291,22 +290,32 @@ static void acm_read_bulk(struct urb *urb, struct pt_regs *regs)
291 struct acm_rb *buf; 290 struct acm_rb *buf;
292 struct acm_ru *rcv = urb->context; 291 struct acm_ru *rcv = urb->context;
293 struct acm *acm = rcv->instance; 292 struct acm *acm = rcv->instance;
293 int status = urb->status;
294 dbg("Entering acm_read_bulk with status %d\n", urb->status); 294 dbg("Entering acm_read_bulk with status %d\n", urb->status);
295 295
296 if (!ACM_READY(acm)) 296 if (!ACM_READY(acm))
297 return; 297 return;
298 298
299 if (urb->status) 299 if (status)
300 dev_dbg(&acm->data->dev, "bulk rx status %d\n", urb->status); 300 dev_dbg(&acm->data->dev, "bulk rx status %d\n", status);
301 301
302 buf = rcv->buffer; 302 buf = rcv->buffer;
303 buf->size = urb->actual_length; 303 buf->size = urb->actual_length;
304 304
305 spin_lock(&acm->read_lock); 305 if (likely(status == 0)) {
306 list_add_tail(&rcv->list, &acm->spare_read_urbs); 306 spin_lock(&acm->read_lock);
307 list_add_tail(&buf->list, &acm->filled_read_bufs); 307 list_add_tail(&rcv->list, &acm->spare_read_urbs);
308 spin_unlock(&acm->read_lock); 308 list_add_tail(&buf->list, &acm->filled_read_bufs);
309 309 spin_unlock(&acm->read_lock);
310 } else {
311 /* we drop the buffer due to an error */
312 spin_lock(&acm->read_lock);
313 list_add_tail(&rcv->list, &acm->spare_read_urbs);
314 list_add(&buf->list, &acm->spare_read_bufs);
315 spin_unlock(&acm->read_lock);
316 /* nevertheless the tasklet must be kicked unconditionally
317 so the queue cannot dry up */
318 }
310 tasklet_schedule(&acm->urb_task); 319 tasklet_schedule(&acm->urb_task);
311} 320}
312 321
@@ -464,10 +473,10 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp)
464 INIT_LIST_HEAD(&acm->spare_read_urbs); 473 INIT_LIST_HEAD(&acm->spare_read_urbs);
465 INIT_LIST_HEAD(&acm->spare_read_bufs); 474 INIT_LIST_HEAD(&acm->spare_read_bufs);
466 INIT_LIST_HEAD(&acm->filled_read_bufs); 475 INIT_LIST_HEAD(&acm->filled_read_bufs);
467 for (i = 0; i < ACM_NRU; i++) { 476 for (i = 0; i < acm->rx_buflimit; i++) {
468 list_add(&(acm->ru[i].list), &acm->spare_read_urbs); 477 list_add(&(acm->ru[i].list), &acm->spare_read_urbs);
469 } 478 }
470 for (i = 0; i < ACM_NRB; i++) { 479 for (i = 0; i < acm->rx_buflimit; i++) {
471 list_add(&(acm->rb[i].list), &acm->spare_read_bufs); 480 list_add(&(acm->rb[i].list), &acm->spare_read_bufs);
472 } 481 }
473 482
@@ -488,14 +497,15 @@ bail_out:
488 497
489static void acm_tty_unregister(struct acm *acm) 498static void acm_tty_unregister(struct acm *acm)
490{ 499{
491 int i; 500 int i,nr;
492 501
502 nr = acm->rx_buflimit;
493 tty_unregister_device(acm_tty_driver, acm->minor); 503 tty_unregister_device(acm_tty_driver, acm->minor);
494 usb_put_intf(acm->control); 504 usb_put_intf(acm->control);
495 acm_table[acm->minor] = NULL; 505 acm_table[acm->minor] = NULL;
496 usb_free_urb(acm->ctrlurb); 506 usb_free_urb(acm->ctrlurb);
497 usb_free_urb(acm->writeurb); 507 usb_free_urb(acm->writeurb);
498 for (i = 0; i < ACM_NRU; i++) 508 for (i = 0; i < nr; i++)
499 usb_free_urb(acm->ru[i].urb); 509 usb_free_urb(acm->ru[i].urb);
500 kfree(acm); 510 kfree(acm);
501} 511}
@@ -503,18 +513,19 @@ static void acm_tty_unregister(struct acm *acm)
503static void acm_tty_close(struct tty_struct *tty, struct file *filp) 513static void acm_tty_close(struct tty_struct *tty, struct file *filp)
504{ 514{
505 struct acm *acm = tty->driver_data; 515 struct acm *acm = tty->driver_data;
506 int i; 516 int i,nr;
507 517
508 if (!acm || !acm->used) 518 if (!acm || !acm->used)
509 return; 519 return;
510 520
521 nr = acm->rx_buflimit;
511 mutex_lock(&open_mutex); 522 mutex_lock(&open_mutex);
512 if (!--acm->used) { 523 if (!--acm->used) {
513 if (acm->dev) { 524 if (acm->dev) {
514 acm_set_control(acm, acm->ctrlout = 0); 525 acm_set_control(acm, acm->ctrlout = 0);
515 usb_kill_urb(acm->ctrlurb); 526 usb_kill_urb(acm->ctrlurb);
516 usb_kill_urb(acm->writeurb); 527 usb_kill_urb(acm->writeurb);
517 for (i = 0; i < ACM_NRU; i++) 528 for (i = 0; i < nr; i++)
518 usb_kill_urb(acm->ru[i].urb); 529 usb_kill_urb(acm->ru[i].urb);
519 } else 530 } else
520 acm_tty_unregister(acm); 531 acm_tty_unregister(acm);
@@ -576,7 +587,7 @@ static int acm_tty_chars_in_buffer(struct tty_struct *tty)
576 /* 587 /*
577 * This is inaccurate (overcounts), but it works. 588 * This is inaccurate (overcounts), but it works.
578 */ 589 */
579 return (ACM_NWB - acm_wb_is_avail(acm)) * acm->writesize; 590 return (ACM_NW - acm_wb_is_avail(acm)) * acm->writesize;
580} 591}
581 592
582static void acm_tty_throttle(struct tty_struct *tty) 593static void acm_tty_throttle(struct tty_struct *tty)
@@ -712,7 +723,7 @@ static void acm_write_buffers_free(struct acm *acm)
712 int i; 723 int i;
713 struct acm_wb *wb; 724 struct acm_wb *wb;
714 725
715 for (wb = &acm->wb[0], i = 0; i < ACM_NWB; i++, wb++) { 726 for (wb = &acm->wb[0], i = 0; i < ACM_NW; i++, wb++) {
716 usb_buffer_free(acm->dev, acm->writesize, wb->buf, wb->dmah); 727 usb_buffer_free(acm->dev, acm->writesize, wb->buf, wb->dmah);
717 } 728 }
718} 729}
@@ -723,7 +734,7 @@ static int acm_write_buffers_alloc(struct acm *acm)
723 int i; 734 int i;
724 struct acm_wb *wb; 735 struct acm_wb *wb;
725 736
726 for (wb = &acm->wb[0], i = 0; i < ACM_NWB; i++, wb++) { 737 for (wb = &acm->wb[0], i = 0; i < ACM_NW; i++, wb++) {
727 wb->buf = usb_buffer_alloc(acm->dev, acm->writesize, GFP_KERNEL, 738 wb->buf = usb_buffer_alloc(acm->dev, acm->writesize, GFP_KERNEL,
728 &wb->dmah); 739 &wb->dmah);
729 if (!wb->buf) { 740 if (!wb->buf) {
@@ -760,10 +771,14 @@ static int acm_probe (struct usb_interface *intf,
760 int call_interface_num = -1; 771 int call_interface_num = -1;
761 int data_interface_num; 772 int data_interface_num;
762 unsigned long quirks; 773 unsigned long quirks;
774 int num_rx_buf;
763 int i; 775 int i;
764 776
765 /* handle quirks deadly to normal probing*/ 777 /* normal quirks */
766 quirks = (unsigned long)id->driver_info; 778 quirks = (unsigned long)id->driver_info;
779 num_rx_buf = (quirks == SINGLE_RX_URB) ? 1 : ACM_NR;
780
781 /* handle quirks deadly to normal probing*/
767 if (quirks == NO_UNION_NORMAL) { 782 if (quirks == NO_UNION_NORMAL) {
768 data_interface = usb_ifnum_to_if(usb_dev, 1); 783 data_interface = usb_ifnum_to_if(usb_dev, 1);
769 control_interface = usb_ifnum_to_if(usb_dev, 0); 784 control_interface = usb_ifnum_to_if(usb_dev, 0);
@@ -900,7 +915,7 @@ skip_normal_probe:
900 } 915 }
901 916
902 ctrlsize = le16_to_cpu(epctrl->wMaxPacketSize); 917 ctrlsize = le16_to_cpu(epctrl->wMaxPacketSize);
903 readsize = le16_to_cpu(epread->wMaxPacketSize)*2; 918 readsize = le16_to_cpu(epread->wMaxPacketSize)* ( quirks == SINGLE_RX_URB ? 1 : 2);
904 acm->writesize = le16_to_cpu(epwrite->wMaxPacketSize); 919 acm->writesize = le16_to_cpu(epwrite->wMaxPacketSize);
905 acm->control = control_interface; 920 acm->control = control_interface;
906 acm->data = data_interface; 921 acm->data = data_interface;
@@ -909,6 +924,7 @@ skip_normal_probe:
909 acm->ctrl_caps = ac_management_function; 924 acm->ctrl_caps = ac_management_function;
910 acm->ctrlsize = ctrlsize; 925 acm->ctrlsize = ctrlsize;
911 acm->readsize = readsize; 926 acm->readsize = readsize;
927 acm->rx_buflimit = num_rx_buf;
912 acm->urb_task.func = acm_rx_tasklet; 928 acm->urb_task.func = acm_rx_tasklet;
913 acm->urb_task.data = (unsigned long) acm; 929 acm->urb_task.data = (unsigned long) acm;
914 INIT_WORK(&acm->work, acm_softint, acm); 930 INIT_WORK(&acm->work, acm_softint, acm);
@@ -935,7 +951,7 @@ skip_normal_probe:
935 dev_dbg(&intf->dev, "out of memory (ctrlurb kmalloc)\n"); 951 dev_dbg(&intf->dev, "out of memory (ctrlurb kmalloc)\n");
936 goto alloc_fail5; 952 goto alloc_fail5;
937 } 953 }
938 for (i = 0; i < ACM_NRU; i++) { 954 for (i = 0; i < num_rx_buf; i++) {
939 struct acm_ru *rcv = &(acm->ru[i]); 955 struct acm_ru *rcv = &(acm->ru[i]);
940 956
941 if (!(rcv->urb = usb_alloc_urb(0, GFP_KERNEL))) { 957 if (!(rcv->urb = usb_alloc_urb(0, GFP_KERNEL))) {
@@ -946,10 +962,9 @@ skip_normal_probe:
946 rcv->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; 962 rcv->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
947 rcv->instance = acm; 963 rcv->instance = acm;
948 } 964 }
949 for (i = 0; i < ACM_NRB; i++) { 965 for (i = 0; i < num_rx_buf; i++) {
950 struct acm_rb *buf = &(acm->rb[i]); 966 struct acm_rb *buf = &(acm->rb[i]);
951 967
952 // Using usb_buffer_alloc instead of kmalloc as Oliver suggested
953 if (!(buf->base = usb_buffer_alloc(acm->dev, readsize, GFP_KERNEL, &buf->dma))) { 968 if (!(buf->base = usb_buffer_alloc(acm->dev, readsize, GFP_KERNEL, &buf->dma))) {
954 dev_dbg(&intf->dev, "out of memory (read bufs usb_buffer_alloc)\n"); 969 dev_dbg(&intf->dev, "out of memory (read bufs usb_buffer_alloc)\n");
955 goto alloc_fail7; 970 goto alloc_fail7;
@@ -988,9 +1003,9 @@ skip_normal_probe:
988 return 0; 1003 return 0;
989 1004
990alloc_fail7: 1005alloc_fail7:
991 for (i = 0; i < ACM_NRB; i++) 1006 for (i = 0; i < num_rx_buf; i++)
992 usb_buffer_free(usb_dev, acm->readsize, acm->rb[i].base, acm->rb[i].dma); 1007 usb_buffer_free(usb_dev, acm->readsize, acm->rb[i].base, acm->rb[i].dma);
993 for (i = 0; i < ACM_NRU; i++) 1008 for (i = 0; i < num_rx_buf; i++)
994 usb_free_urb(acm->ru[i].urb); 1009 usb_free_urb(acm->ru[i].urb);
995 usb_free_urb(acm->ctrlurb); 1010 usb_free_urb(acm->ctrlurb);
996alloc_fail5: 1011alloc_fail5:
@@ -1027,7 +1042,7 @@ static void acm_disconnect(struct usb_interface *intf)
1027 1042
1028 usb_kill_urb(acm->ctrlurb); 1043 usb_kill_urb(acm->ctrlurb);
1029 usb_kill_urb(acm->writeurb); 1044 usb_kill_urb(acm->writeurb);
1030 for (i = 0; i < ACM_NRU; i++) 1045 for (i = 0; i < acm->rx_buflimit; i++)
1031 usb_kill_urb(acm->ru[i].urb); 1046 usb_kill_urb(acm->ru[i].urb);
1032 1047
1033 INIT_LIST_HEAD(&acm->filled_read_bufs); 1048 INIT_LIST_HEAD(&acm->filled_read_bufs);
@@ -1039,7 +1054,7 @@ static void acm_disconnect(struct usb_interface *intf)
1039 1054
1040 acm_write_buffers_free(acm); 1055 acm_write_buffers_free(acm);
1041 usb_buffer_free(usb_dev, acm->ctrlsize, acm->ctrl_buffer, acm->ctrl_dma); 1056 usb_buffer_free(usb_dev, acm->ctrlsize, acm->ctrl_buffer, acm->ctrl_dma);
1042 for (i = 0; i < ACM_NRB; i++) 1057 for (i = 0; i < acm->rx_buflimit; i++)
1043 usb_buffer_free(usb_dev, acm->readsize, acm->rb[i].base, acm->rb[i].dma); 1058 usb_buffer_free(usb_dev, acm->readsize, acm->rb[i].base, acm->rb[i].dma);
1044 1059
1045 usb_driver_release_interface(&acm_driver, intf == acm->control ? acm->data : intf); 1060 usb_driver_release_interface(&acm_driver, intf == acm->control ? acm->data : intf);
@@ -1068,6 +1083,9 @@ static struct usb_device_id acm_ids[] = {
1068 { USB_DEVICE(0x0482, 0x0203), /* KYOCERA AH-K3001V */ 1083 { USB_DEVICE(0x0482, 0x0203), /* KYOCERA AH-K3001V */
1069 .driver_info = NO_UNION_NORMAL, /* has no union descriptor */ 1084 .driver_info = NO_UNION_NORMAL, /* has no union descriptor */
1070 }, 1085 },
1086 { USB_DEVICE(0x0ace, 0x1608), /* ZyDAS 56K USB MODEM */
1087 .driver_info = SINGLE_RX_URB, /* firmware bug */
1088 },
1071 /* control interfaces with various AT-command sets */ 1089 /* control interfaces with various AT-command sets */
1072 { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, 1090 { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM,
1073 USB_CDC_ACM_PROTO_AT_V25TER) }, 1091 USB_CDC_ACM_PROTO_AT_V25TER) },