]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
usb-serial: replace shutdown with disconnect, release
authorAlan Stern <stern@rowland.harvard.edu>
Tue, 30 Jun 2009 15:26:47 +0000 (11:26 -0400)
committerGreg Kroah-Hartman <gregkh@suse.de>
Thu, 2 Jul 2009 23:50:25 +0000 (16:50 -0700)
commit f9c99bb8b3a1ec81af68d484a551307326c2e933 upstream

This patch splits up the shutdown method of usb_serial_driver into a
disconnect and a release method.

The problem is that the usb-serial core was calling shutdown during
disconnect handling, but drivers didn't expect it to be called until
after all the open file references had been closed.  The result was an
oops when the close method tried to use memory that had been
deallocated by shutdown.

Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
37 files changed:
drivers/staging/uc2322/aten2011.c
drivers/usb/serial/aircable.c
drivers/usb/serial/belkin_sa.c
drivers/usb/serial/cp210x.c
drivers/usb/serial/cyberjack.c
drivers/usb/serial/cypress_m8.c
drivers/usb/serial/digi_acceleport.c
drivers/usb/serial/empeg.c
drivers/usb/serial/ftdi_sio.c
drivers/usb/serial/garmin_gps.c
drivers/usb/serial/generic.c
drivers/usb/serial/io_edgeport.c
drivers/usb/serial/io_tables.h
drivers/usb/serial/io_ti.c
drivers/usb/serial/ipaq.c
drivers/usb/serial/iuu_phoenix.c
drivers/usb/serial/keyspan.c
drivers/usb/serial/keyspan.h
drivers/usb/serial/keyspan_pda.c
drivers/usb/serial/kl5kusb105.c
drivers/usb/serial/kobil_sct.c
drivers/usb/serial/mct_u232.c
drivers/usb/serial/mos7720.c
drivers/usb/serial/mos7840.c
drivers/usb/serial/omninet.c
drivers/usb/serial/opticon.c
drivers/usb/serial/option.c
drivers/usb/serial/oti6858.c
drivers/usb/serial/pl2303.c
drivers/usb/serial/sierra.c
drivers/usb/serial/spcp8x5.c
drivers/usb/serial/symbolserial.c
drivers/usb/serial/ti_usb_3410_5052.c
drivers/usb/serial/usb-serial.c
drivers/usb/serial/visor.c
drivers/usb/serial/whiteheat.c
include/linux/usb/serial.h

index 9c62f787cc9cde11ed7b866a9c53e8f82c5eff18..39d0926d1a9015394043091929bfdbce0ce1ed28 100644 (file)
@@ -2336,7 +2336,7 @@ static int ATEN2011_startup(struct usb_serial *serial)
        return 0;
 }
 
-static void ATEN2011_shutdown(struct usb_serial *serial)
+static void ATEN2011_release(struct usb_serial *serial)
 {
        int i;
        struct ATENINTL_port *ATEN2011_port;
@@ -2382,7 +2382,7 @@ static struct usb_serial_driver aten_serial_driver = {
        .tiocmget =             ATEN2011_tiocmget,
        .tiocmset =             ATEN2011_tiocmset,
        .attach =               ATEN2011_startup,
-       .shutdown =             ATEN2011_shutdown,
+       .release =              ATEN2011_release,
        .read_bulk_callback =   ATEN2011_bulk_in_callback,
        .read_int_callback =    ATEN2011_interrupt_callback,
 };
index 6d106e74265e9d839e7a4e5123bb4ce11c97a538..2cbfab3716e59c3764cf333d5bdb933add1e69a9 100644 (file)
@@ -364,7 +364,7 @@ static int aircable_attach(struct usb_serial *serial)
        return 0;
 }
 
-static void aircable_shutdown(struct usb_serial *serial)
+static void aircable_release(struct usb_serial *serial)
 {
 
        struct usb_serial_port *port = serial->port[0];
@@ -375,7 +375,6 @@ static void aircable_shutdown(struct usb_serial *serial)
        if (priv) {
                serial_buf_free(priv->tx_buf);
                serial_buf_free(priv->rx_buf);
-               usb_set_serial_port_data(port, NULL);
                kfree(priv);
        }
 }
@@ -601,7 +600,7 @@ static struct usb_serial_driver aircable_device = {
        .num_ports =            1,
        .attach =               aircable_attach,
        .probe =                aircable_probe,
-       .shutdown =             aircable_shutdown,
+       .release =              aircable_release,
        .write =                aircable_write,
        .write_room =           aircable_write_room,
        .write_bulk_callback =  aircable_write_bulk_callback,
index b7eacad4d48cb4ae34097c8d2ebbe7cb0ad0a363..963722854f8ccded93de1ab69a5456715ae59c24 100644 (file)
@@ -90,7 +90,7 @@ static int debug;
 
 /* function prototypes for a Belkin USB Serial Adapter F5U103 */
 static int  belkin_sa_startup(struct usb_serial *serial);
-static void belkin_sa_shutdown(struct usb_serial *serial);
+static void belkin_sa_release(struct usb_serial *serial);
 static int  belkin_sa_open(struct tty_struct *tty,
                        struct usb_serial_port *port, struct file *filp);
 static void belkin_sa_close(struct tty_struct *tty,
@@ -143,7 +143,7 @@ static struct usb_serial_driver belkin_device = {
        .tiocmget =             belkin_sa_tiocmget,
        .tiocmset =             belkin_sa_tiocmset,
        .attach =               belkin_sa_startup,
-       .shutdown =             belkin_sa_shutdown,
+       .release =              belkin_sa_release,
 };
 
 
@@ -198,14 +198,13 @@ static int belkin_sa_startup(struct usb_serial *serial)
 }
 
 
-static void belkin_sa_shutdown(struct usb_serial *serial)
+static void belkin_sa_release(struct usb_serial *serial)
 {
        struct belkin_sa_private *priv;
        int i;
 
        dbg("%s", __func__);
 
-       /* stop reads and writes on all ports */
        for (i = 0; i < serial->num_ports; ++i) {
                /* My special items, the standard routines free my urbs */
                priv = usb_get_serial_port_data(serial->port[i]);
index e8d5133ce9c84f911d210a374f5af40821c7f6b4..cf5093fea1840ccb38ab4ff0409631924e81c904 100644 (file)
@@ -51,7 +51,7 @@ static int cp2101_tiocmset_port(struct usb_serial_port *port, struct file *,
                unsigned int, unsigned int);
 static void cp2101_break_ctl(struct tty_struct *, int);
 static int cp2101_startup(struct usb_serial *);
-static void cp2101_shutdown(struct usb_serial *);
+static void cp2101_disconnect(struct usb_serial *);
 
 static int debug;
 
@@ -131,7 +131,7 @@ static struct usb_serial_driver cp2101_device = {
        .tiocmget               = cp2101_tiocmget,
        .tiocmset               = cp2101_tiocmset,
        .attach                 = cp2101_startup,
-       .shutdown               = cp2101_shutdown,
+       .disconnect             = cp2101_disconnect,
 };
 
 /* Config request types */
@@ -773,7 +773,7 @@ static int cp2101_startup(struct usb_serial *serial)
        return 0;
 }
 
-static void cp2101_shutdown(struct usb_serial *serial)
+static void cp2101_disconnect(struct usb_serial *serial)
 {
        int i;
 
index dd501bb63ed6173b2b1f31a35f93d3a7d202db0a..49cf9ee858e480bf2439f0c7ae254646d2da7c61 100644 (file)
@@ -58,7 +58,8 @@ static int debug;
 
 /* Function prototypes */
 static int cyberjack_startup(struct usb_serial *serial);
-static void cyberjack_shutdown(struct usb_serial *serial);
+static void cyberjack_disconnect(struct usb_serial *serial);
+static void cyberjack_release(struct usb_serial *serial);
 static int  cyberjack_open(struct tty_struct *tty,
                        struct usb_serial_port *port, struct file *filp);
 static void cyberjack_close(struct tty_struct *tty,
@@ -95,7 +96,8 @@ static struct usb_serial_driver cyberjack_device = {
        .id_table =             id_table,
        .num_ports =            1,
        .attach =               cyberjack_startup,
-       .shutdown =             cyberjack_shutdown,
+       .disconnect =           cyberjack_disconnect,
+       .release =              cyberjack_release,
        .open =                 cyberjack_open,
        .close =                cyberjack_close,
        .write =                cyberjack_write,
@@ -149,17 +151,25 @@ static int cyberjack_startup(struct usb_serial *serial)
        return 0;
 }
 
-static void cyberjack_shutdown(struct usb_serial *serial)
+static void cyberjack_disconnect(struct usb_serial *serial)
 {
        int i;
 
        dbg("%s", __func__);
 
-       for (i = 0; i < serial->num_ports; ++i) {
+       for (i = 0; i < serial->num_ports; ++i)
                usb_kill_urb(serial->port[i]->interrupt_in_urb);
+}
+
+static void cyberjack_release(struct usb_serial *serial)
+{
+       int i;
+
+       dbg("%s", __func__);
+
+       for (i = 0; i < serial->num_ports; ++i) {
                /* My special items, the standard routines free my urbs */
                kfree(usb_get_serial_port_data(serial->port[i]));
-               usb_set_serial_port_data(serial->port[i], NULL);
        }
 }
 
index e568710b263fa9dc6a6e258c6898c70254180d59..b8e6e4d17571a9019f608c1f65ca99227023d25d 100644 (file)
@@ -171,7 +171,7 @@ struct cypress_buf {
 static int  cypress_earthmate_startup(struct usb_serial *serial);
 static int  cypress_hidcom_startup(struct usb_serial *serial);
 static int  cypress_ca42v2_startup(struct usb_serial *serial);
-static void cypress_shutdown(struct usb_serial *serial);
+static void cypress_release(struct usb_serial *serial);
 static int  cypress_open(struct tty_struct *tty,
                        struct usb_serial_port *port, struct file *filp);
 static void cypress_close(struct tty_struct *tty,
@@ -215,7 +215,7 @@ static struct usb_serial_driver cypress_earthmate_device = {
        .id_table =                     id_table_earthmate,
        .num_ports =                    1,
        .attach =                       cypress_earthmate_startup,
-       .shutdown =                     cypress_shutdown,
+       .release =                      cypress_release,
        .open =                         cypress_open,
        .close =                        cypress_close,
        .write =                        cypress_write,
@@ -241,7 +241,7 @@ static struct usb_serial_driver cypress_hidcom_device = {
        .id_table =                     id_table_cyphidcomrs232,
        .num_ports =                    1,
        .attach =                       cypress_hidcom_startup,
-       .shutdown =                     cypress_shutdown,
+       .release =                      cypress_release,
        .open =                         cypress_open,
        .close =                        cypress_close,
        .write =                        cypress_write,
@@ -267,7 +267,7 @@ static struct usb_serial_driver cypress_ca42v2_device = {
        .id_table =                     id_table_nokiaca42v2,
        .num_ports =                    1,
        .attach =                       cypress_ca42v2_startup,
-       .shutdown =                     cypress_shutdown,
+       .release =                      cypress_release,
        .open =                         cypress_open,
        .close =                        cypress_close,
        .write =                        cypress_write,
@@ -613,7 +613,7 @@ static int cypress_ca42v2_startup(struct usb_serial *serial)
 } /* cypress_ca42v2_startup */
 
 
-static void cypress_shutdown(struct usb_serial *serial)
+static void cypress_release(struct usb_serial *serial)
 {
        struct cypress_private *priv;
 
@@ -626,7 +626,6 @@ static void cypress_shutdown(struct usb_serial *serial)
        if (priv) {
                cypress_buf_free(priv->buf);
                kfree(priv);
-               usb_set_serial_port_data(serial->port[0], NULL);
        }
 }
 
index 38ba4ea8b6bfdf1b84b69d9338cd9c3154d60e51..e9373dbe01eb5b4a1e559eb055093a787ab520cd 100644 (file)
@@ -460,7 +460,8 @@ static void digi_close(struct tty_struct *tty, struct usb_serial_port *port,
        struct file *filp);
 static int digi_startup_device(struct usb_serial *serial);
 static int digi_startup(struct usb_serial *serial);
-static void digi_shutdown(struct usb_serial *serial);
+static void digi_disconnect(struct usb_serial *serial);
+static void digi_release(struct usb_serial *serial);
 static void digi_read_bulk_callback(struct urb *urb);
 static int digi_read_inb_callback(struct urb *urb);
 static int digi_read_oob_callback(struct urb *urb);
@@ -522,7 +523,8 @@ static struct usb_serial_driver digi_acceleport_2_device = {
        .tiocmget =                     digi_tiocmget,
        .tiocmset =                     digi_tiocmset,
        .attach =                       digi_startup,
-       .shutdown =                     digi_shutdown,
+       .disconnect =                   digi_disconnect,
+       .release =                      digi_release,
 };
 
 static struct usb_serial_driver digi_acceleport_4_device = {
@@ -548,7 +550,8 @@ static struct usb_serial_driver digi_acceleport_4_device = {
        .tiocmget =                     digi_tiocmget,
        .tiocmset =                     digi_tiocmset,
        .attach =                       digi_startup,
-       .shutdown =                     digi_shutdown,
+       .disconnect =                   digi_disconnect,
+       .release =                      digi_release,
 };
 
 
@@ -1589,16 +1592,23 @@ static int digi_startup(struct usb_serial *serial)
 }
 
 
-static void digi_shutdown(struct usb_serial *serial)
+static void digi_disconnect(struct usb_serial *serial)
 {
        int i;
-       dbg("digi_shutdown: TOP, in_interrupt()=%ld", in_interrupt());
+       dbg("digi_disconnect: TOP, in_interrupt()=%ld", in_interrupt());
 
        /* stop reads and writes on all ports */
        for (i = 0; i < serial->type->num_ports + 1; i++) {
                usb_kill_urb(serial->port[i]->read_urb);
                usb_kill_urb(serial->port[i]->write_urb);
        }
+}
+
+
+static void digi_release(struct usb_serial *serial)
+{
+       int i;
+       dbg("digi_release: TOP, in_interrupt()=%ld", in_interrupt());
 
        /* free the private data structures for all ports */
        /* number of regular ports + 1 for the out-of-band port */
index c709ec474a80b8540e91d5ae6e25fde2690f6b09..b0d678c8c7e0efb9b2f71a1acf34e0cf0616bce9 100644 (file)
@@ -91,7 +91,6 @@ static int  empeg_chars_in_buffer(struct tty_struct *tty);
 static void empeg_throttle(struct tty_struct *tty);
 static void empeg_unthrottle(struct tty_struct *tty);
 static int  empeg_startup(struct usb_serial *serial);
-static void empeg_shutdown(struct usb_serial *serial);
 static void empeg_set_termios(struct tty_struct *tty,
                struct usb_serial_port *port, struct ktermios *old_termios);
 static void empeg_write_bulk_callback(struct urb *urb);
@@ -125,7 +124,6 @@ static struct usb_serial_driver empeg_device = {
        .throttle =             empeg_throttle,
        .unthrottle =           empeg_unthrottle,
        .attach =               empeg_startup,
-       .shutdown =             empeg_shutdown,
        .set_termios =          empeg_set_termios,
        .write =                empeg_write,
        .write_room =           empeg_write_room,
@@ -429,12 +427,6 @@ static int  empeg_startup(struct usb_serial *serial)
 }
 
 
-static void empeg_shutdown(struct usb_serial *serial)
-{
-       dbg("%s", __func__);
-}
-
-
 static void empeg_set_termios(struct tty_struct *tty,
                struct usb_serial_port *port, struct ktermios *old_termios)
 {
index d9fcdaedf389d9c670b57847004939c44a25dc32..9722512e87db99241fb0bb474cda0dad85149c55 100644 (file)
@@ -714,7 +714,6 @@ static const char *ftdi_chip_name[] = {
 /* function prototypes for a FTDI serial converter */
 static int  ftdi_sio_probe(struct usb_serial *serial,
                                        const struct usb_device_id *id);
-static void ftdi_shutdown(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,
@@ -770,7 +769,6 @@ static struct usb_serial_driver ftdi_sio_device = {
        .ioctl =                ftdi_ioctl,
        .set_termios =          ftdi_set_termios,
        .break_ctl =            ftdi_break_ctl,
-       .shutdown =             ftdi_shutdown,
 };
 
 
@@ -1460,18 +1458,6 @@ static int ftdi_mtxorb_hack_setup(struct usb_serial *serial)
        return 0;
 }
 
-/* ftdi_shutdown is called from usbserial:usb_serial_disconnect
- *   it is called when the usb device is disconnected
- *
- *   usbserial:usb_serial_disconnect
- *      calls __serial_close for each open of the port
- *      shutdown is called then (ie ftdi_shutdown)
- */
-static void ftdi_shutdown(struct usb_serial *serial)
-{
-       dbg("%s", __func__);
-}
-
 static void ftdi_sio_priv_release(struct kref *k)
 {
        struct ftdi_private *priv = container_of(k, struct ftdi_private, kref);
index 586d30ff450b2eb9cc8346bd26ea3697056661ac..ed8bd9076d66dcbf0bfce1e24787420dfc066cb2 100644 (file)
@@ -1528,7 +1528,7 @@ static int garmin_attach(struct usb_serial *serial)
 }
 
 
-static void garmin_shutdown(struct usb_serial *serial)
+static void garmin_disconnect(struct usb_serial *serial)
 {
        struct usb_serial_port *port = serial->port[0];
        struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);
@@ -1537,8 +1537,17 @@ static void garmin_shutdown(struct usb_serial *serial)
 
        usb_kill_urb(port->interrupt_in_urb);
        del_timer_sync(&garmin_data_p->timer);
+}
+
+
+static void garmin_release(struct usb_serial *serial)
+{
+       struct usb_serial_port *port = serial->port[0];
+       struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);
+
+       dbg("%s", __func__);
+
        kfree(garmin_data_p);
-       usb_set_serial_port_data(port, NULL);
 }
 
 
@@ -1557,7 +1566,8 @@ static struct usb_serial_driver garmin_device = {
        .throttle            = garmin_throttle,
        .unthrottle          = garmin_unthrottle,
        .attach              = garmin_attach,
-       .shutdown            = garmin_shutdown,
+       .disconnect          = garmin_disconnect,
+       .release             = garmin_release,
        .write               = garmin_write,
        .write_room          = garmin_write_room,
        .write_bulk_callback = garmin_write_bulk_callback,
index 4cec9906ccf394ef312f07d152bbc64785f2cce0..ef2978840910aa9314c9dc73d81080cc1c1c9122 100644 (file)
@@ -63,7 +63,8 @@ struct usb_serial_driver usb_serial_generic_device = {
        .id_table =             generic_device_ids,
        .usb_driver =           &generic_driver,
        .num_ports =            1,
-       .shutdown =             usb_serial_generic_shutdown,
+       .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,
@@ -413,7 +414,7 @@ void usb_serial_generic_unthrottle(struct tty_struct *tty)
        }
 }
 
-void usb_serial_generic_shutdown(struct usb_serial *serial)
+void usb_serial_generic_disconnect(struct usb_serial *serial)
 {
        int i;
 
@@ -424,3 +425,7 @@ void usb_serial_generic_shutdown(struct usb_serial *serial)
                generic_cleanup(serial->port[i]);
 }
 
+void usb_serial_generic_release(struct usb_serial *serial)
+{
+       dbg("%s", __func__);
+}
index fb4a73d090f6b9137daa847301a37545c48edc9b..fc509bba1b02f6192f0972de400ae15caccb0414 100644 (file)
@@ -225,7 +225,8 @@ static int  edge_tiocmget(struct tty_struct *tty, struct file *file);
 static int  edge_tiocmset(struct tty_struct *tty, struct file *file,
                                        unsigned int set, unsigned int clear);
 static int  edge_startup(struct usb_serial *serial);
-static void edge_shutdown(struct usb_serial *serial);
+static void edge_disconnect(struct usb_serial *serial);
+static void edge_release(struct usb_serial *serial);
 
 #include "io_tables.h" /* all of the devices that this driver supports */
 
@@ -3195,21 +3196,16 @@ static int edge_startup(struct usb_serial *serial)
 
 
 /****************************************************************************
- * edge_shutdown
+ * edge_disconnect
  *     This function is called whenever the device is removed from the usb bus.
  ****************************************************************************/
-static void edge_shutdown(struct usb_serial *serial)
+static void edge_disconnect(struct usb_serial *serial)
 {
        struct edgeport_serial *edge_serial = usb_get_serial_data(serial);
-       int i;
 
        dbg("%s", __func__);
 
        /* stop reads and writes on all ports */
-       for (i = 0; i < serial->num_ports; ++i) {
-               kfree(usb_get_serial_port_data(serial->port[i]));
-               usb_set_serial_port_data(serial->port[i],  NULL);
-       }
        /* free up our endpoint stuff */
        if (edge_serial->is_epic) {
                usb_kill_urb(edge_serial->interrupt_read_urb);
@@ -3220,9 +3216,24 @@ static void edge_shutdown(struct usb_serial *serial)
                usb_free_urb(edge_serial->read_urb);
                kfree(edge_serial->bulk_in_buffer);
        }
+}
+
+
+/****************************************************************************
+ * edge_release
+ *     This function is called when the device structure is deallocated.
+ ****************************************************************************/
+static void edge_release(struct usb_serial *serial)
+{
+       struct edgeport_serial *edge_serial = usb_get_serial_data(serial);
+       int i;
+
+       dbg("%s", __func__);
+
+       for (i = 0; i < serial->num_ports; ++i)
+               kfree(usb_get_serial_port_data(serial->port[i]));
 
        kfree(edge_serial);
-       usb_set_serial_data(serial, NULL);
 }
 
 
index 7eb9d67b81b632a20ead2479933c4e86cead3dfe..9241d314751324f65cb430ece19b6e6db373c72c 100644 (file)
@@ -117,7 +117,8 @@ static struct usb_serial_driver edgeport_2port_device = {
        .throttle               = edge_throttle,
        .unthrottle             = edge_unthrottle,
        .attach                 = edge_startup,
-       .shutdown               = edge_shutdown,
+       .disconnect             = edge_disconnect,
+       .release                = edge_release,
        .ioctl                  = edge_ioctl,
        .set_termios            = edge_set_termios,
        .tiocmget               = edge_tiocmget,
@@ -145,7 +146,8 @@ static struct usb_serial_driver edgeport_4port_device = {
        .throttle               = edge_throttle,
        .unthrottle             = edge_unthrottle,
        .attach                 = edge_startup,
-       .shutdown               = edge_shutdown,
+       .disconnect             = edge_disconnect,
+       .release                = edge_release,
        .ioctl                  = edge_ioctl,
        .set_termios            = edge_set_termios,
        .tiocmget               = edge_tiocmget,
@@ -173,7 +175,8 @@ static struct usb_serial_driver edgeport_8port_device = {
        .throttle               = edge_throttle,
        .unthrottle             = edge_unthrottle,
        .attach                 = edge_startup,
-       .shutdown               = edge_shutdown,
+       .disconnect             = edge_disconnect,
+       .release                = edge_release,
        .ioctl                  = edge_ioctl,
        .set_termios            = edge_set_termios,
        .tiocmget               = edge_tiocmget,
@@ -200,7 +203,8 @@ static struct usb_serial_driver epic_device = {
        .throttle               = edge_throttle,
        .unthrottle             = edge_unthrottle,
        .attach                 = edge_startup,
-       .shutdown               = edge_shutdown,
+       .disconnect             = edge_disconnect,
+       .release                = edge_release,
        .ioctl                  = edge_ioctl,
        .set_termios            = edge_set_termios,
        .tiocmget               = edge_tiocmget,
index 513b25e044c166749f062843d246350bd2ea8ea3..3139246b487b3300669e29748001a6826396db16 100644 (file)
@@ -2664,7 +2664,7 @@ cleanup:
        return -ENOMEM;
 }
 
-static void edge_shutdown(struct usb_serial *serial)
+static void edge_disconnect(struct usb_serial *serial)
 {
        int i;
        struct edgeport_port *edge_port;
@@ -2674,12 +2674,22 @@ static void edge_shutdown(struct usb_serial *serial)
        for (i = 0; i < serial->num_ports; ++i) {
                edge_port = usb_get_serial_port_data(serial->port[i]);
                edge_remove_sysfs_attrs(edge_port->port);
+       }
+}
+
+static void edge_release(struct usb_serial *serial)
+{
+       int i;
+       struct edgeport_port *edge_port;
+
+       dbg("%s", __func__);
+
+       for (i = 0; i < serial->num_ports; ++i) {
+               edge_port = usb_get_serial_port_data(serial->port[i]);
                edge_buf_free(edge_port->ep_out_buf);
                kfree(edge_port);
-               usb_set_serial_port_data(serial->port[i], NULL);
        }
        kfree(usb_get_serial_data(serial));
-       usb_set_serial_data(serial, NULL);
 }
 
 
@@ -2916,7 +2926,8 @@ static struct usb_serial_driver edgeport_1port_device = {
        .throttle               = edge_throttle,
        .unthrottle             = edge_unthrottle,
        .attach                 = edge_startup,
-       .shutdown               = edge_shutdown,
+       .disconnect             = edge_disconnect,
+       .release                = edge_release,
        .port_probe             = edge_create_sysfs_attrs,
        .ioctl                  = edge_ioctl,
        .set_termios            = edge_set_termios,
@@ -2945,7 +2956,8 @@ static struct usb_serial_driver edgeport_2port_device = {
        .throttle               = edge_throttle,
        .unthrottle             = edge_unthrottle,
        .attach                 = edge_startup,
-       .shutdown               = edge_shutdown,
+       .disconnect             = edge_disconnect,
+       .release                = edge_release,
        .port_probe             = edge_create_sysfs_attrs,
        .ioctl                  = edge_ioctl,
        .set_termios            = edge_set_termios,
index cd62825a9ac325e520d6cf0ba93f6e7cab763d66..b70b0a0eda176a4a7105b29a05368dc01228a2ec 100644 (file)
@@ -80,7 +80,6 @@ static void ipaq_close(struct tty_struct *tty,
                        struct usb_serial_port *port, struct file *filp);
 static int  ipaq_calc_num_ports(struct usb_serial *serial);
 static int  ipaq_startup(struct usb_serial *serial);
-static void ipaq_shutdown(struct usb_serial *serial);
 static int ipaq_write(struct tty_struct *tty, struct usb_serial_port *port,
                        const unsigned char *buf, int count);
 static int ipaq_write_bulk(struct usb_serial_port *port,
@@ -577,7 +576,6 @@ static struct usb_serial_driver ipaq_device = {
        .close =                ipaq_close,
        .attach =               ipaq_startup,
        .calc_num_ports =       ipaq_calc_num_ports,
-       .shutdown =             ipaq_shutdown,
        .write =                ipaq_write,
        .write_room =           ipaq_write_room,
        .chars_in_buffer =      ipaq_chars_in_buffer,
@@ -992,11 +990,6 @@ static int ipaq_startup(struct usb_serial *serial)
        return usb_reset_configuration(serial->dev);
 }
 
-static void ipaq_shutdown(struct usb_serial *serial)
-{
-       dbg("%s", __func__);
-}
-
 static int __init ipaq_init(void)
 {
        int retval;
index 4473d442b2aa45357f7bfcea14aac39445de87da..c03015b806b80e2d90719e1264b91fb002f9f090 100644 (file)
@@ -122,8 +122,8 @@ static int iuu_startup(struct usb_serial *serial)
        return 0;
 }
 
-/* Shutdown function */
-static void iuu_shutdown(struct usb_serial *serial)
+/* Release function */
+static void iuu_release(struct usb_serial *serial)
 {
        struct usb_serial_port *port = serial->port[0];
        struct iuu_private *priv = usb_get_serial_port_data(port);
@@ -1176,7 +1176,7 @@ static struct usb_serial_driver iuu_device = {
        .tiocmget = iuu_tiocmget,
        .tiocmset = iuu_tiocmset,
        .attach = iuu_startup,
-       .shutdown = iuu_shutdown,
+       .release = iuu_release,
 };
 
 static int __init iuu_init(void)
index 00daa8f7759a99946fc3a902dc1e46c9a2bf55af..8c69c3c12df96a5fb537a6d1ab397db99ac5473c 100644 (file)
@@ -2682,7 +2682,7 @@ static int keyspan_startup(struct usb_serial *serial)
        return 0;
 }
 
-static void keyspan_shutdown(struct usb_serial *serial)
+static void keyspan_disconnect(struct usb_serial *serial)
 {
        int                             i, j;
        struct usb_serial_port          *port;
@@ -2722,6 +2722,17 @@ static void keyspan_shutdown(struct usb_serial *serial)
                        usb_free_urb(p_priv->out_urbs[j]);
                }
        }
+}
+
+static void keyspan_release(struct usb_serial *serial)
+{
+       int                             i;
+       struct usb_serial_port          *port;
+       struct keyspan_serial_private   *s_priv;
+
+       dbg("%s", __func__);
+
+       s_priv = usb_get_serial_data(serial);
 
        /*  dbg("Freeing serial->private."); */
        kfree(s_priv);
index 38b4582e073446ad6513b7ed11145ccc6a26e61c..4961c2661d66b414edaa71fbb3520526ddb91053 100644 (file)
@@ -42,7 +42,8 @@ static void keyspan_close             (struct tty_struct *tty,
                                         struct usb_serial_port *port,
                                         struct file *filp);
 static int  keyspan_startup            (struct usb_serial *serial);
-static void keyspan_shutdown           (struct usb_serial *serial);
+static void keyspan_disconnect         (struct usb_serial *serial);
+static void keyspan_release            (struct usb_serial *serial);
 static int  keyspan_write_room         (struct tty_struct *tty);
 
 static int  keyspan_write              (struct tty_struct *tty,
@@ -569,7 +570,8 @@ static struct usb_serial_driver keyspan_1port_device = {
        .tiocmget               = keyspan_tiocmget,
        .tiocmset               = keyspan_tiocmset,
        .attach                 = keyspan_startup,
-       .shutdown               = keyspan_shutdown,
+       .disconnect             = keyspan_disconnect,
+       .release                = keyspan_release,
 };
 
 static struct usb_serial_driver keyspan_2port_device = {
@@ -589,7 +591,8 @@ static struct usb_serial_driver keyspan_2port_device = {
        .tiocmget               = keyspan_tiocmget,
        .tiocmset               = keyspan_tiocmset,
        .attach                 = keyspan_startup,
-       .shutdown               = keyspan_shutdown,
+       .disconnect             = keyspan_disconnect,
+       .release                = keyspan_release,
 };
 
 static struct usb_serial_driver keyspan_4port_device = {
@@ -609,7 +612,8 @@ static struct usb_serial_driver keyspan_4port_device = {
        .tiocmget               = keyspan_tiocmget,
        .tiocmset               = keyspan_tiocmset,
        .attach                 = keyspan_startup,
-       .shutdown               = keyspan_shutdown,
+       .disconnect             = keyspan_disconnect,
+       .release                = keyspan_release,
 };
 
 #endif
index bf1ae247da66133f64ee79d57f15ef6619f82aa2..d2e2b91f26bf3ce728918c6c23be7ccd525ee909 100644 (file)
@@ -795,7 +795,7 @@ static int keyspan_pda_startup(struct usb_serial *serial)
        return 0;
 }
 
-static void keyspan_pda_shutdown(struct usb_serial *serial)
+static void keyspan_pda_release(struct usb_serial *serial)
 {
        dbg("%s", __func__);
 
@@ -853,7 +853,7 @@ static struct usb_serial_driver keyspan_pda_device = {
        .tiocmget =             keyspan_pda_tiocmget,
        .tiocmset =             keyspan_pda_tiocmset,
        .attach =               keyspan_pda_startup,
-       .shutdown =             keyspan_pda_shutdown,
+       .release =              keyspan_pda_release,
 };
 
 
index fcd9082f3e7f05d93fedc3073e3f6a87c318a6a8..272a94f49e49523312f029830157333cade159d6 100644 (file)
@@ -73,7 +73,8 @@ static int debug;
  * Function prototypes
  */
 static int  klsi_105_startup(struct usb_serial *serial);
-static void klsi_105_shutdown(struct usb_serial *serial);
+static void klsi_105_disconnect(struct usb_serial *serial);
+static void klsi_105_release(struct usb_serial *serial);
 static int  klsi_105_open(struct tty_struct *tty,
                        struct usb_serial_port *port, struct file *filp);
 static void klsi_105_close(struct tty_struct *tty,
@@ -132,7 +133,8 @@ static struct usb_serial_driver kl5kusb105d_device = {
        .tiocmget =          klsi_105_tiocmget,
        .tiocmset =          klsi_105_tiocmset,
        .attach =            klsi_105_startup,
-       .shutdown =          klsi_105_shutdown,
+       .disconnect =        klsi_105_disconnect,
+       .release =           klsi_105_release,
        .throttle =          klsi_105_throttle,
        .unthrottle =        klsi_105_unthrottle,
 };
@@ -316,7 +318,7 @@ err_cleanup:
 } /* klsi_105_startup */
 
 
-static void klsi_105_shutdown(struct usb_serial *serial)
+static void klsi_105_disconnect(struct usb_serial *serial)
 {
        int i;
 
@@ -326,33 +328,36 @@ static void klsi_105_shutdown(struct usb_serial *serial)
        for (i = 0; i < serial->num_ports; ++i) {
                struct klsi_105_private *priv =
                                usb_get_serial_port_data(serial->port[i]);
-               unsigned long flags;
 
                if (priv) {
                        /* kill our write urb pool */
                        int j;
                        struct urb **write_urbs = priv->write_urb_pool;
-                       spin_lock_irqsave(&priv->lock, flags);
 
                        for (j = 0; j < NUM_URBS; j++) {
                                if (write_urbs[j]) {
-                                       /* FIXME - uncomment the following
-                                        * usb_kill_urb call when the host
-                                        * controllers get fixed to set
-                                        * urb->dev = NULL after the urb is
-                                        * finished.  Otherwise this call
-                                        * oopses. */
-                                       /* usb_kill_urb(write_urbs[j]); */
-                                       kfree(write_urbs[j]->transfer_buffer);
+                                       usb_kill_urb(write_urbs[j]);
                                        usb_free_urb(write_urbs[j]);
                                }
                        }
-                       spin_unlock_irqrestore(&priv->lock, flags);
-                       kfree(priv);
-                       usb_set_serial_port_data(serial->port[i], NULL);
                }
        }
-} /* klsi_105_shutdown */
+} /* klsi_105_disconnect */
+
+
+static void klsi_105_release(struct usb_serial *serial)
+{
+       int i;
+
+       dbg("%s", __func__);
+
+       for (i = 0; i < serial->num_ports; ++i) {
+               struct klsi_105_private *priv =
+                               usb_get_serial_port_data(serial->port[i]);
+
+               kfree(priv);
+       }
+} /* klsi_105_release */
 
 static int  klsi_105_open(struct tty_struct *tty,
                        struct usb_serial_port *port, struct file *filp)
index c148544953b37df33a00fc9873377a31168de993..d88368c967fae0af1685e2c7f1c519e46b290631 100644 (file)
@@ -69,7 +69,7 @@ static int debug;
 
 /* Function prototypes */
 static int  kobil_startup(struct usb_serial *serial);
-static void kobil_shutdown(struct usb_serial *serial);
+static void kobil_release(struct usb_serial *serial);
 static int  kobil_open(struct tty_struct *tty,
                        struct usb_serial_port *port, struct file *filp);
 static void kobil_close(struct tty_struct *tty, struct usb_serial_port *port,
@@ -118,7 +118,7 @@ static struct usb_serial_driver kobil_device = {
        .id_table =             id_table,
        .num_ports =            1,
        .attach =               kobil_startup,
-       .shutdown =             kobil_shutdown,
+       .release =              kobil_release,
        .ioctl =                kobil_ioctl,
        .set_termios =          kobil_set_termios,
        .tiocmget =             kobil_tiocmget,
@@ -202,17 +202,13 @@ static int kobil_startup(struct usb_serial *serial)
 }
 
 
-static void kobil_shutdown(struct usb_serial *serial)
+static void kobil_release(struct usb_serial *serial)
 {
        int i;
        dbg("%s - port %d", __func__, serial->port[0]->number);
 
-       for (i = 0; i < serial->num_ports; ++i) {
-               while (serial->port[i]->port.count > 0)
-                       kobil_close(NULL, serial->port[i], NULL);
+       for (i = 0; i < serial->num_ports; ++i)
                kfree(usb_get_serial_port_data(serial->port[i]));
-               usb_set_serial_port_data(serial->port[i], NULL);
-       }
 }
 
 
index 82930a7d509327c2797ef474042e0a3d2a4106ac..08ba8e60604d231330408a25db8ec56234f64c02 100644 (file)
@@ -92,7 +92,7 @@ static int debug;
  * Function prototypes
  */
 static int  mct_u232_startup(struct usb_serial *serial);
-static void mct_u232_shutdown(struct usb_serial *serial);
+static void mct_u232_release(struct usb_serial *serial);
 static int  mct_u232_open(struct tty_struct *tty,
                        struct usb_serial_port *port, struct file *filp);
 static void mct_u232_close(struct tty_struct *tty,
@@ -148,7 +148,7 @@ static struct usb_serial_driver mct_u232_device = {
        .tiocmget =          mct_u232_tiocmget,
        .tiocmset =          mct_u232_tiocmset,
        .attach =            mct_u232_startup,
-       .shutdown =          mct_u232_shutdown,
+       .release =           mct_u232_release,
 };
 
 
@@ -406,7 +406,7 @@ static int mct_u232_startup(struct usb_serial *serial)
 } /* mct_u232_startup */
 
 
-static void mct_u232_shutdown(struct usb_serial *serial)
+static void mct_u232_release(struct usb_serial *serial)
 {
        struct mct_u232_private *priv;
        int i;
@@ -416,12 +416,9 @@ static void mct_u232_shutdown(struct usb_serial *serial)
        for (i = 0; i < serial->num_ports; ++i) {
                /* My special items, the standard routines free my urbs */
                priv = usb_get_serial_port_data(serial->port[i]);
-               if (priv) {
-                       usb_set_serial_port_data(serial->port[i], NULL);
-                       kfree(priv);
-               }
+               kfree(priv);
        }
-} /* mct_u232_shutdown */
+} /* mct_u232_release */
 
 static int  mct_u232_open(struct tty_struct *tty,
                        struct usb_serial_port *port, struct file *filp)
index 24e3b5d4b4d49f088a9891718bc36c815c4a409c..e0137ecc22810072bd984d33617714fd6ffe4933 100644 (file)
@@ -1522,19 +1522,16 @@ static int mos7720_startup(struct usb_serial *serial)
        return 0;
 }
 
-static void mos7720_shutdown(struct usb_serial *serial)
+static void mos7720_release(struct usb_serial *serial)
 {
        int i;
 
        /* free private structure allocated for serial port */
-       for (i = 0; i < serial->num_ports; ++i) {
+       for (i = 0; i < serial->num_ports; ++i)
                kfree(usb_get_serial_port_data(serial->port[i]));
-               usb_set_serial_port_data(serial->port[i], NULL);
-       }
 
        /* free private structure allocated for serial device */
        kfree(usb_get_serial_data(serial));
-       usb_set_serial_data(serial, NULL);
 }
 
 static struct usb_driver usb_driver = {
@@ -1559,7 +1556,7 @@ static struct usb_serial_driver moschip7720_2port_driver = {
        .throttle               = mos7720_throttle,
        .unthrottle             = mos7720_unthrottle,
        .attach                 = mos7720_startup,
-       .shutdown               = mos7720_shutdown,
+       .release                = mos7720_release,
        .ioctl                  = mos7720_ioctl,
        .set_termios            = mos7720_set_termios,
        .write                  = mos7720_write,
index 84fb1dcd30dc3eacdf186c3666375775ff9b1fad..3d3026871d4ae23a2de58d4b745d71426ede8335 100644 (file)
@@ -2673,16 +2673,16 @@ error:
 }
 
 /****************************************************************************
- * mos7840_shutdown
+ * mos7840_disconnect
  *     This function is called whenever the device is removed from the usb bus.
  ****************************************************************************/
 
-static void mos7840_shutdown(struct usb_serial *serial)
+static void mos7840_disconnect(struct usb_serial *serial)
 {
        int i;
        unsigned long flags;
        struct moschip_port *mos7840_port;
-       dbg("%s \n", " shutdown :entering..........");
+       dbg("%s \n", " disconnect :entering..........");
 
        if (!serial) {
                dbg("%s", "Invalid Handler \n");
@@ -2702,11 +2702,42 @@ static void mos7840_shutdown(struct usb_serial *serial)
                        mos7840_port->zombie = 1;
                        spin_unlock_irqrestore(&mos7840_port->pool_lock, flags);
                        usb_kill_urb(mos7840_port->control_urb);
+               }
+       }
+
+       dbg("%s", "Thank u :: ");
+
+}
+
+/****************************************************************************
+ * mos7840_release
+ *     This function is called when the usb_serial structure is freed.
+ ****************************************************************************/
+
+static void mos7840_release(struct usb_serial *serial)
+{
+       int i;
+       struct moschip_port *mos7840_port;
+       dbg("%s", " release :entering..........");
+
+       if (!serial) {
+               dbg("%s", "Invalid Handler");
+               return;
+       }
+
+       /* check for the ports to be closed,close the ports and disconnect */
+
+       /* free private structure allocated for serial port  *
+        * stop reads and writes on all ports                */
+
+       for (i = 0; i < serial->num_ports; ++i) {
+               mos7840_port = mos7840_get_port_private(serial->port[i]);
+               dbg("mos7840_port %d = %p", i, mos7840_port);
+               if (mos7840_port) {
                        kfree(mos7840_port->ctrl_buf);
                        kfree(mos7840_port->dr);
                        kfree(mos7840_port);
                }
-               mos7840_set_port_private(serial->port[i], NULL);
        }
 
        dbg("%s\n", "Thank u :: ");
@@ -2747,7 +2778,8 @@ static struct usb_serial_driver moschip7840_4port_device = {
        .tiocmget = mos7840_tiocmget,
        .tiocmset = mos7840_tiocmset,
        .attach = mos7840_startup,
-       .shutdown = mos7840_shutdown,
+       .disconnect = mos7840_disconnect,
+       .release = mos7840_release,
        .read_bulk_callback = mos7840_bulk_in_callback,
        .read_int_callback = mos7840_interrupt_callback,
 };
index df6539712726b93b8c007ecea018a5ed9ea4cb50..65fb5c62d2f4efd8ecb503dbb34e0f41788e8b67 100644 (file)
@@ -73,7 +73,8 @@ 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);
 static int  omninet_write_room(struct tty_struct *tty);
-static void omninet_shutdown(struct usb_serial *serial);
+static void omninet_disconnect(struct usb_serial *serial);
+static void omninet_release(struct usb_serial *serial);
 static int omninet_attach(struct usb_serial *serial);
 
 static struct usb_device_id id_table[] = {
@@ -109,7 +110,8 @@ static struct usb_serial_driver zyxel_omninet_device = {
        .write_room =           omninet_write_room,
        .read_bulk_callback =   omninet_read_bulk_callback,
        .write_bulk_callback =  omninet_write_bulk_callback,
-       .shutdown =             omninet_shutdown,
+       .disconnect =           omninet_disconnect,
+       .release =              omninet_release,
 };
 
 
@@ -347,13 +349,22 @@ static void omninet_write_bulk_callback(struct urb *urb)
 }
 
 
-static void omninet_shutdown(struct usb_serial *serial)
+static void omninet_disconnect(struct usb_serial *serial)
 {
        struct usb_serial_port *wport = serial->port[1];
-       struct usb_serial_port *port = serial->port[0];
+
        dbg("%s", __func__);
 
        usb_kill_urb(wport->write_urb);
+}
+
+
+static void omninet_release(struct usb_serial *serial)
+{
+       struct usb_serial_port *port = serial->port[0];
+
+       dbg("%s", __func__);
+
        kfree(usb_get_serial_port_data(port));
 }
 
index b500ad10b7589185087bbcb64cc0e4ba97fbfd3b..1e99ae02600ebca6b5038a5c64d7d1ccdf13a022 100644 (file)
@@ -464,7 +464,7 @@ error:
        return retval;
 }
 
-static void opticon_shutdown(struct usb_serial *serial)
+static void opticon_disconnect(struct usb_serial *serial)
 {
        struct opticon_private *priv = usb_get_serial_data(serial);
 
@@ -472,9 +472,16 @@ static void opticon_shutdown(struct usb_serial *serial)
 
        usb_kill_urb(priv->bulk_read_urb);
        usb_free_urb(priv->bulk_read_urb);
+}
+
+static void opticon_release(struct usb_serial *serial)
+{
+       struct opticon_private *priv = usb_get_serial_data(serial);
+
+       dbg("%s", __func__);
+
        kfree(priv->bulk_in_buffer);
        kfree(priv);
-       usb_set_serial_data(serial, NULL);
 }
 
 static int opticon_suspend(struct usb_interface *intf, pm_message_t message)
@@ -525,7 +532,8 @@ static struct usb_serial_driver opticon_device = {
        .close =                opticon_close,
        .write =                opticon_write,
        .write_room =           opticon_write_room,
-       .shutdown =             opticon_shutdown,
+       .disconnect =           opticon_disconnect,
+       .release =              opticon_release,
        .throttle =             opticon_throttle,
        .unthrottle =           opticon_unthrottle,
        .ioctl =                opticon_ioctl,
index 7817b82889ca5e56eeb0c63a01c9351cf1a02612..ab3d88356d5fdf474d040af729dbb704fd530c31 100644 (file)
@@ -48,7 +48,8 @@ static int  option_open(struct tty_struct *tty, struct usb_serial_port *port,
 static void option_close(struct tty_struct *tty, struct usb_serial_port *port,
                                                        struct file *filp);
 static int  option_startup(struct usb_serial *serial);
-static void option_shutdown(struct usb_serial *serial);
+static void option_disconnect(struct usb_serial *serial);
+static void option_release(struct usb_serial *serial);
 static int  option_write_room(struct tty_struct *tty);
 
 static void option_instat_callback(struct urb *urb);
@@ -558,7 +559,8 @@ static struct usb_serial_driver option_1port_device = {
        .tiocmget          = option_tiocmget,
        .tiocmset          = option_tiocmset,
        .attach            = option_startup,
-       .shutdown          = option_shutdown,
+       .disconnect        = option_disconnect,
+       .release           = option_release,
        .read_int_callback = option_instat_callback,
        .suspend           = option_suspend,
        .resume            = option_resume,
@@ -1129,7 +1131,14 @@ static void stop_read_write_urbs(struct usb_serial *serial)
        }
 }
 
-static void option_shutdown(struct usb_serial *serial)
+static void option_disconnect(struct usb_serial *serial)
+{
+       dbg("%s", __func__);
+
+       stop_read_write_urbs(serial);
+}
+
+static void option_release(struct usb_serial *serial)
 {
        int i, j;
        struct usb_serial_port *port;
@@ -1137,8 +1146,6 @@ static void option_shutdown(struct usb_serial *serial)
 
        dbg("%s", __func__);
 
-       stop_read_write_urbs(serial);
-
        /* Now free them */
        for (i = 0; i < serial->num_ports; ++i) {
                port = serial->port[i];
index ba551f00f16ff1ec30fbcd90422f1e1112e8c00a..f7388efe8496b2e4335ff93dfd18cf24c639b9eb 100644 (file)
@@ -160,7 +160,7 @@ static int oti6858_tiocmget(struct tty_struct *tty, struct file *file);
 static int oti6858_tiocmset(struct tty_struct *tty, struct file *file,
                                unsigned int set, unsigned int clear);
 static int oti6858_startup(struct usb_serial *serial);
-static void oti6858_shutdown(struct usb_serial *serial);
+static void oti6858_release(struct usb_serial *serial);
 
 /* functions operating on buffers */
 static struct oti6858_buf *oti6858_buf_alloc(unsigned int size);
@@ -195,7 +195,7 @@ static struct usb_serial_driver oti6858_device = {
        .write_room =           oti6858_write_room,
        .chars_in_buffer =      oti6858_chars_in_buffer,
        .attach =               oti6858_startup,
-       .shutdown =             oti6858_shutdown,
+       .release =              oti6858_release,
 };
 
 struct oti6858_private {
@@ -829,7 +829,7 @@ static int oti6858_ioctl(struct tty_struct *tty, struct file *file,
 }
 
 
-static void oti6858_shutdown(struct usb_serial *serial)
+static void oti6858_release(struct usb_serial *serial)
 {
        struct oti6858_private *priv;
        int i;
@@ -841,7 +841,6 @@ static void oti6858_shutdown(struct usb_serial *serial)
                if (priv) {
                        oti6858_buf_free(priv->buf);
                        kfree(priv);
-                       usb_set_serial_port_data(serial->port[i], NULL);
                }
        }
 }
index 751a533a4347e7324725afb8948b75fcb2437bbd..4cf1ed112a91c897cb16fbab24b0427f258d8795 100644 (file)
@@ -897,7 +897,7 @@ static void pl2303_break_ctl(struct tty_struct *tty, int break_state)
                dbg("%s - error sending break = %d", __func__, result);
 }
 
-static void pl2303_shutdown(struct usb_serial *serial)
+static void pl2303_release(struct usb_serial *serial)
 {
        int i;
        struct pl2303_private *priv;
@@ -909,7 +909,6 @@ static void pl2303_shutdown(struct usb_serial *serial)
                if (priv) {
                        pl2303_buf_free(priv->buf);
                        kfree(priv);
-                       usb_set_serial_port_data(serial->port[i], NULL);
                }
        }
 }
@@ -1137,7 +1136,7 @@ static struct usb_serial_driver pl2303_device = {
        .write_room =           pl2303_write_room,
        .chars_in_buffer =      pl2303_chars_in_buffer,
        .attach =               pl2303_startup,
-       .shutdown =             pl2303_shutdown,
+       .release =              pl2303_release,
 };
 
 static int __init pl2303_init(void)
index 913225c6161037ad78596f5ba68b9fa078f510b5..5a26ed87309c5aaf92424cdc2f19e23cf4f4d9bd 100644 (file)
@@ -699,7 +699,7 @@ static int sierra_startup(struct usb_serial *serial)
        return 0;
 }
 
-static void sierra_shutdown(struct usb_serial *serial)
+static void sierra_disconnect(struct usb_serial *serial)
 {
        int i, j;
        struct usb_serial_port *port;
@@ -718,10 +718,29 @@ static void sierra_shutdown(struct usb_serial *serial)
                for (j = 0; j < N_IN_URB; j++) {
                        usb_kill_urb(portdata->in_urbs[j]);
                        usb_free_urb(portdata->in_urbs[j]);
-                       kfree(portdata->in_buffer[j]);
                }
+       }
+}
+
+static void sierra_release(struct usb_serial *serial)
+{
+       int i, j;
+       struct usb_serial_port *port;
+       struct sierra_port_private *portdata;
+
+       dev_dbg(&serial->dev->dev, "%s\n", __func__);
+
+       for (i = 0; i < serial->num_ports; ++i) {
+               port = serial->port[i];
+               if (!port)
+                       continue;
+               portdata = usb_get_serial_port_data(port);
+               if (!portdata)
+                       continue;
+
+               for (j = 0; j < N_IN_URB; j++)
+                       kfree(portdata->in_buffer[j]);
                kfree(portdata);
-               usb_set_serial_port_data(port, NULL);
        }
 }
 
@@ -743,7 +762,8 @@ static struct usb_serial_driver sierra_device = {
        .tiocmget          = sierra_tiocmget,
        .tiocmset          = sierra_tiocmset,
        .attach            = sierra_startup,
-       .shutdown          = sierra_shutdown,
+       .disconnect        = sierra_disconnect,
+       .release           = sierra_release,
        .read_int_callback = sierra_instat_callback,
 };
 
index 5e7528cc81a8e624f8ef64a869eca06b18918126..f5403b067dddd9925d5b13ae02229ca9611f7b20 100644 (file)
@@ -356,7 +356,7 @@ cleanup:
 }
 
 /* call when the device plug out. free all the memory alloced by probe */
-static void spcp8x5_shutdown(struct usb_serial *serial)
+static void spcp8x5_release(struct usb_serial *serial)
 {
        int i;
        struct spcp8x5_private *priv;
@@ -366,7 +366,6 @@ static void spcp8x5_shutdown(struct usb_serial *serial)
                if (priv) {
                        free_ringbuf(priv->buf);
                        kfree(priv);
-                       usb_set_serial_port_data(serial->port[i] , NULL);
                }
        }
 }
@@ -1043,7 +1042,7 @@ static struct usb_serial_driver spcp8x5_device = {
        .write_bulk_callback    = spcp8x5_write_bulk_callback,
        .chars_in_buffer        = spcp8x5_chars_in_buffer,
        .attach                 = spcp8x5_startup,
-       .shutdown               = spcp8x5_shutdown,
+       .release                = spcp8x5_release,
 };
 
 static int __init spcp8x5_init(void)
index 69879e4379402f63ad53579c6a1184d762322260..b7a6bc8b5de6ea77e01cede9aaf3d95163947856 100644 (file)
@@ -268,7 +268,7 @@ error:
        return retval;
 }
 
-static void symbol_shutdown(struct usb_serial *serial)
+static void symbol_disconnect(struct usb_serial *serial)
 {
        struct symbol_private *priv = usb_get_serial_data(serial);
 
@@ -276,9 +276,16 @@ static void symbol_shutdown(struct usb_serial *serial)
 
        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);
+
+       dbg("%s", __func__);
+
        kfree(priv->int_buffer);
        kfree(priv);
-       usb_set_serial_data(serial, NULL);
 }
 
 static struct usb_driver symbol_driver = {
@@ -300,7 +307,8 @@ static struct usb_serial_driver symbol_device = {
        .attach =               symbol_startup,
        .open =                 symbol_open,
        .close =                symbol_close,
-       .shutdown =             symbol_shutdown,
+       .disconnect =           symbol_disconnect,
+       .release =              symbol_release,
        .throttle =             symbol_throttle,
        .unthrottle =           symbol_unthrottle,
 };
index 0a64bac306ee693f02e9b11ce20a2a70cf452965..ef5f7565e07f7a582fc30171d2ac7ee925693f52 100644 (file)
@@ -97,7 +97,7 @@ struct ti_device {
 /* Function Declarations */
 
 static int ti_startup(struct usb_serial *serial);
-static void ti_shutdown(struct usb_serial *serial);
+static void ti_release(struct usb_serial *serial);
 static int ti_open(struct tty_struct *tty, struct usb_serial_port *port,
                struct file *file);
 static void ti_close(struct tty_struct *tty, struct usb_serial_port *port,
@@ -231,7 +231,7 @@ static struct usb_serial_driver ti_1port_device = {
        .id_table               = ti_id_table_3410,
        .num_ports              = 1,
        .attach                 = ti_startup,
-       .shutdown               = ti_shutdown,
+       .release                = ti_release,
        .open                   = ti_open,
        .close                  = ti_close,
        .write                  = ti_write,
@@ -259,7 +259,7 @@ static struct usb_serial_driver ti_2port_device = {
        .id_table               = ti_id_table_5052,
        .num_ports              = 2,
        .attach                 = ti_startup,
-       .shutdown               = ti_shutdown,
+       .release                = ti_release,
        .open                   = ti_open,
        .close                  = ti_close,
        .write                  = ti_write,
@@ -474,7 +474,7 @@ free_tdev:
 }
 
 
-static void ti_shutdown(struct usb_serial *serial)
+static void ti_release(struct usb_serial *serial)
 {
        int i;
        struct ti_device *tdev = usb_get_serial_data(serial);
@@ -487,12 +487,10 @@ static void ti_shutdown(struct usb_serial *serial)
                if (tport) {
                        ti_buf_free(tport->tp_write_buf);
                        kfree(tport);
-                       usb_set_serial_port_data(serial->port[i], NULL);
                }
        }
 
        kfree(tdev);
-       usb_set_serial_data(serial, NULL);
 }
 
 
index f331e2bde88acbb0c2b4e36fee01eff68ffc9b5c..131fc74d9b82c2f1f3b8a408188d32afebe96af5 100644 (file)
@@ -141,6 +141,14 @@ static void destroy_serial(struct kref *kref)
        if (serial->minor != SERIAL_TTY_NO_MINOR)
                return_serial(serial);
 
+       serial->type->release(serial);
+
+       for (i = 0; i < serial->num_ports; ++i) {
+               port = serial->port[i];
+               if (port)
+                       put_device(&port->dev);
+       }
+
        /* 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 */
@@ -148,9 +156,8 @@ static void destroy_serial(struct kref *kref)
                for (i = serial->num_ports;
                                        i < serial->num_port_pointers; ++i) {
                        port = serial->port[i];
-                       if (!port)
-                               continue;
-                       port_free(port);
+                       if (port)
+                               port_free(port);
                }
        }
 
@@ -1062,10 +1069,6 @@ void usb_serial_disconnect(struct usb_interface *interface)
        serial->disconnected = 1;
        mutex_unlock(&serial->disc_mutex);
 
-       /* Unfortunately, many of the sub-drivers expect the port structures
-        * to exist when their shutdown method is called, so we have to go
-        * through this awkward two-step unregistration procedure.
-        */
        for (i = 0; i < serial->num_ports; ++i) {
                port = serial->port[i];
                if (port) {
@@ -1079,14 +1082,7 @@ void usb_serial_disconnect(struct usb_interface *interface)
                        device_del(&port->dev);
                }
        }
-       serial->type->shutdown(serial);
-       for (i = 0; i < serial->num_ports; ++i) {
-               port = serial->port[i];
-               if (port) {
-                       put_device(&port->dev);
-                       serial->port[i] = NULL;
-               }
-       }
+       serial->type->disconnect(serial);
 
        /* let the last holder of this object
         * cause it to be cleaned up */
@@ -1262,7 +1258,8 @@ 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, shutdown);
+       set_to_generic_if_null(device, disconnect);
+       set_to_generic_if_null(device, release);
 }
 
 int usb_serial_register(struct usb_serial_driver *driver)
index 5ac414bda718103191d6489f613e3d5d3c361dd6..e50f397fb37a37ae44fa610da801979c52599f75 100644 (file)
@@ -48,7 +48,7 @@ static void visor_unthrottle(struct tty_struct *tty);
 static int  visor_probe(struct usb_serial *serial,
                                        const struct usb_device_id *id);
 static int  visor_calc_num_ports(struct usb_serial *serial);
-static void visor_shutdown(struct usb_serial *serial);
+static void visor_release(struct usb_serial *serial);
 static void visor_write_bulk_callback(struct urb *urb);
 static void visor_read_bulk_callback(struct urb *urb);
 static void visor_read_int_callback(struct urb *urb);
@@ -203,7 +203,7 @@ static struct usb_serial_driver handspring_device = {
        .attach =               treo_attach,
        .probe =                visor_probe,
        .calc_num_ports =       visor_calc_num_ports,
-       .shutdown =             visor_shutdown,
+       .release =              visor_release,
        .write =                visor_write,
        .write_room =           visor_write_room,
        .write_bulk_callback =  visor_write_bulk_callback,
@@ -228,7 +228,7 @@ static struct usb_serial_driver clie_5_device = {
        .attach =               clie_5_attach,
        .probe =                visor_probe,
        .calc_num_ports =       visor_calc_num_ports,
-       .shutdown =             visor_shutdown,
+       .release =              visor_release,
        .write =                visor_write,
        .write_room =           visor_write_room,
        .write_bulk_callback =  visor_write_bulk_callback,
@@ -920,7 +920,7 @@ static int clie_5_attach(struct usb_serial *serial)
        return generic_startup(serial);
 }
 
-static void visor_shutdown(struct usb_serial *serial)
+static void visor_release(struct usb_serial *serial)
 {
        struct visor_private *priv;
        int i;
@@ -929,10 +929,7 @@ static void visor_shutdown(struct usb_serial *serial)
 
        for (i = 0; i < serial->num_ports; i++) {
                priv = usb_get_serial_port_data(serial->port[i]);
-               if (priv) {
-                       usb_set_serial_port_data(serial->port[i], NULL);
-                       kfree(priv);
-               }
+               kfree(priv);
        }
 }
 
index 5335d3211c073c1c661d895aeaa0488fa0196ba1..319ec07ed255c3181917356a84e43a73c01245e4 100644 (file)
@@ -144,7 +144,7 @@ static int  whiteheat_firmware_attach(struct usb_serial *serial);
 
 /* function prototypes for the Connect Tech WhiteHEAT serial converter */
 static int  whiteheat_attach(struct usb_serial *serial);
-static void whiteheat_shutdown(struct usb_serial *serial);
+static void whiteheat_release(struct usb_serial *serial);
 static int  whiteheat_open(struct tty_struct *tty,
                        struct usb_serial_port *port, struct file *filp);
 static void whiteheat_close(struct tty_struct *tty,
@@ -190,7 +190,7 @@ static struct usb_serial_driver whiteheat_device = {
        .id_table =             id_table_std,
        .num_ports =            4,
        .attach =               whiteheat_attach,
-       .shutdown =             whiteheat_shutdown,
+       .release =              whiteheat_release,
        .open =                 whiteheat_open,
        .close =                whiteheat_close,
        .write =                whiteheat_write,
@@ -618,7 +618,7 @@ no_command_buffer:
 }
 
 
-static void whiteheat_shutdown(struct usb_serial *serial)
+static void whiteheat_release(struct usb_serial *serial)
 {
        struct usb_serial_port *command_port;
        struct usb_serial_port *port;
index 625e9e4639c68f3e9fc2b6b1d3ce4a734fa2113b..6d6c3b895a3e43b8290e62def348912556a29dc1 100644 (file)
@@ -181,8 +181,10 @@ static inline void usb_set_serial_data(struct usb_serial *serial, void *data)
  *     This will be called when the struct usb_serial structure is fully set
  *     set up.  Do any local initialization of the device, or any private
  *     memory structure allocation at this point in time.
- * @shutdown: pointer to the driver's shutdown function.  This will be
- *     called when the device is removed from the system.
+ * @disconnect: pointer to the driver's disconnect function.  This will be
+ *     called when the device is unplugged or unbound from the driver.
+ * @release: pointer to the driver's release function.  This will be called
+ *     when the usb_serial data structure is about to be destroyed.
  * @usb_driver: pointer to the struct usb_driver that controls this
  *     device.  This is necessary to allow dynamic ids to be added to
  *     the driver from sysfs.
@@ -212,7 +214,8 @@ struct usb_serial_driver {
        int (*attach)(struct usb_serial *serial);
        int (*calc_num_ports) (struct usb_serial *serial);
 
-       void (*shutdown)(struct usb_serial *serial);
+       void (*disconnect)(struct usb_serial *serial);
+       void (*release)(struct usb_serial *serial);
 
        int (*port_probe)(struct usb_serial_port *port);
        int (*port_remove)(struct usb_serial_port *port);
@@ -292,7 +295,8 @@ extern void usb_serial_generic_read_bulk_callback(struct urb *urb);
 extern void usb_serial_generic_write_bulk_callback(struct urb *urb);
 extern void usb_serial_generic_throttle(struct tty_struct *tty);
 extern void usb_serial_generic_unthrottle(struct tty_struct *tty);
-extern void usb_serial_generic_shutdown(struct usb_serial *serial);
+extern void usb_serial_generic_disconnect(struct usb_serial *serial);
+extern void usb_serial_generic_release(struct usb_serial *serial);
 extern int usb_serial_generic_register(int debug);
 extern void usb_serial_generic_deregister(void);