tty: USB does not need the filp argument in the drivers
[deliverable/linux.git] / drivers / usb / serial / usb-serial.c
index a84216464ca01fa60a687974f0324b86bffdc137..3dda6841e72449d512c297a260c96f11ce6f2618 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/slab.h>
+#include <linux/smp_lock.h>
 #include <linux/tty.h>
 #include <linux/tty_driver.h>
 #include <linux/tty_flip.h>
@@ -31,6 +32,7 @@
 #include <linux/mutex.h>
 #include <linux/list.h>
 #include <linux/uaccess.h>
+#include <linux/serial.h>
 #include <linux/usb.h>
 #include <linux/usb/serial.h>
 #include "pl2303.h"
@@ -183,6 +185,7 @@ static int serial_open (struct tty_struct *tty, struct file *filp)
        struct usb_serial_port *port;
        unsigned int portNumber;
        int retval = 0;
+       int first = 0;
 
        dbg("%s", __func__);
 
@@ -220,8 +223,9 @@ static int serial_open (struct tty_struct *tty, struct file *filp)
        tty->driver_data = port;
        tty_port_tty_set(&port->port, tty);
 
-       if (port->port.count == 1) {
-
+       /* If the console is attached, the device is already open */
+       if (port->port.count == 1 && !port->console) {
+               first = 1;
                /* lock this module before we call it
                 * this may fail, which means we must bail out,
                 * safe because we are called with BKL held */
@@ -240,17 +244,25 @@ static int serial_open (struct tty_struct *tty, struct file *filp)
 
                /* only call the device specific open if this
                 * is the first time the port is opened */
-               retval = serial->type->open(tty, port, filp);
+               retval = serial->type->open(tty, port);
                if (retval)
                        goto bailout_interface_put;
                mutex_unlock(&serial->disc_mutex);
+               set_bit(ASYNCB_INITIALIZED, &port->port.flags);
        }
        mutex_unlock(&port->mutex);
        /* Now do the correct tty layer semantics */
        retval = tty_port_block_til_ready(&port->port, tty, filp);
-       if (retval == 0)
+       if (retval == 0) {
+               if (!first)
+                       usb_serial_put(serial);
                return 0;
-
+       }
+       mutex_lock(&port->mutex);
+       if (first == 0)
+               goto bailout_mutex_unlock;
+       /* Undo the initial port actions */
+       mutex_lock(&serial->disc_mutex);
 bailout_interface_put:
        usb_autopm_put_interface(serial->interface);
 bailout_module_put:
@@ -304,16 +316,19 @@ static void serial_do_down(struct usb_serial_port *port)
  *
  *     Do the resource freeing and refcount dropping for the port. We must
  *     be careful about ordering and we must avoid freeing up the console.
+ *
+ *     Called when the last tty kref is dropped.
  */
 
-static void serial_do_free(struct usb_serial_port *port)
+static void serial_do_free(struct tty_struct *tty)
 {
+       struct usb_serial_port *port = tty->driver_data;
        struct usb_serial *serial;
        struct module *owner;
 
        /* The console is magical, do not hang up the console hardware
           or there will be tears */
-       if (port->console)
+       if (port == NULL || port->console)
                return;
 
        serial = port->serial;
@@ -338,14 +353,12 @@ static void serial_close(struct tty_struct *tty, struct file *filp)
 
        dbg("%s - port %d", __func__, port->number);
 
-
        if (tty_port_close_start(&port->port, tty, filp) == 0)
                return;
-
        serial_do_down(port);           
        tty_port_close_end(&port->port, tty);
        tty_port_tty_set(&port->port, NULL);
-       serial_do_free(port);
+
 }
 
 static void serial_hangup(struct tty_struct *tty)
@@ -353,7 +366,8 @@ static void serial_hangup(struct tty_struct *tty)
        struct usb_serial_port *port = tty->driver_data;
        serial_do_down(port);
        tty_port_hangup(&port->port);
-       serial_do_free(port);
+       /* We must not free port yet - the USB serial layer depends on it's
+          continued existence */
 }
 
 static int serial_write(struct tty_struct *tty, const unsigned char *buf,
@@ -392,7 +406,6 @@ static int serial_chars_in_buffer(struct tty_struct *tty)
        struct usb_serial_port *port = tty->driver_data;
        dbg("%s = port %d", __func__, port->number);
 
-       WARN_ON(!port->port.count);
        /* if the device was unplugged then any remaining characters
           fell out of the connector ;) */
        if (port->serial->disconnected)
@@ -1133,10 +1146,7 @@ void usb_serial_disconnect(struct usb_interface *interface)
                if (port) {
                        struct tty_struct *tty = tty_port_tty_get(&port->port);
                        if (tty) {
-                               /* The hangup will occur asynchronously but
-                                  the object refcounts will sort out all the
-                                  cleanup */
-                               tty_hangup(tty);
+                               tty_vhangup(tty);
                                tty_kref_put(tty);
                        }
                        kill_traffic(port);
@@ -1218,6 +1228,7 @@ static const struct tty_operations serial_ops = {
        .chars_in_buffer =      serial_chars_in_buffer,
        .tiocmget =             serial_tiocmget,
        .tiocmset =             serial_tiocmset,
+       .shutdown =             serial_do_free,
        .proc_fops =            &serial_proc_fops,
 };
 
This page took 0.045322 seconds and 5 git commands to generate.