aboutsummaryrefslogtreecommitdiffstats
path: root/tty
diff options
authorGreg Kroah-Hartman <gregkh@suse.de>2009-12-22 12:22:11 -0800
committerGreg Kroah-Hartman <gregkh@suse.de>2009-12-22 12:22:11 -0800
commit52a248c714fb17267c89520a4a854b0f65de998c (patch)
treeb08803dad70c8bfeba8a20e4c06b24ea6ce5cf9d /tty
parentae75e9fa49d0b2a2a776794dad9e420e7bc269f2 (diff)
downloadpatches-52a248c714fb17267c89520a4a854b0f65de998c.tar.gz
huge catchup on pending patches
Diffstat (limited to 'tty')
-rw-r--r--tty/hvc_console-fix-test-on-unsigned-in-hvc_console_print.patch35
-rw-r--r--tty/ip2-remove-ifdef-module-from-ip2main.c.patch97
-rw-r--r--tty/serial-68328serial.c-remove-baud_table_size-macro.patch56
-rw-r--r--tty/serial-8250-add-serial-transmitter-fully-empty-test.patch86
-rw-r--r--tty/serial-8250_pci-add-support-for-mcs9865-syba-6x-serial-port-card.patch124
-rw-r--r--tty/serial-8250_pnp-use-wildcard-for-serial-wacom-tablets.patch46
-rw-r--r--tty/serial-add-support-for-korenix-jetcard.patch52
-rw-r--r--tty/serial-atmel_serial-add-poll_get_char-and-poll_put_char-uart_ops.patch63
-rw-r--r--tty/serial-char-cyclades-fix-compiler-warning.patch58
-rw-r--r--tty/serial-copy-uart-properties-of-upf_fixed_type-ports-provisioned-using-early_serial_setup.patch71
-rw-r--r--tty/serial-core-resume-serial-hardware-with-no_console_suspend.patch186
-rw-r--r--tty/serial-cyclades-allow-overriding-isa-defaults-also-when-the-driver-is-built-in.patch71
-rw-r--r--tty/serial-fit-blackfin-uart-over-sport-driver-into-common-uart-infrastructure.patch1123
-rw-r--r--tty/serial-fix-test-of-unsigned.patch72
-rw-r--r--tty/serial-imx-fix-null-dereference-oops-when-pdata-null.patch63
-rw-r--r--tty/serial-isicom.c-use-pr_fmt-and-pr_-level.patch175
-rw-r--r--tty/serial-serial_cs-oxsemi-quirk-breaks-resume.patch39
-rw-r--r--tty/serial-synclink_gt-dropped-transmit-data-bugfix.patch385
-rw-r--r--tty/tty-char-mxser-remove-unnecessary-tty-test.patch36
-rw-r--r--tty/tty-moxa-remove-ifdef-module-completely.patch88
20 files changed, 2926 insertions, 0 deletions
diff --git a/tty/hvc_console-fix-test-on-unsigned-in-hvc_console_print.patch b/tty/hvc_console-fix-test-on-unsigned-in-hvc_console_print.patch
new file mode 100644
index 00000000000000..0d47f7fd71b985
--- /dev/null
+++ b/tty/hvc_console-fix-test-on-unsigned-in-hvc_console_print.patch
@@ -0,0 +1,35 @@
+From akpm@linux-foundation.org Tue Dec 22 11:45:22 2009
+From: Roel Kluin <roel.kluin@gmail.com>
+Date: Wed, 09 Dec 2009 12:34:16 -0800
+Subject: hvc_console: fix test on unsigned in hvc_console_print()
+To: greg@kroah.com
+Cc: alan@lxorguk.ukuu.org.uk, akpm@linux-foundation.org, roel.kluin@gmail.com, benh@kernel.crashing.org, borntraeger@de.ibm.com, brueckner@linux.vnet.ibm.com
+Message-ID: <200912092034.nB9KYHJV010718@imap1.linux-foundation.org>
+
+
+From: Roel Kluin <roel.kluin@gmail.com>
+
+vtermnos[] is unsigned, so this test was wrong.
+
+Signed-off-by: Roel Kluin <roel.kluin@gmail.com>
+Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
+Cc: Hendrik Brueckner <brueckner@linux.vnet.ibm.com>
+Cc: Christian Borntraeger <borntraeger@de.ibm.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/char/hvc_console.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/char/hvc_console.c
++++ b/drivers/char/hvc_console.c
+@@ -146,7 +146,7 @@ static void hvc_console_print(struct con
+ return;
+
+ /* This console adapter was removed so it is not usable. */
+- if (vtermnos[index] < 0)
++ if (vtermnos[index] == -1)
+ return;
+
+ while (count > 0 || i > 0) {
diff --git a/tty/ip2-remove-ifdef-module-from-ip2main.c.patch b/tty/ip2-remove-ifdef-module-from-ip2main.c.patch
new file mode 100644
index 00000000000000..1ebc9cd30cdb10
--- /dev/null
+++ b/tty/ip2-remove-ifdef-module-from-ip2main.c.patch
@@ -0,0 +1,97 @@
+From akpm@linux-foundation.org Tue Dec 22 11:46:18 2009
+From: Rakib Mullick <rakib.mullick@gmail.com>
+Date: Wed, 09 Dec 2009 12:34:18 -0800
+Subject: ip2: remove #ifdef MODULE from ip2main.c
+To: greg@kroah.com
+Cc: alan@lxorguk.ukuu.org.uk, akpm@linux-foundation.org, rakib.mullick@gmail.com, mhw@WittsEnd.com
+Message-ID: <200912092034.nB9KYJK6010879@imap1.linux-foundation.org>
+
+
+From: Rakib Mullick <rakib.mullick@gmail.com>
+
+On the kernel command line we can pass "module parameters". So #ifdef
+MODULE is obsolute now. Remove it completely. When CONFIG_PCI=n and
+building ip2main.c then we are hit by the following warning. So move
+*pdev into #ifdef CONFIG_PCI.
+
+drivers/char/ip2/ip2main.c: In function `ip2_loadmain':
+drivers/char/ip2/ip2main.c:542: warning: unused variable `pdev'
+
+Signed-off-by: Rakib Mullick <rakib.mullick@gmail.com>
+Acked-by: Michael H. Warfield <mhw@WittsEnd.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/char/ip2/ip2main.c | 11 +++++------
+ 1 file changed, 5 insertions(+), 6 deletions(-)
+
+--- a/drivers/char/ip2/ip2main.c
++++ b/drivers/char/ip2/ip2main.c
+@@ -263,7 +263,7 @@ static int tracewrap;
+ /* Macros */
+ /**********/
+
+-#if defined(MODULE) && defined(IP2DEBUG_OPEN)
++#ifdef IP2DEBUG_OPEN
+ #define DBG_CNT(s) printk(KERN_DEBUG "(%s): [%x] ttyc=%d, modc=%x -> %s\n", \
+ tty->name,(pCh->flags), \
+ tty->count,/*GET_USE_COUNT(module)*/0,s)
+@@ -487,7 +487,6 @@ static const struct firmware *ip2_reques
+ return fw;
+ }
+
+-#ifndef MODULE
+ /******************************************************************************
+ * ip2_setup:
+ * str: kernel command line string
+@@ -531,7 +530,6 @@ static int __init ip2_setup(char *str)
+ return 1;
+ }
+ __setup("ip2=", ip2_setup);
+-#endif /* !MODULE */
+
+ static int __init ip2_loadmain(void)
+ {
+@@ -539,7 +537,6 @@ static int __init ip2_loadmain(void)
+ int err = 0;
+ i2eBordStrPtr pB = NULL;
+ int rc = -1;
+- struct pci_dev *pdev = NULL;
+ const struct firmware *fw = NULL;
+
+ if (poll_only) {
+@@ -612,6 +609,7 @@ static int __init ip2_loadmain(void)
+ case PCI:
+ #ifdef CONFIG_PCI
+ {
++ struct pci_dev *pdev = NULL;
+ u32 addr;
+ int status;
+
+@@ -626,7 +624,7 @@ static int __init ip2_loadmain(void)
+
+ if (pci_enable_device(pdev)) {
+ dev_err(&pdev->dev, "can't enable device\n");
+- break;
++ goto out;
+ }
+ ip2config.type[i] = PCI;
+ ip2config.pci_dev[i] = pci_dev_get(pdev);
+@@ -638,6 +636,8 @@ static int __init ip2_loadmain(void)
+ dev_err(&pdev->dev, "I/O address error\n");
+
+ ip2config.irq[i] = pdev->irq;
++out:
++ pci_dev_put(pdev);
+ }
+ #else
+ printk(KERN_ERR "IP2: PCI card specified but PCI "
+@@ -656,7 +656,6 @@ static int __init ip2_loadmain(void)
+ break;
+ } /* switch */
+ } /* for */
+- pci_dev_put(pdev);
+
+ for (i = 0; i < IP2_MAX_BOARDS; ++i) {
+ if (ip2config.addr[i]) {
diff --git a/tty/serial-68328serial.c-remove-baud_table_size-macro.patch b/tty/serial-68328serial.c-remove-baud_table_size-macro.patch
new file mode 100644
index 00000000000000..4fcc0002194fa4
--- /dev/null
+++ b/tty/serial-68328serial.c-remove-baud_table_size-macro.patch
@@ -0,0 +1,56 @@
+From akpm@linux-foundation.org Tue Dec 22 11:36:53 2009
+From: Thiago Farina <tfransosi@gmail.com>
+Date: Wed, 09 Dec 2009 12:31:30 -0800
+Subject: serial: 68328serial.c: remove BAUD_TABLE_SIZE macro
+To: greg@kroah.com
+Cc: alan@lxorguk.ukuu.org.uk, akpm@linux-foundation.org, tfransosi@gmail.com
+Message-ID: <200912092031.nB9KVVsA003749@imap1.linux-foundation.org>
+
+
+From: Thiago Farina <tfransosi@gmail.com>
+
+This macro is a duplicate of ARRAY_SIZE defined in kernel api, so just use
+that instead.
+
+Signed-off-by: Thiago Farina <tfransosi@gmail.com>
+Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/serial/68328serial.c | 8 +++-----
+ 1 file changed, 3 insertions(+), 5 deletions(-)
+
+--- a/drivers/serial/68328serial.c
++++ b/drivers/serial/68328serial.c
+@@ -153,8 +153,6 @@ static int baud_table[] = {
+ 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
+ 9600, 19200, 38400, 57600, 115200, 0 };
+
+-#define BAUD_TABLE_SIZE (sizeof(baud_table)/sizeof(baud_table[0]))
+-
+ /* Sets or clears DTR/RTS on the requested line */
+ static inline void m68k_rtsdtr(struct m68k_serial *ss, int set)
+ {
+@@ -1406,10 +1404,10 @@ static void m68328_set_baud(void)
+ USTCNT = ustcnt & ~USTCNT_TXEN;
+
+ again:
+- for (i = 0; i < sizeof(baud_table) / sizeof(baud_table[0]); i++)
++ for (i = 0; i < ARRAY_SIZE(baud_table); i++)
+ if (baud_table[i] == m68328_console_baud)
+ break;
+- if (i >= sizeof(baud_table) / sizeof(baud_table[0])) {
++ if (i >= ARRAY_SIZE(baud_table)) {
+ m68328_console_baud = 9600;
+ goto again;
+ }
+@@ -1435,7 +1433,7 @@ int m68328_console_setup(struct console
+ if (arg)
+ n = simple_strtoul(arg,NULL,0);
+
+- for (i = 0; i < BAUD_TABLE_SIZE; i++)
++ for (i = 0; i < ARRAY_SIZE(baud_table); i++)
+ if (baud_table[i] == n)
+ break;
+ if (i < BAUD_TABLE_SIZE) {
diff --git a/tty/serial-8250-add-serial-transmitter-fully-empty-test.patch b/tty/serial-8250-add-serial-transmitter-fully-empty-test.patch
new file mode 100644
index 00000000000000..a3331c56ad9dde
--- /dev/null
+++ b/tty/serial-8250-add-serial-transmitter-fully-empty-test.patch
@@ -0,0 +1,86 @@
+From akpm@linux-foundation.org Tue Dec 22 11:38:31 2009
+From: Dick Hollenbeck <dick@softplc.com>
+Date: Wed, 09 Dec 2009 12:31:34 -0800
+Subject: serial: 8250: add serial transmitter fully empty test
+To: greg@kroah.com
+Cc: alan@lxorguk.ukuu.org.uk, akpm@linux-foundation.org, dick@softplc.com, alan@linux.intel.com, k.schoenmakers@sigmae.nl
+Message-ID: <200912092031.nB9KVYsu003819@imap1.linux-foundation.org>
+
+
+From: Dick Hollenbeck <dick@softplc.com>
+
+When controlling an industrial radio modem it can be necessary to
+manipulate the handshake lines in order to control the radio modem's
+transmitter, from userspace.
+
+The transmitter should not be turned off before all characters have been
+transmitted. serial8250_tx_empty() was reporting that all characters were
+transmitted before they actually were.
+
+===
+
+Discovered in parallel with more testing and analysis by Kees Schoenmakers
+as follows:
+
+I ran into an NetMos 9835 serial pci board which behaves a little
+different than the standard. This type of expansion board is very common.
+
+"Standard" 8250 compatible devices clear the 'UART_LST_TEMT" bit together
+with the "UART_LSR_THRE" bit when writing data to the device.
+
+The NetMos device does it slightly different
+
+I believe that the TEMT bit is coupled to the shift register. The problem
+is that after writing data to the device and very quickly after that one
+does call serial8250_tx_empty, it returns the wrong information.
+
+My patch makes the test more robust (and solves the problem) and it does
+not affect the already correct devices.
+
+
+Alan:
+
+ We may yet need to quirk this but now we know which chips we have a
+ way to do that should we find this breaks some other 8250 clone with
+ dodgy THRE.
+
+Signed-off-by: Dick Hollenbeck <dick@softplc.com>
+Signed-off-by: Alan Cox <alan@linux.intel.com>
+Cc: Kees Schoenmakers <k.schoenmakers@sigmae.nl>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/serial/8250.c | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+--- a/drivers/serial/8250.c
++++ b/drivers/serial/8250.c
+@@ -83,6 +83,9 @@ static unsigned int skip_txen_test; /* f
+
+ #define PASS_LIMIT 256
+
++#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
++
++
+ /*
+ * We default to IRQ0 for the "no irq" hack. Some
+ * machine types want others as well - they're free
+@@ -1792,7 +1795,7 @@ static unsigned int serial8250_tx_empty(
+ up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS;
+ spin_unlock_irqrestore(&up->port.lock, flags);
+
+- return lsr & UART_LSR_TEMT ? TIOCSER_TEMT : 0;
++ return (lsr & BOTH_EMPTY) == BOTH_EMPTY ? TIOCSER_TEMT : 0;
+ }
+
+ static unsigned int serial8250_get_mctrl(struct uart_port *port)
+@@ -1850,8 +1853,6 @@ static void serial8250_break_ctl(struct
+ spin_unlock_irqrestore(&up->port.lock, flags);
+ }
+
+-#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
+-
+ /*
+ * Wait for transmitter & holding register to empty
+ */
diff --git a/tty/serial-8250_pci-add-support-for-mcs9865-syba-6x-serial-port-card.patch b/tty/serial-8250_pci-add-support-for-mcs9865-syba-6x-serial-port-card.patch
new file mode 100644
index 00000000000000..72f2b5d64661bb
--- /dev/null
+++ b/tty/serial-8250_pci-add-support-for-mcs9865-syba-6x-serial-port-card.patch
@@ -0,0 +1,124 @@
+From akpm@linux-foundation.org Tue Dec 22 11:40:32 2009
+From: "Ira W. Snyder" <iws@ovro.caltech.edu>
+Date: Mon, 21 Dec 2009 16:26:45 -0800
+Subject: serial: 8250_pci: add support for MCS9865 / SYBA 6x Serial Port Card
+To: greg@kroah.com
+Cc: alan@lxorguk.ukuu.org.uk, akpm@linux-foundation.org, iws@ovro.caltech.edu, augulis.darius@gmail.com
+Message-ID: <200912220026.nBM0Qjhc005287@imap1.linux-foundation.org>
+
+
+From: "Ira W. Snyder" <iws@ovro.caltech.edu>
+
+This patch is heavily based on an earlier patch found on the linux-serial
+mailing list [1], written by Darius Augulis.
+
+The previous incarnation of this patch only supported a 2x serial port
+card. I have added support for my SYBA 6x serial port card, and tested on
+x86.
+
+[1]: http://marc.info/?l=linux-serial&m=124975806304760
+
+Signed-off-by: Ira W. Snyder <iws@ovro.caltech.edu>
+Cc: Darius Augulis <augulis.darius@gmail.com>
+Cc: Greg KH <greg@kroah.com>
+Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/parport/parport_pc.c | 6 ++++++
+ drivers/serial/8250_pci.c | 22 +++++++++++++++++++++-
+ include/linux/pci_ids.h | 1 +
+ 3 files changed, 28 insertions(+), 1 deletion(-)
+
+--- a/drivers/parport/parport_pc.c
++++ b/drivers/parport/parport_pc.c
+@@ -2908,6 +2908,7 @@ enum parport_pc_pci_cards {
+ netmos_9805,
+ netmos_9815,
+ netmos_9901,
++ netmos_9865,
+ quatech_sppxp100,
+ };
+
+@@ -2989,6 +2990,7 @@ static struct parport_pc_pci {
+ /* netmos_9805 */ { 1, { { 0, -1 }, } },
+ /* netmos_9815 */ { 2, { { 0, -1 }, { 2, -1 }, } },
+ /* netmos_9901 */ { 1, { { 0, -1 }, } },
++ /* netmos_9865 */ { 1, { { 0, -1 }, } },
+ /* quatech_sppxp100 */ { 1, { { 0, 1 }, } },
+ };
+
+@@ -3092,6 +3094,10 @@ static const struct pci_device_id parpor
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9815 },
+ { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9901,
+ 0xA000, 0x2000, 0, 0, netmos_9901 },
++ { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9865,
++ 0xA000, 0x1000, 0, 0, netmos_9865 },
++ { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9865,
++ 0xA000, 0x2000, 0, 0, netmos_9865 },
+ /* Quatech SPPXP-100 Parallel port PCI ExpressCard */
+ { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_SPPXP_100,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, quatech_sppxp100 },
+--- a/drivers/serial/8250_pci.c
++++ b/drivers/serial/8250_pci.c
+@@ -760,7 +760,8 @@ static int pci_netmos_init(struct pci_de
+ /* subdevice 0x00PS means <P> parallel, <S> serial */
+ unsigned int num_serial = dev->subsystem_device & 0xf;
+
+- if (dev->device == PCI_DEVICE_ID_NETMOS_9901)
++ if ((dev->device == PCI_DEVICE_ID_NETMOS_9901) ||
++ (dev->device == PCI_DEVICE_ID_NETMOS_9865))
+ return 0;
+ if (dev->subsystem_vendor == PCI_VENDOR_ID_IBM &&
+ dev->subsystem_device == 0x0299)
+@@ -1479,6 +1480,7 @@ enum pci_board_num_t {
+
+ pbn_b0_bt_1_115200,
+ pbn_b0_bt_2_115200,
++ pbn_b0_bt_4_115200,
+ pbn_b0_bt_8_115200,
+
+ pbn_b0_bt_1_460800,
+@@ -1703,6 +1705,12 @@ static struct pciserial_board pci_boards
+ .base_baud = 115200,
+ .uart_offset = 8,
+ },
++ [pbn_b0_bt_4_115200] = {
++ .flags = FL_BASE0|FL_BASE_BARS,
++ .num_ports = 4,
++ .base_baud = 115200,
++ .uart_offset = 8,
++ },
+ [pbn_b0_bt_8_115200] = {
+ .flags = FL_BASE0|FL_BASE_BARS,
+ .num_ports = 8,
+@@ -3649,6 +3657,18 @@ static struct pci_device_id serial_pci_t
+ 0, 0, pbn_b0_1_115200 },
+
+ /*
++ * Best Connectivity PCI Multi I/O cards
++ */
++
++ { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9865,
++ 0xA000, 0x1000,
++ 0, 0, pbn_b0_1_115200 },
++
++ { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9865,
++ 0xA000, 0x3004,
++ 0, 0, pbn_b0_bt_4_115200 },
++
++ /*
+ * These entries match devices with class COMMUNICATION_SERIAL,
+ * COMMUNICATION_MODEM or COMMUNICATION_MULTISERIAL
+ */
+--- a/include/linux/pci_ids.h
++++ b/include/linux/pci_ids.h
+@@ -2694,6 +2694,7 @@
+ #define PCI_DEVICE_ID_NETMOS_9835 0x9835
+ #define PCI_DEVICE_ID_NETMOS_9845 0x9845
+ #define PCI_DEVICE_ID_NETMOS_9855 0x9855
++#define PCI_DEVICE_ID_NETMOS_9865 0x9865
+ #define PCI_DEVICE_ID_NETMOS_9901 0x9901
+
+ #define PCI_VENDOR_ID_3COM_2 0xa727
diff --git a/tty/serial-8250_pnp-use-wildcard-for-serial-wacom-tablets.patch b/tty/serial-8250_pnp-use-wildcard-for-serial-wacom-tablets.patch
new file mode 100644
index 00000000000000..cb637c7d174c52
--- /dev/null
+++ b/tty/serial-8250_pnp-use-wildcard-for-serial-wacom-tablets.patch
@@ -0,0 +1,46 @@
+From akpm@linux-foundation.org Tue Dec 22 11:39:34 2009
+From: Matthew Garrett <mjg@redhat.com>
+Date: Wed, 09 Dec 2009 12:31:37 -0800
+Subject: serial: 8250_pnp: use wildcard for serial Wacom tablets
+To: greg@kroah.com
+Cc: alan@lxorguk.ukuu.org.uk, akpm@linux-foundation.org, mjg@redhat.com, pingc@wacom.com
+Message-ID: <200912092031.nB9KVbOO004049@imap1.linux-foundation.org>
+
+
+From: Matthew Garrett <mjg@redhat.com>
+
+Wacom claims that the WACF namespace will always be devoted to serial
+Wacom tablets. Remove the existing entries and add a wildcard to avoid
+having to update the kernel every time they add a new device.
+
+Signed-off-by: Ping Cheng <pingc@wacom.com>
+Signed-off-by: Matthew Garrett <mjg@redhat.com>
+Tested-by: Ping Cheng <pingc@wacom.com>
+Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
+Cc: Greg KH <greg@kroah.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/serial/8250_pnp.c | 10 +---------
+ 1 file changed, 1 insertion(+), 9 deletions(-)
+
+--- a/drivers/serial/8250_pnp.c
++++ b/drivers/serial/8250_pnp.c
+@@ -328,15 +328,7 @@ static const struct pnp_device_id pnp_de
+ /* U.S. Robotics 56K Voice INT PnP*/
+ { "USR9190", 0 },
+ /* Wacom tablets */
+- { "WACF004", 0 },
+- { "WACF005", 0 },
+- { "WACF006", 0 },
+- { "WACF007", 0 },
+- { "WACF008", 0 },
+- { "WACF009", 0 },
+- { "WACF00A", 0 },
+- { "WACF00B", 0 },
+- { "WACF00C", 0 },
++ { "WACFXXX", 0 },
+ /* Compaq touchscreen */
+ { "FPI2002", 0 },
+ /* Fujitsu Stylistic touchscreens */
diff --git a/tty/serial-add-support-for-korenix-jetcard.patch b/tty/serial-add-support-for-korenix-jetcard.patch
new file mode 100644
index 00000000000000..55a2b6621922ad
--- /dev/null
+++ b/tty/serial-add-support-for-korenix-jetcard.patch
@@ -0,0 +1,52 @@
+From akpm@linux-foundation.org Tue Dec 22 11:41:35 2009
+From: akpm@linux-foundation.org
+Date: Mon, 21 Dec 2009 16:26:48 -0800
+Subject: serial: add support for Korenix JetCard
+To: greg@kroah.com
+Cc: alan@lxorguk.ukuu.org.uk, akpm@linux-foundation.org, kiros@korenix.com, alan@linux.intel.com
+Message-ID: <200912220026.nBM0QmTm005293@imap1.linux-foundation.org>
+
+
+From: Kiros Yeh <kiros@korenix.com>
+
+Add different model (with a different PCI ID) to support Korenix JetCard.
+
+Signed-off-by: Kiros Yeh <kiros@korenix.com>
+Acked-by: Alan Cox <alan@linux.intel.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/serial/8250_pci.c | 9 +++++++++
+ include/linux/pci_ids.h | 2 ++
+ 2 files changed, 11 insertions(+)
+
+--- a/drivers/serial/8250_pci.c
++++ b/drivers/serial/8250_pci.c
+@@ -3199,6 +3199,15 @@ static struct pci_device_id serial_pci_t
+ 0x1208, 0x0004, 0, 0,
+ pbn_b0_4_921600 },
+
++ { PCI_VENDOR_ID_KORENIX, PCI_DEVICE_ID_KORENIX_JETCARDF2,
++ 0x1204, 0x0004, 0, 0,
++ pbn_b0_4_921600 },
++ { PCI_VENDOR_ID_KORENIX, PCI_DEVICE_ID_KORENIX_JETCARDF2,
++ 0x1208, 0x0004, 0, 0,
++ pbn_b0_4_921600 },
++ { PCI_VENDOR_ID_KORENIX, PCI_DEVICE_ID_KORENIX_JETCARDF3,
++ 0x1208, 0x0004, 0, 0,
++ pbn_b0_4_921600 },
+ /*
+ * Dell Remote Access Card 4 - Tim_T_Murphy@Dell.com
+ */
+--- a/include/linux/pci_ids.h
++++ b/include/linux/pci_ids.h
+@@ -2333,6 +2333,8 @@
+ #define PCI_VENDOR_ID_KORENIX 0x1982
+ #define PCI_DEVICE_ID_KORENIX_JETCARDF0 0x1600
+ #define PCI_DEVICE_ID_KORENIX_JETCARDF1 0x16ff
++#define PCI_DEVICE_ID_KORENIX_JETCARDF2 0x1700
++#define PCI_DEVICE_ID_KORENIX_JETCARDF3 0x17ff
+
+ #define PCI_VENDOR_ID_QMI 0x1a32
+
diff --git a/tty/serial-atmel_serial-add-poll_get_char-and-poll_put_char-uart_ops.patch b/tty/serial-atmel_serial-add-poll_get_char-and-poll_put_char-uart_ops.patch
new file mode 100644
index 00000000000000..e505e786d237e5
--- /dev/null
+++ b/tty/serial-atmel_serial-add-poll_get_char-and-poll_put_char-uart_ops.patch
@@ -0,0 +1,63 @@
+From akpm@linux-foundation.org Tue Dec 22 11:38:06 2009
+From: Albin Tonnerre <albin.tonnerre@free-electrons.com>
+Date: Wed, 09 Dec 2009 12:31:32 -0800
+Subject: serial: atmel_serial: add poll_get_char and poll_put_char uart_ops
+To: greg@kroah.com
+Cc: alan@lxorguk.ukuu.org.uk, akpm@linux-foundation.org, albin.tonnerre@free-electrons.com, haavard.skinnemoen@atmel.com, linux@maxim.org.za
+Message-ID: <200912092031.nB9KVWIv003816@imap1.linux-foundation.org>
+
+
+From: Albin Tonnerre <albin.tonnerre@free-electrons.com>
+
+Permits using KGDB over the console with the atmel_serial driver.
+
+[akpm@linux-foundation.org: s/barrier/cpu_relax/]
+Signed-off-by: Albin Tonnerre <albin.tonnerre@free-electrons.com>
+Acked-by: Andrew Victor <linux@maxim.org.za>
+Acked-by: Haavard Skinnemoen <haavard.skinnemoen@atmel.com>
+Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/serial/atmel_serial.c | 22 ++++++++++++++++++++++
+ 1 file changed, 22 insertions(+)
+
+--- a/drivers/serial/atmel_serial.c
++++ b/drivers/serial/atmel_serial.c
+@@ -1213,6 +1213,24 @@ static int atmel_verify_port(struct uart
+ return ret;
+ }
+
++#ifdef CONFIG_CONSOLE_POLL
++static int atmel_poll_get_char(struct uart_port *port)
++{
++ while (!(UART_GET_CSR(port) & ATMEL_US_RXRDY))
++ cpu_relax();
++
++ return UART_GET_CHAR(port);
++}
++
++static void atmel_poll_put_char(struct uart_port *port, unsigned char ch)
++{
++ while (!(UART_GET_CSR(port) & ATMEL_US_TXRDY))
++ cpu_relax();
++
++ UART_PUT_CHAR(port, ch);
++}
++#endif
++
+ static struct uart_ops atmel_pops = {
+ .tx_empty = atmel_tx_empty,
+ .set_mctrl = atmel_set_mctrl,
+@@ -1232,6 +1250,10 @@ static struct uart_ops atmel_pops = {
+ .config_port = atmel_config_port,
+ .verify_port = atmel_verify_port,
+ .pm = atmel_serial_pm,
++#ifdef CONFIG_CONSOLE_POLL
++ .poll_get_char = atmel_poll_get_char,
++ .poll_put_char = atmel_poll_put_char,
++#endif
+ };
+
+ /*
diff --git a/tty/serial-char-cyclades-fix-compiler-warning.patch b/tty/serial-char-cyclades-fix-compiler-warning.patch
new file mode 100644
index 00000000000000..2d86c48f8bae8c
--- /dev/null
+++ b/tty/serial-char-cyclades-fix-compiler-warning.patch
@@ -0,0 +1,58 @@
+From akpm@linux-foundation.org Tue Dec 22 11:43:18 2009
+From: Jiri Slaby <jslaby@novell.com>
+Date: Wed, 09 Dec 2009 12:34:13 -0800
+Subject: serial: Char: cyclades, fix compiler warning
+To: greg@kroah.com
+Cc: alan@lxorguk.ukuu.org.uk, akpm@linux-foundation.org, jslaby@novell.com, alan@linux.intel.com, gregkh@suse.de, jirislaby@gmail.com, linux@linux.site
+Message-ID: <200912092034.nB9KYExu010573@imap1.linux-foundation.org>
+
+
+From: Jiri Slaby <jslaby@novell.com>
+
+With gcc 4.0.2:
+drivers/char/cyclades.c: In function 'cyy_interrupt':
+drivers/char/cyclades.c:581: warning: 'info' may be used uninitialized in this function
+
+introduced by
+
+: commit 3aeea5b92210083c7cffd4f08a0bb141d3f2d574
+: Author: Jiri Slaby <jirislaby@gmail.com>
+: AuthorDate: Sat Sep 19 13:13:16 2009 -0700
+: Commit: Live-CD User <linux@linux.site>
+: CommitDate: Sat Sep 19 13:13:16 2009 -0700
+:
+: cyclades: introduce cyy_readb/writeb
+
+In fact the true branch which uses uninitialized 'info' can never
+happen because chip is always less than ->nchips and channel is
+always less than 4 which we alloc.
+
+So behave similar to rx handling and remove the test completely.
+
+I wonder why gcc 4.4.1 doesn't spit a word.
+
+Reported-by: Andrew Morton <akpm@linux-foundation.org>
+Cc: Alan Cox <alan@linux.intel.com>
+Signed-off-by: Jiri Slaby <jslaby@novell.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/char/cyclades.c | 6 ------
+ 1 file changed, 6 deletions(-)
+
+--- a/drivers/char/cyclades.c
++++ b/drivers/char/cyclades.c
+@@ -598,12 +598,6 @@ static void cyy_chip_tx(struct cyclades_
+ save_car = readb(base_addr + (CyCAR << index));
+ cy_writeb(base_addr + (CyCAR << index), save_xir);
+
+- /* validate the port# (as configured and open) */
+- if (channel + chip * 4 >= cinfo->nports) {
+- cy_writeb(base_addr + (CySRER << index),
+- readb(base_addr + (CySRER << index)) & ~CyTxRdy);
+- goto end;
+- }
+ info = &cinfo->ports[channel + chip * 4];
+ tty = tty_port_tty_get(&info->port);
+ if (tty == NULL) {
diff --git a/tty/serial-copy-uart-properties-of-upf_fixed_type-ports-provisioned-using-early_serial_setup.patch b/tty/serial-copy-uart-properties-of-upf_fixed_type-ports-provisioned-using-early_serial_setup.patch
new file mode 100644
index 00000000000000..df4133b780cc5c
--- /dev/null
+++ b/tty/serial-copy-uart-properties-of-upf_fixed_type-ports-provisioned-using-early_serial_setup.patch
@@ -0,0 +1,71 @@
+From akpm@linux-foundation.org Tue Dec 22 11:36:26 2009
+From: Shmulik Ladkani <shmulik@jungo.com>
+Date: Wed, 09 Dec 2009 12:31:29 -0800
+Subject: serial: copy UART properties of UPF_FIXED_TYPE ports provisioned using early_serial_setup
+To: greg@kroah.com
+Cc: alan@lxorguk.ukuu.org.uk, akpm@linux-foundation.org, shmulik@jungo.com
+Message-ID: <200912092031.nB9KVU61003732@imap1.linux-foundation.org>
+
+
+From: Shmulik Ladkani <shmulik@jungo.com>
+
+Augment the UPF_FIXED_TYPE logic, which currently applies to UART ports
+provisioned using platform_device_register.
+
+The suggested patch applies same logic into 'serial8250_register_ports',
+making UART ports provisioned using early_serial_setup inherit their
+properties from the uart_config entry.
+
+Signed-off-by: Shmulik Ladkani <shmulik@jungo.com>
+Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/serial/8250.c | 21 +++++++++++++++------
+ 1 file changed, 15 insertions(+), 6 deletions(-)
+
+--- a/drivers/serial/8250.c
++++ b/drivers/serial/8250.c
+@@ -2688,6 +2688,15 @@ static void __init serial8250_isa_init_p
+ }
+ }
+
++static void
++serial8250_init_fixed_type_port(struct uart_8250_port *up, unsigned int type)
++{
++ up->port.type = type;
++ up->port.fifosize = uart_config[type].fifo_size;
++ up->capabilities = uart_config[type].flags;
++ up->tx_loadsz = uart_config[type].tx_loadsz;
++}
++
+ static void __init
+ serial8250_register_ports(struct uart_driver *drv, struct device *dev)
+ {
+@@ -2704,6 +2713,10 @@ serial8250_register_ports(struct uart_dr
+ struct uart_8250_port *up = &serial8250_ports[i];
+
+ up->port.dev = dev;
++
++ if (up->port.flags & UPF_FIXED_TYPE)
++ serial8250_init_fixed_type_port(up, up->port.type);
++
+ uart_add_one_port(drv, &up->port);
+ }
+ }
+@@ -3116,12 +3129,8 @@ int serial8250_register_port(struct uart
+ if (port->dev)
+ uart->port.dev = port->dev;
+
+- if (port->flags & UPF_FIXED_TYPE) {
+- uart->port.type = port->type;
+- uart->port.fifosize = uart_config[port->type].fifo_size;
+- uart->capabilities = uart_config[port->type].flags;
+- uart->tx_loadsz = uart_config[port->type].tx_loadsz;
+- }
++ if (port->flags & UPF_FIXED_TYPE)
++ serial8250_init_fixed_type_port(uart, port->type);
+
+ set_io_from_upio(&uart->port);
+ /* Possibly override default I/O functions. */
diff --git a/tty/serial-core-resume-serial-hardware-with-no_console_suspend.patch b/tty/serial-core-resume-serial-hardware-with-no_console_suspend.patch
new file mode 100644
index 00000000000000..d5c691a63616b5
--- /dev/null
+++ b/tty/serial-core-resume-serial-hardware-with-no_console_suspend.patch
@@ -0,0 +1,186 @@
+From sbrabec@suse.cz Tue Dec 22 11:27:41 2009
+From: Stanislav Brabec <sbrabec@suse.cz>
+Date: Wed, 02 Dec 2009 16:20:56 +0100
+Subject: serial-core: resume serial hardware with no_console_suspend
+To: Andrew Morton <akpm@linux-foundation.org>
+Cc: linux@arm.linux.org.uk, linux-kernel@vger.kernel.org, alan@lxorguk.ukuu.org.uk, gregkh@suse.de, Pavel Machek <pavel@ucw.cz>, Daniel Mack <daniel@caiaq.de>, saxena@laptop.org, Eric Miao <eric.y.miao@gmail.com>, s.hauer@pengutronix.de, Haojian Zhuang <haojian.zhuang@gmail.com>
+Message-ID: <1259767256.8709.323.camel@hammer.suse.cz>
+
+
+Perform a tricky suspend/resume even with no_console_suspend.
+
+With no_console_suspend, kernel skips serial port suspend/resume and the
+serial hardware may remain in undefined state after resume. It actually
+happens on devices that don't have BIOS that handle serial
+initialization. It makes impossible to use serial console after resume.
+
+Devices affected by this problem include:
+Sharp Zaurus devices
+Several PXA based ARM embedded boards
+
+The patch does:
+- Save the hardware state
+- Perform buffer flush in time of its suspend call
+- Tell the driver that port is suspended
+- But still accept new data
+- And keep console hardware in state that allows to send them
+
+It allows to capture late console messages without breaking console
+after resume.
+
+This is just a resend of a patch discussed in these threads, as the
+patch was not yet applied.
+
+"Possible suspend/resume regression in .32-rc?" (Nov 1-5, 2009, ARM
+list, later LKML)
+
+"serial-core: resume serial hardware with no_console_suspend" (Sep
+15-Oct 18, 2009, LKML & ARM lists)
+
+Signed-off-by: Stanislav Brabec <sbrabec@suse.cz>
+Tested-by: Haojian Zhuang <haojian.zhuang@gmail.com>
+Tested-by: Daniel Mack <daniel@caiaq.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/serial/serial_core.c | 88 ++++++++++++++++---------------------------
+ 1 file changed, 33 insertions(+), 55 deletions(-)
+
+--- a/drivers/serial/serial_core.c
++++ b/drivers/serial/serial_core.c
+@@ -2006,12 +2006,6 @@ int uart_suspend_port(struct uart_driver
+
+ mutex_lock(&port->mutex);
+
+- if (!console_suspend_enabled && uart_console(uport)) {
+- /* we're going to avoid suspending serial console */
+- mutex_unlock(&port->mutex);
+- return 0;
+- }
+-
+ tty_dev = device_find_child(uport->dev, &match, serial_match_port);
+ if (device_may_wakeup(tty_dev)) {
+ enable_irq_wake(uport->irq);
+@@ -2019,20 +2013,23 @@ int uart_suspend_port(struct uart_driver
+ mutex_unlock(&port->mutex);
+ return 0;
+ }
+- uport->suspended = 1;
++ if (console_suspend_enabled || !uart_console(uport))
++ uport->suspended = 1;
+
+ if (port->flags & ASYNC_INITIALIZED) {
+ const struct uart_ops *ops = uport->ops;
+ int tries;
+
+- set_bit(ASYNCB_SUSPENDED, &port->flags);
+- clear_bit(ASYNCB_INITIALIZED, &port->flags);
++ if (console_suspend_enabled || !uart_console(uport)) {
++ set_bit(ASYNCB_SUSPENDED, &port->flags);
++ clear_bit(ASYNCB_INITIALIZED, &port->flags);
+
+- spin_lock_irq(&uport->lock);
+- ops->stop_tx(uport);
+- ops->set_mctrl(uport, 0);
+- ops->stop_rx(uport);
+- spin_unlock_irq(&uport->lock);
++ spin_lock_irq(&uport->lock);
++ ops->stop_tx(uport);
++ ops->set_mctrl(uport, 0);
++ ops->stop_rx(uport);
++ spin_unlock_irq(&uport->lock);
++ }
+
+ /*
+ * Wait for the transmitter to empty.
+@@ -2047,16 +2044,18 @@ int uart_suspend_port(struct uart_driver
+ drv->dev_name,
+ drv->tty_driver->name_base + uport->line);
+
+- ops->shutdown(uport);
++ if (console_suspend_enabled || !uart_console(uport))
++ ops->shutdown(uport);
+ }
+
+ /*
+ * Disable the console device before suspending.
+ */
+- if (uart_console(uport))
++ if (console_suspend_enabled && uart_console(uport))
+ console_stop(uport->cons);
+
+- uart_change_pm(state, 3);
++ if (console_suspend_enabled || !uart_console(uport))
++ uart_change_pm(state, 3);
+
+ mutex_unlock(&port->mutex);
+
+@@ -2073,29 +2072,6 @@ int uart_resume_port(struct uart_driver
+
+ mutex_lock(&port->mutex);
+
+- if (!console_suspend_enabled && uart_console(uport)) {
+- /* no need to resume serial console, it wasn't suspended */
+- /*
+- * First try to use the console cflag setting.
+- */
+- memset(&termios, 0, sizeof(struct ktermios));
+- termios.c_cflag = uport->cons->cflag;
+- /*
+- * If that's unset, use the tty termios setting.
+- */
+- if (termios.c_cflag == 0)
+- termios = *state->port.tty->termios;
+- else {
+- termios.c_ispeed = termios.c_ospeed =
+- tty_termios_input_baud_rate(&termios);
+- termios.c_ispeed = termios.c_ospeed =
+- tty_termios_baud_rate(&termios);
+- }
+- uport->ops->set_termios(uport, &termios, NULL);
+- mutex_unlock(&port->mutex);
+- return 0;
+- }
+-
+ tty_dev = device_find_child(uport->dev, &match, serial_match_port);
+ if (!uport->suspended && device_may_wakeup(tty_dev)) {
+ disable_irq_wake(uport->irq);
+@@ -2121,21 +2097,23 @@ int uart_resume_port(struct uart_driver
+ spin_lock_irq(&uport->lock);
+ ops->set_mctrl(uport, 0);
+ spin_unlock_irq(&uport->lock);
+- ret = ops->startup(uport);
+- if (ret == 0) {
+- uart_change_speed(state, NULL);
+- spin_lock_irq(&uport->lock);
+- ops->set_mctrl(uport, uport->mctrl);
+- ops->start_tx(uport);
+- spin_unlock_irq(&uport->lock);
+- set_bit(ASYNCB_INITIALIZED, &port->flags);
+- } else {
+- /*
+- * Failed to resume - maybe hardware went away?
+- * Clear the "initialized" flag so we won't try
+- * to call the low level drivers shutdown method.
+- */
+- uart_shutdown(state);
++ if (console_suspend_enabled || !uart_console(uport)) {
++ ret = ops->startup(uport);
++ if (ret == 0) {
++ uart_change_speed(state, NULL);
++ spin_lock_irq(&uport->lock);
++ ops->set_mctrl(uport, uport->mctrl);
++ ops->start_tx(uport);
++ spin_unlock_irq(&uport->lock);
++ set_bit(ASYNCB_INITIALIZED, &port->flags);
++ } else {
++ /*
++ * Failed to resume - maybe hardware went away?
++ * Clear the "initialized" flag so we won't try
++ * to call the low level drivers shutdown method.
++ */
++ uart_shutdown(state);
++ }
+ }
+
+ clear_bit(ASYNCB_SUSPENDED, &port->flags);
diff --git a/tty/serial-cyclades-allow-overriding-isa-defaults-also-when-the-driver-is-built-in.patch b/tty/serial-cyclades-allow-overriding-isa-defaults-also-when-the-driver-is-built-in.patch
new file mode 100644
index 00000000000000..604e65b1095dfc
--- /dev/null
+++ b/tty/serial-cyclades-allow-overriding-isa-defaults-also-when-the-driver-is-built-in.patch
@@ -0,0 +1,71 @@
+From akpm@linux-foundation.org Tue Dec 22 11:43:38 2009
+From: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
+Date: Wed, 09 Dec 2009 12:34:14 -0800
+Subject: serial: cyclades: allow overriding ISA defaults also when the driver is built-in
+To: greg@kroah.com
+Cc: alan@lxorguk.ukuu.org.uk, akpm@linux-foundation.org, bzolnier@gmail.com, jirislaby@gmail.com
+Message-ID: <200912092034.nB9KYELi010579@imap1.linux-foundation.org>
+
+
+From: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
+
+Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
+Signed-off-by: Jiri Slaby <jirislaby@gmail.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/char/cyclades.c | 9 +--------
+ 1 file changed, 1 insertion(+), 8 deletions(-)
+
+--- a/drivers/char/cyclades.c
++++ b/drivers/char/cyclades.c
+@@ -158,13 +158,11 @@ static unsigned int cy_isa_addresses[] =
+
+ #define NR_ISA_ADDRS ARRAY_SIZE(cy_isa_addresses)
+
+-#ifdef MODULE
+ static long maddr[NR_CARDS];
+ static int irq[NR_CARDS];
+
+ module_param_array(maddr, long, NULL, 0);
+ module_param_array(irq, int, NULL, 0);
+-#endif
+
+ #endif /* CONFIG_ISA */
+
+@@ -3310,13 +3308,10 @@ static int __init cy_detect_isa(void)
+ unsigned short cy_isa_irq, nboard;
+ void __iomem *cy_isa_address;
+ unsigned short i, j, cy_isa_nchan;
+-#ifdef MODULE
+ int isparam = 0;
+-#endif
+
+ nboard = 0;
+
+-#ifdef MODULE
+ /* Check for module parameters */
+ for (i = 0; i < NR_CARDS; i++) {
+ if (maddr[i] || i) {
+@@ -3326,7 +3321,6 @@ static int __init cy_detect_isa(void)
+ if (!maddr[i])
+ break;
+ }
+-#endif
+
+ /* scan the address table probing for Cyclom-Y/ISA boards */
+ for (i = 0; i < NR_ISA_ADDRS; i++) {
+@@ -3347,11 +3341,10 @@ static int __init cy_detect_isa(void)
+ iounmap(cy_isa_address);
+ continue;
+ }
+-#ifdef MODULE
++
+ if (isparam && i < NR_CARDS && irq[i])
+ cy_isa_irq = irq[i];
+ else
+-#endif
+ /* find out the board's irq by probing */
+ cy_isa_irq = detect_isa_irq(cy_isa_address);
+ if (cy_isa_irq == 0) {
diff --git a/tty/serial-fit-blackfin-uart-over-sport-driver-into-common-uart-infrastructure.patch b/tty/serial-fit-blackfin-uart-over-sport-driver-into-common-uart-infrastructure.patch
new file mode 100644
index 00000000000000..54666641f6f82d
--- /dev/null
+++ b/tty/serial-fit-blackfin-uart-over-sport-driver-into-common-uart-infrastructure.patch
@@ -0,0 +1,1123 @@
+From akpm@linux-foundation.org Tue Dec 22 11:35:57 2009
+From: sonic zhang <sonic.adi@gmail.com>
+Date: Wed, 09 Dec 2009 12:31:28 -0800
+Subject: serial: fit blackfin uart over sport driver into common uart infrastructure
+To: greg@kroah.com
+Cc: alan@lxorguk.ukuu.org.uk, akpm@linux-foundation.org, sonic.adi@gmail.com, cooloney@kernel.org, sonic.zhang@analog.com, vapier@gentoo.org
+Message-ID: <200912092031.nB9KVSeT003604@imap1.linux-foundation.org>
+
+
+From: sonic zhang <sonic.adi@gmail.com>
+
+Fit blackfin uart over sport driver into common uart inftrastructure. It
+is based on the early platform interfaces to get the platform data early
+when the console is initilized.
+
+1. Enable sport uart driver to change uart baud, data bit, stop bit at
+ runtime. Bind the index of uart device nodes to physical index of
+ sports.
+
+2. Move all platform data into arch specific board files. Register
+ and probe platform device data in both early and normal stages.
+
+3. Console is registered in sport uart driver as well.
+
+4. Remove 500 us block waiting in sport tx stop code by putting a
+ dummy data into tx fifo to make sure the sport tx stops when all bytes
+ are shifted out except for the dummy data.
+
+5. clean up a bit and fix up coding style.
+
+Signed-off-by: Sonic Zhang <sonic.zhang@analog.com>
+Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
+Cc: Mike Frysinger <vapier@gentoo.org>
+Cc: Bryan Wu <cooloney@kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/serial/Kconfig | 52 +-
+ drivers/serial/bfin_sport_uart.c | 703 ++++++++++++++++++++++++++-------------
+ drivers/serial/bfin_sport_uart.h | 38 --
+ 3 files changed, 512 insertions(+), 281 deletions(-)
+
+--- a/drivers/serial/bfin_sport_uart.c
++++ b/drivers/serial/bfin_sport_uart.c
+@@ -1,27 +1,11 @@
+ /*
+- * File: linux/drivers/serial/bfin_sport_uart.c
++ * Blackfin On-Chip Sport Emulated UART Driver
+ *
+- * Based on: drivers/serial/bfin_5xx.c by Aubrey Li.
+- * Author: Roy Huang <roy.huang@analog.com>
++ * Copyright 2006-2009 Analog Devices Inc.
+ *
+- * Created: Nov 22, 2006
+- * Copyright: (c) 2006-2007 Analog Devices Inc.
+- * Description: this driver enable SPORTs on Blackfin emulate UART.
++ * Enter bugs at http://blackfin.uclinux.org/
+ *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, see the file COPYING, or write
+- * to the Free Software Foundation, Inc.,
+- * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ * Licensed under the GPL-2 or later.
+ */
+
+ /*
+@@ -29,39 +13,18 @@
+ * http://www.analog.com/UploadedFiles/Application_Notes/399447663EE191.pdf
+ * This application note describe how to implement a UART on a Sharc DSP,
+ * but this driver is implemented on Blackfin Processor.
++ * Transmit Frame Sync is not used by this driver to transfer data out.
+ */
+
+-/* After reset, there is a prelude of low level pulse when transmit data first
+- * time. No addtional pulse in following transmit.
+- * According to document:
+- * The SPORTs are ready to start transmitting or receiving data no later than
+- * three serial clock cycles after they are enabled in the SPORTx_TCR1 or
+- * SPORTx_RCR1 register. No serial clock cycles are lost from this point on.
+- * The first internal frame sync will occur one frame sync delay after the
+- * SPORTs are ready. External frame syncs can occur as soon as the SPORT is
+- * ready.
+- */
+-
+-/* Thanks to Axel Alatalo <axel@rubico.se> for fixing sport rx bug. Sometimes
+- * sport receives data incorrectly. The following is Axel's words.
+- * As EE-191, sport rx samples 3 times of the UART baudrate and takes the
+- * middle smaple of every 3 samples as the data bit. For a 8-N-1 UART setting,
+- * 30 samples will be required for a byte. If transmitter sends a 1/3 bit short
+- * byte due to buadrate drift, then the 30th sample of a byte, this sample is
+- * also the third sample of the stop bit, will happens on the immediately
+- * following start bit which will be thrown away and missed. Thus since parts
+- * of the startbit will be missed and the receiver will begin to drift, the
+- * effect accumulates over time until synchronization is lost.
+- * If only require 2 samples of the stopbit (by sampling in total 29 samples),
+- * then a to short byte as in the case above will be tolerated. Then the 1/3
+- * early startbit will trigger a framesync since the last read is complete
+- * after only 2/3 stopbit and framesync is active during the last 1/3 looking
+- * for a possible early startbit. */
++/* #define DEBUG */
+
+-//#define DEBUG
++#define DRV_NAME "bfin-sport-uart"
++#define DEVICE_NAME "ttySS"
++#define pr_fmt(fmt) DRV_NAME ": " fmt
+
+ #include <linux/module.h>
+ #include <linux/ioport.h>
++#include <linux/io.h>
+ #include <linux/init.h>
+ #include <linux/console.h>
+ #include <linux/sysrq.h>
+@@ -75,23 +38,36 @@
+
+ #include "bfin_sport_uart.h"
+
++#ifdef CONFIG_SERIAL_BFIN_SPORT0_UART
+ unsigned short bfin_uart_pin_req_sport0[] =
+ {P_SPORT0_TFS, P_SPORT0_DTPRI, P_SPORT0_TSCLK, P_SPORT0_RFS, \
+ P_SPORT0_DRPRI, P_SPORT0_RSCLK, P_SPORT0_DRSEC, P_SPORT0_DTSEC, 0};
+-
++#endif
++#ifdef CONFIG_SERIAL_BFIN_SPORT1_UART
+ unsigned short bfin_uart_pin_req_sport1[] =
+ {P_SPORT1_TFS, P_SPORT1_DTPRI, P_SPORT1_TSCLK, P_SPORT1_RFS, \
+ P_SPORT1_DRPRI, P_SPORT1_RSCLK, P_SPORT1_DRSEC, P_SPORT1_DTSEC, 0};
+-
+-#define DRV_NAME "bfin-sport-uart"
++#endif
++#ifdef CONFIG_SERIAL_BFIN_SPORT2_UART
++unsigned short bfin_uart_pin_req_sport2[] =
++ {P_SPORT2_TFS, P_SPORT2_DTPRI, P_SPORT2_TSCLK, P_SPORT2_RFS, \
++ P_SPORT2_DRPRI, P_SPORT2_RSCLK, P_SPORT2_DRSEC, P_SPORT2_DTSEC, 0};
++#endif
++#ifdef CONFIG_SERIAL_BFIN_SPORT3_UART
++unsigned short bfin_uart_pin_req_sport3[] =
++ {P_SPORT3_TFS, P_SPORT3_DTPRI, P_SPORT3_TSCLK, P_SPORT3_RFS, \
++ P_SPORT3_DRPRI, P_SPORT3_RSCLK, P_SPORT3_DRSEC, P_SPORT3_DTSEC, 0};
++#endif
+
+ struct sport_uart_port {
+ struct uart_port port;
+- char *name;
+-
+- int tx_irq;
+- int rx_irq;
+ int err_irq;
++ unsigned short csize;
++ unsigned short rxmask;
++ unsigned short txmask1;
++ unsigned short txmask2;
++ unsigned char stopb;
++/* unsigned char parib; */
+ };
+
+ static void sport_uart_tx_chars(struct sport_uart_port *up);
+@@ -99,36 +75,42 @@ static void sport_stop_tx(struct uart_po
+
+ static inline void tx_one_byte(struct sport_uart_port *up, unsigned int value)
+ {
+- pr_debug("%s value:%x\n", __func__, value);
+- /* Place a Start and Stop bit */
++ pr_debug("%s value:%x, mask1=0x%x, mask2=0x%x\n", __func__, value,
++ up->txmask1, up->txmask2);
++
++ /* Place Start and Stop bits */
+ __asm__ __volatile__ (
+- "R2 = b#01111111100;"
+- "R3 = b#10000000001;"
+- "%0 <<= 2;"
+- "%0 = %0 & R2;"
+- "%0 = %0 | R3;"
+- : "=d"(value)
+- : "d"(value)
+- : "ASTAT", "R2", "R3"
++ "%[val] <<= 1;"
++ "%[val] = %[val] & %[mask1];"
++ "%[val] = %[val] | %[mask2];"
++ : [val]"+d"(value)
++ : [mask1]"d"(up->txmask1), [mask2]"d"(up->txmask2)
++ : "ASTAT"
+ );
+ pr_debug("%s value:%x\n", __func__, value);
+
+ SPORT_PUT_TX(up, value);
+ }
+
+-static inline unsigned int rx_one_byte(struct sport_uart_port *up)
++static inline unsigned char rx_one_byte(struct sport_uart_port *up)
+ {
+- unsigned int value, extract;
++ unsigned int value;
++ unsigned char extract;
+ u32 tmp_mask1, tmp_mask2, tmp_shift, tmp;
+
+- value = SPORT_GET_RX32(up);
+- pr_debug("%s value:%x\n", __func__, value);
++ if ((up->csize + up->stopb) > 7)
++ value = SPORT_GET_RX32(up);
++ else
++ value = SPORT_GET_RX(up);
+
+- /* Extract 8 bits data */
++ pr_debug("%s value:%x, cs=%d, mask=0x%x\n", __func__, value,
++ up->csize, up->rxmask);
++
++ /* Extract data */
+ __asm__ __volatile__ (
+ "%[extr] = 0;"
+- "%[mask1] = 0x1801(Z);"
+- "%[mask2] = 0x0300(Z);"
++ "%[mask1] = %[rxmask];"
++ "%[mask2] = 0x0200(Z);"
+ "%[shift] = 0;"
+ "LSETUP(.Lloop_s, .Lloop_e) LC0 = %[lc];"
+ ".Lloop_s:"
+@@ -138,9 +120,9 @@ static inline unsigned int rx_one_byte(s
+ "%[mask1] = %[mask1] - %[mask2];"
+ ".Lloop_e:"
+ "%[shift] += 1;"
+- : [val]"=d"(value), [extr]"=d"(extract), [shift]"=d"(tmp_shift), [tmp]"=d"(tmp),
+- [mask1]"=d"(tmp_mask1), [mask2]"=d"(tmp_mask2)
+- : "d"(value), [lc]"a"(8)
++ : [extr]"=&d"(extract), [shift]"=&d"(tmp_shift), [tmp]"=&d"(tmp),
++ [mask1]"=&d"(tmp_mask1), [mask2]"=&d"(tmp_mask2)
++ : [val]"d"(value), [rxmask]"d"(up->rxmask), [lc]"a"(up->csize)
+ : "ASTAT", "LB0", "LC0", "LT0"
+ );
+
+@@ -148,29 +130,28 @@ static inline unsigned int rx_one_byte(s
+ return extract;
+ }
+
+-static int sport_uart_setup(struct sport_uart_port *up, int sclk, int baud_rate)
++static int sport_uart_setup(struct sport_uart_port *up, int size, int baud_rate)
+ {
+- int tclkdiv, tfsdiv, rclkdiv;
++ int tclkdiv, rclkdiv;
++ unsigned int sclk = get_sclk();
+
+- /* Set TCR1 and TCR2 */
+- SPORT_PUT_TCR1(up, (LATFS | ITFS | TFSR | TLSBIT | ITCLK));
+- SPORT_PUT_TCR2(up, 10);
++ /* Set TCR1 and TCR2, TFSR is not enabled for uart */
++ SPORT_PUT_TCR1(up, (ITFS | TLSBIT | ITCLK));
++ SPORT_PUT_TCR2(up, size + 1);
+ pr_debug("%s TCR1:%x, TCR2:%x\n", __func__, SPORT_GET_TCR1(up), SPORT_GET_TCR2(up));
+
+ /* Set RCR1 and RCR2 */
+ SPORT_PUT_RCR1(up, (RCKFE | LARFS | LRFS | RFSR | IRCLK));
+- SPORT_PUT_RCR2(up, 28);
++ SPORT_PUT_RCR2(up, (size + 1) * 2 - 1);
+ pr_debug("%s RCR1:%x, RCR2:%x\n", __func__, SPORT_GET_RCR1(up), SPORT_GET_RCR2(up));
+
+- tclkdiv = sclk/(2 * baud_rate) - 1;
+- tfsdiv = 12;
+- rclkdiv = sclk/(2 * baud_rate * 3) - 1;
++ tclkdiv = sclk / (2 * baud_rate) - 1;
++ rclkdiv = sclk / (2 * baud_rate * 2) - 1;
+ SPORT_PUT_TCLKDIV(up, tclkdiv);
+- SPORT_PUT_TFSDIV(up, tfsdiv);
+ SPORT_PUT_RCLKDIV(up, rclkdiv);
+ SSYNC();
+- pr_debug("%s sclk:%d, baud_rate:%d, tclkdiv:%d, tfsdiv:%d, rclkdiv:%d\n",
+- __func__, sclk, baud_rate, tclkdiv, tfsdiv, rclkdiv);
++ pr_debug("%s sclk:%d, baud_rate:%d, tclkdiv:%d, rclkdiv:%d\n",
++ __func__, sclk, baud_rate, tclkdiv, rclkdiv);
+
+ return 0;
+ }
+@@ -181,23 +162,29 @@ static irqreturn_t sport_uart_rx_irq(int
+ struct tty_struct *tty = up->port.state->port.tty;
+ unsigned int ch;
+
+- do {
++ spin_lock(&up->port.lock);
++
++ while (SPORT_GET_STAT(up) & RXNE) {
+ ch = rx_one_byte(up);
+ up->port.icount.rx++;
+
+- if (uart_handle_sysrq_char(&up->port, ch))
+- ;
+- else
++ if (!uart_handle_sysrq_char(&up->port, ch))
+ tty_insert_flip_char(tty, ch, TTY_NORMAL);
+- } while (SPORT_GET_STAT(up) & RXNE);
++ }
+ tty_flip_buffer_push(tty);
+
++ spin_unlock(&up->port.lock);
++
+ return IRQ_HANDLED;
+ }
+
+ static irqreturn_t sport_uart_tx_irq(int irq, void *dev_id)
+ {
+- sport_uart_tx_chars(dev_id);
++ struct sport_uart_port *up = dev_id;
++
++ spin_lock(&up->port.lock);
++ sport_uart_tx_chars(up);
++ spin_unlock(&up->port.lock);
+
+ return IRQ_HANDLED;
+ }
+@@ -208,6 +195,8 @@ static irqreturn_t sport_uart_err_irq(in
+ struct tty_struct *tty = up->port.state->port.tty;
+ unsigned int stat = SPORT_GET_STAT(up);
+
++ spin_lock(&up->port.lock);
++
+ /* Overflow in RX FIFO */
+ if (stat & ROVF) {
+ up->port.icount.overrun++;
+@@ -216,15 +205,16 @@ static irqreturn_t sport_uart_err_irq(in
+ }
+ /* These should not happen */
+ if (stat & (TOVF | TUVF | RUVF)) {
+- printk(KERN_ERR "SPORT Error:%s %s %s\n",
+- (stat & TOVF)?"TX overflow":"",
+- (stat & TUVF)?"TX underflow":"",
+- (stat & RUVF)?"RX underflow":"");
++ pr_err("SPORT Error:%s %s %s\n",
++ (stat & TOVF) ? "TX overflow" : "",
++ (stat & TUVF) ? "TX underflow" : "",
++ (stat & RUVF) ? "RX underflow" : "");
+ SPORT_PUT_TCR1(up, SPORT_GET_TCR1(up) & ~TSPEN);
+ SPORT_PUT_RCR1(up, SPORT_GET_RCR1(up) & ~RSPEN);
+ }
+ SSYNC();
+
++ spin_unlock(&up->port.lock);
+ return IRQ_HANDLED;
+ }
+
+@@ -232,60 +222,37 @@ static irqreturn_t sport_uart_err_irq(in
+ static int sport_startup(struct uart_port *port)
+ {
+ struct sport_uart_port *up = (struct sport_uart_port *)port;
+- char buffer[20];
+- int retval;
++ int ret;
+
+ pr_debug("%s enter\n", __func__);
+- snprintf(buffer, 20, "%s rx", up->name);
+- retval = request_irq(up->rx_irq, sport_uart_rx_irq, IRQF_SAMPLE_RANDOM, buffer, up);
+- if (retval) {
+- printk(KERN_ERR "Unable to request interrupt %s\n", buffer);
+- return retval;
++ ret = request_irq(up->port.irq, sport_uart_rx_irq, 0,
++ "SPORT_UART_RX", up);
++ if (ret) {
++ dev_err(port->dev, "unable to request SPORT RX interrupt\n");
++ return ret;
+ }
+
+- snprintf(buffer, 20, "%s tx", up->name);
+- retval = request_irq(up->tx_irq, sport_uart_tx_irq, IRQF_SAMPLE_RANDOM, buffer, up);
+- if (retval) {
+- printk(KERN_ERR "Unable to request interrupt %s\n", buffer);
++ ret = request_irq(up->port.irq+1, sport_uart_tx_irq, 0,
++ "SPORT_UART_TX", up);
++ if (ret) {
++ dev_err(port->dev, "unable to request SPORT TX interrupt\n");
+ goto fail1;
+ }
+
+- snprintf(buffer, 20, "%s err", up->name);
+- retval = request_irq(up->err_irq, sport_uart_err_irq, IRQF_SAMPLE_RANDOM, buffer, up);
+- if (retval) {
+- printk(KERN_ERR "Unable to request interrupt %s\n", buffer);
++ ret = request_irq(up->err_irq, sport_uart_err_irq, 0,
++ "SPORT_UART_STATUS", up);
++ if (ret) {
++ dev_err(port->dev, "unable to request SPORT status interrupt\n");
+ goto fail2;
+ }
+
+- if (port->line) {
+- if (peripheral_request_list(bfin_uart_pin_req_sport1, DRV_NAME))
+- goto fail3;
+- } else {
+- if (peripheral_request_list(bfin_uart_pin_req_sport0, DRV_NAME))
+- goto fail3;
+- }
+-
+- sport_uart_setup(up, get_sclk(), port->uartclk);
+-
+- /* Enable receive interrupt */
+- SPORT_PUT_RCR1(up, (SPORT_GET_RCR1(up) | RSPEN));
+- SSYNC();
+-
+ return 0;
++ fail2:
++ free_irq(up->port.irq+1, up);
++ fail1:
++ free_irq(up->port.irq, up);
+
+-
+-fail3:
+- printk(KERN_ERR DRV_NAME
+- ": Requesting Peripherals failed\n");
+-
+- free_irq(up->err_irq, up);
+-fail2:
+- free_irq(up->tx_irq, up);
+-fail1:
+- free_irq(up->rx_irq, up);
+-
+- return retval;
+-
++ return ret;
+ }
+
+ static void sport_uart_tx_chars(struct sport_uart_port *up)
+@@ -344,20 +311,17 @@ static void sport_set_mctrl(struct uart_
+ static void sport_stop_tx(struct uart_port *port)
+ {
+ struct sport_uart_port *up = (struct sport_uart_port *)port;
+- unsigned int stat;
+
+ pr_debug("%s enter\n", __func__);
+
+- stat = SPORT_GET_STAT(up);
+- while(!(stat & TXHRE)) {
+- udelay(1);
+- stat = SPORT_GET_STAT(up);
+- }
+ /* Although the hold register is empty, last byte is still in shift
+- * register and not sent out yet. If baud rate is lower than default,
+- * delay should be longer. For example, if the baud rate is 9600,
+- * the delay must be at least 2ms by experience */
+- udelay(500);
++ * register and not sent out yet. So, put a dummy data into TX FIFO.
++ * Then, sport tx stops when last byte is shift out and the dummy
++ * data is moved into the shift register.
++ */
++ SPORT_PUT_TX(up, 0xffff);
++ while (!(SPORT_GET_STAT(up) & TXHRE))
++ cpu_relax();
+
+ SPORT_PUT_TCR1(up, (SPORT_GET_TCR1(up) & ~TSPEN));
+ SSYNC();
+@@ -370,6 +334,7 @@ static void sport_start_tx(struct uart_p
+ struct sport_uart_port *up = (struct sport_uart_port *)port;
+
+ pr_debug("%s enter\n", __func__);
++
+ /* Write data into SPORT FIFO before enable SPROT to transmit */
+ sport_uart_tx_chars(up);
+
+@@ -403,37 +368,24 @@ static void sport_shutdown(struct uart_p
+ {
+ struct sport_uart_port *up = (struct sport_uart_port *)port;
+
+- pr_debug("%s enter\n", __func__);
++ dev_dbg(port->dev, "%s enter\n", __func__);
+
+ /* Disable sport */
+ SPORT_PUT_TCR1(up, (SPORT_GET_TCR1(up) & ~TSPEN));
+ SPORT_PUT_RCR1(up, (SPORT_GET_RCR1(up) & ~RSPEN));
+ SSYNC();
+
+- if (port->line) {
+- peripheral_free_list(bfin_uart_pin_req_sport1);
+- } else {
+- peripheral_free_list(bfin_uart_pin_req_sport0);
+- }
+-
+- free_irq(up->rx_irq, up);
+- free_irq(up->tx_irq, up);
++ free_irq(up->port.irq, up);
++ free_irq(up->port.irq+1, up);
+ free_irq(up->err_irq, up);
+ }
+
+-static void sport_set_termios(struct uart_port *port,
+- struct ktermios *termios, struct ktermios *old)
+-{
+- pr_debug("%s enter, c_cflag:%08x\n", __func__, termios->c_cflag);
+- uart_update_timeout(port, CS8 ,port->uartclk);
+-}
+-
+ static const char *sport_type(struct uart_port *port)
+ {
+ struct sport_uart_port *up = (struct sport_uart_port *)port;
+
+ pr_debug("%s enter\n", __func__);
+- return up->name;
++ return up->port.type == PORT_BFIN_SPORT ? "BFIN-SPORT-UART" : NULL;
+ }
+
+ static void sport_release_port(struct uart_port *port)
+@@ -461,6 +413,110 @@ static int sport_verify_port(struct uart
+ return 0;
+ }
+
++static void sport_set_termios(struct uart_port *port,
++ struct ktermios *termios, struct ktermios *old)
++{
++ struct sport_uart_port *up = (struct sport_uart_port *)port;
++ unsigned long flags;
++ int i;
++
++ pr_debug("%s enter, c_cflag:%08x\n", __func__, termios->c_cflag);
++
++ switch (termios->c_cflag & CSIZE) {
++ case CS8:
++ up->csize = 8;
++ break;
++ case CS7:
++ up->csize = 7;
++ break;
++ case CS6:
++ up->csize = 6;
++ break;
++ case CS5:
++ up->csize = 5;
++ break;
++ default:
++ pr_warning("requested word length not supported\n");
++ }
++
++ if (termios->c_cflag & CSTOPB) {
++ up->stopb = 1;
++ }
++ if (termios->c_cflag & PARENB) {
++ pr_warning("PAREN bits is not supported yet\n");
++ /* up->parib = 1; */
++ }
++
++ port->read_status_mask = OE;
++ if (termios->c_iflag & INPCK)
++ port->read_status_mask |= (FE | PE);
++ if (termios->c_iflag & (BRKINT | PARMRK))
++ port->read_status_mask |= BI;
++
++ /*
++ * Characters to ignore
++ */
++ port->ignore_status_mask = 0;
++ if (termios->c_iflag & IGNPAR)
++ port->ignore_status_mask |= FE | PE;
++ if (termios->c_iflag & IGNBRK) {
++ port->ignore_status_mask |= BI;
++ /*
++ * If we're ignoring parity and break indicators,
++ * ignore overruns too (for real raw support).
++ */
++ if (termios->c_iflag & IGNPAR)
++ port->ignore_status_mask |= OE;
++ }
++
++ /* RX extract mask */
++ up->rxmask = 0x01 | (((up->csize + up->stopb) * 2 - 1) << 0x8);
++ /* TX masks, 8 bit data and 1 bit stop for example:
++ * mask1 = b#0111111110
++ * mask2 = b#1000000000
++ */
++ for (i = 0, up->txmask1 = 0; i < up->csize; i++)
++ up->txmask1 |= (1<<i);
++ up->txmask2 = (1<<i);
++ if (up->stopb) {
++ ++i;
++ up->txmask2 |= (1<<i);
++ }
++ up->txmask1 <<= 1;
++ up->txmask2 <<= 1;
++ /* uart baud rate */
++ port->uartclk = uart_get_baud_rate(port, termios, old, 0, get_sclk()/16);
++
++ spin_lock_irqsave(&up->port.lock, flags);
++
++ /* Disable UART */
++ SPORT_PUT_TCR1(up, SPORT_GET_TCR1(up) & ~TSPEN);
++ SPORT_PUT_RCR1(up, SPORT_GET_RCR1(up) & ~RSPEN);
++
++ sport_uart_setup(up, up->csize + up->stopb, port->uartclk);
++
++ /* driver TX line high after config, one dummy data is
++ * necessary to stop sport after shift one byte
++ */
++ SPORT_PUT_TX(up, 0xffff);
++ SPORT_PUT_TX(up, 0xffff);
++ SPORT_PUT_TCR1(up, (SPORT_GET_TCR1(up) | TSPEN));
++ SSYNC();
++ while (!(SPORT_GET_STAT(up) & TXHRE))
++ cpu_relax();
++ SPORT_PUT_TCR1(up, SPORT_GET_TCR1(up) & ~TSPEN);
++ SSYNC();
++
++ /* Port speed changed, update the per-port timeout. */
++ uart_update_timeout(port, termios->c_cflag, port->uartclk);
++
++ /* Enable sport rx */
++ SPORT_PUT_RCR1(up, SPORT_GET_RCR1(up) | RSPEN);
++ SSYNC();
++
++ spin_unlock_irqrestore(&up->port.lock, flags);
++}
++
+ struct uart_ops sport_uart_ops = {
+ .tx_empty = sport_tx_empty,
+ .set_mctrl = sport_set_mctrl,
+@@ -480,138 +536,319 @@ struct uart_ops sport_uart_ops = {
+ .verify_port = sport_verify_port,
+ };
+
+-static struct sport_uart_port sport_uart_ports[] = {
+- { /* SPORT 0 */
+- .name = "SPORT0",
+- .tx_irq = IRQ_SPORT0_TX,
+- .rx_irq = IRQ_SPORT0_RX,
+- .err_irq= IRQ_SPORT0_ERROR,
+- .port = {
+- .type = PORT_BFIN_SPORT,
+- .iotype = UPIO_MEM,
+- .membase = (void __iomem *)SPORT0_TCR1,
+- .mapbase = SPORT0_TCR1,
+- .irq = IRQ_SPORT0_RX,
+- .uartclk = CONFIG_SPORT_BAUD_RATE,
+- .fifosize = 8,
+- .ops = &sport_uart_ops,
+- .line = 0,
+- },
+- }, { /* SPORT 1 */
+- .name = "SPORT1",
+- .tx_irq = IRQ_SPORT1_TX,
+- .rx_irq = IRQ_SPORT1_RX,
+- .err_irq= IRQ_SPORT1_ERROR,
+- .port = {
+- .type = PORT_BFIN_SPORT,
+- .iotype = UPIO_MEM,
+- .membase = (void __iomem *)SPORT1_TCR1,
+- .mapbase = SPORT1_TCR1,
+- .irq = IRQ_SPORT1_RX,
+- .uartclk = CONFIG_SPORT_BAUD_RATE,
+- .fifosize = 8,
+- .ops = &sport_uart_ops,
+- .line = 1,
+- },
+- }
++#define BFIN_SPORT_UART_MAX_PORTS 4
++
++static struct sport_uart_port *bfin_sport_uart_ports[BFIN_SPORT_UART_MAX_PORTS];
++
++#ifdef CONFIG_SERIAL_BFIN_SPORT_CONSOLE
++static int __init
++sport_uart_console_setup(struct console *co, char *options)
++{
++ struct sport_uart_port *up;
++ int baud = 57600;
++ int bits = 8;
++ int parity = 'n';
++ int flow = 'n';
++
++ /* Check whether an invalid uart number has been specified */
++ if (co->index < 0 || co->index >= BFIN_SPORT_UART_MAX_PORTS)
++ return -ENODEV;
++
++ up = bfin_sport_uart_ports[co->index];
++ if (!up)
++ return -ENODEV;
++
++ if (options)
++ uart_parse_options(options, &baud, &parity, &bits, &flow);
++
++ return uart_set_options(&up->port, co, baud, parity, bits, flow);
++}
++
++static void sport_uart_console_putchar(struct uart_port *port, int ch)
++{
++ struct sport_uart_port *up = (struct sport_uart_port *)port;
++
++ while (SPORT_GET_STAT(up) & TXF)
++ barrier();
++
++ tx_one_byte(up, ch);
++}
++
++/*
++ * Interrupts are disabled on entering
++ */
++static void
++sport_uart_console_write(struct console *co, const char *s, unsigned int count)
++{
++ struct sport_uart_port *up = bfin_sport_uart_ports[co->index];
++ unsigned long flags;
++
++ spin_lock_irqsave(&up->port.lock, flags);
++
++ if (SPORT_GET_TCR1(up) & TSPEN)
++ uart_console_write(&up->port, s, count, sport_uart_console_putchar);
++ else {
++ /* dummy data to start sport */
++ while (SPORT_GET_STAT(up) & TXF)
++ barrier();
++ SPORT_PUT_TX(up, 0xffff);
++ /* Enable transmit, then an interrupt will generated */
++ SPORT_PUT_TCR1(up, (SPORT_GET_TCR1(up) | TSPEN));
++ SSYNC();
++
++ uart_console_write(&up->port, s, count, sport_uart_console_putchar);
++
++ /* Although the hold register is empty, last byte is still in shift
++ * register and not sent out yet. So, put a dummy data into TX FIFO.
++ * Then, sport tx stops when last byte is shift out and the dummy
++ * data is moved into the shift register.
++ */
++ while (SPORT_GET_STAT(up) & TXF)
++ barrier();
++ SPORT_PUT_TX(up, 0xffff);
++ while (!(SPORT_GET_STAT(up) & TXHRE))
++ barrier();
++
++ /* Stop sport tx transfer */
++ SPORT_PUT_TCR1(up, (SPORT_GET_TCR1(up) & ~TSPEN));
++ SSYNC();
++ }
++
++ spin_unlock_irqrestore(&up->port.lock, flags);
++}
++
++static struct uart_driver sport_uart_reg;
++
++static struct console sport_uart_console = {
++ .name = DEVICE_NAME,
++ .write = sport_uart_console_write,
++ .device = uart_console_device,
++ .setup = sport_uart_console_setup,
++ .flags = CON_PRINTBUFFER,
++ .index = -1,
++ .data = &sport_uart_reg,
+ };
+
++#define SPORT_UART_CONSOLE (&sport_uart_console)
++#else
++#define SPORT_UART_CONSOLE NULL
++#endif /* CONFIG_SERIAL_BFIN_SPORT_CONSOLE */
++
++
+ static struct uart_driver sport_uart_reg = {
+ .owner = THIS_MODULE,
+- .driver_name = "SPORT-UART",
+- .dev_name = "ttySS",
++ .driver_name = DRV_NAME,
++ .dev_name = DEVICE_NAME,
+ .major = 204,
+ .minor = 84,
+- .nr = ARRAY_SIZE(sport_uart_ports),
+- .cons = NULL,
++ .nr = BFIN_SPORT_UART_MAX_PORTS,
++ .cons = SPORT_UART_CONSOLE,
+ };
+
+-static int sport_uart_suspend(struct platform_device *dev, pm_message_t state)
++#ifdef CONFIG_PM
++static int sport_uart_suspend(struct device *dev)
+ {
+- struct sport_uart_port *sport = platform_get_drvdata(dev);
++ struct sport_uart_port *sport = dev_get_drvdata(dev);
+
+- pr_debug("%s enter\n", __func__);
++ dev_dbg(dev, "%s enter\n", __func__);
+ if (sport)
+ uart_suspend_port(&sport_uart_reg, &sport->port);
+
+ return 0;
+ }
+
+-static int sport_uart_resume(struct platform_device *dev)
++static int sport_uart_resume(struct device *dev)
+ {
+- struct sport_uart_port *sport = platform_get_drvdata(dev);
++ struct sport_uart_port *sport = dev_get_drvdata(dev);
+
+- pr_debug("%s enter\n", __func__);
++ dev_dbg(dev, "%s enter\n", __func__);
+ if (sport)
+ uart_resume_port(&sport_uart_reg, &sport->port);
+
+ return 0;
+ }
+
+-static int sport_uart_probe(struct platform_device *dev)
++static struct dev_pm_ops bfin_sport_uart_dev_pm_ops = {
++ .suspend = sport_uart_suspend,
++ .resume = sport_uart_resume,
++};
++#endif
++
++static int __devinit sport_uart_probe(struct platform_device *pdev)
+ {
+- pr_debug("%s enter\n", __func__);
+- sport_uart_ports[dev->id].port.dev = &dev->dev;
+- uart_add_one_port(&sport_uart_reg, &sport_uart_ports[dev->id].port);
+- platform_set_drvdata(dev, &sport_uart_ports[dev->id]);
++ struct resource *res;
++ struct sport_uart_port *sport;
++ int ret = 0;
++
++ dev_dbg(&pdev->dev, "%s enter\n", __func__);
++
++ if (pdev->id < 0 || pdev->id >= BFIN_SPORT_UART_MAX_PORTS) {
++ dev_err(&pdev->dev, "Wrong sport uart platform device id.\n");
++ return -ENOENT;
++ }
++
++ if (bfin_sport_uart_ports[pdev->id] == NULL) {
++ bfin_sport_uart_ports[pdev->id] =
++ kmalloc(sizeof(struct sport_uart_port), GFP_KERNEL);
++ sport = bfin_sport_uart_ports[pdev->id];
++ if (!sport) {
++ dev_err(&pdev->dev,
++ "Fail to kmalloc sport_uart_port\n");
++ return -ENOMEM;
++ }
++
++ ret = peripheral_request_list(
++ (unsigned short *)pdev->dev.platform_data, DRV_NAME);
++ if (ret) {
++ dev_err(&pdev->dev,
++ "Fail to request SPORT peripherals\n");
++ goto out_error_free_mem;
++ }
++
++ spin_lock_init(&sport->port.lock);
++ sport->port.fifosize = SPORT_TX_FIFO_SIZE,
++ sport->port.ops = &sport_uart_ops;
++ sport->port.line = pdev->id;
++ sport->port.iotype = UPIO_MEM;
++ sport->port.flags = UPF_BOOT_AUTOCONF;
++
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ if (res == NULL) {
++ dev_err(&pdev->dev, "Cannot get IORESOURCE_MEM\n");
++ ret = -ENOENT;
++ goto out_error_free_peripherals;
++ }
++
++ sport->port.membase = ioremap(res->start,
++ res->end - res->start);
++ if (!sport->port.membase) {
++ dev_err(&pdev->dev, "Cannot map sport IO\n");
++ ret = -ENXIO;
++ goto out_error_free_peripherals;
++ }
++
++ sport->port.irq = platform_get_irq(pdev, 0);
++ if (sport->port.irq < 0) {
++ dev_err(&pdev->dev, "No sport RX/TX IRQ specified\n");
++ ret = -ENOENT;
++ goto out_error_unmap;
++ }
++
++ sport->err_irq = platform_get_irq(pdev, 1);
++ if (sport->err_irq < 0) {
++ dev_err(&pdev->dev, "No sport status IRQ specified\n");
++ ret = -ENOENT;
++ goto out_error_unmap;
++ }
++ }
++
++#ifdef CONFIG_SERIAL_BFIN_SPORT_CONSOLE
++ if (!is_early_platform_device(pdev)) {
++#endif
++ sport = bfin_sport_uart_ports[pdev->id];
++ sport->port.dev = &pdev->dev;
++ dev_set_drvdata(&pdev->dev, sport);
++ ret = uart_add_one_port(&sport_uart_reg, &sport->port);
++#ifdef CONFIG_SERIAL_BFIN_SPORT_CONSOLE
++ }
++#endif
++ if (!ret)
++ return 0;
+
+- return 0;
++ if (sport) {
++out_error_unmap:
++ iounmap(sport->port.membase);
++out_error_free_peripherals:
++ peripheral_free_list(
++ (unsigned short *)pdev->dev.platform_data);
++out_error_free_mem:
++ kfree(sport);
++ bfin_sport_uart_ports[pdev->id] = NULL;
++ }
++
++ return ret;
+ }
+
+-static int sport_uart_remove(struct platform_device *dev)
++static int __devexit sport_uart_remove(struct platform_device *pdev)
+ {
+- struct sport_uart_port *sport = platform_get_drvdata(dev);
++ struct sport_uart_port *sport = platform_get_drvdata(pdev);
+
+- pr_debug("%s enter\n", __func__);
+- platform_set_drvdata(dev, NULL);
++ dev_dbg(&pdev->dev, "%s enter\n", __func__);
++ dev_set_drvdata(&pdev->dev, NULL);
+
+- if (sport)
++ if (sport) {
+ uart_remove_one_port(&sport_uart_reg, &sport->port);
++ iounmap(sport->port.membase);
++ peripheral_free_list(
++ (unsigned short *)pdev->dev.platform_data);
++ kfree(sport);
++ bfin_sport_uart_ports[pdev->id] = NULL;
++ }
+
+ return 0;
+ }
+
+ static struct platform_driver sport_uart_driver = {
+ .probe = sport_uart_probe,
+- .remove = sport_uart_remove,
+- .suspend = sport_uart_suspend,
+- .resume = sport_uart_resume,
++ .remove = __devexit_p(sport_uart_remove),
+ .driver = {
+ .name = DRV_NAME,
++#ifdef CONFIG_PM
++ .pm = &bfin_sport_uart_dev_pm_ops,
++#endif
+ },
+ };
+
++#ifdef CONFIG_SERIAL_BFIN_SPORT_CONSOLE
++static __initdata struct early_platform_driver early_sport_uart_driver = {
++ .class_str = DRV_NAME,
++ .pdrv = &sport_uart_driver,
++ .requested_id = EARLY_PLATFORM_ID_UNSET,
++};
++
++static int __init sport_uart_rs_console_init(void)
++{
++ early_platform_driver_register(&early_sport_uart_driver, DRV_NAME);
++
++ early_platform_driver_probe(DRV_NAME, BFIN_SPORT_UART_MAX_PORTS, 0);
++
++ register_console(&sport_uart_console);
++
++ return 0;
++}
++console_initcall(sport_uart_rs_console_init);
++#endif
++
+ static int __init sport_uart_init(void)
+ {
+ int ret;
+
+- pr_debug("%s enter\n", __func__);
++ pr_info("Serial: Blackfin uart over sport driver\n");
++
+ ret = uart_register_driver(&sport_uart_reg);
+- if (ret != 0) {
+- printk(KERN_ERR "Failed to register %s:%d\n",
++ if (ret) {
++ pr_err("failed to register %s:%d\n",
+ sport_uart_reg.driver_name, ret);
+ return ret;
+ }
+
+ ret = platform_driver_register(&sport_uart_driver);
+- if (ret != 0) {
+- printk(KERN_ERR "Failed to register sport uart driver:%d\n", ret);
++ if (ret) {
++ pr_err("failed to register sport uart driver:%d\n", ret);
+ uart_unregister_driver(&sport_uart_reg);
+ }
+
+-
+- pr_debug("%s exit\n", __func__);
+ return ret;
+ }
++module_init(sport_uart_init);
+
+ static void __exit sport_uart_exit(void)
+ {
+- pr_debug("%s enter\n", __func__);
+ platform_driver_unregister(&sport_uart_driver);
+ uart_unregister_driver(&sport_uart_reg);
+ }
+-
+-module_init(sport_uart_init);
+ module_exit(sport_uart_exit);
+
++MODULE_AUTHOR("Sonic Zhang, Roy Huang");
++MODULE_DESCRIPTION("Blackfin serial over SPORT driver");
+ MODULE_LICENSE("GPL");
+--- a/drivers/serial/bfin_sport_uart.h
++++ b/drivers/serial/bfin_sport_uart.h
+@@ -1,29 +1,23 @@
+ /*
+- * File: linux/drivers/serial/bfin_sport_uart.h
++ * Blackfin On-Chip Sport Emulated UART Driver
+ *
+- * Based on: include/asm-blackfin/mach-533/bfin_serial_5xx.h
+- * Author: Roy Huang <roy.huang>analog.com>
++ * Copyright 2006-2008 Analog Devices Inc.
+ *
+- * Created: Nov 22, 2006
+- * Copyright: (C) Analog Device Inc.
+- * Description: this driver enable SPORTs on Blackfin emulate UART.
++ * Enter bugs at http://blackfin.uclinux.org/
+ *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, see the file COPYING, or write
+- * to the Free Software Foundation, Inc.,
+- * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ * Licensed under the GPL-2 or later.
+ */
+
++/*
++ * This driver and the hardware supported are in term of EE-191 of ADI.
++ * http://www.analog.com/UploadedFiles/Application_Notes/399447663EE191.pdf
++ * This application note describe how to implement a UART on a Sharc DSP,
++ * but this driver is implemented on Blackfin Processor.
++ * Transmit Frame Sync is not used by this driver to transfer data out.
++ */
++
++#ifndef _BFIN_SPORT_UART_H
++#define _BFIN_SPORT_UART_H
+
+ #define OFFSET_TCR1 0x00 /* Transmit Configuration 1 Register */
+ #define OFFSET_TCR2 0x04 /* Transmit Configuration 2 Register */
+@@ -61,3 +55,7 @@
+ #define SPORT_PUT_RCLKDIV(sport, v) bfin_write16(((sport)->port.membase + OFFSET_RCLKDIV), v)
+ #define SPORT_PUT_RFSDIV(sport, v) bfin_write16(((sport)->port.membase + OFFSET_RFSDIV), v)
+ #define SPORT_PUT_STAT(sport, v) bfin_write16(((sport)->port.membase + OFFSET_STAT), v)
++
++#define SPORT_TX_FIFO_SIZE 8
++
++#endif /* _BFIN_SPORT_UART_H */
+--- a/drivers/serial/Kconfig
++++ b/drivers/serial/Kconfig
+@@ -1418,38 +1418,34 @@ config SERIAL_BFIN_SPORT
+ To compile this driver as a module, choose M here: the
+ module will be called bfin_sport_uart.
+
+-choice
+- prompt "Baud rate for Blackfin SPORT UART"
+- depends on SERIAL_BFIN_SPORT
+- default SERIAL_SPORT_BAUD_RATE_57600
+- help
+- Choose a baud rate for the SPORT UART, other uart settings are
+- 8 bit, 1 stop bit, no parity, no flow control.
+-
+-config SERIAL_SPORT_BAUD_RATE_115200
+- bool "115200"
+-
+-config SERIAL_SPORT_BAUD_RATE_57600
+- bool "57600"
++config SERIAL_BFIN_SPORT_CONSOLE
++ bool "Console on Blackfin sport emulated uart"
++ depends on SERIAL_BFIN_SPORT=y
++ select SERIAL_CORE_CONSOLE
+
+-config SERIAL_SPORT_BAUD_RATE_38400
+- bool "38400"
++config SERIAL_BFIN_SPORT0_UART
++ bool "Enable UART over SPORT0"
++ depends on SERIAL_BFIN_SPORT && !(BF542 || BF542M || BF544 || BF544M)
++ help
++ Enable UART over SPORT0
+
+-config SERIAL_SPORT_BAUD_RATE_19200
+- bool "19200"
++config SERIAL_BFIN_SPORT1_UART
++ bool "Enable UART over SPORT1"
++ depends on SERIAL_BFIN_SPORT
++ help
++ Enable UART over SPORT1
+
+-config SERIAL_SPORT_BAUD_RATE_9600
+- bool "9600"
+-endchoice
++config SERIAL_BFIN_SPORT2_UART
++ bool "Enable UART over SPORT2"
++ depends on SERIAL_BFIN_SPORT && (BF54x || BF538 || BF539)
++ help
++ Enable UART over SPORT2
+
+-config SPORT_BAUD_RATE
+- int
+- depends on SERIAL_BFIN_SPORT
+- default 115200 if (SERIAL_SPORT_BAUD_RATE_115200)
+- default 57600 if (SERIAL_SPORT_BAUD_RATE_57600)
+- default 38400 if (SERIAL_SPORT_BAUD_RATE_38400)
+- default 19200 if (SERIAL_SPORT_BAUD_RATE_19200)
+- default 9600 if (SERIAL_SPORT_BAUD_RATE_9600)
++config SERIAL_BFIN_SPORT3_UART
++ bool "Enable UART over SPORT3"
++ depends on SERIAL_BFIN_SPORT && (BF54x || BF538 || BF539)
++ help
++ Enable UART over SPORT3
+
+ config SERIAL_TIMBERDALE
+ tristate "Support for timberdale UART"
diff --git a/tty/serial-fix-test-of-unsigned.patch b/tty/serial-fix-test-of-unsigned.patch
new file mode 100644
index 00000000000000..6c83462cb3f4aa
--- /dev/null
+++ b/tty/serial-fix-test-of-unsigned.patch
@@ -0,0 +1,72 @@
+From akpm@linux-foundation.org Tue Dec 22 11:42:07 2009
+From: akpm@linux-foundation.org
+Date: Mon, 21 Dec 2009 16:26:49 -0800
+Subject: serial: fix test of unsigned
+To: greg@kroah.com
+Cc: alan@lxorguk.ukuu.org.uk, akpm@linux-foundation.org, roel.kluin@gmail.com
+Message-ID: <200912220026.nBM0QnCN005296@imap1.linux-foundation.org>
+
+
+From: Roel Kluin <roel.kluin@gmail.com>
+
+The variables were unsigned so the tests did not work.
+
+Signed-off-by: Roel Kluin <roel.kluin@gmail.com>
+Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/serial/msm_serial.c | 6 ++++--
+ drivers/serial/timbuart.c | 7 ++++---
+ 2 files changed, 8 insertions(+), 5 deletions(-)
+
+--- a/drivers/serial/msm_serial.c
++++ b/drivers/serial/msm_serial.c
+@@ -691,6 +691,7 @@ static int __init msm_serial_probe(struc
+ struct msm_port *msm_port;
+ struct resource *resource;
+ struct uart_port *port;
++ int irq;
+
+ if (unlikely(pdev->id < 0 || pdev->id >= UART_NR))
+ return -ENXIO;
+@@ -711,9 +712,10 @@ static int __init msm_serial_probe(struc
+ return -ENXIO;
+ port->mapbase = resource->start;
+
+- port->irq = platform_get_irq(pdev, 0);
+- if (unlikely(port->irq < 0))
++ irq = platform_get_irq(pdev, 0);
++ if (unlikely(irq < 0))
+ return -ENXIO;
++ port->irq = irq;
+
+ platform_set_drvdata(pdev, port);
+
+--- a/drivers/serial/timbuart.c
++++ b/drivers/serial/timbuart.c
+@@ -421,7 +421,7 @@ static struct uart_driver timbuart_drive
+
+ static int timbuart_probe(struct platform_device *dev)
+ {
+- int err;
++ int err, irq;
+ struct timbuart_port *uart;
+ struct resource *iomem;
+
+@@ -453,11 +453,12 @@ static int timbuart_probe(struct platfor
+ uart->port.mapbase = iomem->start;
+ uart->port.membase = NULL;
+
+- uart->port.irq = platform_get_irq(dev, 0);
+- if (uart->port.irq < 0) {
++ irq = platform_get_irq(dev, 0);
++ if (irq < 0) {
+ err = -EINVAL;
+ goto err_register;
+ }
++ uart->port.irq = irq;
+
+ tasklet_init(&uart->tasklet, timbuart_tasklet, (unsigned long)uart);
+
diff --git a/tty/serial-imx-fix-null-dereference-oops-when-pdata-null.patch b/tty/serial-imx-fix-null-dereference-oops-when-pdata-null.patch
new file mode 100644
index 00000000000000..beeb9332a17532
--- /dev/null
+++ b/tty/serial-imx-fix-null-dereference-oops-when-pdata-null.patch
@@ -0,0 +1,63 @@
+From akpm@linux-foundation.org Tue Dec 22 11:41:06 2009
+From: Baruch Siach <baruch@tkos.co.il>
+Date: Mon, 21 Dec 2009 16:26:46 -0800
+Subject: serial: imx: fix NULL dereference Oops when pdata == NULL
+To: greg@kroah.com
+Cc: alan@lxorguk.ukuu.org.uk, akpm@linux-foundation.org, baruch@tkos.co.il, alan@linux.intel.com, dg@emlix.com, fg@emlix.com, os@emlix.com, s.hauer@pengutronix.de, stable@kernel.org
+Message-ID: <200912220026.nBM0QkGe005290@imap1.linux-foundation.org>
+
+
+From: Baruch Siach <baruch@tkos.co.il>
+
+The platform code doesn't have to provide platform data to get sensible
+default behaviour from the imx serial driver.
+
+This patch does not handle NULL dereference in the IrDA case, which still
+requires a valid platform data pointer (in imx_startup()/imx_shutdown()),
+since I don't know whether there is a sensible default behaviour, or
+should the operation just fail cleanly.
+
+Signed-off-by: Baruch Siach <baruch@tkos.co.il>
+Cc: Baruch Siach <baruch@tkos.co.il>
+Cc: Alan Cox <alan@linux.intel.com>
+Cc: Sascha Hauer <s.hauer@pengutronix.de>
+Cc: Oskar Schirmer <os@emlix.com>
+Cc: Fabian Godehardt <fg@emlix.com>
+Cc: Daniel Gl�ckner <dg@emlix.com>
+Cc: stable <stable@kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/serial/imx.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/drivers/serial/imx.c
++++ b/drivers/serial/imx.c
+@@ -1279,7 +1279,7 @@ static int serial_imx_probe(struct platf
+ sport->use_irda = 1;
+ #endif
+
+- if (pdata->init) {
++ if (pdata && pdata->init) {
+ ret = pdata->init(pdev);
+ if (ret)
+ goto clkput;
+@@ -1292,7 +1292,7 @@ static int serial_imx_probe(struct platf
+
+ return 0;
+ deinit:
+- if (pdata->exit)
++ if (pdata && pdata->exit)
+ pdata->exit(pdev);
+ clkput:
+ clk_put(sport->clk);
+@@ -1321,7 +1321,7 @@ static int serial_imx_remove(struct plat
+
+ clk_disable(sport->clk);
+
+- if (pdata->exit)
++ if (pdata && pdata->exit)
+ pdata->exit(pdev);
+
+ iounmap(sport->port.membase);
diff --git a/tty/serial-isicom.c-use-pr_fmt-and-pr_-level.patch b/tty/serial-isicom.c-use-pr_fmt-and-pr_-level.patch
new file mode 100644
index 00000000000000..1abbb3809f2269
--- /dev/null
+++ b/tty/serial-isicom.c-use-pr_fmt-and-pr_-level.patch
@@ -0,0 +1,175 @@
+From akpm@linux-foundation.org Tue Dec 22 11:44:37 2009
+From: Joe Perches <joe@perches.com>
+Date: Wed, 09 Dec 2009 12:34:16 -0800
+Subject: serial: isicom.c: use pr_fmt and pr_<level>
+To: greg@kroah.com
+Cc: alan@lxorguk.ukuu.org.uk, akpm@linux-foundation.org, joe@perches.com, jirislaby@gmail.com
+Message-ID: <200912092034.nB9KYGjI010684@imap1.linux-foundation.org>
+
+
+From: Joe Perches <joe@perches.com>
+
+Add #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+Convert printks to pr_<level>
+Convert some embedded function names to %s...__func__
+Remove a period after exclamation points.
+Remove #define pr_dbg which could be used by future kernel.h includes
+
+Signed-off-by: Joe Perches <joe@perches.com>
+Acked-by: Jiri Slaby <jirislaby@gmail.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/char/isicom.c | 49 ++++++++++++++++++++++++++-----------------------
+ 1 file changed, 26 insertions(+), 23 deletions(-)
+
+--- a/drivers/char/isicom.c
++++ b/drivers/char/isicom.c
+@@ -113,6 +113,8 @@
+ * 64-bit verification
+ */
+
++#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
++
+ #include <linux/module.h>
+ #include <linux/firmware.h>
+ #include <linux/kernel.h>
+@@ -140,7 +142,6 @@
+ #define InterruptTheCard(base) outw(0, (base) + 0xc)
+ #define ClearInterrupt(base) inw((base) + 0x0a)
+
+-#define pr_dbg(str...) pr_debug("ISICOM: " str)
+ #ifdef DEBUG
+ #define isicom_paranoia_check(a, b, c) __isicom_paranoia_check((a), (b), (c))
+ #else
+@@ -249,8 +250,7 @@ static int lock_card(struct isi_board *c
+ spin_unlock_irqrestore(&card->card_lock, card->flags);
+ msleep(10);
+ }
+- printk(KERN_WARNING "ISICOM: Failed to lock Card (0x%lx)\n",
+- card->base);
++ pr_warning("Failed to lock Card (0x%lx)\n", card->base);
+
+ return 0; /* Failed to acquire the card! */
+ }
+@@ -379,13 +379,13 @@ static inline int __isicom_paranoia_chec
+ char *name, const char *routine)
+ {
+ if (!port) {
+- printk(KERN_WARNING "ISICOM: Warning: bad isicom magic for "
+- "dev %s in %s.\n", name, routine);
++ pr_warning("Warning: bad isicom magic for dev %s in %s.\n",
++ name, routine);
+ return 1;
+ }
+ if (port->magic != ISICOM_MAGIC) {
+- printk(KERN_WARNING "ISICOM: Warning: NULL isicom port for "
+- "dev %s in %s.\n", name, routine);
++ pr_warning("Warning: NULL isicom port for dev %s in %s.\n",
++ name, routine);
+ return 1;
+ }
+
+@@ -450,8 +450,8 @@ static void isicom_tx(unsigned long _dat
+ if (!(inw(base + 0x02) & (1 << port->channel)))
+ continue;
+
+- pr_dbg("txing %d bytes, port%d.\n", txcount,
+- port->channel + 1);
++ pr_debug("txing %d bytes, port%d.\n",
++ txcount, port->channel + 1);
+ outw((port->channel << isi_card[card].shift_count) | txcount,
+ base);
+ residue = NO;
+@@ -547,8 +547,8 @@ static irqreturn_t isicom_interrupt(int
+ byte_count = header & 0xff;
+
+ if (channel + 1 > card->port_count) {
+- printk(KERN_WARNING "ISICOM: isicom_interrupt(0x%lx): "
+- "%d(channel) > port_count.\n", base, channel+1);
++ pr_warning("%s(0x%lx): %d(channel) > port_count.\n",
++ __func__, base, channel+1);
+ outw(0x0000, base+0x04); /* enable interrupts */
+ spin_unlock(&card->card_lock);
+ return IRQ_HANDLED;
+@@ -582,14 +582,15 @@ static irqreturn_t isicom_interrupt(int
+ if (port->status & ISI_DCD) {
+ if (!(header & ISI_DCD)) {
+ /* Carrier has been lost */
+- pr_dbg("interrupt: DCD->low.\n"
+- );
++ pr_debug("%s: DCD->low.\n",
++ __func__);
+ port->status &= ~ISI_DCD;
+ tty_hangup(tty);
+ }
+ } else if (header & ISI_DCD) {
+ /* Carrier has been detected */
+- pr_dbg("interrupt: DCD->high.\n");
++ pr_debug("%s: DCD->high.\n",
++ __func__);
+ port->status |= ISI_DCD;
+ wake_up_interruptible(&port->port.open_wait);
+ }
+@@ -641,17 +642,19 @@ static irqreturn_t isicom_interrupt(int
+ break;
+
+ case 2: /* Statistics */
+- pr_dbg("isicom_interrupt: stats!!!.\n");
++ pr_debug("%s: stats!!!\n", __func__);
+ break;
+
+ default:
+- pr_dbg("Intr: Unknown code in status packet.\n");
++ pr_debug("%s: Unknown code in status packet.\n",
++ __func__);
+ break;
+ }
+ } else { /* Data Packet */
+
+ count = tty_prepare_flip_string(tty, &rp, byte_count & ~1);
+- pr_dbg("Intr: Can rx %d of %d bytes.\n", count, byte_count);
++ pr_debug("%s: Can rx %d of %d bytes.\n",
++ __func__, count, byte_count);
+ word_count = count >> 1;
+ insw(base, rp, word_count);
+ byte_count -= (word_count << 1);
+@@ -661,8 +664,8 @@ static irqreturn_t isicom_interrupt(int
+ byte_count -= 2;
+ }
+ if (byte_count > 0) {
+- pr_dbg("Intr(0x%lx:%d): Flip buffer overflow! dropping "
+- "bytes...\n", base, channel + 1);
++ pr_debug("%s(0x%lx:%d): Flip buffer overflow! dropping bytes...\n",
++ __func__, base, channel + 1);
+ /* drain out unread xtra data */
+ while (byte_count > 0) {
+ inw(base);
+@@ -888,8 +891,8 @@ static void isicom_shutdown_port(struct
+ struct isi_board *card = port->card;
+
+ if (--card->count < 0) {
+- pr_dbg("isicom_shutdown_port: bad board(0x%lx) count %d.\n",
+- card->base, card->count);
++ pr_debug("%s: bad board(0x%lx) count %d.\n",
++ __func__, card->base, card->count);
+ card->count = 0;
+ }
+ /* last port was closed, shutdown that board too */
+@@ -1681,13 +1684,13 @@ static int __init isicom_init(void)
+
+ retval = tty_register_driver(isicom_normal);
+ if (retval) {
+- pr_dbg("Couldn't register the dialin driver\n");
++ pr_debug("Couldn't register the dialin driver\n");
+ goto err_puttty;
+ }
+
+ retval = pci_register_driver(&isicom_driver);
+ if (retval < 0) {
+- printk(KERN_ERR "ISICOM: Unable to register pci driver.\n");
++ pr_err("Unable to register pci driver.\n");
+ goto err_unrtty;
+ }
+
diff --git a/tty/serial-serial_cs-oxsemi-quirk-breaks-resume.patch b/tty/serial-serial_cs-oxsemi-quirk-breaks-resume.patch
new file mode 100644
index 00000000000000..b679ec6f00b997
--- /dev/null
+++ b/tty/serial-serial_cs-oxsemi-quirk-breaks-resume.patch
@@ -0,0 +1,39 @@
+From akpm@linux-foundation.org Tue Dec 22 11:37:17 2009
+From: Pavel Machek <pavel@ucw.cz>
+Date: Wed, 09 Dec 2009 12:31:31 -0800
+Subject: serial: serial_cs: oxsemi quirk breaks resume
+To: greg@kroah.com
+Cc: alan@lxorguk.ukuu.org.uk, akpm@linux-foundation.org, pavel@ucw.cz
+Message-ID: <200912092031.nB9KVVuU003813@imap1.linux-foundation.org>
+
+
+From: Pavel Machek <pavel@ucw.cz>
+
+Quirk is applied on all cards with given manfid (is it that correct?).
+Unfortunately, that quirk breaks resume on zaurus with billionton
+bluetooth card inserted: c950ctrl is 0 and outb() faults.
+
+I believe it is simply not a multiport card. (info->multi == 1). ...
+... confirmed by printks.
+
+Signed-off-by: Pavel Machek <pavel@ucw.cz>
+Acked-by: Alan Cox <alan@lxorguk.ukuu.org.uk>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/serial/serial_cs.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/serial/serial_cs.c
++++ b/drivers/serial/serial_cs.c
+@@ -146,7 +146,8 @@ static void quirk_wakeup_oxsemi(struct p
+ {
+ struct serial_info *info = link->priv;
+
+- outb(12, info->c950ctrl + 1);
++ if (info->c950ctrl)
++ outb(12, info->c950ctrl + 1);
+ }
+
+ /* request_region? oxsemi branch does no request_region too... */
diff --git a/tty/serial-synclink_gt-dropped-transmit-data-bugfix.patch b/tty/serial-synclink_gt-dropped-transmit-data-bugfix.patch
new file mode 100644
index 00000000000000..e84bd76835b602
--- /dev/null
+++ b/tty/serial-synclink_gt-dropped-transmit-data-bugfix.patch
@@ -0,0 +1,385 @@
+From akpm@linux-foundation.org Tue Dec 22 11:39:59 2009
+From: Paul Fulghum <paulkf@microgate.com>
+Date: Wed, 09 Dec 2009 12:31:39 -0800
+Subject: serial: synclink_gt: dropped transmit data bugfix
+To: greg@kroah.com
+Cc: alan@lxorguk.ukuu.org.uk, akpm@linux-foundation.org, paulkf@microgate.com
+Message-ID: <200912092031.nB9KVdnT004176@imap1.linux-foundation.org>
+
+
+From: Paul Fulghum <paulkf@microgate.com>
+
+Fix transmit bug that could drop send data if write() called close to
+serial transmitter going idle after sending previous data. Bug is caused
+by incorrect use of device information member tx_count.
+
+Driver originally processed one data block (write call) at a time, waiting
+for transmit idle before sending more. tx_count recorded how much data
+was loaded in DMA buffers on write(), and was cleared on send completion.
+tx_count use was overloaded to record accumulated data from put_char()
+callback when transmitter was idle.
+
+A bug was introduced when transmit code was reworked to allow multiple
+blocks of data in the tx DMA buffers which keeps transmitter from going
+idle between blocks. tx_count was set to size of last block loaded,
+cleared when tx went idle, and monitored to know when to restart
+transmitter without proper synchronization. tx_count could be cleared
+when unsent data remained in DMA buffers and transmitter required
+restarting, effectively dropping unsent data.
+
+Solution:
+1. tx_count now used only to track accumulated data from put_char
+2. DMA buffer state tracked by direct inspection of descriptors
+ with spinlock synchronization
+3. consolidate these tasks in tx_load() :
+ a. check for available buffer space
+ b. load buffers
+ c. restart DMA and or serial transmitter as needed
+ These steps were previously duplicated in multiple places,
+ sometimes incompletely.
+4. fix use of tx_count as active transmit indicator,
+ instead using tx_active which is meant for that purpose
+
+Signed-off-by: Paul Fulghum <paulkf@microgate.com>
+Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
+Cc: Greg KH <greg@kroah.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/char/synclink_gt.c | 186 +++++++++++++++++++++++++--------------------
+ 1 file changed, 105 insertions(+), 81 deletions(-)
+
+--- a/drivers/char/synclink_gt.c
++++ b/drivers/char/synclink_gt.c
+@@ -468,7 +468,7 @@ static unsigned int free_tbuf_count(stru
+ static unsigned int tbuf_bytes(struct slgt_info *info);
+ static void reset_tbufs(struct slgt_info *info);
+ static void tdma_reset(struct slgt_info *info);
+-static void tx_load(struct slgt_info *info, const char *buf, unsigned int count);
++static bool tx_load(struct slgt_info *info, const char *buf, unsigned int count);
+
+ static void get_signals(struct slgt_info *info);
+ static void set_signals(struct slgt_info *info);
+@@ -813,59 +813,32 @@ static int write(struct tty_struct *tty,
+ int ret = 0;
+ struct slgt_info *info = tty->driver_data;
+ unsigned long flags;
+- unsigned int bufs_needed;
+
+ if (sanity_check(info, tty->name, "write"))
+- goto cleanup;
++ return -EIO;
++
+ DBGINFO(("%s write count=%d\n", info->device_name, count));
+
+- if (!info->tx_buf)
+- goto cleanup;
++ if (!info->tx_buf || (count > info->max_frame_size))
++ return -EIO;
+
+- if (count > info->max_frame_size) {
+- ret = -EIO;
+- goto cleanup;
+- }
++ if (!count || tty->stopped || tty->hw_stopped)
++ return 0;
+
+- if (!count)
+- goto cleanup;
++ spin_lock_irqsave(&info->lock, flags);
+
+- if (!info->tx_active && info->tx_count) {
++ if (info->tx_count) {
+ /* send accumulated data from send_char() */
+- tx_load(info, info->tx_buf, info->tx_count);
+- goto start;
++ if (!tx_load(info, info->tx_buf, info->tx_count))
++ goto cleanup;
++ info->tx_count = 0;
+ }
+- bufs_needed = (count/DMABUFSIZE);
+- if (count % DMABUFSIZE)
+- ++bufs_needed;
+- if (bufs_needed > free_tbuf_count(info))
+- goto cleanup;
+
+- ret = info->tx_count = count;
+- tx_load(info, buf, count);
+- goto start;
+-
+-start:
+- if (info->tx_count && !tty->stopped && !tty->hw_stopped) {
+- spin_lock_irqsave(&info->lock,flags);
+- if (!info->tx_active)
+- tx_start(info);
+- else if (!(rd_reg32(info, TDCSR) & BIT0)) {
+- /* transmit still active but transmit DMA stopped */
+- unsigned int i = info->tbuf_current;
+- if (!i)
+- i = info->tbuf_count;
+- i--;
+- /* if DMA buf unsent must try later after tx idle */
+- if (desc_count(info->tbufs[i]))
+- ret = 0;
+- }
+- if (ret > 0)
+- update_tx_timer(info);
+- spin_unlock_irqrestore(&info->lock,flags);
+- }
++ if (tx_load(info, buf, count))
++ ret = count;
+
+ cleanup:
++ spin_unlock_irqrestore(&info->lock, flags);
+ DBGINFO(("%s write rc=%d\n", info->device_name, ret));
+ return ret;
+ }
+@@ -882,7 +855,7 @@ static int put_char(struct tty_struct *t
+ if (!info->tx_buf)
+ return 0;
+ spin_lock_irqsave(&info->lock,flags);
+- if (!info->tx_active && (info->tx_count < info->max_frame_size)) {
++ if (info->tx_count < info->max_frame_size) {
+ info->tx_buf[info->tx_count++] = ch;
+ ret = 1;
+ }
+@@ -981,10 +954,8 @@ static void flush_chars(struct tty_struc
+ DBGINFO(("%s flush_chars start transmit\n", info->device_name));
+
+ spin_lock_irqsave(&info->lock,flags);
+- if (!info->tx_active && info->tx_count) {
+- tx_load(info, info->tx_buf,info->tx_count);
+- tx_start(info);
+- }
++ if (info->tx_count && tx_load(info, info->tx_buf, info->tx_count))
++ info->tx_count = 0;
+ spin_unlock_irqrestore(&info->lock,flags);
+ }
+
+@@ -997,10 +968,9 @@ static void flush_buffer(struct tty_stru
+ return;
+ DBGINFO(("%s flush_buffer\n", info->device_name));
+
+- spin_lock_irqsave(&info->lock,flags);
+- if (!info->tx_active)
+- info->tx_count = 0;
+- spin_unlock_irqrestore(&info->lock,flags);
++ spin_lock_irqsave(&info->lock, flags);
++ info->tx_count = 0;
++ spin_unlock_irqrestore(&info->lock, flags);
+
+ tty_wakeup(tty);
+ }
+@@ -1033,12 +1003,10 @@ static void tx_release(struct tty_struct
+ if (sanity_check(info, tty->name, "tx_release"))
+ return;
+ DBGINFO(("%s tx_release\n", info->device_name));
+- spin_lock_irqsave(&info->lock,flags);
+- if (!info->tx_active && info->tx_count) {
+- tx_load(info, info->tx_buf, info->tx_count);
+- tx_start(info);
+- }
+- spin_unlock_irqrestore(&info->lock,flags);
++ spin_lock_irqsave(&info->lock, flags);
++ if (info->tx_count && tx_load(info, info->tx_buf, info->tx_count))
++ info->tx_count = 0;
++ spin_unlock_irqrestore(&info->lock, flags);
+ }
+
+ /*
+@@ -1506,27 +1474,25 @@ static netdev_tx_t hdlcdev_xmit(struct s
+
+ DBGINFO(("%s hdlc_xmit\n", dev->name));
+
++ if (!skb->len)
++ return NETDEV_TX_OK;
++
+ /* stop sending until this frame completes */
+ netif_stop_queue(dev);
+
+- /* copy data to device buffers */
+- info->tx_count = skb->len;
+- tx_load(info, skb->data, skb->len);
+-
+ /* update network statistics */
+ dev->stats.tx_packets++;
+ dev->stats.tx_bytes += skb->len;
+
+- /* done with socket buffer, so free it */
+- dev_kfree_skb(skb);
+-
+ /* save start time for transmit timeout detection */
+ dev->trans_start = jiffies;
+
+- spin_lock_irqsave(&info->lock,flags);
+- tx_start(info);
+- update_tx_timer(info);
+- spin_unlock_irqrestore(&info->lock,flags);
++ spin_lock_irqsave(&info->lock, flags);
++ tx_load(info, skb->data, skb->len);
++ spin_unlock_irqrestore(&info->lock, flags);
++
++ /* done with socket buffer, so free it */
++ dev_kfree_skb(skb);
+
+ return NETDEV_TX_OK;
+ }
+@@ -2180,7 +2146,7 @@ static void isr_serial(struct slgt_info
+
+ if (info->params.mode == MGSL_MODE_ASYNC) {
+ if (status & IRQ_TXIDLE) {
+- if (info->tx_count)
++ if (info->tx_active)
+ isr_txeom(info, status);
+ }
+ if (info->rx_pio && (status & IRQ_RXDATA))
+@@ -2276,13 +2242,42 @@ static void isr_tdma(struct slgt_info *i
+ }
+ }
+
++/*
++ * return true if there are unsent tx DMA buffers, otherwise false
++ *
++ * if there are unsent buffers then info->tbuf_start
++ * is set to index of first unsent buffer
++ */
++static bool unsent_tbufs(struct slgt_info *info)
++{
++ unsigned int i = info->tbuf_current;
++ bool rc = false;
++
++ /*
++ * search backwards from last loaded buffer (precedes tbuf_current)
++ * for first unsent buffer (desc_count > 0)
++ */
++
++ do {
++ if (i)
++ i--;
++ else
++ i = info->tbuf_count - 1;
++ if (!desc_count(info->tbufs[i]))
++ break;
++ info->tbuf_start = i;
++ rc = true;
++ } while (i != info->tbuf_current);
++
++ return rc;
++}
++
+ static void isr_txeom(struct slgt_info *info, unsigned short status)
+ {
+ DBGISR(("%s txeom status=%04x\n", info->device_name, status));
+
+ slgt_irq_off(info, IRQ_TXDATA + IRQ_TXIDLE + IRQ_TXUNDER);
+ tdma_reset(info);
+- reset_tbufs(info);
+ if (status & IRQ_TXUNDER) {
+ unsigned short val = rd_reg16(info, TCR);
+ wr_reg16(info, TCR, (unsigned short)(val | BIT2)); /* set reset bit */
+@@ -2297,8 +2292,12 @@ static void isr_txeom(struct slgt_info *
+ info->icount.txok++;
+ }
+
++ if (unsent_tbufs(info)) {
++ tx_start(info);
++ update_tx_timer(info);
++ return;
++ }
+ info->tx_active = false;
+- info->tx_count = 0;
+
+ del_timer(&info->tx_timer);
+
+@@ -3949,7 +3948,7 @@ static void tx_start(struct slgt_info *i
+ info->tx_enabled = true;
+ }
+
+- if (info->tx_count) {
++ if (desc_count(info->tbufs[info->tbuf_start])) {
+ info->drop_rts_on_tx_done = false;
+
+ if (info->params.mode != MGSL_MODE_ASYNC) {
+@@ -4772,25 +4771,36 @@ static unsigned int tbuf_bytes(struct sl
+ }
+
+ /*
+- * load transmit DMA buffer(s) with data
++ * load data into transmit DMA buffer ring and start transmitter if needed
++ * return true if data accepted, otherwise false (buffers full)
+ */
+-static void tx_load(struct slgt_info *info, const char *buf, unsigned int size)
++static bool tx_load(struct slgt_info *info, const char *buf, unsigned int size)
+ {
+ unsigned short count;
+ unsigned int i;
+ struct slgt_desc *d;
+
+- if (size == 0)
+- return;
++ /* check required buffer space */
++ if (DIV_ROUND_UP(size, DMABUFSIZE) > free_tbuf_count(info))
++ return false;
+
+ DBGDATA(info, buf, size, "tx");
+
++ /*
++ * copy data to one or more DMA buffers in circular ring
++ * tbuf_start = first buffer for this data
++ * tbuf_current = next free buffer
++ *
++ * Copy all data before making data visible to DMA controller by
++ * setting descriptor count of the first buffer.
++ * This prevents an active DMA controller from reading the first DMA
++ * buffers of a frame and stopping before the final buffers are filled.
++ */
++
+ info->tbuf_start = i = info->tbuf_current;
+
+ while (size) {
+ d = &info->tbufs[i];
+- if (++i == info->tbuf_count)
+- i = 0;
+
+ count = (unsigned short)((size > DMABUFSIZE) ? DMABUFSIZE : size);
+ memcpy(d->buf, buf, count);
+@@ -4808,11 +4818,27 @@ static void tx_load(struct slgt_info *in
+ else
+ set_desc_eof(*d, 0);
+
+- set_desc_count(*d, count);
++ /* set descriptor count for all but first buffer */
++ if (i != info->tbuf_start)
++ set_desc_count(*d, count);
+ d->buf_count = count;
++
++ if (++i == info->tbuf_count)
++ i = 0;
+ }
+
+ info->tbuf_current = i;
++
++ /* set first buffer count to make new data visible to DMA controller */
++ d = &info->tbufs[info->tbuf_start];
++ set_desc_count(*d, d->buf_count);
++
++ /* start transmitter if needed and update transmit timeout */
++ if (!info->tx_active)
++ tx_start(info);
++ update_tx_timer(info);
++
++ return true;
+ }
+
+ static int register_test(struct slgt_info *info)
+@@ -4934,9 +4960,7 @@ static int loopback_test(struct slgt_inf
+ spin_lock_irqsave(&info->lock,flags);
+ async_mode(info);
+ rx_start(info);
+- info->tx_count = count;
+ tx_load(info, buf, count);
+- tx_start(info);
+ spin_unlock_irqrestore(&info->lock, flags);
+
+ /* wait for receive complete */
diff --git a/tty/tty-char-mxser-remove-unnecessary-tty-test.patch b/tty/tty-char-mxser-remove-unnecessary-tty-test.patch
new file mode 100644
index 00000000000000..7b46a0df10a080
--- /dev/null
+++ b/tty/tty-char-mxser-remove-unnecessary-tty-test.patch
@@ -0,0 +1,36 @@
+From akpm@linux-foundation.org Tue Dec 22 11:44:07 2009
+From: Jiri Slaby <jirislaby@gmail.com>
+Date: Wed, 09 Dec 2009 12:34:15 -0800
+Subject: tty: char: mxser, remove unnecessary tty test
+To: greg@kroah.com
+Cc: alan@lxorguk.ukuu.org.uk, akpm@linux-foundation.org, jirislaby@gmail.com
+Message-ID: <200912092034.nB9KYFsV010648@imap1.linux-foundation.org>
+
+
+From: Jiri Slaby <jirislaby@gmail.com>
+
+Stanse found unnecessary test in mxser_startup.
+
+tty is dereferenced earlier, the test is superfluous. Remove it.
+
+Signed-off-by: Jiri Slaby <jirislaby@gmail.com>
+Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/char/mxser.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+--- a/drivers/char/mxser.c
++++ b/drivers/char/mxser.c
+@@ -895,8 +895,7 @@ static int mxser_activate(struct tty_por
+ if (inb(info->ioaddr + UART_LSR) == 0xff) {
+ spin_unlock_irqrestore(&info->slock, flags);
+ if (capable(CAP_SYS_ADMIN)) {
+- if (tty)
+- set_bit(TTY_IO_ERROR, &tty->flags);
++ set_bit(TTY_IO_ERROR, &tty->flags);
+ return 0;
+ } else
+ return -ENODEV;
diff --git a/tty/tty-moxa-remove-ifdef-module-completely.patch b/tty/tty-moxa-remove-ifdef-module-completely.patch
new file mode 100644
index 00000000000000..f332fb88b3eb87
--- /dev/null
+++ b/tty/tty-moxa-remove-ifdef-module-completely.patch
@@ -0,0 +1,88 @@
+From akpm@linux-foundation.org Tue Dec 22 11:45:44 2009
+From: Rakib Mullick <rakib.mullick@gmail.com>
+Date: Wed, 09 Dec 2009 12:34:18 -0800
+Subject: tty: moxa: remove #ifdef MODULE completely.
+To: greg@kroah.com
+Cc: alan@lxorguk.ukuu.org.uk, akpm@linux-foundation.org, rakib.mullick@gmail.com, jirislaby@gmail.com
+Message-ID: <200912092034.nB9KYIgN010803@imap1.linux-foundation.org>
+
+
+From: Rakib Mullick <rakib.mullick@gmail.com>
+
+We can pass "module parameters" on the kernel command line even when
+!MODULE. So, #ifdef MODULE becomes obsolete. Also move the declaration
+moxa_board_conf at the start of the function, since we were hit by the
+following warning.
+
+drivers/char/moxa.c: In function `moxa_init':
+drivers/char/moxa.c:1040: warning: ISO C90 forbids mixed declarations and code
+
+Signed-off-by: Rakib Mullick<rakib.mullick@gmail.com>
+Acked-by: Jiri Slaby <jirislaby@gmail.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/char/moxa.c | 17 ++++++-----------
+ 1 file changed, 6 insertions(+), 11 deletions(-)
+
+--- a/drivers/char/moxa.c
++++ b/drivers/char/moxa.c
+@@ -164,24 +164,22 @@ static unsigned int moxaFuncTout = HZ /
+ static unsigned int moxaLowWaterChk;
+ static DEFINE_MUTEX(moxa_openlock);
+ static DEFINE_SPINLOCK(moxa_lock);
+-/* Variables for insmod */
+-#ifdef MODULE
++
+ static unsigned long baseaddr[MAX_BOARDS];
+ static unsigned int type[MAX_BOARDS];
+ static unsigned int numports[MAX_BOARDS];
+-#endif
+
+ MODULE_AUTHOR("William Chen");
+ MODULE_DESCRIPTION("MOXA Intellio Family Multiport Board Device Driver");
+ MODULE_LICENSE("GPL");
+-#ifdef MODULE
++
+ module_param_array(type, uint, NULL, 0);
+ MODULE_PARM_DESC(type, "card type: C218=2, C320=4");
+ module_param_array(baseaddr, ulong, NULL, 0);
+ MODULE_PARM_DESC(baseaddr, "base address");
+ module_param_array(numports, uint, NULL, 0);
+ MODULE_PARM_DESC(numports, "numports (ignored for C218)");
+-#endif
++
+ module_param(ttymajor, int, 0);
+
+ /*
+@@ -1024,6 +1022,8 @@ static int __init moxa_init(void)
+ {
+ unsigned int isabrds = 0;
+ int retval = 0;
++ struct moxa_board_conf *brd = moxa_boards;
++ unsigned int i;
+
+ printk(KERN_INFO "MOXA Intellio family driver version %s\n",
+ MOXA_VERSION);
+@@ -1051,10 +1051,7 @@ static int __init moxa_init(void)
+ }
+
+ /* Find the boards defined from module args. */
+-#ifdef MODULE
+- {
+- struct moxa_board_conf *brd = moxa_boards;
+- unsigned int i;
++
+ for (i = 0; i < MAX_BOARDS; i++) {
+ if (!baseaddr[i])
+ break;
+@@ -1087,8 +1084,6 @@ static int __init moxa_init(void)
+ isabrds++;
+ }
+ }
+- }
+-#endif
+
+ #ifdef CONFIG_PCI
+ retval = pci_register_driver(&moxa_pci_driver);