X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fusb%2Fserial%2Fusb-serial.c;h=9c36f0ece20ff6b43631e860621198f694400d5f;hb=9464c7cf61b9433057924c36e6e02f303a00e768;hp=e06a41bd0f3ba4b458aaf11470c901965cff7710;hpb=41689045f6a3cbe0550e1d34e9cc20d2e8c432ba;p=linux-2.6.git diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index e06a41bd0..9c36f0ece 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -16,6 +16,7 @@ * */ +#include #include #include #include @@ -31,7 +32,7 @@ #include #include #include -#include +#include "usb-serial.h" #include "pl2303.h" /* @@ -40,8 +41,6 @@ #define DRIVER_AUTHOR "Greg Kroah-Hartman, greg@kroah.com, http://www.kroah.com/linux/" #define DRIVER_DESC "USB Serial Driver core" -static void port_free(struct usb_serial_port *port); - /* Driver structure we register with the USB core */ static struct usb_driver usb_serial_driver = { .name = "usbserial", @@ -148,7 +147,18 @@ static void destroy_serial(struct kref *kref) port = serial->port[i]; if (!port) continue; - port_free(port); + usb_kill_urb(port->read_urb); + usb_free_urb(port->read_urb); + usb_kill_urb(port->write_urb); + usb_free_urb(port->write_urb); + usb_kill_urb(port->interrupt_in_urb); + usb_free_urb(port->interrupt_in_urb); + usb_kill_urb(port->interrupt_out_urb); + usb_free_urb(port->interrupt_out_urb); + kfree(port->bulk_in_buffer); + kfree(port->bulk_out_buffer); + kfree(port->interrupt_in_buffer); + kfree(port->interrupt_out_buffer); } } @@ -158,11 +168,6 @@ static void destroy_serial(struct kref *kref) kfree (serial); } -void usb_serial_put(struct usb_serial *serial) -{ - kref_put(&serial->kref, destroy_serial); -} - /***************************************************************************** * Driver tty interface functions *****************************************************************************/ @@ -196,13 +201,13 @@ static int serial_open (struct tty_struct *tty, struct file * filp) ++port->open_count; - /* set up our port structure making the tty driver - * remember our port object, and us it */ - tty->driver_data = port; - port->tty = tty; - if (port->open_count == 1) { + /* set up our port structure making the tty driver + * remember our port object, and us it */ + tty->driver_data = port; + port->tty = tty; + /* lock this module before we call it * this may fail, which means we must bail out, * safe because we are called with BKL held */ @@ -225,11 +230,9 @@ bailout_module_put: module_put(serial->type->driver.owner); bailout_mutex_unlock: port->open_count = 0; - tty->driver_data = NULL; - port->tty = NULL; mutex_unlock(&port->mutex); bailout_kref_put: - usb_serial_put(serial); + kref_put(&serial->kref, destroy_serial); return retval; } @@ -265,7 +268,7 @@ static void serial_close(struct tty_struct *tty, struct file * filp) } mutex_unlock(&port->mutex); - usb_serial_put(port->serial); + kref_put(&port->serial->kref, destroy_serial); } static int serial_write (struct tty_struct * tty, const unsigned char *buf, int count) @@ -273,7 +276,7 @@ static int serial_write (struct tty_struct * tty, const unsigned char *buf, int struct usb_serial_port *port = tty->driver_data; int retval = -EINVAL; - if (!port || port->serial->dev->state == USB_STATE_NOTATTACHED) + if (!port) goto exit; dbg("%s - port %d, %d byte(s)", __FUNCTION__, port->number, count); @@ -293,7 +296,7 @@ exit: static int serial_write_room (struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; - int retval = -ENODEV; + int retval = -EINVAL; if (!port) goto exit; @@ -315,7 +318,7 @@ exit: static int serial_chars_in_buffer (struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; - int retval = -ENODEV; + int retval = -EINVAL; if (!port) goto exit; @@ -464,15 +467,13 @@ static int serial_read_proc (char *page, char **start, off_t off, int count, int length += sprintf (page+length, " path:%s", tmp); length += sprintf (page+length, "\n"); - if ((length + begin) > (off + count)) { - usb_serial_put(serial); + if ((length + begin) > (off + count)) goto done; - } if ((length + begin) < off) { begin += length; length = 0; } - usb_serial_put(serial); + kref_put(&serial->kref, destroy_serial); } *eof = 1; done: @@ -487,18 +488,19 @@ static int serial_tiocmget (struct tty_struct *tty, struct file *file) struct usb_serial_port *port = tty->driver_data; if (!port) - return -ENODEV; + goto exit; dbg("%s - port %d", __FUNCTION__, port->number); if (!port->open_count) { dbg("%s - port not open", __FUNCTION__); - return -ENODEV; + goto exit; } if (port->serial->type->tiocmget) return port->serial->type->tiocmget(port, file); +exit: return -EINVAL; } @@ -508,32 +510,23 @@ static int serial_tiocmset (struct tty_struct *tty, struct file *file, struct usb_serial_port *port = tty->driver_data; if (!port) - return -ENODEV; + goto exit; dbg("%s - port %d", __FUNCTION__, port->number); if (!port->open_count) { dbg("%s - port not open", __FUNCTION__); - return -ENODEV; + goto exit; } if (port->serial->type->tiocmset) return port->serial->type->tiocmset(port, file, set, clear); +exit: return -EINVAL; } -/* - * We would be calling tty_wakeup here, but unfortunately some line - * disciplines have an annoying habit of calling tty->write from - * the write wakeup callback (e.g. n_hdlc.c). - */ -void usb_serial_port_softint(struct usb_serial_port *port) -{ - schedule_work(&port->work); -} - -static void usb_serial_port_work(void *private) +void usb_serial_port_softint(void *private) { struct usb_serial_port *port = private; struct tty_struct *tty; @@ -555,11 +548,6 @@ static void port_release(struct device *dev) struct usb_serial_port *port = to_usb_serial_port(dev); dbg ("%s - %s", __FUNCTION__, dev->bus_id); - port_free(port); -} - -static void port_free(struct usb_serial_port *port) -{ usb_kill_urb(port->read_urb); usb_free_urb(port->read_urb); usb_kill_urb(port->write_urb); @@ -572,7 +560,6 @@ static void port_free(struct usb_serial_port *port) kfree(port->bulk_out_buffer); kfree(port->interrupt_in_buffer); kfree(port->interrupt_out_buffer); - flush_scheduled_work(); /* port->work */ kfree(port); } @@ -802,7 +789,7 @@ int usb_serial_probe(struct usb_interface *interface, port->serial = serial; spin_lock_init(&port->lock); mutex_init(&port->mutex); - INIT_WORK(&port->work, usb_serial_port_work, port); + INIT_WORK(&port->work, usb_serial_port_softint, port); serial->port[i] = port; } @@ -998,7 +985,6 @@ void usb_serial_disconnect(struct usb_interface *interface) struct device *dev = &interface->dev; struct usb_serial_port *port; - usb_serial_console_disconnect(serial); dbg ("%s", __FUNCTION__); usb_set_intfdata (interface, NULL); @@ -1010,7 +996,7 @@ void usb_serial_disconnect(struct usb_interface *interface) } /* let the last holder of this object * cause it to be cleaned up */ - usb_serial_put(serial); + kref_put(&serial->kref, destroy_serial); } dev_info(dev, "device disconnected\n"); } @@ -1055,12 +1041,13 @@ static int __init usb_serial_init(void) usb_serial_tty_driver->owner = THIS_MODULE; usb_serial_tty_driver->driver_name = "usbserial"; + usb_serial_tty_driver->devfs_name = "usb/tts/"; usb_serial_tty_driver->name = "ttyUSB"; usb_serial_tty_driver->major = SERIAL_TTY_MAJOR; usb_serial_tty_driver->minor_start = 0; usb_serial_tty_driver->type = TTY_DRIVER_TYPE_SERIAL; usb_serial_tty_driver->subtype = SERIAL_TYPE_NORMAL; - usb_serial_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; + usb_serial_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS; usb_serial_tty_driver->init_termios = tty_std_termios; usb_serial_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; tty_set_operations(usb_serial_tty_driver, &serial_ops);