diff options
Diffstat (limited to 'drivers/usb/class/cdc-acm.c')
| -rw-r--r-- | drivers/usb/class/cdc-acm.c | 136 | 
1 files changed, 28 insertions, 108 deletions
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 27346d69f393..47d75c20c211 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -310,17 +310,17 @@ static void acm_process_notification(struct acm *acm, unsigned char *buf)  		if (difference & ACM_CTRL_DSR)  			acm->iocount.dsr++; -		if (difference & ACM_CTRL_BRK) -			acm->iocount.brk++; -		if (difference & ACM_CTRL_RI) -			acm->iocount.rng++;  		if (difference & ACM_CTRL_DCD)  			acm->iocount.dcd++; -		if (difference & ACM_CTRL_FRAMING) +		if (newctrl & ACM_CTRL_BRK) +			acm->iocount.brk++; +		if (newctrl & ACM_CTRL_RI) +			acm->iocount.rng++; +		if (newctrl & ACM_CTRL_FRAMING)  			acm->iocount.frame++; -		if (difference & ACM_CTRL_PARITY) +		if (newctrl & ACM_CTRL_PARITY)  			acm->iocount.parity++; -		if (difference & ACM_CTRL_OVERRUN) +		if (newctrl & ACM_CTRL_OVERRUN)  			acm->iocount.overrun++;  		spin_unlock_irqrestore(&acm->read_lock, flags); @@ -355,7 +355,6 @@ static void acm_ctrl_irq(struct urb *urb)  	case -ENOENT:  	case -ESHUTDOWN:  		/* this urb is terminated, clean up */ -		acm->nb_index = 0;  		dev_dbg(&acm->control->dev,  			"%s - urb shutting down with status: %d\n",  			__func__, status); @@ -780,20 +779,9 @@ 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); @@ -804,66 +792,6 @@ 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; -	int err; -	unsigned long flags; - -	spin_lock_irqsave(&acm->write_lock, flags); - -	cur = acm->putbuffer; -	if (!cur) /* nothing to do */ -		goto out; - -	acm->putbuffer = NULL; -	err = usb_autopm_get_interface_async(acm->control); -	if (err < 0) { -		cur->use = 0; -		acm->putbuffer = cur; -		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; @@ -956,37 +884,28 @@ static int acm_tty_tiocmset(struct tty_struct *tty,  	return acm_set_control(acm, acm->ctrlout = newctrl);  } -static int get_serial_info(struct acm *acm, struct serial_struct __user *info) +static int get_serial_info(struct tty_struct *tty, struct serial_struct *ss)  { -	struct serial_struct tmp; +	struct acm *acm = tty->driver_data; -	memset(&tmp, 0, sizeof(tmp)); -	tmp.xmit_fifo_size = acm->writesize; -	tmp.baud_base = le32_to_cpu(acm->line.dwDTERate); -	tmp.close_delay	= acm->port.close_delay / 10; -	tmp.closing_wait = acm->port.closing_wait == ASYNC_CLOSING_WAIT_NONE ? +	ss->xmit_fifo_size = acm->writesize; +	ss->baud_base = le32_to_cpu(acm->line.dwDTERate); +	ss->close_delay	= acm->port.close_delay / 10; +	ss->closing_wait = acm->port.closing_wait == ASYNC_CLOSING_WAIT_NONE ?  				ASYNC_CLOSING_WAIT_NONE :  				acm->port.closing_wait / 10; - -	if (copy_to_user(info, &tmp, sizeof(tmp))) -		return -EFAULT; -	else -		return 0; +	return 0;  } -static int set_serial_info(struct acm *acm, -				struct serial_struct __user *newinfo) +static int set_serial_info(struct tty_struct *tty, struct serial_struct *ss)  { -	struct serial_struct new_serial; +	struct acm *acm = tty->driver_data;  	unsigned int closing_wait, close_delay;  	int retval = 0; -	if (copy_from_user(&new_serial, newinfo, sizeof(new_serial))) -		return -EFAULT; - -	close_delay = new_serial.close_delay * 10; -	closing_wait = new_serial.closing_wait == ASYNC_CLOSING_WAIT_NONE ? -			ASYNC_CLOSING_WAIT_NONE : new_serial.closing_wait * 10; +	close_delay = ss->close_delay * 10; +	closing_wait = ss->closing_wait == ASYNC_CLOSING_WAIT_NONE ? +			ASYNC_CLOSING_WAIT_NONE : ss->closing_wait * 10;  	mutex_lock(&acm->port.mutex); @@ -1071,12 +990,6 @@ static int acm_tty_ioctl(struct tty_struct *tty,  	int rv = -ENOIOCTLCMD;  	switch (cmd) { -	case TIOCGSERIAL: /* gets serial port data */ -		rv = get_serial_info(acm, (struct serial_struct __user *) arg); -		break; -	case TIOCSSERIAL: -		rv = set_serial_info(acm, (struct serial_struct __user *) arg); -		break;  	case TIOCMIWAIT:  		rv = usb_autopm_get_interface(acm->control);  		if (rv < 0) { @@ -1585,6 +1498,7 @@ static void acm_disconnect(struct usb_interface *intf)  {  	struct acm *acm = usb_get_intfdata(intf);  	struct tty_struct *tty; +	int i;  	/* sibling interface is already cleaning up */  	if (!acm) @@ -1615,6 +1529,11 @@ static void acm_disconnect(struct usb_interface *intf)  	tty_unregister_device(acm_tty_driver, acm->minor); +	usb_free_urb(acm->ctrlurb); +	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->read_urbs[i]);  	acm_write_buffers_free(acm);  	usb_free_coherent(acm->dev, acm->ctrlsize, acm->ctrl_buffer, acm->ctrl_dma);  	acm_read_buffers_free(acm); @@ -1707,6 +1626,7 @@ static int acm_pre_reset(struct usb_interface *intf)  	struct acm *acm = usb_get_intfdata(intf);  	clear_bit(EVENT_RX_STALL, &acm->flags); +	acm->nb_index = 0; /* pending control transfers are lost */  	return 0;  } @@ -1987,8 +1907,6 @@ 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, @@ -1998,6 +1916,8 @@ static const struct tty_operations acm_ops = {  	.set_termios =		acm_tty_set_termios,  	.tiocmget =		acm_tty_tiocmget,  	.tiocmset =		acm_tty_tiocmset, +	.get_serial =		get_serial_info, +	.set_serial =		set_serial_info,  	.get_icount =		acm_tty_get_icount,  };  | 
