diff options
Diffstat (limited to 'drivers/usb/serial')
41 files changed, 904 insertions, 2087 deletions
diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig index 17b7f9ae36a..1d55762afbb 100644 --- a/drivers/usb/serial/Kconfig +++ b/drivers/usb/serial/Kconfig @@ -4,7 +4,7 @@  menuconfig USB_SERIAL  	tristate "USB Serial Converter support" -	depends on USB && TTY +	depends on TTY  	---help---  	  Say Y here if you have a USB device that provides normal serial  	  ports, or acts like a serial device, and you want to connect it to @@ -667,6 +667,23 @@ config USB_SERIAL_ZIO  	  To compile this driver as a module, choose M here: the  	  module will be called zio. +config USB_SERIAL_WISHBONE +	tristate "USB-Wishbone adapter interface driver" +	help +	  Say Y here if you want to use a USB attached Wishbone bus. + +	  Wishbone is an open hardware SoC bus commonly used in FPGA +	  designs. Bus access can be serialized using the Etherbone +	  protocol <http://www.ohwr.org/projects/etherbone-core>. + +	  This driver is intended to be used with devices which attach +	  their internal Wishbone bus to a USB serial interface using +	  the Etherbone protocol. A userspace library is required to +	  speak the protocol made available by this driver as ttyUSBx. + +	  To compile this driver as a module, choose M here: the +	  module will be called wishbone-serial. +  config USB_SERIAL_ZTE  	tristate "ZTE USB serial driver"  	help diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile index eaf5ca14dfe..cec63fa1910 100644 --- a/drivers/usb/serial/Makefile +++ b/drivers/usb/serial/Makefile @@ -58,6 +58,7 @@ obj-$(CONFIG_USB_SERIAL_SYMBOL)			+= symbolserial.o  obj-$(CONFIG_USB_SERIAL_WWAN)			+= usb_wwan.o  obj-$(CONFIG_USB_SERIAL_TI)			+= ti_usb_3410_5052.o  obj-$(CONFIG_USB_SERIAL_VISOR)			+= visor.o +obj-$(CONFIG_USB_SERIAL_WISHBONE)		+= wishbone-serial.o  obj-$(CONFIG_USB_SERIAL_WHITEHEAT)		+= whiteheat.o  obj-$(CONFIG_USB_SERIAL_XIRCOM)			+= keyspan_pda.o  obj-$(CONFIG_USB_SERIAL_VIVOPAY_SERIAL)		+= vivopay-serial.o diff --git a/drivers/usb/serial/ark3116.c b/drivers/usb/serial/ark3116.c index 4775f8209e5..3b16118cbf6 100644 --- a/drivers/usb/serial/ark3116.c +++ b/drivers/usb/serial/ark3116.c @@ -62,7 +62,6 @@ static int is_irda(struct usb_serial *serial)  }  struct ark3116_private { -	struct async_icount	icount;  	int			irda;	/* 1 for irda device */  	/* protects hw register updates */ @@ -341,18 +340,15 @@ static void ark3116_close(struct usb_serial_port *port)  {  	struct usb_serial *serial = port->serial; -	if (serial->dev) { -		/* disable DMA */ -		ark3116_write_reg(serial, UART_FCR, 0); - -		/* deactivate interrupts */ -		ark3116_write_reg(serial, UART_IER, 0); +	/* disable DMA */ +	ark3116_write_reg(serial, UART_FCR, 0); -		usb_serial_generic_close(port); -		if (serial->num_interrupt_in) -			usb_kill_urb(port->interrupt_in_urb); -	} +	/* deactivate interrupts */ +	ark3116_write_reg(serial, UART_IER, 0); +	usb_serial_generic_close(port); +	if (serial->num_interrupt_in) +		usb_kill_urb(port->interrupt_in_urb);  }  static int ark3116_open(struct tty_struct *tty, struct usb_serial_port *port) @@ -405,31 +401,10 @@ err_out:  	return result;  } -static int ark3116_get_icount(struct tty_struct *tty, -					struct serial_icounter_struct *icount) -{ -	struct usb_serial_port *port = tty->driver_data; -	struct ark3116_private *priv = usb_get_serial_port_data(port); -	struct async_icount cnow = priv->icount; -	icount->cts = cnow.cts; -	icount->dsr = cnow.dsr; -	icount->rng = cnow.rng; -	icount->dcd = cnow.dcd; -	icount->rx = cnow.rx; -	icount->tx = cnow.tx; -	icount->frame = cnow.frame; -	icount->overrun = cnow.overrun; -	icount->parity = cnow.parity; -	icount->brk = cnow.brk; -	icount->buf_overrun = cnow.buf_overrun; -	return 0; -} -  static int ark3116_ioctl(struct tty_struct *tty,  			 unsigned int cmd, unsigned long arg)  {  	struct usb_serial_port *port = tty->driver_data; -	struct ark3116_private *priv = usb_get_serial_port_data(port);  	struct serial_struct serstruct;  	void __user *user_arg = (void __user *)arg; @@ -451,33 +426,6 @@ static int ark3116_ioctl(struct tty_struct *tty,  		if (copy_from_user(&serstruct, user_arg, sizeof(serstruct)))  			return -EFAULT;  		return 0; -	case TIOCMIWAIT: -		for (;;) { -			struct async_icount prev = priv->icount; -			interruptible_sleep_on(&port->delta_msr_wait); -			/* see if a signal did it */ -			if (signal_pending(current)) -				return -ERESTARTSYS; - -			if (port->serial->disconnected) -				return -EIO; - -			if ((prev.rng == priv->icount.rng) && -			    (prev.dsr == priv->icount.dsr) && -			    (prev.dcd == priv->icount.dcd) && -			    (prev.cts == priv->icount.cts)) -				return -EIO; -			if ((arg & TIOCM_RNG && -			     (prev.rng != priv->icount.rng)) || -			    (arg & TIOCM_DSR && -			     (prev.dsr != priv->icount.dsr)) || -			    (arg & TIOCM_CD  && -			     (prev.dcd != priv->icount.dcd)) || -			    (arg & TIOCM_CTS && -			     (prev.cts != priv->icount.cts))) -				return 0; -		} -		break;  	}  	return -ENOIOCTLCMD; @@ -575,14 +523,14 @@ static void ark3116_update_msr(struct usb_serial_port *port, __u8 msr)  	if (msr & UART_MSR_ANY_DELTA) {  		/* update input line counters */  		if (msr & UART_MSR_DCTS) -			priv->icount.cts++; +			port->icount.cts++;  		if (msr & UART_MSR_DDSR) -			priv->icount.dsr++; +			port->icount.dsr++;  		if (msr & UART_MSR_DDCD) -			priv->icount.dcd++; +			port->icount.dcd++;  		if (msr & UART_MSR_TERI) -			priv->icount.rng++; -		wake_up_interruptible(&port->delta_msr_wait); +			port->icount.rng++; +		wake_up_interruptible(&port->port.delta_msr_wait);  	}  } @@ -598,13 +546,13 @@ static void ark3116_update_lsr(struct usb_serial_port *port, __u8 lsr)  	if (lsr&UART_LSR_BRK_ERROR_BITS) {  		if (lsr & UART_LSR_BI) -			priv->icount.brk++; +			port->icount.brk++;  		if (lsr & UART_LSR_FE) -			priv->icount.frame++; +			port->icount.frame++;  		if (lsr & UART_LSR_PE) -			priv->icount.parity++; +			port->icount.parity++;  		if (lsr & UART_LSR_OE) -			priv->icount.overrun++; +			port->icount.overrun++;  	}  } @@ -722,7 +670,8 @@ static struct usb_serial_driver ark3116_device = {  	.ioctl =		ark3116_ioctl,  	.tiocmget =		ark3116_tiocmget,  	.tiocmset =		ark3116_tiocmset, -	.get_icount =		ark3116_get_icount, +	.tiocmiwait =		usb_serial_generic_tiocmiwait, +	.get_icount =		usb_serial_generic_get_icount,  	.open =			ark3116_open,  	.close =		ark3116_close,  	.break_ctl = 		ark3116_break_ctl, diff --git a/drivers/usb/serial/bus.c b/drivers/usb/serial/bus.c index 37decb13d7e..3c4db6d196c 100644 --- a/drivers/usb/serial/bus.c +++ b/drivers/usb/serial/bus.c @@ -106,14 +106,15 @@ static int usb_serial_device_remove(struct device *dev)  	/* make sure suspend/resume doesn't race against port_remove */  	usb_autopm_get_interface(port->serial->interface); +	minor = port->number; +	tty_unregister_device(usb_serial_tty_driver, minor); +  	device_remove_file(&port->dev, &dev_attr_port_number);  	driver = port->serial->type;  	if (driver->port_remove)  		retval = driver->port_remove(port); -	minor = port->number; -	tty_unregister_device(usb_serial_tty_driver, minor);  	dev_info(dev, "%s converter now disconnected from ttyUSB%d\n",  		 driver->description, minor); diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c index 07d4650a32a..c2a4171ab9c 100644 --- a/drivers/usb/serial/ch341.c +++ b/drivers/usb/serial/ch341.c @@ -296,7 +296,6 @@ static void ch341_dtr_rts(struct usb_serial_port *port, int on)  		priv->line_control &= ~(CH341_BIT_RTS | CH341_BIT_DTR);  	spin_unlock_irqrestore(&priv->lock, flags);  	ch341_set_handshake(port->serial->dev, priv->line_control); -	wake_up_interruptible(&port->delta_msr_wait);  }  static void ch341_close(struct usb_serial_port *port) @@ -489,7 +488,7 @@ static void ch341_read_int_callback(struct urb *urb)  			tty_kref_put(tty);  		} -		wake_up_interruptible(&port->delta_msr_wait); +		wake_up_interruptible(&port->port.delta_msr_wait);  	}  exit: @@ -500,8 +499,9 @@ exit:  			__func__, status);  } -static int wait_modem_info(struct usb_serial_port *port, unsigned int arg) +static int ch341_tiocmiwait(struct tty_struct *tty, unsigned long arg)  { +	struct usb_serial_port *port = tty->driver_data;  	struct ch341_private *priv = usb_get_serial_port_data(port);  	unsigned long flags;  	u8 prevstatus; @@ -515,7 +515,7 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)  	spin_unlock_irqrestore(&priv->lock, flags);  	while (!multi_change) { -		interruptible_sleep_on(&port->delta_msr_wait); +		interruptible_sleep_on(&port->port.delta_msr_wait);  		/* see if a signal did it */  		if (signal_pending(current))  			return -ERESTARTSYS; @@ -542,26 +542,6 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)  	return 0;  } -static int ch341_ioctl(struct tty_struct *tty, -			unsigned int cmd, unsigned long arg) -{ -	struct usb_serial_port *port = tty->driver_data; - -	dev_dbg(&port->dev, "%s (%d) cmd = 0x%04x\n", __func__, port->number, cmd); - -	switch (cmd) { -	case TIOCMIWAIT: -		dev_dbg(&port->dev, "%s (%d) TIOCMIWAIT\n", __func__,  port->number); -		return wait_modem_info(port, arg); - -	default: -		dev_dbg(&port->dev, "%s not supported = 0x%04x\n", __func__, cmd); -		break; -	} - -	return -ENOIOCTLCMD; -} -  static int ch341_tiocmget(struct tty_struct *tty)  {  	struct usb_serial_port *port = tty->driver_data; @@ -611,11 +591,11 @@ static struct usb_serial_driver ch341_device = {  	.dtr_rts	   = ch341_dtr_rts,  	.carrier_raised	   = ch341_carrier_raised,  	.close             = ch341_close, -	.ioctl             = ch341_ioctl,  	.set_termios       = ch341_set_termios,  	.break_ctl         = ch341_break_ctl,  	.tiocmget          = ch341_tiocmget,  	.tiocmset          = ch341_tiocmset, +	.tiocmiwait        = ch341_tiocmiwait,  	.read_int_callback = ch341_read_int_callback,  	.port_probe        = ch341_port_probe,  	.port_remove       = ch341_port_remove, diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index 4747d1c328f..2c659553c07 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -462,11 +462,7 @@ static int cp210x_open(struct tty_struct *tty, struct usb_serial_port *port)  static void cp210x_close(struct usb_serial_port *port)  {  	usb_serial_generic_close(port); - -	mutex_lock(&port->serial->disc_mutex); -	if (!port->serial->disconnected) -		cp210x_set_config_single(port, CP210X_IFC_ENABLE, UART_DISABLE); -	mutex_unlock(&port->serial->disc_mutex); +	cp210x_set_config_single(port, CP210X_IFC_ENABLE, UART_DISABLE);  }  /* diff --git a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c index 629bd289450..781426230d6 100644 --- a/drivers/usb/serial/cyberjack.c +++ b/drivers/usb/serial/cyberjack.c @@ -51,7 +51,6 @@  #define CYBERJACK_PRODUCT_ID	0x0100  /* Function prototypes */ -static void cyberjack_disconnect(struct usb_serial *serial);  static int cyberjack_port_probe(struct usb_serial_port *port);  static int cyberjack_port_remove(struct usb_serial_port *port);  static int  cyberjack_open(struct tty_struct *tty, @@ -79,7 +78,6 @@ static struct usb_serial_driver cyberjack_device = {  	.description =		"Reiner SCT Cyberjack USB card reader",  	.id_table =		id_table,  	.num_ports =		1, -	.disconnect =		cyberjack_disconnect,  	.port_probe =		cyberjack_port_probe,  	.port_remove =		cyberjack_port_remove,  	.open =			cyberjack_open, @@ -130,20 +128,14 @@ static int cyberjack_port_remove(struct usb_serial_port *port)  {  	struct cyberjack_private *priv; +	usb_kill_urb(port->interrupt_in_urb); +  	priv = usb_get_serial_port_data(port);  	kfree(priv);  	return 0;  } -static void cyberjack_disconnect(struct usb_serial *serial) -{ -	int i; - -	for (i = 0; i < serial->num_ports; ++i) -		usb_kill_urb(serial->port[i]->interrupt_in_urb); -} -  static int  cyberjack_open(struct tty_struct *tty,  					struct usb_serial_port *port)  { @@ -166,11 +158,8 @@ static int  cyberjack_open(struct tty_struct *tty,  static void cyberjack_close(struct usb_serial_port *port)  { -	if (port->serial->dev) { -		/* shutdown any bulk reads that might be going on */ -		usb_kill_urb(port->write_urb); -		usb_kill_urb(port->read_urb); -	} +	usb_kill_urb(port->write_urb); +	usb_kill_urb(port->read_urb);  }  static int cyberjack_write(struct tty_struct *tty, diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c index ba7352e4187..d341555d37d 100644 --- a/drivers/usb/serial/cypress_m8.c +++ b/drivers/usb/serial/cypress_m8.c @@ -129,13 +129,12 @@ static int  cypress_write(struct tty_struct *tty, struct usb_serial_port *port,  			const unsigned char *buf, int count);  static void cypress_send(struct usb_serial_port *port);  static int  cypress_write_room(struct tty_struct *tty); -static int  cypress_ioctl(struct tty_struct *tty, -			unsigned int cmd, unsigned long arg);  static void cypress_set_termios(struct tty_struct *tty,  			struct usb_serial_port *port, struct ktermios *old);  static int  cypress_tiocmget(struct tty_struct *tty);  static int  cypress_tiocmset(struct tty_struct *tty,  			unsigned int set, unsigned int clear); +static int  cypress_tiocmiwait(struct tty_struct *tty, unsigned long arg);  static int  cypress_chars_in_buffer(struct tty_struct *tty);  static void cypress_throttle(struct tty_struct *tty);  static void cypress_unthrottle(struct tty_struct *tty); @@ -158,10 +157,10 @@ static struct usb_serial_driver cypress_earthmate_device = {  	.dtr_rts =			cypress_dtr_rts,  	.write =			cypress_write,  	.write_room =			cypress_write_room, -	.ioctl =			cypress_ioctl,  	.set_termios =			cypress_set_termios,  	.tiocmget =			cypress_tiocmget,  	.tiocmset =			cypress_tiocmset, +	.tiocmiwait =			cypress_tiocmiwait,  	.chars_in_buffer =		cypress_chars_in_buffer,  	.throttle =		 	cypress_throttle,  	.unthrottle =			cypress_unthrottle, @@ -184,10 +183,10 @@ static struct usb_serial_driver cypress_hidcom_device = {  	.dtr_rts =			cypress_dtr_rts,  	.write =			cypress_write,  	.write_room =			cypress_write_room, -	.ioctl =			cypress_ioctl,  	.set_termios =			cypress_set_termios,  	.tiocmget =			cypress_tiocmget,  	.tiocmset =			cypress_tiocmset, +	.tiocmiwait =			cypress_tiocmiwait,  	.chars_in_buffer =		cypress_chars_in_buffer,  	.throttle =			cypress_throttle,  	.unthrottle =			cypress_unthrottle, @@ -210,10 +209,10 @@ static struct usb_serial_driver cypress_ca42v2_device = {  	.dtr_rts =			cypress_dtr_rts,  	.write =			cypress_write,  	.write_room =			cypress_write_room, -	.ioctl =			cypress_ioctl,  	.set_termios =			cypress_set_termios,  	.tiocmget =			cypress_tiocmget,  	.tiocmset =			cypress_tiocmset, +	.tiocmiwait =			cypress_tiocmiwait,  	.chars_in_buffer =		cypress_chars_in_buffer,  	.throttle =			cypress_throttle,  	.unthrottle =			cypress_unthrottle, @@ -633,12 +632,6 @@ static void cypress_close(struct usb_serial_port *port)  	struct cypress_private *priv = usb_get_serial_port_data(port);  	unsigned long flags; -	/* writing is potentially harmful, lock must be taken */ -	mutex_lock(&port->serial->disc_mutex); -	if (port->serial->disconnected) { -		mutex_unlock(&port->serial->disc_mutex); -		return; -	}  	spin_lock_irqsave(&priv->lock, flags);  	kfifo_reset_out(&priv->write_fifo);  	spin_unlock_irqrestore(&priv->lock, flags); @@ -650,7 +643,6 @@ static void cypress_close(struct usb_serial_port *port)  	if (stats)  		dev_info(&port->dev, "Statistics: %d Bytes In | %d Bytes Out | %d Commands Issued\n",  			priv->bytes_in, priv->bytes_out, priv->cmd_count); -	mutex_unlock(&port->serial->disc_mutex);  } /* cypress_close */ @@ -855,55 +847,43 @@ static int cypress_tiocmset(struct tty_struct *tty,  } -static int cypress_ioctl(struct tty_struct *tty, -					unsigned int cmd, unsigned long arg) +static int cypress_tiocmiwait(struct tty_struct *tty, unsigned long arg)  {  	struct usb_serial_port *port = tty->driver_data;  	struct cypress_private *priv = usb_get_serial_port_data(port); +	char diff; -	dev_dbg(&port->dev, "%s - port %d, cmd 0x%.4x\n", __func__, port->number, cmd); - -	switch (cmd) { -	/* This code comes from drivers/char/serial.c and ftdi_sio.c */ -	case TIOCMIWAIT: -		for (;;) { -			interruptible_sleep_on(&port->delta_msr_wait); -			/* see if a signal did it */ -			if (signal_pending(current)) -				return -ERESTARTSYS; +	for (;;) { +		interruptible_sleep_on(&port->port.delta_msr_wait); +		/* see if a signal did it */ +		if (signal_pending(current)) +			return -ERESTARTSYS; -			if (port->serial->disconnected) -				return -EIO; +		if (port->serial->disconnected) +			return -EIO; -			{ -				char diff = priv->diff_status; -				if (diff == 0) -					return -EIO; /* no change => error */ +		diff = priv->diff_status; +		if (diff == 0) +			return -EIO; /* no change => error */ -				/* consume all events */ -				priv->diff_status = 0; +		/* consume all events */ +		priv->diff_status = 0; -				/* return 0 if caller wanted to know about -				   these bits */ -				if (((arg & TIOCM_RNG) && (diff & UART_RI)) || -				    ((arg & TIOCM_DSR) && (diff & UART_DSR)) || -				    ((arg & TIOCM_CD) && (diff & UART_CD)) || -				    ((arg & TIOCM_CTS) && (diff & UART_CTS))) -					return 0; -				/* otherwise caller can't care less about what -				 * happened, and so we continue to wait for -				 * more events. -				 */ -			} -		} -		return 0; -	default: -		break; +		/* return 0 if caller wanted to know about +		   these bits */ +		if (((arg & TIOCM_RNG) && (diff & UART_RI))  || +			((arg & TIOCM_DSR) && (diff & UART_DSR)) || +			((arg & TIOCM_CD)  && (diff & UART_CD))  || +			((arg & TIOCM_CTS) && (diff & UART_CTS))) +			return 0; +		/* otherwise caller can't care less about what +		 * happened, and so we continue to wait for +		 * more events. +		 */  	} -	dev_dbg(&port->dev, "%s - arg not supported - it was 0x%04x - check include/asm/ioctls.h\n", __func__, cmd); -	return -ENOIOCTLCMD; -} /* cypress_ioctl */ +	return 0; +}  static void cypress_set_termios(struct tty_struct *tty,  	struct usb_serial_port *port, struct ktermios *old_termios) @@ -1189,7 +1169,7 @@ static void cypress_read_int_callback(struct urb *urb)  	if (priv->current_status != priv->prev_status) {  		priv->diff_status |= priv->current_status ^  			priv->prev_status; -		wake_up_interruptible(&port->delta_msr_wait); +		wake_up_interruptible(&port->port.delta_msr_wait);  		priv->prev_status = priv->current_status;  	}  	spin_unlock_irqrestore(&priv->lock, flags); diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c index ebe45fa0ed5..7b807d38952 100644 --- a/drivers/usb/serial/digi_acceleport.c +++ b/drivers/usb/serial/digi_acceleport.c @@ -196,7 +196,6 @@ struct digi_port {  	unsigned char dp_out_buf[DIGI_OUT_BUF_SIZE];  	int dp_write_urb_in_use;  	unsigned int dp_modem_signals; -	wait_queue_head_t dp_modem_change_wait;  	int dp_transmit_idle;  	wait_queue_head_t dp_transmit_idle_wait;  	int dp_throttled; @@ -210,7 +209,6 @@ struct digi_port {  /* Local Function Declarations */ -static void digi_wakeup_write(struct usb_serial_port *port);  static void digi_wakeup_write_lock(struct work_struct *work);  static int digi_write_oob_command(struct usb_serial_port *port,  	unsigned char *buf, int count, int interruptible); @@ -374,20 +372,10 @@ static void digi_wakeup_write_lock(struct work_struct *work)  	unsigned long flags;  	spin_lock_irqsave(&priv->dp_port_lock, flags); -	digi_wakeup_write(port); +	tty_port_tty_wakeup(&port->port);  	spin_unlock_irqrestore(&priv->dp_port_lock, flags);  } -static void digi_wakeup_write(struct usb_serial_port *port) -{ -	struct tty_struct *tty = tty_port_tty_get(&port->port); -	if (tty) { -		tty_wakeup(tty); -		tty_kref_put(tty); -	} -} - -  /*   *  Digi Write OOB Command   * @@ -1044,7 +1032,7 @@ static void digi_write_bulk_callback(struct urb *urb)  		}  	}  	/* wake up processes sleeping on writes immediately */ -	digi_wakeup_write(port); +	tty_port_tty_wakeup(&port->port);  	/* also queue up a wakeup at scheduler time, in case we */  	/* lost the race in write_chan(). */  	schedule_work(&priv->dp_wakeup_work); @@ -1149,53 +1137,51 @@ static void digi_close(struct usb_serial_port *port)  	if (port->serial->disconnected)  		goto exit; -	if (port->serial->dev) { -		/* FIXME: Transmit idle belongs in the wait_unti_sent path */ -		digi_transmit_idle(port, DIGI_CLOSE_TIMEOUT); - -		/* disable input flow control */ -		buf[0] = DIGI_CMD_SET_INPUT_FLOW_CONTROL; -		buf[1] = priv->dp_port_num; -		buf[2] = DIGI_DISABLE; -		buf[3] = 0; +	/* FIXME: Transmit idle belongs in the wait_unti_sent path */ +	digi_transmit_idle(port, DIGI_CLOSE_TIMEOUT); -		/* disable output flow control */ -		buf[4] = DIGI_CMD_SET_OUTPUT_FLOW_CONTROL; -		buf[5] = priv->dp_port_num; -		buf[6] = DIGI_DISABLE; -		buf[7] = 0; +	/* disable input flow control */ +	buf[0] = DIGI_CMD_SET_INPUT_FLOW_CONTROL; +	buf[1] = priv->dp_port_num; +	buf[2] = DIGI_DISABLE; +	buf[3] = 0; -		/* disable reading modem signals automatically */ -		buf[8] = DIGI_CMD_READ_INPUT_SIGNALS; -		buf[9] = priv->dp_port_num; -		buf[10] = DIGI_DISABLE; -		buf[11] = 0; +	/* disable output flow control */ +	buf[4] = DIGI_CMD_SET_OUTPUT_FLOW_CONTROL; +	buf[5] = priv->dp_port_num; +	buf[6] = DIGI_DISABLE; +	buf[7] = 0; -		/* disable receive */ -		buf[12] = DIGI_CMD_RECEIVE_ENABLE; -		buf[13] = priv->dp_port_num; -		buf[14] = DIGI_DISABLE; -		buf[15] = 0; +	/* disable reading modem signals automatically */ +	buf[8] = DIGI_CMD_READ_INPUT_SIGNALS; +	buf[9] = priv->dp_port_num; +	buf[10] = DIGI_DISABLE; +	buf[11] = 0; -		/* flush fifos */ -		buf[16] = DIGI_CMD_IFLUSH_FIFO; -		buf[17] = priv->dp_port_num; -		buf[18] = DIGI_FLUSH_TX | DIGI_FLUSH_RX; -		buf[19] = 0; +	/* disable receive */ +	buf[12] = DIGI_CMD_RECEIVE_ENABLE; +	buf[13] = priv->dp_port_num; +	buf[14] = DIGI_DISABLE; +	buf[15] = 0; -		ret = digi_write_oob_command(port, buf, 20, 0); -		if (ret != 0) -			dev_dbg(&port->dev, "digi_close: write oob failed, ret=%d\n", ret); +	/* flush fifos */ +	buf[16] = DIGI_CMD_IFLUSH_FIFO; +	buf[17] = priv->dp_port_num; +	buf[18] = DIGI_FLUSH_TX | DIGI_FLUSH_RX; +	buf[19] = 0; -		/* wait for final commands on oob port to complete */ -		prepare_to_wait(&priv->dp_flush_wait, &wait, -							TASK_INTERRUPTIBLE); -		schedule_timeout(DIGI_CLOSE_TIMEOUT); -		finish_wait(&priv->dp_flush_wait, &wait); +	ret = digi_write_oob_command(port, buf, 20, 0); +	if (ret != 0) +		dev_dbg(&port->dev, "digi_close: write oob failed, ret=%d\n", +									ret); +	/* wait for final commands on oob port to complete */ +	prepare_to_wait(&priv->dp_flush_wait, &wait, +			TASK_INTERRUPTIBLE); +	schedule_timeout(DIGI_CLOSE_TIMEOUT); +	finish_wait(&priv->dp_flush_wait, &wait); -		/* shutdown any outstanding bulk writes */ -		usb_kill_urb(port->write_urb); -	} +	/* shutdown any outstanding bulk writes */ +	usb_kill_urb(port->write_urb);  exit:  	spin_lock_irq(&priv->dp_port_lock);  	priv->dp_write_urb_in_use = 0; @@ -1252,7 +1238,6 @@ static int digi_port_init(struct usb_serial_port *port, unsigned port_num)  	spin_lock_init(&priv->dp_port_lock);  	priv->dp_port_num = port_num; -	init_waitqueue_head(&priv->dp_modem_change_wait);  	init_waitqueue_head(&priv->dp_transmit_idle_wait);  	init_waitqueue_head(&priv->dp_flush_wait);  	init_waitqueue_head(&priv->dp_close_wait); @@ -1522,7 +1507,7 @@ static int digi_read_oob_callback(struct urb *urb)  				/* port must be open to use tty struct */  				if (rts) {  					tty->hw_stopped = 0; -					digi_wakeup_write(port); +					tty_port_tty_wakeup(&port->port);  				}  			} else {  				priv->dp_modem_signals &= ~TIOCM_CTS; @@ -1543,7 +1528,6 @@ static int digi_read_oob_callback(struct urb *urb)  			else  				priv->dp_modem_signals &= ~TIOCM_CD; -			wake_up_interruptible(&priv->dp_modem_change_wait);  			spin_unlock(&priv->dp_port_lock);  		} else if (opcode == DIGI_CMD_TRANSMIT_IDLE) {  			spin_lock(&priv->dp_port_lock); diff --git a/drivers/usb/serial/f81232.c b/drivers/usb/serial/f81232.c index a172ad5c5ce..090b411d893 100644 --- a/drivers/usb/serial/f81232.c +++ b/drivers/usb/serial/f81232.c @@ -110,7 +110,7 @@ static void f81232_process_read_urb(struct urb *urb)  	line_status = priv->line_status;  	priv->line_status &= ~UART_STATE_TRANSIENT_MASK;  	spin_unlock_irqrestore(&priv->lock, flags); -	wake_up_interruptible(&port->delta_msr_wait); +	wake_up_interruptible(&port->port.delta_msr_wait);  	if (!urb->actual_length)  		return; @@ -242,8 +242,9 @@ static int f81232_carrier_raised(struct usb_serial_port *port)  	return 0;  } -static int wait_modem_info(struct usb_serial_port *port, unsigned int arg) +static int f81232_tiocmiwait(struct tty_struct *tty, unsigned long arg)  { +	struct usb_serial_port *port = tty->driver_data;  	struct f81232_private *priv = usb_get_serial_port_data(port);  	unsigned long flags;  	unsigned int prevstatus; @@ -255,7 +256,7 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)  	spin_unlock_irqrestore(&priv->lock, flags);  	while (1) { -		interruptible_sleep_on(&port->delta_msr_wait); +		interruptible_sleep_on(&port->port.delta_msr_wait);  		/* see if a signal did it */  		if (signal_pending(current))  			return -ERESTARTSYS; @@ -302,11 +303,6 @@ static int f81232_ioctl(struct tty_struct *tty,  			return -EFAULT;  		return 0; - -	case TIOCMIWAIT: -		dev_dbg(&port->dev, "%s (%d) TIOCMIWAIT\n", __func__, -			port->number); -		return wait_modem_info(port, arg);  	default:  		dev_dbg(&port->dev, "%s not supported = 0x%04x\n",  			__func__, cmd); @@ -358,6 +354,7 @@ static struct usb_serial_driver f81232_device = {  	.set_termios =		f81232_set_termios,  	.tiocmget =		f81232_tiocmget,  	.tiocmset =		f81232_tiocmset, +	.tiocmiwait =		f81232_tiocmiwait,  	.process_read_urb =	f81232_process_read_urb,  	.read_int_callback =	f81232_read_int_callback,  	.port_probe =		f81232_port_probe, diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 9886180e45f..242b5776648 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -1,7 +1,7 @@  /*   * USB FTDI SIO driver   * - *	Copyright (C) 2009 - 2010 + *	Copyright (C) 2009 - 2013   *	    Johan Hovold (jhovold@gmail.com)   *	Copyright (C) 1999 - 2001   *	    Greg Kroah-Hartman (greg@kroah.com) @@ -55,7 +55,6 @@ static __u16 vendor = FTDI_VID;  static __u16 product;  struct ftdi_private { -	struct kref kref;  	enum ftdi_chip_type chip_type;  				/* type of device, either SIO or FT8U232AM */  	int baud_base;		/* baud base clock for divisor setting */ @@ -68,7 +67,6 @@ struct ftdi_private {  				 */  	int flags;		/* some ASYNC_xxxx flags are supported */  	unsigned long last_dtr_rts;	/* saved modem control outputs */ -	struct async_icount	icount;  	char prev_status;        /* Used for TIOCMIWAIT */  	char transmit_empty;	/* If transmitter is empty or not */  	__u16 interface;	/* FT2232C, FT2232H or FT4232H port interface @@ -189,6 +187,7 @@ static struct usb_device_id id_table_combined [] = {  	{ USB_DEVICE(FTDI_VID, FTDI_OPENDCC_THROTTLE_PID) },  	{ USB_DEVICE(FTDI_VID, FTDI_OPENDCC_GATEWAY_PID) },  	{ USB_DEVICE(FTDI_VID, FTDI_OPENDCC_GBM_PID) }, +	{ USB_DEVICE(FTDI_VID, FTDI_OPENDCC_GBM_BOOST_PID) },  	{ USB_DEVICE(NEWPORT_VID, NEWPORT_AGILIS_PID) },  	{ USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_IOBOARD_PID) },  	{ USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_MINI_IOBOARD_PID) }, @@ -870,7 +869,9 @@ static struct usb_device_id id_table_combined [] = {  	{ USB_DEVICE(FTDI_VID, FTDI_DOTEC_PID) },  	{ USB_DEVICE(QIHARDWARE_VID, MILKYMISTONE_JTAGSERIAL_PID),  		.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, -	{ USB_DEVICE(ST_VID, ST_STMCLT1030_PID), +	{ USB_DEVICE(ST_VID, ST_STMCLT_2232_PID), +		.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, +	{ USB_DEVICE(ST_VID, ST_STMCLT_4232_PID),  		.driver_info = (kernel_ulong_t)&ftdi_stmclite_quirk },  	{ USB_DEVICE(FTDI_VID, FTDI_RF_R106) },  	{ USB_DEVICE(FTDI_VID, FTDI_DISTORTEC_JTAG_LOCK_PICK_PID), @@ -911,7 +912,6 @@ static int  ftdi_sio_probe(struct usb_serial *serial,  static int  ftdi_sio_port_probe(struct usb_serial_port *port);  static int  ftdi_sio_port_remove(struct usb_serial_port *port);  static int  ftdi_open(struct tty_struct *tty, struct usb_serial_port *port); -static void ftdi_close(struct usb_serial_port *port);  static void ftdi_dtr_rts(struct usb_serial_port *port, int on);  static void ftdi_process_read_urb(struct urb *urb);  static int ftdi_prepare_write_buffer(struct usb_serial_port *port, @@ -921,8 +921,6 @@ static void ftdi_set_termios(struct tty_struct *tty,  static int  ftdi_tiocmget(struct tty_struct *tty);  static int  ftdi_tiocmset(struct tty_struct *tty,  			unsigned int set, unsigned int clear); -static int ftdi_get_icount(struct tty_struct *tty, -			   struct serial_icounter_struct *icount);  static int  ftdi_ioctl(struct tty_struct *tty,  			unsigned int cmd, unsigned long arg);  static void ftdi_break_ctl(struct tty_struct *tty, int break_state); @@ -951,7 +949,6 @@ static struct usb_serial_driver ftdi_sio_device = {  	.port_probe =		ftdi_sio_port_probe,  	.port_remove =		ftdi_sio_port_remove,  	.open =			ftdi_open, -	.close =		ftdi_close,  	.dtr_rts =		ftdi_dtr_rts,  	.throttle =		usb_serial_generic_throttle,  	.unthrottle =		usb_serial_generic_unthrottle, @@ -959,7 +956,8 @@ static struct usb_serial_driver ftdi_sio_device = {  	.prepare_write_buffer =	ftdi_prepare_write_buffer,  	.tiocmget =		ftdi_tiocmget,  	.tiocmset =		ftdi_tiocmset, -	.get_icount =           ftdi_get_icount, +	.tiocmiwait =		usb_serial_generic_tiocmiwait, +	.get_icount =           usb_serial_generic_get_icount,  	.ioctl =		ftdi_ioctl,  	.set_termios =		ftdi_set_termios,  	.break_ctl =		ftdi_break_ctl, @@ -1688,7 +1686,6 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port)  		return -ENOMEM;  	} -	kref_init(&priv->kref);  	mutex_init(&priv->cfg_lock);  	priv->flags = ASYNC_LOW_LATENCY; @@ -1792,20 +1789,24 @@ static int ftdi_8u2232c_probe(struct usb_serial *serial)  }  /* - * First and second port on STMCLiteadaptors is reserved for JTAG interface - * and the forth port for pio + * First two ports on JTAG adaptors using an FT4232 such as STMicroelectronics's + * ST Micro Connect Lite are reserved for JTAG or other non-UART interfaces and + * can be accessed from userspace. + * The next two ports are enabled as UARTs by default, where port 2 is + * a conventional RS-232 UART.   */  static int ftdi_stmclite_probe(struct usb_serial *serial)  {  	struct usb_device *udev = serial->dev;  	struct usb_interface *interface = serial->interface; -	if (interface == udev->actconfig->interface[2]) -		return 0; - -	dev_info(&udev->dev, "Ignoring serial port reserved for JTAG\n"); +	if (interface == udev->actconfig->interface[0] || +	    interface == udev->actconfig->interface[1]) { +		dev_info(&udev->dev, "Ignoring serial port reserved for JTAG\n"); +		return -ENODEV; +	} -	return -ENODEV; +	return 0;  }  /* @@ -1826,22 +1827,13 @@ static int ftdi_mtxorb_hack_setup(struct usb_serial *serial)  	return 0;  } -static void ftdi_sio_priv_release(struct kref *k) -{ -	struct ftdi_private *priv = container_of(k, struct ftdi_private, kref); - -	kfree(priv); -} -  static int ftdi_sio_port_remove(struct usb_serial_port *port)  {  	struct ftdi_private *priv = usb_get_serial_port_data(port); -	wake_up_interruptible(&port->delta_msr_wait); -  	remove_sysfs_attrs(port); -	kref_put(&priv->kref, ftdi_sio_priv_release); +	kfree(priv);  	return 0;  } @@ -1851,7 +1843,6 @@ static int ftdi_open(struct tty_struct *tty, struct usb_serial_port *port)  	struct ktermios dummy;  	struct usb_device *dev = port->serial->dev;  	struct ftdi_private *priv = usb_get_serial_port_data(port); -	int result;  	/* No error checking for this (will get errors later anyway) */  	/* See ftdi_sio.h for description of what is reset */ @@ -1870,12 +1861,7 @@ static int ftdi_open(struct tty_struct *tty, struct usb_serial_port *port)  		ftdi_set_termios(tty, port, &dummy);  	} -	/* Start reading from the device */ -	result = usb_serial_generic_open(tty, port); -	if (!result) -		kref_get(&priv->kref); - -	return result; +	return usb_serial_generic_open(tty, port);  }  static void ftdi_dtr_rts(struct usb_serial_port *port, int on) @@ -1900,19 +1886,6 @@ static void ftdi_dtr_rts(struct usb_serial_port *port, int on)  		clear_mctrl(port, TIOCM_DTR | TIOCM_RTS);  } -/* - * usbserial:__serial_close  only calls ftdi_close if the point is open - * - *   This only gets called when it is the last close - */ -static void ftdi_close(struct usb_serial_port *port) -{ -	struct ftdi_private *priv = usb_get_serial_port_data(port); - -	usb_serial_generic_close(port); -	kref_put(&priv->kref, ftdi_sio_priv_release); -} -  /* The SIO requires the first byte to have:   *  B0 1   *  B1 0 @@ -1940,7 +1913,7 @@ static int ftdi_prepare_write_buffer(struct usb_serial_port *port,  			c = kfifo_out(&port->write_fifo, &buffer[i + 1], len);  			if (!c)  				break; -			priv->icount.tx += c; +			port->icount.tx += c;  			buffer[i] = (c << 2) + 1;  			count += c + 1;  		} @@ -1948,7 +1921,7 @@ static int ftdi_prepare_write_buffer(struct usb_serial_port *port,  	} else {  		count = kfifo_out_locked(&port->write_fifo, dest, size,  								&port->lock); -		priv->icount.tx += count; +		port->icount.tx += count;  	}  	return count; @@ -1977,15 +1950,15 @@ static int ftdi_process_packet(struct usb_serial_port *port,  		char diff_status = status ^ priv->prev_status;  		if (diff_status & FTDI_RS0_CTS) -			priv->icount.cts++; +			port->icount.cts++;  		if (diff_status & FTDI_RS0_DSR) -			priv->icount.dsr++; +			port->icount.dsr++;  		if (diff_status & FTDI_RS0_RI) -			priv->icount.rng++; +			port->icount.rng++;  		if (diff_status & FTDI_RS0_RLSD) -			priv->icount.dcd++; +			port->icount.dcd++; -		wake_up_interruptible(&port->delta_msr_wait); +		wake_up_interruptible(&port->port.delta_msr_wait);  		priv->prev_status = status;  	} @@ -1995,18 +1968,18 @@ static int ftdi_process_packet(struct usb_serial_port *port,  		 * over framing errors */  		if (packet[1] & FTDI_RS_BI) {  			flag = TTY_BREAK; -			priv->icount.brk++; +			port->icount.brk++;  			usb_serial_handle_break(port);  		} else if (packet[1] & FTDI_RS_PE) {  			flag = TTY_PARITY; -			priv->icount.parity++; +			port->icount.parity++;  		} else if (packet[1] & FTDI_RS_FE) {  			flag = TTY_FRAME; -			priv->icount.frame++; +			port->icount.frame++;  		}  		/* Overrun is special, not associated with a char */  		if (packet[1] & FTDI_RS_OE) { -			priv->icount.overrun++; +			port->icount.overrun++;  			tty_insert_flip_char(&port->port, 0, TTY_OVERRUN);  		}  	} @@ -2020,7 +1993,7 @@ static int ftdi_process_packet(struct usb_serial_port *port,  	len -= 2;  	if (!len)  		return 0;	/* status only */ -	priv->icount.rx += len; +	port->icount.rx += len;  	ch = packet + 2;  	if (port->port.console && port->sysrq) { @@ -2384,34 +2357,10 @@ static int ftdi_tiocmset(struct tty_struct *tty,  	return update_mctrl(port, set, clear);  } -static int ftdi_get_icount(struct tty_struct *tty, -				struct serial_icounter_struct *icount) -{ -	struct usb_serial_port *port = tty->driver_data; -	struct ftdi_private *priv = usb_get_serial_port_data(port); -	struct async_icount *ic = &priv->icount; - -	icount->cts = ic->cts; -	icount->dsr = ic->dsr; -	icount->rng = ic->rng; -	icount->dcd = ic->dcd; -	icount->tx = ic->tx; -	icount->rx = ic->rx; -	icount->frame = ic->frame; -	icount->parity = ic->parity; -	icount->overrun = ic->overrun; -	icount->brk = ic->brk; -	icount->buf_overrun = ic->buf_overrun; -	return 0; -} -  static int ftdi_ioctl(struct tty_struct *tty,  					unsigned int cmd, unsigned long arg)  {  	struct usb_serial_port *port = tty->driver_data; -	struct ftdi_private *priv = usb_get_serial_port_data(port); -	struct async_icount cnow; -	struct async_icount cprev;  	dev_dbg(&port->dev, "%s cmd 0x%04x\n", __func__, cmd); @@ -2425,35 +2374,6 @@ static int ftdi_ioctl(struct tty_struct *tty,  	case TIOCSSERIAL: /* sets serial port data */  		return set_serial_info(tty, port,  					(struct serial_struct __user *) arg); - -	/* -	 * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change -	 * - mask passed in arg for lines of interest -	 *   (use |'ed TIOCM_RNG/DSR/CD/CTS for masking) -	 * Caller should use TIOCGICOUNT to see which one it was. -	 * -	 * This code is borrowed from linux/drivers/char/serial.c -	 */ -	case TIOCMIWAIT: -		cprev = priv->icount; -		for (;;) { -			interruptible_sleep_on(&port->delta_msr_wait); -			/* see if a signal did it */ -			if (signal_pending(current)) -				return -ERESTARTSYS; - -			if (port->serial->disconnected) -				return -EIO; - -			cnow = priv->icount; -			if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || -			    ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || -			    ((arg & TIOCM_CD)  && (cnow.dcd != cprev.dcd)) || -			    ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) { -				return 0; -			} -			cprev = cnow; -		}  	case TIOCSERGETLSR:  		return get_lsr_info(port, (struct serial_struct __user *)arg);  		break; diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index e79861eeed4..98528270c43 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -74,6 +74,7 @@  #define FTDI_OPENDCC_THROTTLE_PID	0xBFDA  #define FTDI_OPENDCC_GATEWAY_PID	0xBFDB  #define FTDI_OPENDCC_GBM_PID	0xBFDC +#define FTDI_OPENDCC_GBM_BOOST_PID	0xBFDD  /* NZR SEM 16+ USB (http://www.nzr.de) */  #define FTDI_NZR_SEM_USB_PID	0xC1E0	/* NZR SEM-LOG16+ */ @@ -1150,7 +1151,8 @@   * STMicroelectonics   */  #define ST_VID			0x0483 -#define ST_STMCLT1030_PID	0x3747 /* ST Micro Connect Lite STMCLT1030 */ +#define ST_STMCLT_2232_PID	0x3746 +#define ST_STMCLT_4232_PID	0x3747  /*   * Papouch products (http://www.papouch.com/) diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c index 81caf5623ee..b110c573ea8 100644 --- a/drivers/usb/serial/garmin_gps.c +++ b/drivers/usb/serial/garmin_gps.c @@ -946,16 +946,12 @@ static int garmin_open(struct tty_struct *tty, struct usb_serial_port *port)  static void garmin_close(struct usb_serial_port *port)  { -	struct usb_serial *serial = port->serial;  	struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);  	dev_dbg(&port->dev, "%s - port %d - mode=%d state=%d flags=0x%X\n",  		__func__, port->number, garmin_data_p->mode,  		garmin_data_p->state, garmin_data_p->flags); -	if (!serial) -		return; -  	garmin_clear(garmin_data_p);  	/* shutdown our urbs */ @@ -1185,17 +1181,11 @@ static void garmin_read_bulk_callback(struct urb *urb)  {  	unsigned long flags;  	struct usb_serial_port *port = urb->context; -	struct usb_serial *serial =  port->serial;  	struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);  	unsigned char *data = urb->transfer_buffer;  	int status = urb->status;  	int retval; -	if (!serial) { -		dev_dbg(&urb->dev->dev, "%s - bad serial pointer, exiting\n", __func__); -		return; -	} -  	if (status) {  		dev_dbg(&urb->dev->dev, "%s - nonzero read bulk status received: %d\n",  			__func__, status); diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index 4c5c23f1cae..297665fdd16 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c @@ -1,7 +1,7 @@  /*   * USB Serial Converter Generic functions   * - * Copyright (C) 2010 - 2011 Johan Hovold (jhovold@gmail.com) + * Copyright (C) 2010 - 2013 Johan Hovold (jhovold@gmail.com)   * Copyright (C) 1999 - 2002 Greg Kroah-Hartman (greg@kroah.com)   *   *	This program is free software; you can redistribute it and/or @@ -45,8 +45,6 @@ struct usb_serial_driver usb_serial_generic_device = {  	},  	.id_table =		generic_device_ids,  	.num_ports =		1, -	.disconnect =		usb_serial_generic_disconnect, -	.release =		usb_serial_generic_release,  	.throttle =		usb_serial_generic_throttle,  	.unthrottle =		usb_serial_generic_unthrottle,  	.resume =		usb_serial_generic_resume, @@ -102,32 +100,23 @@ int usb_serial_generic_open(struct tty_struct *tty, struct usb_serial_port *port  }  EXPORT_SYMBOL_GPL(usb_serial_generic_open); -static void generic_cleanup(struct usb_serial_port *port) +void usb_serial_generic_close(struct usb_serial_port *port)  { -	struct usb_serial *serial = port->serial;  	unsigned long flags;  	int i; -	if (serial->dev) { -		/* shutdown any bulk transfers that might be going on */ -		if (port->bulk_out_size) { -			for (i = 0; i < ARRAY_SIZE(port->write_urbs); ++i) -				usb_kill_urb(port->write_urbs[i]); +	if (port->bulk_out_size) { +		for (i = 0; i < ARRAY_SIZE(port->write_urbs); ++i) +			usb_kill_urb(port->write_urbs[i]); -			spin_lock_irqsave(&port->lock, flags); -			kfifo_reset_out(&port->write_fifo); -			spin_unlock_irqrestore(&port->lock, flags); -		} -		if (port->bulk_in_size) { -			for (i = 0; i < ARRAY_SIZE(port->read_urbs); ++i) -				usb_kill_urb(port->read_urbs[i]); -		} +		spin_lock_irqsave(&port->lock, flags); +		kfifo_reset_out(&port->write_fifo); +		spin_unlock_irqrestore(&port->lock, flags); +	} +	if (port->bulk_in_size) { +		for (i = 0; i < ARRAY_SIZE(port->read_urbs); ++i) +			usb_kill_urb(port->read_urbs[i]);  	} -} - -void usb_serial_generic_close(struct usb_serial_port *port) -{ -	generic_cleanup(port);  }  EXPORT_SYMBOL_GPL(usb_serial_generic_close); @@ -272,8 +261,7 @@ static int usb_serial_generic_submit_read_urb(struct usb_serial_port *port,  	if (!test_and_clear_bit(index, &port->read_urbs_free))  		return 0; -	dev_dbg(&port->dev, "%s - port %d, urb %d\n", __func__, -		port->number, index); +	dev_dbg(&port->dev, "%s - urb %d\n", __func__, index);  	res = usb_submit_urb(port->read_urbs[index], mem_flags);  	if (res) { @@ -347,8 +335,8 @@ void usb_serial_generic_read_bulk_callback(struct urb *urb)  	}  	set_bit(i, &port->read_urbs_free); -	dev_dbg(&port->dev, "%s - port %d, urb %d, len %d\n", -		__func__, port->number, i, urb->actual_length); +	dev_dbg(&port->dev, "%s - urb %d, len %d\n", __func__, i, +							urb->actual_length);  	if (urb->status) {  		dev_dbg(&port->dev, "%s - non-zero urb status: %d\n", @@ -430,6 +418,91 @@ void usb_serial_generic_unthrottle(struct tty_struct *tty)  }  EXPORT_SYMBOL_GPL(usb_serial_generic_unthrottle); +static bool usb_serial_generic_msr_changed(struct tty_struct *tty, +				unsigned long arg, struct async_icount *cprev) +{ +	struct usb_serial_port *port = tty->driver_data; +	struct async_icount cnow; +	unsigned long flags; +	bool ret; + +	/* +	 * Use tty-port initialised flag to detect all hangups including the +	 * one generated at USB-device disconnect. +	 * +	 * FIXME: Remove hupping check once tty_port_hangup calls shutdown +	 *        (which clears the initialised flag) before wake up. +	 */ +	if (test_bit(TTY_HUPPING, &tty->flags)) +		return true; +	if (!test_bit(ASYNCB_INITIALIZED, &port->port.flags)) +		return true; + +	spin_lock_irqsave(&port->lock, flags); +	cnow = port->icount;				/* atomic copy*/ +	spin_unlock_irqrestore(&port->lock, flags); + +	ret =	((arg & TIOCM_RNG) && (cnow.rng != cprev->rng)) || +		((arg & TIOCM_DSR) && (cnow.dsr != cprev->dsr)) || +		((arg & TIOCM_CD)  && (cnow.dcd != cprev->dcd)) || +		((arg & TIOCM_CTS) && (cnow.cts != cprev->cts)); + +	*cprev = cnow; + +	return ret; +} + +int usb_serial_generic_tiocmiwait(struct tty_struct *tty, unsigned long arg) +{ +	struct usb_serial_port *port = tty->driver_data; +	struct async_icount cnow; +	unsigned long flags; +	int ret; + +	spin_lock_irqsave(&port->lock, flags); +	cnow = port->icount;				/* atomic copy */ +	spin_unlock_irqrestore(&port->lock, flags); + +	ret = wait_event_interruptible(port->port.delta_msr_wait, +			usb_serial_generic_msr_changed(tty, arg, &cnow)); +	if (!ret) { +		if (test_bit(TTY_HUPPING, &tty->flags)) +			ret = -EIO; +		if (!test_bit(ASYNCB_INITIALIZED, &port->port.flags)) +			ret = -EIO; +	} + +	return ret; +} +EXPORT_SYMBOL_GPL(usb_serial_generic_tiocmiwait); + +int usb_serial_generic_get_icount(struct tty_struct *tty, +					struct serial_icounter_struct *icount) +{ +	struct usb_serial_port *port = tty->driver_data; +	struct async_icount cnow; +	unsigned long flags; + +	spin_lock_irqsave(&port->lock, flags); +	cnow = port->icount;				/* atomic copy */ +	spin_unlock_irqrestore(&port->lock, flags); + +	icount->cts = cnow.cts; +	icount->dsr = cnow.dsr; +	icount->rng = cnow.rng; +	icount->dcd = cnow.dcd; +	icount->tx = cnow.tx; +	icount->rx = cnow.rx; +	icount->frame = cnow.frame; +	icount->parity = cnow.parity; +	icount->overrun = cnow.overrun; +	icount->brk = cnow.brk; +	icount->buf_overrun = cnow.buf_overrun; + +	return 0; +} +EXPORT_SYMBOL_GPL(usb_serial_generic_get_icount); +  #ifdef CONFIG_MAGIC_SYSRQ  int usb_serial_handle_sysrq_char(struct usb_serial_port *port, unsigned int ch)  { @@ -473,8 +546,7 @@ void usb_serial_handle_dcd_change(struct usb_serial_port *usb_port,  {  	struct tty_port *port = &usb_port->port; -	dev_dbg(&usb_port->dev, "%s - port %d, status %d\n", __func__, -		usb_port->number, status); +	dev_dbg(&usb_port->dev, "%s - status %d\n", __func__, status);  	if (status)  		wake_up_interruptible(&port->open_wait); @@ -510,17 +582,3 @@ int usb_serial_generic_resume(struct usb_serial *serial)  	return c ? -EIO : 0;  }  EXPORT_SYMBOL_GPL(usb_serial_generic_resume); - -void usb_serial_generic_disconnect(struct usb_serial *serial) -{ -	int i; - -	/* stop reads and writes on all ports */ -	for (i = 0; i < serial->num_ports; ++i) -		generic_cleanup(serial->port[i]); -} -EXPORT_SYMBOL_GPL(usb_serial_generic_disconnect); - -void usb_serial_generic_release(struct usb_serial *serial) -{ -} diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c index efd8b978128..1477e859347 100644 --- a/drivers/usb/serial/io_edgeport.c +++ b/drivers/usb/serial/io_edgeport.c @@ -111,7 +111,6 @@ struct edgeport_port {  	wait_queue_head_t	wait_open;		/* for handling sleeping while waiting for open to finish */  	wait_queue_head_t	wait_command;		/* for handling sleeping while waiting for command to finish */ -	struct async_icount	icount;  	struct usb_serial_port	*port;			/* loop back to the owner of this object */  }; @@ -215,8 +214,6 @@ static void edge_break(struct tty_struct *tty, int break_state);  static int  edge_tiocmget(struct tty_struct *tty);  static int  edge_tiocmset(struct tty_struct *tty,  					unsigned int set, unsigned int clear); -static int  edge_get_icount(struct tty_struct *tty, -				struct serial_icounter_struct *icount);  static int  edge_startup(struct usb_serial *serial);  static void edge_disconnect(struct usb_serial *serial);  static void edge_release(struct usb_serial *serial); @@ -564,7 +561,6 @@ static void edge_interrupt_callback(struct urb *urb)  	struct device *dev;  	struct edgeport_port *edge_port;  	struct usb_serial_port *port; -	struct tty_struct *tty;  	unsigned char *data = urb->transfer_buffer;  	int length = urb->actual_length;  	int bytes_avail; @@ -643,12 +639,7 @@ static void edge_interrupt_callback(struct urb *urb)  					/* tell the tty driver that something  					   has changed */ -					tty = tty_port_tty_get( -						&edge_port->port->port); -					if (tty) { -						tty_wakeup(tty); -						tty_kref_put(tty); -					} +					tty_port_tty_wakeup(&edge_port->port->port);  					/* Since we have more credit, check  					   if more data can be sent */  					send_more_port_data(edge_serial, @@ -737,7 +728,6 @@ static void edge_bulk_in_callback(struct urb *urb)  static void edge_bulk_out_data_callback(struct urb *urb)  {  	struct edgeport_port *edge_port = urb->context; -	struct tty_struct *tty;  	int status = urb->status;  	if (status) { @@ -746,14 +736,8 @@ static void edge_bulk_out_data_callback(struct urb *urb)  			__func__, status);  	} -	tty = tty_port_tty_get(&edge_port->port->port); - -	if (tty && edge_port->open) { -		/* let the tty driver wakeup if it has a special -		   write_wakeup function */ -		tty_wakeup(tty); -	} -	tty_kref_put(tty); +	if (edge_port->open) +		tty_port_tty_wakeup(&edge_port->port->port);  	/* Release the Write URB */  	edge_port->write_in_progress = false; @@ -772,7 +756,6 @@ static void edge_bulk_out_data_callback(struct urb *urb)  static void edge_bulk_out_cmd_callback(struct urb *urb)  {  	struct edgeport_port *edge_port = urb->context; -	struct tty_struct *tty;  	int status = urb->status;  	atomic_dec(&CmdUrbs); @@ -793,13 +776,9 @@ static void edge_bulk_out_cmd_callback(struct urb *urb)  		return;  	} -	/* Get pointer to tty */ -	tty = tty_port_tty_get(&edge_port->port->port); -  	/* tell the tty driver that something has changed */ -	if (tty && edge_port->open) -		tty_wakeup(tty); -	tty_kref_put(tty); +	if (edge_port->open) +		tty_port_tty_wakeup(&edge_port->port->port);  	/* we have completed the command */  	edge_port->commandPending = false; @@ -885,9 +864,6 @@ static int edge_open(struct tty_struct *tty, struct usb_serial_port *port)  	init_waitqueue_head(&edge_port->wait_chase);  	init_waitqueue_head(&edge_port->wait_command); -	/* initialize our icount structure */ -	memset(&(edge_port->icount), 0x00, sizeof(edge_port->icount)); -  	/* initialize our port settings */  	edge_port->txCredits = 0;	/* Can't send any data yet */  	/* Must always set this bit to enable ints! */ @@ -1314,7 +1290,7 @@ static void send_more_port_data(struct edgeport_serial *edge_serial,  	/* decrement the number of credits we have by the number we just sent */  	edge_port->txCredits -= count; -	edge_port->icount.tx += count; +	edge_port->port->icount.tx += count;  	status = usb_submit_urb(urb, GFP_ATOMIC);  	if (status) { @@ -1326,7 +1302,7 @@ static void send_more_port_data(struct edgeport_serial *edge_serial,  		/* revert the credits as something bad happened. */  		edge_port->txCredits += count; -		edge_port->icount.tx -= count; +		edge_port->port->icount.tx -= count;  	}  	dev_dbg(dev, "%s wrote %d byte(s) TxCredit %d, Fifo %d\n",  		__func__, count, edge_port->txCredits, fifo->count); @@ -1588,31 +1564,6 @@ static int edge_tiocmget(struct tty_struct *tty)  	return result;  } -static int edge_get_icount(struct tty_struct *tty, -				struct serial_icounter_struct *icount) -{ -	struct usb_serial_port *port = tty->driver_data; -	struct edgeport_port *edge_port = usb_get_serial_port_data(port); -	struct async_icount cnow; -	cnow = edge_port->icount; - -	icount->cts = cnow.cts; -	icount->dsr = cnow.dsr; -	icount->rng = cnow.rng; -	icount->dcd = cnow.dcd; -	icount->rx = cnow.rx; -	icount->tx = cnow.tx; -	icount->frame = cnow.frame; -	icount->overrun = cnow.overrun; -	icount->parity = cnow.parity; -	icount->brk = cnow.brk; -	icount->buf_overrun = cnow.buf_overrun; - -	dev_dbg(&port->dev, "%s (%d) TIOCGICOUNT RX=%d, TX=%d\n", __func__, -		port->number, icount->rx, icount->tx); -	return 0; -} -  static int get_serial_info(struct edgeport_port *edge_port,  				struct serial_struct __user *retinfo)  { @@ -1649,8 +1600,6 @@ static int edge_ioctl(struct tty_struct *tty,  	struct usb_serial_port *port = tty->driver_data;  	DEFINE_WAIT(wait);  	struct edgeport_port *edge_port = usb_get_serial_port_data(port); -	struct async_icount cnow; -	struct async_icount cprev;  	dev_dbg(&port->dev, "%s - port %d, cmd = 0x%x\n", __func__, port->number, cmd); @@ -1662,37 +1611,6 @@ static int edge_ioctl(struct tty_struct *tty,  	case TIOCGSERIAL:  		dev_dbg(&port->dev, "%s (%d) TIOCGSERIAL\n", __func__,  port->number);  		return get_serial_info(edge_port, (struct serial_struct __user *) arg); - -	case TIOCMIWAIT: -		dev_dbg(&port->dev, "%s (%d) TIOCMIWAIT\n", __func__,  port->number); -		cprev = edge_port->icount; -		while (1) { -			prepare_to_wait(&port->delta_msr_wait, -						&wait, TASK_INTERRUPTIBLE); -			schedule(); -			finish_wait(&port->delta_msr_wait, &wait); -			/* see if a signal did it */ -			if (signal_pending(current)) -				return -ERESTARTSYS; - -			if (port->serial->disconnected) -				return -EIO; - -			cnow = edge_port->icount; -			if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && -			    cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) -				return -EIO; /* no change => error */ -			if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || -			    ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || -			    ((arg & TIOCM_CD)  && (cnow.dcd != cprev.dcd)) || -			    ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) { -				return 0; -			} -			cprev = cnow; -		} -		/* NOTREACHED */ -		break; -  	}  	return -ENOIOCTLCMD;  } @@ -1866,7 +1784,7 @@ static void process_rcvd_data(struct edgeport_serial *edge_serial,  						edge_serial->rxPort);  					edge_tty_recv(edge_port->port, buffer,  							rxLen); -					edge_port->icount.rx += rxLen; +					edge_port->port->icount.rx += rxLen;  				}  				buffer += rxLen;  			} @@ -2042,7 +1960,7 @@ static void handle_new_msr(struct edgeport_port *edge_port, __u8 newMsr)  	if (newMsr & (EDGEPORT_MSR_DELTA_CTS | EDGEPORT_MSR_DELTA_DSR |  			EDGEPORT_MSR_DELTA_RI | EDGEPORT_MSR_DELTA_CD)) { -		icount = &edge_port->icount; +		icount = &edge_port->port->icount;  		/* update input line counters */  		if (newMsr & EDGEPORT_MSR_DELTA_CTS) @@ -2053,7 +1971,7 @@ static void handle_new_msr(struct edgeport_port *edge_port, __u8 newMsr)  			icount->dcd++;  		if (newMsr & EDGEPORT_MSR_DELTA_RI)  			icount->rng++; -		wake_up_interruptible(&edge_port->port->delta_msr_wait); +		wake_up_interruptible(&edge_port->port->port.delta_msr_wait);  	}  	/* Save the new modem status */ @@ -2088,7 +2006,7 @@ static void handle_new_lsr(struct edgeport_port *edge_port, __u8 lsrData,  		edge_tty_recv(edge_port->port, &data, 1);  	/* update input line counters */ -	icount = &edge_port->icount; +	icount = &edge_port->port->icount;  	if (newLsr & LSR_BREAK)  		icount->brk++;  	if (newLsr & LSR_OVER_ERR) diff --git a/drivers/usb/serial/io_tables.h b/drivers/usb/serial/io_tables.h index 1511dd0ad32..ae5fac5656c 100644 --- a/drivers/usb/serial/io_tables.h +++ b/drivers/usb/serial/io_tables.h @@ -116,7 +116,8 @@ static struct usb_serial_driver edgeport_2port_device = {  	.set_termios		= edge_set_termios,  	.tiocmget		= edge_tiocmget,  	.tiocmset		= edge_tiocmset, -	.get_icount		= edge_get_icount, +	.tiocmiwait		= usb_serial_generic_tiocmiwait, +	.get_icount		= usb_serial_generic_get_icount,  	.write			= edge_write,  	.write_room		= edge_write_room,  	.chars_in_buffer	= edge_chars_in_buffer, @@ -147,7 +148,8 @@ static struct usb_serial_driver edgeport_4port_device = {  	.set_termios		= edge_set_termios,  	.tiocmget		= edge_tiocmget,  	.tiocmset		= edge_tiocmset, -	.get_icount		= edge_get_icount, +	.tiocmiwait		= usb_serial_generic_tiocmiwait, +	.get_icount		= usb_serial_generic_get_icount,  	.write			= edge_write,  	.write_room		= edge_write_room,  	.chars_in_buffer	= edge_chars_in_buffer, @@ -178,7 +180,8 @@ static struct usb_serial_driver edgeport_8port_device = {  	.set_termios		= edge_set_termios,  	.tiocmget		= edge_tiocmget,  	.tiocmset		= edge_tiocmset, -	.get_icount		= edge_get_icount, +	.tiocmiwait		= usb_serial_generic_tiocmiwait, +	.get_icount		= usb_serial_generic_get_icount,  	.write			= edge_write,  	.write_room		= edge_write_room,  	.chars_in_buffer	= edge_chars_in_buffer, @@ -209,7 +212,8 @@ static struct usb_serial_driver epic_device = {  	.set_termios		= edge_set_termios,  	.tiocmget		= edge_tiocmget,  	.tiocmset		= edge_tiocmset, -	.get_icount		= edge_get_icount, +	.tiocmiwait		= usb_serial_generic_tiocmiwait, +	.get_icount		= usb_serial_generic_get_icount,  	.write			= edge_write,  	.write_room		= edge_write_room,  	.chars_in_buffer	= edge_chars_in_buffer, diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c index 7777172206d..158bf4bc29c 100644 --- a/drivers/usb/serial/io_ti.c +++ b/drivers/usb/serial/io_ti.c @@ -86,7 +86,7 @@ struct edgeport_port {  	int baud_rate;  	int close_pending;  	int lsr_event; -	struct async_icount	icount; +  	struct edgeport_serial	*edge_serial;  	struct usb_serial_port	*port;  	__u8 bUartMode;		/* Port type, 0: RS232, etc. */ @@ -206,7 +206,7 @@ static int restart_read(struct edgeport_port *edge_port);  static void edge_set_termios(struct tty_struct *tty,  		struct usb_serial_port *port, struct ktermios *old_termios); -static void edge_send(struct tty_struct *tty); +static void edge_send(struct usb_serial_port *port, struct tty_struct *tty);  /* sysfs attributes */  static int edge_create_sysfs_attrs(struct usb_serial_port *port); @@ -1445,7 +1445,7 @@ static void handle_new_msr(struct edgeport_port *edge_port, __u8 msr)  	if (msr & (EDGEPORT_MSR_DELTA_CTS | EDGEPORT_MSR_DELTA_DSR |  			EDGEPORT_MSR_DELTA_RI | EDGEPORT_MSR_DELTA_CD)) { -		icount = &edge_port->icount; +		icount = &edge_port->port->icount;  		/* update input line counters */  		if (msr & EDGEPORT_MSR_DELTA_CTS) @@ -1456,7 +1456,7 @@ static void handle_new_msr(struct edgeport_port *edge_port, __u8 msr)  			icount->dcd++;  		if (msr & EDGEPORT_MSR_DELTA_RI)  			icount->rng++; -		wake_up_interruptible(&edge_port->port->delta_msr_wait); +		wake_up_interruptible(&edge_port->port->port.delta_msr_wait);  	}  	/* Save the new modem status */ @@ -1498,7 +1498,7 @@ static void handle_new_lsr(struct edgeport_port *edge_port, int lsr_data,  		edge_tty_recv(edge_port->port, &data, 1);  	/* update input line counters */ -	icount = &edge_port->icount; +	icount = &edge_port->port->icount;  	if (new_lsr & LSR_BREAK)  		icount->brk++;  	if (new_lsr & LSR_OVER_ERR) @@ -1657,7 +1657,7 @@ static void edge_bulk_in_callback(struct urb *urb)  		else  			edge_tty_recv(edge_port->port, data,  					urb->actual_length); -		edge_port->icount.rx += urb->actual_length; +		edge_port->port->icount.rx += urb->actual_length;  	}  exit: @@ -1712,7 +1712,7 @@ static void edge_bulk_out_callback(struct urb *urb)  	/* send any buffered data */  	tty = tty_port_tty_get(&port->port); -	edge_send(tty); +	edge_send(port, tty);  	tty_kref_put(tty);  } @@ -1750,8 +1750,6 @@ static int edge_open(struct tty_struct *tty, struct usb_serial_port *port)  	dev = port->serial->dev; -	memset(&(edge_port->icount), 0x00, sizeof(edge_port->icount)); -  	/* turn off loopback */  	status = ti_do_config(edge_port, UMPC_SET_CLR_LOOPBACK, 0);  	if (status) { @@ -1909,21 +1907,10 @@ static void edge_close(struct usb_serial_port *port)  	kfifo_reset_out(&edge_port->write_fifo);  	spin_unlock_irqrestore(&edge_port->ep_lock, flags); -	/* assuming we can still talk to the device, -	 * send a close port command to it */  	dev_dbg(&port->dev, "%s - send umpc_close_port\n", __func__);  	port_number = port->number - port->serial->minor; - -	mutex_lock(&serial->disc_mutex); -	if (!serial->disconnected) { -		send_cmd(serial->dev, -				     UMPC_CLOSE_PORT, -				     (__u8)(UMPM_UART1_PORT + port_number), -				     0, -				     NULL, -				     0); -	} -	mutex_unlock(&serial->disc_mutex); +	send_cmd(serial->dev, UMPC_CLOSE_PORT, +		     (__u8)(UMPM_UART1_PORT + port_number), 0, NULL, 0);  	mutex_lock(&edge_serial->es_lock);  	--edge_port->edge_serial->num_ports_open; @@ -1953,14 +1940,13 @@ static int edge_write(struct tty_struct *tty, struct usb_serial_port *port,  	count = kfifo_in_locked(&edge_port->write_fifo, data, count,  							&edge_port->ep_lock); -	edge_send(tty); +	edge_send(port, tty);  	return count;  } -static void edge_send(struct tty_struct *tty) +static void edge_send(struct usb_serial_port *port, struct tty_struct *tty)  { -	struct usb_serial_port *port = tty->driver_data;  	int count, result;  	struct edgeport_port *edge_port = usb_get_serial_port_data(port);  	unsigned long flags; @@ -1999,7 +1985,7 @@ static void edge_send(struct tty_struct *tty)  		edge_port->ep_write_urb_in_use = 0;  		/* TODO: reschedule edge_send */  	} else -		edge_port->icount.tx += count; +		edge_port->port->icount.tx += count;  	/* wakeup any process waiting for writes to complete */  	/* there is now more room in the buffer for new writes */ @@ -2360,27 +2346,6 @@ static int edge_tiocmget(struct tty_struct *tty)  	return result;  } -static int edge_get_icount(struct tty_struct *tty, -				struct serial_icounter_struct *icount) -{ -	struct usb_serial_port *port = tty->driver_data; -	struct edgeport_port *edge_port = usb_get_serial_port_data(port); -	struct async_icount *ic = &edge_port->icount; - -	icount->cts = ic->cts; -	icount->dsr = ic->dsr; -	icount->rng = ic->rng; -	icount->dcd = ic->dcd; -	icount->tx = ic->tx; -        icount->rx = ic->rx; -        icount->frame = ic->frame; -        icount->parity = ic->parity; -        icount->overrun = ic->overrun; -        icount->brk = ic->brk; -        icount->buf_overrun = ic->buf_overrun; -	return 0; -} -  static int get_serial_info(struct edgeport_port *edge_port,  				struct serial_struct __user *retinfo)  { @@ -2392,7 +2357,7 @@ static int get_serial_info(struct edgeport_port *edge_port,  	cwait = edge_port->port->port.closing_wait;  	if (cwait != ASYNC_CLOSING_WAIT_NONE) -		cwait = jiffies_to_msecs(closing_wait) / 10; +		cwait = jiffies_to_msecs(cwait) / 10;  	memset(&tmp, 0, sizeof(tmp)); @@ -2416,8 +2381,6 @@ static int edge_ioctl(struct tty_struct *tty,  {  	struct usb_serial_port *port = tty->driver_data;  	struct edgeport_port *edge_port = usb_get_serial_port_data(port); -	struct async_icount cnow; -	struct async_icount cprev;  	dev_dbg(&port->dev, "%s - port %d, cmd = 0x%x\n", __func__, port->number, cmd); @@ -2426,32 +2389,6 @@ static int edge_ioctl(struct tty_struct *tty,  		dev_dbg(&port->dev, "%s - TIOCGSERIAL\n", __func__);  		return get_serial_info(edge_port,  				(struct serial_struct __user *) arg); -	case TIOCMIWAIT: -		dev_dbg(&port->dev, "%s - TIOCMIWAIT\n", __func__); -		cprev = edge_port->icount; -		while (1) { -			interruptible_sleep_on(&port->delta_msr_wait); -			/* see if a signal did it */ -			if (signal_pending(current)) -				return -ERESTARTSYS; - -			if (port->serial->disconnected) -				return -EIO; - -			cnow = edge_port->icount; -			if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && -			    cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) -				return -EIO; /* no change => error */ -			if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || -			    ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || -			    ((arg & TIOCM_CD)  && (cnow.dcd != cprev.dcd)) || -			    ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) { -				return 0; -			} -			cprev = cnow; -		} -		/* not reached */ -		break;  	}  	return -ENOIOCTLCMD;  } @@ -2463,8 +2400,6 @@ static void edge_break(struct tty_struct *tty, int break_state)  	int status;  	int bv = 0;	/* Off */ -	tty_wait_until_sent(tty, 0); -  	if (break_state == -1)  		bv = 1;	/* On */  	status = ti_do_config(edge_port, UMPC_SET_CLR_BREAK, bv); @@ -2546,7 +2481,6 @@ static int edge_port_remove(struct usb_serial_port *port)  	struct edgeport_port *edge_port;  	edge_port = usb_get_serial_port_data(port); -  	edge_remove_sysfs_attrs(port);  	kfifo_free(&edge_port->write_fifo);  	kfree(edge_port); @@ -2618,7 +2552,8 @@ static struct usb_serial_driver edgeport_1port_device = {  	.set_termios		= edge_set_termios,  	.tiocmget		= edge_tiocmget,  	.tiocmset		= edge_tiocmset, -	.get_icount		= edge_get_icount, +	.tiocmiwait		= usb_serial_generic_tiocmiwait, +	.get_icount		= usb_serial_generic_get_icount,  	.write			= edge_write,  	.write_room		= edge_write_room,  	.chars_in_buffer	= edge_chars_in_buffer, @@ -2649,7 +2584,8 @@ static struct usb_serial_driver edgeport_2port_device = {  	.set_termios		= edge_set_termios,  	.tiocmget		= edge_tiocmget,  	.tiocmset		= edge_tiocmset, -	.get_icount		= edge_get_icount, +	.tiocmiwait		= usb_serial_generic_tiocmiwait, +	.get_icount		= usb_serial_generic_get_icount,  	.write			= edge_write,  	.write_room		= edge_write_room,  	.chars_in_buffer	= edge_chars_in_buffer, diff --git a/drivers/usb/serial/iuu_phoenix.c b/drivers/usb/serial/iuu_phoenix.c index ff77027160a..9d74c278b7b 100644 --- a/drivers/usb/serial/iuu_phoenix.c +++ b/drivers/usb/serial/iuu_phoenix.c @@ -55,7 +55,6 @@ static void read_rxcmd_callback(struct urb *urb);  struct iuu_private {  	spinlock_t lock;	/* store irq state */ -	wait_queue_head_t delta_msr_wait;  	u8 line_status;  	int tiostatus;		/* store IUART SIGNAL for tiocmget call */  	u8 reset;		/* if 1 reset is needed */ @@ -94,7 +93,6 @@ static int iuu_port_probe(struct usb_serial_port *port)  	priv->vcc = vcc_default;  	spin_lock_init(&priv->lock); -	init_waitqueue_head(&priv->delta_msr_wait);  	usb_set_serial_port_data(port, priv); @@ -944,22 +942,13 @@ static void iuu_set_termios(struct tty_struct *tty,  static void iuu_close(struct usb_serial_port *port)  {  	/* iuu_led (port,255,0,0,0); */ -	struct usb_serial *serial; - -	serial = port->serial; -	if (!serial) -		return;  	iuu_uart_off(port); -	if (serial->dev) { -		/* free writebuf */ -		/* shutdown our urbs */ -		dev_dbg(&port->dev, "%s - shutting down urbs\n", __func__); -		usb_kill_urb(port->write_urb); -		usb_kill_urb(port->read_urb); -		usb_kill_urb(port->interrupt_in_urb); -		iuu_led(port, 0, 0, 0xF000, 0xFF); -	} + +	usb_kill_urb(port->write_urb); +	usb_kill_urb(port->read_urb); + +	iuu_led(port, 0, 0, 0xF000, 0xFF);  }  static void iuu_init_termios(struct tty_struct *tty) diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c index 1fd1935c831..eb30d7b01f3 100644 --- a/drivers/usb/serial/keyspan.c +++ b/drivers/usb/serial/keyspan.c @@ -378,7 +378,6 @@ static void	usa26_instat_callback(struct urb *urb)  	struct usb_serial			*serial;  	struct usb_serial_port			*port;  	struct keyspan_port_private	 	*p_priv; -	struct tty_struct			*tty;  	int old_dcd_state, err;  	int status = urb->status; @@ -421,12 +420,8 @@ static void	usa26_instat_callback(struct urb *urb)  	p_priv->dcd_state = ((msg->gpia_dcd) ? 1 : 0);  	p_priv->ri_state = ((msg->ri) ? 1 : 0); -	if (old_dcd_state != p_priv->dcd_state) { -		tty = tty_port_tty_get(&port->port); -		if (tty && !C_CLOCAL(tty)) -			tty_hangup(tty); -		tty_kref_put(tty); -	} +	if (old_dcd_state != p_priv->dcd_state) +		tty_port_tty_hangup(&port->port, true);  	/* Resubmit urb so we continue receiving */  	err = usb_submit_urb(urb, GFP_ATOMIC); @@ -510,7 +505,6 @@ static void	usa28_instat_callback(struct urb *urb)  	struct usb_serial			*serial;  	struct usb_serial_port			*port;  	struct keyspan_port_private	 	*p_priv; -	struct tty_struct			*tty;  	int old_dcd_state;  	int status = urb->status; @@ -551,12 +545,8 @@ static void	usa28_instat_callback(struct urb *urb)  	p_priv->dcd_state = ((msg->dcd) ? 1 : 0);  	p_priv->ri_state = ((msg->ri) ? 1 : 0); -	if (old_dcd_state != p_priv->dcd_state && old_dcd_state) { -		tty = tty_port_tty_get(&port->port); -		if (tty && !C_CLOCAL(tty)) -			tty_hangup(tty); -		tty_kref_put(tty); -	} +	if (old_dcd_state != p_priv->dcd_state && old_dcd_state) +		tty_port_tty_hangup(&port->port, true);  		/* Resubmit urb so we continue receiving */  	err = usb_submit_urb(urb, GFP_ATOMIC); @@ -642,12 +632,8 @@ static void	usa49_instat_callback(struct urb *urb)  	p_priv->dcd_state = ((msg->dcd) ? 1 : 0);  	p_priv->ri_state = ((msg->ri) ? 1 : 0); -	if (old_dcd_state != p_priv->dcd_state && old_dcd_state) { -		struct tty_struct *tty = tty_port_tty_get(&port->port); -		if (tty && !C_CLOCAL(tty)) -			tty_hangup(tty); -		tty_kref_put(tty); -	} +	if (old_dcd_state != p_priv->dcd_state && old_dcd_state) +		tty_port_tty_hangup(&port->port, true);  	/* Resubmit urb so we continue receiving */  	err = usb_submit_urb(urb, GFP_ATOMIC); @@ -726,45 +712,45 @@ static void usa49wg_indat_callback(struct urb *urb)  	i = 0;  	len = 0; -	if (urb->actual_length) { -		while (i < urb->actual_length) { +	while (i < urb->actual_length) { -			/* Check port number from message*/ -			if (data[i] >= serial->num_ports) { -				dev_dbg(&urb->dev->dev, "%s - Unexpected port number %d\n", -					__func__, data[i]); -				return; -			} -			port = serial->port[data[i++]]; -			len = data[i++]; +		/* Check port number from message */ +		if (data[i] >= serial->num_ports) { +			dev_dbg(&urb->dev->dev, "%s - Unexpected port number %d\n", +				__func__, data[i]); +			return; +		} +		port = serial->port[data[i++]]; +		len = data[i++]; -			/* 0x80 bit is error flag */ -			if ((data[i] & 0x80) == 0) { -				/* no error on any byte */ -				i++; -				for (x = 1; x < len ; ++x) -					tty_insert_flip_char(&port->port, -							data[i++], 0); -			} else { -				/* -				 * some bytes had errors, every byte has status -				 */ -				for (x = 0; x + 1 < len; x += 2) { -					int stat = data[i], flag = 0; -					if (stat & RXERROR_OVERRUN) -						flag |= TTY_OVERRUN; -					if (stat & RXERROR_FRAMING) -						flag |= TTY_FRAME; -					if (stat & RXERROR_PARITY) -						flag |= TTY_PARITY; -					/* XXX should handle break (0x10) */ -					tty_insert_flip_char(&port->port, -							data[i+1], flag); -					i += 2; -				} +		/* 0x80 bit is error flag */ +		if ((data[i] & 0x80) == 0) { +			/* no error on any byte */ +			i++; +			for (x = 1; x < len && i < urb->actual_length; ++x) +				tty_insert_flip_char(&port->port, +						data[i++], 0); +		} else { +			/* +			 * some bytes had errors, every byte has status +			 */ +			for (x = 0; x + 1 < len && +				    i + 1 < urb->actual_length; x += 2) { +				int stat = data[i], flag = 0; + +				if (stat & RXERROR_OVERRUN) +					flag |= TTY_OVERRUN; +				if (stat & RXERROR_FRAMING) +					flag |= TTY_FRAME; +				if (stat & RXERROR_PARITY) +					flag |= TTY_PARITY; +				/* XXX should handle break (0x10) */ +				tty_insert_flip_char(&port->port, data[i+1], +						     flag); +				i += 2;  			} -			tty_flip_buffer_push(&port->port);  		} +		tty_flip_buffer_push(&port->port);  	}  	/* Resubmit urb so we continue receiving */ @@ -851,7 +837,6 @@ static void	usa90_instat_callback(struct urb *urb)  	struct usb_serial			*serial;  	struct usb_serial_port			*port;  	struct keyspan_port_private	 	*p_priv; -	struct tty_struct			*tty;  	int old_dcd_state, err;  	int status = urb->status; @@ -880,12 +865,8 @@ static void	usa90_instat_callback(struct urb *urb)  	p_priv->dcd_state = ((msg->dcd) ? 1 : 0);  	p_priv->ri_state = ((msg->ri) ? 1 : 0); -	if (old_dcd_state != p_priv->dcd_state && old_dcd_state) { -		tty = tty_port_tty_get(&port->port); -		if (tty && !C_CLOCAL(tty)) -			tty_hangup(tty); -		tty_kref_put(tty); -	} +	if (old_dcd_state != p_priv->dcd_state && old_dcd_state) +		tty_port_tty_hangup(&port->port, true);  	/* Resubmit urb so we continue receiving */  	err = usb_submit_urb(urb, GFP_ATOMIC); @@ -953,12 +934,8 @@ static void	usa67_instat_callback(struct urb *urb)  	p_priv->cts_state = ((msg->hskia_cts) ? 1 : 0);  	p_priv->dcd_state = ((msg->gpia_dcd) ? 1 : 0); -	if (old_dcd_state != p_priv->dcd_state && old_dcd_state) { -		struct tty_struct *tty = tty_port_tty_get(&port->port); -		if (tty && !C_CLOCAL(tty)) -			tty_hangup(tty); -		tty_kref_put(tty); -	} +	if (old_dcd_state != p_priv->dcd_state && old_dcd_state) +		tty_port_tty_hangup(&port->port, true);  	/* Resubmit urb so we continue receiving */  	err = usb_submit_urb(urb, GFP_ATOMIC); @@ -1115,7 +1092,6 @@ static void keyspan_dtr_rts(struct usb_serial_port *port, int on)  static void keyspan_close(struct usb_serial_port *port)  {  	int			i; -	struct usb_serial	*serial = port->serial;  	struct keyspan_port_private 	*p_priv;  	p_priv = usb_get_serial_port_data(port); @@ -1123,28 +1099,17 @@ static void keyspan_close(struct usb_serial_port *port)  	p_priv->rts_state = 0;  	p_priv->dtr_state = 0; -	if (serial->dev) { -		keyspan_send_setup(port, 2); -		/* pilot-xfer seems to work best with this delay */ -		mdelay(100); -		/* keyspan_set_termios(port, NULL); */ -	} - -	/*while (p_priv->outcont_urb->status == -EINPROGRESS) { -		dev_dbg(&port->dev, "%s - urb in progress\n", __func__); -	}*/ +	keyspan_send_setup(port, 2); +	/* pilot-xfer seems to work best with this delay */ +	mdelay(100);  	p_priv->out_flip = 0;  	p_priv->in_flip = 0; -	if (serial->dev) { -		/* Stop reading/writing urbs */ -		stop_urb(p_priv->inack_urb); -		/* stop_urb(p_priv->outcont_urb); */ -		for (i = 0; i < 2; i++) { -			stop_urb(p_priv->in_urbs[i]); -			stop_urb(p_priv->out_urbs[i]); -		} +	stop_urb(p_priv->inack_urb); +	for (i = 0; i < 2; i++) { +		stop_urb(p_priv->in_urbs[i]); +		stop_urb(p_priv->out_urbs[i]);  	}  } diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c index 3b17d5d13dc..5f1d382e55c 100644 --- a/drivers/usb/serial/keyspan_pda.c +++ b/drivers/usb/serial/keyspan_pda.c @@ -104,10 +104,8 @@ static void keyspan_pda_wakeup_write(struct work_struct *work)  	struct keyspan_pda_private *priv =  		container_of(work, struct keyspan_pda_private, wakeup_work);  	struct usb_serial_port *port = priv->port; -	struct tty_struct *tty = tty_port_tty_get(&port->port); -	if (tty) -		tty_wakeup(tty); -	tty_kref_put(tty); + +	tty_port_tty_wakeup(&port->port);  }  static void keyspan_pda_request_unthrottle(struct work_struct *work) @@ -595,12 +593,10 @@ static void keyspan_pda_dtr_rts(struct usb_serial_port *port, int on)  {  	struct usb_serial *serial = port->serial; -	if (serial->dev) { -		if (on) -			keyspan_pda_set_modem_info(serial, (1<<7) | (1<< 2)); -		else -			keyspan_pda_set_modem_info(serial, 0); -	} +	if (on) +		keyspan_pda_set_modem_info(serial, (1 << 7) | (1 << 2)); +	else +		keyspan_pda_set_modem_info(serial, 0);  } @@ -651,13 +647,8 @@ error:  }  static void keyspan_pda_close(struct usb_serial_port *port)  { -	struct usb_serial *serial = port->serial; - -	if (serial->dev) { -		/* shutdown our bulk reads and writes */ -		usb_kill_urb(port->write_urb); -		usb_kill_urb(port->interrupt_in_urb); -	} +	usb_kill_urb(port->write_urb); +	usb_kill_urb(port->interrupt_in_urb);  } diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c index 769d910ae0a..1b4054fe52a 100644 --- a/drivers/usb/serial/kl5kusb105.c +++ b/drivers/usb/serial/kl5kusb105.c @@ -341,28 +341,20 @@ static void klsi_105_close(struct usb_serial_port *port)  {  	int rc; -	mutex_lock(&port->serial->disc_mutex); -	if (!port->serial->disconnected) { -		/* send READ_OFF */ -		rc = usb_control_msg(port->serial->dev, -				     usb_sndctrlpipe(port->serial->dev, 0), -				     KL5KUSB105A_SIO_CONFIGURE, -				     USB_TYPE_VENDOR | USB_DIR_OUT, -				     KL5KUSB105A_SIO_CONFIGURE_READ_OFF, -				     0, /* index */ -				     NULL, 0, -				     KLSI_TIMEOUT); -		if (rc < 0) -			dev_err(&port->dev, -				"Disabling read failed (error = %d)\n", rc); -	} -	mutex_unlock(&port->serial->disc_mutex); +	/* send READ_OFF */ +	rc = usb_control_msg(port->serial->dev, +			     usb_sndctrlpipe(port->serial->dev, 0), +			     KL5KUSB105A_SIO_CONFIGURE, +			     USB_TYPE_VENDOR | USB_DIR_OUT, +			     KL5KUSB105A_SIO_CONFIGURE_READ_OFF, +			     0, /* index */ +			     NULL, 0, +			     KLSI_TIMEOUT); +	if (rc < 0) +		dev_err(&port->dev, "failed to disable read: %d\n", rc);  	/* shutdown our bulk reads and writes */  	usb_serial_generic_close(port); - -	/* wgg - do I need this? I think so. */ -	usb_kill_urb(port->interrupt_in_urb);  }  /* We need to write a complete 64-byte data block and encode the diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c index 903d938e174..78b48c31abf 100644 --- a/drivers/usb/serial/kobil_sct.c +++ b/drivers/usb/serial/kobil_sct.c @@ -65,7 +65,7 @@ static int  kobil_tiocmget(struct tty_struct *tty);  static int  kobil_tiocmset(struct tty_struct *tty,  			   unsigned int set, unsigned int clear);  static void kobil_read_int_callback(struct urb *urb); -static void kobil_write_callback(struct urb *purb); +static void kobil_write_int_callback(struct urb *urb);  static void kobil_set_termios(struct tty_struct *tty,  			struct usb_serial_port *port, struct ktermios *old);  static void kobil_init_termios(struct tty_struct *tty); @@ -99,6 +99,7 @@ static struct usb_serial_driver kobil_device = {  	.write =		kobil_write,  	.write_room =		kobil_write_room,  	.read_int_callback =	kobil_read_int_callback, +	.write_int_callback =	kobil_write_int_callback,  };  static struct usb_serial_driver * const serial_drivers[] = { @@ -106,8 +107,6 @@ static struct usb_serial_driver * const serial_drivers[] = {  };  struct kobil_private { -	int write_int_endpoint_address; -	int read_int_endpoint_address;  	unsigned char buf[KOBIL_BUF_LENGTH]; /* buffer for the APDU to send */  	int filled;  /* index of the last char in buf */  	int cur_pos; /* index of the next char to send in buf */ @@ -117,14 +116,8 @@ struct kobil_private {  static int kobil_port_probe(struct usb_serial_port *port)  { -	int i;  	struct usb_serial *serial = port->serial;  	struct kobil_private *priv; -	struct usb_device *pdev; -	struct usb_host_config *actconfig; -	struct usb_interface *interface; -	struct usb_host_interface *altsetting; -	struct usb_host_endpoint *endpoint;  	priv = kmalloc(sizeof(struct kobil_private), GFP_KERNEL);  	if (!priv) @@ -150,30 +143,6 @@ static int kobil_port_probe(struct usb_serial_port *port)  	}  	usb_set_serial_port_data(port, priv); -	/* search for the necessary endpoints */ -	pdev = serial->dev; -	actconfig = pdev->actconfig; -	interface = actconfig->interface[0]; -	altsetting = interface->cur_altsetting; -	endpoint = altsetting->endpoint; - -	for (i = 0; i < altsetting->desc.bNumEndpoints; i++) { -		endpoint = &altsetting->endpoint[i]; -		if (usb_endpoint_is_int_out(&endpoint->desc)) { -			dev_dbg(&serial->dev->dev, -				"%s Found interrupt out endpoint. Address: %d\n", -				__func__, endpoint->desc.bEndpointAddress); -			priv->write_int_endpoint_address = -				endpoint->desc.bEndpointAddress; -		} -		if (usb_endpoint_is_int_in(&endpoint->desc)) { -			dev_dbg(&serial->dev->dev, -				"%s Found interrupt in  endpoint. Address: %d\n", -				__func__, endpoint->desc.bEndpointAddress); -			priv->read_int_endpoint_address = -				endpoint->desc.bEndpointAddress; -		} -	}  	return 0;  } @@ -205,7 +174,6 @@ static int kobil_open(struct tty_struct *tty, struct usb_serial_port *port)  	struct kobil_private *priv;  	unsigned char *transfer_buffer;  	int transfer_buffer_length = 8; -	int write_urb_transfer_buffer_length = 8;  	priv = usb_get_serial_port_data(port); @@ -214,27 +182,6 @@ static int kobil_open(struct tty_struct *tty, struct usb_serial_port *port)  	if (!transfer_buffer)  		return -ENOMEM; -	/* allocate write_urb */ -	if (!port->write_urb) { -		dev_dbg(dev, "%s - Allocating port->write_urb\n", __func__); -		port->write_urb = usb_alloc_urb(0, GFP_KERNEL); -		if (!port->write_urb) { -			dev_dbg(dev, "%s - usb_alloc_urb failed\n", __func__); -			kfree(transfer_buffer); -			return -ENOMEM; -		} -	} - -	/* allocate memory for write_urb transfer buffer */ -	port->write_urb->transfer_buffer = -			kmalloc(write_urb_transfer_buffer_length, GFP_KERNEL); -	if (!port->write_urb->transfer_buffer) { -		kfree(transfer_buffer); -		usb_free_urb(port->write_urb); -		port->write_urb = NULL; -		return -ENOMEM; -	} -  	/* get hardware version */  	result = usb_control_msg(port->serial->dev,  			  usb_rcvctrlpipe(port->serial->dev, 0), @@ -310,12 +257,7 @@ static int kobil_open(struct tty_struct *tty, struct usb_serial_port *port)  static void kobil_close(struct usb_serial_port *port)  {  	/* FIXME: Add rts/dtr methods */ -	if (port->write_urb) { -		usb_poison_urb(port->write_urb); -		kfree(port->write_urb->transfer_buffer); -		usb_free_urb(port->write_urb); -		port->write_urb = NULL; -	} +	usb_kill_urb(port->interrupt_out_urb);  	usb_kill_urb(port->interrupt_in_urb);  } @@ -333,24 +275,8 @@ static void kobil_read_int_callback(struct urb *urb)  	}  	if (urb->actual_length) { - -		/* BEGIN DEBUG */ -		/* -		  char *dbg_data; - -		  dbg_data = kzalloc((3 *  purb->actual_length + 10) -						* sizeof(char), GFP_KERNEL); -		  if (! dbg_data) { -			  return; -		  } -		  for (i = 0; i < purb->actual_length; i++) { -			  sprintf(dbg_data +3*i, "%02X ", data[i]); -		  } -		  dev_dbg(&port->dev, " <-- %s\n", dbg_data); -		  kfree(dbg_data); -		*/ -		/* END DEBUG */ - +		usb_serial_debug_data(&port->dev, __func__, urb->actual_length, +									data);  		tty_insert_flip_string(&port->port, data, urb->actual_length);  		tty_flip_buffer_push(&port->port);  	} @@ -360,7 +286,7 @@ static void kobil_read_int_callback(struct urb *urb)  } -static void kobil_write_callback(struct urb *purb) +static void kobil_write_int_callback(struct urb *urb)  {  } @@ -403,23 +329,14 @@ static int kobil_write(struct tty_struct *tty, struct usb_serial_port *port,  		while (todo > 0) {  			/* max 8 byte in one urb (endpoint size) */ -			length = (todo < 8) ? todo : 8; +			length = min(todo, port->interrupt_out_size);  			/* copy data to transfer buffer */ -			memcpy(port->write_urb->transfer_buffer, +			memcpy(port->interrupt_out_buffer,  					priv->buf + priv->cur_pos, length); -			usb_fill_int_urb(port->write_urb, -				  port->serial->dev, -				  usb_sndintpipe(port->serial->dev, -					priv->write_int_endpoint_address), -				  port->write_urb->transfer_buffer, -				  length, -				  kobil_write_callback, -				  port, -				  8 -			); +			port->interrupt_out_urb->transfer_buffer_length = length;  			priv->cur_pos = priv->cur_pos + length; -			result = usb_submit_urb(port->write_urb, GFP_NOIO); +			result = usb_submit_urb(port->interrupt_out_urb, GFP_NOIO);  			dev_dbg(&port->dev, "%s - Send write URB returns: %i\n", __func__, result);  			todo = priv->filled - priv->cur_pos; diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c index 06d5a60be2c..6a15adf5336 100644 --- a/drivers/usb/serial/mct_u232.c +++ b/drivers/usb/serial/mct_u232.c @@ -35,7 +35,6 @@  #include <linux/usb.h>  #include <linux/usb/serial.h>  #include <linux/serial.h> -#include <linux/ioctl.h>  #include "mct_u232.h"  #define DRIVER_AUTHOR "Wolfgang Grandegger <wolfgang@ces.ch>" @@ -44,7 +43,6 @@  /*   * Function prototypes   */ -static int  mct_u232_startup(struct usb_serial *serial);  static int  mct_u232_port_probe(struct usb_serial_port *port);  static int  mct_u232_port_remove(struct usb_serial_port *remove);  static int  mct_u232_open(struct tty_struct *tty, struct usb_serial_port *port); @@ -57,10 +55,6 @@ static void mct_u232_break_ctl(struct tty_struct *tty, int break_state);  static int  mct_u232_tiocmget(struct tty_struct *tty);  static int  mct_u232_tiocmset(struct tty_struct *tty,  			unsigned int set, unsigned int clear); -static int  mct_u232_ioctl(struct tty_struct *tty, -			unsigned int cmd, unsigned long arg); -static int  mct_u232_get_icount(struct tty_struct *tty, -			struct serial_icounter_struct *icount);  static void mct_u232_throttle(struct tty_struct *tty);  static void mct_u232_unthrottle(struct tty_struct *tty); @@ -95,11 +89,10 @@ static struct usb_serial_driver mct_u232_device = {  	.break_ctl =	     mct_u232_break_ctl,  	.tiocmget =	     mct_u232_tiocmget,  	.tiocmset =	     mct_u232_tiocmset, -	.attach =	     mct_u232_startup, +	.tiocmiwait =        usb_serial_generic_tiocmiwait,  	.port_probe =        mct_u232_port_probe,  	.port_remove =       mct_u232_port_remove, -	.ioctl =             mct_u232_ioctl, -	.get_icount =        mct_u232_get_icount, +	.get_icount =        usb_serial_generic_get_icount,  };  static struct usb_serial_driver * const serial_drivers[] = { @@ -107,13 +100,13 @@ static struct usb_serial_driver * const serial_drivers[] = {  };  struct mct_u232_private { +	struct urb *read_urb;  	spinlock_t lock;  	unsigned int	     control_state; /* Modem Line Setting (TIOCM) */  	unsigned char        last_lcr;      /* Line Control Register */  	unsigned char	     last_lsr;      /* Line Status Register */  	unsigned char	     last_msr;      /* Modem Status Register */  	unsigned int	     rx_flags;      /* Throttling flags */ -	struct async_icount  icount;  };  #define THROTTLED		0x01 @@ -382,22 +375,6 @@ static void mct_u232_msr_to_state(struct usb_serial_port *port,   * Driver's tty interface functions   */ -static int mct_u232_startup(struct usb_serial *serial) -{ -	struct usb_serial_port *port, *rport; - -	/* Puh, that's dirty */ -	port = serial->port[0]; -	rport = serial->port[1]; -	/* No unlinking, it wasn't submitted yet. */ -	usb_free_urb(port->read_urb); -	port->read_urb = rport->interrupt_in_urb; -	rport->interrupt_in_urb = NULL; -	port->read_urb->context = port; - -	return 0; -} /* mct_u232_startup */ -  static int mct_u232_port_probe(struct usb_serial_port *port)  {  	struct mct_u232_private *priv; @@ -406,6 +383,10 @@ static int mct_u232_port_probe(struct usb_serial_port *port)  	if (!priv)  		return -ENOMEM; +	/* Use second interrupt-in endpoint for reading. */ +	priv->read_urb = port->serial->port[1]->interrupt_in_urb; +	priv->read_urb->context = port; +  	spin_lock_init(&priv->lock);  	usb_set_serial_port_data(port, priv); @@ -469,17 +450,17 @@ static int  mct_u232_open(struct tty_struct *tty, struct usb_serial_port *port)  	mct_u232_msr_to_state(port, &priv->control_state, priv->last_msr);  	spin_unlock_irqrestore(&priv->lock, flags); -	retval = usb_submit_urb(port->read_urb, GFP_KERNEL); +	retval = usb_submit_urb(priv->read_urb, GFP_KERNEL);  	if (retval) {  		dev_err(&port->dev, -			"usb_submit_urb(read bulk) failed pipe 0x%x err %d\n", +			"usb_submit_urb(read) failed pipe 0x%x err %d\n",  			port->read_urb->pipe, retval);  		goto error;  	}  	retval = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);  	if (retval) { -		usb_kill_urb(port->read_urb); +		usb_kill_urb(priv->read_urb);  		dev_err(&port->dev,  			"usb_submit_urb(read int) failed pipe 0x%x err %d",  			port->interrupt_in_urb->pipe, retval); @@ -509,11 +490,9 @@ static void mct_u232_dtr_rts(struct usb_serial_port *port, int on)  static void mct_u232_close(struct usb_serial_port *port)  { -	/* -	 * Must kill the read urb as it is actually an interrupt urb, which -	 * generic close thus fails to kill. -	 */ -	usb_kill_urb(port->read_urb); +	struct mct_u232_private *priv = usb_get_serial_port_data(port); + +	usb_kill_urb(priv->read_urb);  	usb_kill_urb(port->interrupt_in_urb);  	usb_serial_generic_close(port); @@ -570,7 +549,7 @@ static void mct_u232_read_int_callback(struct urb *urb)  	/* Record Control Line states */  	mct_u232_msr_to_state(port, &priv->control_state, priv->last_msr); -	mct_u232_msr_to_icount(&priv->icount, priv->last_msr); +	mct_u232_msr_to_icount(&port->icount, priv->last_msr);  #if 0  	/* Not yet handled. See belkin_sa.c for further information */ @@ -598,7 +577,7 @@ static void mct_u232_read_int_callback(struct urb *urb)  		tty_kref_put(tty);  	}  #endif -	wake_up_interruptible(&port->delta_msr_wait); +	wake_up_interruptible(&port->port.delta_msr_wait);  	spin_unlock_irqrestore(&priv->lock, flags);  exit:  	retval = usb_submit_urb(urb, GFP_ATOMIC); @@ -786,86 +765,6 @@ static void mct_u232_unthrottle(struct tty_struct *tty)  	}  } -static int  mct_u232_ioctl(struct tty_struct *tty, -			unsigned int cmd, unsigned long arg) -{ -	DEFINE_WAIT(wait); -	struct usb_serial_port *port = tty->driver_data; -	struct mct_u232_private *mct_u232_port = usb_get_serial_port_data(port); -	struct async_icount cnow, cprev; -	unsigned long flags; - -	dev_dbg(&port->dev, "%s - cmd = 0x%x\n", __func__, cmd); - -	switch (cmd) { - -	case TIOCMIWAIT: - -		dev_dbg(&port->dev, "%s TIOCMIWAIT", __func__); - -		spin_lock_irqsave(&mct_u232_port->lock, flags); -		cprev = mct_u232_port->icount; -		spin_unlock_irqrestore(&mct_u232_port->lock, flags); -		for ( ; ; ) { -			prepare_to_wait(&port->delta_msr_wait, -					&wait, TASK_INTERRUPTIBLE); -			schedule(); -			finish_wait(&port->delta_msr_wait, &wait); -			/* see if a signal did it */ -			if (signal_pending(current)) -				return -ERESTARTSYS; - -			if (port->serial->disconnected) -				return -EIO; - -			spin_lock_irqsave(&mct_u232_port->lock, flags); -			cnow = mct_u232_port->icount; -			spin_unlock_irqrestore(&mct_u232_port->lock, flags); -			if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && -			    cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) -				return -EIO; /* no change => error */ -			if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || -			    ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || -			    ((arg & TIOCM_CD)  && (cnow.dcd != cprev.dcd)) || -			    ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) { -				return 0; -			} -			cprev = cnow; -		} - -	} -	return -ENOIOCTLCMD; -} - -static int  mct_u232_get_icount(struct tty_struct *tty, -			struct serial_icounter_struct *icount) -{ -	struct usb_serial_port *port = tty->driver_data; -	struct mct_u232_private *mct_u232_port = usb_get_serial_port_data(port); -	struct async_icount *ic = &mct_u232_port->icount; -	unsigned long flags; - -	spin_lock_irqsave(&mct_u232_port->lock, flags); - -	icount->cts = ic->cts; -	icount->dsr = ic->dsr; -	icount->rng = ic->rng; -	icount->dcd = ic->dcd; -	icount->rx = ic->rx; -	icount->tx = ic->tx; -	icount->frame = ic->frame; -	icount->overrun = ic->overrun; -	icount->parity = ic->parity; -	icount->brk = ic->brk; -	icount->buf_overrun = ic->buf_overrun; - -	spin_unlock_irqrestore(&mct_u232_port->lock, flags); - -	dev_dbg(&port->dev, "%s TIOCGICOUNT RX=%d, TX=%d\n", -		__func__,  icount->rx, icount->tx); -	return 0; -} -  module_usb_serial_driver(serial_drivers, id_table);  MODULE_AUTHOR(DRIVER_AUTHOR); diff --git a/drivers/usb/serial/metro-usb.c b/drivers/usb/serial/metro-usb.c index bf3c7a23553..47e247759eb 100644 --- a/drivers/usb/serial/metro-usb.c +++ b/drivers/usb/serial/metro-usb.c @@ -177,10 +177,7 @@ static void metrousb_cleanup(struct usb_serial_port *port)  	usb_unlink_urb(port->interrupt_in_urb);  	usb_kill_urb(port->interrupt_in_urb); -	mutex_lock(&port->serial->disc_mutex); -	if (!port->serial->disconnected) -		metrousb_send_unidirectional_cmd(UNI_CMD_CLOSE, port); -	mutex_unlock(&port->serial->disc_mutex); +	metrousb_send_unidirectional_cmd(UNI_CMD_CLOSE, port);  }  static int metrousb_open(struct tty_struct *tty, struct usb_serial_port *port) diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c index e0ebec3b5d6..cc0e54345df 100644 --- a/drivers/usb/serial/mos7720.c +++ b/drivers/usb/serial/mos7720.c @@ -62,7 +62,6 @@ struct moschip_port {  	__u8	shadowMCR;		/* last MCR value received */  	__u8	shadowMSR;		/* last MSR value received */  	char			open; -	struct async_icount	icount;  	struct usb_serial_port	*port;	/* loop back to the owner */  	struct urb		*write_urb_pool[NUM_URBS];  }; @@ -932,7 +931,6 @@ static void mos7720_bulk_in_callback(struct urb *urb)  static void mos7720_bulk_out_data_callback(struct urb *urb)  {  	struct moschip_port *mos7720_port; -	struct tty_struct *tty;  	int status = urb->status;  	if (status) { @@ -946,11 +944,8 @@ static void mos7720_bulk_out_data_callback(struct urb *urb)  		return ;  	} -	tty = tty_port_tty_get(&mos7720_port->port->port); - -	if (tty && mos7720_port->open) -		tty_wakeup(tty); -	tty_kref_put(tty); +	if (mos7720_port->open) +		tty_port_tty_wakeup(&mos7720_port->port->port);  }  /* @@ -1075,9 +1070,6 @@ static int mos7720_open(struct tty_struct *tty, struct usb_serial_port *port)  		dev_err(&port->dev, "%s - Error %d submitting read urb\n",  							__func__, response); -	/* initialize our icount structure */ -	memset(&(mos7720_port->icount), 0x00, sizeof(mos7720_port->icount)); -  	/* initialize our port settings */  	mos7720_port->shadowMCR = UART_MCR_OUT2; /* Must set to enable ints! */ @@ -1144,16 +1136,9 @@ static void mos7720_close(struct usb_serial_port *port)  	usb_kill_urb(port->write_urb);  	usb_kill_urb(port->read_urb); -	mutex_lock(&serial->disc_mutex); -	/* these commands must not be issued if the device has -	 * been disconnected */ -	if (!serial->disconnected) { -		write_mos_reg(serial, port->number - port->serial->minor, -			      MCR, 0x00); -		write_mos_reg(serial, port->number - port->serial->minor, -			      IER, 0x00); -	} -	mutex_unlock(&serial->disc_mutex); +	write_mos_reg(serial, port->number - port->serial->minor, MCR, 0x00); +	write_mos_reg(serial, port->number - port->serial->minor, IER, 0x00); +  	mos7720_port->open = 0;  } @@ -1803,33 +1788,6 @@ static int mos7720_tiocmset(struct tty_struct *tty,  	return 0;  } -static int mos7720_get_icount(struct tty_struct *tty, -				struct serial_icounter_struct *icount) -{ -	struct usb_serial_port *port = tty->driver_data; -	struct moschip_port *mos7720_port; -	struct async_icount cnow; - -	mos7720_port = usb_get_serial_port_data(port); -	cnow = mos7720_port->icount; - -	icount->cts = cnow.cts; -	icount->dsr = cnow.dsr; -	icount->rng = cnow.rng; -	icount->dcd = cnow.dcd; -	icount->rx = cnow.rx; -	icount->tx = cnow.tx; -	icount->frame = cnow.frame; -	icount->overrun = cnow.overrun; -	icount->parity = cnow.parity; -	icount->brk = cnow.brk; -	icount->buf_overrun = cnow.buf_overrun; - -	dev_dbg(&port->dev, "%s TIOCGICOUNT RX=%d, TX=%d\n", __func__, -		icount->rx, icount->tx); -	return 0; -} -  static int set_modem_info(struct moschip_port *mos7720_port, unsigned int cmd,  			  unsigned int __user *value)  { @@ -1905,8 +1863,6 @@ static int mos7720_ioctl(struct tty_struct *tty,  {  	struct usb_serial_port *port = tty->driver_data;  	struct moschip_port *mos7720_port; -	struct async_icount cnow; -	struct async_icount cprev;  	mos7720_port = usb_get_serial_port_data(port);  	if (mos7720_port == NULL) @@ -1931,27 +1887,6 @@ static int mos7720_ioctl(struct tty_struct *tty,  		dev_dbg(&port->dev, "%s TIOCGSERIAL\n", __func__);  		return get_serial_info(mos7720_port,  				       (struct serial_struct __user *)arg); - -	case TIOCMIWAIT: -		dev_dbg(&port->dev, "%s TIOCMIWAIT\n", __func__); -		cprev = mos7720_port->icount; -		while (1) { -			if (signal_pending(current)) -				return -ERESTARTSYS; -			cnow = mos7720_port->icount; -			if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && -			    cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) -				return -EIO; /* no change => error */ -			if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || -			    ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || -			    ((arg & TIOCM_CD)  && (cnow.dcd != cprev.dcd)) || -			    ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) { -				return 0; -			} -			cprev = cnow; -		} -		/* NOTREACHED */ -		break;  	}  	return -ENOIOCTLCMD; @@ -2107,7 +2042,6 @@ static struct usb_serial_driver moschip7720_2port_driver = {  	.ioctl			= mos7720_ioctl,  	.tiocmget		= mos7720_tiocmget,  	.tiocmset		= mos7720_tiocmset, -	.get_icount		= mos7720_get_icount,  	.set_termios		= mos7720_set_termios,  	.write			= mos7720_write,  	.write_room		= mos7720_write_room, diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index b8051fa6191..a0d5ea54598 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -219,8 +219,6 @@ struct moschip_port {  	char open;  	char open_ports;  	wait_queue_head_t wait_chase;	/* for handling sleeping while waiting for chase to finish */ -	int delta_msr_cond; -	struct async_icount icount;  	struct usb_serial_port *port;	/* loop back to the owner of this object */  	/* Offsets */ @@ -399,32 +397,22 @@ static void mos7840_handle_new_msr(struct moschip_port *port, __u8 new_msr)  	struct moschip_port *mos7840_port;  	struct async_icount *icount;  	mos7840_port = port; -	icount = &mos7840_port->icount;  	if (new_msr &  	    (MOS_MSR_DELTA_CTS | MOS_MSR_DELTA_DSR | MOS_MSR_DELTA_RI |  	     MOS_MSR_DELTA_CD)) { -		icount = &mos7840_port->icount; +		icount = &mos7840_port->port->icount;  		/* update input line counters */ -		if (new_msr & MOS_MSR_DELTA_CTS) { +		if (new_msr & MOS_MSR_DELTA_CTS)  			icount->cts++; -			smp_wmb(); -		} -		if (new_msr & MOS_MSR_DELTA_DSR) { +		if (new_msr & MOS_MSR_DELTA_DSR)  			icount->dsr++; -			smp_wmb(); -		} -		if (new_msr & MOS_MSR_DELTA_CD) { +		if (new_msr & MOS_MSR_DELTA_CD)  			icount->dcd++; -			smp_wmb(); -		} -		if (new_msr & MOS_MSR_DELTA_RI) { +		if (new_msr & MOS_MSR_DELTA_RI)  			icount->rng++; -			smp_wmb(); -		} -		mos7840_port->delta_msr_cond = 1; -		wake_up_interruptible(&port->port->delta_msr_wait); +		wake_up_interruptible(&port->port->port.delta_msr_wait);  	}  } @@ -442,23 +430,15 @@ static void mos7840_handle_new_lsr(struct moschip_port *port, __u8 new_lsr)  	}  	/* update input line counters */ -	icount = &port->icount; -	if (new_lsr & SERIAL_LSR_BI) { +	icount = &port->port->icount; +	if (new_lsr & SERIAL_LSR_BI)  		icount->brk++; -		smp_wmb(); -	} -	if (new_lsr & SERIAL_LSR_OE) { +	if (new_lsr & SERIAL_LSR_OE)  		icount->overrun++; -		smp_wmb(); -	} -	if (new_lsr & SERIAL_LSR_PE) { +	if (new_lsr & SERIAL_LSR_PE)  		icount->parity++; -		smp_wmb(); -	} -	if (new_lsr & SERIAL_LSR_FE) { +	if (new_lsr & SERIAL_LSR_FE)  		icount->frame++; -		smp_wmb(); -	}  }  /************************************************************************/ @@ -777,9 +757,8 @@ static void mos7840_bulk_in_callback(struct urb *urb)  		struct tty_port *tport = &mos7840_port->port->port;  		tty_insert_flip_string(tport, data, urb->actual_length);  		tty_flip_buffer_push(tport); -		mos7840_port->icount.rx += urb->actual_length; -		smp_wmb(); -		dev_dbg(&port->dev, "mos7840_port->icount.rx is %d:\n", mos7840_port->icount.rx); +		port->icount.rx += urb->actual_length; +		dev_dbg(&port->dev, "icount.rx is %d:\n", port->icount.rx);  	}  	if (!mos7840_port->read_urb) { @@ -816,7 +795,6 @@ static void mos7840_bulk_out_data_callback(struct urb *urb)  {  	struct moschip_port *mos7840_port;  	struct usb_serial_port *port; -	struct tty_struct *tty;  	int status = urb->status;  	int i; @@ -839,10 +817,8 @@ static void mos7840_bulk_out_data_callback(struct urb *urb)  	if (mos7840_port_paranoia_check(port, __func__))  		return; -	tty = tty_port_tty_get(&port->port); -	if (tty && mos7840_port->open) -		tty_wakeup(tty); -	tty_kref_put(tty); +	if (mos7840_port->open) +		tty_port_tty_wakeup(&port->port);  } @@ -1130,17 +1106,12 @@ static int mos7840_open(struct tty_struct *tty, struct usb_serial_port *port)  	/* initialize our wait queues */  	init_waitqueue_head(&mos7840_port->wait_chase); -	/* initialize our icount structure */ -	memset(&(mos7840_port->icount), 0x00, sizeof(mos7840_port->icount)); -  	/* initialize our port settings */  	/* Must set to enable ints! */  	mos7840_port->shadowMCR = MCR_MASTER_IE;  	/* send a open port command */  	mos7840_port->open = 1;  	/* mos7840_change_port_settings(mos7840_port,old_termios); */ -	mos7840_port->icount.tx = 0; -	mos7840_port->icount.rx = 0;  	return 0;  } @@ -1223,25 +1194,10 @@ static void mos7840_close(struct usb_serial_port *port)  		}  	} -	/* While closing port, shutdown all bulk read, write  * -	 * and interrupt read if they exists                  */ -	if (serial->dev) { -		if (mos7840_port->write_urb) { -			dev_dbg(&port->dev, "%s", "Shutdown bulk write\n"); -			usb_kill_urb(mos7840_port->write_urb); -		} -		if (mos7840_port->read_urb) { -			dev_dbg(&port->dev, "%s", "Shutdown bulk read\n"); -			usb_kill_urb(mos7840_port->read_urb); -			mos7840_port->read_urb_busy = false; -		} -		if ((&mos7840_port->control_urb)) { -			dev_dbg(&port->dev, "%s", "Shutdown control read\n"); -			/*/      usb_kill_urb (mos7840_port->control_urb); */ -		} -	} -/*      if(mos7840_port->ctrl_buf != NULL) */ -/*              kfree(mos7840_port->ctrl_buf); */ +	usb_kill_urb(mos7840_port->write_urb); +	usb_kill_urb(mos7840_port->read_urb); +	mos7840_port->read_urb_busy = false; +  	port0->open_ports--;  	dev_dbg(&port->dev, "%s in close%d:in port%d\n", __func__, port0->open_ports, port->number);  	if (port0->open_ports == 0) { @@ -1253,8 +1209,7 @@ static void mos7840_close(struct usb_serial_port *port)  	if (mos7840_port->write_urb) {  		/* if this urb had a transfer buffer already (old tx) free it */ -		if (mos7840_port->write_urb->transfer_buffer != NULL) -			kfree(mos7840_port->write_urb->transfer_buffer); +		kfree(mos7840_port->write_urb->transfer_buffer);  		usb_free_urb(mos7840_port->write_urb);  	} @@ -1331,9 +1286,8 @@ static void mos7840_break(struct tty_struct *tty, int break_state)  	if (mos7840_port == NULL)  		return; -	if (serial->dev) -		/* flush and block until tx is empty */ -		mos7840_block_until_chase_response(tty, mos7840_port); +	/* flush and block until tx is empty */ +	mos7840_block_until_chase_response(tty, mos7840_port);  	if (break_state == -1)  		data = mos7840_port->shadowLCR | LCR_SET_BREAK; @@ -1523,9 +1477,8 @@ static int mos7840_write(struct tty_struct *tty, struct usb_serial_port *port,  		goto exit;  	}  	bytes_sent = transfer_size; -	mos7840_port->icount.tx += transfer_size; -	smp_wmb(); -	dev_dbg(&port->dev, "mos7840_port->icount.tx is %d:\n", mos7840_port->icount.tx); +	port->icount.tx += transfer_size; +	dev_dbg(&port->dev, "icount.tx is %d:\n", port->icount.tx);  exit:  	return bytes_sent; @@ -2144,34 +2097,6 @@ static int mos7840_get_serial_info(struct moschip_port *mos7840_port,  	return 0;  } -static int mos7840_get_icount(struct tty_struct *tty, -			struct serial_icounter_struct *icount) -{ -	struct usb_serial_port *port = tty->driver_data; -	struct moschip_port *mos7840_port; -	struct async_icount cnow; - -	mos7840_port = mos7840_get_port_private(port); -	cnow = mos7840_port->icount; - -	smp_rmb(); -	icount->cts = cnow.cts; -	icount->dsr = cnow.dsr; -	icount->rng = cnow.rng; -	icount->dcd = cnow.dcd; -	icount->rx = cnow.rx; -	icount->tx = cnow.tx; -	icount->frame = cnow.frame; -	icount->overrun = cnow.overrun; -	icount->parity = cnow.parity; -	icount->brk = cnow.brk; -	icount->buf_overrun = cnow.buf_overrun; - -	dev_dbg(&port->dev, "%s TIOCGICOUNT RX=%d, TX=%d\n", __func__, -		icount->rx, icount->tx); -	return 0; -} -  /*****************************************************************************   * SerialIoctl   *	this function handles any ioctl calls to the driver @@ -2184,9 +2109,6 @@ static int mos7840_ioctl(struct tty_struct *tty,  	void __user *argp = (void __user *)arg;  	struct moschip_port *mos7840_port; -	struct async_icount cnow; -	struct async_icount cprev; -  	if (mos7840_port_paranoia_check(port, __func__))  		return -1; @@ -2211,41 +2133,6 @@ static int mos7840_ioctl(struct tty_struct *tty,  	case TIOCSSERIAL:  		dev_dbg(&port->dev, "%s TIOCSSERIAL\n", __func__);  		break; - -	case TIOCMIWAIT: -		dev_dbg(&port->dev, "%s  TIOCMIWAIT\n", __func__); -		cprev = mos7840_port->icount; -		while (1) { -			/* interruptible_sleep_on(&mos7840_port->delta_msr_wait); */ -			mos7840_port->delta_msr_cond = 0; -			wait_event_interruptible(port->delta_msr_wait, -						 (port->serial->disconnected || -						  mos7840_port-> -						  delta_msr_cond == 1)); - -			/* see if a signal did it */ -			if (signal_pending(current)) -				return -ERESTARTSYS; - -			if (port->serial->disconnected) -				return -EIO; - -			cnow = mos7840_port->icount; -			smp_rmb(); -			if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && -			    cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) -				return -EIO;	/* no change => error */ -			if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || -			    ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || -			    ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) || -			    ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) { -				return 0; -			} -			cprev = cnow; -		} -		/* NOTREACHED */ -		break; -  	default:  		break;  	} @@ -2592,7 +2479,8 @@ static struct usb_serial_driver moschip7840_4port_device = {  	.break_ctl = mos7840_break,  	.tiocmget = mos7840_tiocmget,  	.tiocmset = mos7840_tiocmset, -	.get_icount = mos7840_get_icount, +	.tiocmiwait = usb_serial_generic_tiocmiwait, +	.get_icount = usb_serial_generic_get_icount,  	.port_probe = mos7840_port_probe,  	.port_remove = mos7840_port_remove,  	.read_bulk_callback = mos7840_bulk_in_callback, diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c index 1e1cafe287e..5739bf6f720 100644 --- a/drivers/usb/serial/omninet.c +++ b/drivers/usb/serial/omninet.c @@ -33,8 +33,7 @@  /* function prototypes */  static int  omninet_open(struct tty_struct *tty, struct usb_serial_port *port); -static void omninet_close(struct usb_serial_port *port); -static void omninet_read_bulk_callback(struct urb *urb); +static void omninet_process_read_urb(struct urb *urb);  static void omninet_write_bulk_callback(struct urb *urb);  static int  omninet_write(struct tty_struct *tty, struct usb_serial_port *port,  				const unsigned char *buf, int count); @@ -61,11 +60,10 @@ static struct usb_serial_driver zyxel_omninet_device = {  	.port_probe =		omninet_port_probe,  	.port_remove =		omninet_port_remove,  	.open =			omninet_open, -	.close =		omninet_close,  	.write =		omninet_write,  	.write_room =		omninet_write_room, -	.read_bulk_callback =	omninet_read_bulk_callback,  	.write_bulk_callback =	omninet_write_bulk_callback, +	.process_read_urb =	omninet_process_read_urb,  	.disconnect =		omninet_disconnect,  }; @@ -74,29 +72,28 @@ static struct usb_serial_driver * const serial_drivers[] = {  }; -/* The protocol. +/* + * The protocol.   *   * The omni.net always exchange 64 bytes of data with the host. The first - * four bytes are the control header, you can see it in the above structure. + * four bytes are the control header.   *   * oh_seq is a sequence number. Don't know if/how it's used.   * oh_len is the length of the data bytes in the packet.   * oh_xxx Bit-mapped, related to handshaking and status info. - *	I normally set it to 0x03 in trasmitted frames. + *	I normally set it to 0x03 in transmitted frames.   *	7: Active when the TA is in a CONNECTed state.   *	6: unknown   *	5: handshaking, unknown   *	4: handshaking, unknown   *	3: unknown, usually 0   *	2: unknown, usually 0 - *	1: handshaking, unknown, usually set to 1 in trasmitted frames - *	0: handshaking, unknown, usually set to 1 in trasmitted frames + *	1: handshaking, unknown, usually set to 1 in transmitted frames + *	0: handshaking, unknown, usually set to 1 in transmitted frames   * oh_pad Probably a pad byte.   *   * After the header you will find data bytes if oh_len was greater than zero. - *   */ -  struct omninet_header {  	__u8	oh_seq;  	__u8	oh_len; @@ -112,7 +109,7 @@ static int omninet_port_probe(struct usb_serial_port *port)  {  	struct omninet_data *od; -	od = kmalloc(sizeof(struct omninet_data), GFP_KERNEL); +	od = kzalloc(sizeof(*od), GFP_KERNEL);  	if (!od)  		return -ENOMEM; @@ -135,56 +132,32 @@ static int omninet_open(struct tty_struct *tty, struct usb_serial_port *port)  {  	struct usb_serial	*serial = port->serial;  	struct usb_serial_port	*wport; -	int			result = 0;  	wport = serial->port[1];  	tty_port_tty_set(&wport->port, tty); -	/* Start reading from the device */ -	result = usb_submit_urb(port->read_urb, GFP_KERNEL); -	if (result) -		dev_err(&port->dev, -			"%s - failed submitting read urb, error %d\n", -			__func__, result); -	return result; -} - -static void omninet_close(struct usb_serial_port *port) -{ -	usb_kill_urb(port->read_urb); +	return usb_serial_generic_open(tty, port);  } +#define OMNINET_HEADERLEN	4 +#define OMNINET_BULKOUTSIZE	64 +#define OMNINET_PAYLOADSIZE	(OMNINET_BULKOUTSIZE - OMNINET_HEADERLEN) -#define OMNINET_DATAOFFSET	0x04 -#define OMNINET_HEADERLEN	sizeof(struct omninet_header) -#define OMNINET_BULKOUTSIZE 	(64 - OMNINET_HEADERLEN) - -static void omninet_read_bulk_callback(struct urb *urb) +static void omninet_process_read_urb(struct urb *urb)  { -	struct usb_serial_port 	*port 	= urb->context; -	unsigned char 		*data 	= urb->transfer_buffer; -	struct omninet_header 	*header = (struct omninet_header *) &data[0]; -	int status = urb->status; -	int result; +	struct usb_serial_port *port = urb->context; +	const struct omninet_header *hdr = urb->transfer_buffer; +	const unsigned char *data; +	size_t data_len; -	if (status) { -		dev_dbg(&port->dev, "%s - nonzero read bulk status received: %d\n", -			__func__, status); +	if (urb->actual_length <= OMNINET_HEADERLEN || !hdr->oh_len)  		return; -	} - -	if (urb->actual_length && header->oh_len) { -		tty_insert_flip_string(&port->port, data + OMNINET_DATAOFFSET, -				header->oh_len); -		tty_flip_buffer_push(&port->port); -	} -	/* Continue trying to always read  */ -	result = usb_submit_urb(urb, GFP_ATOMIC); -	if (result) -		dev_err(&port->dev, -			"%s - failed resubmitting read urb, error %d\n", -			__func__, result); +	data = (char *)urb->transfer_buffer + OMNINET_HEADERLEN; +	data_len = min_t(size_t, urb->actual_length - OMNINET_HEADERLEN, +								hdr->oh_len); +	tty_insert_flip_string(&port->port, data, data_len); +	tty_flip_buffer_push(&port->port);  }  static int omninet_write(struct tty_struct *tty, struct usb_serial_port *port, @@ -209,9 +182,9 @@ static int omninet_write(struct tty_struct *tty, struct usb_serial_port *port,  		return 0;  	} -	count = (count > OMNINET_BULKOUTSIZE) ? OMNINET_BULKOUTSIZE : count; +	count = (count > OMNINET_PAYLOADSIZE) ? OMNINET_PAYLOADSIZE : count; -	memcpy(wport->write_urb->transfer_buffer + OMNINET_DATAOFFSET, +	memcpy(wport->write_urb->transfer_buffer + OMNINET_HEADERLEN,  								buf, count);  	usb_serial_debug_data(&port->dev, __func__, count, @@ -223,7 +196,7 @@ static int omninet_write(struct tty_struct *tty, struct usb_serial_port *port,  	header->oh_pad 	= 0x00;  	/* send the data out the bulk port, always 64 bytes */ -	wport->write_urb->transfer_buffer_length = 64; +	wport->write_urb->transfer_buffer_length = OMNINET_BULKOUTSIZE;  	result = usb_submit_urb(wport->write_urb, GFP_ATOMIC);  	if (result) { diff --git a/drivers/usb/serial/opticon.c b/drivers/usb/serial/opticon.c index e13e1a4d3e1..5f4b0cd0f6e 100644 --- a/drivers/usb/serial/opticon.c +++ b/drivers/usb/serial/opticon.c @@ -120,7 +120,10 @@ static int send_control_msg(struct usb_serial_port *port, u8 requesttype,  				0, 0, buffer, 1, 0);  	kfree(buffer); -	return retval; +	if (retval < 0) +		return retval; + +	return 0;  }  static int opticon_open(struct tty_struct *tty, struct usb_serial_port *port) @@ -306,7 +309,6 @@ static int opticon_tiocmset(struct tty_struct *tty,  			   unsigned int set, unsigned int clear)  {  	struct usb_serial_port *port = tty->driver_data; -	struct usb_serial *serial = port->serial;  	struct opticon_private *priv = usb_get_serial_port_data(port);  	unsigned long flags;  	bool rts; @@ -327,15 +329,11 @@ static int opticon_tiocmset(struct tty_struct *tty,  	if (!changed)  		return 0; -	/* Send the new RTS state to the connected device */ -	mutex_lock(&serial->disc_mutex); -	if (!serial->disconnected) -		ret = send_control_msg(port, CONTROL_RTS, !rts); -	else -		ret = -ENODEV; -	mutex_unlock(&serial->disc_mutex); +	ret = send_control_msg(port, CONTROL_RTS, !rts); +	if (ret) +		return usb_translate_errors(ret); -	return ret; +	return 0;  }  static int get_serial_info(struct usb_serial_port *port, diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 558adfc0500..734372846ab 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -347,6 +347,7 @@ static void option_instat_callback(struct urb *urb);  /* Olivetti products */  #define OLIVETTI_VENDOR_ID			0x0b3c  #define OLIVETTI_PRODUCT_OLICARD100		0xc000 +#define OLIVETTI_PRODUCT_OLICARD145		0xc003  /* Celot products */  #define CELOT_VENDOR_ID				0x211f @@ -1273,6 +1274,7 @@ static const struct usb_device_id option_ids[] = {  	{ USB_DEVICE(SIEMENS_VENDOR_ID, CINTERION_PRODUCT_HC28_MDMNET) },  	{ USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD100) }, +	{ USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD145) },  	{ USB_DEVICE(CELOT_VENDOR_ID, CELOT_PRODUCT_CT680M) }, /* CT-650 CDMA 450 1xEVDO modem */  	{ USB_DEVICE(ONDA_VENDOR_ID, ONDA_MT825UP) }, /* ONDA MT825UP modem */  	{ USB_DEVICE_AND_INTERFACE_INFO(SAMSUNG_VENDOR_ID, SAMSUNG_PRODUCT_GT_B3730, USB_CLASS_CDC_DATA, 0x00, 0x00) }, /* Samsung GT-B3730 LTE USB modem.*/ @@ -1350,6 +1352,12 @@ static const struct usb_device_id option_ids[] = {  	{ USB_DEVICE(TPLINK_VENDOR_ID, TPLINK_PRODUCT_MA180),  	  .driver_info = (kernel_ulong_t)&net_intf4_blacklist },  	{ USB_DEVICE(CHANGHONG_VENDOR_ID, CHANGHONG_PRODUCT_CH690) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d01, 0xff, 0x02, 0x01) },	/* D-Link DWM-156 (variant) */ +	{ USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d01, 0xff, 0x00, 0x00) },	/* D-Link DWM-156 (variant) */ +	{ USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d02, 0xff, 0x02, 0x01) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d02, 0xff, 0x00, 0x00) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d03, 0xff, 0x02, 0x01) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d03, 0xff, 0x00, 0x00) },  	{ } /* Terminating entry */  };  MODULE_DEVICE_TABLE(usb, option_ids); @@ -1537,13 +1545,8 @@ static void option_instat_callback(struct urb *urb)  			portdata->dsr_state = ((signals & 0x02) ? 1 : 0);  			portdata->ri_state = ((signals & 0x08) ? 1 : 0); -			if (old_dcd_state && !portdata->dcd_state) { -				struct tty_struct *tty = -						tty_port_tty_get(&port->port); -				if (tty && !C_CLOCAL(tty)) -					tty_hangup(tty); -				tty_kref_put(tty); -			} +			if (old_dcd_state && !portdata->dcd_state) +				tty_port_tty_hangup(&port->port, true);  		} else {  			dev_dbg(dev, "%s: type %x req %x\n", __func__,  				req_pkt->bRequestType, req_pkt->bRequest); diff --git a/drivers/usb/serial/oti6858.c b/drivers/usb/serial/oti6858.c index 87c71ccfee8..7e3e0782e51 100644 --- a/drivers/usb/serial/oti6858.c +++ b/drivers/usb/serial/oti6858.c @@ -124,8 +124,6 @@ static void oti6858_close(struct usb_serial_port *port);  static void oti6858_set_termios(struct tty_struct *tty,  			struct usb_serial_port *port, struct ktermios *old);  static void oti6858_init_termios(struct tty_struct *tty); -static int oti6858_ioctl(struct tty_struct *tty, -			unsigned int cmd, unsigned long arg);  static void oti6858_read_int_callback(struct urb *urb);  static void oti6858_read_bulk_callback(struct urb *urb);  static void oti6858_write_bulk_callback(struct urb *urb); @@ -136,6 +134,7 @@ static int oti6858_chars_in_buffer(struct tty_struct *tty);  static int oti6858_tiocmget(struct tty_struct *tty);  static int oti6858_tiocmset(struct tty_struct *tty,  				unsigned int set, unsigned int clear); +static int oti6858_tiocmiwait(struct tty_struct *tty, unsigned long arg);  static int oti6858_port_probe(struct usb_serial_port *port);  static int oti6858_port_remove(struct usb_serial_port *port); @@ -150,11 +149,11 @@ static struct usb_serial_driver oti6858_device = {  	.open =			oti6858_open,  	.close =		oti6858_close,  	.write =		oti6858_write, -	.ioctl =		oti6858_ioctl,  	.set_termios =		oti6858_set_termios,  	.init_termios = 	oti6858_init_termios,  	.tiocmget =		oti6858_tiocmget,  	.tiocmset =		oti6858_tiocmset, +	.tiocmiwait =		oti6858_tiocmiwait,  	.read_bulk_callback =	oti6858_read_bulk_callback,  	.read_int_callback =	oti6858_read_int_callback,  	.write_bulk_callback =	oti6858_write_bulk_callback, @@ -650,8 +649,9 @@ static int oti6858_tiocmget(struct tty_struct *tty)  	return result;  } -static int wait_modem_info(struct usb_serial_port *port, unsigned int arg) +static int oti6858_tiocmiwait(struct tty_struct *tty, unsigned long arg)  { +	struct usb_serial_port *port = tty->driver_data;  	struct oti6858_private *priv = usb_get_serial_port_data(port);  	unsigned long flags;  	unsigned int prev, status; @@ -662,7 +662,7 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)  	spin_unlock_irqrestore(&priv->lock, flags);  	while (1) { -		wait_event_interruptible(port->delta_msr_wait, +		wait_event_interruptible(port->port.delta_msr_wait,  					port->serial->disconnected ||  					priv->status.pin_state != prev);  		if (signal_pending(current)) @@ -689,24 +689,6 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)  	return 0;  } -static int oti6858_ioctl(struct tty_struct *tty, -			unsigned int cmd, unsigned long arg) -{ -	struct usb_serial_port *port = tty->driver_data; - -	dev_dbg(&port->dev, "%s(cmd = 0x%04x, arg = 0x%08lx)\n", __func__, cmd, arg); - -	switch (cmd) { -	case TIOCMIWAIT: -		dev_dbg(&port->dev, "%s(): TIOCMIWAIT\n", __func__); -		return wait_modem_info(port, arg); -	default: -		dev_dbg(&port->dev, "%s(): 0x%04x not supported\n", __func__, cmd); -		break; -	} -	return -ENOIOCTLCMD; -} -  static void oti6858_read_int_callback(struct urb *urb)  {  	struct usb_serial_port *port =  urb->context; @@ -765,7 +747,7 @@ static void oti6858_read_int_callback(struct urb *urb)  		if (!priv->transient) {  			if (xs->pin_state != priv->status.pin_state) -				wake_up_interruptible(&port->delta_msr_wait); +				wake_up_interruptible(&port->port.delta_msr_wait);  			memcpy(&priv->status, xs, OTI6858_CTRL_PKT_SIZE);  		} diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index 3b10018d89a..7151659367a 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -149,7 +149,7 @@ static int pl2303_vendor_read(__u16 value, __u16 index,  	int res = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),  			VENDOR_READ_REQUEST, VENDOR_READ_REQUEST_TYPE,  			value, index, buf, 1, 100); -	dev_dbg(&serial->dev->dev, "0x%x:0x%x:0x%x:0x%x  %d - %x\n", +	dev_dbg(&serial->interface->dev, "0x%x:0x%x:0x%x:0x%x  %d - %x\n",  		VENDOR_READ_REQUEST_TYPE, VENDOR_READ_REQUEST, value, index,  		res, buf[0]);  	return res; @@ -161,7 +161,7 @@ static int pl2303_vendor_write(__u16 value, __u16 index,  	int res = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),  			VENDOR_WRITE_REQUEST, VENDOR_WRITE_REQUEST_TYPE,  			value, index, NULL, 0, 100); -	dev_dbg(&serial->dev->dev, "0x%x:0x%x:0x%x:0x%x  %d\n", +	dev_dbg(&serial->interface->dev, "0x%x:0x%x:0x%x:0x%x  %d\n",  		VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, value, index,  		res);  	return res; @@ -248,14 +248,15 @@ static int pl2303_port_remove(struct usb_serial_port *port)  	return 0;  } -static int set_control_lines(struct usb_device *dev, u8 value) +static int pl2303_set_control_lines(struct usb_serial_port *port, u8 value)  { +	struct usb_device *dev = port->serial->dev;  	int retval;  	retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),  				 SET_CONTROL_REQUEST, SET_CONTROL_REQUEST_TYPE,  				 value, 0, NULL, 0, 100); -	dev_dbg(&dev->dev, "%s - value = %d, retval = %d\n", __func__, +	dev_dbg(&port->dev, "%s - value = %d, retval = %d\n", __func__,  		value, retval);  	return retval;  } @@ -437,7 +438,7 @@ static void pl2303_set_termios(struct tty_struct *tty,  	if (control != priv->line_control) {  		control = priv->line_control;  		spin_unlock_irqrestore(&priv->lock, flags); -		set_control_lines(serial->dev, control); +		pl2303_set_control_lines(port, control);  	} else {  		spin_unlock_irqrestore(&priv->lock, flags);  	} @@ -480,7 +481,7 @@ static void pl2303_dtr_rts(struct usb_serial_port *port, int on)  		priv->line_control &= ~(CONTROL_DTR | CONTROL_RTS);  	control = priv->line_control;  	spin_unlock_irqrestore(&priv->lock, flags); -	set_control_lines(port->serial->dev, control); +	pl2303_set_control_lines(port, control);  }  static void pl2303_close(struct usb_serial_port *port) @@ -530,7 +531,6 @@ static int pl2303_tiocmset(struct tty_struct *tty,  			   unsigned int set, unsigned int clear)  {  	struct usb_serial_port *port = tty->driver_data; -	struct usb_serial *serial = port->serial;  	struct pl2303_private *priv = usb_get_serial_port_data(port);  	unsigned long flags;  	u8 control; @@ -548,14 +548,11 @@ static int pl2303_tiocmset(struct tty_struct *tty,  	control = priv->line_control;  	spin_unlock_irqrestore(&priv->lock, flags); -	mutex_lock(&serial->disc_mutex); -	if (!serial->disconnected) -		ret = set_control_lines(serial->dev, control); -	else -		ret = -ENODEV; -	mutex_unlock(&serial->disc_mutex); +	ret = pl2303_set_control_lines(port, control); +	if (ret) +		return usb_translate_errors(ret); -	return ret; +	return 0;  }  static int pl2303_tiocmget(struct tty_struct *tty) @@ -592,8 +589,9 @@ static int pl2303_carrier_raised(struct usb_serial_port *port)  	return 0;  } -static int wait_modem_info(struct usb_serial_port *port, unsigned int arg) +static int pl2303_tiocmiwait(struct tty_struct *tty, unsigned long arg)  { +	struct usb_serial_port *port = tty->driver_data;  	struct pl2303_private *priv = usb_get_serial_port_data(port);  	unsigned long flags;  	unsigned int prevstatus; @@ -605,7 +603,7 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)  	spin_unlock_irqrestore(&priv->lock, flags);  	while (1) { -		interruptible_sleep_on(&port->delta_msr_wait); +		interruptible_sleep_on(&port->port.delta_msr_wait);  		/* see if a signal did it */  		if (signal_pending(current))  			return -ERESTARTSYS; @@ -651,10 +649,6 @@ static int pl2303_ioctl(struct tty_struct *tty,  			return -EFAULT;  		return 0; - -	case TIOCMIWAIT: -		dev_dbg(&port->dev, "%s TIOCMIWAIT\n", __func__); -		return wait_modem_info(port, arg);  	default:  		dev_dbg(&port->dev, "%s not supported = 0x%04x\n", __func__, cmd);  		break; @@ -720,7 +714,7 @@ static void pl2303_update_line_status(struct usb_serial_port *port,  	spin_unlock_irqrestore(&priv->lock, flags);  	if (priv->line_status & UART_BREAK_ERROR)  		usb_serial_handle_break(port); -	wake_up_interruptible(&port->delta_msr_wait); +	wake_up_interruptible(&port->port.delta_msr_wait);  	tty = tty_port_tty_get(&port->port);  	if (!tty) @@ -784,7 +778,7 @@ static void pl2303_process_read_urb(struct urb *urb)  	line_status = priv->line_status;  	priv->line_status &= ~UART_STATE_TRANSIENT_MASK;  	spin_unlock_irqrestore(&priv->lock, flags); -	wake_up_interruptible(&port->delta_msr_wait); +	wake_up_interruptible(&port->port.delta_msr_wait);  	if (!urb->actual_length)  		return; @@ -835,6 +829,7 @@ static struct usb_serial_driver pl2303_device = {  	.set_termios =		pl2303_set_termios,  	.tiocmget =		pl2303_tiocmget,  	.tiocmset =		pl2303_tiocmset, +	.tiocmiwait =		pl2303_tiocmiwait,  	.process_read_urb =	pl2303_process_read_urb,  	.read_int_callback =	pl2303_read_int_callback,  	.attach =		pl2303_startup, diff --git a/drivers/usb/serial/quatech2.c b/drivers/usb/serial/quatech2.c index 75f125ddb0c..02b0803425c 100644 --- a/drivers/usb/serial/quatech2.c +++ b/drivers/usb/serial/quatech2.c @@ -116,7 +116,6 @@ struct qt2_serial_private {  };  struct qt2_port_private { -	bool is_open;  	u8   device_port;  	spinlock_t urb_lock; @@ -128,8 +127,6 @@ struct qt2_port_private {  	u8          shadowLSR;  	u8          shadowMSR; -	struct async_icount icount; -  	struct usb_serial_port *port;  }; @@ -397,7 +394,6 @@ static int qt2_open(struct tty_struct *tty, struct usb_serial_port *port)  		return status;  	} -	port_priv->is_open = true;  	port_priv->device_port = (u8) device_port;  	if (tty) @@ -417,19 +413,11 @@ static void qt2_close(struct usb_serial_port *port)  	serial = port->serial;  	port_priv = usb_get_serial_port_data(port); -	port_priv->is_open = false; -  	spin_lock_irqsave(&port_priv->urb_lock, flags);  	usb_kill_urb(port_priv->write_urb);  	port_priv->urb_in_use = false;  	spin_unlock_irqrestore(&port_priv->urb_lock, flags); -	mutex_lock(&port->serial->disc_mutex); -	if (port->serial->disconnected) { -		mutex_unlock(&port->serial->disc_mutex); -		return; -	} -  	/* flush the port transmit buffer */  	i = usb_control_msg(serial->dev,  			    usb_rcvctrlpipe(serial->dev, 0), @@ -460,8 +448,6 @@ static void qt2_close(struct usb_serial_port *port)  	if (i < 0)  		dev_err(&port->dev, "%s - close port failed %i\n",  			__func__, i); - -	mutex_unlock(&port->serial->disc_mutex);  }  static void qt2_disconnect(struct usb_serial *serial) @@ -494,71 +480,6 @@ static int get_serial_info(struct usb_serial_port *port,  	return 0;  } -static int wait_modem_info(struct usb_serial_port *port, unsigned int arg) -{ -	struct qt2_port_private *priv = usb_get_serial_port_data(port); -	struct async_icount prev, cur; -	unsigned long flags; - -	spin_lock_irqsave(&priv->lock, flags); -	prev = priv->icount; -	spin_unlock_irqrestore(&priv->lock, flags); - -	while (1) { -		wait_event_interruptible(port->delta_msr_wait, -					 (port->serial->disconnected || -					  (priv->icount.rng != prev.rng) || -					  (priv->icount.dsr != prev.dsr) || -					  (priv->icount.dcd != prev.dcd) || -					  (priv->icount.cts != prev.cts))); - -		if (signal_pending(current)) -			return -ERESTARTSYS; - -		if (port->serial->disconnected) -			return -EIO; - -		spin_lock_irqsave(&priv->lock, flags); -		cur = priv->icount; -		spin_unlock_irqrestore(&priv->lock, flags); - -		if ((prev.rng == cur.rng) && -		    (prev.dsr == cur.dsr) && -		    (prev.dcd == cur.dcd) && -		    (prev.cts == cur.cts)) -			return -EIO; - -		if ((arg & TIOCM_RNG && (prev.rng != cur.rng)) || -		    (arg & TIOCM_DSR && (prev.dsr != cur.dsr)) || -		    (arg & TIOCM_CD && (prev.dcd != cur.dcd)) || -		    (arg & TIOCM_CTS && (prev.cts != cur.cts))) -			return 0; -	} -	return 0; -} - -static int qt2_get_icount(struct tty_struct *tty, -			  struct serial_icounter_struct *icount) -{ -	struct usb_serial_port *port = tty->driver_data; -	struct qt2_port_private *priv = usb_get_serial_port_data(port); -	struct async_icount cnow = priv->icount; - -	icount->cts = cnow.cts; -	icount->dsr = cnow.dsr; -	icount->rng = cnow.rng; -	icount->dcd = cnow.dcd; -	icount->rx = cnow.rx; -	icount->tx = cnow.tx; -	icount->frame = cnow.frame; -	icount->overrun = cnow.overrun; -	icount->parity = cnow.parity; -	icount->brk = cnow.brk; -	icount->buf_overrun = cnow.buf_overrun; - -	return 0; -} -  static int qt2_ioctl(struct tty_struct *tty,  		     unsigned int cmd, unsigned long arg)  { @@ -568,10 +489,6 @@ static int qt2_ioctl(struct tty_struct *tty,  	case TIOCGSERIAL:  		return get_serial_info(port,  				       (struct serial_struct __user *)arg); - -	case TIOCMIWAIT: -		return wait_modem_info(port, arg); -  	default:  		break;  	} @@ -664,9 +581,7 @@ void qt2_process_read_urb(struct urb *urb)  						 __func__);  					break;  				} - -				if (port_priv->is_open) -					tty_flip_buffer_push(&port->port); +				tty_flip_buffer_push(&port->port);  				newport = *(ch + 3); @@ -709,8 +624,7 @@ void qt2_process_read_urb(struct urb *urb)  		tty_insert_flip_string(&port->port, ch, 1);  	} -	if (port_priv->is_open) -		tty_flip_buffer_push(&port->port); +	tty_flip_buffer_push(&port->port);  }  static void qt2_write_bulk_callback(struct urb *urb) @@ -910,12 +824,6 @@ static void qt2_break_ctl(struct tty_struct *tty, int break_state)  	port_priv = usb_get_serial_port_data(port); -	if (!port_priv->is_open) { -		dev_err(&port->dev, -			"%s - port is not open\n", __func__); -		return; -	} -  	val = (break_state == -1) ? 1 : 0;  	status = qt2_control_msg(port->serial->dev, QT2_BREAK_CONTROL, @@ -961,18 +869,15 @@ static void qt2_update_msr(struct usb_serial_port *port, unsigned char *ch)  	if (newMSR & UART_MSR_ANY_DELTA) {  		/* update input line counters */  		if (newMSR & UART_MSR_DCTS) -			port_priv->icount.cts++; - +			port->icount.cts++;  		if (newMSR & UART_MSR_DDSR) -			port_priv->icount.dsr++; - +			port->icount.dsr++;  		if (newMSR & UART_MSR_DDCD) -			port_priv->icount.dcd++; - +			port->icount.dcd++;  		if (newMSR & UART_MSR_TERI) -			port_priv->icount.rng++; +			port->icount.rng++; -		wake_up_interruptible(&port->delta_msr_wait); +		wake_up_interruptible(&port->port.delta_msr_wait);  	}  } @@ -992,7 +897,7 @@ static void qt2_update_lsr(struct usb_serial_port *port, unsigned char *ch)  	port_priv->shadowLSR = newLSR;  	spin_unlock_irqrestore(&port_priv->lock, flags); -	icount = &port_priv->icount; +	icount = &port->icount;  	if (newLSR & UART_LSR_BRK_ERROR_BITS) { @@ -1102,7 +1007,8 @@ static struct usb_serial_driver qt2_device = {  	.break_ctl           = qt2_break_ctl,  	.tiocmget            = qt2_tiocmget,  	.tiocmset            = qt2_tiocmset, -	.get_icount	     = qt2_get_icount, +	.tiocmiwait          = usb_serial_generic_tiocmiwait, +	.get_icount	     = usb_serial_generic_get_icount,  	.ioctl               = qt2_ioctl,  	.set_termios         = qt2_set_termios,  }; diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index c13f6e74774..8894665cd61 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c @@ -628,7 +628,6 @@ static void sierra_instat_callback(struct urb *urb)  			unsigned char signals = *((unsigned char *)  					urb->transfer_buffer +  					sizeof(struct usb_ctrlrequest)); -			struct tty_struct *tty;  			dev_dbg(&port->dev, "%s: signal x%x\n", __func__,  				signals); @@ -639,11 +638,8 @@ static void sierra_instat_callback(struct urb *urb)  			portdata->dsr_state = ((signals & 0x02) ? 1 : 0);  			portdata->ri_state = ((signals & 0x08) ? 1 : 0); -			tty = tty_port_tty_get(&port->port); -			if (tty && !C_CLOCAL(tty) && -					old_dcd_state && !portdata->dcd_state) -				tty_hangup(tty); -			tty_kref_put(tty); +			if (old_dcd_state && !portdata->dcd_state) +				tty_port_tty_hangup(&port->port, true);  		} else {  			dev_dbg(&port->dev, "%s: type %x req %x\n",  				__func__, req_pkt->bRequestType, @@ -778,30 +774,25 @@ static void sierra_close(struct usb_serial_port *port)  	portdata->rts_state = 0;  	portdata->dtr_state = 0; -	if (serial->dev) { -		mutex_lock(&serial->disc_mutex); -		if (!serial->disconnected) { -			serial->interface->needs_remote_wakeup = 0; -			/* odd error handling due to pm counters */ -			if (!usb_autopm_get_interface(serial->interface)) -				sierra_send_setup(port); -			else -				usb_autopm_get_interface_no_resume(serial->interface); -				 -		} -		mutex_unlock(&serial->disc_mutex); -		spin_lock_irq(&intfdata->susp_lock); -		portdata->opened = 0; -		spin_unlock_irq(&intfdata->susp_lock); +	mutex_lock(&serial->disc_mutex); +	if (!serial->disconnected) { +		serial->interface->needs_remote_wakeup = 0; +		/* odd error handling due to pm counters */ +		if (!usb_autopm_get_interface(serial->interface)) +			sierra_send_setup(port); +		else +			usb_autopm_get_interface_no_resume(serial->interface); +	} +	mutex_unlock(&serial->disc_mutex); +	spin_lock_irq(&intfdata->susp_lock); +	portdata->opened = 0; +	spin_unlock_irq(&intfdata->susp_lock); -		/* Stop reading urbs */ -		sierra_stop_rx_urbs(port); -		/* .. and release them */ -		for (i = 0; i < portdata->num_in_urbs; i++) { -			sierra_release_urb(portdata->in_urbs[i]); -			portdata->in_urbs[i] = NULL; -		} +	sierra_stop_rx_urbs(port); +	for (i = 0; i < portdata->num_in_urbs; i++) { +		sierra_release_urb(portdata->in_urbs[i]); +		portdata->in_urbs[i] = NULL;  	}  } diff --git a/drivers/usb/serial/spcp8x5.c b/drivers/usb/serial/spcp8x5.c index 549ef68ff5f..cf3df793c2b 100644 --- a/drivers/usb/serial/spcp8x5.c +++ b/drivers/usb/serial/spcp8x5.c @@ -1,7 +1,7 @@  /*   * spcp8x5 USB to serial adaptor driver   * - * Copyright (C) 2010 Johan Hovold (jhovold@gmail.com) + * Copyright (C) 2010-2013 Johan Hovold (jhovold@gmail.com)   * Copyright (C) 2006 Linxb (xubin.lin@worldplus.com.cn)   * Copyright (C) 2006 S1 Corp.   * @@ -13,8 +13,6 @@   *	it under the terms of the GNU General Public License as published by   *	the Free Software Foundation; either version 2 of the License, or   *	(at your option) any later version. - * - *   */  #include <linux/kernel.h>  #include <linux/errno.h> @@ -28,7 +26,10 @@  #include <linux/usb.h>  #include <linux/usb/serial.h> -#define DRIVER_DESC 	"SPCP8x5 USB to serial adaptor driver" +#define DRIVER_DESC	"SPCP8x5 USB to serial adaptor driver" + +#define SPCP825_QUIRK_NO_UART_STATUS	0x01 +#define SPCP825_QUIRK_NO_WORK_MODE	0x02  #define SPCP8x5_007_VID		0x04FC  #define SPCP8x5_007_PID		0x0201 @@ -46,13 +47,15 @@ static const struct usb_device_id id_table[] = {  	{ USB_DEVICE(SPCP8x5_INTERMATIC_VID, SPCP8x5_INTERMATIC_PID)},  	{ USB_DEVICE(SPCP8x5_835_VID, SPCP8x5_835_PID)},  	{ USB_DEVICE(SPCP8x5_008_VID, SPCP8x5_008_PID)}, -	{ USB_DEVICE(SPCP8x5_007_VID, SPCP8x5_007_PID)}, +	{ USB_DEVICE(SPCP8x5_007_VID, SPCP8x5_007_PID), +	  .driver_info = SPCP825_QUIRK_NO_UART_STATUS | +				SPCP825_QUIRK_NO_WORK_MODE },  	{ }					/* Terminating entry */  };  MODULE_DEVICE_TABLE(usb, id_table);  struct spcp8x5_usb_ctrl_arg { -	u8 	type; +	u8	type;  	u8	cmd;  	u8	cmd_type;  	u16	value; @@ -138,49 +141,33 @@ struct spcp8x5_usb_ctrl_arg {  #define UART_OVERRUN_ERROR		0x40  #define UART_CTS			0x80 -enum spcp8x5_type { -	SPCP825_007_TYPE, -	SPCP825_008_TYPE, -	SPCP825_PHILIP_TYPE, -	SPCP825_INTERMATIC_TYPE, -	SPCP835_TYPE, -}; -  struct spcp8x5_private { -	spinlock_t 	lock; -	enum spcp8x5_type	type; -	u8 			line_control; -	u8 			line_status; +	unsigned		quirks; +	spinlock_t		lock; +	u8			line_control;  }; +static int spcp8x5_probe(struct usb_serial *serial, +						const struct usb_device_id *id) +{ +	usb_set_serial_data(serial, (void *)id); + +	return 0; +} +  static int spcp8x5_port_probe(struct usb_serial_port *port)  { -	struct usb_serial *serial = port->serial; +	const struct usb_device_id *id = usb_get_serial_data(port->serial);  	struct spcp8x5_private *priv; -	enum spcp8x5_type type = SPCP825_007_TYPE; -	u16 product = le16_to_cpu(serial->dev->descriptor.idProduct); - -	if (product == 0x0201) -		type = SPCP825_007_TYPE; -	else if (product == 0x0231) -		type = SPCP835_TYPE; -	else if (product == 0x0235) -		type = SPCP825_008_TYPE; -	else if (product == 0x0204) -		type = SPCP825_INTERMATIC_TYPE; -	else if (product == 0x0471 && -		 serial->dev->descriptor.idVendor == cpu_to_le16(0x081e)) -		type = SPCP825_PHILIP_TYPE; -	dev_dbg(&serial->dev->dev, "device type = %d\n", (int)type);  	priv = kzalloc(sizeof(*priv), GFP_KERNEL);  	if (!priv)  		return -ENOMEM;  	spin_lock_init(&priv->lock); -	priv->type = type; +	priv->quirks = id->driver_info; -	usb_set_serial_port_data(port , priv); +	usb_set_serial_port_data(port, priv);  	return 0;  } @@ -195,86 +182,79 @@ static int spcp8x5_port_remove(struct usb_serial_port *port)  	return 0;  } -/* set the modem control line of the device. - * NOTE spcp825-007 not supported this */ -static int spcp8x5_set_ctrlLine(struct usb_device *dev, u8 value, -				enum spcp8x5_type type) +static int spcp8x5_set_ctrl_line(struct usb_serial_port *port, u8 mcr)  { +	struct spcp8x5_private *priv = usb_get_serial_port_data(port); +	struct usb_device *dev = port->serial->dev;  	int retval; -	u8 mcr = 0 ; -	if (type == SPCP825_007_TYPE) +	if (priv->quirks & SPCP825_QUIRK_NO_UART_STATUS)  		return -EPERM; -	mcr = (unsigned short)value;  	retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),  				 SET_UART_STATUS_TYPE, SET_UART_STATUS,  				 mcr, 0x04, NULL, 0, 100); -	if (retval != 0) -		dev_dbg(&dev->dev, "usb_control_msg return %#x\n", retval); +	if (retval != 0) { +		dev_err(&port->dev, "failed to set control lines: %d\n", +								retval); +	}  	return retval;  } -/* get the modem status register of the device - * NOTE spcp825-007 not supported this */ -static int spcp8x5_get_msr(struct usb_device *dev, u8 *status, -			   enum spcp8x5_type type) +static int spcp8x5_get_msr(struct usb_serial_port *port, u8 *status)  { -	u8 *status_buffer; +	struct spcp8x5_private *priv = usb_get_serial_port_data(port); +	struct usb_device *dev = port->serial->dev; +	u8 *buf;  	int ret; -	/* I return Permited not support here but seem inval device -	 * is more fix */ -	if (type == SPCP825_007_TYPE) +	if (priv->quirks & SPCP825_QUIRK_NO_UART_STATUS)  		return -EPERM; -	if (status == NULL) -		return -EINVAL; -	status_buffer = kmalloc(1, GFP_KERNEL); -	if (!status_buffer) +	buf = kzalloc(1, GFP_KERNEL); +	if (!buf)  		return -ENOMEM; -	status_buffer[0] = status[0];  	ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),  			      GET_UART_STATUS, GET_UART_STATUS_TYPE, -			      0, GET_UART_STATUS_MSR, status_buffer, 1, 100); +			      0, GET_UART_STATUS_MSR, buf, 1, 100);  	if (ret < 0) -		dev_dbg(&dev->dev, "Get MSR = 0x%p failed (error = %d)", -			status_buffer, ret); +		dev_err(&port->dev, "failed to get modem status: %d", ret); -	dev_dbg(&dev->dev, "0xc0:0x22:0:6  %d - 0x%p ", ret, status_buffer); -	status[0] = status_buffer[0]; -	kfree(status_buffer); +	dev_dbg(&port->dev, "0xc0:0x22:0:6  %d - 0x02%x", ret, *buf); +	*status = *buf; +	kfree(buf);  	return ret;  } -/* select the work mode. - * NOTE this function not supported by spcp825-007 */ -static void spcp8x5_set_workMode(struct usb_device *dev, u16 value, -				 u16 index, enum spcp8x5_type type) +static void spcp8x5_set_work_mode(struct usb_serial_port *port, u16 value, +								 u16 index)  { +	struct spcp8x5_private *priv = usb_get_serial_port_data(port); +	struct usb_device *dev = port->serial->dev;  	int ret; -	/* I return Permited not support here but seem inval device -	 * is more fix */ -	if (type == SPCP825_007_TYPE) +	if (priv->quirks & SPCP825_QUIRK_NO_WORK_MODE)  		return;  	ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),  			      SET_WORKING_MODE_TYPE, SET_WORKING_MODE,  			      value, index, NULL, 0, 100); -	dev_dbg(&dev->dev, "value = %#x , index = %#x\n", value, index); +	dev_dbg(&port->dev, "value = %#x , index = %#x\n", value, index);  	if (ret < 0) -		dev_dbg(&dev->dev, -			"RTSCTS usb_control_msg(enable flowctrl) = %d\n", ret); +		dev_err(&port->dev, "failed to set work mode: %d\n", ret);  }  static int spcp8x5_carrier_raised(struct usb_serial_port *port)  { -	struct spcp8x5_private *priv = usb_get_serial_port_data(port); -	if (priv->line_status & MSR_STATUS_LINE_DCD) +	u8 msr; +	int ret; + +	ret = spcp8x5_get_msr(port, &msr); +	if (ret || msr & MSR_STATUS_LINE_DCD)  		return 1; +  	return 0;  } @@ -293,20 +273,17 @@ static void spcp8x5_dtr_rts(struct usb_serial_port *port, int on)  						| MCR_CONTROL_LINE_RTS);  	control = priv->line_control;  	spin_unlock_irqrestore(&priv->lock, flags); -	spcp8x5_set_ctrlLine(port->serial->dev, control , priv->type); +	spcp8x5_set_ctrl_line(port, control);  }  static void spcp8x5_init_termios(struct tty_struct *tty)  { -	/* for the 1st time call this function */  	tty->termios = tty_std_termios;  	tty->termios.c_cflag = B115200 | CS8 | CREAD | HUPCL | CLOCAL;  	tty->termios.c_ispeed = 115200;  	tty->termios.c_ospeed = 115200;  } -/* set the serial param for transfer. we should check if we really need to - * transfer. if we set flow control we should do this too. */  static void spcp8x5_set_termios(struct tty_struct *tty,  		struct usb_serial_port *port, struct ktermios *old_termios)  { @@ -321,7 +298,6 @@ static void spcp8x5_set_termios(struct tty_struct *tty,  	int i;  	u8 control; -  	/* check that they really want us to change something */  	if (!tty_termios_hw_change(&tty->termios, old_termios))  		return; @@ -337,7 +313,7 @@ static void spcp8x5_set_termios(struct tty_struct *tty,  	if (control != priv->line_control) {  		control = priv->line_control;  		spin_unlock_irqrestore(&priv->lock, flags); -		spcp8x5_set_ctrlLine(serial->dev, control , priv->type); +		spcp8x5_set_ctrl_line(port, control);  	} else {  		spin_unlock_irqrestore(&priv->lock, flags);  	} @@ -397,9 +373,9 @@ static void spcp8x5_set_termios(struct tty_struct *tty,  	if (cflag & PARENB) {  		buf[1] |= (cflag & PARODD) ?  		SET_UART_FORMAT_PAR_ODD : SET_UART_FORMAT_PAR_EVEN ; -	} else +	} else {  		buf[1] |= SET_UART_FORMAT_PAR_NONE; - +	}  	uartdata = buf[0] | buf[1]<<8;  	i = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), @@ -412,22 +388,16 @@ static void spcp8x5_set_termios(struct tty_struct *tty,  	if (cflag & CRTSCTS) {  		/* enable hardware flow control */ -		spcp8x5_set_workMode(serial->dev, 0x000a, -				     SET_WORKING_MODE_U2C, priv->type); +		spcp8x5_set_work_mode(port, 0x000a, SET_WORKING_MODE_U2C);  	}  } -/* open the serial port. do some usb system call. set termios and get the line - * status of the device. */  static int spcp8x5_open(struct tty_struct *tty, struct usb_serial_port *port)  {  	struct ktermios tmp_termios;  	struct usb_serial *serial = port->serial;  	struct spcp8x5_private *priv = usb_get_serial_port_data(port);  	int ret; -	unsigned long flags; -	u8 status = 0x30; -	/* status 0x30 means DSR and CTS = 1 other CDC RI and delta = 0 */  	usb_clear_halt(serial->dev, port->write_urb->pipe);  	usb_clear_halt(serial->dev, port->read_urb->pipe); @@ -438,142 +408,16 @@ static int spcp8x5_open(struct tty_struct *tty, struct usb_serial_port *port)  	if (ret)  		return ret; -	spcp8x5_set_ctrlLine(serial->dev, priv->line_control , priv->type); +	spcp8x5_set_ctrl_line(port, priv->line_control); -	/* Setup termios */  	if (tty)  		spcp8x5_set_termios(tty, port, &tmp_termios); -	spcp8x5_get_msr(serial->dev, &status, priv->type); - -	/* may be we should update uart status here but now we did not do */ -	spin_lock_irqsave(&priv->lock, flags); -	priv->line_status = status & 0xf0 ; -	spin_unlock_irqrestore(&priv->lock, flags); -  	port->port.drain_delay = 256;  	return usb_serial_generic_open(tty, port);  } -static void spcp8x5_process_read_urb(struct urb *urb) -{ -	struct usb_serial_port *port = urb->context; -	struct spcp8x5_private *priv = usb_get_serial_port_data(port); -	unsigned char *data = urb->transfer_buffer; -	unsigned long flags; -	u8 status; -	char tty_flag; - -	/* get tty_flag from status */ -	tty_flag = TTY_NORMAL; - -	spin_lock_irqsave(&priv->lock, flags); -	status = priv->line_status; -	priv->line_status &= ~UART_STATE_TRANSIENT_MASK; -	spin_unlock_irqrestore(&priv->lock, flags); -	/* wake up the wait for termios */ -	wake_up_interruptible(&port->delta_msr_wait); - -	if (!urb->actual_length) -		return; - - -	if (status & UART_STATE_TRANSIENT_MASK) { -		/* break takes precedence over parity, which takes precedence -		 * over framing errors */ -		if (status & UART_BREAK_ERROR) -			tty_flag = TTY_BREAK; -		else if (status & UART_PARITY_ERROR) -			tty_flag = TTY_PARITY; -		else if (status & UART_FRAME_ERROR) -			tty_flag = TTY_FRAME; -		dev_dbg(&port->dev, "tty_flag = %d\n", tty_flag); - -		/* overrun is special, not associated with a char */ -		if (status & UART_OVERRUN_ERROR) -			tty_insert_flip_char(&port->port, 0, TTY_OVERRUN); - -		if (status & UART_DCD) { -			struct tty_struct *tty = tty_port_tty_get(&port->port); -			if (tty) { -				usb_serial_handle_dcd_change(port, tty, -				       priv->line_status & MSR_STATUS_LINE_DCD); -				tty_kref_put(tty); -			} -		} -	} - -	tty_insert_flip_string_fixed_flag(&port->port, data, tty_flag, -							urb->actual_length); -	tty_flip_buffer_push(&port->port); -} - -static int spcp8x5_wait_modem_info(struct usb_serial_port *port, -				   unsigned int arg) -{ -	struct spcp8x5_private *priv = usb_get_serial_port_data(port); -	unsigned long flags; -	unsigned int prevstatus; -	unsigned int status; -	unsigned int changed; - -	spin_lock_irqsave(&priv->lock, flags); -	prevstatus = priv->line_status; -	spin_unlock_irqrestore(&priv->lock, flags); - -	while (1) { -		/* wake up in bulk read */ -		interruptible_sleep_on(&port->delta_msr_wait); - -		/* see if a signal did it */ -		if (signal_pending(current)) -			return -ERESTARTSYS; - -		if (port->serial->disconnected) -			return -EIO; - -		spin_lock_irqsave(&priv->lock, flags); -		status = priv->line_status; -		spin_unlock_irqrestore(&priv->lock, flags); - -		changed = prevstatus^status; - -		if (((arg & TIOCM_RNG) && (changed & MSR_STATUS_LINE_RI)) || -		    ((arg & TIOCM_DSR) && (changed & MSR_STATUS_LINE_DSR)) || -		    ((arg & TIOCM_CD)  && (changed & MSR_STATUS_LINE_DCD)) || -		    ((arg & TIOCM_CTS) && (changed & MSR_STATUS_LINE_CTS))) -			return 0; - -		prevstatus = status; -	} -	/* NOTREACHED */ -	return 0; -} - -static int spcp8x5_ioctl(struct tty_struct *tty, -			 unsigned int cmd, unsigned long arg) -{ -	struct usb_serial_port *port = tty->driver_data; - -	dev_dbg(&port->dev, "%s (%d) cmd = 0x%04x\n", __func__, -		port->number, cmd); - -	switch (cmd) { -	case TIOCMIWAIT: -		dev_dbg(&port->dev, "%s (%d) TIOCMIWAIT\n", __func__, -			port->number); -		return spcp8x5_wait_modem_info(port, arg); - -	default: -		dev_dbg(&port->dev, "%s not supported = 0x%04x", __func__, -			cmd); -		break; -	} - -	return -ENOIOCTLCMD; -} -  static int spcp8x5_tiocmset(struct tty_struct *tty,  			    unsigned int set, unsigned int clear)  { @@ -594,7 +438,7 @@ static int spcp8x5_tiocmset(struct tty_struct *tty,  	control = priv->line_control;  	spin_unlock_irqrestore(&priv->lock, flags); -	return spcp8x5_set_ctrlLine(port->serial->dev, control , priv->type); +	return spcp8x5_set_ctrl_line(port, control);  }  static int spcp8x5_tiocmget(struct tty_struct *tty) @@ -603,12 +447,15 @@ static int spcp8x5_tiocmget(struct tty_struct *tty)  	struct spcp8x5_private *priv = usb_get_serial_port_data(port);  	unsigned long flags;  	unsigned int mcr; -	unsigned int status; +	u8 status;  	unsigned int result; +	result = spcp8x5_get_msr(port, &status); +	if (result) +		return result; +  	spin_lock_irqsave(&priv->lock, flags);  	mcr = priv->line_control; -	status = priv->line_status;  	spin_unlock_irqrestore(&priv->lock, flags);  	result = ((mcr & MCR_DTR)			? TIOCM_DTR : 0) @@ -621,7 +468,6 @@ static int spcp8x5_tiocmget(struct tty_struct *tty)  	return result;  } -/* All of the device info needed for the spcp8x5 SIO serial converter */  static struct usb_serial_driver spcp8x5_device = {  	.driver = {  		.owner =	THIS_MODULE, @@ -629,17 +475,16 @@ static struct usb_serial_driver spcp8x5_device = {  	},  	.id_table		= id_table,  	.num_ports		= 1, -	.open 			= spcp8x5_open, +	.open			= spcp8x5_open,  	.dtr_rts		= spcp8x5_dtr_rts,  	.carrier_raised		= spcp8x5_carrier_raised, -	.set_termios 		= spcp8x5_set_termios, +	.set_termios		= spcp8x5_set_termios,  	.init_termios		= spcp8x5_init_termios, -	.ioctl 			= spcp8x5_ioctl, -	.tiocmget 		= spcp8x5_tiocmget, -	.tiocmset 		= spcp8x5_tiocmset, +	.tiocmget		= spcp8x5_tiocmget, +	.tiocmset		= spcp8x5_tiocmset, +	.probe			= spcp8x5_probe,  	.port_probe		= spcp8x5_port_probe,  	.port_remove		= spcp8x5_port_remove, -	.process_read_urb	= spcp8x5_process_read_urb,  };  static struct usb_serial_driver * const serial_drivers[] = { diff --git a/drivers/usb/serial/ssu100.c b/drivers/usb/serial/ssu100.c index 4b2a19757b4..5b62dbbdf99 100644 --- a/drivers/usb/serial/ssu100.c +++ b/drivers/usb/serial/ssu100.c @@ -61,7 +61,6 @@ struct ssu100_port_private {  	spinlock_t status_lock;  	u8 shadowLSR;  	u8 shadowMSR; -	struct async_icount icount;  };  static inline int ssu100_control_msg(struct usb_device *dev, @@ -315,11 +314,6 @@ static int ssu100_open(struct tty_struct *tty, struct usb_serial_port *port)  	return usb_serial_generic_open(tty, port);  } -static void ssu100_close(struct usb_serial_port *port) -{ -	usb_serial_generic_close(port); -} -  static int get_serial_info(struct usb_serial_port *port,  			   struct serial_struct __user *retinfo)  { @@ -343,73 +337,6 @@ static int get_serial_info(struct usb_serial_port *port,  	return 0;  } -static int wait_modem_info(struct usb_serial_port *port, unsigned int arg) -{ -	struct ssu100_port_private *priv = usb_get_serial_port_data(port); -	struct async_icount prev, cur; -	unsigned long flags; - -	spin_lock_irqsave(&priv->status_lock, flags); -	prev = priv->icount; -	spin_unlock_irqrestore(&priv->status_lock, flags); - -	while (1) { -		wait_event_interruptible(port->delta_msr_wait, -					 (port->serial->disconnected || -					  (priv->icount.rng != prev.rng) || -					  (priv->icount.dsr != prev.dsr) || -					  (priv->icount.dcd != prev.dcd) || -					  (priv->icount.cts != prev.cts))); - -		if (signal_pending(current)) -			return -ERESTARTSYS; - -		if (port->serial->disconnected) -			return -EIO; - -		spin_lock_irqsave(&priv->status_lock, flags); -		cur = priv->icount; -		spin_unlock_irqrestore(&priv->status_lock, flags); - -		if ((prev.rng == cur.rng) && -		    (prev.dsr == cur.dsr) && -		    (prev.dcd == cur.dcd) && -		    (prev.cts == cur.cts)) -			return -EIO; - -		if ((arg & TIOCM_RNG && (prev.rng != cur.rng)) || -		    (arg & TIOCM_DSR && (prev.dsr != cur.dsr)) || -		    (arg & TIOCM_CD  && (prev.dcd != cur.dcd)) || -		    (arg & TIOCM_CTS && (prev.cts != cur.cts))) -			return 0; -	} -	return 0; -} - -static int ssu100_get_icount(struct tty_struct *tty, -			struct serial_icounter_struct *icount) -{ -	struct usb_serial_port *port = tty->driver_data; -	struct ssu100_port_private *priv = usb_get_serial_port_data(port); -	struct async_icount cnow = priv->icount; - -	icount->cts = cnow.cts; -	icount->dsr = cnow.dsr; -	icount->rng = cnow.rng; -	icount->dcd = cnow.dcd; -	icount->rx = cnow.rx; -	icount->tx = cnow.tx; -	icount->frame = cnow.frame; -	icount->overrun = cnow.overrun; -	icount->parity = cnow.parity; -	icount->brk = cnow.brk; -	icount->buf_overrun = cnow.buf_overrun; - -	return 0; -} - - -  static int ssu100_ioctl(struct tty_struct *tty,  		    unsigned int cmd, unsigned long arg)  { @@ -421,10 +348,6 @@ static int ssu100_ioctl(struct tty_struct *tty,  	case TIOCGSERIAL:  		return get_serial_info(port,  				       (struct serial_struct __user *) arg); - -	case TIOCMIWAIT: -		return wait_modem_info(port, arg); -  	default:  		break;  	} @@ -532,14 +455,14 @@ static void ssu100_update_msr(struct usb_serial_port *port, u8 msr)  	if (msr & UART_MSR_ANY_DELTA) {  		/* update input line counters */  		if (msr & UART_MSR_DCTS) -			priv->icount.cts++; +			port->icount.cts++;  		if (msr & UART_MSR_DDSR) -			priv->icount.dsr++; +			port->icount.dsr++;  		if (msr & UART_MSR_DDCD) -			priv->icount.dcd++; +			port->icount.dcd++;  		if (msr & UART_MSR_TERI) -			priv->icount.rng++; -		wake_up_interruptible(&port->delta_msr_wait); +			port->icount.rng++; +		wake_up_interruptible(&port->port.delta_msr_wait);  	}  } @@ -558,22 +481,22 @@ static void ssu100_update_lsr(struct usb_serial_port *port, u8 lsr,  		/* we always want to update icount, but we only want to  		 * update tty_flag for one case */  		if (lsr & UART_LSR_BI) { -			priv->icount.brk++; +			port->icount.brk++;  			*tty_flag = TTY_BREAK;  			usb_serial_handle_break(port);  		}  		if (lsr & UART_LSR_PE) { -			priv->icount.parity++; +			port->icount.parity++;  			if (*tty_flag == TTY_NORMAL)  				*tty_flag = TTY_PARITY;  		}  		if (lsr & UART_LSR_FE) { -			priv->icount.frame++; +			port->icount.frame++;  			if (*tty_flag == TTY_NORMAL)  				*tty_flag = TTY_FRAME;  		}  		if (lsr & UART_LSR_OE){ -			priv->icount.overrun++; +			port->icount.overrun++;  			if (*tty_flag == TTY_NORMAL)  				*tty_flag = TTY_OVERRUN;  		} @@ -630,7 +553,6 @@ static struct usb_serial_driver ssu100_device = {  	.id_table	     = id_table,  	.num_ports	     = 1,  	.open		     = ssu100_open, -	.close		     = ssu100_close,  	.attach              = ssu100_attach,  	.port_probe          = ssu100_port_probe,  	.port_remove         = ssu100_port_remove, @@ -638,10 +560,10 @@ static struct usb_serial_driver ssu100_device = {  	.process_read_urb    = ssu100_process_read_urb,  	.tiocmget            = ssu100_tiocmget,  	.tiocmset            = ssu100_tiocmset, -	.get_icount	     = ssu100_get_icount, +	.tiocmiwait          = usb_serial_generic_tiocmiwait, +	.get_icount	     = usb_serial_generic_get_icount,  	.ioctl               = ssu100_ioctl,  	.set_termios         = ssu100_set_termios, -	.disconnect          = usb_serial_generic_disconnect,  };  static struct usb_serial_driver * const serial_drivers[] = { diff --git a/drivers/usb/serial/symbolserial.c b/drivers/usb/serial/symbolserial.c index be05e6caf9a..9b1648945e7 100644 --- a/drivers/usb/serial/symbolserial.c +++ b/drivers/usb/serial/symbolserial.c @@ -1,6 +1,7 @@  /*   * Symbol USB barcode to serial driver   * + * Copyright (C) 2013 Johan Hovold <jhovold@gmail.com>   * Copyright (C) 2009 Greg Kroah-Hartman <gregkh@suse.de>   * Copyright (C) 2009 Novell Inc.   * @@ -26,27 +27,17 @@ static const struct usb_device_id id_table[] = {  };  MODULE_DEVICE_TABLE(usb, id_table); -/* This structure holds all of the individual device information */  struct symbol_private { -	struct usb_device *udev; -	struct usb_serial *serial; -	struct usb_serial_port *port; -	unsigned char *int_buffer; -	struct urb *int_urb; -	int buffer_size; -	u8 bInterval; -	u8 int_address;  	spinlock_t lock;	/* protects the following flags */  	bool throttled;  	bool actually_throttled; -	bool rts;  };  static void symbol_int_callback(struct urb *urb)  { -	struct symbol_private *priv = urb->context; +	struct usb_serial_port *port = urb->context; +	struct symbol_private *priv = usb_get_serial_port_data(port);  	unsigned char *data = urb->transfer_buffer; -	struct usb_serial_port *port = priv->port;  	int status = urb->status;  	int result;  	int data_length; @@ -84,7 +75,7 @@ static void symbol_int_callback(struct urb *urb)  		tty_insert_flip_string(&port->port, &data[1], data_length);  		tty_flip_buffer_push(&port->port);  	} else { -		dev_dbg(&priv->udev->dev, +		dev_dbg(&port->dev,  			"Improper amount of data received from the device, "  			"%d bytes", urb->actual_length);  	} @@ -94,12 +85,7 @@ exit:  	/* Continue trying to always read if we should */  	if (!priv->throttled) { -		usb_fill_int_urb(priv->int_urb, priv->udev, -				 usb_rcvintpipe(priv->udev, -				 		priv->int_address), -				 priv->int_buffer, priv->buffer_size, -				 symbol_int_callback, priv, priv->bInterval); -		result = usb_submit_urb(priv->int_urb, GFP_ATOMIC); +		result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);  		if (result)  			dev_err(&port->dev,  			    "%s - failed resubmitting read urb, error %d\n", @@ -118,15 +104,10 @@ static int symbol_open(struct tty_struct *tty, struct usb_serial_port *port)  	spin_lock_irqsave(&priv->lock, flags);  	priv->throttled = false;  	priv->actually_throttled = false; -	priv->port = port;  	spin_unlock_irqrestore(&priv->lock, flags);  	/* Start reading from the device */ -	usb_fill_int_urb(priv->int_urb, priv->udev, -			 usb_rcvintpipe(priv->udev, priv->int_address), -			 priv->int_buffer, priv->buffer_size, -			 symbol_int_callback, priv, priv->bInterval); -	result = usb_submit_urb(priv->int_urb, GFP_KERNEL); +	result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);  	if (result)  		dev_err(&port->dev,  			"%s - failed resubmitting read urb, error %d\n", @@ -136,10 +117,7 @@ static int symbol_open(struct tty_struct *tty, struct usb_serial_port *port)  static void symbol_close(struct usb_serial_port *port)  { -	struct symbol_private *priv = usb_get_serial_data(port->serial); - -	/* shutdown our urbs */ -	usb_kill_urb(priv->int_urb); +	usb_kill_urb(port->interrupt_in_urb);  }  static void symbol_throttle(struct tty_struct *tty) @@ -166,7 +144,7 @@ static void symbol_unthrottle(struct tty_struct *tty)  	spin_unlock_irq(&priv->lock);  	if (was_throttled) { -		result = usb_submit_urb(priv->int_urb, GFP_KERNEL); +		result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);  		if (result)  			dev_err(&port->dev,  				"%s - failed submitting read urb, error %d\n", @@ -176,89 +154,36 @@ static void symbol_unthrottle(struct tty_struct *tty)  static int symbol_startup(struct usb_serial *serial)  { -	struct symbol_private *priv; -	struct usb_host_interface *intf; -	int i; -	int retval = -ENOMEM; -	bool int_in_found = false; - -	/* create our private serial structure */ -	priv = kzalloc(sizeof(*priv), GFP_KERNEL); -	if (priv == NULL) { -		dev_err(&serial->dev->dev, "%s - Out of memory\n", __func__); -		return -ENOMEM; +	if (!serial->num_interrupt_in) { +		dev_err(&serial->dev->dev, "no interrupt-in endpoint\n"); +		return -ENODEV;  	} -	spin_lock_init(&priv->lock); -	priv->serial = serial; -	priv->port = serial->port[0]; -	priv->udev = serial->dev; -	/* find our interrupt endpoint */ -	intf = serial->interface->altsetting; -	for (i = 0; i < intf->desc.bNumEndpoints; ++i) { -		struct usb_endpoint_descriptor *endpoint; - -		endpoint = &intf->endpoint[i].desc; -		if (!usb_endpoint_is_int_in(endpoint)) -			continue; - -		priv->int_urb = usb_alloc_urb(0, GFP_KERNEL); -		if (!priv->int_urb) { -			dev_err(&priv->udev->dev, "out of memory\n"); -			goto error; -		} - -		priv->buffer_size = usb_endpoint_maxp(endpoint) * 2; -		priv->int_buffer = kmalloc(priv->buffer_size, GFP_KERNEL); -		if (!priv->int_buffer) { -			dev_err(&priv->udev->dev, "out of memory\n"); -			goto error; -		} +	return 0; +} -		priv->int_address = endpoint->bEndpointAddress; -		priv->bInterval = endpoint->bInterval; +static int symbol_port_probe(struct usb_serial_port *port) +{ +	struct symbol_private *priv; -		/* set up our int urb */ -		usb_fill_int_urb(priv->int_urb, priv->udev, -				 usb_rcvintpipe(priv->udev, -				 		endpoint->bEndpointAddress), -				 priv->int_buffer, priv->buffer_size, -				 symbol_int_callback, priv, priv->bInterval); +	priv = kzalloc(sizeof(*priv), GFP_KERNEL); +	if (!priv) +		return -ENOMEM; -		int_in_found = true; -		break; -		} +	spin_lock_init(&priv->lock); -	if (!int_in_found) { -		dev_err(&priv->udev->dev, -			"Error - the proper endpoints were not found!\n"); -		goto error; -	} +	usb_set_serial_port_data(port, priv); -	usb_set_serial_data(serial, priv);  	return 0; - -error: -	usb_free_urb(priv->int_urb); -	kfree(priv->int_buffer); -	kfree(priv); -	return retval;  } -static void symbol_disconnect(struct usb_serial *serial) +static int symbol_port_remove(struct usb_serial_port *port)  { -	struct symbol_private *priv = usb_get_serial_data(serial); +	struct symbol_private *priv = usb_get_serial_port_data(port); -	usb_kill_urb(priv->int_urb); -	usb_free_urb(priv->int_urb); -} - -static void symbol_release(struct usb_serial *serial) -{ -	struct symbol_private *priv = usb_get_serial_data(serial); - -	kfree(priv->int_buffer);  	kfree(priv); + +	return 0;  }  static struct usb_serial_driver symbol_device = { @@ -269,12 +194,13 @@ static struct usb_serial_driver symbol_device = {  	.id_table =		id_table,  	.num_ports =		1,  	.attach =		symbol_startup, +	.port_probe =		symbol_port_probe, +	.port_remove =		symbol_port_remove,  	.open =			symbol_open,  	.close =		symbol_close, -	.disconnect =		symbol_disconnect, -	.release =		symbol_release,  	.throttle = 		symbol_throttle,  	.unthrottle =		symbol_unthrottle, +	.read_int_callback =	symbol_int_callback,  };  static struct usb_serial_driver * const serial_drivers[] = { diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c index 73deb029fc0..cac47aef291 100644 --- a/drivers/usb/serial/ti_usb_3410_5052.c +++ b/drivers/usb/serial/ti_usb_3410_5052.c @@ -67,13 +67,10 @@  struct ti_port {  	int			tp_is_open;  	__u8			tp_msr; -	__u8			tp_lsr;  	__u8			tp_shadow_mcr;  	__u8			tp_uart_mode;	/* 232 or 485 modes */  	unsigned int		tp_uart_base_addr;  	int			tp_flags; -	int			tp_closing_wait;/* in .01 secs */ -	struct async_icount	tp_icount;  	wait_queue_head_t	tp_write_wait;  	struct ti_device	*tp_tdev;  	struct usb_serial_port	*tp_port; @@ -108,8 +105,6 @@ static void ti_throttle(struct tty_struct *tty);  static void ti_unthrottle(struct tty_struct *tty);  static int ti_ioctl(struct tty_struct *tty,  		unsigned int cmd, unsigned long arg); -static int ti_get_icount(struct tty_struct *tty, -		struct serial_icounter_struct *icount);  static void ti_set_termios(struct tty_struct *tty,  		struct usb_serial_port *port, struct ktermios *old_termios);  static int ti_tiocmget(struct tty_struct *tty); @@ -124,15 +119,13 @@ static void ti_recv(struct usb_serial_port *port, unsigned char *data,  		int length);  static void ti_send(struct ti_port *tport);  static int ti_set_mcr(struct ti_port *tport, unsigned int mcr); -static int ti_get_lsr(struct ti_port *tport); +static int ti_get_lsr(struct ti_port *tport, u8 *lsr);  static int ti_get_serial_info(struct ti_port *tport,  	struct serial_struct __user *ret_arg);  static int ti_set_serial_info(struct tty_struct *tty, struct ti_port *tport,  	struct serial_struct __user *new_arg);  static void ti_handle_new_msr(struct ti_port *tport, __u8 msr); -static void ti_drain(struct ti_port *tport, unsigned long timeout, int flush); -  static void ti_stop_read(struct ti_port *tport, struct tty_struct *tty);  static int ti_restart_read(struct ti_port *tport, struct tty_struct *tty); @@ -235,7 +228,8 @@ static struct usb_serial_driver ti_1port_device = {  	.set_termios		= ti_set_termios,  	.tiocmget		= ti_tiocmget,  	.tiocmset		= ti_tiocmset, -	.get_icount		= ti_get_icount, +	.tiocmiwait		= usb_serial_generic_tiocmiwait, +	.get_icount		= usb_serial_generic_get_icount,  	.break_ctl		= ti_break,  	.read_int_callback	= ti_interrupt_callback,  	.read_bulk_callback	= ti_bulk_in_callback, @@ -265,7 +259,8 @@ static struct usb_serial_driver ti_2port_device = {  	.set_termios		= ti_set_termios,  	.tiocmget		= ti_tiocmget,  	.tiocmset		= ti_tiocmset, -	.get_icount		= ti_get_icount, +	.tiocmiwait		= usb_serial_generic_tiocmiwait, +	.get_icount		= usb_serial_generic_get_icount,  	.break_ctl		= ti_break,  	.read_int_callback	= ti_interrupt_callback,  	.read_bulk_callback	= ti_bulk_in_callback, @@ -430,7 +425,7 @@ static int ti_port_probe(struct usb_serial_port *port)  		tport->tp_uart_base_addr = TI_UART1_BASE_ADDR;  	else  		tport->tp_uart_base_addr = TI_UART2_BASE_ADDR; -	tport->tp_closing_wait = closing_wait; +	port->port.closing_wait = msecs_to_jiffies(10 * closing_wait);  	init_waitqueue_head(&tport->tp_write_wait);  	if (kfifo_alloc(&tport->write_fifo, TI_WRITE_BUF_SIZE, GFP_KERNEL)) {  		kfree(tport); @@ -480,8 +475,6 @@ static int ti_open(struct tty_struct *tty, struct usb_serial_port *port)  	port_number = port->number - port->serial->minor; -	memset(&(tport->tp_icount), 0x00, sizeof(tport->tp_icount)); -  	tport->tp_msr = 0;  	tport->tp_shadow_mcr |= (TI_MCR_RTS | TI_MCR_DTR); @@ -585,6 +578,8 @@ static int ti_open(struct tty_struct *tty, struct usb_serial_port *port)  	tport->tp_is_open = 1;  	++tdev->td_open_port_count; +	port->port.drain_delay = 3; +  	goto release_lock;  unlink_int_urb: @@ -604,6 +599,7 @@ static void ti_close(struct usb_serial_port *port)  	int port_number;  	int status;  	int do_unlock; +	unsigned long flags;  	tdev = usb_get_serial_data(port->serial);  	tport = usb_get_serial_port_data(port); @@ -612,11 +608,12 @@ static void ti_close(struct usb_serial_port *port)  	tport->tp_is_open = 0; -	ti_drain(tport, (tport->tp_closing_wait*HZ)/100, 1); -  	usb_kill_urb(port->read_urb);  	usb_kill_urb(port->write_urb);  	tport->tp_write_urb_in_use = 0; +	spin_lock_irqsave(&tport->tp_lock, flags); +	kfifo_reset_out(&tport->write_fifo); +	spin_unlock_irqrestore(&tport->tp_lock, flags);  	port_number = port->number - port->serial->minor; @@ -687,6 +684,8 @@ static int ti_chars_in_buffer(struct tty_struct *tty)  	struct ti_port *tport = usb_get_serial_port_data(port);  	int chars = 0;  	unsigned long flags; +	int ret; +	u8 lsr;  	if (tport == NULL)  		return 0; @@ -695,6 +694,12 @@ static int ti_chars_in_buffer(struct tty_struct *tty)  	chars = kfifo_len(&tport->write_fifo);  	spin_unlock_irqrestore(&tport->tp_lock, flags); +	if (!chars) { +		ret = ti_get_lsr(tport, &lsr); +		if (!ret && !(lsr & TI_LSR_TX_EMPTY)) +			chars = 1; +	} +  	dev_dbg(&port->dev, "%s - returns %d\n", __func__, chars);  	return chars;  } @@ -731,38 +736,11 @@ static void ti_unthrottle(struct tty_struct *tty)  	}  } -static int ti_get_icount(struct tty_struct *tty, -		struct serial_icounter_struct *icount) -{ -	struct usb_serial_port *port = tty->driver_data; -	struct ti_port *tport = usb_get_serial_port_data(port); -	struct async_icount cnow = tport->tp_icount; - -	dev_dbg(&port->dev, "%s - TIOCGICOUNT RX=%d, TX=%d\n", __func__, -		cnow.rx, cnow.tx); - -	icount->cts = cnow.cts; -	icount->dsr = cnow.dsr; -	icount->rng = cnow.rng; -	icount->dcd = cnow.dcd; -	icount->rx = cnow.rx; -	icount->tx = cnow.tx; -	icount->frame = cnow.frame; -	icount->overrun = cnow.overrun; -	icount->parity = cnow.parity; -	icount->brk = cnow.brk; -	icount->buf_overrun = cnow.buf_overrun; - -	return 0; -} -  static int ti_ioctl(struct tty_struct *tty,  	unsigned int cmd, unsigned long arg)  {  	struct usb_serial_port *port = tty->driver_data;  	struct ti_port *tport = usb_get_serial_port_data(port); -	struct async_icount cnow; -	struct async_icount cprev;  	dev_dbg(&port->dev, "%s - cmd = 0x%04X\n", __func__, cmd); @@ -778,29 +756,6 @@ static int ti_ioctl(struct tty_struct *tty,  		dev_dbg(&port->dev, "%s - TIOCSSERIAL\n", __func__);  		return ti_set_serial_info(tty, tport,  				(struct serial_struct __user *)arg); -	case TIOCMIWAIT: -		dev_dbg(&port->dev, "%s - TIOCMIWAIT\n", __func__); -		cprev = tport->tp_icount; -		while (1) { -			interruptible_sleep_on(&port->delta_msr_wait); -			if (signal_pending(current)) -				return -ERESTARTSYS; - -			if (port->serial->disconnected) -				return -EIO; - -			cnow = tport->tp_icount; -			if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && -			    cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) -				return -EIO; /* no change => error */ -			if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || -			    ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || -			    ((arg & TIOCM_CD)  && (cnow.dcd != cprev.dcd)) || -			    ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) -				return 0; -			cprev = cnow; -		} -		break;  	}  	return -ENOIOCTLCMD;  } @@ -1018,8 +973,6 @@ static void ti_break(struct tty_struct *tty, int break_state)  	if (tport == NULL)  		return; -	ti_drain(tport, (tport->tp_closing_wait*HZ)/100, 0); -  	status = ti_write_byte(port, tport->tp_tdev,  		tport->tp_uart_base_addr + TI_UART_OFFSET_LCR,  		TI_LCR_BREAK, break_state == -1 ? TI_LCR_BREAK : 0); @@ -1156,7 +1109,7 @@ static void ti_bulk_in_callback(struct urb *urb)  		else  			ti_recv(port, urb->transfer_buffer, urb->actual_length);  		spin_lock(&tport->tp_lock); -		tport->tp_icount.rx += urb->actual_length; +		port->icount.rx += urb->actual_length;  		spin_unlock(&tport->tp_lock);  	} @@ -1229,7 +1182,6 @@ static void ti_send(struct ti_port *tport)  {  	int count, result;  	struct usb_serial_port *port = tport->tp_port; -	struct tty_struct *tty = tty_port_tty_get(&port->port);	/* FIXME */  	unsigned long flags;  	spin_lock_irqsave(&tport->tp_lock, flags); @@ -1265,19 +1217,17 @@ static void ti_send(struct ti_port *tport)  		/* TODO: reschedule ti_send */  	} else {  		spin_lock_irqsave(&tport->tp_lock, flags); -		tport->tp_icount.tx += count; +		port->icount.tx += count;  		spin_unlock_irqrestore(&tport->tp_lock, flags);  	}  	/* more room in the buffer for new writes, wakeup */ -	if (tty) -		tty_wakeup(tty); -	tty_kref_put(tty); +	tty_port_tty_wakeup(&port->port); +  	wake_up_interruptible(&tport->tp_write_wait);  	return;  unlock:  	spin_unlock_irqrestore(&tport->tp_lock, flags); -	tty_kref_put(tty);  	return;  } @@ -1300,7 +1250,7 @@ static int ti_set_mcr(struct ti_port *tport, unsigned int mcr)  } -static int ti_get_lsr(struct ti_port *tport) +static int ti_get_lsr(struct ti_port *tport, u8 *lsr)  {  	int size, status;  	struct ti_device *tdev = tport->tp_tdev; @@ -1326,7 +1276,7 @@ static int ti_get_lsr(struct ti_port *tport)  	dev_dbg(&port->dev, "%s - lsr 0x%02X\n", __func__, data->bLSR); -	tport->tp_lsr = data->bLSR; +	*lsr = data->bLSR;  free_data:  	kfree(data); @@ -1339,10 +1289,15 @@ static int ti_get_serial_info(struct ti_port *tport,  {  	struct usb_serial_port *port = tport->tp_port;  	struct serial_struct ret_serial; +	unsigned cwait;  	if (!ret_arg)  		return -EFAULT; +	cwait = port->port.closing_wait; +	if (cwait != ASYNC_CLOSING_WAIT_NONE) +		cwait = jiffies_to_msecs(cwait) / 10; +  	memset(&ret_serial, 0, sizeof(ret_serial));  	ret_serial.type = PORT_16550A; @@ -1351,7 +1306,7 @@ static int ti_get_serial_info(struct ti_port *tport,  	ret_serial.flags = tport->tp_flags;  	ret_serial.xmit_fifo_size = TI_WRITE_BUF_SIZE;  	ret_serial.baud_base = tport->tp_tdev->td_is_3410 ? 921600 : 460800; -	ret_serial.closing_wait = tport->tp_closing_wait; +	ret_serial.closing_wait = cwait;  	if (copy_to_user(ret_arg, &ret_serial, sizeof(*ret_arg)))  		return -EFAULT; @@ -1364,12 +1319,17 @@ static int ti_set_serial_info(struct tty_struct *tty, struct ti_port *tport,  	struct serial_struct __user *new_arg)  {  	struct serial_struct new_serial; +	unsigned cwait;  	if (copy_from_user(&new_serial, new_arg, sizeof(new_serial)))  		return -EFAULT; +	cwait = new_serial.closing_wait; +	if (cwait != ASYNC_CLOSING_WAIT_NONE) +		cwait = msecs_to_jiffies(10 * new_serial.closing_wait); +  	tport->tp_flags = new_serial.flags & TI_SET_SERIAL_FLAGS; -	tport->tp_closing_wait = new_serial.closing_wait; +	tport->tp_port->port.closing_wait = cwait;  	return 0;  } @@ -1385,7 +1345,7 @@ static void ti_handle_new_msr(struct ti_port *tport, __u8 msr)  	if (msr & TI_MSR_DELTA_MASK) {  		spin_lock_irqsave(&tport->tp_lock, flags); -		icount = &tport->tp_icount; +		icount = &tport->tp_port->icount;  		if (msr & TI_MSR_DELTA_CTS)  			icount->cts++;  		if (msr & TI_MSR_DELTA_DSR) @@ -1394,7 +1354,7 @@ static void ti_handle_new_msr(struct ti_port *tport, __u8 msr)  			icount->dcd++;  		if (msr & TI_MSR_DELTA_RI)  			icount->rng++; -		wake_up_interruptible(&tport->tp_port->delta_msr_wait); +		wake_up_interruptible(&tport->tp_port->port.delta_msr_wait);  		spin_unlock_irqrestore(&tport->tp_lock, flags);  	} @@ -1414,56 +1374,6 @@ static void ti_handle_new_msr(struct ti_port *tport, __u8 msr)  } -static void ti_drain(struct ti_port *tport, unsigned long timeout, int flush) -{ -	struct ti_device *tdev = tport->tp_tdev; -	struct usb_serial_port *port = tport->tp_port; -	wait_queue_t wait; - -	spin_lock_irq(&tport->tp_lock); - -	/* wait for data to drain from the buffer */ -	tdev->td_urb_error = 0; -	init_waitqueue_entry(&wait, current); -	add_wait_queue(&tport->tp_write_wait, &wait); -	for (;;) { -		set_current_state(TASK_INTERRUPTIBLE); -		if (kfifo_len(&tport->write_fifo) == 0 -		|| timeout == 0 || signal_pending(current) -		|| tdev->td_urb_error -		|| port->serial->disconnected)  /* disconnect */ -			break; -		spin_unlock_irq(&tport->tp_lock); -		timeout = schedule_timeout(timeout); -		spin_lock_irq(&tport->tp_lock); -	} -	set_current_state(TASK_RUNNING); -	remove_wait_queue(&tport->tp_write_wait, &wait); - -	/* flush any remaining data in the buffer */ -	if (flush) -		kfifo_reset_out(&tport->write_fifo); - -	spin_unlock_irq(&tport->tp_lock); - -	mutex_lock(&port->serial->disc_mutex); -	/* wait for data to drain from the device */ -	/* wait for empty tx register, plus 20 ms */ -	timeout += jiffies; -	tport->tp_lsr &= ~TI_LSR_TX_EMPTY; -	while ((long)(jiffies - timeout) < 0 && !signal_pending(current) -	&& !(tport->tp_lsr&TI_LSR_TX_EMPTY) && !tdev->td_urb_error -	&& !port->serial->disconnected) { -		if (ti_get_lsr(tport)) -			break; -		mutex_unlock(&port->serial->disc_mutex); -		msleep_interruptible(20); -		mutex_lock(&port->serial->disc_mutex); -	} -	mutex_unlock(&port->serial->disc_mutex); -} - -  static void ti_stop_read(struct ti_port *tport, struct tty_struct *tty)  {  	unsigned long flags; diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 5d9b178484f..cf75beb1251 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -1,6 +1,7 @@  /*   * USB Serial Converter driver   * + * Copyright (C) 2009 - 2013 Johan Hovold (jhovold@gmail.com)   * Copyright (C) 1999 - 2012 Greg Kroah-Hartman (greg@kroah.com)   * Copyright (C) 2000 Peter Berger (pberger@brimson.com)   * Copyright (C) 2000 Al Borchers (borchers@steinerpoint.com) @@ -14,7 +15,6 @@   *   * See Documentation/usb/usb-serial.txt for more information on using this   * driver - *   */  #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt @@ -49,7 +49,6 @@     drivers depend on it.  */ -/* initially all NULL */  static struct usb_serial *serial_table[SERIAL_TTY_MINORS];  static DEFINE_MUTEX(table_lock);  static LIST_HEAD(usb_serial_driver_list); @@ -139,7 +138,7 @@ static void destroy_serial(struct kref *kref)  	if (serial->minor != SERIAL_TTY_NO_MINOR)  		return_serial(serial); -	if (serial->attached) +	if (serial->attached && serial->type->release)  		serial->type->release(serial);  	/* Now that nothing is using the ports, they can be freed */ @@ -225,7 +224,7 @@ static int serial_install(struct tty_driver *driver, struct tty_struct *tty)  	return retval;  } -static int serial_activate(struct tty_port *tport, struct tty_struct *tty) +static int serial_port_activate(struct tty_port *tport, struct tty_struct *tty)  {  	struct usb_serial_port *port =  		container_of(tport, struct usb_serial_port, port); @@ -249,30 +248,27 @@ static int serial_open(struct tty_struct *tty, struct file *filp)  {  	struct usb_serial_port *port = tty->driver_data; -	dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number); +	dev_dbg(tty->dev, "%s\n", __func__); +  	return tty_port_open(&port->port, tty, filp);  }  /** - * serial_down - shut down hardware + * serial_port_shutdown - shut down hardware   * @tport: tty port to shut down   * - * Shut down a USB serial port unless it is the console.  We never - * shut down the console hardware as it will always be in use. Serialized - * against activate by the tport mutex and kept to matching open/close pairs + * Shut down a USB serial port. Serialized against activate by the + * tport mutex and kept to matching open/close pairs   * of calls by the ASYNCB_INITIALIZED flag. + * + * Not called if tty is console.   */ -static void serial_down(struct tty_port *tport) +static void serial_port_shutdown(struct tty_port *tport)  {  	struct usb_serial_port *port =  		container_of(tport, struct usb_serial_port, port);  	struct usb_serial_driver *drv = port->serial->type; -	/* -	 * The console is magical.  Do not hang up the console hardware -	 * or there will be tears. -	 */ -	if (port->port.console) -		return; +  	if (drv->close)  		drv->close(port);  } @@ -281,7 +277,8 @@ static void serial_hangup(struct tty_struct *tty)  {  	struct usb_serial_port *port = tty->driver_data; -	dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number); +	dev_dbg(tty->dev, "%s\n", __func__); +  	tty_port_hangup(&port->port);  } @@ -289,7 +286,8 @@ static void serial_close(struct tty_struct *tty, struct file *filp)  {  	struct usb_serial_port *port = tty->driver_data; -	dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number); +	dev_dbg(tty->dev, "%s\n", __func__); +  	tty_port_close(&port->port, tty, filp);  } @@ -308,14 +306,14 @@ static void serial_cleanup(struct tty_struct *tty)  	struct usb_serial *serial;  	struct module *owner; +	dev_dbg(tty->dev, "%s\n", __func__); +  	/* The console is magical.  Do not hang up the console hardware  	 * or there will be tears.  	 */  	if (port->port.console)  		return; -	dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number); -  	tty->driver_data = NULL;  	serial = port->serial; @@ -339,10 +337,8 @@ static int serial_write(struct tty_struct *tty, const unsigned char *buf,  	if (port->serial->dev->state == USB_STATE_NOTATTACHED)  		goto exit; -	dev_dbg(tty->dev, "%s - port %d, %d byte(s)\n", __func__, -		port->number, count); +	dev_dbg(tty->dev, "%s - %d byte(s)\n", __func__, count); -	/* pass on to the driver specific version of this function */  	retval = port->serial->type->write(tty, port, buf, count);  	if (retval < 0)  		retval = usb_translate_errors(retval); @@ -354,8 +350,8 @@ static int serial_write_room(struct tty_struct *tty)  {  	struct usb_serial_port *port = tty->driver_data; -	dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number); -	/* pass on to the driver specific version of this function */ +	dev_dbg(tty->dev, "%s\n", __func__); +  	return port->serial->type->write_room(tty);  } @@ -365,7 +361,7 @@ static int serial_chars_in_buffer(struct tty_struct *tty)  	struct usb_serial *serial = port->serial;  	int count = 0; -	dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number); +	dev_dbg(tty->dev, "%s\n", __func__);  	mutex_lock(&serial->disc_mutex);  	/* if the device was unplugged then any remaining characters @@ -383,9 +379,8 @@ static void serial_throttle(struct tty_struct *tty)  {  	struct usb_serial_port *port = tty->driver_data; -	dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number); +	dev_dbg(tty->dev, "%s\n", __func__); -	/* pass on to the driver specific version of this function */  	if (port->serial->type->throttle)  		port->serial->type->throttle(tty);  } @@ -394,9 +389,8 @@ static void serial_unthrottle(struct tty_struct *tty)  {  	struct usb_serial_port *port = tty->driver_data; -	dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number); +	dev_dbg(tty->dev, "%s\n", __func__); -	/* pass on to the driver specific version of this function */  	if (port->serial->type->unthrottle)  		port->serial->type->unthrottle(tty);  } @@ -407,15 +401,20 @@ static int serial_ioctl(struct tty_struct *tty,  	struct usb_serial_port *port = tty->driver_data;  	int retval = -ENODEV; -	dev_dbg(tty->dev, "%s - port %d, cmd 0x%.4x\n", __func__, -		port->number, cmd); +	dev_dbg(tty->dev, "%s - cmd 0x%.4x\n", __func__, cmd); + +	switch (cmd) { +	case TIOCMIWAIT: +		if (port->serial->type->tiocmiwait) +			retval = port->serial->type->tiocmiwait(tty, arg); +		break; +	default: +		if (port->serial->type->ioctl) +			retval = port->serial->type->ioctl(tty, cmd, arg); +		else +			retval = -ENOIOCTLCMD; +	} -	/* pass on to the driver specific version of this function -	   if it is available */ -	if (port->serial->type->ioctl) { -		retval = port->serial->type->ioctl(tty, cmd, arg); -	} else -		retval = -ENOIOCTLCMD;  	return retval;  } @@ -423,10 +422,8 @@ static void serial_set_termios(struct tty_struct *tty, struct ktermios *old)  {  	struct usb_serial_port *port = tty->driver_data; -	dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number); +	dev_dbg(tty->dev, "%s\n", __func__); -	/* pass on to the driver specific version of this function -	   if it is available */  	if (port->serial->type->set_termios)  		port->serial->type->set_termios(tty, port, old);  	else @@ -437,12 +434,11 @@ static int serial_break(struct tty_struct *tty, int break_state)  {  	struct usb_serial_port *port = tty->driver_data; -	dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number); +	dev_dbg(tty->dev, "%s\n", __func__); -	/* pass on to the driver specific version of this function -	   if it is available */  	if (port->serial->type->break_ctl)  		port->serial->type->break_ctl(tty, break_state); +  	return 0;  } @@ -496,7 +492,7 @@ static int serial_tiocmget(struct tty_struct *tty)  {  	struct usb_serial_port *port = tty->driver_data; -	dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number); +	dev_dbg(tty->dev, "%s\n", __func__);  	if (port->serial->type->tiocmget)  		return port->serial->type->tiocmget(tty); @@ -508,7 +504,7 @@ static int serial_tiocmset(struct tty_struct *tty,  {  	struct usb_serial_port *port = tty->driver_data; -	dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number); +	dev_dbg(tty->dev, "%s\n", __func__);  	if (port->serial->type->tiocmset)  		return port->serial->type->tiocmset(tty, set, clear); @@ -520,7 +516,7 @@ static int serial_get_icount(struct tty_struct *tty,  {  	struct usb_serial_port *port = tty->driver_data; -	dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number); +	dev_dbg(tty->dev, "%s\n", __func__);  	if (port->serial->type->get_icount)  		return port->serial->type->get_icount(tty, icount); @@ -542,55 +538,43 @@ static void usb_serial_port_work(struct work_struct *work)  {  	struct usb_serial_port *port =  		container_of(work, struct usb_serial_port, work); -	struct tty_struct *tty; -	tty = tty_port_tty_get(&port->port); -	if (!tty) -		return; +	tty_port_tty_wakeup(&port->port); +} + +static void usb_serial_port_poison_urbs(struct usb_serial_port *port) +{ +	int i; -	dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number); +	for (i = 0; i < ARRAY_SIZE(port->read_urbs); ++i) +		usb_poison_urb(port->read_urbs[i]); +	for (i = 0; i < ARRAY_SIZE(port->write_urbs); ++i) +		usb_poison_urb(port->write_urbs[i]); -	tty_wakeup(tty); -	tty_kref_put(tty); +	usb_poison_urb(port->interrupt_in_urb); +	usb_poison_urb(port->interrupt_out_urb);  } -static void kill_traffic(struct usb_serial_port *port) +static void usb_serial_port_unpoison_urbs(struct usb_serial_port *port)  {  	int i;  	for (i = 0; i < ARRAY_SIZE(port->read_urbs); ++i) -		usb_kill_urb(port->read_urbs[i]); +		usb_unpoison_urb(port->read_urbs[i]);  	for (i = 0; i < ARRAY_SIZE(port->write_urbs); ++i) -		usb_kill_urb(port->write_urbs[i]); -	/* -	 * This is tricky. -	 * Some drivers submit the read_urb in the -	 * handler for the write_urb or vice versa -	 * this order determines the order in which -	 * usb_kill_urb() must be used to reliably -	 * kill the URBs. As it is unknown here, -	 * both orders must be used in turn. -	 * The call below is not redundant. -	 */ -	usb_kill_urb(port->read_urb); -	usb_kill_urb(port->interrupt_in_urb); -	usb_kill_urb(port->interrupt_out_urb); +		usb_unpoison_urb(port->write_urbs[i]); + +	usb_unpoison_urb(port->interrupt_in_urb); +	usb_unpoison_urb(port->interrupt_out_urb);  } -static void port_release(struct device *dev) +static void usb_serial_port_release(struct device *dev)  {  	struct usb_serial_port *port = to_usb_serial_port(dev);  	int i;  	dev_dbg(dev, "%s\n", __func__); -	/* -	 * Stop all the traffic before cancelling the work, so that -	 * nobody will restart it by calling usb_serial_port_softint. -	 */ -	kill_traffic(port); -	cancel_work_sync(&port->work); -  	usb_free_urb(port->interrupt_in_urb);  	usb_free_urb(port->interrupt_out_urb);  	for (i = 0; i < ARRAY_SIZE(port->read_urbs); ++i) { @@ -615,10 +599,8 @@ static struct usb_serial *create_serial(struct usb_device *dev,  	struct usb_serial *serial;  	serial = kzalloc(sizeof(*serial), GFP_KERNEL); -	if (!serial) { -		dev_err(&dev->dev, "%s - out of memory\n", __func__); +	if (!serial)  		return NULL; -	}  	serial->dev = usb_get_dev(dev);  	serial->type = driver;  	serial->interface = usb_get_intf(interface); @@ -681,7 +663,7 @@ static struct usb_serial_driver *search_serial_device(  	return NULL;  } -static int serial_carrier_raised(struct tty_port *port) +static int serial_port_carrier_raised(struct tty_port *port)  {  	struct usb_serial_port *p = container_of(port, struct usb_serial_port, port);  	struct usb_serial_driver *drv = p->serial->type; @@ -692,7 +674,7 @@ static int serial_carrier_raised(struct tty_port *port)  	return 1;  } -static void serial_dtr_rts(struct tty_port *port, int on) +static void serial_port_dtr_rts(struct tty_port *port, int on)  {  	struct usb_serial_port *p = container_of(port, struct usb_serial_port, port);  	struct usb_serial *serial = p->serial; @@ -712,10 +694,10 @@ static void serial_dtr_rts(struct tty_port *port, int on)  }  static const struct tty_port_operations serial_port_ops = { -	.carrier_raised = serial_carrier_raised, -	.dtr_rts = serial_dtr_rts, -	.activate = serial_activate, -	.shutdown = serial_down, +	.carrier_raised		= serial_port_carrier_raised, +	.dtr_rts		= serial_port_dtr_rts, +	.activate		= serial_port_activate, +	.shutdown		= serial_port_shutdown,  };  static int usb_serial_probe(struct usb_interface *interface, @@ -762,7 +744,6 @@ static int usb_serial_probe(struct usb_interface *interface,  	serial = create_serial(dev, interface, type);  	if (!serial) {  		module_put(type->driver.owner); -		dev_err(ddev, "%s - out of memory\n", __func__);  		return -ENOMEM;  	} @@ -903,7 +884,6 @@ static int usb_serial_probe(struct usb_interface *interface,  		port->port.ops = &serial_port_ops;  		port->serial = serial;  		spin_lock_init(&port->lock); -		init_waitqueue_head(&port->delta_msr_wait);  		/* Keep this for private driver use for the moment but  		   should probably go away */  		INIT_WORK(&port->work, usb_serial_port_work); @@ -911,7 +891,7 @@ static int usb_serial_probe(struct usb_interface *interface,  		port->dev.parent = &interface->dev;  		port->dev.driver = NULL;  		port->dev.bus = &usb_serial_bus_type; -		port->dev.release = &port_release; +		port->dev.release = &usb_serial_port_release;  		device_initialize(&port->dev);  	} @@ -927,16 +907,12 @@ static int usb_serial_probe(struct usb_interface *interface,  		for (j = 0; j < ARRAY_SIZE(port->read_urbs); ++j) {  			set_bit(j, &port->read_urbs_free);  			port->read_urbs[j] = usb_alloc_urb(0, GFP_KERNEL); -			if (!port->read_urbs[j]) { -				dev_err(ddev, "No free urbs available\n"); +			if (!port->read_urbs[j])  				goto probe_error; -			}  			port->bulk_in_buffers[j] = kmalloc(buffer_size,  								GFP_KERNEL); -			if (!port->bulk_in_buffers[j]) { -				dev_err(ddev, "Couldn't allocate bulk_in_buffer\n"); +			if (!port->bulk_in_buffers[j])  				goto probe_error; -			}  			usb_fill_bulk_urb(port->read_urbs[j], dev,  					usb_rcvbulkpipe(dev,  						endpoint->bEndpointAddress), @@ -963,16 +939,12 @@ static int usb_serial_probe(struct usb_interface *interface,  		for (j = 0; j < ARRAY_SIZE(port->write_urbs); ++j) {  			set_bit(j, &port->write_urbs_free);  			port->write_urbs[j] = usb_alloc_urb(0, GFP_KERNEL); -			if (!port->write_urbs[j]) { -				dev_err(ddev, "No free urbs available\n"); +			if (!port->write_urbs[j])  				goto probe_error; -			}  			port->bulk_out_buffers[j] = kmalloc(buffer_size,  								GFP_KERNEL); -			if (!port->bulk_out_buffers[j]) { -				dev_err(ddev, "Couldn't allocate bulk_out_buffer\n"); +			if (!port->bulk_out_buffers[j])  				goto probe_error; -			}  			usb_fill_bulk_urb(port->write_urbs[j], dev,  					usb_sndbulkpipe(dev,  						endpoint->bEndpointAddress), @@ -990,19 +962,15 @@ static int usb_serial_probe(struct usb_interface *interface,  			endpoint = interrupt_in_endpoint[i];  			port = serial->port[i];  			port->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL); -			if (!port->interrupt_in_urb) { -				dev_err(ddev, "No free urbs available\n"); +			if (!port->interrupt_in_urb)  				goto probe_error; -			}  			buffer_size = usb_endpoint_maxp(endpoint);  			port->interrupt_in_endpointAddress =  						endpoint->bEndpointAddress;  			port->interrupt_in_buffer = kmalloc(buffer_size,  								GFP_KERNEL); -			if (!port->interrupt_in_buffer) { -				dev_err(ddev, "Couldn't allocate interrupt_in_buffer\n"); +			if (!port->interrupt_in_buffer)  				goto probe_error; -			}  			usb_fill_int_urb(port->interrupt_in_urb, dev,  				usb_rcvintpipe(dev,  						endpoint->bEndpointAddress), @@ -1019,20 +987,16 @@ static int usb_serial_probe(struct usb_interface *interface,  			endpoint = interrupt_out_endpoint[i];  			port = serial->port[i];  			port->interrupt_out_urb = usb_alloc_urb(0, GFP_KERNEL); -			if (!port->interrupt_out_urb) { -				dev_err(ddev, "No free urbs available\n"); +			if (!port->interrupt_out_urb)  				goto probe_error; -			}  			buffer_size = usb_endpoint_maxp(endpoint);  			port->interrupt_out_size = buffer_size;  			port->interrupt_out_endpointAddress =  						endpoint->bEndpointAddress;  			port->interrupt_out_buffer = kmalloc(buffer_size,  								GFP_KERNEL); -			if (!port->interrupt_out_buffer) { -				dev_err(ddev, "Couldn't allocate interrupt_out_buffer\n"); +			if (!port->interrupt_out_buffer)  				goto probe_error; -			}  			usb_fill_int_urb(port->interrupt_out_urb, dev,  				usb_sndintpipe(dev,  						  endpoint->bEndpointAddress), @@ -1121,13 +1085,15 @@ static void usb_serial_disconnect(struct usb_interface *interface)  				tty_vhangup(tty);  				tty_kref_put(tty);  			} -			kill_traffic(port); +			usb_serial_port_poison_urbs(port); +			wake_up_interruptible(&port->port.delta_msr_wait);  			cancel_work_sync(&port->work);  			if (device_is_registered(&port->dev))  				device_del(&port->dev);  		}  	} -	serial->type->disconnect(serial); +	if (serial->type->disconnect) +		serial->type->disconnect(serial);  	/* let the last holder of this object cause it to be cleaned up */  	usb_serial_put(serial); @@ -1142,6 +1108,11 @@ int usb_serial_suspend(struct usb_interface *intf, pm_message_t message)  	serial->suspending = 1; +	/* +	 * serial->type->suspend() MUST return 0 in system sleep context, +	 * otherwise, the resume callback has to recover device from +	 * previous suspend failure. +	 */  	if (serial->type->suspend) {  		r = serial->type->suspend(serial, message);  		if (r < 0) { @@ -1153,7 +1124,7 @@ int usb_serial_suspend(struct usb_interface *intf, pm_message_t message)  	for (i = 0; i < serial->num_ports; ++i) {  		port = serial->port[i];  		if (port) -			kill_traffic(port); +			usb_serial_port_poison_urbs(port);  	}  err_out: @@ -1161,11 +1132,25 @@ err_out:  }  EXPORT_SYMBOL(usb_serial_suspend); +static void usb_serial_unpoison_port_urbs(struct usb_serial *serial) +{ +	struct usb_serial_port *port; +	int i; + +	for (i = 0; i < serial->num_ports; ++i) { +		port = serial->port[i]; +		if (port) +			usb_serial_port_unpoison_urbs(port); +	} +} +  int usb_serial_resume(struct usb_interface *intf)  {  	struct usb_serial *serial = usb_get_intfdata(intf);  	int rv; +	usb_serial_unpoison_port_urbs(serial); +  	serial->suspending = 0;  	if (serial->type->resume)  		rv = serial->type->resume(serial); @@ -1181,6 +1166,8 @@ static int usb_serial_reset_resume(struct usb_interface *intf)  	struct usb_serial *serial = usb_get_intfdata(intf);  	int rv; +	usb_serial_unpoison_port_urbs(serial); +  	serial->suspending = 0;  	if (serial->type->reset_resume)  		rv = serial->type->reset_resume(serial); @@ -1317,12 +1304,12 @@ module_exit(usb_serial_exit);  	do {								\  		if (!type->function) {					\  			type->function = usb_serial_generic_##function;	\ -			pr_debug("Had to override the " #function	\ -				" usb serial operation with the generic one.");\ -			}						\ +			pr_debug("%s: using generic " #function	"\n",	\ +						type->driver.name);	\ +		}							\  	} while (0) -static void fixup_generic(struct usb_serial_driver *device) +static void usb_serial_operations_init(struct usb_serial_driver *device)  {  	set_to_generic_if_null(device, open);  	set_to_generic_if_null(device, write); @@ -1331,8 +1318,6 @@ static void fixup_generic(struct usb_serial_driver *device)  	set_to_generic_if_null(device, chars_in_buffer);  	set_to_generic_if_null(device, read_bulk_callback);  	set_to_generic_if_null(device, write_bulk_callback); -	set_to_generic_if_null(device, disconnect); -	set_to_generic_if_null(device, release);  	set_to_generic_if_null(device, process_read_urb);  	set_to_generic_if_null(device, prepare_write_buffer);  } @@ -1344,8 +1329,6 @@ static int usb_serial_register(struct usb_serial_driver *driver)  	if (usb_disabled())  		return -ENODEV; -	fixup_generic(driver); -  	if (!driver->description)  		driver->description = driver->driver.name;  	if (!driver->usb_driver) { @@ -1354,6 +1337,8 @@ static int usb_serial_register(struct usb_serial_driver *driver)  		return -EINVAL;  	} +	usb_serial_operations_init(driver); +  	/* Add this device to our list of devices */  	mutex_lock(&table_lock);  	list_add(&driver->driver_list, &usb_serial_driver_list); @@ -1471,7 +1456,6 @@ void usb_serial_deregister_drivers(struct usb_serial_driver *const serial_driver  }  EXPORT_SYMBOL_GPL(usb_serial_deregister_drivers); -/* Module information */  MODULE_AUTHOR(DRIVER_AUTHOR);  MODULE_DESCRIPTION(DRIVER_DESC);  MODULE_LICENSE("GPL"); diff --git a/drivers/usb/serial/usb_wwan.c b/drivers/usb/serial/usb_wwan.c index 571965aa1cc..ece326ef63a 100644 --- a/drivers/usb/serial/usb_wwan.c +++ b/drivers/usb/serial/usb_wwan.c @@ -421,20 +421,19 @@ void usb_wwan_close(struct usb_serial_port *port)  	portdata = usb_get_serial_port_data(port); -	if (serial->dev) { -		/* Stop reading/writing urbs */ -		spin_lock_irq(&intfdata->susp_lock); -		portdata->opened = 0; -		spin_unlock_irq(&intfdata->susp_lock); +	/* Stop reading/writing urbs */ +	spin_lock_irq(&intfdata->susp_lock); +	portdata->opened = 0; +	spin_unlock_irq(&intfdata->susp_lock); -		for (i = 0; i < N_IN_URB; i++) -			usb_kill_urb(portdata->in_urbs[i]); -		for (i = 0; i < N_OUT_URB; i++) -			usb_kill_urb(portdata->out_urbs[i]); -		/* balancing - important as an error cannot be handled*/ -		usb_autopm_get_interface_no_resume(serial->interface); -		serial->interface->needs_remote_wakeup = 0; -	} +	for (i = 0; i < N_IN_URB; i++) +		usb_kill_urb(portdata->in_urbs[i]); +	for (i = 0; i < N_OUT_URB; i++) +		usb_kill_urb(portdata->out_urbs[i]); + +	/* balancing - important as an error cannot be handled*/ +	usb_autopm_get_interface_no_resume(serial->interface); +	serial->interface->needs_remote_wakeup = 0;  }  EXPORT_SYMBOL(usb_wwan_close); diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c index 1129aa73c23..7573ec8a084 100644 --- a/drivers/usb/serial/visor.c +++ b/drivers/usb/serial/visor.c @@ -257,24 +257,18 @@ static void visor_close(struct usb_serial_port *port)  {  	unsigned char *transfer_buffer; -	/* shutdown our urbs */  	usb_serial_generic_close(port);  	usb_kill_urb(port->interrupt_in_urb); -	mutex_lock(&port->serial->disc_mutex); -	if (!port->serial->disconnected) { -		/* Try to send shutdown message, unless the device is gone */ -		transfer_buffer =  kmalloc(0x12, GFP_KERNEL); -		if (transfer_buffer) { -			usb_control_msg(port->serial->dev, +	transfer_buffer = kmalloc(0x12, GFP_KERNEL); +	if (!transfer_buffer) +		return; +	usb_control_msg(port->serial->dev,  					 usb_rcvctrlpipe(port->serial->dev, 0),  					 VISOR_CLOSE_NOTIFICATION, 0xc2,  					 0x0000, 0x0000,  					 transfer_buffer, 0x12, 300); -			kfree(transfer_buffer); -		} -	} -	mutex_unlock(&port->serial->disc_mutex); +	kfree(transfer_buffer);  }  static void visor_read_int_callback(struct urb *urb) diff --git a/drivers/usb/serial/wishbone-serial.c b/drivers/usb/serial/wishbone-serial.c new file mode 100644 index 00000000000..100573c6f19 --- /dev/null +++ b/drivers/usb/serial/wishbone-serial.c @@ -0,0 +1,95 @@ +/* + * USB Wishbone-Serial adapter driver + * + * Copyright (C) 2013 Wesley W. Terpstra <w.terpstra@gsi.de> + * Copyright (C) 2013 GSI Helmholtz Centre for Heavy Ion Research GmbH + * + * 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 (at your option) any later version. + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/tty.h> +#include <linux/module.h> +#include <linux/usb.h> +#include <linux/usb/serial.h> +#include <linux/uaccess.h> + +#define GSI_VENDOR_OPENCLOSE 0xB0 + +static const struct usb_device_id id_table[] = { +	{ USB_DEVICE_AND_INTERFACE_INFO(0x1D50, 0x6062, 0xFF, 0xFF, 0xFF) }, +	{ }, +}; +MODULE_DEVICE_TABLE(usb, id_table); + +/* + * Etherbone must be told that a new stream has begun before data arrives. + * This is necessary to restart the negotiation of Wishbone bus parameters. + * Similarly, when the stream ends, Etherbone must be told so that the cycle + * line can be driven low in the case that userspace failed to do so. + */ +static int usb_gsi_openclose(struct usb_serial_port *port, int value) +{ +	struct usb_device *dev = port->serial->dev; + +	return usb_control_msg( +		dev, +		usb_sndctrlpipe(dev, 0), /* Send to EP0OUT */ +		GSI_VENDOR_OPENCLOSE, +		USB_DIR_OUT|USB_TYPE_VENDOR|USB_RECIP_INTERFACE, +		value, /* wValue = device is open(1) or closed(0) */ +		port->serial->interface->cur_altsetting->desc.bInterfaceNumber, +		NULL, 0,  /* There is no data stage */ +		5000); /* Timeout till operation fails */ +} + +static int wishbone_serial_open(struct tty_struct *tty, +				struct usb_serial_port *port) +{ +	int retval; + +	retval = usb_gsi_openclose(port, 1); +	if (retval) { +		dev_err(&port->serial->dev->dev, +		       "Could not mark device as open (%d)\n", +		       retval); +		return retval; +	} + +	retval = usb_serial_generic_open(tty, port); +	if (retval) +		usb_gsi_openclose(port, 0); + +	return retval; +} + +static void wishbone_serial_close(struct usb_serial_port *port) +{ +	usb_serial_generic_close(port); +	usb_gsi_openclose(port, 0); +} + +static struct usb_serial_driver wishbone_serial_device = { +	.driver = { +		.owner =	THIS_MODULE, +		.name =		"wishbone_serial", +	}, +	.id_table =		id_table, +	.num_ports =		1, +	.open =			&wishbone_serial_open, +	.close =		&wishbone_serial_close, +}; + +static struct usb_serial_driver * const serial_drivers[] = { +	&wishbone_serial_device, NULL +}; + +module_usb_serial_driver(serial_drivers, id_table); + +MODULE_AUTHOR("Wesley W. Terpstra <w.terpstra@gsi.de>"); +MODULE_DESCRIPTION("USB Wishbone-Serial adapter"); +MODULE_LICENSE("GPL");  |