Commit 884b600f63dc7c646f415a5d8f356df1f66ff6f2

Authored by Oliver Neukum
Committed by Greg Kroah-Hartman
1 parent d5926ae7a8

[PATCH] USB: fix acm trouble with terminals

This patch fixes lost LF when ACM device is used with getty/login/bash,
in case of a modem which takes calls.

Signed-off-by: Pete Zaitcev <zaitcev@redhat.com>
Signed-off-by: Oliver Neukum <oliver@neukum.name>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

Showing 2 changed files with 197 additions and 37 deletions Side-by-side Diff

drivers/usb/class/cdc-acm.c
... ... @@ -106,6 +106,111 @@
106 106 acm_ctrl_msg(acm, USB_CDC_REQ_SEND_BREAK, ms, NULL, 0)
107 107  
108 108 /*
  109 + * Write buffer management.
  110 + * All of these assume proper locks taken by the caller.
  111 + */
  112 +
  113 +static int acm_wb_alloc(struct acm *acm)
  114 +{
  115 + int i, wbn;
  116 + struct acm_wb *wb;
  117 +
  118 + wbn = acm->write_current;
  119 + i = 0;
  120 + for (;;) {
  121 + wb = &acm->wb[wbn];
  122 + if (!wb->use) {
  123 + wb->use = 1;
  124 + return wbn;
  125 + }
  126 + wbn = (wbn + 1) % ACM_NWB;
  127 + if (++i >= ACM_NWB)
  128 + return -1;
  129 + }
  130 +}
  131 +
  132 +static void acm_wb_free(struct acm *acm, int wbn)
  133 +{
  134 + acm->wb[wbn].use = 0;
  135 +}
  136 +
  137 +static int acm_wb_is_avail(struct acm *acm)
  138 +{
  139 + int i, n;
  140 +
  141 + n = 0;
  142 + for (i = 0; i < ACM_NWB; i++) {
  143 + if (!acm->wb[i].use)
  144 + n++;
  145 + }
  146 + return n;
  147 +}
  148 +
  149 +static inline int acm_wb_is_used(struct acm *acm, int wbn)
  150 +{
  151 + return acm->wb[wbn].use;
  152 +}
  153 +
  154 +/*
  155 + * Finish write.
  156 + */
  157 +static void acm_write_done(struct acm *acm)
  158 +{
  159 + unsigned long flags;
  160 + int wbn;
  161 +
  162 + spin_lock_irqsave(&acm->write_lock, flags);
  163 + acm->write_ready = 1;
  164 + wbn = acm->write_current;
  165 + acm_wb_free(acm, wbn);
  166 + acm->write_current = (wbn + 1) % ACM_NWB;
  167 + spin_unlock_irqrestore(&acm->write_lock, flags);
  168 +}
  169 +
  170 +/*
  171 + * Poke write.
  172 + */
  173 +static int acm_write_start(struct acm *acm)
  174 +{
  175 + unsigned long flags;
  176 + int wbn;
  177 + struct acm_wb *wb;
  178 + int rc;
  179 +
  180 + spin_lock_irqsave(&acm->write_lock, flags);
  181 + if (!acm->dev) {
  182 + spin_unlock_irqrestore(&acm->write_lock, flags);
  183 + return -ENODEV;
  184 + }
  185 +
  186 + if (!acm->write_ready) {
  187 + spin_unlock_irqrestore(&acm->write_lock, flags);
  188 + return 0; /* A white lie */
  189 + }
  190 +
  191 + wbn = acm->write_current;
  192 + if (!acm_wb_is_used(acm, wbn)) {
  193 + spin_unlock_irqrestore(&acm->write_lock, flags);
  194 + return 0;
  195 + }
  196 + wb = &acm->wb[wbn];
  197 +
  198 + acm->write_ready = 0;
  199 + spin_unlock_irqrestore(&acm->write_lock, flags);
  200 +
  201 + acm->writeurb->transfer_buffer = wb->buf;
  202 + acm->writeurb->transfer_dma = wb->dmah;
  203 + acm->writeurb->transfer_buffer_length = wb->len;
  204 + acm->writeurb->dev = acm->dev;
  205 +
  206 + if ((rc = usb_submit_urb(acm->writeurb, GFP_ATOMIC)) < 0) {
  207 + dbg("usb_submit_urb(write bulk) failed: %d", rc);
  208 + acm_write_done(acm);
  209 + }
  210 + return rc;
  211 +}
  212 +
  213 +/*
109 214 * Interrupt handlers for various ACM device responses
110 215 */
111 216  
112 217  
... ... @@ -237,17 +342,13 @@
237 342 static void acm_write_bulk(struct urb *urb, struct pt_regs *regs)
238 343 {
239 344 struct acm *acm = (struct acm *)urb->context;
  345 +
240 346 dbg("Entering acm_write_bulk with status %d\n", urb->status);
241 347  
242   - if (!ACM_READY(acm))
243   - goto out;
244   -
245   - if (urb->status)
246   - dbg("nonzero write bulk status received: %d", urb->status);
247   -
248   - schedule_work(&acm->work);
249   -out:
250   - acm->ready_for_write = 1;
  348 + acm_write_done(acm);
  349 + acm_write_start(acm);
  350 + if (ACM_READY(acm))
  351 + schedule_work(&acm->work);
251 352 }
252 353  
253 354 static void acm_softint(void *private)
254 355  
255 356  
256 357  
257 358  
258 359  
259 360  
... ... @@ -351,32 +452,33 @@
351 452 {
352 453 struct acm *acm = tty->driver_data;
353 454 int stat;
  455 + unsigned long flags;
  456 + int wbn;
  457 + struct acm_wb *wb;
  458 +
354 459 dbg("Entering acm_tty_write to write %d bytes,\n", count);
355 460  
356 461 if (!ACM_READY(acm))
357 462 return -EINVAL;
358   - if (!acm->ready_for_write)
359   - return 0;
360 463 if (!count)
361 464 return 0;
362 465  
363   - count = (count > acm->writesize) ? acm->writesize : count;
  466 + spin_lock_irqsave(&acm->write_lock, flags);
  467 + if ((wbn = acm_wb_alloc(acm)) < 0) {
  468 + spin_unlock_irqrestore(&acm->write_lock, flags);
  469 + acm_write_start(acm);
  470 + return 0;
  471 + }
  472 + wb = &acm->wb[wbn];
364 473  
  474 + count = (count > acm->writesize) ? acm->writesize : count;
365 475 dbg("Get %d bytes...", count);
366   - memcpy(acm->write_buffer, buf, count);
367   - dbg(" Successfully copied.\n");
  476 + memcpy(wb->buf, buf, count);
  477 + wb->len = count;
  478 + spin_unlock_irqrestore(&acm->write_lock, flags);
368 479  
369   - acm->writeurb->transfer_buffer_length = count;
370   - acm->writeurb->dev = acm->dev;
371   -
372   - acm->ready_for_write = 0;
373   - stat = usb_submit_urb(acm->writeurb, GFP_ATOMIC);
374   - if (stat < 0) {
375   - dbg("usb_submit_urb(write bulk) failed");
376   - acm->ready_for_write = 1;
  480 + if ((stat = acm_write_start(acm)) < 0)
377 481 return stat;
378   - }
379   -
380 482 return count;
381 483 }
382 484  
... ... @@ -385,7 +487,11 @@
385 487 struct acm *acm = tty->driver_data;
386 488 if (!ACM_READY(acm))
387 489 return -EINVAL;
388   - return !acm->ready_for_write ? 0 : acm->writesize;
  490 + /*
  491 + * Do not let the line discipline to know that we have a reserve,
  492 + * or it might get too enthusiastic.
  493 + */
  494 + return (acm->write_ready && acm_wb_is_avail(acm)) ? acm->writesize : 0;
389 495 }
390 496  
391 497 static int acm_tty_chars_in_buffer(struct tty_struct *tty)
... ... @@ -393,7 +499,10 @@
393 499 struct acm *acm = tty->driver_data;
394 500 if (!ACM_READY(acm))
395 501 return -EINVAL;
396   - return !acm->ready_for_write ? acm->writeurb->transfer_buffer_length : 0;
  502 + /*
  503 + * This is inaccurate (overcounts), but it works.
  504 + */
  505 + return (ACM_NWB - acm_wb_is_avail(acm)) * acm->writesize;
397 506 }
398 507  
399 508 static void acm_tty_throttle(struct tty_struct *tty)
... ... @@ -526,6 +635,39 @@
526 635 * USB probe and disconnect routines.
527 636 */
528 637  
  638 +/* Little helper: write buffers free */
  639 +static void acm_write_buffers_free(struct acm *acm)
  640 +{
  641 + int i;
  642 + struct acm_wb *wb;
  643 +
  644 + for (wb = &acm->wb[0], i = 0; i < ACM_NWB; i++, wb++) {
  645 + usb_buffer_free(acm->dev, acm->writesize, wb->buf, wb->dmah);
  646 + }
  647 +}
  648 +
  649 +/* Little helper: write buffers allocate */
  650 +static int acm_write_buffers_alloc(struct acm *acm)
  651 +{
  652 + int i;
  653 + struct acm_wb *wb;
  654 +
  655 + for (wb = &acm->wb[0], i = 0; i < ACM_NWB; i++, wb++) {
  656 + wb->buf = usb_buffer_alloc(acm->dev, acm->writesize, GFP_KERNEL,
  657 + &wb->dmah);
  658 + if (!wb->buf) {
  659 + while (i != 0) {
  660 + --i;
  661 + --wb;
  662 + usb_buffer_free(acm->dev, acm->writesize,
  663 + wb->buf, wb->dmah);
  664 + }
  665 + return -ENOMEM;
  666 + }
  667 + }
  668 + return 0;
  669 +}
  670 +
529 671 static int acm_probe (struct usb_interface *intf,
530 672 const struct usb_device_id *id)
531 673 {
... ... @@ -700,7 +842,8 @@
700 842 acm->bh.data = (unsigned long) acm;
701 843 INIT_WORK(&acm->work, acm_softint, acm);
702 844 spin_lock_init(&acm->throttle_lock);
703   - acm->ready_for_write = 1;
  845 + spin_lock_init(&acm->write_lock);
  846 + acm->write_ready = 1;
704 847  
705 848 buf = usb_buffer_alloc(usb_dev, ctrlsize, GFP_KERNEL, &acm->ctrl_dma);
706 849 if (!buf) {
707 850  
... ... @@ -716,12 +859,10 @@
716 859 }
717 860 acm->read_buffer = buf;
718 861  
719   - buf = usb_buffer_alloc(usb_dev, acm->writesize, GFP_KERNEL, &acm->write_dma);
720   - if (!buf) {
  862 + if (acm_write_buffers_alloc(acm) < 0) {
721 863 dev_dbg(&intf->dev, "out of memory (write buffer alloc)\n");
722 864 goto alloc_fail4;
723 865 }
724   - acm->write_buffer = buf;
725 866  
726 867 acm->ctrlurb = usb_alloc_urb(0, GFP_KERNEL);
727 868 if (!acm->ctrlurb) {
728 869  
... ... @@ -750,9 +891,9 @@
750 891 acm->readurb->transfer_dma = acm->read_dma;
751 892  
752 893 usb_fill_bulk_urb(acm->writeurb, usb_dev, usb_sndbulkpipe(usb_dev, epwrite->bEndpointAddress),
753   - acm->write_buffer, acm->writesize, acm_write_bulk, acm);
  894 + NULL, acm->writesize, acm_write_bulk, acm);
754 895 acm->writeurb->transfer_flags |= URB_NO_FSBR | URB_NO_TRANSFER_DMA_MAP;
755   - acm->writeurb->transfer_dma = acm->write_dma;
  896 + /* acm->writeurb->transfer_dma = 0; */
756 897  
757 898 dev_info(&intf->dev, "ttyACM%d: USB ACM device\n", minor);
758 899  
... ... @@ -775,7 +916,7 @@
775 916 alloc_fail6:
776 917 usb_free_urb(acm->ctrlurb);
777 918 alloc_fail5:
778   - usb_buffer_free(usb_dev, acm->writesize, acm->write_buffer, acm->write_dma);
  919 + acm_write_buffers_free(acm);
779 920 alloc_fail4:
780 921 usb_buffer_free(usb_dev, readsize, acm->read_buffer, acm->read_dma);
781 922 alloc_fail3:
... ... @@ -806,7 +947,7 @@
806 947  
807 948 flush_scheduled_work(); /* wait for acm_softint */
808 949  
809   - usb_buffer_free(usb_dev, acm->writesize, acm->write_buffer, acm->write_dma);
  950 + acm_write_buffers_free(acm);
810 951 usb_buffer_free(usb_dev, acm->readsize, acm->read_buffer, acm->read_dma);
811 952 usb_buffer_free(usb_dev, acm->ctrlsize, acm->ctrl_buffer, acm->ctrl_dma);
812 953  
drivers/usb/class/cdc-acm.h
... ... @@ -51,14 +51,34 @@
51 51 * Internal driver structures.
52 52 */
53 53  
  54 +/*
  55 + * The only reason to have several buffers is to accomodate assumptions
  56 + * in line disciplines. They ask for empty space amount, receive our URB size,
  57 + * and proceed to issue several 1-character writes, assuming they will fit.
  58 + * The very first write takes a complete URB. Fortunately, this only happens
  59 + * when processing onlcr, so we only need 2 buffers.
  60 + */
  61 +#define ACM_NWB 2
  62 +struct acm_wb {
  63 + unsigned char *buf;
  64 + dma_addr_t dmah;
  65 + int len;
  66 + int use;
  67 +};
  68 +
54 69 struct acm {
55 70 struct usb_device *dev; /* the corresponding usb device */
56 71 struct usb_interface *control; /* control interface */
57 72 struct usb_interface *data; /* data interface */
58 73 struct tty_struct *tty; /* the corresponding tty */
59 74 struct urb *ctrlurb, *readurb, *writeurb; /* urbs */
60   - u8 *ctrl_buffer, *read_buffer, *write_buffer; /* buffers of urbs */
61   - dma_addr_t ctrl_dma, read_dma, write_dma; /* dma handles of buffers */
  75 + u8 *ctrl_buffer, *read_buffer; /* buffers of urbs */
  76 + dma_addr_t ctrl_dma, read_dma; /* dma handles of buffers */
  77 + struct acm_wb wb[ACM_NWB];
  78 + int write_current; /* current write buffer */
  79 + int write_used; /* number of non-empty write buffers */
  80 + int write_ready; /* write urb is not running */
  81 + spinlock_t write_lock;
62 82 struct usb_cdc_line_coding line; /* bits, stop, parity */
63 83 struct work_struct work; /* work queue entry for line discipline waking up */
64 84 struct tasklet_struct bh; /* rx processing */
... ... @@ -71,7 +91,6 @@
71 91 unsigned int minor; /* acm minor number */
72 92 unsigned char throttle; /* throttled by tty layer */
73 93 unsigned char clocal; /* termios CLOCAL */
74   - unsigned char ready_for_write; /* write urb can be used */
75 94 unsigned char resubmit_to_unthrottle; /* throtteling has disabled the read urb */
76 95 unsigned int ctrl_caps; /* control capabilities from the class specific header */
77 96 };