diff options
Diffstat (limited to 'drivers/serial')
-rw-r--r-- | drivers/serial/21285.c | 2 | ||||
-rw-r--r-- | drivers/serial/8250.c | 2 | ||||
-rw-r--r-- | drivers/serial/8250_hp300.c | 53 | ||||
-rw-r--r-- | drivers/serial/8250_pci.c | 2 | ||||
-rw-r--r-- | drivers/serial/amba-pl010.c | 2 | ||||
-rw-r--r-- | drivers/serial/amba-pl011.c | 2 | ||||
-rw-r--r-- | drivers/serial/clps711x.c | 65 | ||||
-rw-r--r-- | drivers/serial/imx.c | 68 | ||||
-rw-r--r-- | drivers/serial/ioc4_serial.c | 50 | ||||
-rw-r--r-- | drivers/serial/jsm/jsm.h | 1 | ||||
-rw-r--r-- | drivers/serial/jsm/jsm_neo.c | 2 | ||||
-rw-r--r-- | drivers/serial/jsm/jsm_tty.c | 4 | ||||
-rw-r--r-- | drivers/serial/mpsc.c | 14 | ||||
-rw-r--r-- | drivers/serial/mpsc.h | 10 | ||||
-rw-r--r-- | drivers/serial/s3c2410.c | 2 | ||||
-rw-r--r-- | drivers/serial/sa1100.c | 65 | ||||
-rw-r--r-- | drivers/serial/serial_cs.c | 173 | ||||
-rw-r--r-- | drivers/serial/serial_lh7a40x.c | 2 | ||||
-rw-r--r-- | drivers/serial/sn_console.c | 4 | ||||
-rw-r--r-- | drivers/serial/sunsab.c | 16 | ||||
-rw-r--r-- | drivers/serial/sunsu.c | 11 |
21 files changed, 315 insertions, 235 deletions
diff --git a/drivers/serial/21285.c b/drivers/serial/21285.c index f8504b0adebc..33fbda79f350 100644 --- a/drivers/serial/21285.c +++ b/drivers/serial/21285.c @@ -110,7 +110,7 @@ static irqreturn_t serial21285_rx_chars(int irq, void *dev_id, struct pt_regs *r port->icount.rx++; rxs = *CSR_RXSTAT | RXSTAT_DUMMY_READ; - if (rxs & RXSTAT_ANYERR) { + if (unlikely(rxs & RXSTAT_ANYERR)) { if (rxs & RXSTAT_PARITY) port->icount.parity++; else if (rxs & RXSTAT_FRAME) diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index 218b69372c0b..0d9358608fdf 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c @@ -51,7 +51,7 @@ * share_irqs - whether we pass SA_SHIRQ to request_irq(). This option * is unsafe when used on edge-triggered interrupts. */ -unsigned int share_irqs = SERIAL8250_SHARE_IRQS; +static unsigned int share_irqs = SERIAL8250_SHARE_IRQS; /* * Debugging. diff --git a/drivers/serial/8250_hp300.c b/drivers/serial/8250_hp300.c index b8d51eb56bff..4315afe9c080 100644 --- a/drivers/serial/8250_hp300.c +++ b/drivers/serial/8250_hp300.c @@ -9,15 +9,15 @@ #include <linux/init.h> #include <linux/string.h> #include <linux/kernel.h> -#include <linux/tty.h> #include <linux/serial.h> -#include <linux/serialP.h> #include <linux/serial_core.h> #include <linux/delay.h> #include <linux/dio.h> #include <linux/console.h> #include <asm/io.h> +#include "8250.h" + #if !defined(CONFIG_HPDCA) && !defined(CONFIG_HPAPCI) #warning CONFIG_8250 defined but neither CONFIG_HPDCA nor CONFIG_HPAPCI defined, are you sure? #endif @@ -163,7 +163,7 @@ int __init hp300_setup_serial_console(void) static int __devinit hpdca_init_one(struct dio_dev *d, const struct dio_device_id *ent) { - struct serial_struct serial_req; + struct uart_port port; int line; #ifdef CONFIG_SERIAL_8250_CONSOLE @@ -172,21 +172,22 @@ static int __devinit hpdca_init_one(struct dio_dev *d, return 0; } #endif - memset(&serial_req, 0, sizeof(struct serial_struct)); + memset(&port, 0, sizeof(struct uart_port)); /* Memory mapped I/O */ - serial_req.io_type = SERIAL_IO_MEM; - serial_req.flags = UPF_SKIP_TEST | UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF; - serial_req.irq = d->ipl; - serial_req.baud_base = HPDCA_BAUD_BASE; - serial_req.iomap_base = (d->resource.start + UART_OFFSET); - serial_req.iomem_base = (char *)(serial_req.iomap_base + DIO_VIRADDRBASE); - serial_req.iomem_reg_shift = 1; - line = register_serial(&serial_req); + port.iotype = UPIO_MEM; + port.flags = UPF_SKIP_TEST | UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF; + port.irq = d->ipl; + port.uartclk = HPDCA_BAUD_BASE * 16; + port.mapbase = (d->resource.start + UART_OFFSET); + port.membase = (char *)(port.mapbase + DIO_VIRADDRBASE); + port.regshift = 1; + port.dev = &d->dev; + line = serial8250_register_port(&port); if (line < 0) { printk(KERN_NOTICE "8250_hp300: register_serial() DCA scode %d" - " irq %d failed\n", d->scode, serial_req.irq); + " irq %d failed\n", d->scode, port.irq); return -ENOMEM; } @@ -209,7 +210,7 @@ static int __init hp300_8250_init(void) #ifdef CONFIG_HPAPCI int line; unsigned long base; - struct serial_struct serial_req; + struct uart_port uport; struct hp300_port *port; int i; #endif @@ -251,25 +252,25 @@ static int __init hp300_8250_init(void) if (!port) return -ENOMEM; - memset(&serial_req, 0, sizeof(struct serial_struct)); + memset(&uport, 0, sizeof(struct uart_port)); base = (FRODO_BASE + FRODO_APCI_OFFSET(i)); /* Memory mapped I/O */ - serial_req.io_type = SERIAL_IO_MEM; - serial_req.flags = UPF_SKIP_TEST | UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF; + uport.iotype = UPIO_MEM; + uport.flags = UPF_SKIP_TEST | UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF; /* XXX - no interrupt support yet */ - serial_req.irq = 0; - serial_req.baud_base = HPAPCI_BAUD_BASE; - serial_req.iomap_base = base; - serial_req.iomem_base = (char *)(serial_req.iomap_base + DIO_VIRADDRBASE); - serial_req.iomem_reg_shift = 2; + uport.irq = 0; + uport.uartclk = HPAPCI_BAUD_BASE * 16; + uport.mapbase = base; + uport.membase = (char *)(base + DIO_VIRADDRBASE); + uport.regshift = 2; - line = register_serial(&serial_req); + line = serial8250_register_port(&uport); if (line < 0) { printk(KERN_NOTICE "8250_hp300: register_serial() APCI %d" - " irq %d failed\n", i, serial_req.irq); + " irq %d failed\n", i, uport.irq); kfree(port); continue; } @@ -299,7 +300,7 @@ static void __devexit hpdca_remove_one(struct dio_dev *d) /* Disable board-interrupts */ out_8(d->resource.start + DIO_VIRADDRBASE + DCA_IC, 0); } - unregister_serial(line); + serial8250_unregister_port(line); } #endif @@ -309,7 +310,7 @@ static void __exit hp300_8250_exit(void) struct hp300_port *port, *to_free; for (port = hp300_ports; port; ) { - unregister_serial(port->line); + serial8250_unregister_port(port->line); to_free = port; port = port->next; kfree(to_free); diff --git a/drivers/serial/8250_pci.c b/drivers/serial/8250_pci.c index f8d90d0ecfea..de54bdc5398b 100644 --- a/drivers/serial/8250_pci.c +++ b/drivers/serial/8250_pci.c @@ -1009,6 +1009,8 @@ get_pci_irq(struct pci_dev *dev, struct pci_board *board, int idx) * n = number of serial ports * baud = baud rate * + * This table is sorted by (in order): baud, bt, bn, n. + * * Please note: in theory if n = 1, _bt infix should make no difference. * ie, pbn_b0_1_115200 is the same as pbn_b0_bt_1_115200 */ diff --git a/drivers/serial/amba-pl010.c b/drivers/serial/amba-pl010.c index 484f6fb900b5..f2a5e2933c47 100644 --- a/drivers/serial/amba-pl010.c +++ b/drivers/serial/amba-pl010.c @@ -172,7 +172,7 @@ pl010_rx_chars(struct uart_port *port) * out of the main execution path */ rsr = UART_GET_RSR(port) | UART_DUMMY_RSR_RX; - if (rsr & UART01x_RSR_ANY) { + if (unlikely(rsr & UART01x_RSR_ANY)) { if (rsr & UART01x_RSR_BE) { rsr &= ~(UART01x_RSR_FE | UART01x_RSR_PE); port->icount.brk++; diff --git a/drivers/serial/amba-pl011.c b/drivers/serial/amba-pl011.c index ff658a830f34..d5cbef3fe8b6 100644 --- a/drivers/serial/amba-pl011.c +++ b/drivers/serial/amba-pl011.c @@ -137,7 +137,7 @@ pl011_rx_chars(struct uart_amba_port *uap) * out of the main execution path */ rsr = readw(uap->port.membase + UART01x_RSR) | UART_DUMMY_RSR_RX; - if (rsr & UART01x_RSR_ANY) { + if (unlikely(rsr & UART01x_RSR_ANY)) { if (rsr & UART01x_RSR_BE) { rsr &= ~(UART01x_RSR_FE | UART01x_RSR_PE); uap->port.icount.brk++; diff --git a/drivers/serial/clps711x.c b/drivers/serial/clps711x.c index 16592fae47f3..6242f3090a96 100644 --- a/drivers/serial/clps711x.c +++ b/drivers/serial/clps711x.c @@ -116,54 +116,43 @@ static irqreturn_t clps711xuart_int_rx(int irq, void *dev_id, struct pt_regs *re * Note that the error handling code is * out of the main execution path */ - if (ch & UART_ANY_ERR) - goto handle_error; + if (unlikely(ch & UART_ANY_ERR)) { + if (ch & UARTDR_PARERR) + port->icount.parity++; + else if (ch & UARTDR_FRMERR) + port->icount.frame++; + if (ch & UARTDR_OVERR) + port->icount.overrun++; - if (uart_handle_sysrq_char(port, ch, regs)) - goto ignore_char; + ch &= port->read_status_mask; - error_return: - tty_insert_flip_char(tty, ch, flg); - ignore_char: - status = clps_readl(SYSFLG(port)); - } - out: - tty_flip_buffer_push(tty); - return IRQ_HANDLED; + if (ch & UARTDR_PARERR) + flg = TTY_PARITY; + else if (ch & UARTDR_FRMERR) + flg = TTY_FRAME; - handle_error: - if (ch & UARTDR_PARERR) - port->icount.parity++; - else if (ch & UARTDR_FRMERR) - port->icount.frame++; - if (ch & UARTDR_OVERR) - port->icount.overrun++; - - if (ch & port->ignore_status_mask) { - if (++ignored > 100) - goto out; - goto ignore_char; - } - ch &= port->read_status_mask; +#ifdef SUPPORT_SYSRQ + port->sysrq = 0; +#endif + } - if (ch & UARTDR_PARERR) - flg = TTY_PARITY; - else if (ch & UARTDR_FRMERR) - flg = TTY_FRAME; + if (uart_handle_sysrq_char(port, ch, regs)) + goto ignore_char; - if (ch & UARTDR_OVERR) { /* * CHECK: does overrun affect the current character? * ASSUMPTION: it does not. */ - tty_insert_flip_char(tty, ch, flg); - ch = 0; - flg = TTY_OVERRUN; + if ((ch & port->ignore_status_mask & ~RXSTAT_OVERRUN) == 0) + tty_insert_flip_char(tty, ch, flg); + if ((ch & ~port->ignore_status_mask & RXSTAT_OVERRUN) == 0) + tty_insert_flip_char(tty, 0, TTY_OVERRUN); + + ignore_char: + status = clps_readl(SYSFLG(port)); } -#ifdef SUPPORT_SYSRQ - port->sysrq = 0; -#endif - goto error_return; + tty_flip_buffer_push(tty); + return IRQ_HANDLED; } static irqreturn_t clps711xuart_int_tx(int irq, void *dev_id, struct pt_regs *regs) diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c index c682c6308cde..01a8726a3f97 100644 --- a/drivers/serial/imx.c +++ b/drivers/serial/imx.c @@ -321,18 +321,39 @@ static void imx_break_ctl(struct uart_port *port, int break_state) #define TXTL 2 /* reset default */ #define RXTL 1 /* reset default */ +static int imx_setup_ufcr(struct imx_port *sport, unsigned int mode) +{ + unsigned int val; + unsigned int ufcr_rfdiv; + + /* set receiver / transmitter trigger level. + * RFDIV is set such way to satisfy requested uartclk value + */ + val = TXTL<<10 | RXTL; + ufcr_rfdiv = (imx_get_perclk1() + sport->port.uartclk / 2) / sport->port.uartclk; + + if(!ufcr_rfdiv) + ufcr_rfdiv = 1; + + if(ufcr_rfdiv >= 7) + ufcr_rfdiv = 6; + else + ufcr_rfdiv = 6 - ufcr_rfdiv; + + val |= UFCR_RFDIV & (ufcr_rfdiv << 7); + + UFCR((u32)sport->port.membase) = val; + + return 0; +} + static int imx_startup(struct uart_port *port) { struct imx_port *sport = (struct imx_port *)port; int retval; - unsigned int val; unsigned long flags; - /* set receiver / transmitter trigger level. We assume - * that RFDIV has been set by the arch setup or by the bootloader. - */ - val = (UFCR((u32)sport->port.membase) & UFCR_RFDIV) | TXTL<<10 | RXTL; - UFCR((u32)sport->port.membase) = val; + imx_setup_ufcr(sport, 0); /* disable the DREN bit (Data Ready interrupt enable) before * requesting IRQs @@ -737,9 +758,12 @@ static void __init imx_console_get_options(struct imx_port *sport, int *baud, int *parity, int *bits) { + if ( UCR1((u32)sport->port.membase) | UCR1_UARTEN ) { /* ok, the port was enabled */ unsigned int ucr2, ubir,ubmr, uartclk; + unsigned int baud_raw; + unsigned int ucfr_rfdiv; ucr2 = UCR2((u32)sport->port.membase); @@ -758,9 +782,35 @@ imx_console_get_options(struct imx_port *sport, int *baud, ubir = UBIR((u32)sport->port.membase) & 0xffff; ubmr = UBMR((u32)sport->port.membase) & 0xffff; - uartclk = sport->port.uartclk; - *baud = ((uartclk/16) * (ubir + 1)) / (ubmr + 1); + + ucfr_rfdiv = (UFCR((u32)sport->port.membase) & UFCR_RFDIV) >> 7; + if (ucfr_rfdiv == 6) + ucfr_rfdiv = 7; + else + ucfr_rfdiv = 6 - ucfr_rfdiv; + + uartclk = imx_get_perclk1(); + uartclk /= ucfr_rfdiv; + + { /* + * The next code provides exact computation of + * baud_raw = round(((uartclk/16) * (ubir + 1)) / (ubmr + 1)) + * without need of float support or long long division, + * which would be required to prevent 32bit arithmetic overflow + */ + unsigned int mul = ubir + 1; + unsigned int div = 16 * (ubmr + 1); + unsigned int rem = uartclk % div; + + baud_raw = (uartclk / div) * mul; + baud_raw += (rem * mul + div / 2) / div; + *baud = (baud_raw + 50) / 100 * 100; + } + + if(*baud != baud_raw) + printk(KERN_INFO "Serial: Console IMX rounded baud rate from %d to %d\n", + baud_raw, *baud); } } @@ -787,6 +837,8 @@ imx_console_setup(struct console *co, char *options) else imx_console_get_options(sport, &baud, &parity, &bits); + imx_setup_ufcr(sport, 0); + return uart_set_options(&sport->port, co, baud, parity, bits, flow); } diff --git a/drivers/serial/ioc4_serial.c b/drivers/serial/ioc4_serial.c index d054f1265701..ba4e13a22a50 100644 --- a/drivers/serial/ioc4_serial.c +++ b/drivers/serial/ioc4_serial.c @@ -838,7 +838,7 @@ static int inline port_init(struct ioc4_port *port) port->ip_tx_prod = readl(&port->ip_serial_regs->stcir) & PROD_CONS_MASK; writel(port->ip_tx_prod, &port->ip_serial_regs->stpir); port->ip_rx_cons = readl(&port->ip_serial_regs->srpir) & PROD_CONS_MASK; - writel(port->ip_rx_cons, &port->ip_serial_regs->srcir); + writel(port->ip_rx_cons | IOC4_SRCIR_ARM, &port->ip_serial_regs->srcir); /* Disable interrupts for this 16550 */ uart = port->ip_uart_regs; @@ -1272,8 +1272,9 @@ static inline int set_rx_timeout(struct ioc4_port *port, int timeout) * and set the rx threshold to that amount. There are 4 chars * per ring entry, so we'll divide the number of chars that will * arrive in timeout by 4. + * So .... timeout * baud / 10 / HZ / 4, with HZ = 100. */ - threshold = timeout * port->ip_baud / 10 / HZ / 4; + threshold = timeout * port->ip_baud / 4000; if (threshold == 0) threshold = 1; /* otherwise we'll intr all the time! */ @@ -1285,8 +1286,10 @@ static inline int set_rx_timeout(struct ioc4_port *port, int timeout) writel(port->ip_sscr, &port->ip_serial_regs->sscr); - /* Now set the rx timeout to the given value */ - timeout = timeout * IOC4_SRTR_HZ / HZ; + /* Now set the rx timeout to the given value + * again timeout * IOC4_SRTR_HZ / HZ + */ + timeout = timeout * IOC4_SRTR_HZ / 100; if (timeout > IOC4_SRTR_CNT) timeout = IOC4_SRTR_CNT; @@ -1380,7 +1383,7 @@ config_port(struct ioc4_port *port, if (port->ip_tx_lowat == 0) port->ip_tx_lowat = 1; - set_rx_timeout(port, port->ip_rx_timeout); + set_rx_timeout(port, 2); return 0; } @@ -1685,8 +1688,8 @@ ioc4_change_speed(struct uart_port *the_port, { struct ioc4_port *port = get_ioc4_port(the_port); int baud, bits; - unsigned cflag, cval; - int new_parity = 0, new_parity_enable = 0, new_stop = 1, new_data = 8; + unsigned cflag; + int new_parity = 0, new_parity_enable = 0, new_stop = 0, new_data = 8; struct uart_info *info = the_port->info; cflag = new_termios->c_cflag; @@ -1694,48 +1697,35 @@ ioc4_change_speed(struct uart_port *the_port, switch (cflag & CSIZE) { case CS5: new_data = 5; - cval = 0x00; bits = 7; break; case CS6: new_data = 6; - cval = 0x01; bits = 8; break; case CS7: new_data = 7; - cval = 0x02; bits = 9; break; case CS8: new_data = 8; - cval = 0x03; bits = 10; break; default: /* cuz we always need a default ... */ new_data = 5; - cval = 0x00; bits = 7; break; } if (cflag & CSTOPB) { - cval |= 0x04; bits++; new_stop = 1; } if (cflag & PARENB) { - cval |= UART_LCR_PARITY; bits++; new_parity_enable = 1; - } - if (cflag & PARODD) { - cval |= UART_LCR_EPAR; - new_parity = 1; - } - if (cflag & IGNPAR) { - cval &= ~UART_LCR_PARITY; - new_parity_enable = 0; + if (cflag & PARODD) + new_parity = 1; } baud = uart_get_baud_rate(the_port, new_termios, old_termios, MIN_BAUD_SUPPORTED, MAX_BAUD_SUPPORTED); @@ -1765,10 +1755,15 @@ ioc4_change_speed(struct uart_port *the_port, the_port->ignore_status_mask &= ~N_DATA_READY; } - if (cflag & CRTSCTS) + if (cflag & CRTSCTS) { info->flags |= ASYNC_CTS_FLOW; - else + port->ip_sscr |= IOC4_SSCR_HFC_EN; + } + else { info->flags &= ~ASYNC_CTS_FLOW; + port->ip_sscr &= ~IOC4_SSCR_HFC_EN; + } + writel(port->ip_sscr, &port->ip_serial_regs->sscr); /* Set the configuration and proper notification call */ DPRINT_CONFIG(("%s : port 0x%p cflag 0%o " @@ -1825,12 +1820,6 @@ static inline int ic4_startup_local(struct uart_port *the_port) /* set the speed of the serial port */ ioc4_change_speed(the_port, info->tty->termios, (struct termios *)0); - /* enable hardware flow control - after ioc4_change_speed because - * ASYNC_CTS_FLOW is set there */ - if (info->flags & ASYNC_CTS_FLOW) { - port->ip_sscr |= IOC4_SSCR_HFC_EN; - writel(port->ip_sscr, &port->ip_serial_regs->sscr); - } info->flags |= UIF_INITIALIZED; return 0; } @@ -1847,7 +1836,6 @@ static void ioc4_cb_output_lowat(struct ioc4_port *port) } } - /** * handle_intr - service any interrupts for the given port - 2nd level * called via sd_intr diff --git a/drivers/serial/jsm/jsm.h b/drivers/serial/jsm/jsm.h index e0717611c940..777829fa3300 100644 --- a/drivers/serial/jsm/jsm.h +++ b/drivers/serial/jsm/jsm.h @@ -393,7 +393,6 @@ int jsm_tty_init(struct jsm_board *); int jsm_uart_port_init(struct jsm_board *); int jsm_remove_uart_port(struct jsm_board *); void jsm_input(struct jsm_channel *ch); -void jsm_carrier(struct jsm_channel *ch); void jsm_check_queue_flow_control(struct jsm_channel *ch); #endif diff --git a/drivers/serial/jsm/jsm_neo.c b/drivers/serial/jsm/jsm_neo.c index 9b79c1ff6c72..3a11a69feb44 100644 --- a/drivers/serial/jsm/jsm_neo.c +++ b/drivers/serial/jsm/jsm_neo.c @@ -688,7 +688,7 @@ static void neo_flush_uart_read(struct jsm_channel *ch) /* * No locks are assumed to be held when calling this function. */ -void neo_clear_break(struct jsm_channel *ch, int force) +static void neo_clear_break(struct jsm_channel *ch, int force) { unsigned long lock_flags; diff --git a/drivers/serial/jsm/jsm_tty.c b/drivers/serial/jsm/jsm_tty.c index 24fe76c28833..98de2258fd06 100644 --- a/drivers/serial/jsm/jsm_tty.c +++ b/drivers/serial/jsm/jsm_tty.c @@ -31,6 +31,8 @@ #include "jsm.h" +static void jsm_carrier(struct jsm_channel *ch); + static inline int jsm_get_mstat(struct jsm_channel *ch) { unsigned char mstat; @@ -755,7 +757,7 @@ void jsm_input(struct jsm_channel *ch) jsm_printk(IOCTL, INFO, &ch->ch_bd->pci_dev, "finish\n"); } -void jsm_carrier(struct jsm_channel *ch) +static void jsm_carrier(struct jsm_channel *ch) { struct jsm_board *bd; diff --git a/drivers/serial/mpsc.c b/drivers/serial/mpsc.c index d0dfc3cf9245..a8314aee2ab8 100644 --- a/drivers/serial/mpsc.c +++ b/drivers/serial/mpsc.c @@ -329,8 +329,8 @@ mpsc_sdma_stop(struct mpsc_port_info *pi) mpsc_sdma_cmd(pi, SDMA_SDCM_AR | SDMA_SDCM_AT); /* Clear the SDMA current and first TX and RX pointers */ - mpsc_sdma_set_tx_ring(pi, 0); - mpsc_sdma_set_rx_ring(pi, 0); + mpsc_sdma_set_tx_ring(pi, NULL); + mpsc_sdma_set_rx_ring(pi, NULL); /* Disable interrupts */ mpsc_sdma_intr_mask(pi, 0xf); @@ -1540,8 +1540,8 @@ mpsc_shared_unmap_regs(void) MPSC_SDMA_INTR_REG_BLOCK_SIZE); } - mpsc_shared_regs.mpsc_routing_base = 0; - mpsc_shared_regs.sdma_intr_base = 0; + mpsc_shared_regs.mpsc_routing_base = NULL; + mpsc_shared_regs.sdma_intr_base = NULL; mpsc_shared_regs.mpsc_routing_base_p = 0; mpsc_shared_regs.sdma_intr_base_p = 0; @@ -1678,9 +1678,9 @@ mpsc_drv_unmap_regs(struct mpsc_port_info *pi) release_mem_region(pi->brg_base_p, MPSC_BRG_REG_BLOCK_SIZE); } - pi->mpsc_base = 0; - pi->sdma_base = 0; - pi->brg_base = 0; + pi->mpsc_base = NULL; + pi->sdma_base = NULL; + pi->brg_base = NULL; pi->mpsc_base_p = 0; pi->sdma_base_p = 0; diff --git a/drivers/serial/mpsc.h b/drivers/serial/mpsc.h index 1f7294b7095f..678dbcf06c8f 100644 --- a/drivers/serial/mpsc.h +++ b/drivers/serial/mpsc.h @@ -83,8 +83,8 @@ struct mpsc_shared_regs { phys_addr_t mpsc_routing_base_p; phys_addr_t sdma_intr_base_p; - void *mpsc_routing_base; - void *sdma_intr_base; + void __iomem *mpsc_routing_base; + void __iomem *sdma_intr_base; u32 MPSC_MRR_m; u32 MPSC_RCRR_m; @@ -120,9 +120,9 @@ struct mpsc_port_info { phys_addr_t brg_base_p; /* Virtual addresses of various blocks of registers (from platform) */ - void *mpsc_base; - void *sdma_base; - void *brg_base; + void __iomem *mpsc_base; + void __iomem *sdma_base; + void __iomem *brg_base; /* Descriptor ring and buffer allocations */ void *dma_region; diff --git a/drivers/serial/s3c2410.c b/drivers/serial/s3c2410.c index bd6782aeb831..435750d40a47 100644 --- a/drivers/serial/s3c2410.c +++ b/drivers/serial/s3c2410.c @@ -364,7 +364,7 @@ s3c24xx_serial_rx_chars(int irq, void *dev_id, struct pt_regs *regs) flag = TTY_NORMAL; port->icount.rx++; - if (uerstat & S3C2410_UERSTAT_ANY) { + if (unlikely(uerstat & S3C2410_UERSTAT_ANY)) { dbg("rxerr: port ch=0x%02x, rxs=0x%08x\n", ch, uerstat); diff --git a/drivers/serial/sa1100.c b/drivers/serial/sa1100.c index 086065210d1e..157218bc6c6f 100644 --- a/drivers/serial/sa1100.c +++ b/drivers/serial/sa1100.c @@ -214,56 +214,39 @@ sa1100_rx_chars(struct sa1100_port *sport, struct pt_regs *regs) * note that the error handling code is * out of the main execution path */ - if (status & UTSR1_TO_SM(UTSR1_PRE | UTSR1_FRE | UTSR1_ROR)) - goto handle_error; + if (status & UTSR1_TO_SM(UTSR1_PRE | UTSR1_FRE | UTSR1_ROR)) { + if (status & UTSR1_TO_SM(UTSR1_PRE)) + sport->port.icount.parity++; + else if (status & UTSR1_TO_SM(UTSR1_FRE)) + sport->port.icount.frame++; + if (status & UTSR1_TO_SM(UTSR1_ROR)) + sport->port.icount.overrun++; + + status &= sport->port.read_status_mask; + + if (status & UTSR1_TO_SM(UTSR1_PRE)) + flg = TTY_PARITY; + else if (status & UTSR1_TO_SM(UTSR1_FRE)) + flg = TTY_FRAME; + +#ifdef SUPPORT_SYSRQ + sport->port.sysrq = 0; +#endif + } if (uart_handle_sysrq_char(&sport->port, ch, regs)) goto ignore_char; - error_return: - tty_insert_flip_char(tty, ch, flg); + if ((status & port->ignore_status_mask & ~UTSR1_TO_SM(UTSR1_ROR)) == 0) + tty_insert_flip_char(tty, ch, flg); + if (status & ~port->ignore_status_mask & UTSR1_TO_SM(UTSR1_ROR)) + tty_insert_flip_char(tty, 0, TTY_OVERRUN); + ignore_char: status = UTSR1_TO_SM(UART_GET_UTSR1(sport)) | UTSR0_TO_SM(UART_GET_UTSR0(sport)); } - out: tty_flip_buffer_push(tty); - return; - - handle_error: - if (status & UTSR1_TO_SM(UTSR1_PRE)) - sport->port.icount.parity++; - else if (status & UTSR1_TO_SM(UTSR1_FRE)) - sport->port.icount.frame++; - if (status & UTSR1_TO_SM(UTSR1_ROR)) - sport->port.icount.overrun++; - - if (status & sport->port.ignore_status_mask) { - if (++ignored > 100) - goto out; - goto ignore_char; - } - - status &= sport->port.read_status_mask; - - if (status & UTSR1_TO_SM(UTSR1_PRE)) - flg = TTY_PARITY; - else if (status & UTSR1_TO_SM(UTSR1_FRE)) - flg = TTY_FRAME; - - if (status & UTSR1_TO_SM(UTSR1_ROR)) { - /* - * overrun does *not* affect the character - * we read from the FIFO - */ - tty_insert_flip_char(tty, ch, flg); - ch = 0; - flg = TTY_OVERRUN; - } -#ifdef SUPPORT_SYSRQ - sport->port.sysrq = 0; -#endif - goto error_return; } static void sa1100_tx_chars(struct sa1100_port *sport) diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c index 9034f9ad37c7..6eeb48f6a482 100644 --- a/drivers/serial/serial_cs.c +++ b/drivers/serial/serial_cs.c @@ -107,6 +107,13 @@ struct serial_info { int line[4]; }; +struct serial_cfg_mem { + tuple_t tuple; + cisparse_t parse; + u_char buf[256]; +}; + + static void serial_config(dev_link_t * link); static int serial_event(event_t event, int priority, event_callback_args_t * args); @@ -357,14 +364,24 @@ static int simple_config(dev_link_t *link) static int size_table[2] = { 8, 16 }; client_handle_t handle = link->handle; struct serial_info *info = link->priv; - tuple_t tuple; - u_char buf[256]; - cisparse_t parse; - cistpl_cftable_entry_t *cf = &parse.cftable_entry; + struct serial_cfg_mem *cfg_mem; + tuple_t *tuple; + u_char *buf; + cisparse_t *parse; + cistpl_cftable_entry_t *cf; config_info_t config; int i, j, try; int s; + cfg_mem = kmalloc(sizeof(struct serial_cfg_mem), GFP_KERNEL); + if (!cfg_mem) + return -1; + + tuple = &cfg_mem->tuple; + parse = &cfg_mem->parse; + cf = &parse->cftable_entry; + buf = cfg_mem->buf; + /* If the card is already configured, look up the port and irq */ i = pcmcia_get_configuration_info(handle, &config); if ((i == CS_SUCCESS) && (config.Attributes & CONF_VALID_CLIENT)) { @@ -377,21 +394,23 @@ static int simple_config(dev_link_t *link) port = config.BasePort1 + 0x28; info->slave = 1; } - if (info->slave) + if (info->slave) { + kfree(cfg_mem); return setup_serial(handle, info, port, config.AssignedIRQ); + } } link->conf.Vcc = config.Vcc; /* First pass: look for a config entry that looks normal. */ - tuple.TupleData = (cisdata_t *) buf; - tuple.TupleOffset = 0; - tuple.TupleDataMax = 255; - tuple.Attributes = 0; - tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; + tuple->TupleData = (cisdata_t *) buf; + tuple->TupleOffset = 0; + tuple->TupleDataMax = 255; + tuple->Attributes = 0; + tuple->DesiredTuple = CISTPL_CFTABLE_ENTRY; /* Two tries: without IO aliases, then with aliases */ for (s = 0; s < 2; s++) { for (try = 0; try < 2; try++) { - i = first_tuple(handle, &tuple, &parse); + i = first_tuple(handle, tuple, parse); while (i != CS_NO_MORE_ITEMS) { if (i != CS_SUCCESS) goto next_entry; @@ -409,14 +428,14 @@ static int simple_config(dev_link_t *link) goto found_port; } next_entry: - i = next_tuple(handle, &tuple, &parse); + i = next_tuple(handle, tuple, parse); } } } /* Second pass: try to find an entry that isn't picky about its base address, then try to grab any standard serial port address, and finally try to get any free port. */ - i = first_tuple(handle, &tuple, &parse); + i = first_tuple(handle, tuple, parse); while (i != CS_NO_MORE_ITEMS) { if ((i == CS_SUCCESS) && (cf->io.nwin > 0) && ((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) { @@ -429,7 +448,7 @@ next_entry: goto found_port; } } - i = next_tuple(handle, &tuple, &parse); + i = next_tuple(handle, tuple, parse); } found_port: @@ -437,6 +456,7 @@ next_entry: printk(KERN_NOTICE "serial_cs: no usable port range found, giving up\n"); cs_error(link->handle, RequestIO, i); + kfree(cfg_mem); return -1; } @@ -450,9 +470,10 @@ next_entry: i = pcmcia_request_configuration(link->handle, &link->conf); if (i != CS_SUCCESS) { cs_error(link->handle, RequestConfiguration, i); + kfree(cfg_mem); return -1; } - + kfree(cfg_mem); return setup_serial(handle, info, link->io.BasePort1, link->irq.AssignedIRQ); } @@ -460,29 +481,39 @@ static int multi_config(dev_link_t * link) { client_handle_t handle = link->handle; struct serial_info *info = link->priv; - tuple_t tuple; - u_char buf[256]; - cisparse_t parse; - cistpl_cftable_entry_t *cf = &parse.cftable_entry; + struct serial_cfg_mem *cfg_mem; + tuple_t *tuple; + u_char *buf; + cisparse_t *parse; + cistpl_cftable_entry_t *cf; config_info_t config; - int i, base2 = 0; + int i, rc, base2 = 0; + + cfg_mem = kmalloc(sizeof(struct serial_cfg_mem), GFP_KERNEL); + if (!cfg_mem) + return -1; + tuple = &cfg_mem->tuple; + parse = &cfg_mem->parse; + cf = &parse->cftable_entry; + buf = cfg_mem->buf; i = pcmcia_get_configuration_info(handle, &config); if (i != CS_SUCCESS) { cs_error(handle, GetConfigurationInfo, i); - return -1; + rc = -1; + goto free_cfg_mem; } link->conf.Vcc = config.Vcc; - tuple.TupleData = (cisdata_t *) buf; - tuple.TupleOffset = 0; - tuple.TupleDataMax = 255; - tuple.Attributes = 0; - tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; + tuple->TupleData = (cisdata_t *) buf; + tuple->TupleOffset = 0; + tuple->TupleDataMax = 255; + tuple->Attributes = 0; + tuple->DesiredTuple = CISTPL_CFTABLE_ENTRY; /* First, look for a generic full-sized window */ link->io.NumPorts1 = info->multi * 8; - i = first_tuple(handle, &tuple, &parse); + i = first_tuple(handle, tuple, parse); while (i != CS_NO_MORE_ITEMS) { /* The quad port cards have bad CIS's, so just look for a window larger than 8 ports and assume it will be right */ @@ -497,14 +528,14 @@ static int multi_config(dev_link_t * link) if (i == CS_SUCCESS) break; } - i = next_tuple(handle, &tuple, &parse); + i = next_tuple(handle, tuple, parse); } /* If that didn't work, look for two windows */ if (i != CS_SUCCESS) { link->io.NumPorts1 = link->io.NumPorts2 = 8; info->multi = 2; - i = first_tuple(handle, &tuple, &parse); + i = first_tuple(handle, tuple, parse); while (i != CS_NO_MORE_ITEMS) { if ((i == CS_SUCCESS) && (cf->io.nwin == 2)) { link->conf.ConfigIndex = cf->index; @@ -517,13 +548,14 @@ static int multi_config(dev_link_t * link) if (i == CS_SUCCESS) break; } - i = next_tuple(handle, &tuple, &parse); + i = next_tuple(handle, tuple, parse); } } if (i != CS_SUCCESS) { cs_error(link->handle, RequestIO, i); - return -1; + rc = -1; + goto free_cfg_mem; } i = pcmcia_request_irq(link->handle, &link->irq); @@ -541,7 +573,8 @@ static int multi_config(dev_link_t * link) i = pcmcia_request_configuration(link->handle, &link->conf); if (i != CS_SUCCESS) { cs_error(link->handle, RequestConfiguration, i); - return -1; + rc = -1; + goto free_cfg_mem; } /* The Oxford Semiconductor OXCF950 cards are in fact single-port: @@ -554,17 +587,23 @@ static int multi_config(dev_link_t * link) setup_serial(handle, info, link->io.BasePort1, link->irq.AssignedIRQ); outb(12, base2 + 1); } - return 0; + rc = 0; + goto free_cfg_mem; } setup_serial(handle, info, link->io.BasePort1, link->irq.AssignedIRQ); /* The Nokia cards are not really multiport cards */ - if (info->manfid == MANFID_NOKIA) - return 0; + if (info->manfid == MANFID_NOKIA) { + rc = 0; + goto free_cfg_mem; + } for (i = 0; i < info->multi - 1; i++) - setup_serial(handle, info, base2 + (8 * i), link->irq.AssignedIRQ); - - return 0; + setup_serial(handle, info, base2 + (8 * i), + link->irq.AssignedIRQ); + rc = 0; +free_cfg_mem: + kfree(cfg_mem); + return rc; } /*====================================================================== @@ -579,39 +618,49 @@ void serial_config(dev_link_t * link) { client_handle_t handle = link->handle; struct serial_info *info = link->priv; - tuple_t tuple; - u_short buf[128]; - cisparse_t parse; - cistpl_cftable_entry_t *cf = &parse.cftable_entry; + struct serial_cfg_mem *cfg_mem; + tuple_t *tuple; + u_char *buf; + cisparse_t *parse; + cistpl_cftable_entry_t *cf; int i, last_ret, last_fn; DEBUG(0, "serial_config(0x%p)\n", link); - tuple.TupleData = (cisdata_t *) buf; - tuple.TupleOffset = 0; - tuple.TupleDataMax = 255; - tuple.Attributes = 0; + cfg_mem = kmalloc(sizeof(struct serial_cfg_mem), GFP_KERNEL); + if (!cfg_mem) + goto failed; + + tuple = &cfg_mem->tuple; + parse = &cfg_mem->parse; + cf = &parse->cftable_entry; + buf = cfg_mem->buf; + + tuple->TupleData = (cisdata_t *) buf; + tuple->TupleOffset = 0; + tuple->TupleDataMax = 255; + tuple->Attributes = 0; /* Get configuration register information */ - tuple.DesiredTuple = CISTPL_CONFIG; - last_ret = first_tuple(handle, &tuple, &parse); + tuple->DesiredTuple = CISTPL_CONFIG; + last_ret = first_tuple(handle, tuple, parse); if (last_ret != CS_SUCCESS) { last_fn = ParseTuple; goto cs_failed; } - link->conf.ConfigBase = parse.config.base; - link->conf.Present = parse.config.rmask[0]; + link->conf.ConfigBase = parse->config.base; + link->conf.Present = parse->config.rmask[0]; /* Configure card */ link->state |= DEV_CONFIG; /* Is this a compliant multifunction card? */ - tuple.DesiredTuple = CISTPL_LONGLINK_MFC; - tuple.Attributes = TUPLE_RETURN_COMMON | TUPLE_RETURN_LINK; - info->multi = (first_tuple(handle, &tuple, &parse) == CS_SUCCESS); + tuple->DesiredTuple = CISTPL_LONGLINK_MFC; + tuple->Attributes = TUPLE_RETURN_COMMON | TUPLE_RETURN_LINK; + info->multi = (first_tuple(handle, tuple, parse) == CS_SUCCESS); /* Is this a multiport card? */ - tuple.DesiredTuple = CISTPL_MANFID; - if (first_tuple(handle, &tuple, &parse) == CS_SUCCESS) { + tuple->DesiredTuple = CISTPL_MANFID; + if (first_tuple(handle, tuple, parse) == CS_SUCCESS) { info->manfid = le16_to_cpu(buf[0]); for (i = 0; i < MULTI_COUNT; i++) if ((info->manfid == multi_id[i].manfid) && @@ -623,13 +672,13 @@ void serial_config(dev_link_t * link) /* Another check for dual-serial cards: look for either serial or multifunction cards that ask for appropriate IO port ranges */ - tuple.DesiredTuple = CISTPL_FUNCID; + tuple->DesiredTuple = CISTPL_FUNCID; if ((info->multi == 0) && - ((first_tuple(handle, &tuple, &parse) != CS_SUCCESS) || - (parse.funcid.func == CISTPL_FUNCID_MULTI) || - (parse.funcid.func == CISTPL_FUNCID_SERIAL))) { - tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; - if (first_tuple(handle, &tuple, &parse) == CS_SUCCESS) { + ((first_tuple(handle, tuple, parse) != CS_SUCCESS) || + (parse->funcid.func == CISTPL_FUNCID_MULTI) || + (parse->funcid.func == CISTPL_FUNCID_SERIAL))) { + tuple->DesiredTuple = CISTPL_CFTABLE_ENTRY; + if (first_tuple(handle, tuple, parse) == CS_SUCCESS) { if ((cf->io.nwin == 1) && (cf->io.win[0].len % 8 == 0)) info->multi = cf->io.win[0].len >> 3; if ((cf->io.nwin == 2) && (cf->io.win[0].len == 8) && @@ -664,6 +713,7 @@ void serial_config(dev_link_t * link) link->dev = &info->node[0]; link->state &= ~DEV_CONFIG_PENDING; + kfree(cfg_mem); return; cs_failed: @@ -671,6 +721,7 @@ void serial_config(dev_link_t * link) failed: serial_remove(link); link->state &= ~DEV_CONFIG_PENDING; + kfree(cfg_mem); } /*====================================================================== diff --git a/drivers/serial/serial_lh7a40x.c b/drivers/serial/serial_lh7a40x.c index 4ce3a41f1611..85cfa08d3bad 100644 --- a/drivers/serial/serial_lh7a40x.c +++ b/drivers/serial/serial_lh7a40x.c @@ -162,7 +162,7 @@ lh7a40xuart_rx_chars (struct uart_port* port) flag = TTY_NORMAL; ++port->icount.rx; - if (data & RxError) { /* Quick check, short-circuit */ + if (unlikely(data & RxError)) { /* Quick check, short-circuit */ if (data & RxBreak) { data &= ~(RxFramingError | RxParityError); ++port->icount.brk; diff --git a/drivers/serial/sn_console.c b/drivers/serial/sn_console.c index ffaab9b90fd8..fee6418e84c4 100644 --- a/drivers/serial/sn_console.c +++ b/drivers/serial/sn_console.c @@ -787,7 +787,7 @@ static void __init sn_sal_switch_to_interrupts(struct sn_cons_port *port) static void sn_sal_console_write(struct console *, const char *, unsigned); static int __init sn_sal_console_setup(struct console *, char *); -extern struct uart_driver sal_console_uart; +static struct uart_driver sal_console_uart; extern struct tty_driver *uart_console_device(struct console *, int *); static struct console sal_console = { @@ -801,7 +801,7 @@ static struct console sal_console = { #define SAL_CONSOLE &sal_console -struct uart_driver sal_console_uart = { +static struct uart_driver sal_console_uart = { .owner = THIS_MODULE, .driver_name = "sn_console", .dev_name = DEVICE_NAME, diff --git a/drivers/serial/sunsab.c b/drivers/serial/sunsab.c index 8caaf2e5e47c..39b788d95e39 100644 --- a/drivers/serial/sunsab.c +++ b/drivers/serial/sunsab.c @@ -682,7 +682,8 @@ static void calc_ebrg(int baud, int *n_ret, int *m_ret) /* Internal routine, port->lock is held and local interrupts are disabled. */ static void sunsab_convert_to_sab(struct uart_sunsab_port *up, unsigned int cflag, - unsigned int iflag, int baud) + unsigned int iflag, unsigned int baud, + unsigned int quot) { unsigned int ebrg; unsigned char dafo; @@ -766,6 +767,9 @@ static void sunsab_convert_to_sab(struct uart_sunsab_port *up, unsigned int cfla up->port.ignore_status_mask |= (SAB82532_ISR0_RPF | SAB82532_ISR0_TCD); + uart_update_timeout(&up->port, cflag, + (up->port.uartclk / (16 * quot))); + /* Now bang the new settings into the chip. */ sunsab_cec_wait(up); sunsab_tec_wait(up); @@ -784,10 +788,11 @@ static void sunsab_set_termios(struct uart_port *port, struct termios *termios, { struct uart_sunsab_port *up = (struct uart_sunsab_port *) port; unsigned long flags; - int baud = uart_get_baud_rate(port, termios, old, 0, 4000000); + unsigned int baud = uart_get_baud_rate(port, termios, old, 0, 4000000); + unsigned int quot = uart_get_divisor(port, baud); spin_lock_irqsave(&up->port.lock, flags); - sunsab_convert_to_sab(up, termios->c_cflag, termios->c_iflag, baud); + sunsab_convert_to_sab(up, termios->c_cflag, termios->c_iflag, baud, quot); spin_unlock_irqrestore(&up->port.lock, flags); } @@ -880,7 +885,7 @@ static int sunsab_console_setup(struct console *con, char *options) { struct uart_sunsab_port *up = &sunsab_ports[con->index]; unsigned long flags; - int baud; + unsigned int baud, quot; printk("Console: ttyS%d (SAB82532)\n", (sunsab_reg.minor - 64) + con->index); @@ -926,7 +931,8 @@ static int sunsab_console_setup(struct console *con, char *options) SAB82532_IMR1_XPR; writeb(up->interrupt_mask1, &up->regs->w.imr1); - sunsab_convert_to_sab(up, con->cflag, 0, baud); + quot = uart_get_divisor(&up->port, baud); + sunsab_convert_to_sab(up, con->cflag, 0, baud, quot); sunsab_set_mctrl(&up->port, TIOCM_DTR | TIOCM_RTS); spin_unlock_irqrestore(&up->port.lock, flags); diff --git a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c index 23d19d394320..ddc97c905e14 100644 --- a/drivers/serial/sunsu.c +++ b/drivers/serial/sunsu.c @@ -1285,6 +1285,7 @@ static struct uart_driver sunsu_reg = { static int __init sunsu_kbd_ms_init(struct uart_sunsu_port *up, int channel) { + int quot, baud; #ifdef CONFIG_SERIO struct serio *serio; #endif @@ -1293,10 +1294,14 @@ static int __init sunsu_kbd_ms_init(struct uart_sunsu_port *up, int channel) up->port.type = PORT_UNKNOWN; up->port.uartclk = (SU_BASE_BAUD * 16); - if (up->su_type == SU_PORT_KBD) + if (up->su_type == SU_PORT_KBD) { up->cflag = B1200 | CS8 | CLOCAL | CREAD; - else + baud = 1200; + } else { up->cflag = B4800 | CS8 | CLOCAL | CREAD; + baud = 4800; + } + quot = up->port.uartclk / (16 * baud); sunsu_autoconfig(up); if (up->port.type == PORT_UNKNOWN) @@ -1337,6 +1342,8 @@ static int __init sunsu_kbd_ms_init(struct uart_sunsu_port *up, int channel) } #endif + sunsu_change_speed(&up->port, up->cflag, 0, quot); + sunsu_startup(&up->port); return 0; } |