aboutsummaryrefslogtreecommitdiffstats
path: root/tty
diff options
authorGreg Kroah-Hartman <gregkh@suse.de>2009-10-27 10:54:41 -0700
committerGreg Kroah-Hartman <gregkh@suse.de>2009-10-27 10:54:41 -0700
commit607008879414ffa8d5f424a3646cca2644119c3b (patch)
tree32c49c67c62c88b9559f644f418b1c585122f2d7 /tty
parentd93ada0e086cc8b5de957b5dfaeb1247489f1717 (diff)
downloadpatches-607008879414ffa8d5f424a3646cca2644119c3b.tar.gz
more patches
Diffstat (limited to 'tty')
-rw-r--r--tty/opticon-fix-resume-logic.patch32
-rw-r--r--tty/serial-8250-calculate-irqflags-bitmask-before-loop.patch72
-rw-r--r--tty/serial-cascade-needless-conditionals.patch55
-rw-r--r--tty/serial-fix-null-pointer-dereference.patch71
-rw-r--r--tty/tty_port-add-tty_port_open-helper.patch174
-rw-r--r--tty/tty_port-coding-style-cleaning-pass.patch98
-rw-r--r--tty/usb_serial-kill-port-mutex.patch68
-rw-r--r--tty/usb_serial-use-the-shutdown-operation.patch124
8 files changed, 694 insertions, 0 deletions
diff --git a/tty/opticon-fix-resume-logic.patch b/tty/opticon-fix-resume-logic.patch
new file mode 100644
index 00000000000000..3335b23dd16710
--- /dev/null
+++ b/tty/opticon-fix-resume-logic.patch
@@ -0,0 +1,32 @@
+From alan@linux.intel.com Tue Oct 27 10:08:01 2009
+From: Alan Cox <alan@linux.intel.com>
+Date: Tue, 06 Oct 2009 16:06:57 +0100
+Subject: [PATCH 5/5] opticon: Fix resume logic
+To: greg@kroah.com, linux-kernel@vger.kernel.org, linux-usb@vger.kernel.org
+Message-ID: <20091006150651.9431.16939.stgit@localhost.localdomain>
+
+
+Opticon now takes the right mutex to check the port status but the status
+check is done wrongly for the modern serial code, so fix it.
+
+Signed-off-by: Alan Cox <alan@linux.intel.com>
+Cc: Alan Stern <stern@rowland.harvard.edu>
+Cc: Oliver Neukum <oliver@neukum.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/serial/opticon.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/usb/serial/opticon.c
++++ b/drivers/usb/serial/opticon.c
+@@ -502,7 +502,8 @@ static int opticon_resume(struct usb_int
+ int result;
+
+ mutex_lock(&port->port.mutex);
+- if (port->port.count)
++ /* This is protected by the port mutex against close/open */
++ if (test_bit(ASYNCB_INITIALIZED, &port->port.flags))
+ result = usb_submit_urb(priv->bulk_read_urb, GFP_NOIO);
+ else
+ result = 0;
diff --git a/tty/serial-8250-calculate-irqflags-bitmask-before-loop.patch b/tty/serial-8250-calculate-irqflags-bitmask-before-loop.patch
new file mode 100644
index 00000000000000..e67d804738ce1d
--- /dev/null
+++ b/tty/serial-8250-calculate-irqflags-bitmask-before-loop.patch
@@ -0,0 +1,72 @@
+From andre.goddard@gmail.com Tue Oct 27 10:44:02 2009
+From: Andr� Goddard Rosa <andre.goddard@gmail.com>
+Date: Sun, 25 Oct 2009 12:01:34 -0200
+Subject: serial, 8250: calculate irqflags bitmask before loop
+To: alan@linux.intel.com, Andrew Morton <akpm@linux-foundation.org>, ddaney@caviumnetworks.com, tpaoletti@caviumnetworks.com, gregkh@suse.de
+Cc: me <andre.goddard@gmail.com>
+Message-ID: <b8bf37780910250701r58d25082y12ea482f6c1b2ea4@mail.gmail.com>
+
+
+Signed-off-by: Andr� Goddard Rosa <andre.goddard@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/serial/8250.c | 16 ++++++++++------
+ 1 file changed, 10 insertions(+), 6 deletions(-)
+
+--- a/drivers/serial/8250.c
++++ b/drivers/serial/8250.c
+@@ -2646,7 +2646,7 @@ static void __init serial8250_isa_init_p
+ {
+ struct uart_8250_port *up;
+ static int first = 1;
+- int i;
++ int i, irqflag = 0;
+
+ if (!first)
+ return;
+@@ -2670,6 +2670,9 @@ static void __init serial8250_isa_init_p
+ up->port.ops = &serial8250_pops;
+ }
+
++ if (share_irqs)
++ irqflag = IRQF_SHARED;
++
+ for (i = 0, up = serial8250_ports;
+ i < ARRAY_SIZE(old_serial_port) && i < nr_uarts;
+ i++, up++) {
+@@ -2683,8 +2686,7 @@ static void __init serial8250_isa_init_p
+ up->port.iotype = old_serial_port[i].io_type;
+ up->port.regshift = old_serial_port[i].iomem_reg_shift;
+ set_io_from_upio(&up->port);
+- if (share_irqs)
+- up->port.irqflags |= IRQF_SHARED;
++ up->port.irqflags |= irqflag;
+ }
+ }
+
+@@ -2940,10 +2942,13 @@ static int __devinit serial8250_probe(st
+ {
+ struct plat_serial8250_port *p = dev->dev.platform_data;
+ struct uart_port port;
+- int ret, i;
++ int ret, i, irqflag = 0;
+
+ memset(&port, 0, sizeof(struct uart_port));
+
++ if (share_irqs)
++ irqflag = IRQF_SHARED;
++
+ for (i = 0; p && p->flags != 0; p++, i++) {
+ port.iobase = p->iobase;
+ port.membase = p->membase;
+@@ -2960,8 +2965,7 @@ static int __devinit serial8250_probe(st
+ port.serial_in = p->serial_in;
+ port.serial_out = p->serial_out;
+ port.dev = &dev->dev;
+- if (share_irqs)
+- port.irqflags |= IRQF_SHARED;
++ port.irqflags |= irqflag;
+ ret = serial8250_register_port(&port);
+ if (ret < 0) {
+ dev_err(&dev->dev, "unable to register port at index %d "
diff --git a/tty/serial-cascade-needless-conditionals.patch b/tty/serial-cascade-needless-conditionals.patch
new file mode 100644
index 00000000000000..a3ac4ac1c8db32
--- /dev/null
+++ b/tty/serial-cascade-needless-conditionals.patch
@@ -0,0 +1,55 @@
+From andre.goddard@gmail.com Tue Oct 27 10:42:56 2009
+From: Andr� Goddard Rosa <andre.goddard@gmail.com>
+Date: Sun, 25 Oct 2009 11:18:26 -0200
+Subject: serial: cascade needless conditionals
+To: gregkh@suse.de, alan@linux.intel.com, Andrew Morton <akpm@linux-foundation.org>, adobriyan@gmail.com
+Cc: me <andre.goddard@gmail.com>
+Message-ID: <b8bf37780910250618h3edce547y41a8dd03e4fb4e71@mail.gmail.com>
+
+
+Signed-off-by: Andr� Goddard Rosa <andre.goddard@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/serial/serial_core.c | 12 +++++-------
+ 1 file changed, 5 insertions(+), 7 deletions(-)
+
+--- a/drivers/serial/serial_core.c
++++ b/drivers/serial/serial_core.c
+@@ -342,11 +342,11 @@ uart_get_baud_rate(struct uart_port *por
+
+ if (flags == UPF_SPD_HI)
+ altbaud = 57600;
+- if (flags == UPF_SPD_VHI)
++ else if (flags == UPF_SPD_VHI)
+ altbaud = 115200;
+- if (flags == UPF_SPD_SHI)
++ else if (flags == UPF_SPD_SHI)
+ altbaud = 230400;
+- if (flags == UPF_SPD_WARP)
++ else if (flags == UPF_SPD_WARP)
+ altbaud = 460800;
+
+ for (try = 0; try < 2; try++) {
+@@ -1217,9 +1217,8 @@ static void uart_set_termios(struct tty_
+ /* Handle transition to B0 status */
+ if ((old_termios->c_cflag & CBAUD) && !(cflag & CBAUD))
+ uart_clear_mctrl(state->uart_port, TIOCM_RTS | TIOCM_DTR);
+-
+ /* Handle transition away from B0 status */
+- if (!(old_termios->c_cflag & CBAUD) && (cflag & CBAUD)) {
++ else if (!(old_termios->c_cflag & CBAUD) && (cflag & CBAUD)) {
+ unsigned int mask = TIOCM_DTR;
+ if (!(cflag & CRTSCTS) ||
+ !test_bit(TTY_THROTTLED, &tty->flags))
+@@ -1234,9 +1233,8 @@ static void uart_set_termios(struct tty_
+ __uart_start(tty);
+ spin_unlock_irqrestore(&state->uart_port->lock, flags);
+ }
+-
+ /* Handle turning on CRTSCTS */
+- if (!(old_termios->c_cflag & CRTSCTS) && (cflag & CRTSCTS)) {
++ else if (!(old_termios->c_cflag & CRTSCTS) && (cflag & CRTSCTS)) {
+ spin_lock_irqsave(&state->uart_port->lock, flags);
+ if (!(state->uart_port->ops->get_mctrl(state->uart_port) & TIOCM_CTS)) {
+ tty->hw_stopped = 1;
diff --git a/tty/serial-fix-null-pointer-dereference.patch b/tty/serial-fix-null-pointer-dereference.patch
new file mode 100644
index 00000000000000..772ff351c318bc
--- /dev/null
+++ b/tty/serial-fix-null-pointer-dereference.patch
@@ -0,0 +1,71 @@
+From andre.goddard@gmail.com Tue Oct 27 10:42:06 2009
+From: Andr� Goddard Rosa <andre.goddard@gmail.com>
+Date: Sun, 25 Oct 2009 11:16:32 -0200
+Subject: serial: fix NULL pointer dereference
+To: gregkh@suse.de, alan@linux.intel.com, Andrew Morton <akpm@linux-foundation.org>, adobriyan@gmail.com
+Cc: me <andre.goddard@gmail.com>
+Message-ID: <b8bf37780910250616g8f204d2h471bd4d511a4816@mail.gmail.com>
+
+From: Andr� Goddard Rosa <andre.goddard@gmail.com>
+
+If kzalloc() or alloc_tty_driver() fails, we call:
+ put_tty_driver(normal = NULL).
+
+Then:
+ put_tty_driver -> tty_driver_kref_put -> kref_put(&NULL->kref, ...)
+
+Signed-off-by: Andr� Goddard Rosa <andre.goddard@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/serial/serial_core.c | 21 +++++++++++----------
+ 1 file changed, 11 insertions(+), 10 deletions(-)
+
+--- a/drivers/serial/serial_core.c
++++ b/drivers/serial/serial_core.c
+@@ -2344,7 +2344,7 @@ static const struct tty_operations uart_
+ */
+ int uart_register_driver(struct uart_driver *drv)
+ {
+- struct tty_driver *normal = NULL;
++ struct tty_driver *normal;
+ int i, retval;
+
+ BUG_ON(drv->state);
+@@ -2354,13 +2354,12 @@ int uart_register_driver(struct uart_dri
+ * we have a large number of ports to handle.
+ */
+ drv->state = kzalloc(sizeof(struct uart_state) * drv->nr, GFP_KERNEL);
+- retval = -ENOMEM;
+ if (!drv->state)
+ goto out;
+
+- normal = alloc_tty_driver(drv->nr);
++ normal = alloc_tty_driver(drv->nr);
+ if (!normal)
+- goto out;
++ goto out_kfree;
+
+ drv->tty_driver = normal;
+
+@@ -2393,12 +2392,14 @@ int uart_register_driver(struct uart_dri
+ }
+
+ retval = tty_register_driver(normal);
+- out:
+- if (retval < 0) {
+- put_tty_driver(normal);
+- kfree(drv->state);
+- }
+- return retval;
++ if (retval >= 0)
++ return retval;
++
++ put_tty_driver(normal);
++out_kfree:
++ kfree(drv->state);
++out:
++ return -ENOMEM;
+ }
+
+ /**
diff --git a/tty/tty_port-add-tty_port_open-helper.patch b/tty/tty_port-add-tty_port_open-helper.patch
new file mode 100644
index 00000000000000..968fa62f0458f4
--- /dev/null
+++ b/tty/tty_port-add-tty_port_open-helper.patch
@@ -0,0 +1,174 @@
+From alan@linux.intel.com Tue Oct 27 10:03:02 2009
+From: Alan Cox <alan@linux.intel.com>
+Date: Tue, 06 Oct 2009 16:06:11 +0100
+Subject: tty_port: add "tty_port_open" helper
+To: greg@kroah.com, linux-kernel@vger.kernel.org, linux-usb@vger.kernel.org
+Message-ID: <20091006150555.9431.34664.stgit@localhost.localdomain>
+
+
+For the moment this just moves the USB logic over and fixes the 'what if
+we open and hangup at the same time' race noticed by Oliver Neukum.
+
+Signed-off-by: Alan Cox <alan@linux.intel.com>
+Cc: Alan Stern <stern@rowland.harvard.edu>
+Cc: Oliver Neukum <oliver@neukum.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+
+---
+ drivers/char/tty_port.c | 36 ++++++++++++++++++++++++++++-
+ drivers/usb/serial/usb-serial.c | 49 ++++++++++++++++------------------------
+ include/linux/tty.h | 10 +++++++-
+ 3 files changed, 64 insertions(+), 31 deletions(-)
+
+--- a/drivers/char/tty_port.c
++++ b/drivers/char/tty_port.c
+@@ -99,10 +99,11 @@ EXPORT_SYMBOL(tty_port_tty_set);
+
+ static void tty_port_shutdown(struct tty_port *port)
+ {
++ mutex_lock(&port->mutex);
+ if (port->ops->shutdown &&
+ test_and_clear_bit(ASYNCB_INITIALIZED, &port->flags))
+ port->ops->shutdown(port);
+-
++ mutex_unlock(&port->mutex);
+ }
+
+ /**
+@@ -375,3 +376,36 @@ void tty_port_close(struct tty_port *por
+ tty_port_tty_set(port, NULL);
+ }
+ EXPORT_SYMBOL(tty_port_close);
++
++int tty_port_open(struct tty_port *port, struct tty_struct *tty,
++ struct file *filp)
++{
++ spin_lock_irq(&port->lock);
++ if (!tty_hung_up_p(filp))
++ ++port->count;
++ spin_unlock_irq(&port->lock);
++ tty_port_tty_set(port, tty);
++
++ /*
++ * Do the device-specific open only if the hardware isn't
++ * already initialized. Serialize open and shutdown using the
++ * port mutex.
++ */
++
++ mutex_lock(&port->mutex);
++
++ if (!test_bit(ASYNCB_INITIALIZED, &port->flags)) {
++ if (port->ops->activate) {
++ int retval = port->ops->activate(port, tty);
++ if (retval) {
++ mutex_unlock(&port->mutex);
++ return retval;
++ }
++ }
++ set_bit(ASYNCB_INITIALIZED, &port->flags);
++ }
++ mutex_unlock(&port->mutex);
++ return tty_port_block_til_ready(port, tty, filp);
++}
++
++EXPORT_SYMBOL(tty_port_open);
+--- a/drivers/usb/serial/usb-serial.c
++++ b/drivers/usb/serial/usb-serial.c
+@@ -247,41 +247,31 @@ static int serial_install(struct tty_dri
+ return retval;
+ }
+
+-static int serial_open(struct tty_struct *tty, struct file *filp)
++static int serial_activate(struct tty_port *tport, struct tty_struct *tty)
+ {
+- struct usb_serial_port *port = tty->driver_data;
++ struct usb_serial_port *port =
++ container_of(tport, struct usb_serial_port, port);
+ struct usb_serial *serial = port->serial;
+ int retval;
+
+- dbg("%s - port %d", __func__, port->number);
+-
+- spin_lock_irq(&port->port.lock);
+- if (!tty_hung_up_p(filp))
+- ++port->port.count;
+- spin_unlock_irq(&port->port.lock);
+- tty_port_tty_set(&port->port, tty);
++ if (mutex_lock_interruptible(&port->mutex))
++ return -ERESTARTSYS;
++ mutex_lock(&serial->disc_mutex);
++ if (serial->disconnected)
++ retval = -ENODEV;
++ else
++ retval = port->serial->type->open(tty, port);
++ mutex_unlock(&serial->disc_mutex);
++ mutex_unlock(&port->mutex);
++ return retval;
++}
+
+- /* Do the device-specific open only if the hardware isn't
+- * already initialized.
+- */
+- if (!test_bit(ASYNCB_INITIALIZED, &port->port.flags)) {
+- if (mutex_lock_interruptible(&port->mutex))
+- return -ERESTARTSYS;
+- mutex_lock(&serial->disc_mutex);
+- if (serial->disconnected)
+- retval = -ENODEV;
+- else
+- retval = port->serial->type->open(tty, port);
+- mutex_unlock(&serial->disc_mutex);
+- mutex_unlock(&port->mutex);
+- if (retval)
+- return retval;
+- set_bit(ASYNCB_INITIALIZED, &port->port.flags);
+- }
++static int serial_open(struct tty_struct *tty, struct file *filp)
++{
++ struct usb_serial_port *port = tty->driver_data;
+
+- /* Now do the correct tty layer semantics */
+- retval = tty_port_block_til_ready(&port->port, tty, filp);
+- return retval;
++ dbg("%s - port %d", __func__, port->number);
++ return tty_port_open(&port->port, tty, filp);
+ }
+
+ /**
+@@ -725,6 +715,7 @@ static void serial_dtr_rts(struct tty_po
+ static const struct tty_port_operations serial_port_ops = {
+ .carrier_raised = serial_carrier_raised,
+ .dtr_rts = serial_dtr_rts,
++ .activate = serial_activate,
+ };
+
+ int usb_serial_probe(struct usb_interface *interface,
+--- a/include/linux/tty.h
++++ b/include/linux/tty.h
+@@ -190,9 +190,15 @@ struct tty_port_operations {
+ /* Control the DTR line */
+ void (*dtr_rts)(struct tty_port *port, int raise);
+ /* Called when the last close completes or a hangup finishes
+- IFF the port was initialized. Do not use to free resources */
++ IFF the port was initialized. Do not use to free resources. Called
++ under the port mutex to serialize against activate/shutdowns */
+ void (*shutdown)(struct tty_port *port);
+ void (*drop)(struct tty_port *port);
++ /* Called under the port mutex from tty_port_open, serialized using
++ the port mutex */
++ /* FIXME: long term getting the tty argument *out* of this would be
++ good for consoles */
++ int (*activate)(struct tty_port *port, struct tty_struct *tty);
+ };
+
+ struct tty_port {
+@@ -467,6 +473,8 @@ extern int tty_port_close_start(struct t
+ extern void tty_port_close_end(struct tty_port *port, struct tty_struct *tty);
+ extern void tty_port_close(struct tty_port *port,
+ struct tty_struct *tty, struct file *filp);
++extern int tty_port_open(struct tty_port *port,
++ struct tty_struct *tty, struct file *filp);
+ extern inline int tty_port_users(struct tty_port *port)
+ {
+ return port->count + port->blocked_open;
diff --git a/tty/tty_port-coding-style-cleaning-pass.patch b/tty/tty_port-coding-style-cleaning-pass.patch
new file mode 100644
index 00000000000000..8c322f6308d063
--- /dev/null
+++ b/tty/tty_port-coding-style-cleaning-pass.patch
@@ -0,0 +1,98 @@
+From alan@linux.intel.com Tue Oct 27 10:03:21 2009
+From: Alan Cox <alan@linux.intel.com>
+Date: Tue, 06 Oct 2009 16:06:21 +0100
+Subject: tty_port: coding style cleaning pass
+To: greg@kroah.com, linux-kernel@vger.kernel.org, linux-usb@vger.kernel.org
+Message-ID: <20091006150616.9431.29417.stgit@localhost.localdomain>
+
+
+Mind the hoover wire...
+
+Signed-off-by: Alan Cox <alan@linux.intel.com>
+Cc: Alan Stern <stern@rowland.harvard.edu>
+Cc: Oliver Neukum <oliver@neukum.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/char/tty_port.c | 25 +++++++++++++------------
+ 1 file changed, 13 insertions(+), 12 deletions(-)
+
+--- a/drivers/char/tty_port.c
++++ b/drivers/char/tty_port.c
+@@ -199,7 +199,7 @@ EXPORT_SYMBOL(tty_port_lower_dtr_rts);
+ * management of these lines. Note that the dtr/rts raise is done each
+ * iteration as a hangup may have previously dropped them while we wait.
+ */
+-
++
+ int tty_port_block_til_ready(struct tty_port *port,
+ struct tty_struct *tty, struct file *filp)
+ {
+@@ -248,7 +248,8 @@ int tty_port_block_til_ready(struct tty_
+ tty_port_raise_dtr_rts(port);
+
+ prepare_to_wait(&port->open_wait, &wait, TASK_INTERRUPTIBLE);
+- /* Check for a hangup or uninitialised port. Return accordingly */
++ /* Check for a hangup or uninitialised port.
++ Return accordingly */
+ if (tty_hung_up_p(filp) || !(port->flags & ASYNC_INITIALIZED)) {
+ if (port->flags & ASYNC_HUP_NOTIFY)
+ retval = -EAGAIN;
+@@ -280,11 +281,11 @@ int tty_port_block_til_ready(struct tty_
+ port->flags |= ASYNC_NORMAL_ACTIVE;
+ spin_unlock_irqrestore(&port->lock, flags);
+ return retval;
+-
+ }
+ EXPORT_SYMBOL(tty_port_block_til_ready);
+
+-int tty_port_close_start(struct tty_port *port, struct tty_struct *tty, struct file *filp)
++int tty_port_close_start(struct tty_port *port,
++ struct tty_struct *tty, struct file *filp)
+ {
+ unsigned long flags;
+
+@@ -294,7 +295,7 @@ int tty_port_close_start(struct tty_port
+ return 0;
+ }
+
+- if( tty->count == 1 && port->count != 1) {
++ if (tty->count == 1 && port->count != 1) {
+ printk(KERN_WARNING
+ "tty_port_close_start: tty->count = 1 port count = %d.\n",
+ port->count);
+@@ -326,8 +327,8 @@ int tty_port_close_start(struct tty_port
+ long timeout;
+
+ if (bps > 1200)
+- timeout = max_t(long, (HZ * 10 * port->drain_delay) / bps,
+- HZ / 10);
++ timeout = max_t(long,
++ (HZ * 10 * port->drain_delay) / bps, HZ / 10);
+ else
+ timeout = 2 * HZ;
+ schedule_timeout_interruptible(timeout);
+@@ -378,7 +379,7 @@ void tty_port_close(struct tty_port *por
+ EXPORT_SYMBOL(tty_port_close);
+
+ int tty_port_open(struct tty_port *port, struct tty_struct *tty,
+- struct file *filp)
++ struct file *filp)
+ {
+ spin_lock_irq(&port->lock);
+ if (!tty_hung_up_p(filp))
+@@ -398,10 +399,10 @@ int tty_port_open(struct tty_port *port,
+ if (port->ops->activate) {
+ int retval = port->ops->activate(port, tty);
+ if (retval) {
+- mutex_unlock(&port->mutex);
+- return retval;
+- }
+- }
++ mutex_unlock(&port->mutex);
++ return retval;
++ }
++ }
+ set_bit(ASYNCB_INITIALIZED, &port->flags);
+ }
+ mutex_unlock(&port->mutex);
diff --git a/tty/usb_serial-kill-port-mutex.patch b/tty/usb_serial-kill-port-mutex.patch
new file mode 100644
index 00000000000000..32b861dffc5506
--- /dev/null
+++ b/tty/usb_serial-kill-port-mutex.patch
@@ -0,0 +1,68 @@
+From alan@linux.intel.com Tue Oct 27 10:07:10 2009
+From: Alan Cox <alan@linux.intel.com>
+Date: Tue, 06 Oct 2009 16:06:46 +0100
+Subject: usb_serial: Kill port mutex
+To: greg@kroah.com, linux-kernel@vger.kernel.org, linux-usb@vger.kernel.org
+Message-ID: <20091006150641.9431.67880.stgit@localhost.localdomain>
+
+
+The tty port has a port mutex used for all the port related locking so we
+don't need the one in the USB serial layer any more.
+
+Signed-off-by: Alan Cox <alan@linux.intel.com>
+Cc: Alan Stern <stern@rowland.harvard.edu>
+Cc: Oliver Neukum <oliver@neukum.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/serial/opticon.c | 4 ++--
+ drivers/usb/serial/usb-serial.c | 1 -
+ include/linux/usb/serial.h | 3 ---
+ 3 files changed, 2 insertions(+), 6 deletions(-)
+
+--- a/drivers/usb/serial/opticon.c
++++ b/drivers/usb/serial/opticon.c
+@@ -501,12 +501,12 @@ static int opticon_resume(struct usb_int
+ struct usb_serial_port *port = serial->port[0];
+ int result;
+
+- mutex_lock(&port->mutex);
++ mutex_lock(&port->port.mutex);
+ if (port->port.count)
+ result = usb_submit_urb(priv->bulk_read_urb, GFP_NOIO);
+ else
+ result = 0;
+- mutex_unlock(&port->mutex);
++ mutex_unlock(&port->port.mutex);
+ return result;
+ }
+
+--- a/drivers/usb/serial/usb-serial.c
++++ b/drivers/usb/serial/usb-serial.c
+@@ -897,7 +897,6 @@ int usb_serial_probe(struct usb_interfac
+ spin_lock_init(&port->lock);
+ /* Keep this for private driver use for the moment but
+ should probably go away */
+- mutex_init(&port->mutex);
+ INIT_WORK(&port->work, usb_serial_port_work);
+ serial->port[i] = port;
+ port->dev.parent = &interface->dev;
+--- a/include/linux/usb/serial.h
++++ b/include/linux/usb/serial.h
+@@ -39,8 +39,6 @@ enum port_dev_state {
+ * @serial: pointer back to the struct usb_serial owner of this port.
+ * @port: pointer to the corresponding tty_port for this port.
+ * @lock: spinlock to grab when updating portions of this structure.
+- * @mutex: mutex used to synchronize serial_open() and serial_close()
+- * access for this port.
+ * @number: the number of the port (the minor number).
+ * @interrupt_in_buffer: pointer to the interrupt in buffer for this port.
+ * @interrupt_in_urb: pointer to the interrupt in struct urb for this port.
+@@ -77,7 +75,6 @@ struct usb_serial_port {
+ struct usb_serial *serial;
+ struct tty_port port;
+ spinlock_t lock;
+- struct mutex mutex;
+ unsigned char number;
+
+ unsigned char *interrupt_in_buffer;
diff --git a/tty/usb_serial-use-the-shutdown-operation.patch b/tty/usb_serial-use-the-shutdown-operation.patch
new file mode 100644
index 00000000000000..0def7d620d5395
--- /dev/null
+++ b/tty/usb_serial-use-the-shutdown-operation.patch
@@ -0,0 +1,124 @@
+From alan@linux.intel.com Tue Oct 27 10:05:50 2009
+From: Alan Cox <alan@linux.intel.com>
+Date: Tue, 06 Oct 2009 16:06:36 +0100
+Subject: [PATCH 3/5] usb_serial: Use the shutdown() operation
+To: greg@kroah.com, linux-kernel@vger.kernel.org, linux-usb@vger.kernel.org
+Message-ID: <20091006150626.9431.34542.stgit@localhost.localdomain>
+
+
+As Alan Stern pointed out - now we have tty_port_open the shutdown method
+and locking allow us to whack the other bits into the full helper methods
+and provide a shutdown op which the tty port code will synchronize with
+setup for us.
+
+Signed-off-by: Alan Cox <alan@linux.intel.com>
+Cc: Alan Stern <stern@rowland.harvard.edu>
+Cc: Oliver Neukum <oliver@neukum.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+
+---
+ drivers/usb/serial/usb-serial.c | 39 +++++++++++----------------------------
+ 1 file changed, 11 insertions(+), 28 deletions(-)
+
+--- a/drivers/usb/serial/usb-serial.c
++++ b/drivers/usb/serial/usb-serial.c
+@@ -254,15 +254,12 @@ static int serial_activate(struct tty_po
+ struct usb_serial *serial = port->serial;
+ int retval;
+
+- if (mutex_lock_interruptible(&port->mutex))
+- return -ERESTARTSYS;
+ mutex_lock(&serial->disc_mutex);
+ if (serial->disconnected)
+ retval = -ENODEV;
+ else
+ retval = port->serial->type->open(tty, port);
+ mutex_unlock(&serial->disc_mutex);
+- mutex_unlock(&port->mutex);
+ return retval;
+ }
+
+@@ -276,57 +273,40 @@ static int serial_open(struct tty_struct
+
+ /**
+ * serial_down - shut down hardware
+- * @port: port to shut down
++ * @tport: tty port to shut down
+ *
+ * Shut down a USB serial port unless it is the console. We never
+- * shut down the console hardware as it will always be in use.
++ * shut down the console hardware as it will always be in use. Serialized
++ * against activate by the tport mutex and kept to matching open/close pairs
++ * of calls by the ASYNCB_INITIALIZED flag.
+ */
+-static void serial_down(struct usb_serial_port *port)
++static void serial_down(struct tty_port *tport)
+ {
++ struct usb_serial_port *port =
++ container_of(tport, struct usb_serial_port, port);
+ struct usb_serial_driver *drv = port->serial->type;
+-
+ /*
+ * The console is magical. Do not hang up the console hardware
+ * or there will be tears.
+ */
+ if (port->console)
+ return;
+-
+- /* Don't call the close method if the hardware hasn't been
+- * initialized.
+- */
+- if (!test_and_clear_bit(ASYNCB_INITIALIZED, &port->port.flags))
+- return;
+-
+- mutex_lock(&port->mutex);
+ if (drv->close)
+ drv->close(port);
+- mutex_unlock(&port->mutex);
+ }
+
+ static void serial_hangup(struct tty_struct *tty)
+ {
+ struct usb_serial_port *port = tty->driver_data;
+-
+ dbg("%s - port %d", __func__, port->number);
+-
+- serial_down(port);
+ tty_port_hangup(&port->port);
+ }
+
+ static void serial_close(struct tty_struct *tty, struct file *filp)
+ {
+ struct usb_serial_port *port = tty->driver_data;
+-
+ dbg("%s - port %d", __func__, port->number);
+-
+- if (tty_hung_up_p(filp))
+- return;
+- if (tty_port_close_start(&port->port, tty, filp) == 0)
+- return;
+- serial_down(port);
+- tty_port_close_end(&port->port, tty);
+- tty_port_tty_set(&port->port, NULL);
++ tty_port_close(&port->port, tty, filp);
+ }
+
+ /**
+@@ -716,6 +696,7 @@ static const struct tty_port_operations
+ .carrier_raised = serial_carrier_raised,
+ .dtr_rts = serial_dtr_rts,
+ .activate = serial_activate,
++ .shutdown = serial_down,
+ };
+
+ int usb_serial_probe(struct usb_interface *interface,
+@@ -914,6 +895,8 @@ int usb_serial_probe(struct usb_interfac
+ port->port.ops = &serial_port_ops;
+ port->serial = serial;
+ spin_lock_init(&port->lock);
++ /* Keep this for private driver use for the moment but
++ should probably go away */
+ mutex_init(&port->mutex);
+ INIT_WORK(&port->work, usb_serial_port_work);
+ serial->port[i] = port;