From 59d7fec7c6908604862658a3679ac44c2c3eea44 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 22 Mar 2011 11:12:12 +0100 Subject: USB: cdc-acm: add missing newlines to dev_dbg and dev_err Add missing newline to two dev_dbg and dev_err messages. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-acm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/usb/class/cdc-acm.c') diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index e057e538146..849aa04e609 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -341,7 +341,7 @@ exit: retval = usb_submit_urb(urb, GFP_ATOMIC); if (retval) dev_err(&urb->dev->dev, "%s - usb_submit_urb failed with " - "result %d", __func__, retval); + "result %d\n", __func__, retval); } /* data interface returns incoming bytes, or we got unthrottled */ @@ -355,7 +355,7 @@ static void acm_read_bulk(struct urb *urb) dbg("Entering acm_read_bulk with status %d", status); if (!ACM_READY(acm)) { - dev_dbg(&acm->data->dev, "Aborting, acm not ready"); + dev_dbg(&acm->data->dev, "Aborting, acm not ready\n"); return; } usb_mark_last_busy(acm->dev); @@ -1224,7 +1224,7 @@ made_compressed_probe: snd->urb = usb_alloc_urb(0, GFP_KERNEL); if (snd->urb == NULL) { dev_dbg(&intf->dev, - "out of memory (write urbs usb_alloc_urb)"); + "out of memory (write urbs usb_alloc_urb)\n"); goto alloc_fail8; } -- cgit v1.2.2 From 255ab56c5ae30165d506b837f6576944a02ecdf0 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 22 Mar 2011 11:12:13 +0100 Subject: USB: cdc-acm: use dev_err to report failed allocations Upgrade out-of-memory dev_dbg to dev_err. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-acm.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers/usb/class/cdc-acm.c') diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 849aa04e609..c9f8a837c5f 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -1143,7 +1143,7 @@ made_compressed_probe: acm = kzalloc(sizeof(struct acm), GFP_KERNEL); if (acm == NULL) { - dev_dbg(&intf->dev, "out of memory (acm kzalloc)\n"); + dev_err(&intf->dev, "out of memory (acm kzalloc)\n"); goto alloc_fail; } @@ -1179,19 +1179,19 @@ made_compressed_probe: buf = usb_alloc_coherent(usb_dev, ctrlsize, GFP_KERNEL, &acm->ctrl_dma); if (!buf) { - dev_dbg(&intf->dev, "out of memory (ctrl buffer alloc)\n"); + dev_err(&intf->dev, "out of memory (ctrl buffer alloc)\n"); goto alloc_fail2; } acm->ctrl_buffer = buf; if (acm_write_buffers_alloc(acm) < 0) { - dev_dbg(&intf->dev, "out of memory (write buffer alloc)\n"); + dev_err(&intf->dev, "out of memory (write buffer alloc)\n"); goto alloc_fail4; } acm->ctrlurb = usb_alloc_urb(0, GFP_KERNEL); if (!acm->ctrlurb) { - dev_dbg(&intf->dev, "out of memory (ctrlurb kmalloc)\n"); + dev_err(&intf->dev, "out of memory (ctrlurb kmalloc)\n"); goto alloc_fail5; } for (i = 0; i < num_rx_buf; i++) { @@ -1199,7 +1199,7 @@ made_compressed_probe: rcv->urb = usb_alloc_urb(0, GFP_KERNEL); if (rcv->urb == NULL) { - dev_dbg(&intf->dev, + dev_err(&intf->dev, "out of memory (read urbs usb_alloc_urb)\n"); goto alloc_fail6; } @@ -1213,7 +1213,7 @@ made_compressed_probe: rb->base = usb_alloc_coherent(acm->dev, readsize, GFP_KERNEL, &rb->dma); if (!rb->base) { - dev_dbg(&intf->dev, + dev_err(&intf->dev, "out of memory (read bufs usb_alloc_coherent)\n"); goto alloc_fail7; } @@ -1223,7 +1223,7 @@ made_compressed_probe: snd->urb = usb_alloc_urb(0, GFP_KERNEL); if (snd->urb == NULL) { - dev_dbg(&intf->dev, + dev_err(&intf->dev, "out of memory (write urbs usb_alloc_urb)\n"); goto alloc_fail8; } -- cgit v1.2.2 From 1d9846e505febb71255b098910ace741433312b7 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 22 Mar 2011 11:12:14 +0100 Subject: USB: cdc-acm: clean up dev_err and dev_dbg Clean up some dev_err and dev_dbg messages and make sure that the appropriate interface device is used for reporting consistently throughout. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-acm.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'drivers/usb/class/cdc-acm.c') diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index c9f8a837c5f..612b9ff0fcf 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -340,8 +340,8 @@ static void acm_ctrl_irq(struct urb *urb) exit: retval = usb_submit_urb(urb, GFP_ATOMIC); if (retval) - dev_err(&urb->dev->dev, "%s - usb_submit_urb failed with " - "result %d\n", __func__, retval); + dev_err(&acm->control->dev, "%s - usb_submit_urb failed: %d\n", + __func__, retval); } /* data interface returns incoming bytes, or we got unthrottled */ @@ -355,13 +355,14 @@ static void acm_read_bulk(struct urb *urb) dbg("Entering acm_read_bulk with status %d", status); if (!ACM_READY(acm)) { - dev_dbg(&acm->data->dev, "Aborting, acm not ready\n"); + dev_dbg(&acm->data->dev, "%s - acm not ready\n", __func__); return; } usb_mark_last_busy(acm->dev); if (status) - dev_dbg(&acm->data->dev, "bulk rx status %d\n", status); + dev_dbg(&acm->data->dev, "%s - non-zero urb status: %d\n", + __func__, status); buf = rcv->buffer; buf->size = urb->actual_length; @@ -511,7 +512,8 @@ static void acm_write_bulk(struct urb *urb) if (verbose || urb->status || (urb->actual_length != urb->transfer_buffer_length)) - dev_dbg(&acm->data->dev, "tx %d/%d bytes -- > %d\n", + dev_dbg(&acm->data->dev, "%s - len %d/%d, status %d\n", + __func__, urb->actual_length, urb->transfer_buffer_length, urb->status); @@ -530,7 +532,8 @@ static void acm_softint(struct work_struct *work) struct acm *acm = container_of(work, struct acm, work); struct tty_struct *tty; - dev_vdbg(&acm->data->dev, "tx work\n"); + dev_vdbg(&acm->data->dev, "%s\n", __func__); + if (!ACM_READY(acm)) return; tty = tty_port_tty_get(&acm->port); -- cgit v1.2.2 From a5cc7ef92f69a88a1984cc3e09f6c19656efeb2e Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 22 Mar 2011 11:12:15 +0100 Subject: USB: cdc-acm: replace dbg macros with dev_dbg Replace all remaining instances of dbg with dev_dbg. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-acm.c | 80 +++++++++++++++++++++++++++++---------------- 1 file changed, 52 insertions(+), 28 deletions(-) (limited to 'drivers/usb/class/cdc-acm.c') diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 612b9ff0fcf..fee7d8b94fe 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -111,8 +111,9 @@ static int acm_ctrl_msg(struct acm *acm, int request, int value, request, USB_RT_ACM, value, acm->control->altsetting[0].desc.bInterfaceNumber, buf, len, 5000); - dbg("acm_control_msg: rq: 0x%02x val: %#x len: %#x result: %d", - request, value, len, retval); + dev_dbg(&acm->control->dev, + "%s - rq 0x%02x, val %#x, len %#x, result %d\n", + __func__, request, value, len, retval); return retval < 0 ? retval : 0; } @@ -192,7 +193,9 @@ static int acm_start_wb(struct acm *acm, struct acm_wb *wb) rc = usb_submit_urb(wb->urb, GFP_ATOMIC); if (rc < 0) { - dbg("usb_submit_urb(write bulk) failed: %d", rc); + dev_err(&acm->data->dev, + "%s - usb_submit_urb(write bulk) failed: %d\n", + __func__, rc); acm_write_done(acm, wb); } return rc; @@ -211,7 +214,8 @@ static int acm_write_start(struct acm *acm, int wbn) return -ENODEV; } - dbg("%s susp_count: %d", __func__, acm->susp_count); + dev_dbg(&acm->data->dev, "%s - susp_count %d\n", __func__, + acm->susp_count); usb_autopm_get_interface_async(acm->control); if (acm->susp_count) { if (!acm->delayed_wb) @@ -287,10 +291,14 @@ static void acm_ctrl_irq(struct urb *urb) case -ENOENT: case -ESHUTDOWN: /* this urb is terminated, clean up */ - dbg("%s - urb shutting down with status: %d", __func__, status); + dev_dbg(&acm->control->dev, + "%s - urb shutting down with status: %d\n", + __func__, status); return; default: - dbg("%s - nonzero urb status received: %d", __func__, status); + dev_dbg(&acm->control->dev, + "%s - nonzero urb status received: %d\n", + __func__, status); goto exit; } @@ -302,8 +310,8 @@ static void acm_ctrl_irq(struct urb *urb) data = (unsigned char *)(dr + 1); switch (dr->bNotificationType) { case USB_CDC_NOTIFY_NETWORK_CONNECTION: - dbg("%s network", dr->wValue ? - "connected to" : "disconnected from"); + dev_dbg(&acm->control->dev, "%s - network connection: %d\n", + __func__, dr->wValue); break; case USB_CDC_NOTIFY_SERIAL_STATE: @@ -313,7 +321,8 @@ static void acm_ctrl_irq(struct urb *urb) if (tty) { if (!acm->clocal && (acm->ctrlin & ~newctrl & ACM_CTRL_DCD)) { - dbg("calling hangup"); + dev_dbg(&acm->control->dev, + "%s - calling hangup\n", __func__); tty_hangup(tty); } tty_kref_put(tty); @@ -321,7 +330,10 @@ static void acm_ctrl_irq(struct urb *urb) acm->ctrlin = newctrl; - dbg("input control lines: dcd%c dsr%c break%c ring%c framing%c parity%c overrun%c", + dev_dbg(&acm->control->dev, + "%s - input control lines: dcd%c dsr%c break%c " + "ring%c framing%c parity%c overrun%c\n", + __func__, acm->ctrlin & ACM_CTRL_DCD ? '+' : '-', acm->ctrlin & ACM_CTRL_DSR ? '+' : '-', acm->ctrlin & ACM_CTRL_BRK ? '+' : '-', @@ -332,7 +344,10 @@ static void acm_ctrl_irq(struct urb *urb) break; default: - dbg("unknown notification %d received: index %d len %d data0 %d data1 %d", + dev_dbg(&acm->control->dev, + "%s - unknown notification %d received: index %d " + "len %d data0 %d data1 %d\n", + __func__, dr->bNotificationType, dr->wIndex, dr->wLength, data[0], data[1]); break; @@ -352,7 +367,7 @@ static void acm_read_bulk(struct urb *urb) struct acm *acm = rcv->instance; int status = urb->status; - dbg("Entering acm_read_bulk with status %d", status); + dev_dbg(&acm->data->dev, "%s - status %d\n", __func__, status); if (!ACM_READY(acm)) { dev_dbg(&acm->data->dev, "%s - acm not ready\n", __func__); @@ -395,10 +410,10 @@ static void acm_rx_tasklet(unsigned long _acm) unsigned long flags; unsigned char throttled; - dbg("Entering acm_rx_tasklet"); + dev_dbg(&acm->data->dev, "%s\n", __func__); if (!ACM_READY(acm)) { - dbg("acm_rx_tasklet: ACM not ready"); + dev_dbg(&acm->data->dev, "%s - acm not ready\n", __func__); return; } @@ -406,7 +421,7 @@ static void acm_rx_tasklet(unsigned long _acm) throttled = acm->throttle; spin_unlock_irqrestore(&acm->throttle_lock, flags); if (throttled) { - dbg("acm_rx_tasklet: throttled"); + dev_dbg(&acm->data->dev, "%s - throttled\n", __func__); return; } @@ -423,8 +438,8 @@ next_buffer: list_del(&buf->list); spin_unlock_irqrestore(&acm->read_lock, flags); - dbg("acm_rx_tasklet: procesing buf 0x%p, size = %d", buf, buf->size); - + dev_dbg(&acm->data->dev, "%s - processing buf 0x%p, size = %d\n", + __func__, buf, buf->size); if (tty) { spin_lock_irqsave(&acm->throttle_lock, flags); throttled = acm->throttle; @@ -434,7 +449,8 @@ next_buffer: tty_flip_buffer_push(tty); } else { tty_kref_put(tty); - dbg("Throttling noticed"); + dev_dbg(&acm->data->dev, "%s - throttling noticed\n", + __func__); spin_lock_irqsave(&acm->read_lock, flags); list_add(&buf->list, &acm->filled_read_bufs); spin_unlock_irqrestore(&acm->read_lock, flags); @@ -495,7 +511,9 @@ urbs: return; } else { spin_unlock_irqrestore(&acm->read_lock, flags); - dbg("acm_rx_tasklet: sending urb 0x%p, rcv 0x%p, buf 0x%p", rcv->urb, rcv, buf); + dev_dbg(&acm->data->dev, + "%s - sending urb 0x%p, rcv 0x%p, buf 0x%p\n", + __func__, rcv->urb, rcv, buf); } } spin_lock_irqsave(&acm->read_lock, flags); @@ -552,7 +570,6 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp) struct acm *acm; int rv = -ENODEV; int i; - dbg("Entering acm_tty_open."); mutex_lock(&open_mutex); @@ -562,6 +579,8 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp) else rv = 0; + dev_dbg(&acm->control->dev, "%s\n", __func__); + set_bit(TTY_NO_WRITE_SPLIT, &tty->flags); tty->driver_data = acm; @@ -581,7 +600,8 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp) acm->ctrlurb->dev = acm->dev; if (usb_submit_urb(acm->ctrlurb, GFP_KERNEL)) { - dbg("usb_submit_urb(ctrl irq) failed"); + dev_err(&acm->control->dev, + "%s - usb_submit_urb(ctrl irq) failed\n", __func__); goto bail_out; } @@ -701,13 +721,13 @@ static int acm_tty_write(struct tty_struct *tty, int wbn; struct acm_wb *wb; - dbg("Entering acm_tty_write to write %d bytes,", count); - if (!ACM_READY(acm)) return -EINVAL; if (!count) return 0; + dev_dbg(&acm->data->dev, "%s - count %d\n", __func__, count); + spin_lock_irqsave(&acm->write_lock, flags); wbn = acm_wb_alloc(acm); if (wbn < 0) { @@ -717,7 +737,7 @@ static int acm_tty_write(struct tty_struct *tty, wb = &acm->wb[wbn]; count = (count > acm->writesize) ? acm->writesize : count; - dbg("Get %d bytes...", count); + dev_dbg(&acm->data->dev, "%s - write %d\n", __func__, count); memcpy(wb->buf, buf, count); wb->len = count; spin_unlock_irqrestore(&acm->write_lock, flags); @@ -780,7 +800,8 @@ static int acm_tty_break_ctl(struct tty_struct *tty, int state) return -EINVAL; retval = acm_send_break(acm, state ? 0xffff : 0); if (retval < 0) - dbg("send break failed"); + dev_dbg(&acm->control->dev, "%s - send break failed\n", + __func__); return retval; } @@ -875,7 +896,9 @@ static void acm_tty_set_termios(struct tty_struct *tty, if (memcmp(&acm->line, &newline, sizeof newline)) { memcpy(&acm->line, &newline, sizeof newline); - dbg("set line: %d %d %d %d", le32_to_cpu(newline.dwDTERate), + dev_dbg(&acm->control->dev, "%s - set line: %d %d %d %d\n", + __func__, + le32_to_cpu(newline.dwDTERate), newline.bCharFormat, newline.bParityType, newline.bDataBits); acm_set_line(acm, &acm->line); @@ -1136,7 +1159,7 @@ skip_normal_probe: epwrite = t; } made_compressed_probe: - dbg("interfaces are valid"); + dev_dbg(&intf->dev, "interfaces are valid\n"); for (minor = 0; minor < ACM_TTY_MINORS && acm_table[minor]; minor++); if (minor == ACM_TTY_MINORS) { @@ -1321,7 +1344,8 @@ alloc_fail: static void stop_data_traffic(struct acm *acm) { int i; - dbg("Entering stop_data_traffic"); + + dev_dbg(&acm->control->dev, "%s\n", __func__); tasklet_disable(&acm->urb_task); -- cgit v1.2.2 From 4fa4626cd43679dc62a73ee3e347665e761abc9c Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 22 Mar 2011 11:12:16 +0100 Subject: USB: cdc-acm: clean up verbose debug Clean up use of verbose debug. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-acm.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) (limited to 'drivers/usb/class/cdc-acm.c') diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index fee7d8b94fe..44a5291c569 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -94,12 +94,6 @@ static DEFINE_MUTEX(open_mutex); static const struct tty_port_operations acm_port_ops = { }; -#ifdef VERBOSE_DEBUG -#define verbose 1 -#else -#define verbose 0 -#endif - /* * Functions for ACM control messages. */ @@ -528,9 +522,8 @@ static void acm_write_bulk(struct urb *urb) struct acm *acm = wb->instance; unsigned long flags; - if (verbose || urb->status - || (urb->actual_length != urb->transfer_buffer_length)) - dev_dbg(&acm->data->dev, "%s - len %d/%d, status %d\n", + if (urb->status || (urb->actual_length != urb->transfer_buffer_length)) + dev_vdbg(&acm->data->dev, "%s - len %d/%d, status %d\n", __func__, urb->actual_length, urb->transfer_buffer_length, -- cgit v1.2.2 From 5e9e75f8bd97864d552ec2b8d1a00e2b3012a6b3 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 22 Mar 2011 11:12:17 +0100 Subject: USB: cdc-acm: use dev_vdbg in read/write paths Replace dev_dbg with verbose dev_vdbg in read/write paths where appropriate. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-acm.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers/usb/class/cdc-acm.c') diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 44a5291c569..3c0d4b913a8 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -208,7 +208,7 @@ static int acm_write_start(struct acm *acm, int wbn) return -ENODEV; } - dev_dbg(&acm->data->dev, "%s - susp_count %d\n", __func__, + dev_vdbg(&acm->data->dev, "%s - susp_count %d\n", __func__, acm->susp_count); usb_autopm_get_interface_async(acm->control); if (acm->susp_count) { @@ -361,7 +361,7 @@ static void acm_read_bulk(struct urb *urb) struct acm *acm = rcv->instance; int status = urb->status; - dev_dbg(&acm->data->dev, "%s - status %d\n", __func__, status); + dev_vdbg(&acm->data->dev, "%s - status %d\n", __func__, status); if (!ACM_READY(acm)) { dev_dbg(&acm->data->dev, "%s - acm not ready\n", __func__); @@ -404,7 +404,7 @@ static void acm_rx_tasklet(unsigned long _acm) unsigned long flags; unsigned char throttled; - dev_dbg(&acm->data->dev, "%s\n", __func__); + dev_vdbg(&acm->data->dev, "%s\n", __func__); if (!ACM_READY(acm)) { dev_dbg(&acm->data->dev, "%s - acm not ready\n", __func__); @@ -432,7 +432,7 @@ next_buffer: list_del(&buf->list); spin_unlock_irqrestore(&acm->read_lock, flags); - dev_dbg(&acm->data->dev, "%s - processing buf 0x%p, size = %d\n", + dev_vdbg(&acm->data->dev, "%s - processing buf 0x%p, size = %d\n", __func__, buf, buf->size); if (tty) { spin_lock_irqsave(&acm->throttle_lock, flags); @@ -505,7 +505,7 @@ urbs: return; } else { spin_unlock_irqrestore(&acm->read_lock, flags); - dev_dbg(&acm->data->dev, + dev_vdbg(&acm->data->dev, "%s - sending urb 0x%p, rcv 0x%p, buf 0x%p\n", __func__, rcv->urb, rcv, buf); } @@ -719,7 +719,7 @@ static int acm_tty_write(struct tty_struct *tty, if (!count) return 0; - dev_dbg(&acm->data->dev, "%s - count %d\n", __func__, count); + dev_vdbg(&acm->data->dev, "%s - count %d\n", __func__, count); spin_lock_irqsave(&acm->write_lock, flags); wbn = acm_wb_alloc(acm); @@ -730,7 +730,7 @@ static int acm_tty_write(struct tty_struct *tty, wb = &acm->wb[wbn]; count = (count > acm->writesize) ? acm->writesize : count; - dev_dbg(&acm->data->dev, "%s - write %d\n", __func__, count); + dev_vdbg(&acm->data->dev, "%s - write %d\n", __func__, count); memcpy(wb->buf, buf, count); wb->len = count; spin_unlock_irqrestore(&acm->write_lock, flags); -- cgit v1.2.2 From a2c7b9353e8f782590852052fe2948692020147e Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 22 Mar 2011 11:12:18 +0100 Subject: USB: cdc-acm: remove version information and changelog Remove driver version and changelog which can be retrieved from git history. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-acm.c | 32 ++------------------------------ 1 file changed, 2 insertions(+), 30 deletions(-) (limited to 'drivers/usb/class/cdc-acm.c') diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 3c0d4b913a8..a693381ed3c 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -12,30 +12,6 @@ * * Sponsored by SuSE * - * ChangeLog: - * v0.9 - thorough cleaning, URBification, almost a rewrite - * v0.10 - some more cleanups - * v0.11 - fixed flow control, read error doesn't stop reads - * v0.12 - added TIOCM ioctls, added break handling, made struct acm - * kmalloced - * v0.13 - added termios, added hangup - * v0.14 - sized down struct acm - * v0.15 - fixed flow control again - characters could be lost - * v0.16 - added code for modems with swapped data and control interfaces - * v0.17 - added new style probing - * v0.18 - fixed new style probing for devices with more configurations - * v0.19 - fixed CLOCAL handling (thanks to Richard Shih-Ping Chan) - * v0.20 - switched to probing on interface (rather than device) class - * v0.21 - revert to probing on device for devices with multiple configs - * v0.22 - probe only the control interface. if usbcore doesn't choose the - * config we want, sysadmin changes bConfigurationValue in sysfs. - * v0.23 - use softirq for rx processing, as needed by tty layer - * v0.24 - change probe method to evaluate CDC union descriptor - * v0.25 - downstream tasks paralelized to maximize throughput - * v0.26 - multiple write urbs, writesize increased - */ - -/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or @@ -76,10 +52,7 @@ #define ACM_CLOSE_TIMEOUT 15 /* seconds to let writes drain */ -/* - * Version Information - */ -#define DRIVER_VERSION "v0.26" + #define DRIVER_AUTHOR "Armin Fuerst, Pavel Machek, Johannes Erdfelt, Vojtech Pavlik, David Kubicek" #define DRIVER_DESC "USB Abstract Control Model driver for USB modems and ISDN adapters" @@ -1736,8 +1709,7 @@ static int __init acm_init(void) return retval; } - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC "\n"); return 0; } -- cgit v1.2.2 From 3a42610812c55e8a60e2660e01c6cb6eb01d4171 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 22 Mar 2011 11:12:19 +0100 Subject: USB: cdc-acm: remove superfluous prototype Remove unnecessary acm_tty_chars_in_buffer prototype. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-acm.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/usb/class/cdc-acm.c') diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index a693381ed3c..b84ccec8fc7 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -626,8 +626,6 @@ static void acm_tty_unregister(struct acm *acm) kfree(acm); } -static int acm_tty_chars_in_buffer(struct tty_struct *tty); - static void acm_port_down(struct acm *acm) { int i, nr = acm->rx_buflimit; -- cgit v1.2.2 From 6fb6b8846458afb7b5689f86cf35705c40eb70e5 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 22 Mar 2011 11:12:20 +0100 Subject: USB: cdc-acm: remove unused drain-delay code The drain-delay code is no longer used, so remove it. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-acm.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers/usb/class/cdc-acm.c') diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index b84ccec8fc7..e0f9febee7e 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -50,9 +50,6 @@ #include "cdc-acm.h" -#define ACM_CLOSE_TIMEOUT 15 /* seconds to let writes drain */ - - #define DRIVER_AUTHOR "Armin Fuerst, Pavel Machek, Johannes Erdfelt, Vojtech Pavlik, David Kubicek" #define DRIVER_DESC "USB Abstract Control Model driver for USB modems and ISDN adapters" @@ -507,8 +504,6 @@ static void acm_write_bulk(struct urb *urb) spin_unlock_irqrestore(&acm->write_lock, flags); if (ACM_READY(acm)) schedule_work(&acm->work); - else - wake_up_interruptible(&acm->drain_wait); } static void acm_softint(struct work_struct *work) @@ -1155,7 +1150,6 @@ made_compressed_probe: acm->urb_task.func = acm_rx_tasklet; acm->urb_task.data = (unsigned long) acm; INIT_WORK(&acm->work, acm_softint); - init_waitqueue_head(&acm->drain_wait); spin_lock_init(&acm->throttle_lock); spin_lock_init(&acm->write_lock); spin_lock_init(&acm->read_lock); -- cgit v1.2.2 From dab54c9f1e26f47a3313300bc1f4dc0eecb47375 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 22 Mar 2011 11:12:21 +0100 Subject: USB: cdc-acm: clean up rx_buflimit references Clean up references to rx_buflimit. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-acm.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers/usb/class/cdc-acm.c') diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index e0f9febee7e..2d8d6b83823 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -606,16 +606,15 @@ early_bail: static void acm_tty_unregister(struct acm *acm) { - int i, nr; + int i; - nr = acm->rx_buflimit; tty_unregister_device(acm_tty_driver, acm->minor); usb_put_intf(acm->control); acm_table[acm->minor] = NULL; usb_free_urb(acm->ctrlurb); for (i = 0; i < ACM_NW; i++) usb_free_urb(acm->wb[i].urb); - for (i = 0; i < nr; i++) + for (i = 0; i < acm->rx_buflimit; i++) usb_free_urb(acm->ru[i].urb); kfree(acm->country_codes); kfree(acm); @@ -623,7 +622,8 @@ static void acm_tty_unregister(struct acm *acm) static void acm_port_down(struct acm *acm) { - int i, nr = acm->rx_buflimit; + int i; + mutex_lock(&open_mutex); if (acm->dev) { usb_autopm_get_interface(acm->control); @@ -632,7 +632,7 @@ static void acm_port_down(struct acm *acm) for (i = 0; i < ACM_NW; i++) usb_kill_urb(acm->wb[i].urb); tasklet_disable(&acm->urb_task); - for (i = 0; i < nr; i++) + for (i = 0; i < acm->rx_buflimit; i++) usb_kill_urb(acm->ru[i].urb); tasklet_enable(&acm->urb_task); acm->control->needs_remote_wakeup = 0; @@ -882,9 +882,9 @@ static void acm_write_buffers_free(struct acm *acm) static void acm_read_buffers_free(struct acm *acm) { struct usb_device *usb_dev = interface_to_usbdev(acm->control); - int i, n = acm->rx_buflimit; + int i; - for (i = 0; i < n; i++) + for (i = 0; i < acm->rx_buflimit; i++) usb_free_coherent(usb_dev, acm->readsize, acm->rb[i].base, acm->rb[i].dma); } -- cgit v1.2.2 From 94d4c8919de3ae9e2e029ed121adfed43803bb5d Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 22 Mar 2011 11:12:22 +0100 Subject: USB: cdc-acm: clean up open error handling No need to kill ctrl urb on errors as this is done later during close. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-acm.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers/usb/class/cdc-acm.c') diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 2d8d6b83823..f239e3bd642 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -568,7 +568,7 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp) if (0 > acm_set_control(acm, acm->ctrlout = ACM_CTRL_DTR | ACM_CTRL_RTS) && (acm->ctrl_caps & USB_CDC_CAP_LINE)) - goto full_bailout; + goto bail_out; usb_autopm_put_interface(acm->control); @@ -592,8 +592,6 @@ out: mutex_unlock(&open_mutex); return rv; -full_bailout: - usb_kill_urb(acm->ctrlurb); bail_out: acm->port.count--; mutex_unlock(&acm->mutex); -- cgit v1.2.2 From 74f5e1babde76149c2bb35ca5dbf4d0b9b38f161 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 22 Mar 2011 11:12:23 +0100 Subject: USB: cdc-acm: clean up read urb allocation Allocate read urbs and read buffers in the same loop during probe. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-acm.c | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) (limited to 'drivers/usb/class/cdc-acm.c') diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index f239e3bd642..519c7b93350 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -1177,8 +1177,17 @@ made_compressed_probe: goto alloc_fail5; } for (i = 0; i < num_rx_buf; i++) { + struct acm_rb *rb = &(acm->rb[i]); struct acm_ru *rcv = &(acm->ru[i]); + rb->base = usb_alloc_coherent(acm->dev, readsize, GFP_KERNEL, + &rb->dma); + if (!rb->base) { + dev_err(&intf->dev, "out of memory " + "(read bufs usb_alloc_coherent)\n"); + goto alloc_fail6; + } + rcv->urb = usb_alloc_urb(0, GFP_KERNEL); if (rcv->urb == NULL) { dev_err(&intf->dev, @@ -1189,17 +1198,6 @@ made_compressed_probe: rcv->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; rcv->instance = acm; } - for (i = 0; i < num_rx_buf; i++) { - struct acm_rb *rb = &(acm->rb[i]); - - rb->base = usb_alloc_coherent(acm->dev, readsize, - GFP_KERNEL, &rb->dma); - if (!rb->base) { - dev_err(&intf->dev, - "out of memory (read bufs usb_alloc_coherent)\n"); - goto alloc_fail7; - } - } for (i = 0; i < ACM_NW; i++) { struct acm_wb *snd = &(acm->wb[i]); @@ -1207,7 +1205,7 @@ made_compressed_probe: if (snd->urb == NULL) { dev_err(&intf->dev, "out of memory (write urbs usb_alloc_urb)\n"); - goto alloc_fail8; + goto alloc_fail7; } if (usb_endpoint_xfer_int(epwrite)) @@ -1226,7 +1224,7 @@ made_compressed_probe: i = device_create_file(&intf->dev, &dev_attr_bmCapabilities); if (i < 0) - goto alloc_fail8; + goto alloc_fail7; if (cfd) { /* export the country data */ acm->country_codes = kmalloc(cfd->bLength - 4, GFP_KERNEL); @@ -1278,14 +1276,13 @@ skip_countries: acm_table[minor] = acm; return 0; -alloc_fail8: +alloc_fail7: for (i = 0; i < ACM_NW; i++) usb_free_urb(acm->wb[i].urb); -alloc_fail7: - acm_read_buffers_free(acm); alloc_fail6: for (i = 0; i < num_rx_buf; i++) usb_free_urb(acm->ru[i].urb); + acm_read_buffers_free(acm); usb_free_urb(acm->ctrlurb); alloc_fail5: acm_write_buffers_free(acm); -- cgit v1.2.2 From 088c64f812847b3623b03d167ed329f90f3e38a4 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Fri, 25 Mar 2011 11:06:02 +0100 Subject: USB: cdc-acm: re-write read processing Kill rx tasklet, which is no longer needed, and re-write read processing. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-acm.c | 295 +++++++++++++++++--------------------------- 1 file changed, 114 insertions(+), 181 deletions(-) (limited to 'drivers/usb/class/cdc-acm.c') diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 519c7b93350..58754b508a0 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -7,6 +7,7 @@ * Copyright (c) 2000 Vojtech Pavlik * Copyright (c) 2004 Oliver Neukum * Copyright (c) 2005 David Kubicek + * Copyright (c) 2011 Johan Hovold * * USB Abstract Control Model driver for USB modems and ISDN adapters * @@ -50,7 +51,7 @@ #include "cdc-acm.h" -#define DRIVER_AUTHOR "Armin Fuerst, Pavel Machek, Johannes Erdfelt, Vojtech Pavlik, David Kubicek" +#define DRIVER_AUTHOR "Armin Fuerst, Pavel Machek, Johannes Erdfelt, Vojtech Pavlik, David Kubicek, Johan Hovold" #define DRIVER_DESC "USB Abstract Control Model driver for USB modems and ISDN adapters" static struct usb_driver acm_driver; @@ -323,166 +324,92 @@ exit: __func__, retval); } -/* data interface returns incoming bytes, or we got unthrottled */ -static void acm_read_bulk(struct urb *urb) +static int acm_submit_read_urb(struct acm *acm, int index, gfp_t mem_flags) { - struct acm_rb *buf; - struct acm_ru *rcv = urb->context; - struct acm *acm = rcv->instance; - int status = urb->status; + int res; - dev_vdbg(&acm->data->dev, "%s - status %d\n", __func__, status); + if (!test_and_clear_bit(index, &acm->read_urbs_free)) + return 0; - if (!ACM_READY(acm)) { - dev_dbg(&acm->data->dev, "%s - acm not ready\n", __func__); - return; + dev_vdbg(&acm->data->dev, "%s - urb %d\n", __func__, index); + + res = usb_submit_urb(acm->read_urbs[index], mem_flags); + if (res) { + if (res != -EPERM) { + dev_err(&acm->data->dev, + "%s - usb_submit_urb failed: %d\n", + __func__, res); + } + set_bit(index, &acm->read_urbs_free); + return res; } - usb_mark_last_busy(acm->dev); - if (status) - dev_dbg(&acm->data->dev, "%s - non-zero urb status: %d\n", - __func__, status); + return 0; +} - buf = rcv->buffer; - buf->size = urb->actual_length; +static int acm_submit_read_urbs(struct acm *acm, gfp_t mem_flags) +{ + int res; + int i; - if (likely(status == 0)) { - spin_lock(&acm->read_lock); - acm->processing++; - list_add_tail(&rcv->list, &acm->spare_read_urbs); - list_add_tail(&buf->list, &acm->filled_read_bufs); - spin_unlock(&acm->read_lock); - } else { - /* we drop the buffer due to an error */ - spin_lock(&acm->read_lock); - list_add_tail(&rcv->list, &acm->spare_read_urbs); - list_add(&buf->list, &acm->spare_read_bufs); - spin_unlock(&acm->read_lock); - /* nevertheless the tasklet must be kicked unconditionally - so the queue cannot dry up */ + for (i = 0; i < acm->rx_buflimit; ++i) { + res = acm_submit_read_urb(acm, i, mem_flags); + if (res) + return res; } - if (likely(!acm->susp_count)) - tasklet_schedule(&acm->urb_task); + + return 0; } -static void acm_rx_tasklet(unsigned long _acm) +static void acm_process_read_urb(struct acm *acm, struct urb *urb) { - struct acm *acm = (void *)_acm; - struct acm_rb *buf; struct tty_struct *tty; - struct acm_ru *rcv; - unsigned long flags; - unsigned char throttled; - - dev_vdbg(&acm->data->dev, "%s\n", __func__); - if (!ACM_READY(acm)) { - dev_dbg(&acm->data->dev, "%s - acm not ready\n", __func__); + if (!urb->actual_length) return; - } - - spin_lock_irqsave(&acm->throttle_lock, flags); - throttled = acm->throttle; - spin_unlock_irqrestore(&acm->throttle_lock, flags); - if (throttled) { - dev_dbg(&acm->data->dev, "%s - throttled\n", __func__); - return; - } tty = tty_port_tty_get(&acm->port); + if (!tty) + return; -next_buffer: - spin_lock_irqsave(&acm->read_lock, flags); - if (list_empty(&acm->filled_read_bufs)) { - spin_unlock_irqrestore(&acm->read_lock, flags); - goto urbs; - } - buf = list_entry(acm->filled_read_bufs.next, - struct acm_rb, list); - list_del(&buf->list); - spin_unlock_irqrestore(&acm->read_lock, flags); - - dev_vdbg(&acm->data->dev, "%s - processing buf 0x%p, size = %d\n", - __func__, buf, buf->size); - if (tty) { - spin_lock_irqsave(&acm->throttle_lock, flags); - throttled = acm->throttle; - spin_unlock_irqrestore(&acm->throttle_lock, flags); - if (!throttled) { - tty_insert_flip_string(tty, buf->base, buf->size); - tty_flip_buffer_push(tty); - } else { - tty_kref_put(tty); - dev_dbg(&acm->data->dev, "%s - throttling noticed\n", - __func__); - spin_lock_irqsave(&acm->read_lock, flags); - list_add(&buf->list, &acm->filled_read_bufs); - spin_unlock_irqrestore(&acm->read_lock, flags); - return; - } - } - - spin_lock_irqsave(&acm->read_lock, flags); - list_add(&buf->list, &acm->spare_read_bufs); - spin_unlock_irqrestore(&acm->read_lock, flags); - goto next_buffer; + tty_insert_flip_string(tty, urb->transfer_buffer, urb->actual_length); + tty_flip_buffer_push(tty); -urbs: tty_kref_put(tty); +} - while (!list_empty(&acm->spare_read_bufs)) { - spin_lock_irqsave(&acm->read_lock, flags); - if (list_empty(&acm->spare_read_urbs)) { - acm->processing = 0; - spin_unlock_irqrestore(&acm->read_lock, flags); - return; - } - rcv = list_entry(acm->spare_read_urbs.next, - struct acm_ru, list); - list_del(&rcv->list); - spin_unlock_irqrestore(&acm->read_lock, flags); +static void acm_read_bulk_callback(struct urb *urb) +{ + struct acm_rb *rb = urb->context; + struct acm *acm = rb->instance; + unsigned long flags; - buf = list_entry(acm->spare_read_bufs.next, - struct acm_rb, list); - list_del(&buf->list); + dev_vdbg(&acm->data->dev, "%s - urb %d, len %d\n", __func__, + rb->index, urb->actual_length); + set_bit(rb->index, &acm->read_urbs_free); - rcv->buffer = buf; + if (!acm->dev) { + dev_dbg(&acm->data->dev, "%s - disconnected\n", __func__); + return; + } + usb_mark_last_busy(acm->dev); - if (acm->is_int_ep) - usb_fill_int_urb(rcv->urb, acm->dev, - acm->rx_endpoint, - buf->base, - acm->readsize, - acm_read_bulk, rcv, acm->bInterval); - else - usb_fill_bulk_urb(rcv->urb, acm->dev, - acm->rx_endpoint, - buf->base, - acm->readsize, - acm_read_bulk, rcv); - rcv->urb->transfer_dma = buf->dma; - rcv->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - - /* This shouldn't kill the driver as unsuccessful URBs are - returned to the free-urbs-pool and resubmited ASAP */ - spin_lock_irqsave(&acm->read_lock, flags); - if (acm->susp_count || - usb_submit_urb(rcv->urb, GFP_ATOMIC) < 0) { - list_add(&buf->list, &acm->spare_read_bufs); - list_add(&rcv->list, &acm->spare_read_urbs); - acm->processing = 0; - spin_unlock_irqrestore(&acm->read_lock, flags); - return; - } else { - spin_unlock_irqrestore(&acm->read_lock, flags); - dev_vdbg(&acm->data->dev, - "%s - sending urb 0x%p, rcv 0x%p, buf 0x%p\n", - __func__, rcv->urb, rcv, buf); - } + if (urb->status) { + dev_dbg(&acm->data->dev, "%s - non-zero urb status: %d\n", + __func__, urb->status); + return; } + acm_process_read_urb(acm, urb); + + /* throttle device if requested by tty */ spin_lock_irqsave(&acm->read_lock, flags); - acm->processing = 0; - spin_unlock_irqrestore(&acm->read_lock, flags); + acm->throttled = acm->throttle_req; + if (!acm->throttled && !acm->susp_count) { + spin_unlock_irqrestore(&acm->read_lock, flags); + acm_submit_read_urb(acm, rb->index, GFP_ATOMIC); + } else { + spin_unlock_irqrestore(&acm->read_lock, flags); + } } /* data interface wrote those outgoing bytes */ @@ -530,7 +457,6 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp) { struct acm *acm; int rv = -ENODEV; - int i; mutex_lock(&open_mutex); @@ -572,20 +498,11 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp) usb_autopm_put_interface(acm->control); - INIT_LIST_HEAD(&acm->spare_read_urbs); - INIT_LIST_HEAD(&acm->spare_read_bufs); - INIT_LIST_HEAD(&acm->filled_read_bufs); - - for (i = 0; i < acm->rx_buflimit; i++) - list_add(&(acm->ru[i].list), &acm->spare_read_urbs); - for (i = 0; i < acm->rx_buflimit; i++) - list_add(&(acm->rb[i].list), &acm->spare_read_bufs); - - acm->throttle = 0; + if (acm_submit_read_urbs(acm, GFP_KERNEL)) + goto bail_out; set_bit(ASYNCB_INITIALIZED, &acm->port.flags); rv = tty_port_block_til_ready(&acm->port, tty, filp); - tasklet_schedule(&acm->urb_task); mutex_unlock(&acm->mutex); out: @@ -613,7 +530,7 @@ static void acm_tty_unregister(struct acm *acm) for (i = 0; i < ACM_NW; i++) usb_free_urb(acm->wb[i].urb); for (i = 0; i < acm->rx_buflimit; i++) - usb_free_urb(acm->ru[i].urb); + usb_free_urb(acm->read_urbs[i]); kfree(acm->country_codes); kfree(acm); } @@ -629,10 +546,8 @@ static void acm_port_down(struct acm *acm) usb_kill_urb(acm->ctrlurb); for (i = 0; i < ACM_NW; i++) usb_kill_urb(acm->wb[i].urb); - tasklet_disable(&acm->urb_task); for (i = 0; i < acm->rx_buflimit; i++) - usb_kill_urb(acm->ru[i].urb); - tasklet_enable(&acm->urb_task); + usb_kill_urb(acm->read_urbs[i]); acm->control->needs_remote_wakeup = 0; usb_autopm_put_interface(acm->control); } @@ -731,22 +646,31 @@ static int acm_tty_chars_in_buffer(struct tty_struct *tty) static void acm_tty_throttle(struct tty_struct *tty) { struct acm *acm = tty->driver_data; + if (!ACM_READY(acm)) return; - spin_lock_bh(&acm->throttle_lock); - acm->throttle = 1; - spin_unlock_bh(&acm->throttle_lock); + + spin_lock_irq(&acm->read_lock); + acm->throttle_req = 1; + spin_unlock_irq(&acm->read_lock); } static void acm_tty_unthrottle(struct tty_struct *tty) { struct acm *acm = tty->driver_data; + unsigned int was_throttled; + if (!ACM_READY(acm)) return; - spin_lock_bh(&acm->throttle_lock); - acm->throttle = 0; - spin_unlock_bh(&acm->throttle_lock); - tasklet_schedule(&acm->urb_task); + + spin_lock_irq(&acm->read_lock); + was_throttled = acm->throttled; + acm->throttled = 0; + acm->throttle_req = 0; + spin_unlock_irq(&acm->read_lock); + + if (was_throttled) + acm_submit_read_urbs(acm, GFP_KERNEL); } static int acm_tty_break_ctl(struct tty_struct *tty, int state) @@ -884,7 +808,7 @@ static void acm_read_buffers_free(struct acm *acm) for (i = 0; i < acm->rx_buflimit; i++) usb_free_coherent(usb_dev, acm->readsize, - acm->rb[i].base, acm->rb[i].dma); + acm->read_buffers[i].base, acm->read_buffers[i].dma); } /* Little helper: write buffers allocate */ @@ -1145,10 +1069,7 @@ made_compressed_probe: acm->ctrlsize = ctrlsize; acm->readsize = readsize; acm->rx_buflimit = num_rx_buf; - acm->urb_task.func = acm_rx_tasklet; - acm->urb_task.data = (unsigned long) acm; INIT_WORK(&acm->work, acm_softint); - spin_lock_init(&acm->throttle_lock); spin_lock_init(&acm->write_lock); spin_lock_init(&acm->read_lock); mutex_init(&acm->mutex); @@ -1177,8 +1098,8 @@ made_compressed_probe: goto alloc_fail5; } for (i = 0; i < num_rx_buf; i++) { - struct acm_rb *rb = &(acm->rb[i]); - struct acm_ru *rcv = &(acm->ru[i]); + struct acm_rb *rb = &(acm->read_buffers[i]); + struct urb *urb; rb->base = usb_alloc_coherent(acm->dev, readsize, GFP_KERNEL, &rb->dma); @@ -1187,16 +1108,34 @@ made_compressed_probe: "(read bufs usb_alloc_coherent)\n"); goto alloc_fail6; } + rb->index = i; + rb->instance = acm; - rcv->urb = usb_alloc_urb(0, GFP_KERNEL); - if (rcv->urb == NULL) { + urb = usb_alloc_urb(0, GFP_KERNEL); + if (!urb) { dev_err(&intf->dev, "out of memory (read urbs usb_alloc_urb)\n"); goto alloc_fail6; } + urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; + urb->transfer_dma = rb->dma; + if (acm->is_int_ep) { + usb_fill_int_urb(urb, acm->dev, + acm->rx_endpoint, + rb->base, + acm->readsize, + acm_read_bulk_callback, rb, + acm->bInterval); + } else { + usb_fill_bulk_urb(urb, acm->dev, + acm->rx_endpoint, + rb->base, + acm->readsize, + acm_read_bulk_callback, rb); + } - rcv->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - rcv->instance = acm; + acm->read_urbs[i] = urb; + __set_bit(i, &acm->read_urbs_free); } for (i = 0; i < ACM_NW; i++) { struct acm_wb *snd = &(acm->wb[i]); @@ -1281,7 +1220,7 @@ alloc_fail7: usb_free_urb(acm->wb[i].urb); alloc_fail6: for (i = 0; i < num_rx_buf; i++) - usb_free_urb(acm->ru[i].urb); + usb_free_urb(acm->read_urbs[i]); acm_read_buffers_free(acm); usb_free_urb(acm->ctrlurb); alloc_fail5: @@ -1300,15 +1239,11 @@ static void stop_data_traffic(struct acm *acm) dev_dbg(&acm->control->dev, "%s\n", __func__); - tasklet_disable(&acm->urb_task); - usb_kill_urb(acm->ctrlurb); for (i = 0; i < ACM_NW; i++) usb_kill_urb(acm->wb[i].urb); for (i = 0; i < acm->rx_buflimit; i++) - usb_kill_urb(acm->ru[i].urb); - - tasklet_enable(&acm->urb_task); + usb_kill_urb(acm->read_urbs[i]); cancel_work_sync(&acm->work); } @@ -1369,11 +1304,9 @@ static int acm_suspend(struct usb_interface *intf, pm_message_t message) if (message.event & PM_EVENT_AUTO) { int b; - spin_lock_irq(&acm->read_lock); - spin_lock(&acm->write_lock); - b = acm->processing + acm->transmitting; - spin_unlock(&acm->write_lock); - spin_unlock_irq(&acm->read_lock); + spin_lock_irq(&acm->write_lock); + b = acm->transmitting; + spin_unlock_irq(&acm->write_lock); if (b) return -EBUSY; } @@ -1435,7 +1368,7 @@ static int acm_resume(struct usb_interface *intf) if (rv < 0) goto err_out; - tasklet_schedule(&acm->urb_task); + rv = acm_submit_read_urbs(acm, GFP_NOIO); } err_out: -- cgit v1.2.2 From fd5054c169d29747a44b4e1419ff47f57ae82dbc Mon Sep 17 00:00:00 2001 From: Erik Slagter Date: Wed, 11 May 2011 12:06:55 +0200 Subject: USB: cdc_acm: Fix oops when Droids MuIn LCD is connected The Droids MuIn LCD operates like a serial remote terminal. Data received are displayed directly on the LCD. This patch fixes the kernel null pointer oops when it is plugged in. Add NO_DATA_INTERFACE quirk to tell the driver that "control" and "data" interfaces are not separated for this device, which prevents dereferencing a null pointer in the device probe code. Signed-off-by: Erik Slagter Signed-off-by: Maxin B. John Tested-by: Erik Slagter Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-acm.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'drivers/usb/class/cdc-acm.c') diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 58754b508a0..395a347f2eb 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -853,7 +853,7 @@ static int acm_probe(struct usb_interface *intf, u8 ac_management_function = 0; u8 call_management_function = 0; int call_interface_num = -1; - int data_interface_num; + int data_interface_num = -1; unsigned long quirks; int num_rx_buf; int i; @@ -937,7 +937,11 @@ next_desc: if (!union_header) { if (call_interface_num > 0) { dev_dbg(&intf->dev, "No union descriptor, using call management descriptor\n"); - data_interface = usb_ifnum_to_if(usb_dev, (data_interface_num = call_interface_num)); + /* quirks for Droids MuIn LCD */ + if (quirks & NO_DATA_INTERFACE) + data_interface = usb_ifnum_to_if(usb_dev, 0); + else + data_interface = usb_ifnum_to_if(usb_dev, (data_interface_num = call_interface_num)); control_interface = intf; } else { if (intf->cur_altsetting->desc.bNumEndpoints != 3) { @@ -1535,6 +1539,11 @@ static const struct usb_device_id acm_ids[] = { .driver_info = NOT_A_MODEM, }, + /* Support for Droids MuIn LCD */ + { USB_DEVICE(0x04d8, 0x000b), + .driver_info = NO_DATA_INTERFACE, + }, + /* control interfaces without any protocol set */ { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, USB_CDC_PROTO_NONE) }, -- cgit v1.2.2