Loading drivers/usb/class/cdc-acm.c +98 −66 Original line number Diff line number Diff line Loading @@ -62,7 +62,7 @@ #include <linux/tty_flip.h> #include <linux/module.h> #include <linux/mutex.h> #include <asm/uaccess.h> #include <linux/uaccess.h> #include <linux/usb.h> #include <linux/usb/cdc.h> #include <asm/byteorder.h> Loading @@ -87,7 +87,7 @@ static struct acm *acm_table[ACM_TTY_MINORS]; static DEFINE_MUTEX(open_mutex); #define ACM_READY(acm) (acm && acm->dev && acm->used) #define ACM_READY(acm) (acm && acm->dev && acm->port.count) static const struct tty_port_operations acm_port_ops = { }; Loading Loading @@ -265,6 +265,7 @@ static void acm_ctrl_irq(struct urb *urb) { struct acm *acm = urb->context; struct usb_cdc_notification *dr = urb->transfer_buffer; struct tty_struct *tty; unsigned char *data; int newctrl; int retval; Loading Loading @@ -297,12 +298,16 @@ static void acm_ctrl_irq(struct urb *urb) break; case USB_CDC_NOTIFY_SERIAL_STATE: tty = tty_port_tty_get(&acm->port); newctrl = get_unaligned_le16(data); if (acm->tty && !acm->clocal && (acm->ctrlin & ~newctrl & ACM_CTRL_DCD)) { if (tty) { if (!acm->clocal && (acm->ctrlin & ~newctrl & ACM_CTRL_DCD)) { dbg("calling hangup"); tty_hangup(acm->tty); tty_hangup(tty); } tty_kref_put(tty); } acm->ctrlin = newctrl; Loading Loading @@ -374,15 +379,14 @@ static void acm_rx_tasklet(unsigned long _acm) { struct acm *acm = (void *)_acm; struct acm_rb *buf; struct tty_struct *tty = acm->tty; struct tty_struct *tty; struct acm_ru *rcv; unsigned long flags; unsigned char throttled; dbg("Entering acm_rx_tasklet"); if (!ACM_READY(acm)) { if (!ACM_READY(acm)) { dbg("acm_rx_tasklet: ACM not ready"); return; } Loading @@ -390,12 +394,13 @@ static void acm_rx_tasklet(unsigned long _acm) spin_lock_irqsave(&acm->throttle_lock, flags); throttled = acm->throttle; spin_unlock_irqrestore(&acm->throttle_lock, flags); if (throttled) { if (throttled) { dbg("acm_rx_tasklet: throttled"); return; } tty = tty_port_tty_get(&acm->port); next_buffer: spin_lock_irqsave(&acm->read_lock, flags); if (list_empty(&acm->filled_read_bufs)) { Loading @@ -409,21 +414,23 @@ next_buffer: dbg("acm_rx_tasklet: procesing buf 0x%p, size = %d", buf, buf->size); tty_buffer_request_room(tty, buf->size); if (tty) { spin_lock_irqsave(&acm->throttle_lock, flags); throttled = acm->throttle; spin_unlock_irqrestore(&acm->throttle_lock, flags); if (!throttled) if (!throttled) { tty_buffer_request_room(tty, buf->size); tty_insert_flip_string(tty, buf->base, buf->size); tty_flip_buffer_push(tty); if (throttled) { } else { tty_kref_put(tty); dbg("Throttling noticed"); 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); Loading @@ -431,6 +438,8 @@ next_buffer: goto next_buffer; 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)) { Loading Loading @@ -502,11 +511,14 @@ static void acm_write_bulk(struct urb *urb) 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"); if (!ACM_READY(acm)) return; tty_wakeup(acm->tty); tty = tty_port_tty_get(&acm->port); tty_wakeup(tty); tty_kref_put(tty); } static void acm_waker(struct work_struct *waker) Loading Loading @@ -546,8 +558,9 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp) rv = 0; set_bit(TTY_NO_WRITE_SPLIT, &tty->flags); tty->driver_data = acm; acm->tty = tty; tty_port_tty_set(&acm->port, tty); if (usb_autopm_get_interface(acm->control) < 0) goto early_bail; Loading @@ -555,12 +568,11 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp) acm->control->needs_remote_wakeup = 1; mutex_lock(&acm->mutex); if (acm->used++) { if (acm->port.count++) { usb_autopm_put_interface(acm->control); goto done; } acm->ctrlurb->dev = acm->dev; if (usb_submit_urb(acm->ctrlurb, GFP_KERNEL)) { dbg("usb_submit_urb(ctrl irq) failed"); Loading @@ -570,6 +582,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; usb_autopm_put_interface(acm->control); INIT_LIST_HEAD(&acm->spare_read_urbs); Loading @@ -585,7 +598,7 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp) acm->throttle = 0; tasklet_schedule(&acm->urb_task); rv = tty_port_block_til_ready(&acm->port, tty, filp); done: mutex_unlock(&acm->mutex); err_out: Loading @@ -596,10 +609,11 @@ full_bailout: usb_kill_urb(acm->ctrlurb); bail_out: usb_autopm_put_interface(acm->control); acm->used--; acm->port.count--; mutex_unlock(&acm->mutex); early_bail: mutex_unlock(&open_mutex); tty_port_tty_set(&acm->port, NULL); return -EIO; } Loading @@ -622,27 +636,19 @@ static void acm_tty_unregister(struct acm *acm) static int acm_tty_chars_in_buffer(struct tty_struct *tty); static void acm_tty_close(struct tty_struct *tty, struct file *filp) static void acm_port_down(struct acm *acm, int drain) { struct acm *acm = tty->driver_data; int i,nr; if (!acm || !acm->used) return; nr = acm->rx_buflimit; int i, nr = acm->rx_buflimit; mutex_lock(&open_mutex); if (!--acm->used) { if (acm->dev) { usb_autopm_get_interface(acm->control); acm_set_control(acm, acm->ctrlout = 0); /* try letting the last writes drain naturally */ if (drain) { wait_event_interruptible_timeout(acm->drain_wait, (ACM_NW == acm_wb_is_avail(acm)) || !acm->dev, (ACM_NW == acm_wb_is_avail(acm)) || !acm->dev, ACM_CLOSE_TIMEOUT * HZ); } usb_kill_urb(acm->ctrlurb); for (i = 0; i < ACM_NW; i++) usb_kill_urb(acm->wb[i].urb); Loading @@ -650,12 +656,34 @@ static void acm_tty_close(struct tty_struct *tty, struct file *filp) usb_kill_urb(acm->ru[i].urb); acm->control->needs_remote_wakeup = 0; usb_autopm_put_interface(acm->control); } else acm_tty_unregister(acm); } mutex_unlock(&open_mutex); } static void acm_tty_hangup(struct tty_struct *tty) { struct acm *acm = tty->driver_data; tty_port_hangup(&acm->port); acm_port_down(acm, 0); } static void acm_tty_close(struct tty_struct *tty, struct file *filp) { struct acm *acm = tty->driver_data; /* Perform the closing process and see if we need to do the hardware shutdown */ if (tty_port_close_start(&acm->port, tty, filp) == 0) return; acm_port_down(acm, 0); tty_port_close_end(&acm->port, tty); mutex_lock(&open_mutex); tty_port_tty_set(&acm->port, NULL); if (!acm->dev) acm_tty_unregister(acm); mutex_unlock(&open_mutex); } static int acm_tty_write(struct tty_struct *tty, const unsigned char *buf, int count) { struct acm *acm = tty->driver_data; Loading Loading @@ -1232,6 +1260,7 @@ static void acm_disconnect(struct usb_interface *intf) { struct acm *acm = usb_get_intfdata(intf); struct usb_device *usb_dev = interface_to_usbdev(intf); struct tty_struct *tty; /* sibling interface is already cleaning up */ if (!acm) Loading @@ -1258,16 +1287,18 @@ static void acm_disconnect(struct usb_interface *intf) usb_driver_release_interface(&acm_driver, intf == acm->control ? acm->data : acm->control); if (!acm->used) { if (acm->port.count == 0) { acm_tty_unregister(acm); mutex_unlock(&open_mutex); return; } mutex_unlock(&open_mutex); if (acm->tty) tty_hangup(acm->tty); tty = tty_port_tty_get(&acm->port); if (tty) { tty_hangup(tty); tty_kref_put(tty); } } #ifdef CONFIG_PM Loading Loading @@ -1302,7 +1333,7 @@ static int acm_suspend(struct usb_interface *intf, pm_message_t message) */ mutex_lock(&acm->mutex); if (acm->used) if (acm->port.count) stop_data_traffic(acm); mutex_unlock(&acm->mutex); Loading @@ -1324,7 +1355,7 @@ static int acm_resume(struct usb_interface *intf) return 0; mutex_lock(&acm->mutex); if (acm->used) { if (acm->port.count) { rv = usb_submit_urb(acm->ctrlurb, GFP_NOIO); if (rv < 0) goto err_out; Loading Loading @@ -1434,6 +1465,7 @@ static struct usb_driver acm_driver = { static const struct tty_operations acm_ops = { .open = acm_tty_open, .close = acm_tty_close, .hangup = acm_tty_hangup, .write = acm_tty_write, .write_room = acm_tty_write_room, .ioctl = acm_tty_ioctl, Loading drivers/usb/class/cdc-acm.h +0 −2 Original line number Diff line number Diff line Loading @@ -89,7 +89,6 @@ struct acm { struct usb_device *dev; /* the corresponding usb device */ struct usb_interface *control; /* control interface */ struct usb_interface *data; /* data interface */ struct tty_struct *tty; /* the corresponding tty */ struct tty_port port; /* our tty port data */ struct urb *ctrlurb; /* urbs */ u8 *ctrl_buffer; /* buffers of urbs */ Loading Loading @@ -121,7 +120,6 @@ struct acm { unsigned int ctrlout; /* output control lines (DTR, RTS) */ unsigned int writesize; /* max packet size for the output bulk endpoint */ unsigned int readsize,ctrlsize; /* buffer sizes for freeing */ unsigned int used; /* someone has this acm's device open */ unsigned int minor; /* acm minor number */ unsigned char throttle; /* throttled by tty layer */ unsigned char clocal; /* termios CLOCAL */ Loading Loading
drivers/usb/class/cdc-acm.c +98 −66 Original line number Diff line number Diff line Loading @@ -62,7 +62,7 @@ #include <linux/tty_flip.h> #include <linux/module.h> #include <linux/mutex.h> #include <asm/uaccess.h> #include <linux/uaccess.h> #include <linux/usb.h> #include <linux/usb/cdc.h> #include <asm/byteorder.h> Loading @@ -87,7 +87,7 @@ static struct acm *acm_table[ACM_TTY_MINORS]; static DEFINE_MUTEX(open_mutex); #define ACM_READY(acm) (acm && acm->dev && acm->used) #define ACM_READY(acm) (acm && acm->dev && acm->port.count) static const struct tty_port_operations acm_port_ops = { }; Loading Loading @@ -265,6 +265,7 @@ static void acm_ctrl_irq(struct urb *urb) { struct acm *acm = urb->context; struct usb_cdc_notification *dr = urb->transfer_buffer; struct tty_struct *tty; unsigned char *data; int newctrl; int retval; Loading Loading @@ -297,12 +298,16 @@ static void acm_ctrl_irq(struct urb *urb) break; case USB_CDC_NOTIFY_SERIAL_STATE: tty = tty_port_tty_get(&acm->port); newctrl = get_unaligned_le16(data); if (acm->tty && !acm->clocal && (acm->ctrlin & ~newctrl & ACM_CTRL_DCD)) { if (tty) { if (!acm->clocal && (acm->ctrlin & ~newctrl & ACM_CTRL_DCD)) { dbg("calling hangup"); tty_hangup(acm->tty); tty_hangup(tty); } tty_kref_put(tty); } acm->ctrlin = newctrl; Loading Loading @@ -374,15 +379,14 @@ static void acm_rx_tasklet(unsigned long _acm) { struct acm *acm = (void *)_acm; struct acm_rb *buf; struct tty_struct *tty = acm->tty; struct tty_struct *tty; struct acm_ru *rcv; unsigned long flags; unsigned char throttled; dbg("Entering acm_rx_tasklet"); if (!ACM_READY(acm)) { if (!ACM_READY(acm)) { dbg("acm_rx_tasklet: ACM not ready"); return; } Loading @@ -390,12 +394,13 @@ static void acm_rx_tasklet(unsigned long _acm) spin_lock_irqsave(&acm->throttle_lock, flags); throttled = acm->throttle; spin_unlock_irqrestore(&acm->throttle_lock, flags); if (throttled) { if (throttled) { dbg("acm_rx_tasklet: throttled"); return; } tty = tty_port_tty_get(&acm->port); next_buffer: spin_lock_irqsave(&acm->read_lock, flags); if (list_empty(&acm->filled_read_bufs)) { Loading @@ -409,21 +414,23 @@ next_buffer: dbg("acm_rx_tasklet: procesing buf 0x%p, size = %d", buf, buf->size); tty_buffer_request_room(tty, buf->size); if (tty) { spin_lock_irqsave(&acm->throttle_lock, flags); throttled = acm->throttle; spin_unlock_irqrestore(&acm->throttle_lock, flags); if (!throttled) if (!throttled) { tty_buffer_request_room(tty, buf->size); tty_insert_flip_string(tty, buf->base, buf->size); tty_flip_buffer_push(tty); if (throttled) { } else { tty_kref_put(tty); dbg("Throttling noticed"); 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); Loading @@ -431,6 +438,8 @@ next_buffer: goto next_buffer; 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)) { Loading Loading @@ -502,11 +511,14 @@ static void acm_write_bulk(struct urb *urb) 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"); if (!ACM_READY(acm)) return; tty_wakeup(acm->tty); tty = tty_port_tty_get(&acm->port); tty_wakeup(tty); tty_kref_put(tty); } static void acm_waker(struct work_struct *waker) Loading Loading @@ -546,8 +558,9 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp) rv = 0; set_bit(TTY_NO_WRITE_SPLIT, &tty->flags); tty->driver_data = acm; acm->tty = tty; tty_port_tty_set(&acm->port, tty); if (usb_autopm_get_interface(acm->control) < 0) goto early_bail; Loading @@ -555,12 +568,11 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp) acm->control->needs_remote_wakeup = 1; mutex_lock(&acm->mutex); if (acm->used++) { if (acm->port.count++) { usb_autopm_put_interface(acm->control); goto done; } acm->ctrlurb->dev = acm->dev; if (usb_submit_urb(acm->ctrlurb, GFP_KERNEL)) { dbg("usb_submit_urb(ctrl irq) failed"); Loading @@ -570,6 +582,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; usb_autopm_put_interface(acm->control); INIT_LIST_HEAD(&acm->spare_read_urbs); Loading @@ -585,7 +598,7 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp) acm->throttle = 0; tasklet_schedule(&acm->urb_task); rv = tty_port_block_til_ready(&acm->port, tty, filp); done: mutex_unlock(&acm->mutex); err_out: Loading @@ -596,10 +609,11 @@ full_bailout: usb_kill_urb(acm->ctrlurb); bail_out: usb_autopm_put_interface(acm->control); acm->used--; acm->port.count--; mutex_unlock(&acm->mutex); early_bail: mutex_unlock(&open_mutex); tty_port_tty_set(&acm->port, NULL); return -EIO; } Loading @@ -622,27 +636,19 @@ static void acm_tty_unregister(struct acm *acm) static int acm_tty_chars_in_buffer(struct tty_struct *tty); static void acm_tty_close(struct tty_struct *tty, struct file *filp) static void acm_port_down(struct acm *acm, int drain) { struct acm *acm = tty->driver_data; int i,nr; if (!acm || !acm->used) return; nr = acm->rx_buflimit; int i, nr = acm->rx_buflimit; mutex_lock(&open_mutex); if (!--acm->used) { if (acm->dev) { usb_autopm_get_interface(acm->control); acm_set_control(acm, acm->ctrlout = 0); /* try letting the last writes drain naturally */ if (drain) { wait_event_interruptible_timeout(acm->drain_wait, (ACM_NW == acm_wb_is_avail(acm)) || !acm->dev, (ACM_NW == acm_wb_is_avail(acm)) || !acm->dev, ACM_CLOSE_TIMEOUT * HZ); } usb_kill_urb(acm->ctrlurb); for (i = 0; i < ACM_NW; i++) usb_kill_urb(acm->wb[i].urb); Loading @@ -650,12 +656,34 @@ static void acm_tty_close(struct tty_struct *tty, struct file *filp) usb_kill_urb(acm->ru[i].urb); acm->control->needs_remote_wakeup = 0; usb_autopm_put_interface(acm->control); } else acm_tty_unregister(acm); } mutex_unlock(&open_mutex); } static void acm_tty_hangup(struct tty_struct *tty) { struct acm *acm = tty->driver_data; tty_port_hangup(&acm->port); acm_port_down(acm, 0); } static void acm_tty_close(struct tty_struct *tty, struct file *filp) { struct acm *acm = tty->driver_data; /* Perform the closing process and see if we need to do the hardware shutdown */ if (tty_port_close_start(&acm->port, tty, filp) == 0) return; acm_port_down(acm, 0); tty_port_close_end(&acm->port, tty); mutex_lock(&open_mutex); tty_port_tty_set(&acm->port, NULL); if (!acm->dev) acm_tty_unregister(acm); mutex_unlock(&open_mutex); } static int acm_tty_write(struct tty_struct *tty, const unsigned char *buf, int count) { struct acm *acm = tty->driver_data; Loading Loading @@ -1232,6 +1260,7 @@ static void acm_disconnect(struct usb_interface *intf) { struct acm *acm = usb_get_intfdata(intf); struct usb_device *usb_dev = interface_to_usbdev(intf); struct tty_struct *tty; /* sibling interface is already cleaning up */ if (!acm) Loading @@ -1258,16 +1287,18 @@ static void acm_disconnect(struct usb_interface *intf) usb_driver_release_interface(&acm_driver, intf == acm->control ? acm->data : acm->control); if (!acm->used) { if (acm->port.count == 0) { acm_tty_unregister(acm); mutex_unlock(&open_mutex); return; } mutex_unlock(&open_mutex); if (acm->tty) tty_hangup(acm->tty); tty = tty_port_tty_get(&acm->port); if (tty) { tty_hangup(tty); tty_kref_put(tty); } } #ifdef CONFIG_PM Loading Loading @@ -1302,7 +1333,7 @@ static int acm_suspend(struct usb_interface *intf, pm_message_t message) */ mutex_lock(&acm->mutex); if (acm->used) if (acm->port.count) stop_data_traffic(acm); mutex_unlock(&acm->mutex); Loading @@ -1324,7 +1355,7 @@ static int acm_resume(struct usb_interface *intf) return 0; mutex_lock(&acm->mutex); if (acm->used) { if (acm->port.count) { rv = usb_submit_urb(acm->ctrlurb, GFP_NOIO); if (rv < 0) goto err_out; Loading Loading @@ -1434,6 +1465,7 @@ static struct usb_driver acm_driver = { static const struct tty_operations acm_ops = { .open = acm_tty_open, .close = acm_tty_close, .hangup = acm_tty_hangup, .write = acm_tty_write, .write_room = acm_tty_write_room, .ioctl = acm_tty_ioctl, Loading
drivers/usb/class/cdc-acm.h +0 −2 Original line number Diff line number Diff line Loading @@ -89,7 +89,6 @@ struct acm { struct usb_device *dev; /* the corresponding usb device */ struct usb_interface *control; /* control interface */ struct usb_interface *data; /* data interface */ struct tty_struct *tty; /* the corresponding tty */ struct tty_port port; /* our tty port data */ struct urb *ctrlurb; /* urbs */ u8 *ctrl_buffer; /* buffers of urbs */ Loading Loading @@ -121,7 +120,6 @@ struct acm { unsigned int ctrlout; /* output control lines (DTR, RTS) */ unsigned int writesize; /* max packet size for the output bulk endpoint */ unsigned int readsize,ctrlsize; /* buffer sizes for freeing */ unsigned int used; /* someone has this acm's device open */ unsigned int minor; /* acm minor number */ unsigned char throttle; /* throttled by tty layer */ unsigned char clocal; /* termios CLOCAL */ Loading