public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Greg KH <gregkh@suse.de>
To: linux-kernel@vger.kernel.org, stable@kernel.org
Cc: stable-review@kernel.org, torvalds@linux-foundation.org,
	akpm@linux-foundation.org, alan@lxorguk.ukuu.org.uk,
	Alan Stern <stern@rowland.harvard.edu>
Subject: [patch 082/108] usb-serial: replace shutdown with disconnect, release
Date: Tue, 30 Jun 2009 17:24:11 -0700	[thread overview]
Message-ID: <20090701002438.907510161@mini.kroah.org> (raw)
In-Reply-To: <20090701002838.GA7100@kroah.com>

[-- Attachment #1: usb-serial-replace-shutdown-with-disconnect-release.patch --]
[-- Type: text/plain, Size: 52361 bytes --]

2.6.30-stable review patch.  If anyone has any objections, please let us know.

------------------

From: Alan Stern <stern@rowland.harvard.edu>

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>

---
 drivers/staging/uc2322/aten2011.c     |    4 +--
 drivers/usb/serial/aircable.c         |    5 +---
 drivers/usb/serial/belkin_sa.c        |    7 ++---
 drivers/usb/serial/cp210x.c           |    6 ++--
 drivers/usb/serial/cyberjack.c        |   20 ++++++++++++----
 drivers/usb/serial/cypress_m8.c       |   11 ++++----
 drivers/usb/serial/digi_acceleport.c  |   20 ++++++++++++----
 drivers/usb/serial/empeg.c            |    8 ------
 drivers/usb/serial/ftdi_sio.c         |   14 -----------
 drivers/usb/serial/garmin_gps.c       |   16 ++++++++++--
 drivers/usb/serial/generic.c          |    9 +++++--
 drivers/usb/serial/io_edgeport.c      |   29 ++++++++++++++++-------
 drivers/usb/serial/io_tables.h        |   12 ++++++---
 drivers/usb/serial/io_ti.c            |   22 +++++++++++++----
 drivers/usb/serial/ipaq.c             |    7 -----
 drivers/usb/serial/iuu_phoenix.c      |    6 ++--
 drivers/usb/serial/keyspan.c          |   13 +++++++++-
 drivers/usb/serial/keyspan.h          |   12 ++++++---
 drivers/usb/serial/keyspan_pda.c      |    4 +--
 drivers/usb/serial/kl5kusb105.c       |   39 +++++++++++++++++--------------
 drivers/usb/serial/kobil_sct.c        |   12 +++------
 drivers/usb/serial/mct_u232.c         |   13 ++++------
 drivers/usb/serial/mos7720.c          |    9 ++-----
 drivers/usb/serial/mos7840.c          |   42 +++++++++++++++++++++++++++++-----
 drivers/usb/serial/omninet.c          |   19 ++++++++++++---
 drivers/usb/serial/opticon.c          |   14 ++++++++---
 drivers/usb/serial/option.c           |   17 +++++++++----
 drivers/usb/serial/oti6858.c          |    7 ++---
 drivers/usb/serial/pl2303.c           |    5 +---
 drivers/usb/serial/sierra.c           |   28 +++++++++++++++++++---
 drivers/usb/serial/spcp8x5.c          |    5 +---
 drivers/usb/serial/symbolserial.c     |   14 ++++++++---
 drivers/usb/serial/ti_usb_3410_5052.c |   10 +++-----
 drivers/usb/serial/usb-serial.c       |   29 ++++++++++-------------
 drivers/usb/serial/visor.c            |   13 ++++------
 drivers/usb/serial/whiteheat.c        |    6 ++--
 include/linux/usb/serial.h            |   12 ++++++---
 37 files changed, 319 insertions(+), 200 deletions(-)

--- a/drivers/staging/uc2322/aten2011.c
+++ b/drivers/staging/uc2322/aten2011.c
@@ -2336,7 +2336,7 @@ static int ATEN2011_startup(struct usb_s
 	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_ser
 	.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,
 };
--- a/drivers/usb/serial/aircable.c
+++ b/drivers/usb/serial/aircable.c
@@ -364,7 +364,7 @@ static int aircable_attach(struct usb_se
 	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
 	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
 	.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,
--- a/drivers/usb/serial/belkin_sa.c
+++ b/drivers/usb/serial/belkin_sa.c
@@ -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_d
 	.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_
 }
 
 
-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]);
--- a/drivers/usb/serial/cp210x.c
+++ b/drivers/usb/serial/cp210x.c
@@ -51,7 +51,7 @@ static int cp2101_tiocmset_port(struct u
 		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_d
 	.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_ser
 	return 0;
 }
 
-static void cp2101_shutdown(struct usb_serial *serial)
+static void cp2101_disconnect(struct usb_serial *serial)
 {
 	int i;
 
--- a/drivers/usb/serial/cyberjack.c
+++ b/drivers/usb/serial/cyberjack.c
@@ -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 cyberjac
 	.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_
 	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);
 	}
 }
 
--- a/drivers/usb/serial/cypress_m8.c
+++ b/drivers/usb/serial/cypress_m8.c
@@ -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_
 	.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_
 	.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_
 	.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
 } /* 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_
 	if (priv) {
 		cypress_buf_free(priv->buf);
 		kfree(priv);
-		usb_set_serial_port_data(serial->port[0], NULL);
 	}
 }
 
--- a/drivers/usb/serial/digi_acceleport.c
+++ b/drivers/usb/serial/digi_acceleport.c
@@ -460,7 +460,8 @@ static void digi_close(struct tty_struct
 	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_acc
 	.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_acc
 	.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_seria
 }
 
 
-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 */
--- a/drivers/usb/serial/empeg.c
+++ b/drivers/usb/serial/empeg.c
@@ -91,7 +91,6 @@ static int  empeg_chars_in_buffer(struct
 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_de
 	.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_ser
 }
 
 
-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)
 {
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -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
 	.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
 	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);
--- a/drivers/usb/serial/garmin_gps.c
+++ b/drivers/usb/serial/garmin_gps.c
@@ -1528,7 +1528,7 @@ static int garmin_attach(struct usb_seri
 }
 
 
-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_s
 
 	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_d
 	.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,
--- a/drivers/usb/serial/generic.c
+++ b/drivers/usb/serial/generic.c
@@ -63,7 +63,8 @@ struct usb_serial_driver usb_serial_gene
 	.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(struc
 	}
 }
 
-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 
 		generic_cleanup(serial->port[i]);
 }
 
+void usb_serial_generic_release(struct usb_serial *serial)
+{
+	dbg("%s", __func__);
+}
--- a/drivers/usb/serial/io_edgeport.c
+++ b/drivers/usb/serial/io_edgeport.c
@@ -225,7 +225,8 @@ static int  edge_tiocmget(struct tty_str
 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_seria
 
 
 /****************************************************************************
- * 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_ser
 		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);
 }
 
 
--- a/drivers/usb/serial/io_tables.h
+++ b/drivers/usb/serial/io_tables.h
@@ -117,7 +117,8 @@ static struct usb_serial_driver edgeport
 	.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
 	.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
 	.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_dev
 	.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,
--- a/drivers/usb/serial/io_ti.c
+++ b/drivers/usb/serial/io_ti.c
@@ -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_ser
 	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
 	.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
 	.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,
--- a/drivers/usb/serial/ipaq.c
+++ b/drivers/usb/serial/ipaq.c
@@ -80,7 +80,6 @@ static void ipaq_close(struct tty_struct
 			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_dev
 	.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_seria
 	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;
--- a/drivers/usb/serial/iuu_phoenix.c
+++ b/drivers/usb/serial/iuu_phoenix.c
@@ -122,8 +122,8 @@ static int iuu_startup(struct usb_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_devi
 	.tiocmget = iuu_tiocmget,
 	.tiocmset = iuu_tiocmset,
 	.attach = iuu_startup,
-	.shutdown = iuu_shutdown,
+	.release = iuu_release,
 };
 
 static int __init iuu_init(void)
--- a/drivers/usb/serial/keyspan.c
+++ b/drivers/usb/serial/keyspan.c
@@ -2682,7 +2682,7 @@ static int keyspan_startup(struct usb_se
 	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_
 			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);
--- a/drivers/usb/serial/keyspan.h
+++ b/drivers/usb/serial/keyspan.h
@@ -42,7 +42,8 @@ static void keyspan_close		(struct tty_s
 					 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_
 	.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_
 	.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_
 	.tiocmget		= keyspan_tiocmget,
 	.tiocmset		= keyspan_tiocmset,
 	.attach			= keyspan_startup,
-	.shutdown		= keyspan_shutdown,
+	.disconnect		= keyspan_disconnect,
+	.release		= keyspan_release,
 };
 
 #endif
--- a/drivers/usb/serial/keyspan_pda.c
+++ b/drivers/usb/serial/keyspan_pda.c
@@ -795,7 +795,7 @@ static int keyspan_pda_startup(struct us
 	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_
 	.tiocmget =		keyspan_pda_tiocmget,
 	.tiocmset =		keyspan_pda_tiocmset,
 	.attach =		keyspan_pda_startup,
-	.shutdown =		keyspan_pda_shutdown,
+	.release =		keyspan_pda_release,
 };
 
 
--- a/drivers/usb/serial/kl5kusb105.c
+++ b/drivers/usb/serial/kl5kusb105.c
@@ -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 kl5kusb1
 	.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
 	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)
--- a/drivers/usb/serial/kobil_sct.c
+++ b/drivers/usb/serial/kobil_sct.c
@@ -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_de
 	.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_seri
 }
 
 
-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);
-	}
 }
 
 
--- a/drivers/usb/serial/mct_u232.c
+++ b/drivers/usb/serial/mct_u232.c
@@ -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
 	.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_s
 } /* 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
 	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)
--- a/drivers/usb/serial/mos7720.c
+++ b/drivers/usb/serial/mos7720.c
@@ -1522,19 +1522,16 @@ static int mos7720_startup(struct usb_se
 	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 moschip7
 	.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,
--- a/drivers/usb/serial/mos7840.c
+++ b/drivers/usb/serial/mos7840.c
@@ -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_
 			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 moschip7
 	.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,
 };
--- a/drivers/usb/serial/omninet.c
+++ b/drivers/usb/serial/omninet.c
@@ -73,7 +73,8 @@ static void omninet_write_bulk_callback(
 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_om
 	.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(
 }
 
 
-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));
 }
 
--- a/drivers/usb/serial/opticon.c
+++ b/drivers/usb/serial/opticon.c
@@ -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_
 
 	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_
 	.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,
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -48,7 +48,8 @@ static int  option_open(struct tty_struc
 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_1
 	.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 
 	}
 }
 
-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_s
 
 	dbg("%s", __func__);
 
-	stop_read_write_urbs(serial);
-
 	/* Now free them */
 	for (i = 0; i < serial->num_ports; ++i) {
 		port = serial->port[i];
--- a/drivers/usb/serial/oti6858.c
+++ b/drivers/usb/serial/oti6858.c
@@ -160,7 +160,7 @@ static int oti6858_tiocmget(struct tty_s
 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_
 	.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_stru
 }
 
 
-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_
 		if (priv) {
 			oti6858_buf_free(priv->buf);
 			kfree(priv);
-			usb_set_serial_port_data(serial->port[i], NULL);
 		}
 	}
 }
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -897,7 +897,7 @@ static void pl2303_break_ctl(struct tty_
 		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_s
 		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_d
 	.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)
--- a/drivers/usb/serial/sierra.c
+++ b/drivers/usb/serial/sierra.c
@@ -699,7 +699,7 @@ static int sierra_startup(struct usb_ser
 	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_s
 		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_d
 	.tiocmget          = sierra_tiocmget,
 	.tiocmset          = sierra_tiocmset,
 	.attach            = sierra_startup,
-	.shutdown          = sierra_shutdown,
+	.disconnect        = sierra_disconnect,
+	.release           = sierra_release,
 	.read_int_callback = sierra_instat_callback,
 };
 
--- a/drivers/usb/serial/spcp8x5.c
+++ b/drivers/usb/serial/spcp8x5.c
@@ -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_
 		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_
 	.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)
--- a/drivers/usb/serial/symbolserial.c
+++ b/drivers/usb/serial/symbolserial.c
@@ -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_s
 
 	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_d
 	.attach =		symbol_startup,
 	.open =			symbol_open,
 	.close =		symbol_close,
-	.shutdown =		symbol_shutdown,
+	.disconnect =		symbol_disconnect,
+	.release =		symbol_release,
 	.throttle = 		symbol_throttle,
 	.unthrottle =		symbol_unthrottle,
 };
--- a/drivers/usb/serial/ti_usb_3410_5052.c
+++ b/drivers/usb/serial/ti_usb_3410_5052.c
@@ -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
 	.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
 	.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_seria
 		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);
 }
 
 
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -141,6 +141,14 @@ static void destroy_serial(struct 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 *
 		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_in
 	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_in
 			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_ser
 	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)
--- a/drivers/usb/serial/visor.c
+++ b/drivers/usb/serial/visor.c
@@ -48,7 +48,7 @@ static void visor_unthrottle(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 handspri
 	.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_d
 	.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_seri
 	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_se
 
 	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);
 	}
 }
 
--- a/drivers/usb/serial/whiteheat.c
+++ b/drivers/usb/serial/whiteheat.c
@@ -144,7 +144,7 @@ static int  whiteheat_firmware_attach(st
 
 /* 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 whitehea
 	.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;
--- a/include/linux/usb/serial.h
+++ b/include/linux/usb/serial.h
@@ -181,8 +181,10 @@ static inline void usb_set_serial_data(s
  *	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
 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);
 



  parent reply	other threads:[~2009-07-01  1:10 UTC|newest]

Thread overview: 124+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <20090701002249.937782934@mini.kroah.org>
2009-07-01  0:28 ` [patch 000/108] 2.6.30-stable review Greg KH
2009-07-01  0:22   ` [patch 001/108] firmware_map: fix hang with x86/32bit Greg KH
2009-07-01  0:22   ` [patch 002/108] fs: remove incorrect I_NEW warnings Greg KH
2009-07-01  0:22   ` [patch 003/108] PCI: disable ASPM on VIA root-port-under-bridge configurations Greg KH
2009-07-01  0:22   ` [patch 004/108] KVM: VMX: Fix handling of a fault during NMI unblocked due to IRET Greg KH
2009-07-01  0:22   ` [patch 005/108] KVM: Move "exit due to NMI" handling into vmx_complete_interrupts() Greg KH
2009-07-01  0:22   ` [patch 006/108] KVM: Add VT-x machine check support Greg KH
2009-07-01  0:22   ` [patch 007/108] KVM: Disable large pages on misaligned memory slots Greg KH
2009-07-01  0:22   ` [patch 008/108] KVM: Prevent overflow in largepages calculation Greg KH
2009-07-01  0:22   ` [patch 009/108] KVM: x86: check for cr3 validity in ioctl_set_sregs Greg KH
2009-07-01  0:22   ` [patch 010/108] KVM: VMX: Handle vmx instruction vmexits Greg KH
2009-07-01  0:23   ` [patch 011/108] KVM: protect concurrent make_all_cpus_request Greg KH
2009-07-01  0:23   ` [patch 012/108] KVM: Fix dirty bit tracking for slots with large pages Greg KH
2009-07-01  0:23   ` [patch 013/108] IMA: use current_cred() instead of current->cred Greg KH
2009-07-01  0:23   ` [patch 014/108] IMA: Handle dentry_open failures Greg KH
2009-07-01  0:23   ` [patch 015/108] IMA: open all files O_LARGEFILE Greg KH
2009-07-01  0:23   ` [patch 016/108] e1000e: stop unnecessary polling when using msi-x Greg KH
2009-07-01  0:23   ` [patch 017/108] pegasus usb-net: Fix endianness bugs Greg KH
2009-07-01  0:23   ` [patch 018/108] ipv4: fix NULL pointer + success return in route lookup path Greg KH
2009-07-01  0:23   ` [patch 019/108] ipv4 routing: Ensure that route cache entries are usable and reclaimable with caching is off Greg KH
2009-07-01  0:23   ` [patch 020/108] sky2: dont look for VPD size Greg KH
2009-07-01  0:23   ` [patch 021/108] tun: Fix unregister race Greg KH
2009-07-01  0:23   ` [patch 022/108] via-velocity: Fix velocity driver unmapping incorrect size Greg KH
2009-07-01  0:23   ` [patch 023/108] x25: Fix sleep from timer on socket destroy Greg KH
2009-07-01  0:23   ` [patch 024/108] bonding: fix multiple module load problem Greg KH
2009-07-01  0:23   ` [patch 025/108] dma-debug: change hash_bucket_find from first-fit to best-fit Greg KH
2009-07-01  0:23   ` [patch 026/108] char: moxa, prevent opening unavailable ports Greg KH
2009-07-01  0:23   ` [patch 027/108] serial: refactor ASYNC_ flags Greg KH
2009-07-01  0:23   ` [patch 028/108] rocket: fix test_bit parameters Greg KH
2009-07-01  0:23   ` [patch 029/108] epca: " Greg KH
2009-07-01  0:23   ` [patch 030/108] x86: Detect use of extended APIC ID for AMD CPUs Greg KH
2009-07-01  0:23   ` [patch 031/108] USB: usbtmc: fix switch statment Greg KH
2009-07-01  0:23   ` [patch 032/108] DVB: lgdt3305: fix 64bit division in function lgdt3305_set_if Greg KH
2009-07-01  0:23   ` [patch 033/108] V4L: ivtv/cx18: fix regression: class controls are no longer seen Greg KH
2009-07-01  0:23   ` [patch 034/108] V4L: pvrusb2: Fix hardware scaling when used with cx25840 Greg KH
2009-07-01  0:23   ` [patch 035/108] V4L: pvrusb2: Re-fix hardware scaling on video standard change Greg KH
2009-07-01  0:23   ` [patch 036/108] V4L: i2c modules must be linked before the v4l2 drivers Greg KH
2009-07-01  0:23   ` [patch 037/108] sym53c8xx: ratelimit parity errors Greg KH
2009-07-01  0:23   ` [patch 038/108] ISDN: Fix DMA alloc for hfcpci Greg KH
2009-07-01  0:23   ` [patch 039/108] jfs: fix regression preventing coalescing of extents Greg KH
2009-07-01  0:23   ` [patch 040/108] spi: takes size of a pointer to determine the size of the pointed-to type Greg KH
2009-07-01  0:23   ` [patch 041/108] serial: bfin_5xx: add missing spin_lock init Greg KH
2009-07-01  0:23   ` [patch 042/108] x86: memtest: remove 64-bit division Greg KH
2009-07-01  0:23   ` [patch 043/108] x86: Fix UV BAU activation descriptor init Greg KH
2009-07-01  0:23   ` [patch 044/108] x86, UV: Fix macros for multiple coherency domains Greg KH
2009-07-01  0:23   ` [patch 045/108] x86: enable GART-IOMMU only after setting up protection methods Greg KH
2009-07-01  0:23   ` [patch 046/108] x86: move rdtsc_barrier() into the TSC vread method Greg KH
2009-07-01  0:23   ` [patch 047/108] x86: Fix uv bau sending buffer initialization Greg KH
2009-07-01  0:23   ` [patch 048/108] x86: Add quirk for reboot stalls on a Dell Optiplex 360 Greg KH
2009-07-01  0:23   ` [patch 049/108] x86: handle initrd that extends into unusable memory Greg KH
2009-07-01  0:23   ` [patch 050/108] ALSA: ca0106 - Add missing registrations of vmaster controls Greg KH
2009-07-01  0:23   ` [patch 051/108] ALSA: intel8x0 - Fix PCM position craziness Greg KH
2009-07-01  0:23   ` [patch 052/108] ALSA: hda - Get back Input Source for ALC262 toshiba-s06 model Greg KH
2009-07-01  0:23   ` [patch 053/108] ALSA: hda - Add quirk for Sony VAIO Z21MN Greg KH
2009-07-01  0:23   ` [patch 054/108] ALSA: cmi8330: fix MPU-401 PnP init copy&paste bug Greg KH
2009-07-01  0:23   ` [patch 055/108] x86: hpet: Mark per cpu interrupts IRQF_TIMER to prevent resume failure Greg KH
2009-07-01  0:23   ` [patch 056/108] ARM: 5545/2: add flush_kernel_dcache_page() for ARM Greg KH
2009-07-01  0:23   ` [patch 057/108] IB/mlx4: Add strong ordering to local inval and fast reg work requests Greg KH
2009-07-01  0:23   ` [patch 058/108] epoll: fix nested calls support Greg KH
2009-07-01  0:23   ` [patch 059/108] lockdep: Select frame pointers on x86 Greg KH
2009-07-01  0:23   ` [patch 060/108] ASoC: Remove odd bit clock ratios for WM8903 Greg KH
2009-07-01  0:23   ` [patch 061/108] ramfs: ignore unknown mount options Greg KH
2009-07-01  0:23   ` [patch 062/108] mac80211: fix minstrel single-rate memory corruption Greg KH
2009-07-01  0:23   ` [patch 063/108] cfg80211: fix for duplicate userspace replies Greg KH
2009-07-01  0:23   ` [patch 064/108] cfg80211: cleanup return calls on nl80211_set_reg() Greg KH
2009-07-01  0:23   ` [patch 065/108] cfg80211: return immediately if num reg rules > NL80211_MAX_SUPP_REG_RULES Greg KH
2009-07-01  0:23   ` [patch 066/108] cfg80211: fix in nl80211_set_reg() Greg KH
2009-07-01  0:23   ` [patch 067/108] ath9k: Fix bug when using a card with a busted EEPROM Greg KH
2009-07-01  0:23   ` [patch 068/108] ath9k: Fix bug in calibration initialization Greg KH
2009-07-01  0:23   ` [patch 069/108] ath9k: Fix bug in determining calibration support Greg KH
2009-07-01  0:23   ` [patch 070/108] ath9k: Fix bug in checking HT flag Greg KH
2009-07-01  0:24   ` [patch 071/108] ath9k: Fix bug in scan termination Greg KH
2009-07-01  0:24   ` [patch 072/108] ath9k: Fix memleak on TX DMA failure Greg KH
2009-07-01  0:24   ` [patch 073/108] ath9k: Initialize ANI timers Greg KH
2009-07-01  0:24   ` [patch 074/108] ath9k: Fix PCI FATAL interrupts by restoring RETRY_TIMEOUT disabling Greg KH
2009-07-01  0:24   ` [patch 075/108] crypto: aes-ni - Fix cbc mode IV saving Greg KH
2009-07-01  0:24   ` [patch 076/108] md/raid5: add missing call to schedule() after prepare_to_wait() Greg KH
2009-07-01  0:24   ` [patch 077/108] tracing/urgent: fix unbalanced ftrace_start_up Greg KH
2009-07-01  0:24   ` [patch 078/108] cifs: fix fh_mutex locking in cifs_reopen_file Greg KH
2009-07-01  0:24   ` [patch 079/108] vt_ioctl: fix lock imbalance Greg KH
2009-07-01  0:24   ` [patch 080/108] x86: Fix non-lazy GS handling in sys_vm86() Greg KH
2009-07-01  0:24   ` [patch 081/108] x86: Set cpu_llc_id on AMD CPUs Greg KH
2009-07-01  0:24   ` Greg KH [this message]
2009-07-01  0:24   ` [patch 083/108] pcmcia/cm4000: fix lock imbalance Greg KH
2009-07-01  0:24   ` [patch 084/108] n_r3964: " Greg KH
2009-07-01  0:24   ` [patch 085/108] parport_pc: set properly the dma_mask for parport_pc device Greg KH
2009-07-01  0:24   ` [patch 086/108] parport_pc: after superio probing restore original register values Greg KH
2009-07-01  0:24   ` [patch 087/108] mv643xx_eth: fix unicast filter programming in promiscuous mode Greg KH
2009-07-01  0:24   ` [patch 088/108] ath5k: avoid PCI FATAL interrupts by restoring RETRY_TIMEOUT disabling Greg KH
2009-07-01  0:24   ` [patch 089/108] sound: seq_midi_event: fix decoding of (N)RPN events Greg KH
2009-07-01  0:24   ` [patch 090/108] PCI PM: Fix handling of devices without PM support by pci_target_state() Greg KH
2009-07-01  0:24   ` [patch 091/108] PCI PM: Follow PCI_PM_CTRL_NO_SOFT_RESET during transitions from D3 Greg KH
2009-07-01  0:24   ` [patch 092/108] qla2xxx: Correct (again) overflow during dump-processing on large-memory ISP23xx parts Greg KH
2009-07-01  0:24   ` [patch 093/108] mm: fix handling of pagesets for downed cpus Greg KH
2009-07-01  0:24   ` [patch 094/108] dm mpath: validate hw_handler argument count Greg KH
2009-07-01  0:24   ` [patch 095/108] dm mpath: validate table " Greg KH
2009-07-01  0:24   ` [patch 096/108] dm: sysfs skip output when device is being destroyed Greg KH
2009-07-01  0:24   ` [patch 097/108] dm mpath: flush keventd queue in destructor Greg KH
2009-07-01  0:24   ` [patch 098/108] dm exception store: fix exstore lookup to be case insensitive Greg KH
2009-07-01  7:11     ` Milan Broz
2009-07-01 17:26       ` [Stable-review] " Greg KH
2009-07-01  0:24   ` [patch 099/108] dm: use i_size_read Greg KH
2009-07-01  0:24   ` [patch 100/108] vmscan: properly account for the number of page cache pages zone_reclaim() can reclaim Greg KH
2009-07-01  0:24   ` [patch 101/108] vmscan: count the number of times zone_reclaim() scans and fails Greg KH
2009-07-01  0:24   ` [patch 102/108] lib/genalloc.c: remove unmatched write_lock() in gen_pool_destroy Greg KH
2009-07-01  0:24   ` [patch 103/108] CONFIG_FILE_LOCKING should not depend on CONFIG_BLOCK Greg KH
2009-07-01  0:24   ` [patch 104/108] serial: bfin_5xx: fix building as module when early printk is enabled Greg KH
2009-07-01  0:24   ` [patch 105/108] ocfs2: Fix ocfs2_osb_dump() Greg KH
2009-07-01  0:24   ` [patch 106/108] ide-cd: prevent null pointer deref via cdrom_newpc_intr Greg KH
2009-07-01  0:24   ` [patch 107/108] drm/i915: correct suspend/resume ordering Greg KH
2009-07-01  0:24   ` [patch 108/108] KVM: x86: silence preempt warning on kvm_write_guest_time Greg KH
2009-07-01 11:22   ` [patch 000/108] 2.6.30-stable review Julien BLACHE
2009-07-01 15:02     ` Stefan Richter
2009-07-01 15:41       ` Julien BLACHE
2009-07-01 16:22         ` [Stable-review] " Luis R. Rodriguez
2009-07-01 16:27           ` Julien BLACHE
2009-07-01 16:43             ` Stefan Richter
2009-07-01 17:21     ` Greg KH
2009-07-01 18:10   ` Greg KH
2009-07-01 18:12     ` [patch 109/108] bsdacct: fix access to invalid filp in acct_on() Greg KH
2009-07-01 18:13     ` [patch 110/108] dm exception store: really fix type lookup Greg KH
2009-07-01 18:14     ` [patch 111/108] xfs: fix freeing memory in xfs_getbmap() Greg KH
2009-07-01 18:33     ` [patch 000/108] 2.6.30-stable review Greg KH
2009-07-01 18:24   ` [Stable-review] " Luis R. Rodriguez

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20090701002438.907510161@mini.kroah.org \
    --to=gregkh@suse.de \
    --cc=akpm@linux-foundation.org \
    --cc=alan@lxorguk.ukuu.org.uk \
    --cc=linux-kernel@vger.kernel.org \
    --cc=stable-review@kernel.org \
    --cc=stable@kernel.org \
    --cc=stern@rowland.harvard.edu \
    --cc=torvalds@linux-foundation.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox