GIT 75fde2eddcfcd1dcc87a72dc6cd3c859420b6148 git+ssh://master.kernel.org/home/rmk/linux-2.6-serial.git#devel commit 75fde2eddcfcd1dcc87a72dc6cd3c859420b6148 Author: Matthew Garrett Date: Sun Oct 1 19:27:38 2006 +0100 [SERIAL] add PNP IDs for FPI based touchscreens The Compaq TC1000 and Fujitsu Stylistic range of tablet machines use touchscreens from FPI. These are implemented as serial interfaces, generally exposed in the ACPIPNP information on the system. This patch adds them to the 8250_pnp driver tables, avoiding the need to mess around with setserial to set them up. I haven't been able to confirm what FUJ02B5, FUJ02BA and FUJ02BB are. FUJ02B1 refers to the controller for the system hotkeys. FUJ02BC appears to be the last in the range - after this, they moved to Wacom-based systems. Signed-off-by: Matthew Garrett Signed-off-by: Russell King commit d8d64d6b29d331f1217c77999f5104fe68b0ef3a Author: Simon Tatham Date: Mon Sep 25 16:51:28 2006 -0700 [SERIAL] Magic SysRq SAK does nothing on serial consoles Make sysrq-K work on serial console by passing in the tty. Signed-off-by: Andrew Morton Signed-off-by: Russell King commit e480af09c49736848f749a43dff2c902104f6691 Author: Dave Jones Date: Mon Sep 25 16:51:26 2006 -0700 [SERIAL] tickle NMI watchdog on serial output. Serial is _slow_ sometimes. So slow, that the NMI watchdog kicks in. NMI Watchdog detected LOCKUP on CPU2CPU 2 Modules linked in: loop usb_storage md5 ipv6 parport_pc lp parport autofs4 i2c_dev i2c_core rfcomm l2cap bluetooth sunrpc pcdPid: 3138, comm: gpm Not tainted 2.6.11-1.1290_FC4smp RIP: 0010:[] {serial_in+106} RSP: 0018:ffff81003afc3d50 EFLAGS: 00000002 RAX: 0000000000000020 RBX: 0000000000000020 RCX: 0000000000000000 RDX: 00000000000003fd RSI: 0000000000000005 RDI: ffffffff804dcd60 RBP: 00000000000024fc R08: 000000000000000a R09: 0000000000000033 R10: ffff81001beb7c20 R11: 0000000000000020 R12: ffffffff804dcd60 R13: ffffffff804ade76 R14: 000000000000002b R15: 000000000000002c FS: 00002aaaaaac4920(0000) GS:ffffffff804fca00(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b CR2: 00002aaaaabcb000 CR3: 000000003c0d0000 CR4: 00000000000006e0 Process gpm (pid: 3138, threadinfo ffff81003afc2000, task ffff81003eb63780) Stack: ffffffff80275f2e 0000000000000000 ffffffff80448380 0000000000007d6b 000000000000002c fffffffffffffbbf 0000000000000292 0000000000008000 ffffffff80138e8c 0000000000007d97 Call Trace:{serial8250_console_write+270} {__call_console_drivers+76} {release_console_sem+315} {con_open+149} {tty_open+537} {chrdev_open+387} {dentry_open+260} {filp_open+68} {get_unused_fd+227} {sys_open+76} {tracesys+209} Code: 0f b6 c0 c3 66 90 41 57 49 89 f7 41 56 41 be 00 01 00 00 41 console shuts up ... I initially did the patch below a year ago for the Fedora kernel, and have been keeping it up to date since. I recently got the same thing happening on a vanilla kernel, so figured it was time to repost this. Signed-off-by: Dave Jones Acked-by: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Russell King commit a6b93a908508810c5d51dd9b390283345af6f2d9 Author: Russell King Date: Sun Oct 1 17:17:40 2006 +0100 [SERIAL] Fix oops when removing suspended serial port A serial card might have been removed when the system is resumed. This results in a suspended port being shut down, which results in the ports shutdown method being called twice in a row. This causes BUGs. Avoid this by tracking the suspended state separately from the initialised state. Signed-off-by: Russell King commit fe59d5372ae719ca4550958f1e5bb4dd6eeac9cd Author: Russell King Date: Sun Oct 1 17:14:07 2006 +0100 [SERIAL] Fix resume handling bug Unfortunately, pcmcia_dev_present() returns false when a device is suspended, so checking this on resume does not work too well. Omit this test. Signed-off-by: Russell King commit bcf5111a58c7db968c3fb9cd77e340a5e076f549 Author: Russell King Date: Wed Aug 30 10:27:15 2006 +0100 [SERIAL] Remove wrong asm/serial.h inclusions asm/serial.h is supposed to contain the definitions for the architecture specific 8250 ports for the 8250 driver. It may also define BASE_BAUD, but this is the base baud for the architecture specific ports _only_. Therefore, nothing other than the 8250 driver should be including this header file. In order to move towards this goal, here is a patch which removes some of the more obvious incorrect includes of the file. Acked-by: Paul Fulghum Acked-by: Tony Luck Acked-by: Ralf Baechle Acked-by: David Howells Signed-off-by: Russell King commit 1d5e799663046917a0eb085e716d818af20050b2 Author: Alexey Dobriyan Date: Mon Sep 25 16:51:27 2006 -0700 [SERIAL] CONFIG_PM=n slim: drivers/serial/8250_pci.c Remove some code which is unneeded if CONFIG_PM=n. Signed-off-by: Alexey Dobriyan Signed-off-by: Andrew Morton Signed-off-by: Russell King commit 255341c6fded73204b1ee6feb5fe16e125b27f62 Author: Jonathan McDowell Date: Mon Aug 14 23:05:32 2006 -0700 [SERIAL] OMAP1510 serial fix for 115200 baud The patch below is necessary for 115200 baud on an OMAP1510 internal UART. It's been in the linux-omap tree for some time and with it applied to a vanilla Linus git tree the serial console on the Amstrad Delta (which is OMAP1510 based and whose initial bootloader runs at 115200) works fine (it doesn't without it). Signed-off-by: Jonathan McDowell Signed-off-by: Andrew Morton Signed-off-by: Russell King commit 80e3c2b659515ef236f33f691ff5b22ae90ae8e4 Author: Ram Gupta Date: Mon Aug 14 23:05:29 2006 -0700 [SERIAL] returning proper error from serial core driver Fix the issue of returning 0 even in case of error from uart_set_info function. Now it returns the error EBUSY when it can not set new port. Signed-off-by: Ram Gupta Signed-off-by: Andrew Morton Signed-off-by: Russell King commit 6c6a2334a1e8af7c3eaab992732825fa9ade77cf Author: Sergei Shtylyov Date: Mon Sep 4 00:04:20 2006 +0400 [SERIAL] Make uart_line_info() correctly tell MMIO from I/O port /proc/tty/driver/serial incorrectly claims that UARTs having iotype of UPIO_MEM32, UPIO_AU, or UPIO_TSI are I/O mapped. Signed-off-by: Sergei Shtylyov Signed-off-by: Russell King commit a4b775735c0dff5a8d59a877ff0033526b469116 Author: Sergei Shtylyov Date: Mon Sep 11 20:32:58 2006 +0400 [SERIAL] suspend/resume handlers don't have level arg anymore 8250.c and serial_txx9.c port suspend/resume handler still have this obsolete argument documented... Signed-off-by: Sergei Shtylyov Signed-off-by: Russell King commit 0b30d668a20acd2ffd4268f7bbe799b0dd73d5cf Author: Sergei Shtylyov Date: Sat Sep 9 22:23:56 2006 +0400 [SERIAL] 8250 resourse management fixes I think register ranges obviously need to be claimed/released for all UARTs including those with UPIO_MEM32 and UPIO_TSI iotype. Also, serial8250_request_rsa_resources() returns false positives with UPIO_MEM32, UPIO_AU, and UPIO_TSI iotype -- I don't think this makes any sense. Signed-off-by: Sergei Shtylyov Signed-off-by: Russell King commit f3d106881b06a423455f95916e666acebe6503f2 Author: Russell King Date: Sat Sep 16 23:07:46 2006 +0100 [SERIAL] serial_cs: Add quirk for brainboxes 2-port RS232 card Mauro Ziliani reports that this card has a higher clock rate. Rather than tweak the 8250 driver to handle this, add a quirk to pass the correct clock rate to the driver. Signed-off-by: Russell King commit 20f130495c07cd01fb423c3dec7f045038118dec Author: Russell King Date: Sat Sep 16 23:04:37 2006 +0100 [SERIAL] serial_cs: handle Nokia multi->single port bodge via config quirk According to the existing code, Nokia only make single-port cards, but are detected as multi-port cards. Handle this in roughly the same way via the config quirk - forcing it to be a real single port card (info->multi=0) changes the way we allocate the IO memory, which might stop the card working. Signed-off-by: Russell King commit efd92dfaad962c4fbaf4251b28578c97bd3aa85f Author: Russell King Date: Sat Sep 16 23:00:54 2006 +0100 [SERIAL] serial_cs: add configuration quirk Add a quirk primerily to handle tweaks to the link->conf structure, eg as required for Socket cards. Signed-off-by: Russell King commit 7ef057fa707897c19725d7e07123e57f6aea79db Author: Russell King Date: Sat Sep 16 22:45:41 2006 +0100 [SERIAL] serial_cs: Convert Oxford 950 / Possio GCC wakeup quirk Move the Oxford Semi OX950 / Possio GCC wakeup handling to a quirk wakeup handler. Signed-off-by: Russell King commit eee3a883cebefca6c450c3c1c18a996e23001c2c Author: Russell King Date: Sat Sep 16 21:34:11 2006 +0100 [SERIAL] serial_cs: convert IBM post-init handling to a quirk Move IBM quirk handling into its own quirk entry. Note that doing quirk handling after we've registered the ports is racy, but since I don't know if moving this will have an undesired effect, it's probably better to leave where it is. Signed-off-by: Russell King commit a8244b564ccc46dabf2367008aecf2b380a9be8d Author: Russell King Date: Sat Sep 16 21:26:16 2006 +0100 [SERIAL] serial_cs: allow wildcarded quirks Some quirks we will introduce next apply to (eg) all cards of one manufacturer. Therefore, we need a way to list these in the quirk table - use ~0 - this is not a possible device ID value. Signed-off-by: Russell King commit 1fbbac4bcb03033d325c71fc7273aa0b9c1d9a03 Author: Russell King Date: Sat Sep 16 21:09:41 2006 +0100 [SERIAL] serial_cs: convert multi-port table to quirk table - rename multi_id table to serial_quirk / quirks[] - use named initialisers - store a pointer to the quirk table in the serial_info structure so we can use the quirk table entry later. - apply multi-port quirk after the multi-port guessing code, but only if it's != -1. Signed-off-by: Russell King commit 43549ad7a74e33947f3ba1756a7713086d32e97c Author: Russell King Date: Sat Sep 16 20:53:05 2006 +0100 [SERIAL] serial_cs: Use clean up multiport card detection - Use ARRAY_SIZE() instead of home grown based version. - use parse->manfid.card rather than le16_to_cpu(buf[1]) - manfid.card is already converted to this format. - use info->prodid in subsequent tests rather than parse->manfid.card. Signed-off-by: Russell King commit de6cc84f723ab4373d1f83e64771392d6f784c81 Author: Russell King Date: Wed Aug 30 15:30:39 2006 +0100 [SERIAL] Remove m32r_sio dependency on asm/serial.h m32r_sio re-uses a custom defined BASE_BAUD from asm/serial.h, and replaces SERIAL_PORT_DFNS with its own driver private copy. Since asm/serial.h is supposed to define 8250-based ports using these symbols, this isn't a sane idea. Hence, eliminate asm/serial.h from m32r_sio.c. Acked-by: Hirokazu Takata Signed-off-by: Russell King Signed-off-by: Andrew Morton --- arch/frv/kernel/setup.c | 1 arch/ia64/kernel/setup.c | 1 arch/mips/cobalt/setup.c | 1 arch/mips/lasat/setup.c | 1 drivers/char/pcmcia/synclink_cs.c | 1 drivers/char/synclink.c | 1 drivers/serial/8250.c | 35 ++- drivers/serial/8250_pci.c | 4 drivers/serial/8250_pnp.c | 13 + drivers/serial/m32r_sio.c | 5 drivers/serial/serial_core.c | 18 + drivers/serial/serial_cs.c | 277 ++++++++++++++++++++-------- drivers/serial/serial_txx9.c | 2 include/linux/serial_core.h | 3 14 files changed, 261 insertions(+), 102 deletions(-) diff -puN arch/frv/kernel/setup.c~git-serial arch/frv/kernel/setup.c --- a/arch/frv/kernel/setup.c~git-serial +++ a/arch/frv/kernel/setup.c @@ -31,7 +31,6 @@ #include #include -#include #include #include #include diff -puN arch/ia64/kernel/setup.c~git-serial arch/ia64/kernel/setup.c --- a/arch/ia64/kernel/setup.c~git-serial +++ a/arch/ia64/kernel/setup.c @@ -56,7 +56,6 @@ #include #include #include -#include #include #include #include diff -puN arch/mips/cobalt/setup.c~git-serial arch/mips/cobalt/setup.c --- a/arch/mips/cobalt/setup.c~git-serial +++ a/arch/mips/cobalt/setup.c @@ -23,7 +23,6 @@ #include #include #include -#include #include diff -puN arch/mips/lasat/setup.c~git-serial arch/mips/lasat/setup.c --- a/arch/mips/lasat/setup.c~git-serial +++ a/arch/mips/lasat/setup.c @@ -34,7 +34,6 @@ #include #include #include -#include #include #include diff -puN drivers/char/pcmcia/synclink_cs.c~git-serial drivers/char/pcmcia/synclink_cs.c --- a/drivers/char/pcmcia/synclink_cs.c~git-serial +++ a/drivers/char/pcmcia/synclink_cs.c @@ -57,7 +57,6 @@ #include #include #include -#include #include #include diff -puN drivers/char/synclink.c~git-serial drivers/char/synclink.c --- a/drivers/char/synclink.c~git-serial +++ a/drivers/char/synclink.c @@ -87,7 +87,6 @@ #include #include -#include #include #include diff -puN drivers/serial/8250.c~git-serial drivers/serial/8250.c --- a/drivers/serial/8250.c~git-serial +++ a/drivers/serial/8250.c @@ -1896,6 +1896,17 @@ serial8250_set_termios(struct uart_port serial_outp(up, UART_EFR, efr); } +#ifdef CONFIG_ARCH_OMAP15XX + /* Workaround to enable 115200 baud on OMAP1510 internal ports */ + if (cpu_is_omap1510() && is_omap_port((unsigned int)up->port.membase)) { + if (baud == 115200) { + quot = 1; + serial_out(up, UART_OMAP_OSC_12M_SEL, 1); + } else + serial_out(up, UART_OMAP_OSC_12M_SEL, 0); + } +#endif + if (up->capabilities & UART_NATSEMI) { /* Switch to bank 2 not bank 1, to avoid resetting EXCR2 */ serial_outp(up, UART_LCR, 0xe0); @@ -1949,6 +1960,8 @@ static int serial8250_request_std_resour case UPIO_AU: size = 0x100000; /* fall thru */ + case UPIO_TSI: + case UPIO_MEM32: case UPIO_MEM: if (!up->port.mapbase) break; @@ -1984,6 +1997,8 @@ static void serial8250_release_std_resou case UPIO_AU: size = 0x100000; /* fall thru */ + case UPIO_TSI: + case UPIO_MEM32: case UPIO_MEM: if (!up->port.mapbase) break; @@ -2007,17 +2022,15 @@ static int serial8250_request_rsa_resour { unsigned long start = UART_RSA_BASE << up->port.regshift; unsigned int size = 8 << up->port.regshift; - int ret = 0; + int ret = -EINVAL; switch (up->port.iotype) { - case UPIO_MEM: - ret = -EINVAL; - break; - case UPIO_HUB6: case UPIO_PORT: start += up->port.iobase; - if (!request_region(start, size, "serial-rsa")) + if (request_region(start, size, "serial-rsa")) + ret = 0; + else ret = -EBUSY; break; } @@ -2031,9 +2044,6 @@ static void serial8250_release_rsa_resou unsigned int size = 8 << up->port.regshift; switch (up->port.iotype) { - case UPIO_MEM: - break; - case UPIO_HUB6: case UPIO_PORT: release_region(up->port.iobase + offset, size); @@ -2222,9 +2232,10 @@ static inline void wait_for_xmitr(struct /* Wait up to 1s for flow control if necessary */ if (up->port.flags & UPF_CONS_FLOW) { tmout = 1000000; - while (--tmout && - ((serial_in(up, UART_MSR) & UART_MSR_CTS) == 0)) + while (!(serial_in(up, UART_MSR) & UART_MSR_CTS) && --tmout) { udelay(1); + touch_nmi_watchdog(); + } } } @@ -2397,7 +2408,6 @@ int __init early_serial_setup(struct uar /** * serial8250_suspend_port - suspend one serial port * @line: serial line number - * @level: the level of port suspension, as per uart_suspend_port * * Suspend one serial port. */ @@ -2409,7 +2419,6 @@ void serial8250_suspend_port(int line) /** * serial8250_resume_port - resume one serial port * @line: serial line number - * @level: the level of port resumption, as per uart_resume_port * * Resume one serial port. */ diff -puN drivers/serial/8250_pci.c~git-serial drivers/serial/8250_pci.c --- a/drivers/serial/8250_pci.c~git-serial +++ a/drivers/serial/8250_pci.c @@ -1789,6 +1789,7 @@ static void __devexit pciserial_remove_o pci_disable_device(dev); } +#ifdef CONFIG_PM static int pciserial_suspend_one(struct pci_dev *dev, pm_message_t state) { struct serial_private *priv = pci_get_drvdata(dev); @@ -1818,6 +1819,7 @@ static int pciserial_resume_one(struct p } return 0; } +#endif static struct pci_device_id serial_pci_tbl[] = { { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V960, @@ -2375,8 +2377,10 @@ static struct pci_driver serial_pci_driv .name = "serial", .probe = pciserial_init_one, .remove = __devexit_p(pciserial_remove_one), +#ifdef CONFIG_PM .suspend = pciserial_suspend_one, .resume = pciserial_resume_one, +#endif .id_table = serial_pci_tbl, }; diff -puN drivers/serial/8250_pnp.c~git-serial drivers/serial/8250_pnp.c --- a/drivers/serial/8250_pnp.c~git-serial +++ a/drivers/serial/8250_pnp.c @@ -327,6 +327,19 @@ static const struct pnp_device_id pnp_de { "WACF004", 0 }, { "WACF005", 0 }, { "WACF006", 0 }, + /* Compaq touchscreen */ + { "FPI2002", 0 }, + /* Fujitsu Stylistic touchscreens */ + { "FUJ02B2", 0 }, + { "FUJ02B3", 0 }, + /* Fujitsu Stylistic LT touchscreens */ + { "FUJ02B4", 0 }, + /* Passive Fujitsu Stylistic touchscreens */ + { "FUJ02B6", 0 }, + { "FUJ02B7", 0 }, + { "FUJ02B8", 0 }, + { "FUJ02B9", 0 }, + { "FUJ02BC", 0 }, /* Rockwell's (PORALiNK) 33600 INT PNP */ { "WCI0003", 0 }, /* Unkown PnP modems */ diff -puN drivers/serial/m32r_sio.c~git-serial drivers/serial/m32r_sio.c --- a/drivers/serial/m32r_sio.c~git-serial +++ a/drivers/serial/m32r_sio.c @@ -76,7 +76,7 @@ */ #define is_real_interrupt(irq) ((irq) != 0) -#include +#define BASE_BAUD 115200 /* Standard COM flags */ #define STD_COM_FLAGS (UPF_BOOT_AUTOCONF | UPF_SKIP_TEST) @@ -86,7 +86,6 @@ * standard enumeration mechanism. Platforms that can find all * serial ports via mechanisms like ACPI or PCI need not supply it. */ -#undef SERIAL_PORT_DFNS #if defined(CONFIG_PLAT_USRV) #define SERIAL_PORT_DFNS \ @@ -109,7 +108,7 @@ #endif /* !CONFIG_PLAT_USRV */ static struct old_serial_port old_serial_port[] = { - SERIAL_PORT_DFNS /* defined in asm/serial.h */ + SERIAL_PORT_DFNS }; #define UART_NR ARRAY_SIZE(old_serial_port) diff -puN drivers/serial/serial_core.c~git-serial drivers/serial/serial_core.c --- a/drivers/serial/serial_core.c~git-serial +++ a/drivers/serial/serial_core.c @@ -792,6 +792,7 @@ static int uart_set_info(struct uart_sta * We failed anyway. */ retval = -EBUSY; + goto exit; // Added to return the correct error -Ram Gupta } } @@ -1662,16 +1663,16 @@ static int uart_line_info(char *buf, str struct uart_port *port = state->port; char stat_buf[32]; unsigned int status; - int ret; + int mmio, ret; if (!port) return 0; + mmio = port->iotype >= UPIO_MEM; ret = sprintf(buf, "%d: uart:%s %s%08lX irq:%d", port->line, uart_type(port), - port->iotype == UPIO_MEM ? "mmio:0x" : "port:", - port->iotype == UPIO_MEM ? port->mapbase : - (unsigned long) port->iobase, + mmio ? "mmio:0x" : "port:", + mmio ? port->mapbase : (unsigned long) port->iobase, port->irq); if (port->type == PORT_UNKNOWN) { @@ -1939,6 +1940,9 @@ int uart_suspend_port(struct uart_driver if (state->info && state->info->flags & UIF_INITIALIZED) { const struct uart_ops *ops = port->ops; + state->info->flags = (state->info->flags & ~UIF_INITIALIZED) + | UIF_SUSPENDED; + spin_lock_irq(&port->lock); ops->stop_tx(port); ops->set_mctrl(port, 0); @@ -2005,7 +2009,7 @@ int uart_resume_port(struct uart_driver console_start(port->cons); } - if (state->info && state->info->flags & UIF_INITIALIZED) { + if (state->info && state->info->flags & UIF_SUSPENDED) { const struct uart_ops *ops = port->ops; int ret; @@ -2017,15 +2021,17 @@ int uart_resume_port(struct uart_driver ops->set_mctrl(port, port->mctrl); ops->start_tx(port); spin_unlock_irq(&port->lock); + state->info->flags |= UIF_INITIALIZED; } 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. */ - state->info->flags &= ~UIF_INITIALIZED; uart_shutdown(state); } + + state->info->flags &= ~UIF_SUSPENDED; } mutex_unlock(&state->mutex); diff -puN drivers/serial/serial_cs.c~git-serial drivers/serial/serial_cs.c --- a/drivers/serial/serial_cs.c~git-serial +++ a/drivers/serial/serial_cs.c @@ -80,23 +80,16 @@ module_param(buggy_uart, int, 0444); /* Table of multi-port card ID's */ -struct multi_id { - u_short manfid; - u_short prodid; +struct serial_quirk { + unsigned int manfid; + unsigned int prodid; int multi; /* 1 = multifunction, > 1 = # ports */ + void (*config)(struct pcmcia_device *); + void (*setup)(struct pcmcia_device *, struct uart_port *); + void (*wakeup)(struct pcmcia_device *); + int (*post)(struct pcmcia_device *); }; -static const struct multi_id multi_id[] = { - { MANFID_OMEGA, PRODID_OMEGA_QSP_100, 4 }, - { MANFID_QUATECH, PRODID_QUATECH_DUAL_RS232, 2 }, - { MANFID_QUATECH, PRODID_QUATECH_DUAL_RS232_D1, 2 }, - { MANFID_QUATECH, PRODID_QUATECH_QUAD_RS232, 4 }, - { MANFID_SOCKET, PRODID_SOCKET_DUAL_RS232, 2 }, - { MANFID_INTEL, PRODID_INTEL_DUAL_RS232, 2 }, - { MANFID_NATINST, PRODID_NATINST_QUAD_RS232, 4 } -}; -#define MULTI_COUNT (sizeof(multi_id)/sizeof(struct multi_id)) - struct serial_info { struct pcmcia_device *p_dev; int ndev; @@ -107,6 +100,7 @@ struct serial_info { int c950ctrl; dev_node_t node[4]; int line[4]; + const struct serial_quirk *quirk; }; struct serial_cfg_mem { @@ -115,37 +109,165 @@ struct serial_cfg_mem { u_char buf[256]; }; +/* + * vers_1 5.0, "Brain Boxes", "2-Port RS232 card", "r6" + * manfid 0x0160, 0x0104 + * This card appears to have a 14.7456MHz clock. + */ +static void quirk_setup_brainboxes_0104(struct pcmcia_device *link, struct uart_port *port) +{ + port->uartclk = 14745600; +} + +static int quirk_post_ibm(struct pcmcia_device *link) +{ + conf_reg_t reg = { 0, CS_READ, 0x800, 0 }; + int last_ret, last_fn; + + last_ret = pcmcia_access_configuration_register(link, ®); + if (last_ret) { + last_fn = AccessConfigurationRegister; + goto cs_failed; + } + reg.Action = CS_WRITE; + reg.Value = reg.Value | 1; + last_ret = pcmcia_access_configuration_register(link, ®); + if (last_ret) { + last_fn = AccessConfigurationRegister; + goto cs_failed; + } + return 0; -static int serial_config(struct pcmcia_device * link); + cs_failed: + cs_error(link, last_fn, last_ret); + return -ENODEV; +} + +/* + * Nokia cards are not really multiport cards. Shouldn't this + * be handled by setting the quirk entry .multi = 0 | 1 ? + */ +static void quirk_config_nokia(struct pcmcia_device *link) +{ + struct serial_info *info = link->priv; + + if (info->multi > 1) + info->multi = 1; +} + +static void quirk_wakeup_oxsemi(struct pcmcia_device *link) +{ + struct serial_info *info = link->priv; + + outb(12, info->c950ctrl + 1); +} +/* request_region? oxsemi branch does no request_region too... */ +/* + * This sequence is needed to properly initialize MC45 attached to OXCF950. + * I tried decreasing these msleep()s, but it worked properly (survived + * 1000 stop/start operations) with these timeouts (or bigger). + */ +static void quirk_wakeup_possio_gcc(struct pcmcia_device *link) +{ + struct serial_info *info = link->priv; + unsigned int ctrl = info->c950ctrl; -static void wakeup_card(struct serial_info *info) + outb(0xA, ctrl + 1); + msleep(100); + outb(0xE, ctrl + 1); + msleep(300); + outb(0xC, ctrl + 1); + msleep(100); + outb(0xE, ctrl + 1); + msleep(200); + outb(0xF, ctrl + 1); + msleep(100); + outb(0xE, ctrl + 1); + msleep(100); + outb(0xC, ctrl + 1); +} + +/* + * Socket Dual IO: this enables irq's for second port + */ +static void quirk_config_socket(struct pcmcia_device *link) { - int ctrl = info->c950ctrl; + struct serial_info *info = link->priv; - if (info->manfid == MANFID_OXSEMI) { - outb(12, ctrl + 1); - } else if (info->manfid == MANFID_POSSIO && info->prodid == PRODID_POSSIO_GCC) { - /* request_region? oxsemi branch does no request_region too... */ - /* This sequence is needed to properly initialize MC45 attached to OXCF950. - * I tried decreasing these msleep()s, but it worked properly (survived - * 1000 stop/start operations) with these timeouts (or bigger). */ - outb(0xA, ctrl + 1); - msleep(100); - outb(0xE, ctrl + 1); - msleep(300); - outb(0xC, ctrl + 1); - msleep(100); - outb(0xE, ctrl + 1); - msleep(200); - outb(0xF, ctrl + 1); - msleep(100); - outb(0xE, ctrl + 1); - msleep(100); - outb(0xC, ctrl + 1); + if (info->multi) { + link->conf.Present |= PRESENT_EXT_STATUS; + link->conf.ExtStatus = ESR_REQ_ATTN_ENA; } } +static const struct serial_quirk quirks[] = { + { + .manfid = 0x0160, + .prodid = 0x0104, + .multi = -1, + .setup = quirk_setup_brainboxes_0104, + }, { + .manfid = MANFID_IBM, + .prodid = ~0, + .multi = -1, + .post = quirk_post_ibm, + }, { + .manfid = MANFID_INTEL, + .prodid = PRODID_INTEL_DUAL_RS232, + .multi = 2, + }, { + .manfid = MANFID_NATINST, + .prodid = PRODID_NATINST_QUAD_RS232, + .multi = 4, + }, { + .manfid = MANFID_NOKIA, + .prodid = ~0, + .multi = -1, + .config = quirk_config_nokia, + }, { + .manfid = MANFID_OMEGA, + .prodid = PRODID_OMEGA_QSP_100, + .multi = 4, + }, { + .manfid = MANFID_OXSEMI, + .prodid = ~0, + .multi = -1, + .wakeup = quirk_wakeup_oxsemi, + }, { + .manfid = MANFID_POSSIO, + .prodid = PRODID_POSSIO_GCC, + .multi = -1, + .wakeup = quirk_wakeup_possio_gcc, + }, { + .manfid = MANFID_QUATECH, + .prodid = PRODID_QUATECH_DUAL_RS232, + .multi = 2, + }, { + .manfid = MANFID_QUATECH, + .prodid = PRODID_QUATECH_DUAL_RS232_D1, + .multi = 2, + }, { + .manfid = MANFID_QUATECH, + .prodid = PRODID_QUATECH_QUAD_RS232, + .multi = 4, + }, { + .manfid = MANFID_SOCKET, + .prodid = PRODID_SOCKET_DUAL_RS232, + .multi = 2, + .config = quirk_config_socket, + }, { + .manfid = MANFID_SOCKET, + .prodid = ~0, + .multi = -1, + .config = quirk_config_socket, + } +}; + + +static int serial_config(struct pcmcia_device * link); + + /*====================================================================== After a card is removed, serial_remove() will unregister @@ -185,14 +307,14 @@ static int serial_suspend(struct pcmcia_ static int serial_resume(struct pcmcia_device *link) { - if (pcmcia_dev_present(link)) { - struct serial_info *info = link->priv; - int i; - - for (i = 0; i < info->ndev; i++) - serial8250_resume_port(info->line[i]); - wakeup_card(info); - } + struct serial_info *info = link->priv; + int i; + + for (i = 0; i < info->ndev; i++) + serial8250_resume_port(info->line[i]); + + if (info->quirk && info->quirk->wakeup) + info->quirk->wakeup(link); return 0; } @@ -278,6 +400,10 @@ static int setup_serial(struct pcmcia_de port.dev = &handle_to_dev(handle); if (buggy_uart) port.flags |= UPF_BUGGY_UART; + + if (info->quirk && info->quirk->setup) + info->quirk->setup(handle, &port); + line = serial8250_register_port(&port); if (line < 0) { printk(KERN_NOTICE "serial_cs: serial8250_register_port() at " @@ -433,6 +559,13 @@ next_entry: } if (info->multi && (info->manfid == MANFID_3COM)) link->conf.ConfigIndex &= ~(0x08); + + /* + * Apply any configuration quirks. + */ + if (info->quirk && info->quirk->config) + info->quirk->config(link); + i = pcmcia_request_configuration(link, &link->conf); if (i != CS_SUCCESS) { cs_error(link, RequestConfiguration, i); @@ -521,11 +654,13 @@ static int multi_config(struct pcmcia_de cs_error(link, RequestIRQ, i); link->irq.AssignedIRQ = 0; } - /* Socket Dual IO: this enables irq's for second port */ - if (info->multi && (info->manfid == MANFID_SOCKET)) { - link->conf.Present |= PRESENT_EXT_STATUS; - link->conf.ExtStatus = ESR_REQ_ATTN_ENA; - } + + /* + * Apply any configuration quirks. + */ + if (info->quirk && info->quirk->config) + info->quirk->config(link); + i = pcmcia_request_configuration(link, &link->conf); if (i != CS_SUCCESS) { cs_error(link, RequestConfiguration, i); @@ -550,17 +685,19 @@ static int multi_config(struct pcmcia_de link->irq.AssignedIRQ); } info->c950ctrl = base2; - wakeup_card(info); + + /* + * FIXME: We really should wake up the port prior to + * handing it over to the serial layer. + */ + if (info->quirk && info->quirk->wakeup) + info->quirk->wakeup(link); + rc = 0; goto free_cfg_mem; } setup_serial(link, info, link->io.BasePort1, link->irq.AssignedIRQ); - /* The Nokia cards are not really multiport cards */ - if (info->manfid == MANFID_NOKIA) { - rc = 0; - goto free_cfg_mem; - } for (i = 0; i < info->multi - 1; i++) setup_serial(link, info, base2 + (8 * i), link->irq.AssignedIRQ); @@ -635,6 +772,12 @@ static int serial_config(struct pcmcia_d } } + /* + * Apply any multi-port quirk. + */ + if (info->quirk && info->quirk->multi != -1) + info->multi = info->quirk->multi; + if (info->multi > 1) multi_config(link); else @@ -643,21 +786,13 @@ static int serial_config(struct pcmcia_d if (info->ndev == 0) goto failed; - if (info->manfid == MANFID_IBM) { - conf_reg_t reg = { 0, CS_READ, 0x800, 0 }; - last_ret = pcmcia_access_configuration_register(link, ®); - if (last_ret) { - last_fn = AccessConfigurationRegister; - goto cs_failed; - } - reg.Action = CS_WRITE; - reg.Value = reg.Value | 1; - last_ret = pcmcia_access_configuration_register(link, ®); - if (last_ret) { - last_fn = AccessConfigurationRegister; - goto cs_failed; - } - } + /* + * Apply any post-init quirk. FIXME: This should really happen + * before we register the port, since it might already be in use. + */ + if (info->quirk && info->quirk->post) + if (info->quirk->post(link)) + goto failed; link->dev_node = &info->node[0]; kfree(cfg_mem); diff -puN drivers/serial/serial_txx9.c~git-serial drivers/serial/serial_txx9.c --- a/drivers/serial/serial_txx9.c~git-serial +++ a/drivers/serial/serial_txx9.c @@ -990,7 +990,6 @@ int __init early_serial_txx9_setup(struc /** * serial_txx9_suspend_port - suspend one serial port * @line: serial line number - * @level: the level of port suspension, as per uart_suspend_port * * Suspend one serial port. */ @@ -1002,7 +1001,6 @@ static void serial_txx9_suspend_port(int /** * serial_txx9_resume_port - resume one serial port * @line: serial line number - * @level: the level of port resumption, as per uart_resume_port * * Resume one serial port. */ diff -puN include/linux/serial_core.h~git-serial include/linux/serial_core.h --- a/include/linux/serial_core.h~git-serial +++ a/include/linux/serial_core.h @@ -319,6 +319,7 @@ struct uart_info { #define UIF_CTS_FLOW ((__force uif_t) (1 << 26)) #define UIF_NORMAL_ACTIVE ((__force uif_t) (1 << 29)) #define UIF_INITIALIZED ((__force uif_t) (1 << 31)) +#define UIF_SUSPENDED ((__force uif_t) (1 << 30)) int blocked_open; @@ -414,7 +415,7 @@ uart_handle_sysrq_char(struct uart_port #ifdef SUPPORT_SYSRQ if (port->sysrq) { if (ch && time_before(jiffies, port->sysrq)) { - handle_sysrq(ch, regs, NULL); + handle_sysrq(ch, regs, port->info->tty); port->sysrq = 0; return 1; } _