diff options
| author | Greg Kroah-Hartman <gregkh@suse.de> | 2009-12-22 12:22:11 -0800 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@suse.de> | 2009-12-22 12:22:11 -0800 |
| commit | 52a248c714fb17267c89520a4a854b0f65de998c (patch) | |
| tree | b08803dad70c8bfeba8a20e4c06b24ea6ce5cf9d /tty | |
| parent | ae75e9fa49d0b2a2a776794dad9e420e7bc269f2 (diff) | |
| download | patches-52a248c714fb17267c89520a4a854b0f65de998c.tar.gz | |
huge catchup on pending patches
Diffstat (limited to 'tty')
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); |
