aboutsummaryrefslogtreecommitdiffstats
diff options
authorGreg Kroah-Hartman <gregkh@suse.de>2010-06-15 16:54:26 -0700
committerGreg Kroah-Hartman <gregkh@suse.de>2010-06-15 16:54:26 -0700
commitb97d8272574fd248ce819353c65b210f04602b74 (patch)
treea0d8eeba93977bdb7039da551b0a2026c38d3f40
parent7142a157be617a09cbf999cf35006da3c168eb36 (diff)
downloadpatches-b97d8272574fd248ce819353c65b210f04602b74.tar.gz
first part of the tty bkl work
-rw-r--r--series17
-rw-r--r--tty/cyclades-kill-off-bkl-usage.patch134
-rw-r--r--tty/epca-kill-the-big-kernel-lock.patch48
-rw-r--r--tty/isicom-kill-off-the-bkl.patch86
-rw-r--r--tty/istallion-use-bit-ops-for-the-board-flags.patch178
-rw-r--r--tty/riscom8-kill-use-of-lock_kernel.patch93
-rw-r--r--tty/rocket-kill-bkl.patch162
-rw-r--r--tty/specialix-kill-the-bkl.patch68
-rw-r--r--tty/stallion-prune-lock_kernel-calls.patch244
-rw-r--r--tty/synclink-kill-the-big-kernel-lock.patch370
-rw-r--r--tty/synclink-reworking-locking-a-bit.patch133
-rw-r--r--tty/tty-fix-the-digi-acceleport-driver-null-checks.patch57
-rw-r--r--tty/tty-serial-fix-tty-back-references-in-termios.patch170
-rw-r--r--tty/tty-serial-fix-tty-referencing-in-set_ldisc.patch66
-rw-r--r--tty/tty-serial-fix-various-misuses-mishandlings-of-port-tty.patch363
15 files changed, 2189 insertions, 0 deletions
diff --git a/series b/series
index d4dad78d6eafe7..83870f5462022c 100644
--- a/series
+++ b/series
@@ -51,6 +51,22 @@ driver-core/driver-core-internal-struct-dma_coherent_mem-change-type-of-a-member
tty/n_gsm.c-removed-duplicated-includes.patch
tty/serial-there-s-no-config-console.patch
+# tty bkl removal work
+tty/stallion-prune-lock_kernel-calls.patch
+tty/istallion-use-bit-ops-for-the-board-flags.patch
+tty/riscom8-kill-use-of-lock_kernel.patch
+tty/isicom-kill-off-the-bkl.patch
+tty/rocket-kill-bkl.patch
+tty/synclink-kill-the-big-kernel-lock.patch
+tty/cyclades-kill-off-bkl-usage.patch
+tty/epca-kill-the-big-kernel-lock.patch
+tty/specialix-kill-the-bkl.patch
+tty/tty-fix-the-digi-acceleport-driver-null-checks.patch
+tty/synclink-reworking-locking-a-bit.patch
+tty/tty-serial-fix-various-misuses-mishandlings-of-port-tty.patch
+tty/tty-serial-fix-tty-back-references-in-termios.patch
+tty/tty-serial-fix-tty-referencing-in-set_ldisc.patch
+
###################################
# USB stuff for after 2.6.35 is out
###################################
@@ -76,3 +92,4 @@ usb/usb-isd200.c-remove-unnecessary-kmalloc-cast.patch
# staging stuff is now in the staging-next tree on git.kernel.org
+
diff --git a/tty/cyclades-kill-off-bkl-usage.patch b/tty/cyclades-kill-off-bkl-usage.patch
new file mode 100644
index 00000000000000..3ee254b00ddd17
--- /dev/null
+++ b/tty/cyclades-kill-off-bkl-usage.patch
@@ -0,0 +1,134 @@
+From arnd@arndb.de Tue Jun 15 16:45:31 2010
+From: Alan Cox <alan@linux.intel.com>
+Date: Tue, 1 Jun 2010 22:52:47 +0200
+Subject: cyclades: Kill off BKL usage
+To: Greg KH <gregkh@suse.de>
+Cc: linux-kernel@vger.kernel.org, Arnd Bergmann <arnd@arndb.de>, Alan Cox <alan@lxorguk.ukuu.org.uk>, Frederic Weisbecker <fweisbec@gmail.com>, John Kacur <jkacur@redhat.com>, Alan Cox <alan@linux.intel.com>
+Message-ID: <1275425591-8803-8-git-send-email-arnd@arndb.de>
+
+
+From: Alan Cox <alan@linux.intel.com>
+
+Use the port mutext for config setting, the rest is locked sufficiently
+anyway that the BKL makes no odds.
+
+Signed-off-by: Alan Cox <alan@linux.intel.com>
+Cc: Arnd Bergmann <arnd@arndb.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/char/cyclades.c | 20 +++++++++-----------
+ 1 file changed, 9 insertions(+), 11 deletions(-)
+
+--- a/drivers/char/cyclades.c
++++ b/drivers/char/cyclades.c
+@@ -65,7 +65,6 @@
+ #include <linux/tty.h>
+ #include <linux/tty_flip.h>
+ #include <linux/serial.h>
+-#include <linux/smp_lock.h>
+ #include <linux/major.h>
+ #include <linux/string.h>
+ #include <linux/fcntl.h>
+@@ -1655,7 +1654,6 @@ static void cy_wait_until_sent(struct tt
+ return; /* Just in case.... */
+
+ orig_jiffies = jiffies;
+- lock_kernel();
+ /*
+ * Set the check interval to be 1/5 of the estimated time to
+ * send a single character, and make it at least 1. The check
+@@ -1702,7 +1700,6 @@ static void cy_wait_until_sent(struct tt
+ }
+ /* Run one more char cycle */
+ msleep_interruptible(jiffies_to_msecs(char_time * 5));
+- unlock_kernel();
+ #ifdef CY_DEBUG_WAIT_UNTIL_SENT
+ printk(KERN_DEBUG "Clean (jiff=%lu)...done\n", jiffies);
+ #endif
+@@ -1959,7 +1956,6 @@ static int cy_chars_in_buffer(struct tty
+ int char_count;
+ __u32 tx_put, tx_get, tx_bufsize;
+
+- lock_kernel();
+ tx_get = readl(&buf_ctrl->tx_get);
+ tx_put = readl(&buf_ctrl->tx_put);
+ tx_bufsize = readl(&buf_ctrl->tx_bufsize);
+@@ -1971,7 +1967,6 @@ static int cy_chars_in_buffer(struct tty
+ printk(KERN_DEBUG "cyc:cy_chars_in_buffer ttyC%d %d\n",
+ info->line, info->xmit_cnt + char_count);
+ #endif
+- unlock_kernel();
+ return info->xmit_cnt + char_count;
+ }
+ #endif /* Z_EXT_CHARS_IN_BUFFER */
+@@ -2359,17 +2354,22 @@ cy_set_serial_info(struct cyclades_port
+ struct serial_struct __user *new_info)
+ {
+ struct serial_struct new_serial;
++ int ret;
+
+ if (copy_from_user(&new_serial, new_info, sizeof(new_serial)))
+ return -EFAULT;
+
++ mutex_lock(&info->port.mutex);
+ if (!capable(CAP_SYS_ADMIN)) {
+ if (new_serial.close_delay != info->port.close_delay ||
+ new_serial.baud_base != info->baud ||
+ (new_serial.flags & ASYNC_FLAGS &
+ ~ASYNC_USR_MASK) !=
+ (info->port.flags & ASYNC_FLAGS & ~ASYNC_USR_MASK))
++ {
++ mutex_unlock(&info->port.mutex);
+ return -EPERM;
++ }
+ info->port.flags = (info->port.flags & ~ASYNC_USR_MASK) |
+ (new_serial.flags & ASYNC_USR_MASK);
+ info->baud = new_serial.baud_base;
+@@ -2392,10 +2392,12 @@ cy_set_serial_info(struct cyclades_port
+ check_and_exit:
+ if (info->port.flags & ASYNC_INITIALIZED) {
+ cy_set_line_char(info, tty);
+- return 0;
++ ret = 0;
+ } else {
+- return cy_startup(info, tty);
++ ret = cy_startup(info, tty);
+ }
++ mutex_unlock(&info->port.mutex);
++ return ret;
+ } /* set_serial_info */
+
+ /*
+@@ -2438,7 +2440,6 @@ static int cy_tiocmget(struct tty_struct
+
+ card = info->card;
+
+- lock_kernel();
+ if (!cy_is_Z(card)) {
+ unsigned long flags;
+ int channel = info->line - card->first_line;
+@@ -2478,7 +2479,6 @@ static int cy_tiocmget(struct tty_struct
+ ((lstatus & C_RS_CTS) ? TIOCM_CTS : 0);
+ }
+ end:
+- unlock_kernel();
+ return result;
+ } /* cy_tiomget */
+
+@@ -2696,7 +2696,6 @@ cy_ioctl(struct tty_struct *tty, struct
+ printk(KERN_DEBUG "cyc:cy_ioctl ttyC%d, cmd = %x arg = %lx\n",
+ info->line, cmd, arg);
+ #endif
+- lock_kernel();
+
+ switch (cmd) {
+ case CYGETMON:
+@@ -2817,7 +2816,6 @@ cy_ioctl(struct tty_struct *tty, struct
+ default:
+ ret_val = -ENOIOCTLCMD;
+ }
+- unlock_kernel();
+
+ #ifdef CY_DEBUG_OTHER
+ printk(KERN_DEBUG "cyc:cy_ioctl done\n");
diff --git a/tty/epca-kill-the-big-kernel-lock.patch b/tty/epca-kill-the-big-kernel-lock.patch
new file mode 100644
index 00000000000000..58a4462e36e1a1
--- /dev/null
+++ b/tty/epca-kill-the-big-kernel-lock.patch
@@ -0,0 +1,48 @@
+From arnd@arndb.de Tue Jun 15 16:45:53 2010
+From: Alan Cox <alan@linux.intel.com>
+Date: Tue, 1 Jun 2010 22:52:48 +0200
+Subject: epca: Kill the big kernel lock
+To: Greg KH <gregkh@suse.de>
+Cc: linux-kernel@vger.kernel.org, Arnd Bergmann <arnd@arndb.de>, Alan Cox <alan@lxorguk.ukuu.org.uk>, Frederic Weisbecker <fweisbec@gmail.com>, John Kacur <jkacur@redhat.com>, Alan Cox <alan@linux.intel.com>
+Message-ID: <1275425591-8803-9-git-send-email-arnd@arndb.de>
+
+
+From: Alan Cox <alan@linux.intel.com>
+
+The lock is no longer needed for wait until sent paths so this can go
+
+Signed-off-by: Alan Cox <alan@linux.intel.com>
+Cc: Arnd Bergmann <arnd@arndb.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/char/epca.c | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+--- a/drivers/char/epca.c
++++ b/drivers/char/epca.c
+@@ -36,7 +36,7 @@
+ #include <linux/ctype.h>
+ #include <linux/tty.h>
+ #include <linux/tty_flip.h>
+-#include <linux/smp_lock.h>
++#include <linux/slab.h>
+ #include <linux/ioport.h>
+ #include <linux/interrupt.h>
+ #include <linux/uaccess.h>
+@@ -2105,7 +2105,6 @@ static int pc_ioctl(struct tty_struct *t
+ break;
+ case DIGI_SETAW:
+ case DIGI_SETAF:
+- lock_kernel();
+ if (cmd == DIGI_SETAW) {
+ /* Setup an event to indicate when the transmit
+ buffer empties */
+@@ -2118,7 +2117,6 @@ static int pc_ioctl(struct tty_struct *t
+ if (tty->ldisc->ops->flush_buffer)
+ tty->ldisc->ops->flush_buffer(tty);
+ }
+- unlock_kernel();
+ /* Fall Thru */
+ case DIGI_SETA:
+ if (copy_from_user(&ch->digiext, argp, sizeof(digi_t)))
diff --git a/tty/isicom-kill-off-the-bkl.patch b/tty/isicom-kill-off-the-bkl.patch
new file mode 100644
index 00000000000000..8b8ee59c5ac63b
--- /dev/null
+++ b/tty/isicom-kill-off-the-bkl.patch
@@ -0,0 +1,86 @@
+From arnd@arndb.de Tue Jun 15 16:44:18 2010
+From: Alan Cox <alan@linux.intel.com>
+Date: Tue, 1 Jun 2010 22:52:44 +0200
+Subject: isicom: kill off the BKL
+To: Greg KH <gregkh@suse.de>
+Cc: linux-kernel@vger.kernel.org, Arnd Bergmann <arnd@arndb.de>, Alan Cox <alan@lxorguk.ukuu.org.uk>, Frederic Weisbecker <fweisbec@gmail.com>, John Kacur <jkacur@redhat.com>, Alan Cox <alan@linux.intel.com>
+Message-ID: <1275425591-8803-5-git-send-email-arnd@arndb.de>
+
+
+From: Alan Cox <alan@linux.intel.com>
+
+As with the others we can use the port mutex to get the needed locking
+properties and fix the race with open.
+
+Signed-off-by: Alan Cox <alan@linux.intel.com>
+Cc: Arnd Bergmann <arnd@arndb.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/char/isicom.c | 13 +++++--------
+ 1 file changed, 5 insertions(+), 8 deletions(-)
+
+--- a/drivers/char/isicom.c
++++ b/drivers/char/isicom.c
+@@ -124,7 +124,6 @@
+ #include <linux/fs.h>
+ #include <linux/sched.h>
+ #include <linux/serial.h>
+-#include <linux/smp_lock.h>
+ #include <linux/mm.h>
+ #include <linux/interrupt.h>
+ #include <linux/timer.h>
+@@ -872,7 +871,6 @@ static struct tty_port *isicom_find_port
+ static int isicom_open(struct tty_struct *tty, struct file *filp)
+ {
+ struct isi_port *port;
+- struct isi_board *card;
+ struct tty_port *tport;
+
+ tport = isicom_find_port(tty);
+@@ -1118,8 +1116,7 @@ static int isicom_set_serial_info(struct
+ if (copy_from_user(&newinfo, info, sizeof(newinfo)))
+ return -EFAULT;
+
+- lock_kernel();
+-
++ mutex_lock(&port->port.mutex);
+ reconfig_port = ((port->port.flags & ASYNC_SPD_MASK) !=
+ (newinfo.flags & ASYNC_SPD_MASK));
+
+@@ -1128,7 +1125,7 @@ static int isicom_set_serial_info(struct
+ (newinfo.closing_wait != port->port.closing_wait) ||
+ ((newinfo.flags & ~ASYNC_USR_MASK) !=
+ (port->port.flags & ~ASYNC_USR_MASK))) {
+- unlock_kernel();
++ mutex_unlock(&port->port.mutex);
+ return -EPERM;
+ }
+ port->port.flags = ((port->port.flags & ~ASYNC_USR_MASK) |
+@@ -1145,7 +1142,7 @@ static int isicom_set_serial_info(struct
+ isicom_config_port(tty);
+ spin_unlock_irqrestore(&port->card->card_lock, flags);
+ }
+- unlock_kernel();
++ mutex_unlock(&port->port.mutex);
+ return 0;
+ }
+
+@@ -1154,7 +1151,7 @@ static int isicom_get_serial_info(struct
+ {
+ struct serial_struct out_info;
+
+- lock_kernel();
++ mutex_lock(&port->port.mutex);
+ memset(&out_info, 0, sizeof(out_info));
+ /* out_info.type = ? */
+ out_info.line = port - isi_ports;
+@@ -1164,7 +1161,7 @@ static int isicom_get_serial_info(struct
+ /* out_info.baud_base = ? */
+ out_info.close_delay = port->port.close_delay;
+ out_info.closing_wait = port->port.closing_wait;
+- unlock_kernel();
++ mutex_unlock(&port->port.mutex);
+ if (copy_to_user(info, &out_info, sizeof(out_info)))
+ return -EFAULT;
+ return 0;
diff --git a/tty/istallion-use-bit-ops-for-the-board-flags.patch b/tty/istallion-use-bit-ops-for-the-board-flags.patch
new file mode 100644
index 00000000000000..9d175f68bf7745
--- /dev/null
+++ b/tty/istallion-use-bit-ops-for-the-board-flags.patch
@@ -0,0 +1,178 @@
+From arnd@arndb.de Tue Jun 15 16:43:31 2010
+From: Alan Cox <alan@linux.intel.com>
+Date: Tue, 1 Jun 2010 22:52:42 +0200
+Subject: istallion: use bit ops for the board flags
+To: Greg KH <gregkh@suse.de>
+Cc: linux-kernel@vger.kernel.org, Arnd Bergmann <arnd@arndb.de>, Alan Cox <alan@lxorguk.ukuu.org.uk>, Frederic Weisbecker <fweisbec@gmail.com>, John Kacur <jkacur@redhat.com>, Alan Cox <alan@linux.intel.com>
+Message-ID: <1275425591-8803-3-git-send-email-arnd@arndb.de>
+
+
+From: Alan Cox <alan@linux.intel.com>
+
+This lets us avoid problems with races on the flag changes
+
+Signed-off-by: Alan Cox <alan@linux.intel.com>
+Cc: Arnd Bergmann <arnd@arndb.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/char/istallion.c | 36 ++++++++++++++++++------------------
+ include/linux/istallion.h | 2 +-
+ 2 files changed, 19 insertions(+), 19 deletions(-)
+
+--- a/drivers/char/istallion.c
++++ b/drivers/char/istallion.c
+@@ -14,7 +14,6 @@
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+- * FIXME: brdp->state needs proper locking.
+ */
+
+ /*****************************************************************************/
+@@ -204,9 +203,9 @@ static int stli_shared;
+ * the board has been detected, and whether it is actually running a slave
+ * or not.
+ */
+-#define BST_FOUND 0x1
+-#define BST_STARTED 0x2
+-#define BST_PROBED 0x4
++#define BST_FOUND 0
++#define BST_STARTED 1
++#define BST_PROBED 2
+
+ /*
+ * Define the set of port state flags. These are marked for internal
+@@ -817,7 +816,7 @@ static int stli_open(struct tty_struct *
+ brdp = stli_brds[brdnr];
+ if (brdp == NULL)
+ return -ENODEV;
+- if ((brdp->state & BST_STARTED) == 0)
++ if (!test_bit(BST_STARTED, &brdp->state))
+ return -ENODEV;
+ portnr = MINOR2PORT(minordev);
+ if (portnr > brdp->nrports)
+@@ -1847,7 +1846,7 @@ static void stli_portinfo(struct seq_fil
+ rc = stli_portcmdstats(NULL, portp);
+
+ uart = "UNKNOWN";
+- if (brdp->state & BST_STARTED) {
++ if (test_bit(BST_STARTED, &brdp->state)) {
+ switch (stli_comstats.hwid) {
+ case 0: uart = "2681"; break;
+ case 1: uart = "SC26198"; break;
+@@ -1856,7 +1855,7 @@ static void stli_portinfo(struct seq_fil
+ }
+ seq_printf(m, "%d: uart:%s ", portnr, uart);
+
+- if ((brdp->state & BST_STARTED) && (rc >= 0)) {
++ if (test_bit(BST_STARTED, &brdp->state) && rc >= 0) {
+ char sep;
+
+ seq_printf(m, "tx:%d rx:%d", (int) stli_comstats.txtotal,
+@@ -2356,7 +2355,7 @@ static void stli_poll(unsigned long arg)
+ brdp = stli_brds[brdnr];
+ if (brdp == NULL)
+ continue;
+- if ((brdp->state & BST_STARTED) == 0)
++ if (!test_bit(BST_STARTED, &brdp->state))
+ continue;
+
+ spin_lock(&brd_lock);
+@@ -3141,7 +3140,7 @@ static int stli_initecp(struct stlibrd *
+ }
+
+
+- brdp->state |= BST_FOUND;
++ set_bit(BST_FOUND, &brdp->state);
+ return 0;
+ err_unmap:
+ iounmap(brdp->membase);
+@@ -3298,7 +3297,7 @@ static int stli_initonb(struct stlibrd *
+ brdp->panels[0] = brdp->nrports;
+
+
+- brdp->state |= BST_FOUND;
++ set_bit(BST_FOUND, &brdp->state);
+ return 0;
+ err_unmap:
+ iounmap(brdp->membase);
+@@ -3408,7 +3407,7 @@ stli_donestartup:
+ spin_unlock_irqrestore(&brd_lock, flags);
+
+ if (rc == 0)
+- brdp->state |= BST_STARTED;
++ set_bit(BST_STARTED, &brdp->state);
+
+ if (! stli_timeron) {
+ stli_timeron++;
+@@ -3711,7 +3710,7 @@ static int __devinit stli_pciprobe(struc
+ if (retval)
+ goto err_null;
+
+- brdp->state |= BST_PROBED;
++ set_bit(BST_PROBED, &brdp->state);
+ pci_set_drvdata(pdev, brdp);
+
+ EBRDENABLE(brdp);
+@@ -3842,7 +3841,7 @@ static int __init stli_initbrds(void)
+ brdp = stli_brds[i];
+ if (brdp == NULL)
+ continue;
+- if (brdp->state & BST_FOUND) {
++ if (test_bit(BST_FOUND, &brdp->state)) {
+ EBRDENABLE(brdp);
+ brdp->enable = NULL;
+ brdp->disable = NULL;
+@@ -4079,7 +4078,7 @@ static int stli_portcmdstats(struct tty_
+ return -ENODEV;
+
+ mutex_lock(&portp->port.mutex);
+- if (brdp->state & BST_STARTED) {
++ if (test_bit(BST_STARTED, &brdp->state)) {
+ if ((rc = stli_cmdwait(brdp, portp, A_GETSTATS,
+ &stli_cdkstats, sizeof(asystats_t), 1)) < 0) {
+ mutex_unlock(&portp->port.mutex);
+@@ -4194,7 +4193,7 @@ static int stli_clrportstats(struct stli
+
+ mutex_lock(&portp->port.mutex);
+
+- if (brdp->state & BST_STARTED) {
++ if (test_bit(BST_STARTED, &brdp->state)) {
+ if ((rc = stli_cmdwait(brdp, portp, A_CLEARSTATS, NULL, 0, 0)) < 0) {
+ mutex_unlock(&portp->port.mutex);
+ return rc;
+@@ -4323,10 +4322,10 @@ static long stli_memioctl(struct file *f
+ rc = stli_startbrd(brdp);
+ break;
+ case STL_BSTOP:
+- brdp->state &= ~BST_STARTED;
++ clear_bit(BST_STARTED, &brdp->state);
+ break;
+ case STL_BRESET:
+- brdp->state &= ~BST_STARTED;
++ clear_bit(BST_STARTED, &brdp->state);
+ EBRDRESET(brdp);
+ if (stli_shared == 0) {
+ if (brdp->reenable != NULL)
+@@ -4382,7 +4381,8 @@ static void istallion_cleanup_isa(void)
+ unsigned int j;
+
+ for (j = 0; (j < stli_nrbrds); j++) {
+- if ((brdp = stli_brds[j]) == NULL || (brdp->state & BST_PROBED))
++ if ((brdp = stli_brds[j]) == NULL ||
++ test_bit(BST_PROBED, &brdp->state))
+ continue;
+
+ stli_cleanup_ports(brdp);
+--- a/include/linux/istallion.h
++++ b/include/linux/istallion.h
+@@ -86,7 +86,7 @@ struct stlibrd {
+ unsigned long magic;
+ unsigned int brdnr;
+ unsigned int brdtype;
+- unsigned int state;
++ unsigned long state;
+ unsigned int nrpanels;
+ unsigned int nrports;
+ unsigned int nrdevs;
diff --git a/tty/riscom8-kill-use-of-lock_kernel.patch b/tty/riscom8-kill-use-of-lock_kernel.patch
new file mode 100644
index 00000000000000..162b4b665ca1d0
--- /dev/null
+++ b/tty/riscom8-kill-use-of-lock_kernel.patch
@@ -0,0 +1,93 @@
+From arnd@arndb.de Tue Jun 15 16:43:54 2010
+From: Alan Cox <alan@linux.intel.com>
+Date: Tue, 1 Jun 2010 22:52:43 +0200
+Subject: riscom8: kill use of lock_kernel
+To: Greg KH <gregkh@suse.de>
+Cc: linux-kernel@vger.kernel.org, Arnd Bergmann <arnd@arndb.de>, Alan Cox <alan@lxorguk.ukuu.org.uk>, Frederic Weisbecker <fweisbec@gmail.com>, John Kacur <jkacur@redhat.com>, Alan Cox <alan@linux.intel.com>
+Message-ID: <1275425591-8803-4-git-send-email-arnd@arndb.de>
+
+
+From: Alan Cox <alan@linux.intel.com>
+
+The riscom8 board uses lock_kernel to protect bits of the port setting
+ioctl logic. We can use the port mutex for this as the logic is internal
+and will also lock set versus open (a locking property that has been lost
+somewhere along the way)
+
+Signed-off-by: Alan Cox <alan@linux.intel.com>
+Cc: Arnd Bergmann <arnd@arndb.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/char/riscom8.c | 14 ++++++++------
+ 1 file changed, 8 insertions(+), 6 deletions(-)
+
+--- a/drivers/char/riscom8.c
++++ b/drivers/char/riscom8.c
+@@ -47,7 +47,6 @@
+ #include <linux/init.h>
+ #include <linux/delay.h>
+ #include <linux/tty_flip.h>
+-#include <linux/smp_lock.h>
+ #include <linux/spinlock.h>
+ #include <linux/device.h>
+
+@@ -1184,6 +1183,7 @@ static int rc_set_serial_info(struct tty
+ if (copy_from_user(&tmp, newinfo, sizeof(tmp)))
+ return -EFAULT;
+
++ mutex_lock(&port->port.mutex);
+ change_speed = ((port->port.flags & ASYNC_SPD_MASK) !=
+ (tmp.flags & ASYNC_SPD_MASK));
+
+@@ -1191,8 +1191,10 @@ static int rc_set_serial_info(struct tty
+ if ((tmp.close_delay != port->port.close_delay) ||
+ (tmp.closing_wait != port->port.closing_wait) ||
+ ((tmp.flags & ~ASYNC_USR_MASK) !=
+- (port->port.flags & ~ASYNC_USR_MASK)))
++ (port->port.flags & ~ASYNC_USR_MASK))) {
++ mutex_unlock(&port->port.mutex);
+ return -EPERM;
++ }
+ port->port.flags = ((port->port.flags & ~ASYNC_USR_MASK) |
+ (tmp.flags & ASYNC_USR_MASK));
+ } else {
+@@ -1208,6 +1210,7 @@ static int rc_set_serial_info(struct tty
+ rc_change_speed(tty, bp, port);
+ spin_unlock_irqrestore(&riscom_lock, flags);
+ }
++ mutex_unlock(&port->port.mutex);
+ return 0;
+ }
+
+@@ -1220,12 +1223,15 @@ static int rc_get_serial_info(struct ris
+ memset(&tmp, 0, sizeof(tmp));
+ tmp.type = PORT_CIRRUS;
+ tmp.line = port - rc_port;
++
++ mutex_lock(&port->port.mutex);
+ tmp.port = bp->base;
+ tmp.irq = bp->irq;
+ tmp.flags = port->port.flags;
+ tmp.baud_base = (RC_OSCFREQ + CD180_TPC/2) / CD180_TPC;
+ tmp.close_delay = port->port.close_delay * HZ/100;
+ tmp.closing_wait = port->port.closing_wait * HZ/100;
++ mutex_unlock(&port->port.mutex);
+ tmp.xmit_fifo_size = CD180_NFIFO;
+ return copy_to_user(retinfo, &tmp, sizeof(tmp)) ? -EFAULT : 0;
+ }
+@@ -1242,14 +1248,10 @@ static int rc_ioctl(struct tty_struct *t
+
+ switch (cmd) {
+ case TIOCGSERIAL:
+- lock_kernel();
+ retval = rc_get_serial_info(port, argp);
+- unlock_kernel();
+ break;
+ case TIOCSSERIAL:
+- lock_kernel();
+ retval = rc_set_serial_info(tty, port, argp);
+- unlock_kernel();
+ break;
+ default:
+ retval = -ENOIOCTLCMD;
diff --git a/tty/rocket-kill-bkl.patch b/tty/rocket-kill-bkl.patch
new file mode 100644
index 00000000000000..22a7659de2e307
--- /dev/null
+++ b/tty/rocket-kill-bkl.patch
@@ -0,0 +1,162 @@
+From arnd@arndb.de Tue Jun 15 16:44:37 2010
+From: Alan Cox <alan@linux.intel.com>
+Date: Tue, 1 Jun 2010 22:52:45 +0200
+Subject: rocket: kill BKL
+To: Greg KH <gregkh@suse.de>
+Cc: linux-kernel@vger.kernel.org, Arnd Bergmann <arnd@arndb.de>, Alan Cox <alan@lxorguk.ukuu.org.uk>, Frederic Weisbecker <fweisbec@gmail.com>, John Kacur <jkacur@redhat.com>, Alan Cox <alan@linux.intel.com>
+Message-ID: <1275425591-8803-6-git-send-email-arnd@arndb.de>
+
+
+From: Alan Cox <alan@linux.intel.com>
+
+We can use the port mutex for this and also for the hangup path so removing
+the problematic use of the hangup mutex in this driver. Fix up the locking
+on the various port flags while we are at it.
+
+Ultimately this driver needs to be using tty_port_ helpers which would sort
+this out far better.
+
+Signed-off-by: Alan Cox <alan@linux.intel.com>
+Cc: Arnd Bergmann <arnd@arndb.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/char/rocket.c | 28 +++++++++++++++++++---------
+ 1 file changed, 19 insertions(+), 9 deletions(-)
+
+--- a/drivers/char/rocket.c
++++ b/drivers/char/rocket.c
+@@ -73,7 +73,6 @@
+ #include <linux/tty_driver.h>
+ #include <linux/tty_flip.h>
+ #include <linux/serial.h>
+-#include <linux/smp_lock.h>
+ #include <linux/string.h>
+ #include <linux/fcntl.h>
+ #include <linux/ptrace.h>
+@@ -1017,6 +1016,7 @@ static void rp_close(struct tty_struct *
+ if (tty_port_close_start(port, tty, filp) == 0)
+ return;
+
++ mutex_lock(&port->mutex);
+ cp = &info->channel;
+ /*
+ * Before we drop DTR, make sure the UART transmitter
+@@ -1060,9 +1060,13 @@ static void rp_close(struct tty_struct *
+ info->xmit_buf = NULL;
+ }
+ }
++ spin_lock_irq(&port->lock);
+ info->port.flags &= ~(ASYNC_INITIALIZED | ASYNC_CLOSING | ASYNC_NORMAL_ACTIVE);
+ tty->closing = 0;
++ spin_unlock_irq(&port->lock);
++ mutex_unlock(&port->mutex);
+ tty_port_tty_set(port, NULL);
++
+ wake_up_interruptible(&port->close_wait);
+ complete_all(&info->close_wait);
+ atomic_dec(&rp_num_ports_open);
+@@ -1210,11 +1214,13 @@ static int get_config(struct r_port *inf
+ if (!retinfo)
+ return -EFAULT;
+ memset(&tmp, 0, sizeof (tmp));
++ mutex_lock(&info->port.mutex);
+ tmp.line = info->line;
+ tmp.flags = info->flags;
+ tmp.close_delay = info->port.close_delay;
+ tmp.closing_wait = info->port.closing_wait;
+ tmp.port = rcktpt_io_addr[(info->line >> 5) & 3];
++ mutex_unlock(&info->port.mutex);
+
+ if (copy_to_user(retinfo, &tmp, sizeof (*retinfo)))
+ return -EFAULT;
+@@ -1229,10 +1235,13 @@ static int set_config(struct tty_struct
+ if (copy_from_user(&new_serial, new_info, sizeof (new_serial)))
+ return -EFAULT;
+
++ mutex_lock(&info->port.mutex);
+ if (!capable(CAP_SYS_ADMIN))
+ {
+- if ((new_serial.flags & ~ROCKET_USR_MASK) != (info->flags & ~ROCKET_USR_MASK))
++ if ((new_serial.flags & ~ROCKET_USR_MASK) != (info->flags & ~ROCKET_USR_MASK)) {
++ mutex_unlock(&info->port.mutex);
+ return -EPERM;
++ }
+ info->flags = ((info->flags & ~ROCKET_USR_MASK) | (new_serial.flags & ROCKET_USR_MASK));
+ configure_r_port(tty, info, NULL);
+ return 0;
+@@ -1250,6 +1259,7 @@ static int set_config(struct tty_struct
+ tty->alt_speed = 230400;
+ if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_WARP)
+ tty->alt_speed = 460800;
++ mutex_unlock(&info->port.mutex);
+
+ configure_r_port(tty, info, NULL);
+ return 0;
+@@ -1325,8 +1335,6 @@ static int rp_ioctl(struct tty_struct *t
+ if (cmd != RCKP_GET_PORTS && rocket_paranoia_check(info, "rp_ioctl"))
+ return -ENXIO;
+
+- lock_kernel();
+-
+ switch (cmd) {
+ case RCKP_GET_STRUCT:
+ if (copy_to_user(argp, info, sizeof (struct r_port)))
+@@ -1350,7 +1358,6 @@ static int rp_ioctl(struct tty_struct *t
+ default:
+ ret = -ENOIOCTLCMD;
+ }
+- unlock_kernel();
+ return ret;
+ }
+
+@@ -1471,7 +1478,6 @@ static void rp_wait_until_sent(struct tt
+ jiffies);
+ printk(KERN_INFO "cps=%d...\n", info->cps);
+ #endif
+- lock_kernel();
+ while (1) {
+ txcnt = sGetTxCnt(cp);
+ if (!txcnt) {
+@@ -1499,7 +1505,6 @@ static void rp_wait_until_sent(struct tt
+ break;
+ }
+ __set_current_state(TASK_RUNNING);
+- unlock_kernel();
+ #ifdef ROCKET_DEBUG_WAIT_UNTIL_SENT
+ printk(KERN_INFO "txcnt = %d (jiff=%lu)...done\n", txcnt, jiffies);
+ #endif
+@@ -1512,6 +1517,7 @@ static void rp_hangup(struct tty_struct
+ {
+ CHANNEL_t *cp;
+ struct r_port *info = tty->driver_data;
++ unsigned long flags;
+
+ if (rocket_paranoia_check(info, "rp_hangup"))
+ return;
+@@ -1520,11 +1526,15 @@ static void rp_hangup(struct tty_struct
+ printk(KERN_INFO "rp_hangup of ttyR%d...\n", info->line);
+ #endif
+ rp_flush_buffer(tty);
+- if (info->port.flags & ASYNC_CLOSING)
++ spin_lock_irqsave(&info->port.lock, flags);
++ if (info->port.flags & ASYNC_CLOSING) {
++ spin_unlock_irqrestore(&info->port.lock, flags);
+ return;
++ }
+ if (info->port.count)
+ atomic_dec(&rp_num_ports_open);
+ clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]);
++ spin_unlock_irqrestore(&info->port.lock, flags);
+
+ tty_port_hangup(&info->port);
+
+@@ -1535,7 +1545,7 @@ static void rp_hangup(struct tty_struct
+ sDisCTSFlowCtl(cp);
+ sDisTxSoftFlowCtl(cp);
+ sClrTxXOFF(cp);
+- info->port.flags &= ~ASYNC_INITIALIZED;
++ clear_bit(ASYNCB_INITIALIZED, &info->port.flags);
+
+ wake_up_interruptible(&info->port.open_wait);
+ }
diff --git a/tty/specialix-kill-the-bkl.patch b/tty/specialix-kill-the-bkl.patch
new file mode 100644
index 00000000000000..a848fbe545a72c
--- /dev/null
+++ b/tty/specialix-kill-the-bkl.patch
@@ -0,0 +1,68 @@
+From arnd@arndb.de Tue Jun 15 16:46:14 2010
+From: Alan Cox <alan@linux.intel.com>
+Date: Tue, 1 Jun 2010 22:52:49 +0200
+Subject: specialix: Kill the BKL
+To: Greg KH <gregkh@suse.de>
+Cc: linux-kernel@vger.kernel.org, Arnd Bergmann <arnd@arndb.de>, Alan Cox <alan@lxorguk.ukuu.org.uk>, Frederic Weisbecker <fweisbec@gmail.com>, John Kacur <jkacur@redhat.com>, Alan Cox <alan@linux.intel.com>
+Message-ID: <1275425591-8803-10-git-send-email-arnd@arndb.de>
+
+
+From: Alan Cox <alan@linux.intel.com>
+
+Use the port mutex instead
+
+Signed-off-by: Alan Cox <alan@linux.intel.com>
+Cc: Arnd Bergmann <arnd@arndb.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ drivers/char/specialix.c | 11 +++++------
+ 1 file changed, 5 insertions(+), 6 deletions(-)
+
+--- a/drivers/char/specialix.c
++++ b/drivers/char/specialix.c
+@@ -1863,8 +1863,7 @@ static int sx_set_serial_info(struct spe
+ return -EFAULT;
+ }
+
+- lock_kernel();
+-
++ mutex_lock(&port->port.mutex);
+ change_speed = ((port->port.flags & ASYNC_SPD_MASK) !=
+ (tmp.flags & ASYNC_SPD_MASK));
+ change_speed |= (tmp.custom_divisor != port->custom_divisor);
+@@ -1875,7 +1874,7 @@ static int sx_set_serial_info(struct spe
+ ((tmp.flags & ~ASYNC_USR_MASK) !=
+ (port->port.flags & ~ASYNC_USR_MASK))) {
+ func_exit();
+- unlock_kernel();
++ mutex_unlock(&port->port.mutex);
+ return -EPERM;
+ }
+ port->port.flags = ((port->port.flags & ~ASYNC_USR_MASK) |
+@@ -1892,7 +1891,7 @@ static int sx_set_serial_info(struct spe
+ sx_change_speed(bp, port);
+
+ func_exit();
+- unlock_kernel();
++ mutex_unlock(&port->port.mutex);
+ return 0;
+ }
+
+@@ -1906,7 +1905,7 @@ static int sx_get_serial_info(struct spe
+ func_enter();
+
+ memset(&tmp, 0, sizeof(tmp));
+- lock_kernel();
++ mutex_lock(&port->port.mutex);
+ tmp.type = PORT_CIRRUS;
+ tmp.line = port - sx_port;
+ tmp.port = bp->base;
+@@ -1917,7 +1916,7 @@ static int sx_get_serial_info(struct spe
+ tmp.closing_wait = port->port.closing_wait * HZ/100;
+ tmp.custom_divisor = port->custom_divisor;
+ tmp.xmit_fifo_size = CD186x_NFIFO;
+- unlock_kernel();
++ mutex_unlock(&port->port.mutex);
+ if (copy_to_user(retinfo, &tmp, sizeof(tmp))) {
+ func_exit();
+ return -EFAULT;
diff --git a/tty/stallion-prune-lock_kernel-calls.patch b/tty/stallion-prune-lock_kernel-calls.patch
new file mode 100644
index 00000000000000..93e5cf4fee77ca
--- /dev/null
+++ b/tty/stallion-prune-lock_kernel-calls.patch
@@ -0,0 +1,244 @@
+From arnd@arndb.de Tue Jun 15 16:42:44 2010
+Date: Tue, 1 Jun 2010 22:52:41 +0200
+From: Alan Cox <alan@linux.intel.com>
+Subject: stallion: prune lock_kernel calls
+To: Greg KH <gregkh@suse.de>
+Cc: linux-kernel@vger.kernel.org, Arnd Bergmann <arnd@arndb.de>, Alan Cox <alan@lxorguk.ukuu.org.uk>, Frederic Weisbecker <fweisbec@gmail.com>, John Kacur <jkacur@redhat.com>, Alan Cox <alan@linux.intel.com>
+Message-ID: <1275425591-8803-2-git-send-email-arnd@arndb.de>
+
+
+From: Alan Cox <alan@linux.intel.com>
+
+Remove unneeded tty layer lock kernel bits. Relock the needed bits using the
+port mutex. The istallion still has brd state races but those are not new
+or introduced by the removal of the lock_kernel logic.
+
+Signed-off-by: Alan Cox <alan@linux.intel.com>
+Cc: Arnd Bergmann <arnd@arndb.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/char/istallion.c | 22 +++++++++++++---------
+ drivers/char/stallion.c | 20 ++++++++++++--------
+ 2 files changed, 25 insertions(+), 17 deletions(-)
+
+--- a/drivers/char/istallion.c
++++ b/drivers/char/istallion.c
+@@ -14,6 +14,7 @@
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
++ * FIXME: brdp->state needs proper locking.
+ */
+
+ /*****************************************************************************/
+@@ -4011,6 +4012,7 @@ static int stli_getbrdstats(combrd_t __u
+ return -ENODEV;
+
+ memset(&stli_brdstats, 0, sizeof(combrd_t));
++
+ stli_brdstats.brd = brdp->brdnr;
+ stli_brdstats.type = brdp->brdtype;
+ stli_brdstats.hwid = 0;
+@@ -4076,10 +4078,13 @@ static int stli_portcmdstats(struct tty_
+ if (brdp == NULL)
+ return -ENODEV;
+
++ mutex_lock(&portp->port.mutex);
+ if (brdp->state & BST_STARTED) {
+ if ((rc = stli_cmdwait(brdp, portp, A_GETSTATS,
+- &stli_cdkstats, sizeof(asystats_t), 1)) < 0)
++ &stli_cdkstats, sizeof(asystats_t), 1)) < 0) {
++ mutex_unlock(&portp->port.mutex);
+ return rc;
++ }
+ } else {
+ memset(&stli_cdkstats, 0, sizeof(asystats_t));
+ }
+@@ -4124,6 +4129,7 @@ static int stli_portcmdstats(struct tty_
+ stli_comstats.modem = stli_cdkstats.dcdcnt;
+ stli_comstats.hwid = stli_cdkstats.hwid;
+ stli_comstats.signals = stli_mktiocm(stli_cdkstats.signals);
++ mutex_unlock(&portp->port.mutex);
+
+ return 0;
+ }
+@@ -4186,15 +4192,20 @@ static int stli_clrportstats(struct stli
+ if (!brdp)
+ return -ENODEV;
+
++ mutex_lock(&portp->port.mutex);
++
+ if (brdp->state & BST_STARTED) {
+- if ((rc = stli_cmdwait(brdp, portp, A_CLEARSTATS, NULL, 0, 0)) < 0)
++ if ((rc = stli_cmdwait(brdp, portp, A_CLEARSTATS, NULL, 0, 0)) < 0) {
++ mutex_unlock(&portp->port.mutex);
+ return rc;
++ }
+ }
+
+ memset(&stli_comstats, 0, sizeof(comstats_t));
+ stli_comstats.brd = portp->brdnr;
+ stli_comstats.panel = portp->panelnr;
+ stli_comstats.port = portp->portnr;
++ mutex_unlock(&portp->port.mutex);
+
+ if (copy_to_user(cp, &stli_comstats, sizeof(comstats_t)))
+ return -EFAULT;
+@@ -4266,8 +4277,6 @@ static long stli_memioctl(struct file *f
+ done = 0;
+ rc = 0;
+
+- lock_kernel();
+-
+ switch (cmd) {
+ case COM_GETPORTSTATS:
+ rc = stli_getportstats(NULL, NULL, argp);
+@@ -4290,8 +4299,6 @@ static long stli_memioctl(struct file *f
+ done++;
+ break;
+ }
+- unlock_kernel();
+-
+ if (done)
+ return rc;
+
+@@ -4308,8 +4315,6 @@ static long stli_memioctl(struct file *f
+ if (brdp->state == 0)
+ return -ENODEV;
+
+- lock_kernel();
+-
+ switch (cmd) {
+ case STL_BINTR:
+ EBRDINTR(brdp);
+@@ -4332,7 +4337,6 @@ static long stli_memioctl(struct file *f
+ rc = -ENOIOCTLCMD;
+ break;
+ }
+- unlock_kernel();
+ return rc;
+ }
+
+--- a/drivers/char/stallion.c
++++ b/drivers/char/stallion.c
+@@ -807,7 +807,6 @@ static void stl_waituntilsent(struct tty
+ timeout = HZ;
+ tend = jiffies + timeout;
+
+- lock_kernel();
+ while (stl_datastate(portp)) {
+ if (signal_pending(current))
+ break;
+@@ -815,7 +814,6 @@ static void stl_waituntilsent(struct tty
+ if (time_after_eq(jiffies, tend))
+ break;
+ }
+- unlock_kernel();
+ }
+
+ /*****************************************************************************/
+@@ -1029,6 +1027,8 @@ static int stl_getserial(struct stlport
+ pr_debug("stl_getserial(portp=%p,sp=%p)\n", portp, sp);
+
+ memset(&sio, 0, sizeof(struct serial_struct));
++
++ mutex_lock(&portp->port.mutex);
+ sio.line = portp->portnr;
+ sio.port = portp->ioaddr;
+ sio.flags = portp->port.flags;
+@@ -1048,6 +1048,7 @@ static int stl_getserial(struct stlport
+ brdp = stl_brds[portp->brdnr];
+ if (brdp != NULL)
+ sio.irq = brdp->irq;
++ mutex_unlock(&portp->port.mutex);
+
+ return copy_to_user(sp, &sio, sizeof(struct serial_struct)) ? -EFAULT : 0;
+ }
+@@ -1069,12 +1070,15 @@ static int stl_setserial(struct tty_stru
+
+ if (copy_from_user(&sio, sp, sizeof(struct serial_struct)))
+ return -EFAULT;
++ mutex_lock(&portp->port.mutex);
+ if (!capable(CAP_SYS_ADMIN)) {
+ if ((sio.baud_base != portp->baud_base) ||
+ (sio.close_delay != portp->close_delay) ||
+ ((sio.flags & ~ASYNC_USR_MASK) !=
+- (portp->port.flags & ~ASYNC_USR_MASK)))
++ (portp->port.flags & ~ASYNC_USR_MASK))) {
++ mutex_unlock(&portp->port.mutex);
+ return -EPERM;
++ }
+ }
+
+ portp->port.flags = (portp->port.flags & ~ASYNC_USR_MASK) |
+@@ -1083,6 +1087,7 @@ static int stl_setserial(struct tty_stru
+ portp->close_delay = sio.close_delay;
+ portp->closing_wait = sio.closing_wait;
+ portp->custom_divisor = sio.custom_divisor;
++ mutex_unlock(&portp->port.mutex);
+ stl_setport(portp, tty->termios);
+ return 0;
+ }
+@@ -1147,8 +1152,6 @@ static int stl_ioctl(struct tty_struct *
+
+ rc = 0;
+
+- lock_kernel();
+-
+ switch (cmd) {
+ case TIOCGSERIAL:
+ rc = stl_getserial(portp, argp);
+@@ -1173,7 +1176,6 @@ static int stl_ioctl(struct tty_struct *
+ rc = -ENOIOCTLCMD;
+ break;
+ }
+- unlock_kernel();
+ return rc;
+ }
+
+@@ -2327,6 +2329,7 @@ static int stl_getportstats(struct tty_s
+ return -ENODEV;
+ }
+
++ mutex_lock(&portp->port.mutex);
+ portp->stats.state = portp->istate;
+ portp->stats.flags = portp->port.flags;
+ portp->stats.hwid = portp->hwid;
+@@ -2358,6 +2361,7 @@ static int stl_getportstats(struct tty_s
+ (STL_TXBUFSIZE - (tail - head));
+
+ portp->stats.signals = (unsigned long) stl_getsignals(portp);
++ mutex_unlock(&portp->port.mutex);
+
+ return copy_to_user(cp, &portp->stats,
+ sizeof(comstats_t)) ? -EFAULT : 0;
+@@ -2382,10 +2386,12 @@ static int stl_clrportstats(struct stlpo
+ return -ENODEV;
+ }
+
++ mutex_lock(&portp->port.mutex);
+ memset(&portp->stats, 0, sizeof(comstats_t));
+ portp->stats.brd = portp->brdnr;
+ portp->stats.panel = portp->panelnr;
+ portp->stats.port = portp->portnr;
++ mutex_unlock(&portp->port.mutex);
+ return copy_to_user(cp, &portp->stats,
+ sizeof(comstats_t)) ? -EFAULT : 0;
+ }
+@@ -2451,7 +2457,6 @@ static long stl_memioctl(struct file *fp
+ return -ENODEV;
+ rc = 0;
+
+- lock_kernel();
+ switch (cmd) {
+ case COM_GETPORTSTATS:
+ rc = stl_getportstats(NULL, NULL, argp);
+@@ -2472,7 +2477,6 @@ static long stl_memioctl(struct file *fp
+ rc = -ENOIOCTLCMD;
+ break;
+ }
+- unlock_kernel();
+ return rc;
+ }
+
diff --git a/tty/synclink-kill-the-big-kernel-lock.patch b/tty/synclink-kill-the-big-kernel-lock.patch
new file mode 100644
index 00000000000000..4a6877e76f58a6
--- /dev/null
+++ b/tty/synclink-kill-the-big-kernel-lock.patch
@@ -0,0 +1,370 @@
+From arnd@arndb.de Tue Jun 15 16:45:03 2010
+From: Alan Cox <alan@linux.intel.com>
+Date: Tue, 1 Jun 2010 22:52:46 +0200
+Subject: synclink: kill the big kernel lock
+To: Greg KH <gregkh@suse.de>
+Cc: linux-kernel@vger.kernel.org, Arnd Bergmann <arnd@arndb.de>, Alan Cox <alan@lxorguk.ukuu.org.uk>, Frederic Weisbecker <fweisbec@gmail.com>, John Kacur <jkacur@redhat.com>, Alan Cox <alan@linux.intel.com>
+Message-ID: <1275425591-8803-7-git-send-email-arnd@arndb.de>
+
+
+From: Alan Cox <alan@linux.intel.com>
+
+We don't need it while waiting and we can lock the ioctls using the port
+mutex. While at it eliminate use of the hangup mutex and switch to the port
+mutex.
+
+Signed-off-by: Alan Cox <alan@linux.intel.com>
+Cc: Arnd Bergmann <arnd@arndb.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/char/synclink.c | 19 +++++-----
+ drivers/char/synclink_gt.c | 78 +++++++++++++++++++--------------------------
+ drivers/char/synclinkmp.c | 32 ++++++------------
+ 3 files changed, 56 insertions(+), 73 deletions(-)
+
+--- a/drivers/char/synclink.c
++++ b/drivers/char/synclink.c
+@@ -81,7 +81,6 @@
+ #include <linux/mm.h>
+ #include <linux/seq_file.h>
+ #include <linux/slab.h>
+-#include <linux/smp_lock.h>
+ #include <linux/delay.h>
+ #include <linux/netdevice.h>
+ #include <linux/vmalloc.h>
+@@ -2436,7 +2435,9 @@ static int mgsl_get_stats(struct mgsl_st
+ if (!user_icount) {
+ memset(&info->icount, 0, sizeof(info->icount));
+ } else {
++ mutex_lock(&info->port.mutex);
+ COPY_TO_USER(err, user_icount, &info->icount, sizeof(struct mgsl_icount));
++ mutex_unlock(&info->port.mutex);
+ if (err)
+ return -EFAULT;
+ }
+@@ -2461,7 +2462,9 @@ static int mgsl_get_params(struct mgsl_s
+ printk("%s(%d):mgsl_get_params(%s)\n",
+ __FILE__,__LINE__, info->device_name);
+
++ mutex_lock(&info->port.mutex);
+ COPY_TO_USER(err,user_params, &info->params, sizeof(MGSL_PARAMS));
++ mutex_unlock(&info->port.mutex);
+ if (err) {
+ if ( debug_level >= DEBUG_LEVEL_INFO )
+ printk( "%s(%d):mgsl_get_params(%s) user buffer copy failed\n",
+@@ -2501,11 +2504,13 @@ static int mgsl_set_params(struct mgsl_s
+ return -EFAULT;
+ }
+
++ mutex_lock(&info->port.mutex);
+ spin_lock_irqsave(&info->irq_spinlock,flags);
+ memcpy(&info->params,&tmp_params,sizeof(MGSL_PARAMS));
+ spin_unlock_irqrestore(&info->irq_spinlock,flags);
+
+ mgsl_change_params(info);
++ mutex_unlock(&info->port.mutex);
+
+ return 0;
+
+@@ -2935,7 +2940,6 @@ static int mgsl_ioctl(struct tty_struct
+ unsigned int cmd, unsigned long arg)
+ {
+ struct mgsl_struct * info = tty->driver_data;
+- int ret;
+
+ if (debug_level >= DEBUG_LEVEL_INFO)
+ printk("%s(%d):mgsl_ioctl %s cmd=%08X\n", __FILE__,__LINE__,
+@@ -2950,10 +2954,7 @@ static int mgsl_ioctl(struct tty_struct
+ return -EIO;
+ }
+
+- lock_kernel();
+- ret = mgsl_ioctl_common(info, cmd, arg);
+- unlock_kernel();
+- return ret;
++ return mgsl_ioctl_common(info, cmd, arg);
+ }
+
+ static int mgsl_ioctl_common(struct mgsl_struct *info, unsigned int cmd, unsigned long arg)
+@@ -3109,12 +3110,14 @@ static void mgsl_close(struct tty_struct
+
+ if (tty_port_close_start(&info->port, tty, filp) == 0)
+ goto cleanup;
+-
++
++ mutex_lock(&info->port.mutex);
+ if (info->port.flags & ASYNC_INITIALIZED)
+ mgsl_wait_until_sent(tty, info->timeout);
+ mgsl_flush_buffer(tty);
+ tty_ldisc_flush(tty);
+ shutdown(info);
++ mutex_unlock(&info->port.mutex);
+
+ tty_port_close_end(&info->port, tty);
+ info->port.tty = NULL;
+@@ -3162,7 +3165,6 @@ static void mgsl_wait_until_sent(struct
+ * Note: use tight timings here to satisfy the NIST-PCTS.
+ */
+
+- lock_kernel();
+ if ( info->params.data_rate ) {
+ char_time = info->timeout/(32 * 5);
+ if (!char_time)
+@@ -3192,7 +3194,6 @@ static void mgsl_wait_until_sent(struct
+ break;
+ }
+ }
+- unlock_kernel();
+
+ exit:
+ if (debug_level >= DEBUG_LEVEL_INFO)
+--- a/drivers/char/synclink_gt.c
++++ b/drivers/char/synclink_gt.c
+@@ -40,8 +40,8 @@
+ #define DBGBH(fmt) if (debug_level >= DEBUG_LEVEL_BH) printk fmt
+ #define DBGISR(fmt) if (debug_level >= DEBUG_LEVEL_ISR) printk fmt
+ #define DBGDATA(info, buf, size, label) if (debug_level >= DEBUG_LEVEL_DATA) trace_block((info), (buf), (size), (label))
+-//#define DBGTBUF(info) dump_tbufs(info)
+-//#define DBGRBUF(info) dump_rbufs(info)
++/*#define DBGTBUF(info) dump_tbufs(info)*/
++/*#define DBGRBUF(info) dump_rbufs(info)*/
+
+
+ #include <linux/module.h>
+@@ -62,7 +62,6 @@
+ #include <linux/mm.h>
+ #include <linux/seq_file.h>
+ #include <linux/slab.h>
+-#include <linux/smp_lock.h>
+ #include <linux/netdevice.h>
+ #include <linux/vmalloc.h>
+ #include <linux/init.h>
+@@ -901,8 +900,6 @@ static void wait_until_sent(struct tty_s
+ * Note: use tight timings here to satisfy the NIST-PCTS.
+ */
+
+- lock_kernel();
+-
+ if (info->params.data_rate) {
+ char_time = info->timeout/(32 * 5);
+ if (!char_time)
+@@ -920,8 +917,6 @@ static void wait_until_sent(struct tty_s
+ if (timeout && time_after(jiffies, orig_jiffies + timeout))
+ break;
+ }
+- unlock_kernel();
+-
+ exit:
+ DBGINFO(("%s wait_until_sent exit\n", info->device_name));
+ }
+@@ -1041,8 +1036,37 @@ static int ioctl(struct tty_struct *tty,
+ return -EIO;
+ }
+
+- lock_kernel();
+-
++ switch (cmd) {
++ case MGSL_IOCWAITEVENT:
++ return wait_mgsl_event(info, argp);
++ case TIOCMIWAIT:
++ return modem_input_wait(info,(int)arg);
++ case TIOCGICOUNT:
++ spin_lock_irqsave(&info->lock,flags);
++ cnow = info->icount;
++ spin_unlock_irqrestore(&info->lock,flags);
++ p_cuser = argp;
++ if (put_user(cnow.cts, &p_cuser->cts) ||
++ put_user(cnow.dsr, &p_cuser->dsr) ||
++ put_user(cnow.rng, &p_cuser->rng) ||
++ put_user(cnow.dcd, &p_cuser->dcd) ||
++ put_user(cnow.rx, &p_cuser->rx) ||
++ put_user(cnow.tx, &p_cuser->tx) ||
++ put_user(cnow.frame, &p_cuser->frame) ||
++ put_user(cnow.overrun, &p_cuser->overrun) ||
++ put_user(cnow.parity, &p_cuser->parity) ||
++ put_user(cnow.brk, &p_cuser->brk) ||
++ put_user(cnow.buf_overrun, &p_cuser->buf_overrun))
++ return -EFAULT;
++ return 0;
++ case MGSL_IOCSGPIO:
++ return set_gpio(info, argp);
++ case MGSL_IOCGGPIO:
++ return get_gpio(info, argp);
++ case MGSL_IOCWAITGPIO:
++ return wait_gpio(info, argp);
++ }
++ mutex_lock(&info->port.mutex);
+ switch (cmd) {
+ case MGSL_IOCGPARAMS:
+ ret = get_params(info, argp);
+@@ -1068,50 +1092,16 @@ static int ioctl(struct tty_struct *tty,
+ case MGSL_IOCGSTATS:
+ ret = get_stats(info, argp);
+ break;
+- case MGSL_IOCWAITEVENT:
+- ret = wait_mgsl_event(info, argp);
+- break;
+- case TIOCMIWAIT:
+- ret = modem_input_wait(info,(int)arg);
+- break;
+ case MGSL_IOCGIF:
+ ret = get_interface(info, argp);
+ break;
+ case MGSL_IOCSIF:
+ ret = set_interface(info,(int)arg);
+ break;
+- case MGSL_IOCSGPIO:
+- ret = set_gpio(info, argp);
+- break;
+- case MGSL_IOCGGPIO:
+- ret = get_gpio(info, argp);
+- break;
+- case MGSL_IOCWAITGPIO:
+- ret = wait_gpio(info, argp);
+- break;
+- case TIOCGICOUNT:
+- spin_lock_irqsave(&info->lock,flags);
+- cnow = info->icount;
+- spin_unlock_irqrestore(&info->lock,flags);
+- p_cuser = argp;
+- if (put_user(cnow.cts, &p_cuser->cts) ||
+- put_user(cnow.dsr, &p_cuser->dsr) ||
+- put_user(cnow.rng, &p_cuser->rng) ||
+- put_user(cnow.dcd, &p_cuser->dcd) ||
+- put_user(cnow.rx, &p_cuser->rx) ||
+- put_user(cnow.tx, &p_cuser->tx) ||
+- put_user(cnow.frame, &p_cuser->frame) ||
+- put_user(cnow.overrun, &p_cuser->overrun) ||
+- put_user(cnow.parity, &p_cuser->parity) ||
+- put_user(cnow.brk, &p_cuser->brk) ||
+- put_user(cnow.buf_overrun, &p_cuser->buf_overrun))
+- ret = -EFAULT;
+- ret = 0;
+- break;
+ default:
+ ret = -ENOIOCTLCMD;
+ }
+- unlock_kernel();
++ mutex_unlock(&info->port.mutex);
+ return ret;
+ }
+
+--- a/drivers/char/synclinkmp.c
++++ b/drivers/char/synclinkmp.c
+@@ -52,7 +52,6 @@
+ #include <linux/mm.h>
+ #include <linux/seq_file.h>
+ #include <linux/slab.h>
+-#include <linux/smp_lock.h>
+ #include <linux/netdevice.h>
+ #include <linux/vmalloc.h>
+ #include <linux/init.h>
+@@ -1062,9 +1061,7 @@ static void wait_until_sent(struct tty_s
+ if (sanity_check(info, tty->name, "wait_until_sent"))
+ return;
+
+- lock_kernel();
+-
+- if (!(info->port.flags & ASYNC_INITIALIZED))
++ if (!test_bit(ASYNCB_INITIALIZED, &info->port.flags))
+ goto exit;
+
+ orig_jiffies = jiffies;
+@@ -1094,8 +1091,10 @@ static void wait_until_sent(struct tty_s
+ break;
+ }
+ } else {
+- //TODO: determine if there is something similar to USC16C32
+- // TXSTATUS_ALL_SENT status
++ /*
++ * TODO: determine if there is something similar to USC16C32
++ * TXSTATUS_ALL_SENT status
++ */
+ while ( info->tx_active && info->tx_enabled) {
+ msleep_interruptible(jiffies_to_msecs(char_time));
+ if (signal_pending(current))
+@@ -1106,7 +1105,6 @@ static void wait_until_sent(struct tty_s
+ }
+
+ exit:
+- unlock_kernel();
+ if (debug_level >= DEBUG_LEVEL_INFO)
+ printk("%s(%d):%s wait_until_sent() exit\n",
+ __FILE__,__LINE__, info->device_name );
+@@ -1122,7 +1120,6 @@ static int write_room(struct tty_struct
+ if (sanity_check(info, tty->name, "write_room"))
+ return 0;
+
+- lock_kernel();
+ if (info->params.mode == MGSL_MODE_HDLC) {
+ ret = (info->tx_active) ? 0 : HDLC_MAX_FRAME_SIZE;
+ } else {
+@@ -1130,7 +1127,6 @@ static int write_room(struct tty_struct
+ if (ret < 0)
+ ret = 0;
+ }
+- unlock_kernel();
+
+ if (debug_level >= DEBUG_LEVEL_INFO)
+ printk("%s(%d):%s write_room()=%d\n",
+@@ -1251,7 +1247,7 @@ static void tx_release(struct tty_struct
+ *
+ * Return Value: 0 if success, otherwise error code
+ */
+-static int do_ioctl(struct tty_struct *tty, struct file *file,
++static int ioctl(struct tty_struct *tty, struct file *file,
+ unsigned int cmd, unsigned long arg)
+ {
+ SLMP_INFO *info = tty->driver_data;
+@@ -1341,16 +1337,6 @@ static int do_ioctl(struct tty_struct *t
+ return 0;
+ }
+
+-static int ioctl(struct tty_struct *tty, struct file *file,
+- unsigned int cmd, unsigned long arg)
+-{
+- int ret;
+- lock_kernel();
+- ret = do_ioctl(tty, file, cmd, arg);
+- unlock_kernel();
+- return ret;
+-}
+-
+ /*
+ * /proc fs routines....
+ */
+@@ -2883,7 +2869,9 @@ static int get_stats(SLMP_INFO * info, s
+ if (!user_icount) {
+ memset(&info->icount, 0, sizeof(info->icount));
+ } else {
++ mutex_lock(&info->port.mutex);
+ COPY_TO_USER(err, user_icount, &info->icount, sizeof(struct mgsl_icount));
++ mutex_unlock(&info->port.mutex);
+ if (err)
+ return -EFAULT;
+ }
+@@ -2898,7 +2886,9 @@ static int get_params(SLMP_INFO * info,
+ printk("%s(%d):%s get_params()\n",
+ __FILE__,__LINE__, info->device_name);
+
++ mutex_lock(&info->port.mutex);
+ COPY_TO_USER(err,user_params, &info->params, sizeof(MGSL_PARAMS));
++ mutex_unlock(&info->port.mutex);
+ if (err) {
+ if ( debug_level >= DEBUG_LEVEL_INFO )
+ printk( "%s(%d):%s get_params() user buffer copy failed\n",
+@@ -2926,11 +2916,13 @@ static int set_params(SLMP_INFO * info,
+ return -EFAULT;
+ }
+
++ mutex_lock(&info->port.mutex);
+ spin_lock_irqsave(&info->lock,flags);
+ memcpy(&info->params,&tmp_params,sizeof(MGSL_PARAMS));
+ spin_unlock_irqrestore(&info->lock,flags);
+
+ change_params(info);
++ mutex_unlock(&info->port.mutex);
+
+ return 0;
+ }
diff --git a/tty/synclink-reworking-locking-a-bit.patch b/tty/synclink-reworking-locking-a-bit.patch
new file mode 100644
index 00000000000000..949f67647977ca
--- /dev/null
+++ b/tty/synclink-reworking-locking-a-bit.patch
@@ -0,0 +1,133 @@
+From arnd@arndb.de Tue Jun 15 16:48:45 2010
+From: Alan Cox <alan@linux.intel.com>
+Date: Tue, 1 Jun 2010 22:52:50 +0200
+Subject: synclink: reworking locking a bit
+To: Greg KH <gregkh@suse.de>
+Cc: linux-kernel@vger.kernel.org, Arnd Bergmann <arnd@arndb.de>, Alan Cox <alan@lxorguk.ukuu.org.uk>, Frederic Weisbecker <fweisbec@gmail.com>, John Kacur <jkacur@redhat.com>, Alan Cox <alan@linux.intel.com>
+Message-ID: <1275425591-8803-11-git-send-email-arnd@arndb.de>
+
+
+From: Alan Cox <alan@linux.intel.com>
+
+Use the port mutex and port lock to fix the various races. The locking
+still isn't totally consistent but its better than before. Wants switching
+to the port helpers.
+
+Signed-off-by: Alan Cox <alan@linux.intel.com>
+Cc: Arnd Bergmann <arnd@arndb.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/char/synclink_gt.c | 12 +++++++++++-
+ drivers/char/synclinkmp.c | 9 ++++++++-
+ 2 files changed, 19 insertions(+), 2 deletions(-)
+
+--- a/drivers/char/synclink_gt.c
++++ b/drivers/char/synclink_gt.c
+@@ -675,12 +675,14 @@ static int open(struct tty_struct *tty,
+ goto cleanup;
+ }
+
++ mutex_lock(&info->port.mutex);
+ info->port.tty->low_latency = (info->port.flags & ASYNC_LOW_LATENCY) ? 1 : 0;
+
+ spin_lock_irqsave(&info->netlock, flags);
+ if (info->netcount) {
+ retval = -EBUSY;
+ spin_unlock_irqrestore(&info->netlock, flags);
++ mutex_unlock(&info->port.mutex);
+ goto cleanup;
+ }
+ info->port.count++;
+@@ -692,7 +694,7 @@ static int open(struct tty_struct *tty,
+ if (retval < 0)
+ goto cleanup;
+ }
+-
++ mutex_unlock(&info->port.mutex);
+ retval = block_til_ready(tty, filp, info);
+ if (retval) {
+ DBGINFO(("%s block_til_ready rc=%d\n", info->device_name, retval));
+@@ -724,12 +726,14 @@ static void close(struct tty_struct *tty
+ if (tty_port_close_start(&info->port, tty, filp) == 0)
+ goto cleanup;
+
++ mutex_lock(&info->port.mutex);
+ if (info->port.flags & ASYNC_INITIALIZED)
+ wait_until_sent(tty, info->timeout);
+ flush_buffer(tty);
+ tty_ldisc_flush(tty);
+
+ shutdown(info);
++ mutex_unlock(&info->port.mutex);
+
+ tty_port_close_end(&info->port, tty);
+ info->port.tty = NULL;
+@@ -740,17 +744,23 @@ cleanup:
+ static void hangup(struct tty_struct *tty)
+ {
+ struct slgt_info *info = tty->driver_data;
++ unsigned long flags;
+
+ if (sanity_check(info, tty->name, "hangup"))
+ return;
+ DBGINFO(("%s hangup\n", info->device_name));
+
+ flush_buffer(tty);
++
++ mutex_lock(&info->port.mutex);
+ shutdown(info);
+
++ spin_lock_irqsave(&info->port.lock, flags);
+ info->port.count = 0;
+ info->port.flags &= ~ASYNC_NORMAL_ACTIVE;
+ info->port.tty = NULL;
++ spin_unlock_irqrestore(&info->port.lock, flags);
++ mutex_unlock(&info->port.mutex);
+
+ wake_up_interruptible(&info->port.open_wait);
+ }
+--- a/drivers/char/synclinkmp.c
++++ b/drivers/char/synclinkmp.c
+@@ -812,13 +812,15 @@ static void close(struct tty_struct *tty
+
+ if (tty_port_close_start(&info->port, tty, filp) == 0)
+ goto cleanup;
+-
++
++ mutex_lock(&info->port.mutex);
+ if (info->port.flags & ASYNC_INITIALIZED)
+ wait_until_sent(tty, info->timeout);
+
+ flush_buffer(tty);
+ tty_ldisc_flush(tty);
+ shutdown(info);
++ mutex_unlock(&info->port.mutex);
+
+ tty_port_close_end(&info->port, tty);
+ info->port.tty = NULL;
+@@ -834,6 +836,7 @@ cleanup:
+ static void hangup(struct tty_struct *tty)
+ {
+ SLMP_INFO *info = tty->driver_data;
++ unsigned long flags;
+
+ if (debug_level >= DEBUG_LEVEL_INFO)
+ printk("%s(%d):%s hangup()\n",
+@@ -842,12 +845,16 @@ static void hangup(struct tty_struct *tt
+ if (sanity_check(info, tty->name, "hangup"))
+ return;
+
++ mutex_lock(&info->port.mutex);
+ flush_buffer(tty);
+ shutdown(info);
+
++ spin_lock_irqsave(&info->port.lock, flags);
+ info->port.count = 0;
+ info->port.flags &= ~ASYNC_NORMAL_ACTIVE;
+ info->port.tty = NULL;
++ spin_unlock_irqrestore(&info->port.lock, flags);
++ mutex_unlock(&info->port.mutex);
+
+ wake_up_interruptible(&info->port.open_wait);
+ }
diff --git a/tty/tty-fix-the-digi-acceleport-driver-null-checks.patch b/tty/tty-fix-the-digi-acceleport-driver-null-checks.patch
new file mode 100644
index 00000000000000..3740f952f7fc71
--- /dev/null
+++ b/tty/tty-fix-the-digi-acceleport-driver-null-checks.patch
@@ -0,0 +1,57 @@
+From alan@linux.intel.com Tue Jun 15 16:48:07 2010
+From: Alan Cox <alan@linux.intel.com>
+Date: Wed, 19 May 2010 13:01:56 +0100
+Subject: tty: Fix the digi acceleport driver NULL checks
+To: greg@kroah.com, linux-serial@vger.kernel.org
+Message-ID: <20100519120148.16717.1135.stgit@localhost.localdomain>
+
+
+This now refcounts but doesn't actually check the reference was obtained in
+all the places it should.
+
+Signed-off-by: Alan Cox <alan@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/serial/digi_acceleport.c | 14 +++++++++-----
+ 1 file changed, 9 insertions(+), 5 deletions(-)
+
+--- a/drivers/usb/serial/digi_acceleport.c
++++ b/drivers/usb/serial/digi_acceleport.c
+@@ -609,8 +609,10 @@ static void digi_wakeup_write_lock(struc
+ static void digi_wakeup_write(struct usb_serial_port *port)
+ {
+ struct tty_struct *tty = tty_port_tty_get(&port->port);
+- tty_wakeup(tty);
+- tty_kref_put(tty);
++ if (tty) {
++ tty_wakeup(tty);
++ tty_kref_put(tty);
++ }
+ }
+
+
+@@ -1682,7 +1684,7 @@ static int digi_read_inb_callback(struct
+ priv->dp_throttle_restart = 1;
+
+ /* receive data */
+- if (opcode == DIGI_CMD_RECEIVE_DATA) {
++ if (tty && opcode == DIGI_CMD_RECEIVE_DATA) {
+ /* get flag from port_status */
+ flag = 0;
+
+@@ -1763,10 +1765,12 @@ static int digi_read_oob_callback(struct
+ return -1;
+
+ tty = tty_port_tty_get(&port->port);
++
+ rts = 0;
+- rts = tty->termios->c_cflag & CRTSCTS;
++ if (tty)
++ rts = tty->termios->c_cflag & CRTSCTS;
+
+- if (opcode == DIGI_CMD_READ_INPUT_SIGNALS) {
++ if (tty && opcode == DIGI_CMD_READ_INPUT_SIGNALS) {
+ spin_lock(&priv->dp_port_lock);
+ /* convert from digi flags to termiox flags */
+ if (val & DIGI_READ_INPUT_SIGNALS_CTS) {
diff --git a/tty/tty-serial-fix-tty-back-references-in-termios.patch b/tty/tty-serial-fix-tty-back-references-in-termios.patch
new file mode 100644
index 00000000000000..5838fa4959296b
--- /dev/null
+++ b/tty/tty-serial-fix-tty-back-references-in-termios.patch
@@ -0,0 +1,170 @@
+From arnd@arndb.de Tue Jun 15 16:51:09 2010
+From: Alan Cox <alan@linux.intel.com>
+Date: Tue, 1 Jun 2010 22:52:52 +0200
+Subject: tty: serial - fix tty back references in termios
+To: Greg KH <gregkh@suse.de>
+Cc: linux-kernel@vger.kernel.org, Arnd Bergmann <arnd@arndb.de>, Alan Cox <alan@lxorguk.ukuu.org.uk>, Frederic Weisbecker <fweisbec@gmail.com>, John Kacur <jkacur@redhat.com>, Alan Cox <alan@linux.intel.com>
+Message-ID: <1275425591-8803-13-git-send-email-arnd@arndb.de>
+
+
+From: Alan Cox <alan@linux.intel.com>
+
+One or two drivers go poking back into the tty from the termios setting
+routine in unsafe ways. We don't need to pass the tty down because the
+[ab]users are just using it to get at things they can get at anyway.
+
+This leaves low_latency setting to sort out along with set_ldisc use.
+
+Signed-off-by: Alan Cox <alan@linux.intel.com>
+Cc: Arnd Bergmann <arnd@arndb.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/serial/21285.c | 10 +++-------
+ drivers/serial/imx.c | 10 ++++------
+ drivers/serial/ioc3_serial.c | 9 +++++----
+ drivers/serial/ioc4_serial.c | 9 +++++----
+ drivers/serial/max3100.c | 7 ++-----
+ 5 files changed, 19 insertions(+), 26 deletions(-)
+
+--- a/drivers/serial/21285.c
++++ b/drivers/serial/21285.c
+@@ -216,7 +216,7 @@ serial21285_set_termios(struct uart_port
+ struct ktermios *old)
+ {
+ unsigned long flags;
+- unsigned int baud, quot, h_lcr;
++ unsigned int baud, quot, h_lcr, b;
+
+ /*
+ * We don't support modem control lines.
+@@ -234,12 +234,8 @@ serial21285_set_termios(struct uart_port
+ */
+ baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
+ quot = uart_get_divisor(port, baud);
+-
+- if (port->state && port->state->port.tty) {
+- struct tty_struct *tty = port->state->port.tty;
+- unsigned int b = port->uartclk / (16 * quot);
+- tty_encode_baud_rate(tty, b, b);
+- }
++ b = port->uartclk / (16 * quot);
++ tty_termios_encode_baud_rate(termios, b, b);
+
+ switch (termios->c_cflag & CSIZE) {
+ case CS5:
+--- a/drivers/serial/imx.c
++++ b/drivers/serial/imx.c
+@@ -909,13 +909,11 @@ imx_set_termios(struct uart_port *port,
+ rational_best_approximation(16 * div * baud, sport->port.uartclk,
+ 1 << 16, 1 << 16, &num, &denom);
+
+- if (port->state && port->state->port.tty) {
+- tdiv64 = sport->port.uartclk;
+- tdiv64 *= num;
+- do_div(tdiv64, denom * 16 * div);
+- tty_encode_baud_rate(sport->port.state->port.tty,
++ tdiv64 = sport->port.uartclk;
++ tdiv64 *= num;
++ do_div(tdiv64, denom * 16 * div);
++ tty_termios_encode_baud_rate(termios,
+ (speed_t)tdiv64, (speed_t)tdiv64);
+- }
+
+ num -= 1;
+ denom -= 1;
+--- a/drivers/serial/ioc3_serial.c
++++ b/drivers/serial/ioc3_serial.c
+@@ -954,12 +954,13 @@ ioc3_change_speed(struct uart_port *the_
+ struct ktermios *new_termios, struct ktermios *old_termios)
+ {
+ struct ioc3_port *port = get_ioc3_port(the_port);
+- unsigned int cflag;
++ unsigned int cflag, iflag;
+ int baud;
+ int new_parity = 0, new_parity_enable = 0, new_stop = 0, new_data = 8;
+ struct uart_state *state = the_port->state;
+
+ cflag = new_termios->c_cflag;
++ iflag = new_termios->c_iflag;
+
+ switch (cflag & CSIZE) {
+ case CS5:
+@@ -1000,12 +1001,12 @@ ioc3_change_speed(struct uart_port *the_
+
+ state->port.tty->low_latency = 1;
+
+- if (I_IGNPAR(state->port.tty))
++ if (iflag & IGNPAR))
+ the_port->ignore_status_mask &= ~(N_PARITY_ERROR
+ | N_FRAMING_ERROR);
+- if (I_IGNBRK(state->port.tty)) {
++ if (iflag & IGNBRK) {
+ the_port->ignore_status_mask &= ~N_BREAK;
+- if (I_IGNPAR(state->port.tty))
++ if (iflag & IGNPAR)
+ the_port->ignore_status_mask &= ~N_OVERRUN_ERROR;
+ }
+ if (!(cflag & CREAD)) {
+--- a/drivers/serial/ioc4_serial.c
++++ b/drivers/serial/ioc4_serial.c
+@@ -1685,11 +1685,12 @@ ioc4_change_speed(struct uart_port *the_
+ {
+ struct ioc4_port *port = get_ioc4_port(the_port, 0);
+ int baud, bits;
+- unsigned cflag;
++ unsigned cflag, iflag;
+ int new_parity = 0, new_parity_enable = 0, new_stop = 0, new_data = 8;
+ struct uart_state *state = the_port->state;
+
+ cflag = new_termios->c_cflag;
++ iflag = new_termios->c_iflag;
+
+ switch (cflag & CSIZE) {
+ case CS5:
+@@ -1741,12 +1742,12 @@ ioc4_change_speed(struct uart_port *the_
+
+ state->port.tty->low_latency = 1;
+
+- if (I_IGNPAR(state->port.tty))
++ if (iflag & IGNPAR)
+ the_port->ignore_status_mask &= ~(N_PARITY_ERROR
+ | N_FRAMING_ERROR);
+- if (I_IGNBRK(state->port.tty)) {
++ if (iflag & IGNBRK) {
+ the_port->ignore_status_mask &= ~N_BREAK;
+- if (I_IGNPAR(state->port.tty))
++ if (iflag & IGNPAR))
+ the_port->ignore_status_mask &= ~N_OVERRUN_ERROR;
+ }
+ if (!(cflag & CREAD)) {
+--- a/drivers/serial/max3100.c
++++ b/drivers/serial/max3100.c
+@@ -430,17 +430,14 @@ max3100_set_termios(struct uart_port *po
+ int baud = 0;
+ unsigned cflag;
+ u32 param_new, param_mask, parity = 0;
+- struct tty_struct *tty = s->port.state->port.tty;
+
+ dev_dbg(&s->spi->dev, "%s\n", __func__);
+- if (!tty)
+- return;
+
+ cflag = termios->c_cflag;
+ param_new = 0;
+ param_mask = 0;
+
+- baud = tty_get_baud_rate(tty);
++ baud = tty_termios_baud_rate(termios);
+ param_new = s->conf & MAX3100_BAUD;
+ switch (baud) {
+ case 300:
+@@ -485,7 +482,7 @@ max3100_set_termios(struct uart_port *po
+ default:
+ baud = s->baud;
+ }
+- tty_encode_baud_rate(tty, baud, baud);
++ tty_termios_encode_baud_rate(termios, baud, baud);
+ s->baud = baud;
+ param_mask |= MAX3100_BAUD;
+
diff --git a/tty/tty-serial-fix-tty-referencing-in-set_ldisc.patch b/tty/tty-serial-fix-tty-referencing-in-set_ldisc.patch
new file mode 100644
index 00000000000000..22ba06b048d544
--- /dev/null
+++ b/tty/tty-serial-fix-tty-referencing-in-set_ldisc.patch
@@ -0,0 +1,66 @@
+From arnd@arndb.de Tue Jun 15 16:51:48 2010
+From: Alan Cox <alan@linux.intel.com>
+Date: Tue, 1 Jun 2010 22:52:53 +0200
+Subject: tty: serial - fix tty referencing in set_ldisc
+To: Greg KH <gregkh@suse.de>
+Cc: linux-kernel@vger.kernel.org, Arnd Bergmann <arnd@arndb.de>, Alan Cox <alan@lxorguk.ukuu.org.uk>, Frederic Weisbecker <fweisbec@gmail.com>, John Kacur <jkacur@redhat.com>, Alan Cox <alan@linux.intel.com>
+Message-ID: <1275425591-8803-14-git-send-email-arnd@arndb.de>
+
+
+From: Alan Cox <alan@linux.intel.com>
+
+Pass down the ldisc number so that the drivers don't have to peek into the
+tty object themselves. This lets us get rid of another case of back referencing
+port to tty which we don't want (because of races versus hangup/close).
+
+Signed-off-by: Alan Cox <alan@linux.intel.com>
+Cc: Arnd Bergmann <arnd@arndb.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ drivers/serial/bfin_5xx.c | 7 ++-----
+ drivers/serial/serial_core.c | 2 +-
+ include/linux/serial_core.h | 2 +-
+ 3 files changed, 4 insertions(+), 7 deletions(-)
+
+--- a/drivers/serial/bfin_5xx.c
++++ b/drivers/serial/bfin_5xx.c
+@@ -957,15 +957,12 @@ bfin_serial_verify_port(struct uart_port
+ * Enable the IrDA function if tty->ldisc.num is N_IRDA.
+ * In other cases, disable IrDA function.
+ */
+-static void bfin_serial_set_ldisc(struct uart_port *port)
++static void bfin_serial_set_ldisc(struct uart_port *port, int ld)
+ {
+ int line = port->line;
+ unsigned short val;
+
+- if (line >= port->state->port.tty->driver->num)
+- return;
+-
+- switch (port->state->port.tty->termios->c_line) {
++ switch (ld) {
+ case N_IRDA:
+ val = UART_GET_GCTL(&bfin_serial_ports[line]);
+ val |= (IREN | RPOLC);
+--- a/drivers/serial/serial_core.c
++++ b/drivers/serial/serial_core.c
+@@ -1194,7 +1194,7 @@ static void uart_set_ldisc(struct tty_st
+ struct uart_port *uport = state->uart_port;
+
+ if (uport->ops->set_ldisc)
+- uport->ops->set_ldisc(uport);
++ uport->ops->set_ldisc(uport, tty->termios->c_line);
+ }
+
+ static void uart_set_termios(struct tty_struct *tty,
+--- a/include/linux/serial_core.h
++++ b/include/linux/serial_core.h
+@@ -220,7 +220,7 @@ struct uart_ops {
+ void (*flush_buffer)(struct uart_port *);
+ void (*set_termios)(struct uart_port *, struct ktermios *new,
+ struct ktermios *old);
+- void (*set_ldisc)(struct uart_port *);
++ void (*set_ldisc)(struct uart_port *, int new);
+ void (*pm)(struct uart_port *, unsigned int state,
+ unsigned int oldstate);
+ int (*set_wake)(struct uart_port *, unsigned int state);
diff --git a/tty/tty-serial-fix-various-misuses-mishandlings-of-port-tty.patch b/tty/tty-serial-fix-various-misuses-mishandlings-of-port-tty.patch
new file mode 100644
index 00000000000000..3ea9779699e5ca
--- /dev/null
+++ b/tty/tty-serial-fix-various-misuses-mishandlings-of-port-tty.patch
@@ -0,0 +1,363 @@
+From arnd@arndb.de Tue Jun 15 16:50:16 2010
+From: Alan Cox <alan@linux.intel.com>
+Date: Tue, 1 Jun 2010 22:52:51 +0200
+Subject: tty: serial - fix various misuses/mishandlings of port->tty
+To: Greg KH <gregkh@suse.de>
+Cc: linux-kernel@vger.kernel.org, Arnd Bergmann <arnd@arndb.de>, Alan Cox <alan@lxorguk.ukuu.org.uk>, Frederic Weisbecker <fweisbec@gmail.com>, John Kacur <jkacur@redhat.com>, Alan Cox <alan@linux.intel.com>
+Message-ID: <1275425591-8803-12-git-send-email-arnd@arndb.de>
+
+
+From: Alan Cox <alan@linux.intel.com>
+
+Make it robust against hang up events. In most cases we can do this simply
+by passing the right things in the first place.
+
+Signed-off-by: Alan Cox <alan@linux.intel.com>
+Cc: Arnd Bergmann <arnd@arndb.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/serial/serial_core.c | 109 +++++++++++++++++++++++--------------------
+ 1 file changed, 60 insertions(+), 49 deletions(-)
+
+--- a/drivers/serial/serial_core.c
++++ b/drivers/serial/serial_core.c
+@@ -58,7 +58,7 @@ static struct lock_class_key port_lock_k
+ #define uart_console(port) (0)
+ #endif
+
+-static void uart_change_speed(struct uart_state *state,
++static void uart_change_speed(struct tty_struct *tty, struct uart_state *state,
+ struct ktermios *old_termios);
+ static void uart_wait_until_sent(struct tty_struct *tty, int timeout);
+ static void uart_change_pm(struct uart_state *state, int pm_state);
+@@ -137,7 +137,7 @@ uart_update_mctrl(struct uart_port *port
+ * Startup the port. This will be called once per open. All calls
+ * will be serialised by the per-port mutex.
+ */
+-static int uart_startup(struct uart_state *state, int init_hw)
++static int uart_startup(struct tty_struct *tty, struct uart_state *state, int init_hw)
+ {
+ struct uart_port *uport = state->uart_port;
+ struct tty_port *port = &state->port;
+@@ -152,7 +152,7 @@ static int uart_startup(struct uart_stat
+ * once we have successfully opened the port. Also set
+ * up the tty->alt_speed kludge
+ */
+- set_bit(TTY_IO_ERROR, &port->tty->flags);
++ set_bit(TTY_IO_ERROR, &tty->flags);
+
+ if (uport->type == PORT_UNKNOWN)
+ return 0;
+@@ -177,26 +177,26 @@ static int uart_startup(struct uart_stat
+ /*
+ * Initialise the hardware port settings.
+ */
+- uart_change_speed(state, NULL);
++ uart_change_speed(tty, state, NULL);
+
+ /*
+ * Setup the RTS and DTR signals once the
+ * port is open and ready to respond.
+ */
+- if (port->tty->termios->c_cflag & CBAUD)
++ if (tty->termios->c_cflag & CBAUD)
+ uart_set_mctrl(uport, TIOCM_RTS | TIOCM_DTR);
+ }
+
+ if (port->flags & ASYNC_CTS_FLOW) {
+ spin_lock_irq(&uport->lock);
+ if (!(uport->ops->get_mctrl(uport) & TIOCM_CTS))
+- port->tty->hw_stopped = 1;
++ tty->hw_stopped = 1;
+ spin_unlock_irq(&uport->lock);
+ }
+
+ set_bit(ASYNCB_INITIALIZED, &port->flags);
+
+- clear_bit(TTY_IO_ERROR, &port->tty->flags);
++ clear_bit(TTY_IO_ERROR, &tty->flags);
+ }
+
+ if (retval && capable(CAP_SYS_ADMIN))
+@@ -210,11 +210,10 @@ static int uart_startup(struct uart_stat
+ * DTR is dropped if the hangup on close termio flag is on. Calls to
+ * uart_shutdown are serialised by the per-port semaphore.
+ */
+-static void uart_shutdown(struct uart_state *state)
++static void uart_shutdown(struct tty_struct *tty, struct uart_state *state)
+ {
+ struct uart_port *uport = state->uart_port;
+ struct tty_port *port = &state->port;
+- struct tty_struct *tty = port->tty;
+
+ /*
+ * Set the TTY IO error marker
+@@ -430,11 +429,10 @@ uart_get_divisor(struct uart_port *port,
+ EXPORT_SYMBOL(uart_get_divisor);
+
+ /* FIXME: Consistent locking policy */
+-static void
+-uart_change_speed(struct uart_state *state, struct ktermios *old_termios)
++static void uart_change_speed(struct tty_struct *tty, struct uart_state *state,
++ struct ktermios *old_termios)
+ {
+ struct tty_port *port = &state->port;
+- struct tty_struct *tty = port->tty;
+ struct uart_port *uport = state->uart_port;
+ struct ktermios *termios;
+
+@@ -463,8 +461,8 @@ uart_change_speed(struct uart_state *sta
+ uport->ops->set_termios(uport, termios, old_termios);
+ }
+
+-static inline int
+-__uart_put_char(struct uart_port *port, struct circ_buf *circ, unsigned char c)
++static inline int __uart_put_char(struct uart_port *port,
++ struct circ_buf *circ, unsigned char c)
+ {
+ unsigned long flags;
+ int ret = 0;
+@@ -494,8 +492,8 @@ static void uart_flush_chars(struct tty_
+ uart_start(tty);
+ }
+
+-static int
+-uart_write(struct tty_struct *tty, const unsigned char *buf, int count)
++static int uart_write(struct tty_struct *tty,
++ const unsigned char *buf, int count)
+ {
+ struct uart_state *state = tty->driver_data;
+ struct uart_port *port;
+@@ -675,7 +673,7 @@ static int uart_get_info(struct uart_sta
+ return 0;
+ }
+
+-static int uart_set_info(struct uart_state *state,
++static int uart_set_info(struct tty_struct *tty, struct uart_state *state,
+ struct serial_struct __user *newinfo)
+ {
+ struct serial_struct new_serial;
+@@ -770,7 +768,7 @@ static int uart_set_info(struct uart_sta
+ * We need to shutdown the serial port at the old
+ * port/type/irq combination.
+ */
+- uart_shutdown(state);
++ uart_shutdown(tty, state);
+ }
+
+ if (change_port) {
+@@ -869,25 +867,27 @@ static int uart_set_info(struct uart_sta
+ "is deprecated.\n", current->comm,
+ tty_name(port->tty, buf));
+ }
+- uart_change_speed(state, NULL);
++ uart_change_speed(tty, state, NULL);
+ }
+ } else
+- retval = uart_startup(state, 1);
++ retval = uart_startup(tty, state, 1);
+ exit:
+ mutex_unlock(&port->mutex);
+ return retval;
+ }
+
+-
+-/*
+- * uart_get_lsr_info - get line status register info.
+- * Note: uart_ioctl protects us against hangups.
++/**
++ * uart_get_lsr_info - get line status register info
++ * @tty: tty associated with the UART
++ * @state: UART being queried
++ * @value: returned modem value
++ *
++ * Note: uart_ioctl protects us against hangups.
+ */
+-static int uart_get_lsr_info(struct uart_state *state,
+- unsigned int __user *value)
++static int uart_get_lsr_info(struct tty_struct *tty,
++ struct uart_state *state, unsigned int __user *value)
+ {
+ struct uart_port *uport = state->uart_port;
+- struct tty_port *port = &state->port;
+ unsigned int result;
+
+ result = uport->ops->tx_empty(uport);
+@@ -900,7 +900,7 @@ static int uart_get_lsr_info(struct uart
+ */
+ if (uport->x_char ||
+ ((uart_circ_chars_pending(&state->xmit) > 0) &&
+- !port->tty->stopped && !port->tty->hw_stopped))
++ !tty->stopped && !tty->hw_stopped))
+ result &= ~TIOCSER_TEMT;
+
+ return put_user(result, value);
+@@ -961,7 +961,7 @@ static int uart_break_ctl(struct tty_str
+ return 0;
+ }
+
+-static int uart_do_autoconfig(struct uart_state *state)
++static int uart_do_autoconfig(struct tty_struct *tty,struct uart_state *state)
+ {
+ struct uart_port *uport = state->uart_port;
+ struct tty_port *port = &state->port;
+@@ -980,7 +980,7 @@ static int uart_do_autoconfig(struct uar
+
+ ret = -EBUSY;
+ if (tty_port_users(port) == 1) {
+- uart_shutdown(state);
++ uart_shutdown(tty, state);
+
+ /*
+ * If we already have a port type configured,
+@@ -999,7 +999,7 @@ static int uart_do_autoconfig(struct uar
+ */
+ uport->ops->config_port(uport, flags);
+
+- ret = uart_startup(state, 1);
++ ret = uart_startup(tty, state, 1);
+ }
+ mutex_unlock(&port->mutex);
+ return ret;
+@@ -1122,11 +1122,11 @@ uart_ioctl(struct tty_struct *tty, struc
+ break;
+
+ case TIOCSSERIAL:
+- ret = uart_set_info(state, uarg);
++ ret = uart_set_info(tty, state, uarg);
+ break;
+
+ case TIOCSERCONFIG:
+- ret = uart_do_autoconfig(state);
++ ret = uart_do_autoconfig(tty, state);
+ break;
+
+ case TIOCSERGWILD: /* obsolete */
+@@ -1172,7 +1172,7 @@ uart_ioctl(struct tty_struct *tty, struc
+ */
+ switch (cmd) {
+ case TIOCSERGETLSR: /* Get line status register */
+- ret = uart_get_lsr_info(state, uarg);
++ ret = uart_get_lsr_info(tty, state, uarg);
+ break;
+
+ default: {
+@@ -1219,7 +1219,7 @@ static void uart_set_termios(struct tty_
+ return;
+ }
+
+- uart_change_speed(state, old_termios);
++ uart_change_speed(tty, state, old_termios);
+
+ /* Handle transition to B0 status */
+ if ((old_termios->c_cflag & CBAUD) && !(cflag & CBAUD))
+@@ -1335,7 +1335,7 @@ static void uart_close(struct tty_struct
+ uart_wait_until_sent(tty, uport->timeout);
+ }
+
+- uart_shutdown(state);
++ uart_shutdown(tty, state);
+ uart_flush_buffer(tty);
+
+ tty_ldisc_flush(tty);
+@@ -1436,7 +1436,7 @@ static void uart_hangup(struct tty_struc
+ mutex_lock(&port->mutex);
+ if (port->flags & ASYNC_NORMAL_ACTIVE) {
+ uart_flush_buffer(tty);
+- uart_shutdown(state);
++ uart_shutdown(tty, state);
+ port->count = 0;
+ clear_bit(ASYNCB_NORMAL_ACTIVE, &port->flags);
+ tty_port_tty_set(port, NULL);
+@@ -1446,15 +1446,19 @@ static void uart_hangup(struct tty_struc
+ mutex_unlock(&port->mutex);
+ }
+
+-/*
+- * Copy across the serial console cflag setting into the termios settings
+- * for the initial open of the port. This allows continuity between the
+- * kernel settings, and the settings init adopts when it opens the port
+- * for the first time.
++/**
++ * uart_update_termios - update the terminal hw settings
++ * @tty: tty associated with UART
++ * @state: UART to update
++ *
++ * Copy across the serial console cflag setting into the termios settings
++ * for the initial open of the port. This allows continuity between the
++ * kernel settings, and the settings init adopts when it opens the port
++ * for the first time.
+ */
+-static void uart_update_termios(struct uart_state *state)
++static void uart_update_termios(struct tty_struct *tty,
++ struct uart_state *state)
+ {
+- struct tty_struct *tty = state->port.tty;
+ struct uart_port *port = state->uart_port;
+
+ if (uart_console(port) && port->cons->cflag) {
+@@ -1471,7 +1475,7 @@ static void uart_update_termios(struct u
+ /*
+ * Make termios settings take effect.
+ */
+- uart_change_speed(state, NULL);
++ uart_change_speed(tty, state, NULL);
+
+ /*
+ * And finally enable the RTS and DTR signals.
+@@ -1668,7 +1672,7 @@ static int uart_open(struct tty_struct *
+ /*
+ * Start up the serial port.
+ */
+- retval = uart_startup(state, 0);
++ retval = uart_startup(tty, state, 0);
+
+ /*
+ * If we succeeded, wait until the port is ready.
+@@ -1683,7 +1687,7 @@ static int uart_open(struct tty_struct *
+ if (retval == 0 && !(port->flags & ASYNC_NORMAL_ACTIVE)) {
+ set_bit(ASYNCB_NORMAL_ACTIVE, &port->flags);
+
+- uart_update_termios(state);
++ uart_update_termios(tty, state);
+ }
+
+ fail:
+@@ -2010,9 +2014,13 @@ int uart_suspend_port(struct uart_driver
+ struct tty_port *port = &state->port;
+ struct device *tty_dev;
+ struct uart_match match = {uport, drv};
++ struct tty_struct *tty;
+
+ mutex_lock(&port->mutex);
+
++ /* Must be inside the mutex lock until we convert to tty_port */
++ tty = port->tty;
++
+ tty_dev = device_find_child(uport->dev, &match, serial_match_port);
+ if (device_may_wakeup(tty_dev)) {
+ enable_irq_wake(uport->irq);
+@@ -2105,9 +2113,12 @@ int uart_resume_port(struct uart_driver
+ ops->set_mctrl(uport, 0);
+ spin_unlock_irq(&uport->lock);
+ if (console_suspend_enabled || !uart_console(uport)) {
++ /* Protected by port mutex for now */
++ struct tty_struct *tty = port->tty;
+ ret = ops->startup(uport);
+ if (ret == 0) {
+- uart_change_speed(state, NULL);
++ if (tty)
++ uart_change_speed(tty, state, NULL);
+ spin_lock_irq(&uport->lock);
+ ops->set_mctrl(uport, uport->mctrl);
+ ops->start_tx(uport);
+@@ -2119,7 +2130,7 @@ int uart_resume_port(struct uart_driver
+ * Clear the "initialized" flag so we won't try
+ * to call the low level drivers shutdown method.
+ */
+- uart_shutdown(state);
++ uart_shutdown(tty, state);
+ }
+ }
+