From a88a477f1df703f0e2a7592e19618799cb598623 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Breno=20Leit=C3=A3o?= Date: Thu, 24 Sep 2009 16:58:22 -0300 Subject: jsm: IRQ handlers doesn't need to have IRQ_DISABLED enabled MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently jsm is showing the following message when loaded: IRQ 432/JSM: IRQF_DISABLED is not guaranteed on shared IRQs It's because the request_irq() is called using IRQF_DISABLED and IRQF_SHARED. Actually there is no need to use IRQF_DISABLED in this driver. Signed-off-by: Breno Leitão Cc: Scott Kilau Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/serial/jsm/jsm_driver.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/serial') diff --git a/drivers/serial/jsm/jsm_driver.c b/drivers/serial/jsm/jsm_driver.c index b3604aa322a4..48326f75a81e 100644 --- a/drivers/serial/jsm/jsm_driver.c +++ b/drivers/serial/jsm/jsm_driver.c @@ -123,7 +123,7 @@ static int __devinit jsm_probe_one(struct pci_dev *pdev, const struct pci_device } rc = request_irq(brd->irq, brd->bd_ops->intr, - IRQF_DISABLED|IRQF_SHARED, "JSM", brd); + IRQF_SHARED, "JSM", brd); if (rc) { printk(KERN_WARNING "Failed to hook IRQ %d\n",brd->irq); goto out_iounmap; -- cgit v1.2.3 From 354aaf964ed1ae45c175aa496526bae4662c4452 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Breno=20Leit=C3=A3o?= Date: Thu, 24 Sep 2009 16:58:23 -0300 Subject: jsm: Rewriting a bad log message MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Actually jsm displays "Device Added" 8 times (for a 8 port device). This silly patch just makes things more informative, showing the port (instead of the device) that was added. Signed-off-by: Breno Leitão Cc: Scott Kilau Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/serial/jsm/jsm_tty.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/serial') diff --git a/drivers/serial/jsm/jsm_tty.c b/drivers/serial/jsm/jsm_tty.c index 7439c0373620..6423dfb825f4 100644 --- a/drivers/serial/jsm/jsm_tty.c +++ b/drivers/serial/jsm/jsm_tty.c @@ -472,7 +472,7 @@ int __devinit jsm_uart_port_init(struct jsm_board *brd) if (uart_add_one_port (&jsm_uart_driver, &brd->channels[i]->uart_port)) printk(KERN_INFO "jsm: add device failed\n"); else - printk(KERN_INFO "Added device \n"); + printk(KERN_INFO "jsm: Port %d added\n", i); } jsm_printk(INIT, INFO, &brd->pci_dev, "finish\n"); -- cgit v1.2.3 From a53568a22adf6881183096d0863b0ff301173cbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Breno=20Leit=C3=A3o?= Date: Tue, 29 Sep 2009 15:16:55 -0300 Subject: jsm: remove the ch_custom_speed field MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently the ch_custom_speed field exists but is never used, so, this patch removes it. Signed-off-by: Breno Leitão Cc: Scott Kilau Signed-off-by: Greg Kroah-Hartman --- drivers/serial/jsm/jsm.h | 1 - drivers/serial/jsm/jsm_neo.c | 4 ---- 2 files changed, 5 deletions(-) (limited to 'drivers/serial') diff --git a/drivers/serial/jsm/jsm.h b/drivers/serial/jsm/jsm.h index 4e5f3bde0461..afcbee24a6b2 100644 --- a/drivers/serial/jsm/jsm.h +++ b/drivers/serial/jsm/jsm.h @@ -216,7 +216,6 @@ struct jsm_channel { u8 ch_startc; /* Start character */ u32 ch_old_baud; /* Cache of the current baud */ - u32 ch_custom_speed;/* Custom baud, if set */ u32 ch_wopen; /* Waiting for open process cnt */ diff --git a/drivers/serial/jsm/jsm_neo.c b/drivers/serial/jsm/jsm_neo.c index b4b124e4828f..088e702ef5f3 100644 --- a/drivers/serial/jsm/jsm_neo.c +++ b/drivers/serial/jsm/jsm_neo.c @@ -957,10 +957,6 @@ static void neo_param(struct jsm_channel *ch) ch->ch_old_baud = 0; return; - } else if (ch->ch_custom_speed) { - baud = ch->ch_custom_speed; - if (ch->ch_flags & CH_BAUD0) - ch->ch_flags &= ~(CH_BAUD0); } else { int i; unsigned int cflag; -- cgit v1.2.3 From cead486f407bbf152feccfe3734dd3966f9ff166 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Breno=20Leit=C3=A3o?= Date: Tue, 29 Sep 2009 15:16:56 -0300 Subject: jsm: removing ch_old_baud field MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently the field jsm_channel->ch_old_baud is not used, just assigned in a lot of places but never used. This patches removes this field. Signed-off-by: Breno Leitão Cc: Scott Kilau Signed-off-by: Greg Kroah-Hartman --- drivers/serial/jsm/jsm.h | 2 -- drivers/serial/jsm/jsm_neo.c | 2 -- drivers/serial/jsm/jsm_tty.c | 2 -- 3 files changed, 6 deletions(-) (limited to 'drivers/serial') diff --git a/drivers/serial/jsm/jsm.h b/drivers/serial/jsm/jsm.h index afcbee24a6b2..d413e4a6aa9b 100644 --- a/drivers/serial/jsm/jsm.h +++ b/drivers/serial/jsm/jsm.h @@ -215,8 +215,6 @@ struct jsm_channel { u8 ch_stopc; /* Stop character */ u8 ch_startc; /* Start character */ - u32 ch_old_baud; /* Cache of the current baud */ - u32 ch_wopen; /* Waiting for open process cnt */ u8 ch_mostat; /* FEP output modem status */ diff --git a/drivers/serial/jsm/jsm_neo.c b/drivers/serial/jsm/jsm_neo.c index 088e702ef5f3..bee37274cc9a 100644 --- a/drivers/serial/jsm/jsm_neo.c +++ b/drivers/serial/jsm/jsm_neo.c @@ -954,7 +954,6 @@ static void neo_param(struct jsm_channel *ch) ch->ch_flags |= (CH_BAUD0); ch->ch_mostat &= ~(UART_MCR_RTS | UART_MCR_DTR); neo_assert_modem_signals(ch); - ch->ch_old_baud = 0; return; } else { @@ -1041,7 +1040,6 @@ static void neo_param(struct jsm_channel *ch) quot = ch->ch_bd->bd_dividend / baud; if (quot != 0) { - ch->ch_old_baud = baud; writeb(UART_LCR_DLAB, &ch->ch_neo_uart->lcr); writeb((quot & 0xff), &ch->ch_neo_uart->txrx); writeb((quot >> 8), &ch->ch_neo_uart->ier); diff --git a/drivers/serial/jsm/jsm_tty.c b/drivers/serial/jsm/jsm_tty.c index 6423dfb825f4..1bcad596f3d6 100644 --- a/drivers/serial/jsm/jsm_tty.c +++ b/drivers/serial/jsm/jsm_tty.c @@ -296,8 +296,6 @@ static void jsm_tty_close(struct uart_port *port) bd->bd_ops->assert_modem_signals(channel); } - channel->ch_old_baud = 0; - /* Turn off UART interrupts for this port */ channel->ch_bd->bd_ops->uart_off(channel); -- cgit v1.2.3 From 2fd107c01567673c85f724a24d56614478d40f89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Breno=20Leit=C3=A3o?= Date: Tue, 29 Sep 2009 15:16:57 -0300 Subject: jsm: Remove ch_cpstime field MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently the field jsm_channel->ch_cpstime is defined but never used, so this patch removes it. Signed-off-by: Breno Leitão Cc: Scott Kilau Signed-off-by: Greg Kroah-Hartman --- drivers/serial/jsm/jsm.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/serial') diff --git a/drivers/serial/jsm/jsm.h b/drivers/serial/jsm/jsm.h index d413e4a6aa9b..8c1435179071 100644 --- a/drivers/serial/jsm/jsm.h +++ b/drivers/serial/jsm/jsm.h @@ -206,8 +206,6 @@ struct jsm_channel { u64 ch_close_delay; /* How long we should drop RTS/DTR for */ - u64 ch_cpstime; /* Time for CPS calculations */ - tcflag_t ch_c_iflag; /* channel iflags */ tcflag_t ch_c_cflag; /* channel cflags */ tcflag_t ch_c_oflag; /* channel oflags */ -- cgit v1.2.3 From a44829dd8bcd5335f0498275bb63f1028b32f141 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Breno=20Leit=C3=A3o?= Date: Tue, 29 Sep 2009 15:16:58 -0300 Subject: jsm: Removing unused jsm_channel->ch_wopen field MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently the jsm_channel->ch_wopen field is defined and never used. So, this patch removes it. Signed-off-by: Breno Leitão Cc: Scott Kilau Signed-off-by: Greg Kroah-Hartman --- drivers/serial/jsm/jsm.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/serial') diff --git a/drivers/serial/jsm/jsm.h b/drivers/serial/jsm/jsm.h index 8c1435179071..484c9275718a 100644 --- a/drivers/serial/jsm/jsm.h +++ b/drivers/serial/jsm/jsm.h @@ -213,8 +213,6 @@ struct jsm_channel { u8 ch_stopc; /* Stop character */ u8 ch_startc; /* Start character */ - u32 ch_wopen; /* Waiting for open process cnt */ - u8 ch_mostat; /* FEP output modem status */ u8 ch_mistat; /* FEP input modem status */ -- cgit v1.2.3 From f9d1dff276c40157638415cdddf6a051869e8d92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Breno=20Leit=C3=A3o?= Date: Tue, 29 Sep 2009 15:16:59 -0300 Subject: jsm: removing the field jsm_board->intr_count MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently there is a field in the jsm_board structure to cont the number of interrupt that the card recevived, but it's not working properly when the IRQ line is shared, and also nowhere else this field is used. So, This patch is removing it. Signed-off-by: Breno Leitão Cc: Scott Kilau Signed-off-by: Greg Kroah-Hartman --- drivers/serial/jsm/jsm.h | 1 - drivers/serial/jsm/jsm_neo.c | 2 -- 2 files changed, 3 deletions(-) (limited to 'drivers/serial') diff --git a/drivers/serial/jsm/jsm.h b/drivers/serial/jsm/jsm.h index 484c9275718a..38a509c684cd 100644 --- a/drivers/serial/jsm/jsm.h +++ b/drivers/serial/jsm/jsm.h @@ -138,7 +138,6 @@ struct jsm_board u32 nasync; /* Number of ports on card */ u32 irq; /* Interrupt request number */ - u64 intr_count; /* Count of interrupts */ u64 membase; /* Start of base memory of the card */ u64 membase_end; /* End of base memory of the card */ diff --git a/drivers/serial/jsm/jsm_neo.c b/drivers/serial/jsm/jsm_neo.c index bee37274cc9a..7960d9633c15 100644 --- a/drivers/serial/jsm/jsm_neo.c +++ b/drivers/serial/jsm/jsm_neo.c @@ -1117,8 +1117,6 @@ static irqreturn_t neo_intr(int irq, void *voidbrd) unsigned long lock_flags2; int outofloop_count = 0; - brd->intr_count++; - /* Lock out the slow poller from running on this board. */ spin_lock_irqsave(&brd->bd_intr_lock, lock_flags); -- cgit v1.2.3 From e6bdf24cf2992e1775fc095ed021f6b886707c41 Mon Sep 17 00:00:00 2001 From: Breno Leitao Date: Wed, 14 Oct 2009 14:57:51 -0300 Subject: jsm: adding EEH handlers Adding EEH handlers for the serial jsm driver. This patch adds the PCI error handlers and also register them to be called when a error is detected. Signed-off-by: Breno Leitao Acked-by: Scott Kilau Signed-off-by: Greg Kroah-Hartman --- drivers/serial/jsm/jsm_driver.c | 46 +++++++++++++++++++++++++++++++++++++++++ drivers/serial/jsm/jsm_tty.c | 2 +- 2 files changed, 47 insertions(+), 1 deletion(-) (limited to 'drivers/serial') diff --git a/drivers/serial/jsm/jsm_driver.c b/drivers/serial/jsm/jsm_driver.c index 48326f75a81e..108c3e0471fd 100644 --- a/drivers/serial/jsm/jsm_driver.c +++ b/drivers/serial/jsm/jsm_driver.c @@ -48,6 +48,17 @@ struct uart_driver jsm_uart_driver = { .nr = NR_PORTS, }; +static pci_ers_result_t jsm_io_error_detected(struct pci_dev *pdev, + pci_channel_state_t state); +static pci_ers_result_t jsm_io_slot_reset(struct pci_dev *pdev); +static void jsm_io_resume(struct pci_dev *pdev); + +static struct pci_error_handlers jsm_err_handler = { + .error_detected = jsm_io_error_detected, + .slot_reset = jsm_io_slot_reset, + .resume = jsm_io_resume, +}; + int jsm_debug; module_param(jsm_debug, int, 0); MODULE_PARM_DESC(jsm_debug, "Driver debugging level"); @@ -164,6 +175,7 @@ static int __devinit jsm_probe_one(struct pci_dev *pdev, const struct pci_device } pci_set_drvdata(pdev, brd); + pci_save_state(pdev); return 0; out_free_irq: @@ -222,8 +234,42 @@ static struct pci_driver jsm_driver = { .id_table = jsm_pci_tbl, .probe = jsm_probe_one, .remove = __devexit_p(jsm_remove_one), + .err_handler = &jsm_err_handler, }; +static pci_ers_result_t jsm_io_error_detected(struct pci_dev *pdev, + pci_channel_state_t state) +{ + struct jsm_board *brd = pci_get_drvdata(pdev); + + jsm_remove_uart_port(brd); + + return PCI_ERS_RESULT_NEED_RESET; +} + +static pci_ers_result_t jsm_io_slot_reset(struct pci_dev *pdev) +{ + int rc; + + rc = pci_enable_device(pdev); + + if (rc) + return PCI_ERS_RESULT_DISCONNECT; + + pci_set_master(pdev); + + return PCI_ERS_RESULT_RECOVERED; +} + +static void jsm_io_resume(struct pci_dev *pdev) +{ + struct jsm_board *brd = pci_get_drvdata(pdev); + + pci_restore_state(pdev); + + jsm_uart_port_init(brd); +} + static int __init jsm_init_module(void) { int rc; diff --git a/drivers/serial/jsm/jsm_tty.c b/drivers/serial/jsm/jsm_tty.c index 1bcad596f3d6..cd95e215550d 100644 --- a/drivers/serial/jsm/jsm_tty.c +++ b/drivers/serial/jsm/jsm_tty.c @@ -430,7 +430,7 @@ int __devinit jsm_tty_init(struct jsm_board *brd) return 0; } -int __devinit jsm_uart_port_init(struct jsm_board *brd) +int jsm_uart_port_init(struct jsm_board *brd) { int i; unsigned int line; -- cgit v1.2.3 From 9e845abfc8a8973373821aa05302794fd254514b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Goddard=20Rosa?= Date: Sun, 25 Oct 2009 11:16:32 -0200 Subject: serial: fix NULL pointer dereference MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If kzalloc() or alloc_tty_driver() fails, we call: put_tty_driver(normal = NULL). Then: put_tty_driver -> tty_driver_kref_put -> kref_put(&NULL->kref, ...) Signed-off-by: André Goddard Rosa Signed-off-by: Greg Kroah-Hartman --- drivers/serial/serial_core.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) (limited to 'drivers/serial') diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c index dcc72444e8e7..885eabe552cd 100644 --- a/drivers/serial/serial_core.c +++ b/drivers/serial/serial_core.c @@ -2344,7 +2344,7 @@ static const struct tty_operations uart_ops = { */ int uart_register_driver(struct uart_driver *drv) { - struct tty_driver *normal = NULL; + struct tty_driver *normal; int i, retval; BUG_ON(drv->state); @@ -2354,13 +2354,12 @@ int uart_register_driver(struct uart_driver *drv) * we have a large number of ports to handle. */ drv->state = kzalloc(sizeof(struct uart_state) * drv->nr, GFP_KERNEL); - retval = -ENOMEM; if (!drv->state) goto out; - normal = alloc_tty_driver(drv->nr); + normal = alloc_tty_driver(drv->nr); if (!normal) - goto out; + goto out_kfree; drv->tty_driver = normal; @@ -2393,12 +2392,14 @@ int uart_register_driver(struct uart_driver *drv) } retval = tty_register_driver(normal); - out: - if (retval < 0) { - put_tty_driver(normal); - kfree(drv->state); - } - return retval; + if (retval >= 0) + return retval; + + put_tty_driver(normal); +out_kfree: + kfree(drv->state); +out: + return -ENOMEM; } /** -- cgit v1.2.3 From 82cb7ba10deafe17686bf22ce4a7a303a77a197f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Goddard=20Rosa?= Date: Sun, 25 Oct 2009 11:18:26 -0200 Subject: serial: cascade needless conditionals MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: André Goddard Rosa Signed-off-by: Greg Kroah-Hartman --- drivers/serial/serial_core.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'drivers/serial') diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c index 885eabe552cd..047530b285bb 100644 --- a/drivers/serial/serial_core.c +++ b/drivers/serial/serial_core.c @@ -342,11 +342,11 @@ uart_get_baud_rate(struct uart_port *port, struct ktermios *termios, if (flags == UPF_SPD_HI) altbaud = 57600; - if (flags == UPF_SPD_VHI) + else if (flags == UPF_SPD_VHI) altbaud = 115200; - if (flags == UPF_SPD_SHI) + else if (flags == UPF_SPD_SHI) altbaud = 230400; - if (flags == UPF_SPD_WARP) + else if (flags == UPF_SPD_WARP) altbaud = 460800; for (try = 0; try < 2; try++) { @@ -1217,9 +1217,8 @@ static void uart_set_termios(struct tty_struct *tty, /* Handle transition to B0 status */ if ((old_termios->c_cflag & CBAUD) && !(cflag & CBAUD)) uart_clear_mctrl(state->uart_port, TIOCM_RTS | TIOCM_DTR); - /* Handle transition away from B0 status */ - if (!(old_termios->c_cflag & CBAUD) && (cflag & CBAUD)) { + else if (!(old_termios->c_cflag & CBAUD) && (cflag & CBAUD)) { unsigned int mask = TIOCM_DTR; if (!(cflag & CRTSCTS) || !test_bit(TTY_THROTTLED, &tty->flags)) @@ -1234,9 +1233,8 @@ static void uart_set_termios(struct tty_struct *tty, __uart_start(tty); spin_unlock_irqrestore(&state->uart_port->lock, flags); } - /* Handle turning on CRTSCTS */ - if (!(old_termios->c_cflag & CRTSCTS) && (cflag & CRTSCTS)) { + else if (!(old_termios->c_cflag & CRTSCTS) && (cflag & CRTSCTS)) { spin_lock_irqsave(&state->uart_port->lock, flags); if (!(state->uart_port->ops->get_mctrl(state->uart_port) & TIOCM_CTS)) { tty->hw_stopped = 1; -- cgit v1.2.3 From 4c0ebb8057bc335d345c8e205a3e6fd1320be21e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Goddard=20Rosa?= Date: Sun, 25 Oct 2009 12:01:34 -0200 Subject: serial, 8250: calculate irqflags bitmask before loop MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: André Goddard Rosa Signed-off-by: Greg Kroah-Hartman --- drivers/serial/8250.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'drivers/serial') diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index 737b4c960971..b75e63e9d1ee 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c @@ -2646,7 +2646,7 @@ static void __init serial8250_isa_init_ports(void) { struct uart_8250_port *up; static int first = 1; - int i; + int i, irqflag = 0; if (!first) return; @@ -2670,6 +2670,9 @@ static void __init serial8250_isa_init_ports(void) up->port.ops = &serial8250_pops; } + if (share_irqs) + irqflag = IRQF_SHARED; + for (i = 0, up = serial8250_ports; i < ARRAY_SIZE(old_serial_port) && i < nr_uarts; i++, up++) { @@ -2683,8 +2686,7 @@ static void __init serial8250_isa_init_ports(void) up->port.iotype = old_serial_port[i].io_type; up->port.regshift = old_serial_port[i].iomem_reg_shift; set_io_from_upio(&up->port); - if (share_irqs) - up->port.irqflags |= IRQF_SHARED; + up->port.irqflags |= irqflag; } } @@ -2940,10 +2942,13 @@ static int __devinit serial8250_probe(struct platform_device *dev) { struct plat_serial8250_port *p = dev->dev.platform_data; struct uart_port port; - int ret, i; + int ret, i, irqflag = 0; memset(&port, 0, sizeof(struct uart_port)); + if (share_irqs) + irqflag = IRQF_SHARED; + for (i = 0; p && p->flags != 0; p++, i++) { port.iobase = p->iobase; port.membase = p->membase; @@ -2960,8 +2965,7 @@ static int __devinit serial8250_probe(struct platform_device *dev) port.serial_in = p->serial_in; port.serial_out = p->serial_out; port.dev = &dev->dev; - if (share_irqs) - port.irqflags |= IRQF_SHARED; + port.irqflags |= irqflag; ret = serial8250_register_port(&port); if (ret < 0) { dev_err(&dev->dev, "unable to register port at index %d " -- cgit v1.2.3 From c934878cc09fdd4a06ffa554c5149b11d972456f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Fri, 6 Nov 2009 21:40:46 +0100 Subject: Serial: pxa: work around Errata #75 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Intel(R) PXA27x Processor Family Specification Update (Nov 2005) says: E75. UART: Baud rate may not be programmed correctly on back-to-back writes. Problem: When programming the Divisor Latch registers, Low and High (DLL and DLH), with back-to-back writes, the second register write may not take effect. The result is an incorrect baud rate. Workaround: After programming the first Divisor Latch register, read and verify it before programming the second Divisor Latch register. This was hit when changing the baud rate from 115200 to 9600 while receiving characters at 9600 Bd. And fixed indention of some comments nearby. Signed-off-by: Uwe Kleine-König Acked-by: Wolfram Sang Acked-by: Marc Kleine-Budde Cc: Eric Miao Cc: Alan Cox Cc: Mike Rapoport Signed-off-by: Greg Kroah-Hartman --- drivers/serial/pxa.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'drivers/serial') diff --git a/drivers/serial/pxa.c b/drivers/serial/pxa.c index b8629d74f6a2..4a821046baae 100644 --- a/drivers/serial/pxa.c +++ b/drivers/serial/pxa.c @@ -438,6 +438,7 @@ serial_pxa_set_termios(struct uart_port *port, struct ktermios *termios, unsigned char cval, fcr = 0; unsigned long flags; unsigned int baud, quot; + unsigned int dll; switch (termios->c_cflag & CSIZE) { case CS5: @@ -534,10 +535,18 @@ serial_pxa_set_termios(struct uart_port *port, struct ktermios *termios, else up->mcr &= ~UART_MCR_AFE; - serial_out(up, UART_LCR, cval | UART_LCR_DLAB);/* set DLAB */ + serial_out(up, UART_LCR, cval | UART_LCR_DLAB); /* set DLAB */ serial_out(up, UART_DLL, quot & 0xff); /* LS of divisor */ + + /* + * work around Errata #75 according to Intel(R) PXA27x Processor Family + * Specification Update (Nov 2005) + */ + dll = serial_in(up, UART_DLL); + WARN_ON(dll != (quot & 0xff)); + serial_out(up, UART_DLM, quot >> 8); /* MS of divisor */ - serial_out(up, UART_LCR, cval); /* reset DLAB */ + serial_out(up, UART_LCR, cval); /* reset DLAB */ up->lcr = cval; /* Save LCR */ serial_pxa_set_mctrl(&up->port, up->port.mctrl); serial_out(up, UART_FCR, fcr); -- cgit v1.2.3 From 68cb4f8e246bbbc649980be0628cae9265870a91 Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Wed, 18 Nov 2009 11:08:11 +0100 Subject: Serial: Do not read IIR in serial8250_start_tx when UART_BUG_TXEN Do not read IIR in serial8250_start_tx when UART_BUG_TXEN Reading the IIR clears some oustanding interrupts so it is not safe. Instead, simply transmit immediately if the buffer is empty without regard to IIR. Signed-off-by: Ian Jackson Reviewed-by: Markus Armbruster Reviewed-by: Jiri Kosina Cc: Alan Cox Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/serial/8250.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'drivers/serial') diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index b75e63e9d1ee..c3e37c8e7e26 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c @@ -1339,14 +1339,12 @@ static void serial8250_start_tx(struct uart_port *port) serial_out(up, UART_IER, up->ier); if (up->bugs & UART_BUG_TXEN) { - unsigned char lsr, iir; + unsigned char lsr; lsr = serial_in(up, UART_LSR); up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS; - iir = serial_in(up, UART_IIR) & 0x0f; if ((up->port.type == PORT_RM9000) ? - (lsr & UART_LSR_THRE && - (iir == UART_IIR_NO_INT || iir == UART_IIR_THRI)) : - (lsr & UART_LSR_TEMT && iir & UART_IIR_NO_INT)) + (lsr & UART_LSR_THRE) : + (lsr & UART_LSR_TEMT)) transmit_chars(up); } } -- cgit v1.2.3