diff options
Diffstat (limited to 'drivers/usb/serial/usb-serial.c')
| -rw-r--r-- | drivers/usb/serial/usb-serial.c | 236 | 
1 files changed, 110 insertions, 126 deletions
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");  |