Loading drivers/usb/class/cdc-acm.c +67 −0 Original line number Diff line number Diff line Loading @@ -713,9 +713,20 @@ static int acm_tty_write(struct tty_struct *tty, } if (acm->susp_count) { if (acm->putbuffer) { /* now to preserve order */ usb_anchor_urb(acm->putbuffer->urb, &acm->delayed); acm->putbuffer = NULL; } usb_anchor_urb(wb->urb, &acm->delayed); spin_unlock_irqrestore(&acm->write_lock, flags); return count; } else { if (acm->putbuffer) { /* at this point there is no good way to handle errors */ acm_start_wb(acm, acm->putbuffer); acm->putbuffer = NULL; } } stat = acm_start_wb(acm, wb); Loading @@ -726,6 +737,60 @@ static int acm_tty_write(struct tty_struct *tty, return count; } static void acm_tty_flush_chars(struct tty_struct *tty) { struct acm *acm = tty->driver_data; struct acm_wb *cur = acm->putbuffer; int err; unsigned long flags; acm->putbuffer = NULL; err = usb_autopm_get_interface_async(acm->control); spin_lock_irqsave(&acm->write_lock, flags); if (err < 0) { cur->use = 0; goto out; } if (acm->susp_count) usb_anchor_urb(cur->urb, &acm->delayed); else acm_start_wb(acm, cur); out: spin_unlock_irqrestore(&acm->write_lock, flags); return; } static int acm_tty_put_char(struct tty_struct *tty, unsigned char ch) { struct acm *acm = tty->driver_data; struct acm_wb *cur; int wbn; unsigned long flags; overflow: cur = acm->putbuffer; if (!cur) { spin_lock_irqsave(&acm->write_lock, flags); wbn = acm_wb_alloc(acm); if (wbn >= 0) { cur = &acm->wb[wbn]; acm->putbuffer = cur; } spin_unlock_irqrestore(&acm->write_lock, flags); if (!cur) return 0; } if (cur->len == acm->writesize) { acm_tty_flush_chars(tty); goto overflow; } cur->buf[cur->len++] = ch; return 1; } static int acm_tty_write_room(struct tty_struct *tty) { struct acm *acm = tty->driver_data; Loading Loading @@ -1905,6 +1970,8 @@ static const struct tty_operations acm_ops = { .cleanup = acm_tty_cleanup, .hangup = acm_tty_hangup, .write = acm_tty_write, .put_char = acm_tty_put_char, .flush_chars = acm_tty_flush_chars, .write_room = acm_tty_write_room, .ioctl = acm_tty_ioctl, .throttle = acm_tty_throttle, Loading drivers/usb/class/cdc-acm.h +1 −0 Original line number Diff line number Diff line Loading @@ -94,6 +94,7 @@ struct acm { unsigned long read_urbs_free; struct urb *read_urbs[ACM_NR]; struct acm_rb read_buffers[ACM_NR]; struct acm_wb *putbuffer; /* for acm_tty_put_char() */ int rx_buflimit; int rx_endpoint; spinlock_t read_lock; Loading Loading
drivers/usb/class/cdc-acm.c +67 −0 Original line number Diff line number Diff line Loading @@ -713,9 +713,20 @@ static int acm_tty_write(struct tty_struct *tty, } if (acm->susp_count) { if (acm->putbuffer) { /* now to preserve order */ usb_anchor_urb(acm->putbuffer->urb, &acm->delayed); acm->putbuffer = NULL; } usb_anchor_urb(wb->urb, &acm->delayed); spin_unlock_irqrestore(&acm->write_lock, flags); return count; } else { if (acm->putbuffer) { /* at this point there is no good way to handle errors */ acm_start_wb(acm, acm->putbuffer); acm->putbuffer = NULL; } } stat = acm_start_wb(acm, wb); Loading @@ -726,6 +737,60 @@ static int acm_tty_write(struct tty_struct *tty, return count; } static void acm_tty_flush_chars(struct tty_struct *tty) { struct acm *acm = tty->driver_data; struct acm_wb *cur = acm->putbuffer; int err; unsigned long flags; acm->putbuffer = NULL; err = usb_autopm_get_interface_async(acm->control); spin_lock_irqsave(&acm->write_lock, flags); if (err < 0) { cur->use = 0; goto out; } if (acm->susp_count) usb_anchor_urb(cur->urb, &acm->delayed); else acm_start_wb(acm, cur); out: spin_unlock_irqrestore(&acm->write_lock, flags); return; } static int acm_tty_put_char(struct tty_struct *tty, unsigned char ch) { struct acm *acm = tty->driver_data; struct acm_wb *cur; int wbn; unsigned long flags; overflow: cur = acm->putbuffer; if (!cur) { spin_lock_irqsave(&acm->write_lock, flags); wbn = acm_wb_alloc(acm); if (wbn >= 0) { cur = &acm->wb[wbn]; acm->putbuffer = cur; } spin_unlock_irqrestore(&acm->write_lock, flags); if (!cur) return 0; } if (cur->len == acm->writesize) { acm_tty_flush_chars(tty); goto overflow; } cur->buf[cur->len++] = ch; return 1; } static int acm_tty_write_room(struct tty_struct *tty) { struct acm *acm = tty->driver_data; Loading Loading @@ -1905,6 +1970,8 @@ static const struct tty_operations acm_ops = { .cleanup = acm_tty_cleanup, .hangup = acm_tty_hangup, .write = acm_tty_write, .put_char = acm_tty_put_char, .flush_chars = acm_tty_flush_chars, .write_room = acm_tty_write_room, .ioctl = acm_tty_ioctl, .throttle = acm_tty_throttle, Loading
drivers/usb/class/cdc-acm.h +1 −0 Original line number Diff line number Diff line Loading @@ -94,6 +94,7 @@ struct acm { unsigned long read_urbs_free; struct urb *read_urbs[ACM_NR]; struct acm_rb read_buffers[ACM_NR]; struct acm_wb *putbuffer; /* for acm_tty_put_char() */ int rx_buflimit; int rx_endpoint; spinlock_t read_lock; Loading