Skip to content

Commit 8647894

Browse files
Oliver Neukumgregkh
authored andcommitted
[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 <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 5cd330f commit 8647894

File tree

2 files changed

+59
-39
lines changed

2 files changed

+59
-39
lines changed

drivers/usb/class/cdc-acm.c

Lines changed: 50 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -127,8 +127,8 @@ static int acm_wb_alloc(struct acm *acm)
127127
wb->use = 1;
128128
return wbn;
129129
}
130-
wbn = (wbn + 1) % ACM_NWB;
131-
if (++i >= ACM_NWB)
130+
wbn = (wbn + 1) % ACM_NW;
131+
if (++i >= ACM_NW)
132132
return -1;
133133
}
134134
}
@@ -142,10 +142,9 @@ static int acm_wb_is_avail(struct acm *acm)
142142
{
143143
int i, n;
144144

145-
n = 0;
146-
for (i = 0; i < ACM_NWB; i++) {
147-
if (!acm->wb[i].use)
148-
n++;
145+
n = ACM_NW;
146+
for (i = 0; i < ACM_NW; i++) {
147+
n -= acm->wb[i].use;
149148
}
150149
return n;
151150
}
@@ -167,7 +166,7 @@ static void acm_write_done(struct acm *acm)
167166
acm->write_ready = 1;
168167
wbn = acm->write_current;
169168
acm_wb_free(acm, wbn);
170-
acm->write_current = (wbn + 1) % ACM_NWB;
169+
acm->write_current = (wbn + 1) % ACM_NW;
171170
spin_unlock_irqrestore(&acm->write_lock, flags);
172171
}
173172

@@ -291,22 +290,32 @@ static void acm_read_bulk(struct urb *urb, struct pt_regs *regs)
291290
struct acm_rb *buf;
292291
struct acm_ru *rcv = urb->context;
293292
struct acm *acm = rcv->instance;
293+
int status = urb->status;
294294
dbg("Entering acm_read_bulk with status %d\n", urb->status);
295295

296296
if (!ACM_READY(acm))
297297
return;
298298

299-
if (urb->status)
300-
dev_dbg(&acm->data->dev, "bulk rx status %d\n", urb->status);
299+
if (status)
300+
dev_dbg(&acm->data->dev, "bulk rx status %d\n", status);
301301

302302
buf = rcv->buffer;
303303
buf->size = urb->actual_length;
304304

305-
spin_lock(&acm->read_lock);
306-
list_add_tail(&rcv->list, &acm->spare_read_urbs);
307-
list_add_tail(&buf->list, &acm->filled_read_bufs);
308-
spin_unlock(&acm->read_lock);
309-
305+
if (likely(status == 0)) {
306+
spin_lock(&acm->read_lock);
307+
list_add_tail(&rcv->list, &acm->spare_read_urbs);
308+
list_add_tail(&buf->list, &acm->filled_read_bufs);
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+
}
310319
tasklet_schedule(&acm->urb_task);
311320
}
312321

@@ -464,10 +473,10 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp)
464473
INIT_LIST_HEAD(&acm->spare_read_urbs);
465474
INIT_LIST_HEAD(&acm->spare_read_bufs);
466475
INIT_LIST_HEAD(&acm->filled_read_bufs);
467-
for (i = 0; i < ACM_NRU; i++) {
476+
for (i = 0; i < acm->rx_buflimit; i++) {
468477
list_add(&(acm->ru[i].list), &acm->spare_read_urbs);
469478
}
470-
for (i = 0; i < ACM_NRB; i++) {
479+
for (i = 0; i < acm->rx_buflimit; i++) {
471480
list_add(&(acm->rb[i].list), &acm->spare_read_bufs);
472481
}
473482

@@ -488,33 +497,35 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp)
488497

489498
static void acm_tty_unregister(struct acm *acm)
490499
{
491-
int i;
500+
int i,nr;
492501

502+
nr = acm->rx_buflimit;
493503
tty_unregister_device(acm_tty_driver, acm->minor);
494504
usb_put_intf(acm->control);
495505
acm_table[acm->minor] = NULL;
496506
usb_free_urb(acm->ctrlurb);
497507
usb_free_urb(acm->writeurb);
498-
for (i = 0; i < ACM_NRU; i++)
508+
for (i = 0; i < nr; i++)
499509
usb_free_urb(acm->ru[i].urb);
500510
kfree(acm);
501511
}
502512

503513
static void acm_tty_close(struct tty_struct *tty, struct file *filp)
504514
{
505515
struct acm *acm = tty->driver_data;
506-
int i;
516+
int i,nr;
507517

508518
if (!acm || !acm->used)
509519
return;
510520

521+
nr = acm->rx_buflimit;
511522
mutex_lock(&open_mutex);
512523
if (!--acm->used) {
513524
if (acm->dev) {
514525
acm_set_control(acm, acm->ctrlout = 0);
515526
usb_kill_urb(acm->ctrlurb);
516527
usb_kill_urb(acm->writeurb);
517-
for (i = 0; i < ACM_NRU; i++)
528+
for (i = 0; i < nr; i++)
518529
usb_kill_urb(acm->ru[i].urb);
519530
} else
520531
acm_tty_unregister(acm);
@@ -576,7 +587,7 @@ static int acm_tty_chars_in_buffer(struct tty_struct *tty)
576587
/*
577588
* This is inaccurate (overcounts), but it works.
578589
*/
579-
return (ACM_NWB - acm_wb_is_avail(acm)) * acm->writesize;
590+
return (ACM_NW - acm_wb_is_avail(acm)) * acm->writesize;
580591
}
581592

582593
static void acm_tty_throttle(struct tty_struct *tty)
@@ -712,7 +723,7 @@ static void acm_write_buffers_free(struct acm *acm)
712723
int i;
713724
struct acm_wb *wb;
714725

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++) {
716727
usb_buffer_free(acm->dev, acm->writesize, wb->buf, wb->dmah);
717728
}
718729
}
@@ -723,7 +734,7 @@ static int acm_write_buffers_alloc(struct acm *acm)
723734
int i;
724735
struct acm_wb *wb;
725736

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++) {
727738
wb->buf = usb_buffer_alloc(acm->dev, acm->writesize, GFP_KERNEL,
728739
&wb->dmah);
729740
if (!wb->buf) {
@@ -760,10 +771,14 @@ static int acm_probe (struct usb_interface *intf,
760771
int call_interface_num = -1;
761772
int data_interface_num;
762773
unsigned long quirks;
774+
int num_rx_buf;
763775
int i;
764776

765-
/* handle quirks deadly to normal probing*/
777+
/* normal quirks */
766778
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*/
767782
if (quirks == NO_UNION_NORMAL) {
768783
data_interface = usb_ifnum_to_if(usb_dev, 1);
769784
control_interface = usb_ifnum_to_if(usb_dev, 0);
@@ -900,7 +915,7 @@ static int acm_probe (struct usb_interface *intf,
900915
}
901916

902917
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);
904919
acm->writesize = le16_to_cpu(epwrite->wMaxPacketSize);
905920
acm->control = control_interface;
906921
acm->data = data_interface;
@@ -909,6 +924,7 @@ static int acm_probe (struct usb_interface *intf,
909924
acm->ctrl_caps = ac_management_function;
910925
acm->ctrlsize = ctrlsize;
911926
acm->readsize = readsize;
927+
acm->rx_buflimit = num_rx_buf;
912928
acm->urb_task.func = acm_rx_tasklet;
913929
acm->urb_task.data = (unsigned long) acm;
914930
INIT_WORK(&acm->work, acm_softint, acm);
@@ -935,7 +951,7 @@ static int acm_probe (struct usb_interface *intf,
935951
dev_dbg(&intf->dev, "out of memory (ctrlurb kmalloc)\n");
936952
goto alloc_fail5;
937953
}
938-
for (i = 0; i < ACM_NRU; i++) {
954+
for (i = 0; i < num_rx_buf; i++) {
939955
struct acm_ru *rcv = &(acm->ru[i]);
940956

941957
if (!(rcv->urb = usb_alloc_urb(0, GFP_KERNEL))) {
@@ -946,10 +962,9 @@ static int acm_probe (struct usb_interface *intf,
946962
rcv->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
947963
rcv->instance = acm;
948964
}
949-
for (i = 0; i < ACM_NRB; i++) {
965+
for (i = 0; i < num_rx_buf; i++) {
950966
struct acm_rb *buf = &(acm->rb[i]);
951967

952-
// Using usb_buffer_alloc instead of kmalloc as Oliver suggested
953968
if (!(buf->base = usb_buffer_alloc(acm->dev, readsize, GFP_KERNEL, &buf->dma))) {
954969
dev_dbg(&intf->dev, "out of memory (read bufs usb_buffer_alloc)\n");
955970
goto alloc_fail7;
@@ -988,9 +1003,9 @@ static int acm_probe (struct usb_interface *intf,
9881003
return 0;
9891004

9901005
alloc_fail7:
991-
for (i = 0; i < ACM_NRB; i++)
1006+
for (i = 0; i < num_rx_buf; i++)
9921007
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++)
9941009
usb_free_urb(acm->ru[i].urb);
9951010
usb_free_urb(acm->ctrlurb);
9961011
alloc_fail5:
@@ -1027,7 +1042,7 @@ static void acm_disconnect(struct usb_interface *intf)
10271042

10281043
usb_kill_urb(acm->ctrlurb);
10291044
usb_kill_urb(acm->writeurb);
1030-
for (i = 0; i < ACM_NRU; i++)
1045+
for (i = 0; i < acm->rx_buflimit; i++)
10311046
usb_kill_urb(acm->ru[i].urb);
10321047

10331048
INIT_LIST_HEAD(&acm->filled_read_bufs);
@@ -1039,7 +1054,7 @@ static void acm_disconnect(struct usb_interface *intf)
10391054

10401055
acm_write_buffers_free(acm);
10411056
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++)
10431058
usb_buffer_free(usb_dev, acm->readsize, acm->rb[i].base, acm->rb[i].dma);
10441059

10451060
usb_driver_release_interface(&acm_driver, intf == acm->control ? acm->data : intf);
@@ -1068,6 +1083,9 @@ static struct usb_device_id acm_ids[] = {
10681083
{ USB_DEVICE(0x0482, 0x0203), /* KYOCERA AH-K3001V */
10691084
.driver_info = NO_UNION_NORMAL, /* has no union descriptor */
10701085
},
1086+
{ USB_DEVICE(0x0ace, 0x1608), /* ZyDAS 56K USB MODEM */
1087+
.driver_info = SINGLE_RX_URB, /* firmware bug */
1088+
},
10711089
/* control interfaces with various AT-command sets */
10721090
{ USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM,
10731091
USB_CDC_ACM_PROTO_AT_V25TER) },

drivers/usb/class/cdc-acm.h

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -56,11 +56,11 @@
5656
* in line disciplines. They ask for empty space amount, receive our URB size,
5757
* and proceed to issue several 1-character writes, assuming they will fit.
5858
* The very first write takes a complete URB. Fortunately, this only happens
59-
* when processing onlcr, so we only need 2 buffers.
59+
* when processing onlcr, so we only need 2 buffers. These values must be
60+
* powers of 2.
6061
*/
61-
#define ACM_NWB 2
62-
#define ACM_NRU 16
63-
#define ACM_NRB 16
62+
#define ACM_NW 2
63+
#define ACM_NR 16
6464

6565
struct acm_wb {
6666
unsigned char *buf;
@@ -91,9 +91,10 @@ struct acm {
9191
struct urb *ctrlurb, *writeurb; /* urbs */
9292
u8 *ctrl_buffer; /* buffers of urbs */
9393
dma_addr_t ctrl_dma; /* dma handles of buffers */
94-
struct acm_wb wb[ACM_NWB];
95-
struct acm_ru ru[ACM_NRU];
96-
struct acm_rb rb[ACM_NRB];
94+
struct acm_wb wb[ACM_NW];
95+
struct acm_ru ru[ACM_NR];
96+
struct acm_rb rb[ACM_NR];
97+
int rx_buflimit;
9798
int rx_endpoint;
9899
spinlock_t read_lock;
99100
struct list_head spare_read_urbs;
@@ -122,3 +123,4 @@ struct acm {
122123

123124
/* constants describing various quirks and errors */
124125
#define NO_UNION_NORMAL 1
126+
#define SINGLE_RX_URB 2

0 commit comments

Comments
 (0)