vserver 1.9.3
[linux-2.6.git] / drivers / usb / serial / usb-serial.c
index 19c92e8..03e8a7e 100644 (file)
 #include <linux/smp_lock.h>
 #include <asm/uaccess.h>
 #include <linux/usb.h>
-
-
-#ifdef CONFIG_USB_SERIAL_DEBUG
-       static int debug = 1;
-#else
-       static int debug;
-#endif
-
 #include "usb-serial.h"
 #include "pl2303.h"
 
 #define DRIVER_AUTHOR "Greg Kroah-Hartman, greg@kroah.com, http://www.kroah.com/linux/"
 #define DRIVER_DESC "USB Serial Driver core"
 
-
-#ifdef CONFIG_USB_SERIAL_GENERIC
-/* we want to look at all devices, as the vendor/product id can change
- * depending on the command line argument */
-static struct usb_device_id generic_serial_ids[] = {
-       {.driver_info = 42},
-       {}
-};
-
-#endif /* CONFIG_USB_SERIAL_GENERIC */
-
 /* Driver structure we register with the USB core */
 static struct usb_driver usb_serial_driver = {
        .owner =        THIS_MODULE,
        .name =         "usbserial",
        .probe =        usb_serial_probe,
        .disconnect =   usb_serial_disconnect,
-#ifdef CONFIG_USB_SERIAL_GENERIC
-       .id_table =     generic_serial_ids,
-#endif
 };
 
 /* There is no MODULE_DEVICE_TABLE for usbserial.c.  Instead
@@ -383,10 +361,10 @@ static struct usb_driver usb_serial_driver = {
    drivers depend on it.
 */
 
-static struct usb_serial       *serial_table[SERIAL_TTY_MINORS];       /* initially all NULL */
+static int debug;
+static struct usb_serial *serial_table[SERIAL_TTY_MINORS];     /* initially all NULL */
 static LIST_HEAD(usb_serial_driver_list);
 
-
 struct usb_serial *usb_serial_get_by_index(unsigned index)
 {
        struct usb_serial *serial = serial_table[index];
@@ -443,6 +421,63 @@ static void return_serial (struct usb_serial *serial)
        return;
 }
 
+static void destroy_serial(struct kref *kref)
+{
+       struct usb_serial *serial;
+       struct usb_serial_port *port;
+       int i;
+
+       serial = to_usb_serial(kref);
+
+       dbg ("%s - %s", __FUNCTION__, serial->type->name);
+
+       serial->type->shutdown(serial);
+
+       /* return the minor range that this device had */
+       return_serial(serial);
+
+       for (i = 0; i < serial->num_ports; ++i)
+               serial->port[i]->open_count = 0;
+
+       /* the ports are cleaned up and released in port_release() */
+       for (i = 0; i < serial->num_ports; ++i)
+               if (serial->port[i]->dev.parent != NULL) {
+                       device_unregister(&serial->port[i]->dev);
+                       serial->port[i] = NULL;
+               }
+
+       /* If this is a "fake" port, we have to clean it up here, as it will
+        * not get cleaned up in port_release() as it was never registered with
+        * the driver core */
+       if (serial->num_ports < serial->num_port_pointers) {
+               for (i = serial->num_ports; i < serial->num_port_pointers; ++i) {
+                       port = serial->port[i];
+                       if (!port)
+                               continue;
+                       if (port->read_urb) {
+                               usb_unlink_urb(port->read_urb);
+                               usb_free_urb(port->read_urb);
+                       }
+                       if (port->write_urb) {
+                               usb_unlink_urb(port->write_urb);
+                               usb_free_urb(port->write_urb);
+                       }
+                       if (port->interrupt_in_urb) {
+                               usb_unlink_urb(port->interrupt_in_urb);
+                               usb_free_urb(port->interrupt_in_urb);
+                       }
+                       kfree(port->bulk_in_buffer);
+                       kfree(port->bulk_out_buffer);
+                       kfree(port->interrupt_in_buffer);
+               }
+       }
+
+       usb_put_dev(serial->dev);
+
+       /* free up any memory that we allocated */
+       kfree (serial);
+}
+
 /*****************************************************************************
  * Driver tty interface functions
  *****************************************************************************/
@@ -487,7 +522,7 @@ static int serial_open (struct tty_struct *tty, struct file * filp)
                if (retval) {
                        port->open_count = 0;
                        module_put(serial->type->owner);
-                       kref_put(&serial->kref);
+                       kref_put(&serial->kref, destroy_serial);
                }
        }
 bailout:
@@ -518,7 +553,7 @@ static void serial_close(struct tty_struct *tty, struct file * filp)
        }
 
        module_put(port->serial->type->owner);
-       kref_put(&port->serial->kref);
+       kref_put(&port->serial->kref, destroy_serial);
 }
 
 static int serial_write (struct tty_struct * tty, int from_user, const unsigned char *buf, int count)
@@ -676,13 +711,6 @@ exit:
        ;
 }
 
-static void serial_shutdown (struct usb_serial *serial)
-{
-       dbg ("%s", __FUNCTION__);
-
-       serial->type->shutdown(serial);
-}
-
 static int serial_read_proc (char *page, char **start, off_t off, int count, int *eof, void *data)
 {
        struct usb_serial *serial;
@@ -716,7 +744,7 @@ static int serial_read_proc (char *page, char **start, off_t off, int count, int
                        begin += length;
                        length = 0;
                }
-               kref_put(&serial->kref);
+               kref_put(&serial->kref, destroy_serial);
        }
        *eof = 1;
 done:
@@ -777,68 +805,7 @@ void usb_serial_port_softint(void *private)
        if (!tty)
                return;
 
-       if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) {
-               dbg("%s - write wakeup call.", __FUNCTION__);
-               (tty->ldisc.write_wakeup)(tty);
-       }
-
-       wake_up_interruptible(&tty->write_wait);
-}
-
-static void destroy_serial(struct kref *kref)
-{
-       struct usb_serial *serial;
-       struct usb_serial_port *port;
-       int i;
-
-       serial = to_usb_serial(kref);
-
-       dbg ("%s - %s", __FUNCTION__, serial->type->name);
-       serial_shutdown (serial);
-
-       /* return the minor range that this device had */
-       return_serial(serial);
-
-       for (i = 0; i < serial->num_ports; ++i)
-               serial->port[i]->open_count = 0;
-
-       /* the ports are cleaned up and released in port_release() */
-       for (i = 0; i < serial->num_ports; ++i)
-               if (serial->port[i]->dev.parent != NULL) {
-                       device_unregister(&serial->port[i]->dev);
-                       serial->port[i] = NULL;
-               }
-
-       /* If this is a "fake" port, we have to clean it up here, as it will
-        * not get cleaned up in port_release() as it was never registered with
-        * the driver core */
-       if (serial->num_ports < serial->num_port_pointers) {
-               for (i = serial->num_ports; i < serial->num_port_pointers; ++i) {
-                       port = serial->port[i];
-                       if (!port)
-                               continue;
-                       if (port->read_urb) {
-                               usb_unlink_urb(port->read_urb);
-                               usb_free_urb(port->read_urb);
-                       }
-                       if (port->write_urb) {
-                               usb_unlink_urb(port->write_urb);
-                               usb_free_urb(port->write_urb);
-                       }
-                       if (port->interrupt_in_urb) {
-                               usb_unlink_urb(port->interrupt_in_urb);
-                               usb_free_urb(port->interrupt_in_urb);
-                       }
-                       kfree(port->bulk_in_buffer);
-                       kfree(port->bulk_out_buffer);
-                       kfree(port->interrupt_in_buffer);
-               }
-       }
-
-       usb_put_dev(serial->dev);
-
-       /* free up any memory that we allocated */
-       kfree (serial);
+       tty_wakeup(tty);
 }
 
 static void port_release(struct device *dev)
@@ -881,7 +848,7 @@ static struct usb_serial * create_serial (struct usb_device *dev,
        serial->interface = interface;
        serial->vendor = dev->descriptor.idVendor;
        serial->product = dev->descriptor.idProduct;
-       kref_init(&serial->kref, destroy_serial);
+       kref_init(&serial->kref);
 
        return serial;
 }
@@ -1231,7 +1198,7 @@ void usb_serial_disconnect(struct usb_interface *interface)
        if (serial) {
                /* let the last holder of this object 
                 * cause it to be cleaned up */
-               kref_put(&serial->kref);
+               kref_put(&serial->kref, destroy_serial);
        }
        dev_info(dev, "device disconnected\n");
 }
@@ -1383,22 +1350,9 @@ error:
 
 void usb_serial_deregister(struct usb_serial_device_type *device)
 {
-       struct usb_serial *serial;
-       int i;
-
        info("USB Serial deregistering driver %s", device->name);
-
-       /* clear out the serial_table if the device is attached to a port */
-       for(i = 0; i < SERIAL_TTY_MINORS; ++i) {
-               serial = serial_table[i];
-               if ((serial != NULL) && (serial->type == device)) {
-                       usb_driver_release_interface (&usb_serial_driver, serial->interface);
-                       usb_serial_disconnect (serial->interface);
-               }
-       }
-
        list_del(&device->driver_list);
-       usb_serial_bus_deregister (device);
+       usb_serial_bus_deregister(device);
 }